1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter.git synced 2025-03-09 15:40:20 +00:00

Add partial 6.1 support for ips40xx

This commit is contained in:
Ycarus (Yannick Chabanois) 2023-05-23 07:55:16 +02:00
parent 06f732ecad
commit 1c57837d55
25 changed files with 3276 additions and 0 deletions

View file

@ -0,0 +1,15 @@
--- a/src/linux/ifxos_linux_thread_drv.c 2023-05-22 08:50:14.087507831 +0200
+++ b/src/linux/ifxos_linux_thread_drv.c 2023-05-22 08:51:32.702129369 +0200
@@ -154,8 +154,11 @@
retVal = pThrCntrl->pThrFct(&pThrCntrl->thrParams);
pThrCntrl->thrParams.bRunning = IFX_FALSE;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(5,17,0))
complete_and_exit(&pThrCntrl->thrCompletion, (long)retVal);
-
+#else
+ kthread_complete_and_exit(&pThrCntrl->thrCompletion, (long)retVal);
+#endif
IFXOS_PRN_USR_DBG_NL( IFXOS, IFXOS_PRN_LEVEL_NORMAL,
("EXIT - Kernel Thread Startup <%s>" IFXOS_CRLF,
pThrCntrl->thrParams.pName));

View file

@ -0,0 +1,22 @@
--- a/src/drv_mei_cpe_linux.c 2023-05-22 14:07:34.356721319 +0200
+++ b/src/drv_mei_cpe_linux.c 2023-05-22 14:08:02.328250656 +0200
@@ -2062,7 +2062,7 @@
static int mei_proc_single_open(struct inode *inode, struct file *file)
{
- return single_open(file, mei_seq_single_show, PDE_DATA(inode));
+ return single_open(file, mei_seq_single_show, pde_data(inode));
}
static void mei_proc_entry_create(struct proc_dir_entry *parent_node,
--- a/src/drv_mei_cpe_linux_proc_config.c 2023-05-22 14:12:26.251818708 +0200
+++ b/src/drv_mei_cpe_linux_proc_config.c 2023-05-22 14:12:51.219401891 +0200
@@ -1274,7 +1274,7 @@
static int mei_proc_single_open(struct inode *inode, struct file *file)
{
- return single_open(file, mei_seq_single_show, PDE_DATA(inode));
+ return single_open(file, mei_seq_single_show, pde_data(inode));
}
static struct proc_ops proc_ops = {

View file

@ -0,0 +1,18 @@
--- a/ep.c 2023-05-22 10:23:11.790142567 +0200
+++ b/ep.c 2023-05-22 10:27:23.029791914 +0200
@@ -589,13 +589,13 @@
/* Target structures have a limit of 32 bit DMA pointers.
* DMA pointers can be wider than 32 bits by default on some systems.
*/
- ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
if (ret) {
dev_err(&pdev->dev, "32-bit DMA not available: %d\n", ret);
goto err_region;
}
- ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
if (ret) {
dev_err(&pdev->dev, "cannot enable 32-bit consistent DMA\n");
goto err_region;

View file

@ -0,0 +1,325 @@
--- a/dcdp/ptm_tc.c 2023-05-22 11:06:09.177510131 +0200
+++ b/dcdp/ptm_tc.c 2023-05-22 11:37:23.765131033 +0200
@@ -659,7 +659,11 @@
memcpy(ptm_tc->outq_map, def_outq_map, sizeof(def_outq_map));
SET_NETDEV_DEV(ptm_tc->dev, tc_priv->ep_dev[id].dev);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,0,0)
+ netif_napi_add(ptm_tc->dev, &ptm_tc->napi_rx, tc_priv->tc_ops.napi_rx);
+#else
netif_napi_add(ptm_tc->dev, &ptm_tc->napi_rx, tc_priv->tc_ops.napi_rx, NAPI_POLL_WEIGHT);
+#endif
netif_tx_napi_add(ptm_tc->dev, &ptm_tc->napi_tx, tc_priv->tc_ops.napi_tx, NAPI_POLL_WEIGHT);
err = register_netdev(ptm_tc->dev);
@@ -3125,7 +3129,7 @@
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- priv = (struct ptm_ep_priv *)PDE_DATA(file_inode(file));
+ priv = (struct ptm_ep_priv *)pde_data(file_inode(file));
len = count < sizeof(str) ? count : sizeof(str) - 1;
rlen = len - copy_from_user(str, buf, len);
@@ -3335,7 +3339,7 @@
local_buf[len] = 0;
num = vrx_split_buffer(local_buf, param_list, ARRAY_SIZE(param_list));
- priv = (struct ptm_ep_priv *)PDE_DATA(file_inode(file));
+ priv = (struct ptm_ep_priv *)pde_data(file_inode(file));
if (priv == NULL) {
pr_err("%s: Invalid private data\n", __func__);
return -EINVAL;
--- a/dcdp/inc/ptm_tc.h 2023-05-22 11:24:47.982177396 +0200
+++ b/dcdp/inc/ptm_tc.h 2023-05-22 11:25:34.313376656 +0200
@@ -76,6 +76,9 @@
#define SFSM_DBACE 0x6000
#define SFSM_CBACE 0x7100
+
+#define netif_tx_napi_add netif_napi_add_tx_weight
+
enum {
US_DMA_PRE_RXCH = 0,
US_DMA_PRE_TXCH,
--- a/dcdp/tc_proc.c 2023-05-22 11:58:32.715356238 +0200
+++ b/dcdp/tc_proc.c 2023-05-22 11:59:13.454660657 +0200
@@ -343,7 +343,7 @@
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- priv = ((struct tc_comm *)PDE_DATA(file_inode(file)));
+ priv = ((struct tc_comm *)pde_data(file_inode(file)));
if (priv == NULL) {
pr_err("%s: Invalid priv data\n", __func__);
return -EFAULT;
@@ -476,7 +476,7 @@
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- priv = ((struct tc_comm *)PDE_DATA(file_inode(file)));
+ priv = ((struct tc_comm *)pde_data(file_inode(file)));
if (priv == NULL) {
pr_err("%s: priv pointer is NULL!!!\n", __func__);
return -EINVAL;
@@ -746,7 +746,7 @@
static int proc_read_pp32_seq_open(struct inode *inode, struct file *file)
{
- return single_open(file, proc_read_pp32, PDE_DATA(inode));
+ return single_open(file, proc_read_pp32, pde_data(inode));
}
static const struct proc_ops pp32_proc_fops = {
@@ -822,7 +822,7 @@
len = count < sizeof(str) ? count : sizeof(str) - 1;
rlen = len - copy_from_user(str, buf, len);
str[rlen] = 0;
- priv = (struct tc_priv *)PDE_DATA(file_inode(file));
+ priv = (struct tc_priv *)pde_data(file_inode(file));
if (priv == NULL)
return count;
@@ -862,7 +862,7 @@
static int proc_read_tc_cfg_seq_open(struct inode *inode, struct file *file)
{
- return single_open(file, proc_read_tc_cfg, PDE_DATA(inode));
+ return single_open(file, proc_read_tc_cfg, pde_data(inode));
}
static const struct proc_ops tc_cfg_proc_fops = {
@@ -888,7 +888,7 @@
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- priv = (struct tc_priv *)PDE_DATA(file_inode(file));
+ priv = (struct tc_priv *)pde_data(file_inode(file));
if (priv == NULL)
return count;
@@ -947,7 +947,7 @@
static int proc_read_dbg_seq_open(struct inode *inode, struct file *file)
{
- return single_open(file, proc_read_dbg, PDE_DATA(inode));
+ return single_open(file, proc_read_dbg, pde_data(inode));
}
static const struct proc_ops tc_dbg_proc_fops = {
@@ -970,7 +970,7 @@
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- priv = (struct tc_priv *)PDE_DATA(file_inode(file));
+ priv = (struct tc_priv *)pde_data(file_inode(file));
len = count < sizeof(str) ? count : sizeof(str) - 1;
rlen = len - copy_from_user(str, buf, len);
@@ -1033,7 +1033,7 @@
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- priv = (struct tc_priv *)PDE_DATA(file_inode(file));
+ priv = (struct tc_priv *)pde_data(file_inode(file));
len = count < sizeof(str) ? count : sizeof(str) - 1;
rlen = len - copy_from_user(str, buf, len);
@@ -1125,7 +1125,7 @@
static int proc_read_ver_seq_open(struct inode *inode, struct file *file)
{
- return single_open(file, proc_read_ver, PDE_DATA(inode));
+ return single_open(file, proc_read_ver, pde_data(inode));
}
static const struct proc_ops tc_ver_proc_fops = {
@@ -1159,7 +1159,7 @@
static int proc_read_soc_seq_open(struct inode *inode, struct file *file)
{
- return single_open(file, proc_read_soc, PDE_DATA(inode));
+ return single_open(file, proc_read_soc, pde_data(inode));
}
static const struct proc_ops tc_soc_proc_fops = {
@@ -1185,7 +1185,7 @@
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- priv = (struct tc_priv *)PDE_DATA(file_inode(file));
+ priv = (struct tc_priv *)pde_data(file_inode(file));
if (priv == NULL)
return count;
@@ -1264,7 +1264,7 @@
static int proc_read_desc_conf_seq_open(struct inode *inode, struct file *file)
{
- return single_open(file, proc_read_desc_conf, PDE_DATA(inode));
+ return single_open(file, proc_read_desc_conf, pde_data(inode));
}
#endif
@@ -1343,7 +1343,7 @@
static int proc_read_ptm_wanmib_seq_open(struct inode *inode, struct file *file)
{
- return single_open(file, proc_read_ptm_wanmib, PDE_DATA(inode));
+ return single_open(file, proc_read_ptm_wanmib, pde_data(inode));
}
static const struct proc_ops ptm_wanmib_proc_fops = {
@@ -1382,7 +1382,7 @@
static int proc_read_cfg_seq_open(struct inode *inode, struct file *file)
{
- return single_open(file, proc_ptm_read_cfg, PDE_DATA(inode));
+ return single_open(file, proc_ptm_read_cfg, pde_data(inode));
}
static ssize_t ptm_cfg_proc_write(struct file *file,
@@ -1398,7 +1398,7 @@
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- priv = (struct ptm_ep_priv *)PDE_DATA(file_inode(file));
+ priv = (struct ptm_ep_priv *)pde_data(file_inode(file));
if (priv == NULL) {
pr_err("%s: Invalid private data\n", __func__);
return -EINVAL;
@@ -1478,7 +1478,7 @@
p1 = local_buf;
num = vrx_split_buffer(local_buf, param_list, ARRAY_SIZE(param_list));
- priv = (struct ptm_ep_priv *)PDE_DATA(file_inode(file));
+ priv = (struct ptm_ep_priv *)pde_data(file_inode(file));
if (priv == NULL) {
pr_err("%s: Invalid private data\n", __func__);
@@ -1554,7 +1554,7 @@
static int proc_ptm_read_prio_seq_open(struct inode *inode, struct file *file)
{
- return single_open(file, proc_ptm_read_prio, PDE_DATA(inode));
+ return single_open(file, proc_ptm_read_prio, pde_data(inode));
}
static const struct proc_ops ptm_prio_proc_fops = {
@@ -1567,7 +1567,7 @@
static int proc_ptm_read_bond_seq_open(struct inode *inode, struct file *file)
{
- return single_open(file, proc_ptm_read_bond, PDE_DATA(inode));
+ return single_open(file, proc_ptm_read_bond, pde_data(inode));
}
static const struct proc_ops ptm_bond_proc_fops = {
@@ -1580,7 +1580,7 @@
static int proc_ptm_read_bondmib_seq_open(struct inode *inode,
struct file *file)
{
- return single_open(file, proc_ptm_read_bondmib, PDE_DATA(inode));
+ return single_open(file, proc_ptm_read_bondmib, pde_data(inode));
}
static const struct proc_ops ptm_bondmib_proc_fops = {
@@ -1983,7 +1983,7 @@
num = vrx_split_buffer(local_buf, param_list,
ARRAY_SIZE(param_list));
- priv = (struct tc_comm *)PDE_DATA(file_inode(file));
+ priv = (struct tc_comm *)pde_data(file_inode(file));
if (priv == NULL) {
pr_err("<%s>: Invalid private data\n", __func__);
return count;
@@ -2158,7 +2158,7 @@
static int proc_read_atm_cfg_seq_open(struct inode *inode, struct file *file)
{
- return single_open(file, proc_read_atm_cfg, PDE_DATA(inode));
+ return single_open(file, proc_read_atm_cfg, pde_data(inode));
}
static ssize_t atm_cfg_proc_write(struct file *file,
@@ -2174,7 +2174,7 @@
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- priv = (struct atm_priv *)PDE_DATA(file_inode(file));
+ priv = (struct atm_priv *)pde_data(file_inode(file));
if (!access_ok(buf, count))
return -EFAULT;
@@ -2238,7 +2238,7 @@
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- priv = (struct atm_priv *)PDE_DATA(file_inode(file));
+ priv = (struct atm_priv *)pde_data(file_inode(file));
if (priv == NULL) {
pr_err("%s: Invalid private data\n", __func__);
return -EINVAL;
@@ -2266,7 +2266,7 @@
static int proc_read_atm_wanmib_seq_open(struct inode *inode,
struct file *file)
{
- return single_open(file, proc_read_atm_wanmib, PDE_DATA(inode));
+ return single_open(file, proc_read_atm_wanmib, pde_data(inode));
}
@@ -2281,7 +2281,7 @@
static int proc_read_htu_seq_open(struct inode *inode, struct file *file)
{
- return single_open(file, proc_read_htu, PDE_DATA(inode));
+ return single_open(file, proc_read_htu, pde_data(inode));
}
static const struct proc_ops htu_proc_fops = {
@@ -2293,7 +2293,7 @@
static int proc_read_queue_seq_open(struct inode *inode, struct file *file)
{
- return single_open(file, proc_read_queue, PDE_DATA(inode));
+ return single_open(file, proc_read_queue, pde_data(inode));
}
static const struct proc_ops queue_proc_fops = {
@@ -2350,7 +2350,7 @@
p1 = local_buf;
num = vrx_split_buffer(local_buf, param_list, ARRAY_SIZE(param_list));
- priv = (struct atm_priv *)PDE_DATA(file_inode(file));
+ priv = (struct atm_priv *)pde_data(file_inode(file));
if (vrx_strcmpi(param_list[0], "help") == 0)
goto proc_atm_prio_help;
else if (vrx_strcmpi(param_list[0], "pvc") == 0) {
@@ -2513,7 +2513,7 @@
static int proc_atm_read_prio_seq_open(struct inode *inode, struct file *file)
{
- return single_open(file, proc_atm_read_prio, PDE_DATA(inode));
+ return single_open(file, proc_atm_read_prio, pde_data(inode));
}
static const struct seq_operations pvc_mib_seq_ops = {
@@ -2536,7 +2536,7 @@
int ret = seq_open(file, &pvc_mib_seq_ops);
if (ret == 0) {
struct seq_file *m = file->private_data;
- m->private = PDE_DATA(inode);
+ m->private = pde_data(inode);
}
return ret;
}
@@ -2574,7 +2574,7 @@
local_buf[len] = 0;
num = vrx_split_buffer(local_buf, param_list, ARRAY_SIZE(param_list));
- priv = (struct atm_priv *)PDE_DATA(file_inode(file));
+ priv = (struct atm_priv *)pde_data(file_inode(file));
if (priv == NULL) {
pr_err("<%s>: Invalid private data\n", __func__);
return count;

View file

@ -0,0 +1,533 @@
CONFIG_ALIGNMENT_TRAP=y
# CONFIG_APQ_GCC_8084 is not set
# CONFIG_APQ_MMCC_8084 is not set
CONFIG_ARCH_32BIT_OFF_T=y
CONFIG_ARCH_FORCE_MAX_ORDER=11
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_IPQ40XX=y
CONFIG_ARCH_KEEP_MEMBLOCK=y
# CONFIG_ARCH_MDM9615 is not set
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
# CONFIG_ARCH_MSM8909 is not set
# CONFIG_ARCH_MSM8916 is not set
# CONFIG_ARCH_MSM8960 is not set
# CONFIG_ARCH_MSM8974 is not set
# CONFIG_ARCH_MSM8X60 is not set
CONFIG_ARCH_MULTIPLATFORM=y
CONFIG_ARCH_MULTI_V6_V7=y
CONFIG_ARCH_MULTI_V7=y
CONFIG_ARCH_NR_GPIO=0
CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y
CONFIG_ARCH_QCOM=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARM=y
CONFIG_ARM_AMBA=y
CONFIG_ARM_APPENDED_DTB=y
CONFIG_ARM_ARCH_TIMER=y
CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
# CONFIG_ARM_ATAG_DTB_COMPAT is not set
CONFIG_ARM_CPUIDLE=y
# CONFIG_ARM_CPU_TOPOLOGY is not set
CONFIG_ARM_CRYPTO=y
CONFIG_ARM_GIC=y
CONFIG_ARM_HAS_SG_CHAIN=y
CONFIG_ARM_L1_CACHE_SHIFT=6
CONFIG_ARM_L1_CACHE_SHIFT_6=y
CONFIG_ARM_PATCH_IDIV=y
CONFIG_ARM_PATCH_PHYS_VIRT=y
# CONFIG_ARM_QCOM_CPUFREQ_HW is not set
# CONFIG_ARM_QCOM_CPUFREQ_NVMEM is not set
# CONFIG_ARM_QCOM_SPM_CPUIDLE is not set
# CONFIG_ARM_SMMU is not set
CONFIG_ARM_THUMB=y
CONFIG_ARM_UNWIND=y
CONFIG_ARM_VIRT_EXT=y
CONFIG_AT803X_PHY=y
CONFIG_AUTO_ZRELADDR=y
CONFIG_BCH=y
CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_MQ_PCI=y
CONFIG_BOUNCE=y
# CONFIG_CACHE_L2X0 is not set
CONFIG_CLKSRC_QCOM=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_CMDLINE_PARTITION=y
CONFIG_COMMON_CLK=y
CONFIG_COMMON_CLK_QCOM=y
CONFIG_COMPAT_32BIT_TIME=y
CONFIG_CPUFREQ_DT=y
CONFIG_CPUFREQ_DT_PLATDEV=y
CONFIG_CPU_32v6K=y
CONFIG_CPU_32v7=y
CONFIG_CPU_ABRT_EV7=y
CONFIG_CPU_CACHE_V7=y
CONFIG_CPU_CACHE_VIPT=y
CONFIG_CPU_COPY_V6=y
CONFIG_CPU_CP15=y
CONFIG_CPU_CP15_MMU=y
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
CONFIG_CPU_FREQ_GOV_ATTR_SET=y
CONFIG_CPU_FREQ_GOV_COMMON=y
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_HAS_ASID=y
CONFIG_CPU_IDLE=y
CONFIG_CPU_IDLE_GOV_LADDER=y
CONFIG_CPU_IDLE_GOV_MENU=y
CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y
CONFIG_CPU_PABRT_V7=y
CONFIG_CPU_PM=y
CONFIG_CPU_RMAP=y
CONFIG_CPU_SPECTRE=y
CONFIG_CPU_THERMAL=y
CONFIG_CPU_THUMB_CAPABLE=y
CONFIG_CPU_TLB_V7=y
CONFIG_CPU_V7=y
CONFIG_CRC16=y
# CONFIG_CRC32_SARWATE is not set
CONFIG_CRC32_SLICEBY8=y
CONFIG_CRC8=y
CONFIG_CRYPTO_AES_ARM=y
CONFIG_CRYPTO_AES_ARM_BS=y
CONFIG_CRYPTO_BLAKE2S_ARM=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_CRYPTD=y
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_DEV_QCE=y
# CONFIG_CRYPTO_DEV_QCE_ENABLE_AEAD is not set
# CONFIG_CRYPTO_DEV_QCE_ENABLE_ALL is not set
# CONFIG_CRYPTO_DEV_QCE_ENABLE_SHA is not set
CONFIG_CRYPTO_DEV_QCE_ENABLE_SKCIPHER=y
CONFIG_CRYPTO_DEV_QCE_SKCIPHER=y
CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN=512
CONFIG_CRYPTO_DEV_QCOM_RNG=y
CONFIG_CRYPTO_DRBG=y
CONFIG_CRYPTO_DRBG_HMAC=y
CONFIG_CRYPTO_DRBG_MENU=y
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_HASH_INFO=y
CONFIG_CRYPTO_HMAC=y
CONFIG_CRYPTO_HW=y
CONFIG_CRYPTO_JITTERENTROPY=y
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
CONFIG_CRYPTO_LIB_DES=y
CONFIG_CRYPTO_LIB_SHA256=y
CONFIG_CRYPTO_LZO=y
CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_RNG_DEFAULT=y
CONFIG_CRYPTO_SEQIV=y
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA256_ARM=y
CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_SIMD=y
CONFIG_CRYPTO_XTS=y
CONFIG_CRYPTO_ZSTD=y
CONFIG_DCACHE_WORD_ACCESS=y
CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
CONFIG_DEBUG_MISC=y
CONFIG_DMADEVICES=y
CONFIG_DMA_ENGINE=y
CONFIG_DMA_OF=y
CONFIG_DMA_OPS=y
CONFIG_DMA_REMAP=y
CONFIG_DMA_SHARED_BUFFER=y
CONFIG_DMA_VIRTUAL_CHANNELS=y
CONFIG_DTC=y
CONFIG_DT_IDLE_STATES=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_EDAC_ATOMIC_SCRUB=y
CONFIG_EDAC_SUPPORT=y
CONFIG_EEPROM_AT24=y
CONFIG_EXTCON=y
CONFIG_FIXED_PHY=y
CONFIG_FIX_EARLYCON_MEM=y
CONFIG_FWNODE_MDIO=y
CONFIG_FW_LOADER_PAGED_BUF=y
CONFIG_GENERIC_ALLOCATOR=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_GENERIC_CPU_AUTOPROBE=y
CONFIG_GENERIC_CPU_VULNERABILITIES=y
CONFIG_GENERIC_EARLY_IOREMAP=y
CONFIG_GENERIC_GETTIMEOFDAY=y
CONFIG_GENERIC_IDLE_POLL_SETUP=y
CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
CONFIG_GENERIC_IRQ_MULTI_HANDLER=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y
CONFIG_GENERIC_MSI_IRQ=y
CONFIG_GENERIC_MSI_IRQ_DOMAIN=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_PHY=y
CONFIG_GENERIC_PINCONF=y
CONFIG_GENERIC_PINCTRL_GROUPS=y
CONFIG_GENERIC_PINMUX_FUNCTIONS=y
CONFIG_GENERIC_SCHED_CLOCK=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GENERIC_STRNCPY_FROM_USER=y
CONFIG_GENERIC_STRNLEN_USER=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GENERIC_VDSO_32=y
CONFIG_GPIOLIB_IRQCHIP=y
CONFIG_GPIO_74X164=y
CONFIG_GPIO_CDEV=y
CONFIG_GPIO_WATCHDOG=y
CONFIG_GPIO_WATCHDOG_ARCH_INITCALL=y
CONFIG_GRO_CELLS=y
CONFIG_HANDLE_DOMAIN_IRQ=y
CONFIG_HARDEN_BRANCH_PREDICTOR=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y
CONFIG_HAVE_SMP=y
CONFIG_HIGHMEM=y
# CONFIG_HIGHPTE is not set
CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_QCOM=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_OPTEE=y
CONFIG_HZ_FIXED=0
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_HELPER_AUTO=y
# CONFIG_I2C_QCOM_CCI is not set
CONFIG_I2C_QUP=y
CONFIG_INITRAMFS_SOURCE=""
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set
# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set
CONFIG_IOMMU_SUPPORT=y
CONFIG_IO_URING=y
# CONFIG_IPQ_APSS_PLL is not set
CONFIG_IPQ_GCC_4019=y
# CONFIG_IPQ_GCC_6018 is not set
# CONFIG_IPQ_GCC_806X is not set
# CONFIG_IPQ_GCC_8074 is not set
# CONFIG_IPQ_LCC_806X is not set
CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_DOMAIN_HIERARCHY=y
CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_WORK=y
CONFIG_KMAP_LOCAL=y
CONFIG_KMAP_LOCAL_NON_LINEAR_PTE_ARRAY=y
# CONFIG_KPSS_XCC is not set
# CONFIG_KRAITCC is not set
CONFIG_LEDS_LP5523=y
CONFIG_LEDS_LP5562=y
CONFIG_LEDS_LP55XX_COMMON=y
CONFIG_LEDS_TLC591XX=y
CONFIG_LIBFDT=y
CONFIG_LOCK_DEBUGGING_SUPPORT=y
CONFIG_LOCK_SPIN_ON_OWNER=y
CONFIG_LZO_COMPRESS=y
CONFIG_LZO_DECOMPRESS=y
CONFIG_MDIO_BITBANG=y
CONFIG_MDIO_BUS=y
CONFIG_MDIO_DEVICE=y
CONFIG_MDIO_DEVRES=y
CONFIG_MDIO_GPIO=y
CONFIG_MDIO_IPQ4019=y
# CONFIG_MDM_GCC_9615 is not set
# CONFIG_MDM_LCC_9615 is not set
CONFIG_MEMFD_CREATE=y
# CONFIG_MFD_HI6421_SPMI is not set
# CONFIG_MFD_QCOM_RPM is not set
# CONFIG_MFD_SPMI_PMIC is not set
CONFIG_MFD_SYSCON=y
CONFIG_MIGHT_HAVE_CACHE_L2X0=y
CONFIG_MIGRATION=y
CONFIG_MMC=y
CONFIG_MMC_BLOCK=y
CONFIG_MMC_CQHCI=y
# CONFIG_MSM_GCC_8909 is not set
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_IO_ACCESSORS=y
CONFIG_MMC_SDHCI_MSM=y
# CONFIG_MMC_SDHCI_PCI is not set
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MODULES_USE_ELF_REL=y
# CONFIG_MSM_GCC_8660 is not set
# CONFIG_MSM_GCC_8916 is not set
# CONFIG_MSM_GCC_8939 is not set
# CONFIG_MSM_GCC_8960 is not set
# CONFIG_MSM_GCC_8974 is not set
# CONFIG_MSM_GCC_8976 is not set
# CONFIG_MSM_GCC_8994 is not set
# CONFIG_MSM_GCC_8996 is not set
# CONFIG_MSM_GCC_8998 is not set
# CONFIG_MSM_GPUCC_8998 is not set
# CONFIG_MSM_LCC_8960 is not set
# CONFIG_MSM_MMCC_8960 is not set
# CONFIG_MSM_MMCC_8974 is not set
# CONFIG_MSM_MMCC_8996 is not set
# CONFIG_MSM_MMCC_8998 is not set
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_NAND_CORE=y
CONFIG_MTD_NAND_ECC=y
CONFIG_MTD_NAND_ECC_SW_BCH=y
CONFIG_MTD_NAND_ECC_SW_HAMMING=y
CONFIG_MTD_NAND_QCOM=y
# CONFIG_MTD_QCOMSMEM_PARTS is not set
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_SPI_NAND=y
CONFIG_MTD_SPI_NOR=y
CONFIG_MTD_SPLIT_FIRMWARE=y
CONFIG_MTD_SPLIT_FIT_FW=y
CONFIG_MTD_SPLIT_WRGG_FW=y
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_BEB_LIMIT=20
CONFIG_MTD_UBI_BLOCK=y
CONFIG_MTD_UBI_WL_THRESHOLD=4096
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEON=y
CONFIG_NET_DEVLINK=y
CONFIG_NET_DSA=y
CONFIG_NET_DSA_QCA8K_IPQ4019=y
CONFIG_NET_DSA_TAG_IPQ4019=y
CONFIG_NET_FLOW_LIMIT=y
CONFIG_NET_PTP_CLASSIFY=y
CONFIG_NET_SELFTESTS=y
CONFIG_NET_SWITCHDEV=y
CONFIG_NLS=y
CONFIG_NO_HZ=y
CONFIG_NO_HZ_COMMON=y
CONFIG_NO_HZ_IDLE=y
CONFIG_NR_CPUS=4
CONFIG_NVMEM=y
CONFIG_NVMEM_QCOM_QFPROM=y
# CONFIG_NVMEM_SPMI_SDAM is not set
CONFIG_NVMEM_SYSFS=y
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IRQ=y
CONFIG_OF_KOBJ=y
CONFIG_OF_MDIO=y
CONFIG_OLD_SIGACTION=y
CONFIG_OLD_SIGSUSPEND3=y
CONFIG_OPTEE=y
CONFIG_OPTEE_SHM_NUM_PRIV_PAGES=1
CONFIG_PADATA=y
CONFIG_PAGE_OFFSET=0xC0000000
CONFIG_PCI=y
CONFIG_PCIEAER=y
CONFIG_PCIEPORTBUS=y
CONFIG_PCIE_DW=y
CONFIG_PCIE_DW_HOST=y
CONFIG_PCIE_QCOM=y
CONFIG_PCI_DISABLE_COMMON_QUIRKS=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_DOMAINS_GENERIC=y
CONFIG_PCI_MSI=y
CONFIG_PCI_MSI_IRQ_DOMAIN=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PGTABLE_LEVELS=2
CONFIG_PHYLIB=y
CONFIG_PHYLINK=y
# CONFIG_PHY_QCOM_APQ8064_SATA is not set
CONFIG_PHY_QCOM_IPQ4019_USB=y
# CONFIG_PHY_QCOM_IPQ806X_SATA is not set
# CONFIG_PHY_QCOM_IPQ806X_USB is not set
# CONFIG_PHY_QCOM_PCIE2 is not set
# CONFIG_PHY_QCOM_QMP is not set
# CONFIG_PHY_QCOM_QUSB2 is not set
# CONFIG_PHY_QCOM_USB_HS_28NM is not set
# CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2 is not set
# CONFIG_PHY_QCOM_USB_SS is not set
CONFIG_PINCTRL=y
# CONFIG_PINCTRL_APQ8064 is not set
# CONFIG_PINCTRL_APQ8084 is not set
CONFIG_PINCTRL_IPQ4019=y
# CONFIG_PINCTRL_IPQ6018 is not set
# CONFIG_PINCTRL_IPQ8064 is not set
# CONFIG_PINCTRL_IPQ8074 is not set
# CONFIG_PINCTRL_MDM9615 is not set
CONFIG_PINCTRL_MSM=y
# CONFIG_PINCTRL_MSM8226 is not set
# CONFIG_PINCTRL_MSM8660 is not set
# CONFIG_PINCTRL_MSM8909 is not set
# CONFIG_PINCTRL_MSM8916 is not set
# CONFIG_PINCTRL_MSM8960 is not set
# CONFIG_PINCTRL_MSM8976 is not set
# CONFIG_PINCTRL_MSM8994 is not set
# CONFIG_PINCTRL_MSM8996 is not set
# CONFIG_PINCTRL_MSM8998 is not set
# CONFIG_PINCTRL_QCOM_SPMI_PMIC is not set
# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set
# CONFIG_PINCTRL_QCS404 is not set
# CONFIG_PINCTRL_SC7180 is not set
# CONFIG_PINCTRL_SDM660 is not set
# CONFIG_PINCTRL_SDM845 is not set
# CONFIG_PINCTRL_SM8150 is not set
# CONFIG_PINCTRL_SM8250 is not set
# CONFIG_PINCTRL_SDX65 is not set
# CONFIG_PHY_QCOM_EDP is not set
CONFIG_PM_OPP=y
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_MSM=y
CONFIG_POWER_SUPPLY=y
CONFIG_PPS=y
CONFIG_PRINTK_TIME=y
CONFIG_PTP_1588_CLOCK=y
CONFIG_PTP_1588_CLOCK_OPTIONAL=y
CONFIG_QCA807X_PHY=y
# CONFIG_QCM_GCC_2290 is not set
# CONFIG_QCM_DISPCC_2290 is not set
CONFIG_QCOM_A53PLL=y
# CONFIG_QCOM_ADM is not set
CONFIG_QCOM_BAM_DMA=y
# CONFIG_QCOM_COMMAND_DB is not set
# CONFIG_QCOM_CPR is not set
# CONFIG_QCOM_EBI2 is not set
# CONFIG_QCOM_GENI_SE is not set
# CONFIG_QCOM_GSBI is not set
# CONFIG_QCOM_HFPLL is not set
# CONFIG_QCOM_ICC_BWMON is not set
# CONFIG_QCOM_IOMMU is not set
CONFIG_QCOM_IPQ4019_ESS_EDMA=y
# CONFIG_QCOM_LLCC is not set
# CONFIG_QCOM_OCMEM is not set
# CONFIG_QCOM_PDC is not set
# CONFIG_QCOM_RMTFS_MEM is not set
# CONFIG_QCOM_RPMH is not set
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set
CONFIG_QCOM_SMEM=y
# CONFIG_QCOM_SMSM is not set
# CONFIG_QCOM_SOCINFO is not set
# CONFIG_QCOM_SPM is not set
# CONFIG_QCOM_STATS is not set
CONFIG_QCOM_TCSR=y
# CONFIG_QCOM_TSENS is not set
CONFIG_QCOM_WDT=y
# CONFIG_QCS_GCC_404 is not set
# CONFIG_QCS_Q6SSTOP_404 is not set
# CONFIG_QCS_TURING_404 is not set
CONFIG_RAS=y
CONFIG_RATIONAL=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_MMIO=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
# CONFIG_REGULATOR_QCOM_LABIBB is not set
# CONFIG_REGULATOR_QCOM_SPMI is not set
# CONFIG_REGULATOR_QCOM_USB_VBUS is not set
CONFIG_REGULATOR_VCTRL=y
CONFIG_REGULATOR_VQMMC_IPQ4019=y
CONFIG_RESET_CONTROLLER=y
# CONFIG_RESET_QCOM_AOSS is not set
# CONFIG_RESET_QCOM_PDC is not set
CONFIG_RFS_ACCEL=y
CONFIG_RPS=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_DRV_OPTEE is not set
CONFIG_RTC_I2C_AND_SPI=y
CONFIG_RTC_MC146818_LIB=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
# CONFIG_SC_CAMCC_7280 is not set
# CONFIG_SC_DISPCC_7180 is not set
# CONFIG_SC_GCC_7180 is not set
# CONFIG_SC_GCC_8280XP is not set
# CONFIG_SC_GPUCC_7180 is not set
# CONFIG_SC_LPASS_CORECC_7180 is not set
# CONFIG_SC_LPASSCC_7280 is not set
# CONFIG_SC_LPASS_CORECC_7280 is not set
# CONFIG_SC_MSS_7180 is not set
# CONFIG_SC_VIDEOCC_7180 is not set
# CONFIG_SDM_CAMCC_845 is not set
# CONFIG_SDM_DISPCC_845 is not set
# CONFIG_SDM_GCC_660 is not set
# CONFIG_SDM_GCC_845 is not set
# CONFIG_SDM_GPUCC_845 is not set
# CONFIG_SDM_LPASSCC_845 is not set
# CONFIG_SDM_VIDEOCC_845 is not set
# CONFIG_SDX_GCC_65 is not set
CONFIG_SERIAL_8250_FSL=y
CONFIG_SERIAL_MCTRL_GPIO=y
CONFIG_SERIAL_MSM=y
CONFIG_SERIAL_MSM_CONSOLE=y
CONFIG_SGL_ALLOC=y
CONFIG_SMP=y
CONFIG_SMP_ON_UP=y
# CONFIG_SM_CAMCC_8450 is not set
# CONFIG_SM_GCC_8150 is not set
# CONFIG_SM_GCC_8250 is not set
# CONFIG_SM_GCC_8450 is not set
# CONFIG_SM_GPUCC_6350 is not set
# CONFIG_SM_GPUCC_8150 is not set
# CONFIG_SM_GPUCC_8250 is not set
# CONFIG_SM_GPUCC_8350 is not set
# CONFIG_SM_VIDEOCC_8150 is not set
# CONFIG_SM_VIDEOCC_8250 is not set
CONFIG_SOCK_RX_QUEUE_MAPPING=y
CONFIG_SPARSE_IRQ=y
CONFIG_SPI=y
CONFIG_SPI_BITBANG=y
CONFIG_SPI_GPIO=y
CONFIG_SPI_MASTER=y
CONFIG_SPI_MEM=y
CONFIG_SPI_QUP=y
CONFIG_SPMI=y
# CONFIG_SPMI_HISI3670 is not set
CONFIG_SPMI_MSM_PMIC_ARB=y
# CONFIG_SPMI_PMIC_CLKDIV is not set
CONFIG_SRCU=y
CONFIG_SWPHY=y
CONFIG_SWP_EMULATE=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
CONFIG_TEE=y
CONFIG_THERMAL=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_OF=y
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_TIMER_OF=y
CONFIG_TIMER_PROBE=y
CONFIG_TREE_RCU=y
CONFIG_TREE_SRCU=y
# CONFIG_TRUSTED_KEYS_TEE is not set
CONFIG_UBIFS_FS=y
CONFIG_UEVENT_HELPER_PATH=""
CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
CONFIG_UNWINDER_ARM=y
CONFIG_USB=y
CONFIG_USB_COMMON=y
CONFIG_USB_SUPPORT=y
CONFIG_USE_OF=y
CONFIG_VFP=y
CONFIG_VFPv3=y
CONFIG_WATCHDOG_CORE=y
CONFIG_XPS=y
CONFIG_XXHASH=y
CONFIG_XZ_DEC_ARM=y
CONFIG_XZ_DEC_BCJ=y
CONFIG_ZBOOT_ROM_BSS=0
CONFIG_ZBOOT_ROM_TEXT=0
CONFIG_ZLIB_DEFLATE=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZSTD_COMPRESS=y
CONFIG_ZSTD_DECOMPRESS=y

View file

@ -0,0 +1,859 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2020 Sartura Ltd.
*
* Author: Robert Marko <robert.marko@sartura.hr>
*
* Qualcomm QCA8072 and QCA8075 PHY driver
*/
#include <linux/version.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/phy.h>
#include <linux/bitfield.h>
#include <linux/ethtool_netlink.h>
#include <linux/gpio.h>
#include <linux/sfp.h>
#include <dt-bindings/net/qcom-qca807x.h>
#define PHY_ID_QCA8072 0x004dd0b2
#define PHY_ID_QCA8075 0x004dd0b1
#define PHY_ID_QCA807X_PSGMII 0x06820805
/* Downshift */
#define QCA807X_SMARTSPEED_EN BIT(5)
#define QCA807X_SMARTSPEED_RETRY_LIMIT_MASK GENMASK(4, 2)
#define QCA807X_SMARTSPEED_RETRY_LIMIT_DEFAULT 5
#define QCA807X_SMARTSPEED_RETRY_LIMIT_MIN 2
#define QCA807X_SMARTSPEED_RETRY_LIMIT_MAX 9
/* Cable diagnostic test (CDT) */
#define QCA807X_CDT 0x16
#define QCA807X_CDT_ENABLE BIT(15)
#define QCA807X_CDT_ENABLE_INTER_PAIR_SHORT BIT(13)
#define QCA807X_CDT_STATUS BIT(11)
#define QCA807X_CDT_MMD3_STATUS 0x8064
#define QCA807X_CDT_MDI0_STATUS_MASK GENMASK(15, 12)
#define QCA807X_CDT_MDI1_STATUS_MASK GENMASK(11, 8)
#define QCA807X_CDT_MDI2_STATUS_MASK GENMASK(7, 4)
#define QCA807X_CDT_MDI3_STATUS_MASK GENMASK(3, 0)
#define QCA807X_CDT_RESULTS_INVALID 0x0
#define QCA807X_CDT_RESULTS_OK 0x1
#define QCA807X_CDT_RESULTS_OPEN 0x2
#define QCA807X_CDT_RESULTS_SAME_SHORT 0x3
#define QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI1_SAME_OK 0x4
#define QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI2_SAME_OK 0x8
#define QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI3_SAME_OK 0xc
#define QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI1_SAME_OPEN 0x6
#define QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI2_SAME_OPEN 0xa
#define QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI3_SAME_OPEN 0xe
#define QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI1_SAME_SHORT 0x7
#define QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI2_SAME_SHORT 0xb
#define QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI3_SAME_SHORT 0xf
#define QCA807X_CDT_RESULTS_BUSY 0x9
#define QCA807X_CDT_MMD3_MDI0_LENGTH 0x8065
#define QCA807X_CDT_MMD3_MDI1_LENGTH 0x8066
#define QCA807X_CDT_MMD3_MDI2_LENGTH 0x8067
#define QCA807X_CDT_MMD3_MDI3_LENGTH 0x8068
#define QCA807X_CDT_SAME_SHORT_LENGTH_MASK GENMASK(15, 8)
#define QCA807X_CDT_CROSS_SHORT_LENGTH_MASK GENMASK(7, 0)
#define QCA807X_CHIP_CONFIGURATION 0x1f
#define QCA807X_BT_BX_REG_SEL BIT(15)
#define QCA807X_BT_BX_REG_SEL_FIBER 0
#define QCA807X_BT_BX_REG_SEL_COPPER 1
#define QCA807X_CHIP_CONFIGURATION_MODE_CFG_MASK GENMASK(3, 0)
#define QCA807X_CHIP_CONFIGURATION_MODE_QSGMII_SGMII 4
#define QCA807X_CHIP_CONFIGURATION_MODE_PSGMII_FIBER 3
#define QCA807X_CHIP_CONFIGURATION_MODE_PSGMII_ALL_COPPER 0
#define QCA807X_MEDIA_SELECT_STATUS 0x1a
#define QCA807X_MEDIA_DETECTED_COPPER BIT(5)
#define QCA807X_MEDIA_DETECTED_1000_BASE_X BIT(4)
#define QCA807X_MEDIA_DETECTED_100_BASE_FX BIT(3)
#define QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION 0x807e
#define QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION_EN BIT(0)
#define QCA807X_MMD7_1000BASE_T_POWER_SAVE_PER_CABLE_LENGTH 0x801a
#define QCA807X_CONTROL_DAC_MASK GENMASK(2, 0)
#define QCA807X_MMD7_LED_100N_1 0x8074
#define QCA807X_MMD7_LED_100N_2 0x8075
#define QCA807X_MMD7_LED_1000N_1 0x8076
#define QCA807X_MMD7_LED_1000N_2 0x8077
#define QCA807X_LED_TXACT_BLK_EN_2 BIT(10)
#define QCA807X_LED_RXACT_BLK_EN_2 BIT(9)
#define QCA807X_LED_GT_ON_EN_2 BIT(6)
#define QCA807X_LED_HT_ON_EN_2 BIT(5)
#define QCA807X_LED_BT_ON_EN_2 BIT(4)
#define QCA807X_GPIO_FORCE_EN BIT(15)
#define QCA807X_GPIO_FORCE_MODE_MASK GENMASK(14, 13)
#define QCA807X_INTR_ENABLE 0x12
#define QCA807X_INTR_STATUS 0x13
#define QCA807X_INTR_ENABLE_AUTONEG_ERR BIT(15)
#define QCA807X_INTR_ENABLE_SPEED_CHANGED BIT(14)
#define QCA807X_INTR_ENABLE_DUPLEX_CHANGED BIT(13)
#define QCA807X_INTR_ENABLE_LINK_FAIL BIT(11)
#define QCA807X_INTR_ENABLE_LINK_SUCCESS BIT(10)
#define QCA807X_FUNCTION_CONTROL 0x10
#define QCA807X_FC_MDI_CROSSOVER_MODE_MASK GENMASK(6, 5)
#define QCA807X_FC_MDI_CROSSOVER_AUTO 3
#define QCA807X_FC_MDI_CROSSOVER_MANUAL_MDIX 1
#define QCA807X_FC_MDI_CROSSOVER_MANUAL_MDI 0
#define QCA807X_PHY_SPECIFIC_STATUS 0x11
#define QCA807X_SS_SPEED_AND_DUPLEX_RESOLVED BIT(11)
#define QCA807X_SS_SPEED_MASK GENMASK(15, 14)
#define QCA807X_SS_SPEED_1000 2
#define QCA807X_SS_SPEED_100 1
#define QCA807X_SS_SPEED_10 0
#define QCA807X_SS_DUPLEX BIT(13)
#define QCA807X_SS_MDIX BIT(6)
/* PSGMII PHY specific */
#define PSGMII_QSGMII_DRIVE_CONTROL_1 0xb
#define PSGMII_QSGMII_TX_DRIVER_MASK GENMASK(7, 4)
#define PSGMII_MODE_CTRL 0x6d
#define PSGMII_MODE_CTRL_AZ_WORKAROUND_MASK BIT(0)
#define PSGMII_MMD3_SERDES_CONTROL 0x805a
struct qca807x_gpio_priv {
struct phy_device *phy;
};
static int qca807x_get_downshift(struct phy_device *phydev, u8 *data)
{
int val, cnt, enable;
val = phy_read(phydev, MII_NWAYTEST);
if (val < 0)
return val;
enable = FIELD_GET(QCA807X_SMARTSPEED_EN, val);
cnt = FIELD_GET(QCA807X_SMARTSPEED_RETRY_LIMIT_MASK, val) + 2;
*data = enable ? cnt : DOWNSHIFT_DEV_DISABLE;
return 0;
}
static int qca807x_set_downshift(struct phy_device *phydev, u8 cnt)
{
int ret, val;
if (cnt > QCA807X_SMARTSPEED_RETRY_LIMIT_MAX ||
(cnt < QCA807X_SMARTSPEED_RETRY_LIMIT_MIN && cnt != DOWNSHIFT_DEV_DISABLE))
return -EINVAL;
if (!cnt) {
ret = phy_clear_bits(phydev, MII_NWAYTEST, QCA807X_SMARTSPEED_EN);
} else {
val = QCA807X_SMARTSPEED_EN;
val |= FIELD_PREP(QCA807X_SMARTSPEED_RETRY_LIMIT_MASK, cnt - 2);
phy_modify(phydev, MII_NWAYTEST,
QCA807X_SMARTSPEED_EN |
QCA807X_SMARTSPEED_RETRY_LIMIT_MASK,
val);
}
ret = genphy_soft_reset(phydev);
return ret;
}
static int qca807x_get_tunable(struct phy_device *phydev,
struct ethtool_tunable *tuna, void *data)
{
switch (tuna->id) {
case ETHTOOL_PHY_DOWNSHIFT:
return qca807x_get_downshift(phydev, data);
default:
return -EOPNOTSUPP;
}
}
static int qca807x_set_tunable(struct phy_device *phydev,
struct ethtool_tunable *tuna, const void *data)
{
switch (tuna->id) {
case ETHTOOL_PHY_DOWNSHIFT:
return qca807x_set_downshift(phydev, *(const u8 *)data);
default:
return -EOPNOTSUPP;
}
}
static bool qca807x_distance_valid(int result)
{
switch (result) {
case QCA807X_CDT_RESULTS_OPEN:
case QCA807X_CDT_RESULTS_SAME_SHORT:
case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI1_SAME_OK:
case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI2_SAME_OK:
case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI3_SAME_OK:
case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI1_SAME_OPEN:
case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI2_SAME_OPEN:
case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI3_SAME_OPEN:
case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI1_SAME_SHORT:
case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI2_SAME_SHORT:
case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI3_SAME_SHORT:
return true;
}
return false;
}
static int qca807x_report_length(struct phy_device *phydev,
int pair, int result)
{
int length;
int ret;
ret = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA807X_CDT_MMD3_MDI0_LENGTH + pair);
if (ret < 0)
return ret;
switch (result) {
case ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT:
length = (FIELD_GET(QCA807X_CDT_SAME_SHORT_LENGTH_MASK, ret) * 800) / 10;
break;
case ETHTOOL_A_CABLE_RESULT_CODE_OPEN:
case ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT:
length = (FIELD_GET(QCA807X_CDT_CROSS_SHORT_LENGTH_MASK, ret) * 800) / 10;
break;
}
ethnl_cable_test_fault_length(phydev, pair, length);
return 0;
}
static int qca807x_cable_test_report_trans(int result)
{
switch (result) {
case QCA807X_CDT_RESULTS_OK:
return ETHTOOL_A_CABLE_RESULT_CODE_OK;
case QCA807X_CDT_RESULTS_OPEN:
return ETHTOOL_A_CABLE_RESULT_CODE_OPEN;
case QCA807X_CDT_RESULTS_SAME_SHORT:
return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT;
case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI1_SAME_OK:
case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI2_SAME_OK:
case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI3_SAME_OK:
case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI1_SAME_OPEN:
case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI2_SAME_OPEN:
case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI3_SAME_OPEN:
case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI1_SAME_SHORT:
case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI2_SAME_SHORT:
case QCA807X_CDT_RESULTS_CROSS_SHORT_WITH_MDI3_SAME_SHORT:
return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT;
default:
return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC;
}
}
static int qca807x_cable_test_report(struct phy_device *phydev)
{
int pair0, pair1, pair2, pair3;
int ret;
ret = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA807X_CDT_MMD3_STATUS);
if (ret < 0)
return ret;
pair0 = FIELD_GET(QCA807X_CDT_MDI0_STATUS_MASK, ret);
pair1 = FIELD_GET(QCA807X_CDT_MDI1_STATUS_MASK, ret);
pair2 = FIELD_GET(QCA807X_CDT_MDI2_STATUS_MASK, ret);
pair3 = FIELD_GET(QCA807X_CDT_MDI3_STATUS_MASK, ret);
ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
qca807x_cable_test_report_trans(pair0));
ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_B,
qca807x_cable_test_report_trans(pair1));
ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_C,
qca807x_cable_test_report_trans(pair2));
ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_D,
qca807x_cable_test_report_trans(pair3));
if (qca807x_distance_valid(pair0))
qca807x_report_length(phydev, 0, qca807x_cable_test_report_trans(pair0));
if (qca807x_distance_valid(pair1))
qca807x_report_length(phydev, 1, qca807x_cable_test_report_trans(pair1));
if (qca807x_distance_valid(pair2))
qca807x_report_length(phydev, 2, qca807x_cable_test_report_trans(pair2));
if (qca807x_distance_valid(pair3))
qca807x_report_length(phydev, 3, qca807x_cable_test_report_trans(pair3));
return 0;
}
static int qca807x_cable_test_get_status(struct phy_device *phydev,
bool *finished)
{
int val;
*finished = false;
val = phy_read(phydev, QCA807X_CDT);
if (!((val & QCA807X_CDT_ENABLE) && (val & QCA807X_CDT_STATUS))) {
*finished = true;
return qca807x_cable_test_report(phydev);
}
return 0;
}
static int qca807x_cable_test_start(struct phy_device *phydev)
{
int val, ret;
val = phy_read(phydev, QCA807X_CDT);
/* Enable inter-pair short check as well */
val &= ~QCA807X_CDT_ENABLE_INTER_PAIR_SHORT;
val |= QCA807X_CDT_ENABLE;
ret = phy_write(phydev, QCA807X_CDT, val);
return ret;
}
#ifdef CONFIG_GPIOLIB
static int qca807x_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
{
return GPIO_LINE_DIRECTION_OUT;
}
static int qca807x_gpio_get_reg(unsigned int offset)
{
return QCA807X_MMD7_LED_100N_2 + (offset % 2) * 2;
}
static int qca807x_gpio_get(struct gpio_chip *gc, unsigned int offset)
{
struct qca807x_gpio_priv *priv = gpiochip_get_data(gc);
int val;
val = phy_read_mmd(priv->phy, MDIO_MMD_AN, qca807x_gpio_get_reg(offset));
return FIELD_GET(QCA807X_GPIO_FORCE_MODE_MASK, val);
}
static void qca807x_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
{
struct qca807x_gpio_priv *priv = gpiochip_get_data(gc);
int val;
val = phy_read_mmd(priv->phy, MDIO_MMD_AN, qca807x_gpio_get_reg(offset));
val &= ~QCA807X_GPIO_FORCE_MODE_MASK;
val |= QCA807X_GPIO_FORCE_EN;
val |= FIELD_PREP(QCA807X_GPIO_FORCE_MODE_MASK, value);
phy_write_mmd(priv->phy, MDIO_MMD_AN, qca807x_gpio_get_reg(offset), val);
}
static int qca807x_gpio_dir_out(struct gpio_chip *gc, unsigned int offset, int value)
{
qca807x_gpio_set(gc, offset, value);
return 0;
}
static int qca807x_gpio(struct phy_device *phydev)
{
struct device *dev = &phydev->mdio.dev;
struct qca807x_gpio_priv *priv;
struct gpio_chip *gc;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->phy = phydev;
gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL);
if (!gc)
return -ENOMEM;
gc->label = dev_name(dev);
gc->base = -1;
gc->ngpio = 2;
gc->parent = dev;
gc->owner = THIS_MODULE;
gc->can_sleep = true;
gc->get_direction = qca807x_gpio_get_direction;
gc->direction_output = qca807x_gpio_dir_out;
gc->get = qca807x_gpio_get;
gc->set = qca807x_gpio_set;
return devm_gpiochip_add_data(dev, gc, priv);
}
#endif
static int qca807x_read_copper_status(struct phy_device *phydev)
{
int ss, err, old_link = phydev->link;
/* Update the link, but return if there was an error */
err = genphy_update_link(phydev);
if (err)
return err;
/* why bother the PHY if nothing can have changed */
if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link)
return 0;
phydev->speed = SPEED_UNKNOWN;
phydev->duplex = DUPLEX_UNKNOWN;
phydev->pause = 0;
phydev->asym_pause = 0;
err = genphy_read_lpa(phydev);
if (err < 0)
return err;
/* Read the QCA807x PHY-Specific Status register copper page,
* which indicates the speed and duplex that the PHY is actually
* using, irrespective of whether we are in autoneg mode or not.
*/
ss = phy_read(phydev, QCA807X_PHY_SPECIFIC_STATUS);
if (ss < 0)
return ss;
if (ss & QCA807X_SS_SPEED_AND_DUPLEX_RESOLVED) {
int sfc;
sfc = phy_read(phydev, QCA807X_FUNCTION_CONTROL);
if (sfc < 0)
return sfc;
switch (FIELD_GET(QCA807X_SS_SPEED_MASK, ss)) {
case QCA807X_SS_SPEED_10:
phydev->speed = SPEED_10;
break;
case QCA807X_SS_SPEED_100:
phydev->speed = SPEED_100;
break;
case QCA807X_SS_SPEED_1000:
phydev->speed = SPEED_1000;
break;
}
if (ss & QCA807X_SS_DUPLEX)
phydev->duplex = DUPLEX_FULL;
else
phydev->duplex = DUPLEX_HALF;
if (ss & QCA807X_SS_MDIX)
phydev->mdix = ETH_TP_MDI_X;
else
phydev->mdix = ETH_TP_MDI;
switch (FIELD_GET(QCA807X_FC_MDI_CROSSOVER_MODE_MASK, sfc)) {
case QCA807X_FC_MDI_CROSSOVER_MANUAL_MDI:
phydev->mdix_ctrl = ETH_TP_MDI;
break;
case QCA807X_FC_MDI_CROSSOVER_MANUAL_MDIX:
phydev->mdix_ctrl = ETH_TP_MDI_X;
break;
case QCA807X_FC_MDI_CROSSOVER_AUTO:
phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
break;
}
}
if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete)
phy_resolve_aneg_pause(phydev);
return 0;
}
static int qca807x_read_fiber_status(struct phy_device *phydev)
{
int ss, err, lpa, old_link = phydev->link;
/* Update the link, but return if there was an error */
err = genphy_update_link(phydev);
if (err)
return err;
/* why bother the PHY if nothing can have changed */
if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link)
return 0;
phydev->speed = SPEED_UNKNOWN;
phydev->duplex = DUPLEX_UNKNOWN;
phydev->pause = 0;
phydev->asym_pause = 0;
if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) {
lpa = phy_read(phydev, MII_LPA);
if (lpa < 0)
return lpa;
linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
phydev->lp_advertising, lpa & LPA_LPACK);
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
phydev->lp_advertising, lpa & LPA_1000XFULL);
linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT,
phydev->lp_advertising, lpa & LPA_1000XPAUSE);
linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
phydev->lp_advertising,
lpa & LPA_1000XPAUSE_ASYM);
phy_resolve_aneg_linkmode(phydev);
}
/* Read the QCA807x PHY-Specific Status register fiber page,
* which indicates the speed and duplex that the PHY is actually
* using, irrespective of whether we are in autoneg mode or not.
*/
ss = phy_read(phydev, QCA807X_PHY_SPECIFIC_STATUS);
if (ss < 0)
return ss;
if (ss & QCA807X_SS_SPEED_AND_DUPLEX_RESOLVED) {
switch (FIELD_GET(QCA807X_SS_SPEED_MASK, ss)) {
case QCA807X_SS_SPEED_100:
phydev->speed = SPEED_100;
break;
case QCA807X_SS_SPEED_1000:
phydev->speed = SPEED_1000;
break;
}
if (ss & QCA807X_SS_DUPLEX)
phydev->duplex = DUPLEX_FULL;
else
phydev->duplex = DUPLEX_HALF;
}
return 0;
}
static int qca807x_read_status(struct phy_device *phydev)
{
if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported)) {
switch (phydev->port) {
case PORT_FIBRE:
return qca807x_read_fiber_status(phydev);
case PORT_TP:
return qca807x_read_copper_status(phydev);
default:
return -EINVAL;
}
} else
return qca807x_read_copper_status(phydev);
}
static int qca807x_config_intr(struct phy_device *phydev)
{
int ret, val;
val = phy_read(phydev, QCA807X_INTR_ENABLE);
if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
/* Check for combo port as it has fewer interrupts */
if (phy_read(phydev, QCA807X_CHIP_CONFIGURATION)) {
val |= QCA807X_INTR_ENABLE_SPEED_CHANGED;
val |= QCA807X_INTR_ENABLE_LINK_FAIL;
val |= QCA807X_INTR_ENABLE_LINK_SUCCESS;
} else {
val |= QCA807X_INTR_ENABLE_AUTONEG_ERR;
val |= QCA807X_INTR_ENABLE_SPEED_CHANGED;
val |= QCA807X_INTR_ENABLE_DUPLEX_CHANGED;
val |= QCA807X_INTR_ENABLE_LINK_FAIL;
val |= QCA807X_INTR_ENABLE_LINK_SUCCESS;
}
ret = phy_write(phydev, QCA807X_INTR_ENABLE, val);
} else {
ret = phy_write(phydev, QCA807X_INTR_ENABLE, 0);
}
return ret;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0)
static int qca807x_ack_intr(struct phy_device *phydev)
{
int ret;
ret = phy_read(phydev, QCA807X_INTR_STATUS);
return (ret < 0) ? ret : 0;
}
#else
static irqreturn_t qca807x_handle_interrupt(struct phy_device *phydev)
{
int irq_status, int_enabled;
irq_status = phy_read(phydev, QCA807X_INTR_STATUS);
if (irq_status < 0) {
phy_error(phydev);
return IRQ_NONE;
}
/* Read the current enabled interrupts */
int_enabled = phy_read(phydev, QCA807X_INTR_ENABLE);
if (int_enabled < 0) {
phy_error(phydev);
return IRQ_NONE;
}
/* See if this was one of our enabled interrupts */
if (!(irq_status & int_enabled))
return IRQ_NONE;
phy_trigger_machine(phydev);
return IRQ_HANDLED;
}
#endif
static int qca807x_led_config(struct phy_device *phydev)
{
struct device_node *node = phydev->mdio.dev.of_node;
bool led_config = false;
int val;
val = phy_read_mmd(phydev, MDIO_MMD_AN, QCA807X_MMD7_LED_1000N_1);
if (val < 0)
return val;
if (of_property_read_bool(node, "qcom,single-led-1000")) {
val |= QCA807X_LED_TXACT_BLK_EN_2;
val |= QCA807X_LED_RXACT_BLK_EN_2;
val |= QCA807X_LED_GT_ON_EN_2;
led_config = true;
}
if (of_property_read_bool(node, "qcom,single-led-100")) {
val |= QCA807X_LED_HT_ON_EN_2;
led_config = true;
}
if (of_property_read_bool(node, "qcom,single-led-10")) {
val |= QCA807X_LED_BT_ON_EN_2;
led_config = true;
}
if (led_config)
return phy_write_mmd(phydev, MDIO_MMD_AN, QCA807X_MMD7_LED_1000N_1, val);
else
return 0;
}
static int qca807x_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
{
struct phy_device *phydev = upstream;
__ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, };
DECLARE_PHY_INTERFACE_MASK(interfaces);
phy_interface_t iface;
int ret;
sfp_parse_support(phydev->sfp_bus, id, support, interfaces);
iface = sfp_select_interface(phydev->sfp_bus, support);
dev_info(&phydev->mdio.dev, "%s SFP module inserted\n", phy_modes(iface));
switch (iface) {
case PHY_INTERFACE_MODE_1000BASEX:
case PHY_INTERFACE_MODE_100BASEX:
/* Set PHY mode to PSGMII combo (1/4 copper + combo ports) mode */
ret = phy_modify(phydev,
QCA807X_CHIP_CONFIGURATION,
QCA807X_CHIP_CONFIGURATION_MODE_CFG_MASK,
QCA807X_CHIP_CONFIGURATION_MODE_PSGMII_FIBER);
/* Enable fiber mode autodection (1000Base-X or 100Base-FX) */
ret = phy_set_bits_mmd(phydev,
MDIO_MMD_AN,
QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION,
QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION_EN);
/* Select fiber page */
ret = phy_clear_bits(phydev,
QCA807X_CHIP_CONFIGURATION,
QCA807X_BT_BX_REG_SEL);
phydev->port = PORT_FIBRE;
break;
default:
dev_err(&phydev->mdio.dev, "Incompatible SFP module inserted\n");
return -EINVAL;
}
return ret;
}
static void qca807x_sfp_remove(void *upstream)
{
struct phy_device *phydev = upstream;
/* Select copper page */
phy_set_bits(phydev,
QCA807X_CHIP_CONFIGURATION,
QCA807X_BT_BX_REG_SEL);
phydev->port = PORT_TP;
}
static const struct sfp_upstream_ops qca807x_sfp_ops = {
.attach = phy_sfp_attach,
.detach = phy_sfp_detach,
.module_insert = qca807x_sfp_insert,
.module_remove = qca807x_sfp_remove,
};
static int qca807x_config(struct phy_device *phydev)
{
struct device_node *node = phydev->mdio.dev.of_node;
int control_dac, ret = 0;
u32 of_control_dac;
/* Check for Combo port */
if (phy_read(phydev, QCA807X_CHIP_CONFIGURATION)) {
int psgmii_serdes;
/* Prevent PSGMII going into hibernation via PSGMII self test */
psgmii_serdes = phy_read_mmd(phydev, MDIO_MMD_PCS, PSGMII_MMD3_SERDES_CONTROL);
psgmii_serdes &= ~BIT(1);
ret = phy_write_mmd(phydev, MDIO_MMD_PCS,
PSGMII_MMD3_SERDES_CONTROL,
psgmii_serdes);
}
if (!of_property_read_u32(node, "qcom,control-dac", &of_control_dac)) {
control_dac = phy_read_mmd(phydev, MDIO_MMD_AN,
QCA807X_MMD7_1000BASE_T_POWER_SAVE_PER_CABLE_LENGTH);
control_dac &= ~QCA807X_CONTROL_DAC_MASK;
control_dac |= FIELD_PREP(QCA807X_CONTROL_DAC_MASK, of_control_dac);
ret = phy_write_mmd(phydev, MDIO_MMD_AN,
QCA807X_MMD7_1000BASE_T_POWER_SAVE_PER_CABLE_LENGTH,
control_dac);
}
/* Optionally configure LED-s */
if (IS_ENABLED(CONFIG_GPIOLIB)) {
/* Check whether PHY-s pins are used as GPIO-s */
if (!of_property_read_bool(node, "gpio-controller"))
ret = qca807x_led_config(phydev);
} else {
ret = qca807x_led_config(phydev);
}
return ret;
}
static int qca807x_probe(struct phy_device *phydev)
{
struct device_node *node = phydev->mdio.dev.of_node;
int ret = 0;
if (IS_ENABLED(CONFIG_GPIOLIB)) {
/* Do not register a GPIO controller unless flagged for it */
if (of_property_read_bool(node, "gpio-controller"))
ret = qca807x_gpio(phydev);
}
/* Attach SFP bus on combo port*/
if (phy_read(phydev, QCA807X_CHIP_CONFIGURATION)) {
ret = phy_sfp_probe(phydev, &qca807x_sfp_ops);
linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported);
linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->advertising);
}
return ret;
}
static int qca807x_psgmii_config(struct phy_device *phydev)
{
struct device_node *node = phydev->mdio.dev.of_node;
int tx_amp, ret = 0;
u32 tx_driver_strength;
/* Workaround to enable AZ transmitting ability */
ret = phy_clear_bits_mmd(phydev,
MDIO_MMD_PMAPMD,
PSGMII_MODE_CTRL,
PSGMII_MODE_CTRL_AZ_WORKAROUND_MASK);
/* PSGMII/QSGMII TX amp set to DT defined value instead of default 600mV */
if (!of_property_read_u32(node, "qcom,tx-driver-strength", &tx_driver_strength)) {
tx_amp = phy_read(phydev, PSGMII_QSGMII_DRIVE_CONTROL_1);
tx_amp &= ~PSGMII_QSGMII_TX_DRIVER_MASK;
tx_amp |= FIELD_PREP(PSGMII_QSGMII_TX_DRIVER_MASK, tx_driver_strength);
ret = phy_write(phydev, PSGMII_QSGMII_DRIVE_CONTROL_1, tx_amp);
}
return ret;
}
static struct phy_driver qca807x_drivers[] = {
{
PHY_ID_MATCH_EXACT(PHY_ID_QCA8072),
.name = "Qualcomm QCA8072",
.flags = PHY_POLL_CABLE_TEST,
/* PHY_GBIT_FEATURES */
.probe = qca807x_probe,
.config_init = qca807x_config,
.read_status = qca807x_read_status,
.config_intr = qca807x_config_intr,
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0)
.ack_interrupt = qca807x_ack_intr,
#else
.handle_interrupt = qca807x_handle_interrupt,
#endif
.soft_reset = genphy_soft_reset,
.get_tunable = qca807x_get_tunable,
.set_tunable = qca807x_set_tunable,
.resume = genphy_resume,
.suspend = genphy_suspend,
.cable_test_start = qca807x_cable_test_start,
.cable_test_get_status = qca807x_cable_test_get_status,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_QCA8075),
.name = "Qualcomm QCA8075",
.flags = PHY_POLL_CABLE_TEST,
/* PHY_GBIT_FEATURES */
.probe = qca807x_probe,
.config_init = qca807x_config,
.read_status = qca807x_read_status,
.config_intr = qca807x_config_intr,
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0)
.ack_interrupt = qca807x_ack_intr,
#else
.handle_interrupt = qca807x_handle_interrupt,
#endif
.soft_reset = genphy_soft_reset,
.get_tunable = qca807x_get_tunable,
.set_tunable = qca807x_set_tunable,
.resume = genphy_resume,
.suspend = genphy_suspend,
.cable_test_start = qca807x_cable_test_start,
.cable_test_get_status = qca807x_cable_test_get_status,
},
{
PHY_ID_MATCH_EXACT(PHY_ID_QCA807X_PSGMII),
.name = "Qualcomm QCA807x PSGMII",
.probe = qca807x_psgmii_config,
},
};
module_phy_driver(qca807x_drivers);
static struct mdio_device_id __maybe_unused qca807x_tbl[] = {
{ PHY_ID_MATCH_EXACT(PHY_ID_QCA8072) },
{ PHY_ID_MATCH_EXACT(PHY_ID_QCA8075) },
{ PHY_ID_MATCH_MODEL(PHY_ID_QCA807X_PSGMII) },
{ }
};
MODULE_AUTHOR("Robert Marko");
MODULE_DESCRIPTION("Qualcomm QCA807x PHY driver");
MODULE_DEVICE_TABLE(mdio, qca807x_tbl);
MODULE_LICENSE("GPL");

View file

@ -0,0 +1,115 @@
From f2b87dc1028b710ec8ce25808b9d21f92b376184 Mon Sep 17 00:00:00 2001
From: Christian Lamparter <chunkeey@googlemail.com>
Date: Sun, 11 Mar 2018 14:41:31 +0100
Subject: [PATCH 2/2] clk: fix apss cpu overclocking
There's an interaction issue between the clk changes:"
clk: qcom: ipq4019: Add the apss cpu pll divider clock node
clk: qcom: ipq4019: remove fixed clocks and add pll clocks
" and the cpufreq-dt.
cpufreq-dt is now spamming the kernel-log with the following:
[ 1099.190658] cpu cpu0: dev_pm_opp_set_rate: failed to find current OPP
for freq 761142857 (-34)
This only happens on certain devices like the Compex WPJ428
and AVM FritzBox!4040. However, other devices like the Asus
RT-AC58U and Meraki MR33 work just fine.
The issue stem from the fact that all higher CPU-Clocks
are achieved by switching the clock-parent to the P_DDRPLLAPSS
(ddrpllapss). Which is set by Qualcomm's proprietary bootcode
as part of the DDR calibration.
For example, the FB4040 uses 256 MiB Nanya NT5CC128M16IP clocked
at round 533 MHz (ddrpllsdcc = 190285714 Hz).
whereas the 128 MiB Nanya NT5CC64M16GP-DI in the ASUS RT-AC58U is
clocked at a slightly higher 537 MHz ( ddrpllsdcc = 192000000 Hz).
This patch attempts to fix the issue by modifying
clk_cpu_div_round_rate(), clk_cpu_div_set_rate(), clk_cpu_div_recalc_rate()
to use a new qcom_find_freq_close() function, which returns the closest
matching frequency, instead of the next higher. This way, the SoC in
the FB4040 (with its max clock speed of 710.4 MHz) will no longer
try to overclock to 761 MHz.
Fixes: d83dcacea18 ("clk: qcom: ipq4019: Add the apss cpu pll divider clock node")
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
Signed-off-by: John Crispin <john@phrozen.org>
---
drivers/clk/qcom/gcc-ipq4019.c | 34 +++++++++++++++++++++++++++++++---
1 file changed, 31 insertions(+), 3 deletions(-)
--- a/drivers/clk/qcom/gcc-ipq4019.c
+++ b/drivers/clk/qcom/gcc-ipq4019.c
@@ -1243,6 +1243,29 @@ static const struct clk_fepll_vco gcc_fe
.reg = 0x2f020,
};
+
+const struct freq_tbl *qcom_find_freq_close(const struct freq_tbl *f,
+ unsigned long rate)
+{
+ const struct freq_tbl *last = NULL;
+
+ for ( ; f->freq; f++) {
+ if (rate == f->freq)
+ return f;
+
+ if (f->freq > rate) {
+ if (!last ||
+ (f->freq - rate) < (rate - last->freq))
+ return f;
+ else
+ return last;
+ }
+ last = f;
+ }
+
+ return last;
+}
+
/*
* Round rate function for APSS CPU PLL Clock divider.
* It looks up the frequency table and returns the next higher frequency
@@ -1255,7 +1278,7 @@ static long clk_cpu_div_round_rate(struc
struct clk_hw *p_hw;
const struct freq_tbl *f;
- f = qcom_find_freq(pll->freq_tbl, rate);
+ f = qcom_find_freq_close(pll->freq_tbl, rate);
if (!f)
return -EINVAL;
@@ -1277,7 +1300,7 @@ static int clk_cpu_div_set_rate(struct c
const struct freq_tbl *f;
u32 mask;
- f = qcom_find_freq(pll->freq_tbl, rate);
+ f = qcom_find_freq_close(pll->freq_tbl, rate);
if (!f)
return -EINVAL;
@@ -1304,6 +1327,7 @@ static unsigned long
clk_cpu_div_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
+ const struct freq_tbl *f;
struct clk_fepll *pll = to_clk_fepll(hw);
u32 cdiv, pre_div;
u64 rate;
@@ -1324,7 +1348,11 @@ clk_cpu_div_recalc_rate(struct clk_hw *h
rate = clk_fepll_vco_calc_rate(pll, parent_rate) * 2;
do_div(rate, pre_div);
- return rate;
+ f = qcom_find_freq_close(pll->freq_tbl, rate);
+ if (!f)
+ return rate;
+
+ return f->freq;
};
static const struct clk_ops clk_regmap_cpu_div_ops = {

View file

@ -0,0 +1,52 @@
From 480c1f7648fc586db12d6003c717c23667a4fcf0 Mon Sep 17 00:00:00 2001
From: Ram Chandra Jangir <rjangir@codeaurora.org>
Date: Tue, 28 Mar 2017 22:35:33 +0530
Subject: [PATCH] clk: qcom: ipq4019: add ess reset
Added the ESS reset in IPQ4019 GCC.
Signed-off-by: Ram Chandra Jangir <rjangir@codeaurora.org>
---
drivers/clk/qcom/gcc-ipq4019.c | 11 +++++++++++
include/dt-bindings/clock/qcom,gcc-ipq4019.h | 11 +++++++++++
2 files changed, 22 insertions(+)
--- a/drivers/clk/qcom/gcc-ipq4019.c
+++ b/drivers/clk/qcom/gcc-ipq4019.c
@@ -1735,6 +1735,17 @@ static const struct qcom_reset_map gcc_i
[GCC_TCSR_BCR] = {0x22000, 0},
[GCC_MPM_BCR] = {0x24000, 0},
[GCC_SPDM_BCR] = {0x25000, 0},
+ [ESS_MAC1_ARES] = {0x1200C, 0},
+ [ESS_MAC2_ARES] = {0x1200C, 1},
+ [ESS_MAC3_ARES] = {0x1200C, 2},
+ [ESS_MAC4_ARES] = {0x1200C, 3},
+ [ESS_MAC5_ARES] = {0x1200C, 4},
+ [ESS_PSGMII_ARES] = {0x1200C, 5},
+ [ESS_MAC1_CLK_DIS] = {0x1200C, 8},
+ [ESS_MAC2_CLK_DIS] = {0x1200C, 9},
+ [ESS_MAC3_CLK_DIS] = {0x1200C, 10},
+ [ESS_MAC4_CLK_DIS] = {0x1200C, 11},
+ [ESS_MAC5_CLK_DIS] = {0x1200C, 12},
};
static const struct regmap_config gcc_ipq4019_regmap_config = {
--- a/include/dt-bindings/clock/qcom,gcc-ipq4019.h
+++ b/include/dt-bindings/clock/qcom,gcc-ipq4019.h
@@ -165,5 +165,16 @@
#define GCC_QDSS_BCR 69
#define GCC_MPM_BCR 70
#define GCC_SPDM_BCR 71
+#define ESS_MAC1_ARES 72
+#define ESS_MAC2_ARES 73
+#define ESS_MAC3_ARES 74
+#define ESS_MAC4_ARES 75
+#define ESS_MAC5_ARES 76
+#define ESS_PSGMII_ARES 77
+#define ESS_MAC1_CLK_DIS 78
+#define ESS_MAC2_CLK_DIS 79
+#define ESS_MAC3_CLK_DIS 80
+#define ESS_MAC4_CLK_DIS 81
+#define ESS_MAC5_CLK_DIS 82
#endif

View file

@ -0,0 +1,48 @@
From 0843a61d6913bdac8889eb048ed89f7903059787 Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Fri, 30 Oct 2020 13:36:31 +0100
Subject: [PATCH] arm: compressed: add appended DTB section
This adds a appended_dtb section to the ARM decompressor
linker script.
This allows using the existing ARM zImage appended DTB support for
appending a DTB to the raw ELF kernel.
Its size is set to 1MB max to match the zImage appended DTB size limit.
To use it to pass the DTB to the kernel, objcopy is used:
objcopy --set-section-flags=.appended_dtb=alloc,contents \
--update-section=.appended_dtb=<target>.dtb vmlinux
This is based off the following patch:
https://github.com/openwrt/openwrt/commit/c063e27e02a9dcac0e7f5877fb154e58fa3e1a69
Signed-off-by: Robert Marko <robimarko@gmail.com>
---
arch/arm/boot/compressed/vmlinux.lds.S | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
--- a/arch/arm/boot/compressed/vmlinux.lds.S
+++ b/arch/arm/boot/compressed/vmlinux.lds.S
@@ -103,6 +103,13 @@ SECTIONS
_edata = .;
+ .appended_dtb : {
+ /* leave space for appended DTB */
+ . += 0x100000;
+ }
+
+ _edata_dtb = .;
+
/*
* The image_end section appears after any additional loadable sections
* that the linker may decide to insert in the binary image. Having
@@ -140,4 +147,4 @@ SECTIONS
ARM_ASSERTS
}
-ASSERT(_edata_real == _edata, "error: zImage file size is incorrect");
+ASSERT(_edata_real == _edata_dtb, "error: zImage file size is incorrect");

View file

@ -0,0 +1,66 @@
From 11d6a6128a5a07c429941afc202b6e62a19771be Mon Sep 17 00:00:00 2001
From: John Thomson <git@johnthomson.fastmail.com.au>
Date: Fri, 23 Oct 2020 19:42:36 +1000
Subject: [PATCH 2/2] arm: compressed: set ipq40xx watchdog to allow boot
For IPQ40XX systems where the SoC watchdog is activated before linux,
the watchdog timer may be too small for linux to finish uncompress,
boot, and watchdog management start.
If the watchdog is enabled, set the timeout for it to 30 seconds.
The functionality and offsets were copied from:
drivers/watchdog/qcom-wdt.c qcom_wdt_set_timeout & qcom_wdt_start
The watchdog memory address was taken from:
arch/arm/boot/dts/qcom-ipq4019.dtsi
This was required on Mikrotik IPQ40XX consumer hardware using Mikrotik's
RouterBoot bootloader.
Signed-off-by: John Thomson <git@johnthomson.fastmail.com.au>
---
arch/arm/boot/compressed/head.S | 35 +++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -624,6 +624,41 @@ not_relocated: mov r0, #0
bic r4, r4, #1
blne cache_on
+/* Set the Qualcom IPQ40xx watchdog timeout to 30 seconds
+ * if it is enabled, so that there is time for kernel
+ * to decompress, boot, and take over the watchdog.
+ * data and functionality from drivers/watchdog/qcom-wdt.c
+ * address from arch/arm/boot/dts/qcom-ipq4019.dtsi
+ */
+#ifdef CONFIG_ARCH_IPQ40XX
+watchdog_set:
+ /* offsets:
+ * 0x04 reset (=1 resets countdown)
+ * 0x08 enable (=0 disables)
+ * 0x0c status (=1 when SoC was reset by watchdog)
+ * 0x10 bark (=timeout warning in ticks)
+ * 0x14 bite (=timeout reset in ticks)
+ * clock rate is 1<<15 hertz
+ */
+ .equ watchdog, 0x0b017000 @Store watchdog base address
+ movw r0, #:lower16:watchdog
+ movt r0, #:upper16:watchdog
+ ldr r1, [r0, #0x08] @Get enabled?
+ cmp r1, #1 @If not enabled, do not change
+ bne watchdog_finished
+ mov r1, #0
+ str r1, [r0, #0x08] @Disable the watchdog
+ mov r1, #1
+ str r1, [r0, #0x04] @Pet the watchdog
+ mov r1, #30 @30 seconds timeout
+ lsl r1, r1, #15 @converted to ticks
+ str r1, [r0, #0x10] @Set the bark timeout
+ str r1, [r0, #0x14] @Set the bite timeout
+ mov r1, #1
+ str r1, [r0, #0x08] @Enable the watchdog
+watchdog_finished:
+#endif /* CONFIG_ARCH_IPQ40XX */
+
/*
* The C runtime environment should now be setup sufficiently.
* Set up some pointers, and start decompressing.

View file

@ -0,0 +1,24 @@
From f63ea127643a605da97090ce585fdd7c2d17fa42 Mon Sep 17 00:00:00 2001
From: Robert Marko <robert.marko@sartura.hr>
Date: Mon, 14 Dec 2020 13:35:35 +0100
Subject: [PATCH] mmc: sdhci-msm: use sdhci_set_clock
When using sdhci_msm_set_clock clock setting will fail, so lets
use the generic sdhci_set_clock.
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
---
drivers/mmc/host/sdhci-msm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2447,7 +2447,7 @@ MODULE_DEVICE_TABLE(of, sdhci_msm_dt_mat
static const struct sdhci_ops sdhci_msm_ops = {
.reset = sdhci_msm_reset,
- .set_clock = sdhci_msm_set_clock,
+ .set_clock = sdhci_set_clock,
.get_min_clock = sdhci_msm_get_min_clock,
.get_max_clock = sdhci_msm_get_max_clock,
.set_bus_width = sdhci_set_bus_width,

View file

@ -0,0 +1,47 @@
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -404,6 +404,20 @@ static int __qcom_scm_set_dload_mode(str
return qcom_scm_call_atomic(__scm->dev, &desc, NULL);
}
+static int __qcom_scm_disable_sdi(struct device *dev)
+{
+ struct qcom_scm_desc desc = {
+ .svc = QCOM_SCM_SVC_BOOT,
+ .cmd = QCOM_SCM_BOOT_CONFIG_SDI,
+ .arginfo = QCOM_SCM_ARGS(2),
+ .args[0] = 1 /* 1: disable watchdog debug */,
+ .args[1] = 0 /* 0: disable SDI */,
+ .owner = ARM_SMCCC_OWNER_SIP,
+ };
+
+ return qcom_scm_call(__scm->dev, &desc, NULL);
+}
+
static void qcom_scm_set_download_mode(bool enable)
{
bool avail;
@@ -1314,6 +1328,13 @@ static int qcom_scm_probe(struct platfor
if (download_mode)
qcom_scm_set_download_mode(true);
+ /*
+ * Factory firmware leaves SDI (a debug interface), which prevents
+ * clean reboot.
+ */
+ if (of_machine_is_compatible("google,wifi"))
+ __qcom_scm_disable_sdi(__scm->dev);
+
return 0;
}
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -77,6 +77,7 @@ extern int scm_legacy_call(struct device
#define QCOM_SCM_SVC_BOOT 0x01
#define QCOM_SCM_BOOT_SET_ADDR 0x01
#define QCOM_SCM_BOOT_TERMINATE_PC 0x02
+#define QCOM_SCM_BOOT_CONFIG_SDI 0x09
#define QCOM_SCM_BOOT_SET_DLOAD_MODE 0x10
#define QCOM_SCM_BOOT_SET_REMOTE_STATE 0x0a
#define QCOM_SCM_FLUSH_FLAG_MASK 0x3

View file

@ -0,0 +1,121 @@
--- a/drivers/firmware/qcom_scm-legacy.c
+++ b/drivers/firmware/qcom_scm-legacy.c
@@ -13,6 +13,9 @@
#include <linux/arm-smccc.h>
#include <linux/dma-mapping.h>
+#include <asm/cacheflush.h>
+#include <asm/outercache.h>
+
#include "qcom_scm.h"
static DEFINE_MUTEX(qcom_scm_lock);
@@ -117,6 +120,25 @@ static void __scm_legacy_do(const struct
} while (res->a0 == QCOM_SCM_INTERRUPTED);
}
+static void qcom_scm_inv_range(unsigned long start, unsigned long end)
+{
+ u32 cacheline_size, ctr;
+
+ asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr));
+ cacheline_size = 4 << ((ctr >> 16) & 0xf);
+
+ start = round_down(start, cacheline_size);
+ end = round_up(end, cacheline_size);
+ outer_inv_range(start, end);
+ while (start < end) {
+ asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
+ : "memory");
+ start += cacheline_size;
+ }
+ dsb();
+ isb();
+}
+
/**
* scm_legacy_call() - Sends a command to the SCM and waits for the command to
* finish processing.
@@ -160,10 +182,16 @@ int scm_legacy_call(struct device *dev,
rsp = scm_legacy_command_to_response(cmd);
- cmd_phys = dma_map_single(dev, cmd, alloc_len, DMA_TO_DEVICE);
- if (dma_mapping_error(dev, cmd_phys)) {
- kfree(cmd);
- return -ENOMEM;
+ if (dev) {
+ cmd_phys = dma_map_single(dev, cmd, alloc_len, DMA_TO_DEVICE);
+ if (dma_mapping_error(dev, cmd_phys)) {
+ kfree(cmd);
+ return -ENOMEM;
+ }
+ } else {
+ cmd_phys = virt_to_phys(cmd);
+ __cpuc_flush_dcache_area(cmd, alloc_len);
+ outer_flush_range(cmd_phys, cmd_phys + alloc_len);
}
smc.args[0] = 1;
@@ -179,13 +207,26 @@ int scm_legacy_call(struct device *dev,
goto out;
do {
- dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len,
- sizeof(*rsp), DMA_FROM_DEVICE);
+ if (dev) {
+ dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) +
+ cmd_len, sizeof(*rsp),
+ DMA_FROM_DEVICE);
+ } else {
+ unsigned long start = (uintptr_t)cmd + sizeof(*cmd) +
+ cmd_len;
+ qcom_scm_inv_range(start, start + sizeof(*rsp));
+ }
} while (!rsp->is_complete);
- dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len +
- le32_to_cpu(rsp->buf_offset),
- resp_len, DMA_FROM_DEVICE);
+ if (dev) {
+ dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len +
+ le32_to_cpu(rsp->buf_offset),
+ resp_len, DMA_FROM_DEVICE);
+ } else {
+ unsigned long start = (uintptr_t)cmd + sizeof(*cmd) + cmd_len +
+ le32_to_cpu(rsp->buf_offset);
+ qcom_scm_inv_range(start, start + resp_len);
+ }
if (res) {
res_buf = scm_legacy_get_response_buffer(rsp);
@@ -193,7 +234,8 @@ int scm_legacy_call(struct device *dev,
res->result[i] = le32_to_cpu(res_buf[i]);
}
out:
- dma_unmap_single(dev, cmd_phys, alloc_len, DMA_TO_DEVICE);
+ if (dev)
+ dma_unmap_single(dev, cmd_phys, alloc_len, DMA_TO_DEVICE);
kfree(cmd);
return ret;
}
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -344,6 +344,17 @@ int qcom_scm_set_cold_boot_addr(void *en
desc.args[0] = flags;
desc.args[1] = virt_to_phys(entry);
+ /*
+ * Factory firmware doesn't support the atomic variant. Non-atomic SCMs
+ * require ugly DMA invalidation support that was dropped upstream a
+ * while ago. For more info, see:
+ *
+ * [RFC] qcom_scm: IPQ4019 firmware does not support atomic API?
+ * https://lore.kernel.org/linux-arm-msm/20200913201608.GA3162100@bDebian/
+ */
+ if (of_machine_is_compatible("google,wifi"))
+ return qcom_scm_call(__scm ? __scm->dev : NULL, &desc, NULL);
+
return qcom_scm_call_atomic(__scm ? __scm->dev : NULL, &desc, NULL);
}
EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr);

View file

@ -0,0 +1,29 @@
From 35ca7e3e6ccd120d694a3425f37fc6374ad2e11e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andreas=20B=C3=B6hler?= <dev@aboehler.at>
Date: Wed, 20 Apr 2022 12:08:38 +0200
Subject: [PATCH] mtd: rawnand: add support for Toshiba TC58NVG0S3HTA00
NAND flash
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The Toshiba TC58NVG0S3HTA00 is detected with 64 byte OOB while the flash
has 128 bytes OOB. This adds a static NAND ID entry to correct this.
Tested on FRITZ!Box 7530 flashed with OpenWrt.
Signed-off-by: Andreas Böhler <dev@aboehler.at>
(changed id_len to 8, added comment about possible counterfeits)
---
--- a/drivers/mtd/nand/raw/nand_ids.c
+++ b/drivers/mtd/nand/raw/nand_ids.c
@@ -29,6 +29,9 @@ struct nand_flash_dev nand_flash_ids[] =
{"TC58NVG0S3E 1G 3.3V 8-bit",
{ .id = {0x98, 0xd1, 0x90, 0x15, 0x76, 0x14, 0x01, 0x00} },
SZ_2K, SZ_128, SZ_128K, 0, 8, 64, NAND_ECC_INFO(1, SZ_512), },
+ {"TC58NVG0S3HTA00 1G 3.3V 8-bit", /* possibly counterfeit chip - see commit */
+ { .id = {0x98, 0xf1, 0x80, 0x15} }, /* should be more bytes */
+ SZ_2K, SZ_128, SZ_128K, 0, 8, 128, NAND_ECC_INFO(8, SZ_512), },
{"TC58NVG2S0F 4G 3.3V 8-bit",
{ .id = {0x98, 0xdc, 0x90, 0x26, 0x76, 0x15, 0x01, 0x08} },
SZ_4K, SZ_512, SZ_256K, 0, 8, 224, NAND_ECC_INFO(4, SZ_512) },

View file

@ -0,0 +1,43 @@
From da75807ac41175e9db8c95f7a172b4133763b744 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <j4g8y7@gmail.com>
Date: Mon, 11 Jan 2021 17:49:36 +0100
Subject: [PATCH] skbuff: add DSA specific data to struct skb_shared_info
All of the already existing DSA tagging protocol drivers
are storing the tagging data directly into the skb. In most
cases that is the only way to send the required information
to the underlying ethernet switch.
However on certain platforms (like the Qualcomm IPQ40xx
SoCs) the built-in ethernet switch is connected directly
to an ethernet MAC, and the tagging information must be
sent out-of-band which is done directly via the hardware
TX descriptors of the ethernet MAC.
In such cases, putting the information into the skb causes
unneccesary overhead, because the ethernet driver must
remove that before sending the ethernet frame towards to
the hardware.
This change adds two new DSA specific fields to struct
skb_shared_info which makes it possible to send the
tagging information via skb->shinfo. With this approach,
the twofold modifications of the skb data can be avoided.
Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
---
include/linux/skbuff.h | 3 +++
1 file changed, 3 insertions(+)
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -563,6 +563,9 @@ struct skb_shared_info {
unsigned int gso_type;
u32 tskey;
+ unsigned int dsa_tag_proto;
+ unsigned char dsa_tag_data[8];
+
/*
* Warning : all fields before dataref are cleared in __alloc_skb()
*/

View file

@ -0,0 +1,187 @@
From 29a0c2fae991cab142575c92276c0afdeb260ebe Mon Sep 17 00:00:00 2001
From: Gabor Juhos <j4g8y7@gmail.com>
Date: Thu, 28 Oct 2021 21:44:52 +0200
Subject: [PATCH] net: dsa: tag_ipq4019: add shinfo based tagging driver for
IPQ40xx
This change adds a tagging protocol driver for the built-in
ethernet switch of the Qualcomm Atheros IPQ4019 SoCs.
In comparison to the existing tagging protocols this hardware
requires a slightly different approach because the switch does
not use in-band tags.
On the receive path, the source port information is embedded
into the RX descriptors of the ethernet MAC hardware. Similarly,
the destination port mask must be sent via the TX descriptors
of the ethernet MAC when a packet is sent towards the switch.
In order to support this special requirements, this patch
adds a new tagging protocol driver.
The driver extracts the source port information directly
from the 'receive return descriptor' of the ethernet MAC.
It is possible because that descriptor is part of the skb
received from the ethernet driver.
Unfortunatley, it is not possible to put the destination
port information directly to the TX descriptors, because
those are handled internally by the driver of the ethernet
hardware.
To overcome this limitation, this tagging driver uses the
DSA specific fields in skb->shinfo to send the destination
port information to the ethernet driver.
A similar tagging driver is exist but that uses skb
extensions which causes unnecessary overhead.
Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
---
include/linux/dsa/ipq4019.h | 11 ++++++
include/net/dsa.h | 2 +
net/dsa/Kconfig | 6 +++
net/dsa/Makefile | 1 +
net/dsa/tag_ipq4019.c | 79 +++++++++++++++++++++++++++++++++++++
5 files changed, 99 insertions(+)
create mode 100644 include/linux/dsa/ipq4019.h
create mode 100644 net/dsa/tag_ipq4019.c
--- /dev/null
+++ b/include/linux/dsa/ipq4019.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef DSA_IPQ40XX_H
+#define DSA_IPQ40XX_H
+
+struct ipq40xx_dsa_tag_data {
+ u8 from_cpu;
+ u8 dp;
+};
+
+#endif /* DSA_IPQ40XX_H */
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -51,6 +51,7 @@ struct phylink_link_state;
#define DSA_TAG_PROTO_RTL8_4T_VALUE 24
#define DSA_TAG_PROTO_RZN1_A5PSW_VALUE 25
#define DSA_TAG_PROTO_LAN937X_VALUE 27
+#define DSA_TAG_PROTO_IPQ4019_VALUE 28
enum dsa_tag_protocol {
DSA_TAG_PROTO_NONE = DSA_TAG_PROTO_NONE_VALUE,
@@ -77,6 +78,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_RTL8_4T = DSA_TAG_PROTO_RTL8_4T_VALUE,
DSA_TAG_PROTO_RZN1_A5PSW = DSA_TAG_PROTO_RZN1_A5PSW_VALUE,
DSA_TAG_PROTO_LAN937X = DSA_TAG_PROTO_LAN937X_VALUE,
+ DSA_TAG_PROTO_IPQ4019 = DSA_TAG_PROTO_IPQ4019_VALUE,
};
struct dsa_switch;
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -57,6 +57,12 @@ config NET_DSA_TAG_HELLCREEK
Say Y or M if you want to enable support for tagging frames
for the Hirschmann Hellcreek TSN switches.
+config NET_DSA_TAG_IPQ4019
+ tristate "Tag driver for Qualcomm Atheros IPQ4019 SoC built-in switch"
+ help
+ Say Y or M if you want to enable support for tagging frames for
+ the built-in switch of the Qualcomm Atheros IPQ4019 SoC-s.
+
config NET_DSA_TAG_GSWIP
tristate "Tag driver for Lantiq / Intel GSWIP switches"
help
--- a/net/dsa/Makefile
+++ b/net/dsa/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_NET_DSA_TAG_AR9331) += tag_
obj-$(CONFIG_NET_DSA_TAG_BRCM_COMMON) += tag_brcm.o
obj-$(CONFIG_NET_DSA_TAG_DSA_COMMON) += tag_dsa.o
obj-$(CONFIG_NET_DSA_TAG_GSWIP) += tag_gswip.o
+obj-$(CONFIG_NET_DSA_TAG_IPQ4019) += tag_ipq4019.o
obj-$(CONFIG_NET_DSA_TAG_HELLCREEK) += tag_hellcreek.o
obj-$(CONFIG_NET_DSA_TAG_KSZ) += tag_ksz.o
obj-$(CONFIG_NET_DSA_TAG_RTL4_A) += tag_rtl4_a.o
--- /dev/null
+++ b/net/dsa/tag_ipq4019.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/* Copyright (c) 2021, Gabor Juhos <j4g8y7@gmail.com> */
+
+#include <linux/bitfield.h>
+#include <linux/dsa/ipq4019.h>
+
+#include "dsa_priv.h"
+
+/* Receive Return Descriptor */
+struct edma_rrd {
+ u16 rrd0;
+ u16 rrd1;
+ u16 rrd2;
+ u16 rrd3;
+ u16 rrd4;
+ u16 rrd5;
+ u16 rrd6;
+ u16 rrd7;
+} __packed;
+
+#define EDMA_RRD_SIZE sizeof(struct edma_rrd)
+
+#define EDMA_RRD1_PORT_ID_MASK GENMASK(14, 12)
+
+static struct sk_buff *ipq4019_sh_tag_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct dsa_port *dp = dsa_slave_to_port(dev);
+ struct ipq40xx_dsa_tag_data *tag_data;
+
+ BUILD_BUG_ON(sizeof_field(struct skb_shared_info, dsa_tag_data) <
+ sizeof(struct ipq40xx_dsa_tag_data));
+
+ skb_shinfo(skb)->dsa_tag_proto = DSA_TAG_PROTO_IPQ4019;
+ tag_data = (struct ipq40xx_dsa_tag_data *)skb_shinfo(skb)->dsa_tag_data;
+
+ tag_data->from_cpu = 1;
+ /* set the destination port information */
+ tag_data->dp = BIT(dp->index);
+
+ return skb;
+}
+
+static struct sk_buff *ipq4019_sh_tag_rcv(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct edma_rrd *rrd;
+ int offset;
+ int port;
+
+ offset = EDMA_RRD_SIZE + ETH_HLEN;
+ if (unlikely(skb_headroom(skb) < offset))
+ return NULL;
+
+ rrd = (struct edma_rrd *)(skb->data - offset);
+ port = FIELD_GET(EDMA_RRD1_PORT_ID_MASK, rrd->rrd1);
+
+ skb->dev = dsa_master_find_slave(dev, 0, port);
+ if (!skb->dev)
+ return NULL;
+
+ return skb;
+}
+
+const struct dsa_device_ops ipq4019_sh_tag_dsa_ops = {
+ .name = "ipq4019-sh",
+ .proto = DSA_TAG_PROTO_IPQ4019,
+ .xmit = ipq4019_sh_tag_xmit,
+ .rcv = ipq4019_sh_tag_rcv,
+};
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("DSA tag driver for the IPQ4019 SoC built-in ethernet switch");
+MODULE_AUTHOR("Gabor Juhos <j4g8y7@gmail.com>");
+MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_IPQ4019);
+
+module_dsa_tag_driver(ipq4019_sh_tag_dsa_ops);

View file

@ -0,0 +1,81 @@
From 44327d7098d4f32c24ec8c528e5aff6e030956bc Mon Sep 17 00:00:00 2001
From: Robert Marko <robert.marko@sartura.hr>
Date: Wed, 20 Oct 2021 13:21:45 +0200
Subject: [PATCH] arm: dts: ipq4019: add ethernet controller DT node
Since IPQ40xx SoC built-in ethernet controller now has a driver,
add its DT node so it can be used.
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
---
arch/arm/boot/dts/qcom-ipq4019.dtsi | 48 +++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
@@ -38,6 +38,7 @@
spi1 = &blsp1_spi2;
i2c0 = &blsp1_i2c3;
i2c1 = &blsp1_i2c4;
+ ethernet0 = &gmac;
};
cpus {
@@ -589,6 +590,57 @@
status = "disabled";
};
+ gmac: ethernet@c080000 {
+ compatible = "qcom,ipq4019-ess-edma";
+ reg = <0xc080000 0x8000>;
+ resets = <&gcc ESS_RESET>;
+ reset-names = "ess_rst";
+ clocks = <&gcc GCC_ESS_CLK>;
+ clock-names = "ess_clk";
+ interrupts = <GIC_SPI 65 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 66 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 67 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 68 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 69 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 70 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 71 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 72 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 73 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 74 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 76 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 77 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 78 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 79 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 80 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 240 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 241 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 242 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 243 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 244 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 245 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 246 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 247 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 248 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 249 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 250 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 251 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 252 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 253 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 254 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 255 IRQ_TYPE_EDGE_RISING>;
+
+ status = "disabled";
+
+ phy-mode = "internal";
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ pause;
+ asym-pause;
+ };
+ };
+
mdio: mdio@90000 {
#address-cells = <1>;
#size-cells = <0>;

View file

@ -0,0 +1,61 @@
From 3e1825e00dafb68eec25df389b63f3ab3d905b59 Mon Sep 17 00:00:00 2001
From: Gabor Juhos <j4g8y7@gmail.com>
Date: Fri, 25 Dec 2020 08:02:47 +0100
Subject: [PATCH] net: phy: define PSGMII PHY interface mode
The PSGMII interface is similar to QSGMII. The main difference
is that the PSGMII interface combines five SGMII lines into a
single link while in QSGMII only four lines are combined.
Similarly to the QSGMII, this interface mode might also needs
special handling within the MAC driver.
Add definitions for the PHY layer to allow to express this type
of connection between the MAC and PHY.
Signed-off-by: Gabor Juhos <j4g8y7@gmail.com>
---
Documentation/devicetree/bindings/net/ethernet-controller.yaml | 1 +
drivers/net/phy/phylink.c | 1 +
include/linux/phy.h | 3 +++
3 files changed, 5 insertions(+)
--- a/Documentation/devicetree/bindings/net/ethernet-controller.yaml
+++ b/Documentation/devicetree/bindings/net/ethernet-controller.yaml
@@ -64,6 +64,7 @@ properties:
- mii
- gmii
- sgmii
+ - psgmii
- qsgmii
- tbi
- rev-mii
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -629,6 +629,7 @@ static int phylink_parse_mode(struct phy
switch (pl->link_config.interface) {
case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_PSGMII:
case PHY_INTERFACE_MODE_QSGMII:
phylink_set(pl->supported, 10baseT_Half);
phylink_set(pl->supported, 10baseT_Full);
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -138,6 +138,7 @@ typedef enum {
PHY_INTERFACE_MODE_XGMII,
PHY_INTERFACE_MODE_XLGMII,
PHY_INTERFACE_MODE_MOCA,
+ PHY_INTERFACE_MODE_PSGMII,
PHY_INTERFACE_MODE_QSGMII,
PHY_INTERFACE_MODE_TRGMII,
PHY_INTERFACE_MODE_100BASEX,
@@ -243,6 +244,8 @@ static inline const char *phy_modes(phy_
return "xlgmii";
case PHY_INTERFACE_MODE_MOCA:
return "moca";
+ case PHY_INTERFACE_MODE_PSGMII:
+ return "psgmii";
case PHY_INTERFACE_MODE_QSGMII:
return "qsgmii";
case PHY_INTERFACE_MODE_TRGMII:

View file

@ -0,0 +1,98 @@
From ebb62523990a27b3a25e422fa575619f7f725a20 Mon Sep 17 00:00:00 2001
From: Robert Marko <robert.marko@sartura.hr>
Date: Mon, 1 Nov 2021 18:15:04 +0100
Subject: [PATCH] arm: dts: ipq4019: add switch node
Since the built-in IPQ40xx switch now has a driver, add the required node
for it to work.
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
---
arch/arm/boot/dts/qcom-ipq4019.dtsi | 78 +++++++++++++++++++++++++++++
1 file changed, 78 insertions(+)
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
@@ -590,6 +590,82 @@
status = "disabled";
};
+ switch: switch@c000000 {
+ compatible = "qca,ipq4019-qca8337n";
+ reg = <0xc000000 0x80000>, <0x98000 0x800>;
+ reg-names = "base", "psgmii_phy";
+ resets = <&gcc ESS_PSGMII_ARES>;
+ reset-names = "psgmii_rst";
+ mdio = <&mdio>;
+ psgmii-ethphy = <&psgmiiphy>;
+
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 { /* MAC0 */
+ reg = <0>;
+ label = "cpu";
+ ethernet = <&gmac>;
+ phy-mode = "internal";
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ pause;
+ asym-pause;
+ };
+ };
+
+ swport1: port@1 { /* MAC1 */
+ reg = <1>;
+ label = "lan1";
+ phy-handle = <&ethphy0>;
+ phy-mode = "psgmii";
+
+ status = "disabled";
+ };
+
+ swport2: port@2 { /* MAC2 */
+ reg = <2>;
+ label = "lan2";
+ phy-handle = <&ethphy1>;
+ phy-mode = "psgmii";
+
+ status = "disabled";
+ };
+
+ swport3: port@3 { /* MAC3 */
+ reg = <3>;
+ label = "lan3";
+ phy-handle = <&ethphy2>;
+ phy-mode = "psgmii";
+
+ status = "disabled";
+ };
+
+ swport4: port@4 { /* MAC4 */
+ reg = <4>;
+ label = "lan4";
+ phy-handle = <&ethphy3>;
+ phy-mode = "psgmii";
+
+ status = "disabled";
+ };
+
+ swport5: port@5 { /* MAC5 */
+ reg = <5>;
+ label = "wan";
+ phy-handle = <&ethphy4>;
+ phy-mode = "psgmii";
+
+ status = "disabled";
+ };
+ };
+ };
+
gmac: ethernet@c080000 {
compatible = "qcom,ipq4019-ess-edma";
reg = <0xc080000 0x8000>;

View file

@ -0,0 +1,61 @@
From c66863c1ba8995b61e6d727d78a241c734f5bb57 Mon Sep 17 00:00:00 2001
From: Robert Marko <robert.marko@sartura.hr>
Date: Thu, 1 Oct 2020 15:05:35 +0200
Subject: [PATCH] dt-bindings: net: add QCA807x PHY
Add DT bindings for Qualcomm QCA807x PHY series.
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
---
include/dt-bindings/net/qcom-qca807x.h | 45 ++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
create mode 100644 include/dt-bindings/net/qcom-qca807x.h
--- /dev/null
+++ b/include/dt-bindings/net/qcom-qca807x.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Device Tree constants for the Qualcomm QCA807X PHYs
+ */
+
+#ifndef _DT_BINDINGS_QCOM_QCA807X_H
+#define _DT_BINDINGS_QCOM_QCA807X_H
+
+#define PSGMII_QSGMII_TX_DRIVER_140MV 0
+#define PSGMII_QSGMII_TX_DRIVER_160MV 1
+#define PSGMII_QSGMII_TX_DRIVER_180MV 2
+#define PSGMII_QSGMII_TX_DRIVER_200MV 3
+#define PSGMII_QSGMII_TX_DRIVER_220MV 4
+#define PSGMII_QSGMII_TX_DRIVER_240MV 5
+#define PSGMII_QSGMII_TX_DRIVER_260MV 6
+#define PSGMII_QSGMII_TX_DRIVER_280MV 7
+#define PSGMII_QSGMII_TX_DRIVER_300MV 8
+#define PSGMII_QSGMII_TX_DRIVER_320MV 9
+#define PSGMII_QSGMII_TX_DRIVER_400MV 10
+#define PSGMII_QSGMII_TX_DRIVER_500MV 11
+/* Default value */
+#define PSGMII_QSGMII_TX_DRIVER_600MV 12
+
+/* Full amplitude, full bias current */
+#define QCA807X_CONTROL_DAC_FULL_VOLT_BIAS 0
+/* Amplitude follow DSP (amplitude is adjusted based on cable length), half bias current */
+#define QCA807X_CONTROL_DAC_DSP_VOLT_HALF_BIAS 1
+/* Full amplitude, bias current follow DSP (bias current is adjusted based on cable length) */
+#define QCA807X_CONTROL_DAC_FULL_VOLT_DSP_BIAS 2
+/* Both amplitude and bias current follow DSP */
+#define QCA807X_CONTROL_DAC_DSP_VOLT_BIAS 3
+/* Full amplitude, half bias current */
+#define QCA807X_CONTROL_DAC_FULL_VOLT_HALF_BIAS 4
+/* Amplitude follow DSP setting; 1/4 bias current when cable<10m,
+ * otherwise half bias current
+ */
+#define QCA807X_CONTROL_DAC_DSP_VOLT_QUARTER_BIAS 5
+/* Full amplitude; same bias current setting with “010” and “011”,
+ * but half more bias is reduced when cable <10m
+ */
+#define QCA807X_CONTROL_DAC_FULL_VOLT_HALF_BIAS_SHORT 6
+/* Amplitude follow DSP; same bias current setting with “110”, default value */
+#define QCA807X_CONTROL_DAC_DSP_VOLT_HALF_BIAS_SHORT 7
+
+#endif

View file

@ -0,0 +1,50 @@
From f825cdc8bfde7616a14e2163f16303a8973031d2 Mon Sep 17 00:00:00 2001
From: Robert Marko <robert.marko@sartura.hr>
Date: Wed, 7 Oct 2020 17:38:48 +0200
Subject: [PATCH] net: phy: Add Qualcom QCA807x driver
This adds driver for the Qualcomm QCA8072 and QCA8075 PHY-s.
They are 2 or 5 port IEEE 802.3 clause 22 compliant 10BASE-Te, 100BASE-TX and 1000BASE-T PHY-s.
They feature 2 SerDes, one for PSGMII or QSGMII connection with MAC, while second one is SGMII for connection to MAC or fiber.
Both models have a combo port that supports 1000BASE-X and 100BASE-FX fiber.
Each PHY inside of QCA807x series has 4 digitally controlled output only pins that natively drive LED-s.
But some vendors used these to driver generic LED-s controlled by userspace,
so lets enable registering each PHY as GPIO controller and add driver for it.
These are commonly used in Qualcomm IPQ40xx, IPQ60xx and IPQ807x boards.
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
---
drivers/net/phy/Kconfig | 6 ++++++
drivers/net/phy/Makefile | 1 +
2 files changed, 7 insertions(+)
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -346,6 +346,12 @@ config AT803X_PHY
Currently supports the AR8030, AR8031, AR8033, AR8035 and internal
QCA8337(Internal qca8k PHY) model
+config QCA807X_PHY
+ tristate "Qualcomm QCA807X PHYs"
+ depends on OF_MDIO
+ help
+ Currently supports the QCA8072 and QCA8075 models.
+
config QSEMI_PHY
tristate "Quality Semiconductor PHYs"
help
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -92,6 +92,7 @@ obj-$(CONFIG_NATIONAL_PHY) += national.o
obj-$(CONFIG_NXP_C45_TJA11XX_PHY) += nxp-c45-tja11xx.o
obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o
obj-$(CONFIG_QSEMI_PHY) += qsemi.o
+obj-$(CONFIG_QCA807X_PHY) += qca807x.o
obj-$(CONFIG_REALTEK_PHY) += realtek.o
obj-$(CONFIG_RENESAS_PHY) += uPD60620.o
obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o

View file

@ -0,0 +1,61 @@
From e0fa88eaa3c176b71e563da68949ac2ab45aaa61 Mon Sep 17 00:00:00 2001
From: Robert Marko <robert.marko@sartura.hr>
Date: Fri, 2 Oct 2020 10:43:26 +0200
Subject: [PATCH] arm: dts: ipq4019: QCA807x properties
This adds necessary DT properties for QCA807x PHY-s to IPQ4019 DTSI.
Signed-off-by: Robert Marko <robert.marko@sartura.hr>
---
arch/arm/boot/dts/qcom-ipq4019.dtsi | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
@@ -8,6 +8,7 @@
#include <dt-bindings/clock/qcom,gcc-ipq4019.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/net/qcom-qca807x.h>
/ {
#address-cells = <1>;
@@ -726,22 +727,38 @@
ethphy0: ethernet-phy@0 {
reg = <0>;
+
+ qcom,control-dac = <QCA807X_CONTROL_DAC_DSP_VOLT_QUARTER_BIAS>;
};
ethphy1: ethernet-phy@1 {
reg = <1>;
+
+ qcom,control-dac = <QCA807X_CONTROL_DAC_DSP_VOLT_QUARTER_BIAS>;
};
ethphy2: ethernet-phy@2 {
reg = <2>;
+
+ qcom,control-dac = <QCA807X_CONTROL_DAC_DSP_VOLT_QUARTER_BIAS>;
};
ethphy3: ethernet-phy@3 {
reg = <3>;
+
+ qcom,control-dac = <QCA807X_CONTROL_DAC_DSP_VOLT_QUARTER_BIAS>;
};
ethphy4: ethernet-phy@4 {
reg = <4>;
+
+ qcom,control-dac = <QCA807X_CONTROL_DAC_DSP_VOLT_QUARTER_BIAS>;
+ };
+
+ psgmiiphy: psgmii-phy@5 {
+ reg = <5>;
+
+ qcom,tx-driver-strength = <PSGMII_QSGMII_TX_DRIVER_300MV>;
};
};

View file

@ -0,0 +1,180 @@
From: Christian Lamparter <chunkeey@googlemail.com>
Subject: SoC: add qualcomm syscon
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_QCOM_SMP2P) += smp2p.o
obj-$(CONFIG_QCOM_SMSM) += smsm.o
obj-$(CONFIG_QCOM_SOCINFO) += socinfo.o
obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
+obj-$(CONFIG_QCOM_TCSR) += qcom_tcsr.o
obj-$(CONFIG_QCOM_APR) += apr.o
obj-$(CONFIG_QCOM_LLCC) += llcc-qcom.o
obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -192,6 +192,13 @@ config QCOM_SOCINFO
Say yes here to support the Qualcomm socinfo driver, providing
information about the SoC to user space.
+config QCOM_TCSR
+ tristate "QCOM Top Control and Status Registers"
+ depends on ARCH_QCOM
+ help
+ Say y here to enable TCSR support. The TCSR provides control
+ functions for various peripherals.
+
config QCOM_WCNSS_CTRL
tristate "Qualcomm WCNSS control driver"
depends on ARCH_QCOM || COMPILE_TEST
--- /dev/null
+++ b/drivers/soc/qcom/qcom_tcsr.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2014, 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 rev 2 and
+ * only rev 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/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+#define TCSR_USB_PORT_SEL 0xb0
+#define TCSR_USB_HSPHY_CONFIG 0xC
+
+#define TCSR_ESS_INTERFACE_SEL_OFFSET 0x0
+#define TCSR_ESS_INTERFACE_SEL_MASK 0xf
+
+#define TCSR_WIFI0_GLB_CFG_OFFSET 0x0
+#define TCSR_WIFI1_GLB_CFG_OFFSET 0x4
+#define TCSR_PNOC_SNOC_MEMTYPE_M0_M2 0x4
+
+static int tcsr_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ const struct device_node *node = pdev->dev.of_node;
+ void __iomem *base;
+ u32 val;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ if (!of_property_read_u32(node, "qcom,usb-ctrl-select", &val)) {
+ dev_err(&pdev->dev, "setting usb port select = %d\n", val);
+ writel(val, base + TCSR_USB_PORT_SEL);
+ }
+
+ if (!of_property_read_u32(node, "qcom,usb-hsphy-mode-select", &val)) {
+ dev_info(&pdev->dev, "setting usb hs phy mode select = %x\n", val);
+ writel(val, base + TCSR_USB_HSPHY_CONFIG);
+ }
+
+ if (!of_property_read_u32(node, "qcom,ess-interface-select", &val)) {
+ u32 tmp = 0;
+ dev_info(&pdev->dev, "setting ess interface select = %x\n", val);
+ tmp = readl(base + TCSR_ESS_INTERFACE_SEL_OFFSET);
+ tmp = tmp & (~TCSR_ESS_INTERFACE_SEL_MASK);
+ tmp = tmp | (val&TCSR_ESS_INTERFACE_SEL_MASK);
+ writel(tmp, base + TCSR_ESS_INTERFACE_SEL_OFFSET);
+ }
+
+ if (!of_property_read_u32(node, "qcom,wifi_glb_cfg", &val)) {
+ dev_info(&pdev->dev, "setting wifi_glb_cfg = %x\n", val);
+ writel(val, base + TCSR_WIFI0_GLB_CFG_OFFSET);
+ writel(val, base + TCSR_WIFI1_GLB_CFG_OFFSET);
+ }
+
+ if (!of_property_read_u32(node, "qcom,wifi_noc_memtype_m0_m2", &val)) {
+ dev_info(&pdev->dev,
+ "setting wifi_noc_memtype_m0_m2 = %x\n", val);
+ writel(val, base + TCSR_PNOC_SNOC_MEMTYPE_M0_M2);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id tcsr_dt_match[] = {
+ { .compatible = "qcom,tcsr", },
+ { },
+};
+
+MODULE_DEVICE_TABLE(of, tcsr_dt_match);
+
+static struct platform_driver tcsr_driver = {
+ .driver = {
+ .name = "tcsr",
+ .owner = THIS_MODULE,
+ .of_match_table = tcsr_dt_match,
+ },
+ .probe = tcsr_probe,
+};
+
+module_platform_driver(tcsr_driver);
+
+MODULE_AUTHOR("Andy Gross <agross@codeaurora.org>");
+MODULE_DESCRIPTION("QCOM TCSR driver");
+MODULE_LICENSE("GPL v2");
--- /dev/null
+++ b/include/dt-bindings/soc/qcom,tcsr.h
@@ -0,0 +1,48 @@
+/* Copyright (c) 2014, 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 __DT_BINDINGS_QCOM_TCSR_H
+#define __DT_BINDINGS_QCOM_TCSR_H
+
+#define TCSR_USB_SELECT_USB3_P0 0x1
+#define TCSR_USB_SELECT_USB3_P1 0x2
+#define TCSR_USB_SELECT_USB3_DUAL 0x3
+
+/* IPQ40xx HS PHY Mode Select */
+#define TCSR_USB_HSPHY_HOST_MODE 0x00E700E7
+#define TCSR_USB_HSPHY_DEVICE_MODE 0x00C700E7
+
+/* IPQ40xx ess interface mode select */
+#define TCSR_ESS_PSGMII 0
+#define TCSR_ESS_PSGMII_RGMII5 1
+#define TCSR_ESS_PSGMII_RMII0 2
+#define TCSR_ESS_PSGMII_RMII1 4
+#define TCSR_ESS_PSGMII_RMII0_RMII1 6
+#define TCSR_ESS_PSGMII_RGMII4 9
+
+/*
+ * IPQ40xx WiFi Global Config
+ * Bit 30:AXID_EN
+ * Enable AXI master bus Axid translating to confirm all txn submitted by order
+ * Bit 24: Use locally generated socslv_wxi_bvalid
+ * 1: use locally generate socslv_wxi_bvalid for performance.
+ * 0: use SNOC socslv_wxi_bvalid.
+ */
+#define TCSR_WIFI_GLB_CFG 0x41000000
+
+/* IPQ40xx MEM_TYPE_SEL_M0_M2 Select Bit 26:24 - 2 NORMAL */
+#define TCSR_WIFI_NOC_MEMTYPE_M0_M2 0x02222222
+
+/* TCSR A/B REG */
+#define IPQ806X_TCSR_REG_A_ADM_CRCI_MUX_SEL 0
+#define IPQ806X_TCSR_REG_B_ADM_CRCI_MUX_SEL 1
+
+#endif

View file

@ -0,0 +1,43 @@
From: John Crispin <blogic@openwrt.org>
Date: Fri, 3 Aug 2012 10:27:25 +0200
Subject: [PATCH 04/36] MIPS: lantiq: add atm hack
Signed-off-by: John Crispin <blogic@openwrt.org>
--- a/include/uapi/linux/atm.h
+++ b/include/uapi/linux/atm.h
@@ -131,8 +131,14 @@
#define ATM_ABR 4
#define ATM_ANYCLASS 5 /* compatible with everything */
+#define ATM_VBR_NRT ATM_VBR
+#define ATM_VBR_RT 6
+#define ATM_UBR_PLUS 7
+#define ATM_GFR 8
+
#define ATM_MAX_PCR -1 /* maximum available PCR */
+
struct atm_trafprm {
unsigned char traffic_class; /* traffic class (ATM_UBR, ...) */
int max_pcr; /* maximum PCR in cells per second */
@@ -155,6 +161,9 @@ struct atm_trafprm {
unsigned int adtf :10; /* ACR Decrease Time Factor (10-bit) */
unsigned int cdf :3; /* Cutoff Decrease Factor (3-bit) */
unsigned int spare :9; /* spare bits */
+ int scr; /* sustained rate in cells per second */
+ int mbs; /* maximum burst size (MBS) in cells */
+ int cdv; /* Cell delay variation */
};
struct atm_qos {
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -141,7 +141,7 @@ static void *vcc_seq_next(struct seq_fil
static void pvc_info(struct seq_file *seq, struct atm_vcc *vcc)
{
static const char *const class_name[] = {
- "off", "UBR", "CBR", "VBR", "ABR"};
+ "off","UBR","CBR","NTR-VBR","ABR","ANY","RT-VBR","UBR+","GFR"};
static const char *const aal_name[] = {
"---", "1", "2", "3/4", /* 0- 3 */
"???", "5", "???", "???", /* 4- 7 */

View file

@ -0,0 +1,137 @@
From: Subhra Banerjee <subhrax.banerjee@intel.com>
Date: Fri, 31 Aug 2018 12:01:19 +0530
Subject: [PATCH] UGW_SW-29163: ATM oam support
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -2952,6 +2952,22 @@ char *ppp_dev_name(struct ppp_channel *c
return name;
}
+/*
+ * Return the PPP device interface pointer
+ */
+struct net_device *ppp_device(struct ppp_channel *chan)
+{
+ struct channel *pch = chan->ppp;
+ struct net_device *dev = NULL;
+
+ if (pch) {
+ read_lock_bh(&pch->upl);
+ if (pch->ppp && pch->ppp->dev)
+ dev = pch->ppp->dev;
+ read_unlock_bh(&pch->upl);
+ }
+ return dev;
+}
/*
* Disconnect a channel from the generic layer.
@@ -3598,6 +3614,7 @@ EXPORT_SYMBOL(ppp_unregister_channel);
EXPORT_SYMBOL(ppp_channel_index);
EXPORT_SYMBOL(ppp_unit_number);
EXPORT_SYMBOL(ppp_dev_name);
+EXPORT_SYMBOL(ppp_device);
EXPORT_SYMBOL(ppp_input);
EXPORT_SYMBOL(ppp_input_error);
EXPORT_SYMBOL(ppp_output_wakeup);
--- a/include/linux/ppp_channel.h
+++ b/include/linux/ppp_channel.h
@@ -74,6 +74,9 @@ extern int ppp_unit_number(struct ppp_ch
/* Get the device name associated with a channel, or NULL if none */
extern char *ppp_dev_name(struct ppp_channel *);
+/* Get the device pointer associated with a channel, or NULL if none */
+extern struct net_device *ppp_device(struct ppp_channel *);
+
/*
* SMP locking notes:
* The channel code must ensure that when it calls ppp_unregister_channel,
--- a/net/atm/Kconfig
+++ b/net/atm/Kconfig
@@ -56,6 +56,12 @@ config ATM_MPOA
subnetwork boundaries. These shortcut connections bypass routers
enhancing overall network performance.
+config ATM_MPOA_INTEL_DSL_PHY_SUPPORT
+ bool "Intel DSL Phy MPOA support"
+ depends on ATM && INET && ATM_MPOA!=n
+ help
+ Add support for Intel DSL Phy ATM MPOA
+
config ATM_BR2684
tristate "RFC1483/2684 Bridged protocols"
depends on ATM && INET
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -596,6 +596,11 @@ static int br2684_regvcc(struct atm_vcc
atmvcc->push = br2684_push;
atmvcc->pop = br2684_pop;
atmvcc->release_cb = br2684_release_cb;
+#if IS_ENABLED(CONFIG_ATM_MPOA_INTEL_DSL_PHY_SUPPORT)
+ if (atm_hook_mpoa_setup) /* IPoA or EoA w/o FCS */
+ atm_hook_mpoa_setup(atmvcc, brdev->payload == p_routed ? 3 : 0,
+ brvcc->encaps == BR2684_ENCAPS_LLC ? 1 : 0, net_dev);
+#endif
atmvcc->owner = THIS_MODULE;
/* initialize netdev carrier state */
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -137,6 +137,11 @@ static struct proto vcc_proto = {
.release_cb = vcc_release_cb,
};
+#if IS_ENABLED(CONFIG_ATM_MPOA_INTEL_DSL_PHY_SUPPORT)
+void (*atm_hook_mpoa_setup)(struct atm_vcc *, int, int, struct net_device *) = NULL;
+EXPORT_SYMBOL(atm_hook_mpoa_setup);
+#endif
+
int vcc_create(struct net *net, struct socket *sock, int protocol, int family, int kern)
{
struct sock *sk;
--- a/net/atm/common.h
+++ b/net/atm/common.h
@@ -53,4 +53,6 @@ int svc_change_qos(struct atm_vcc *vcc,s
void atm_dev_release_vccs(struct atm_dev *dev);
+extern void (*atm_hook_mpoa_setup)(struct atm_vcc *, int, int, struct net_device *);
+
#endif
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -31,6 +31,7 @@
/* Modular too */
#include <linux/module.h>
+#include "common.h"
#include "lec.h"
#include "mpc.h"
#include "resources.h"
@@ -645,6 +646,10 @@ static int atm_mpoa_vcc_attach(struct at
vcc->proto_data = mpc->dev;
vcc->push = mpc_push;
+#if IS_ENABLED(CONFIG_ATM_MPOA_INTEL_DSL_PHY_SUPPORT)
+ if (atm_hook_mpoa_setup) /* IPoA, LLC */
+ atm_hook_mpoa_setup(vcc, 3, 1, mpc->dev);
+#endif
return 0;
}
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -422,6 +422,12 @@ static int pppoatm_assign_vcc(struct atm
atmvcc->user_back = pvcc;
atmvcc->push = pppoatm_push;
atmvcc->pop = pppoatm_pop;
+#if IS_ENABLED(CONFIG_ATM_MPOA_INTEL_DSL_PHY_SUPPORT)
+ if (atm_hook_mpoa_setup) /* PPPoA */
+ atm_hook_mpoa_setup(atmvcc, 2,
+ pvcc->encaps == e_llc ? 1 : 0,
+ ppp_device(&pvcc->chan));
+#endif
atmvcc->release_cb = pppoatm_release_cb;
__module_get(THIS_MODULE);
atmvcc->owner = THIS_MODULE;