Compare commits
18 Commits
snic10e
...
snic10e-et
| Author | SHA1 | Date | |
|---|---|---|---|
| 7e0984e70f | |||
| ad6a039808 | |||
| 34ee966cba | |||
| 8d73f4e647 | |||
| 4f8715bdbf | |||
| d803c68954 | |||
| b5d1f3cbc3 | |||
| 15977758ba | |||
| 319b41636f | |||
| 99afb6ba21 | |||
| 47890af657 | |||
| 0ea1b55c49 | |||
| 6e303ca958 | |||
| c316f05f21 | |||
| a78fd8e4b7 | |||
| 665d617447 | |||
| fea3bae7b1 | |||
| b1ce6e7731 |
@@ -159,6 +159,7 @@ CONFIG_HZ_250=y
|
||||
CONFIG_HZ_PERIODIC=y
|
||||
CONFIG_IMAGE_CMDLINE_HACK=y
|
||||
CONFIG_I2C=y
|
||||
CONFIG_I2C_BOARDINFO=y
|
||||
CONFIG_I2C_OCTEON=y
|
||||
CONFIG_INITRAMFS_SOURCE=""
|
||||
CONFIG_IRQCHIP=y
|
||||
@@ -205,8 +206,10 @@ CONFIG_MTD_PHYSMAP=y
|
||||
CONFIG_MTD_SPI_NOR=y
|
||||
CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
|
||||
CONFIG_NEED_DMA_MAP_STATE=y
|
||||
CONFIG_NET_DEVLINK=y
|
||||
CONFIG_NET_DSA=y
|
||||
CONFIG_NET_FLOW_LIMIT=y
|
||||
CONFIG_NET_SWITCHDEV=y
|
||||
CONFIG_NLS=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
@@ -214,9 +217,9 @@ CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
|
||||
CONFIG_NR_CPUS=16
|
||||
CONFIG_NR_CPUS_DEFAULT_64=y
|
||||
CONFIG_NVMEM=y
|
||||
CONFIG_OCTEON_ETHERNET=n
|
||||
CONFIG_OCTEON_ETHERNET=y
|
||||
CONFIG_OCTEON_ILM=y
|
||||
CONFIG_OCTEON_MGMT_ETHERNET=n
|
||||
CONFIG_OCTEON_MGMT_ETHERNET=y
|
||||
CONFIG_OCTEON_USB=y
|
||||
CONFIG_OCTEON_WDT=y
|
||||
CONFIG_OF=y
|
||||
@@ -227,22 +230,25 @@ CONFIG_OF_GPIO=y
|
||||
CONFIG_OF_IRQ=y
|
||||
CONFIG_OF_KOBJ=y
|
||||
CONFIG_OF_MDIO=y
|
||||
CONFIG_OF_MEMORY_ACCESSOR=y
|
||||
CONFIG_OF_NET=y
|
||||
CONFIG_PADATA=y
|
||||
# CONFIG_PARTITION_ADVANCED is not set
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCI_DOMAINS=y
|
||||
CONFIG_PCI_DRIVERS_LEGACY=y
|
||||
CONFIG_PCIEAER=y
|
||||
CONFIG_PCIEPORTBUS=y
|
||||
CONFIG_PCI_DOMAINS=y
|
||||
CONFIG_PCI_DRIVERS_LEGACY=y
|
||||
CONFIG_PERF_USE_VMALLOC=y
|
||||
CONFIG_PGTABLE_LEVELS=3
|
||||
CONFIG_PHYLIB=y
|
||||
CONFIG_PHYLINK=y
|
||||
CONFIG_PHYS_ADDR_T_64BIT=y
|
||||
CONFIG_POSIX_MQUEUE=y
|
||||
CONFIG_POSIX_MQUEUE_SYSCTL=y
|
||||
CONFIG_QUEUED_RWLOCKS=y
|
||||
CONFIG_QUEUED_SPINLOCKS=y
|
||||
CONFIG_RAS=y
|
||||
CONFIG_RCU_NEED_SEGCBLIST=y
|
||||
CONFIG_RCU_STALL_COMMON=y
|
||||
CONFIG_RELAY=y
|
||||
@@ -260,6 +266,7 @@ CONFIG_SPARSEMEM=y
|
||||
CONFIG_SPARSEMEM_STATIC=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_SPI_MASTER=y
|
||||
CONFIG_SPI_MEM=y
|
||||
CONFIG_SPI_OCTEON=y
|
||||
CONFIG_SRCU=y
|
||||
CONFIG_SWIOTLB=y
|
||||
@@ -295,6 +302,7 @@ CONFIG_USE_OF=y
|
||||
CONFIG_VFAT_FS=y
|
||||
CONFIG_VITESSE_PHY=y
|
||||
CONFIG_VM_EVENT_COUNTERS=y
|
||||
CONFIG_VSC848X_PHY=y
|
||||
CONFIG_WATCHDOG_CORE=y
|
||||
CONFIG_WEAK_ORDERING=y
|
||||
CONFIG_XPS=y
|
||||
|
||||
@@ -116,7 +116,6 @@
|
||||
reg = <0x11800 0x00001800 0x0 0x40>;
|
||||
status = "disabled";
|
||||
mphyA: ethernet-phy-nexus@A {
|
||||
status = "disabled";
|
||||
reg = <0>;
|
||||
/* The Vitesse VSC8488 is a dual-PHY where
|
||||
* some of the configuration is common across
|
||||
@@ -133,7 +132,6 @@
|
||||
reset = <&gpio 17 0>;
|
||||
|
||||
phy0: ethernet-phy@0 {
|
||||
status = "disabled";
|
||||
/* Absolute address */
|
||||
reg = <0>;
|
||||
compatible = "vitesse,vsc8488", "ethernet-phy-ieee802.3-c45";
|
||||
@@ -350,7 +348,6 @@
|
||||
};
|
||||
|
||||
phy1: ethernet-phy@1 {
|
||||
status = "disabled";
|
||||
/* Absolute address */
|
||||
reg = <0x1>;
|
||||
compatible = "vitesse,vsc8488", "ethernet-phy-ieee802.3-c45";
|
||||
@@ -567,7 +564,6 @@
|
||||
};
|
||||
};
|
||||
mphyB: ethernet-phy-nexus@B {
|
||||
status = "disabled";
|
||||
reg = <0>;
|
||||
/* The TI TLK10232 is a dual-PHY where
|
||||
* some of the configuration is common across
|
||||
@@ -584,7 +580,6 @@
|
||||
reset = <&gpio 17 2>;
|
||||
|
||||
phy11: ethernet-phy@0 {
|
||||
status = "disabled";
|
||||
/* Absolute address */
|
||||
reg = <0>;
|
||||
compatible = "ti,tlk10232", "ethernet-phy-ieee802.3-c45";
|
||||
@@ -608,7 +603,6 @@
|
||||
};
|
||||
|
||||
phy10: ethernet-phy@1 {
|
||||
status = "disabled";
|
||||
/* Absolute address */
|
||||
reg = <0x1>;
|
||||
compatible = "ti,tlk10232", "ethernet-phy-ieee802.3-c45";
|
||||
|
||||
829
target/linux/octeon/patches-5.4/0001_add_vsc_phy.patch
Normal file
829
target/linux/octeon/patches-5.4/0001_add_vsc_phy.patch
Normal file
@@ -0,0 +1,829 @@
|
||||
From: Abhishek Paliwal <abhishek.paliwal@aricent.com>
|
||||
Date: Fri, 13 Feb 2015 15:04:55 +0530
|
||||
Subject: netdev/phy: Add driver for Vitesse vsc848x single, dual and quad 10G
|
||||
phys
|
||||
|
||||
From: David Daney <david.daney@cavium.com>
|
||||
|
||||
These phys implement the standard IEEE 802.3 clause 45 registers but
|
||||
require additional configuration. Some of these registers in the multi-phy
|
||||
devices are shared among all phys such as the GPIO registers.
|
||||
|
||||
Additionally, this PHY does not automatically access the SFP+ serial EEPROM so
|
||||
it is up to the PHY driver to parse it and change certain parameters in the
|
||||
PHY according to the type of module installed and the length of the cable, if
|
||||
copper.
|
||||
|
||||
This module has support for the vsc8488, vsc8486 and vsc8484 Vitesse devices
|
||||
but thus far has only been tested with the vsc8488 dual PHY.
|
||||
|
||||
netdev/phy: Clean up structure names in vsc848x.c
|
||||
Cut-and-paste snafu left some bad names, no functional change.
|
||||
|
||||
Signed-off-by: David Daney <david.daney@cavium.com>
|
||||
Signed-off-by: Aaron Williams <aaron.williams@cavium.com>
|
||||
Signed-off-by: Leonid Rosenboim <lrosenboim@caviumnetworks.com>
|
||||
Signed-off-by: Abhishek Paliwal <abhishek.paliwal@aricent.com>
|
||||
[Rebased on kernel 5.4 by Martin Kennedy <hurricos@gmail.com>]
|
||||
Signed-off-by: Martin Kennedy <hurricos@gmail.com>
|
||||
--- a/drivers/net/phy/Kconfig
|
||||
+++ b/drivers/net/phy/Kconfig
|
||||
@@ -54,6 +54,13 @@ config VITESSE_PHY
|
||||
---help---
|
||||
Currently supports the vsc8244
|
||||
|
||||
+config VSC848X_PHY
|
||||
+ tristate "Drivers for the Vitesse 10G PHYs"
|
||||
+ depends on OF_MEMORY_ACCESSOR
|
||||
+ help
|
||||
+ Driver for Vitesse vsc848x single, dual and quad 10G PHY devices.
|
||||
+ Currently supports the vsc8488, vsc8486 and vsc8484 chips
|
||||
+
|
||||
config SMSC_PHY
|
||||
tristate "Drivers for SMSC PHYs"
|
||||
---help---
|
||||
--- a/drivers/net/phy/Makefile
|
||||
+++ b/drivers/net/phy/Makefile
|
||||
@@ -108,4 +108,5 @@
|
||||
obj-$(CONFIG_STE10XP) += ste10Xp.o
|
||||
obj-$(CONFIG_TERANETICS_PHY) += teranetics.o
|
||||
obj-$(CONFIG_VITESSE_PHY) += vitesse.o
|
||||
+obj-$(CONFIG_VSC848X_PHY) += vsc848x.o
|
||||
obj-$(CONFIG_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/phy/vsc848x.c
|
||||
@@ -0,0 +1,774 @@
|
||||
+/*
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2012 Cavium, Inc.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/of_mdio.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/phy.h>
|
||||
+#include <linux/memory.h>
|
||||
+#include <linux/mutex.h>
|
||||
+#include <linux/of_memory_accessor.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/ctype.h>
|
||||
+
|
||||
+#define PMD_RX_SIGNAL_DETECT (MII_ADDR_C45 | 0x01000a)
|
||||
+#define PMA_TXOUTCTRL2 (MII_ADDR_C45 | 0x018014)
|
||||
+#define EDC_EYE_QUALITY (MII_ADDR_C45 | 0x018034)
|
||||
+/* EDC Firmware State Machine Status and Lib Force
|
||||
+ * 15: library force enable
|
||||
+ * 14:8 - Library number
|
||||
+ * 7:5 - N/A
|
||||
+ * 4 - State force
|
||||
+ * 3:0 - FW state (1=reset, 2=wait for alarm to clear, 3 = convergence,
|
||||
+ * 4 = tracking, 5 = freeze)
|
||||
+ */
|
||||
+#define EDC_FW_SM_STATUS (MII_ADDR_C45 | 0x018036)
|
||||
+
|
||||
+#define BASER_PCS_STATUS (MII_ADDR_C45 | 0x030020)
|
||||
+#define XGXS_LANE_STATUS (MII_ADDR_C45 | 0x040018)
|
||||
+#define EWIS_INTR_PEND1 (MII_ADDR_C45 | 0x02EE00)
|
||||
+#define EWIS_INTR_MASKA_1 (MII_ADDR_C45 | 0x02EE01)
|
||||
+#define EWIS_INTR_MASKB_1 (MII_ADDR_C45 | 0x02EE02)
|
||||
+#define EWIS_INTR_STAT2 (MII_ADDR_C45 | 0x02EE03)
|
||||
+#define EWIS_INTR_PEND2 (MII_ADDR_C45 | 0x02EE04)
|
||||
+#define EWIS_INTR_MASKA_2 (MII_ADDR_C45 | 0x02EE05)
|
||||
+#define EWIS_INTR_MASKB_2 (MII_ADDR_C45 | 0x02EE06)
|
||||
+#define EWIS_FAULT_MASK (MII_ADDR_C45 | 0x02EE07)
|
||||
+#define EWIS_INTR_PEND3 (MII_ADDR_C45 | 0x02EE08)
|
||||
+#define EWIS_INTR_MASKA_3 (MII_ADDR_C45 | 0x02EE09)
|
||||
+#define EWIS_INTR_MASKB_3 (MII_ADDR_C45 | 0x02EE0A)
|
||||
+
|
||||
+/* Device ID
|
||||
+ * 15:0 - device ID
|
||||
+ */
|
||||
+#define GBL_DEVICE_ID (MII_ADDR_C45 | 0x1e0000)
|
||||
+/* Device revision
|
||||
+ * 15:04 - reserved
|
||||
+ * 03:00 - revision ID
|
||||
+ */
|
||||
+#define GBL_DEVICE_REVISION (MII_ADDR_C45 | 0x1e0001)
|
||||
+/* Block Level Software Reset
|
||||
+ * 15:14 - reserved
|
||||
+ * 13: - software reset EDC 1 (1 = reset, autoclears)
|
||||
+ * 12: - software reset EDC 0 (1 = reset, autoclears)
|
||||
+ * 11:10 - reserved
|
||||
+ * 09: - Software reset channel 1 (1 = reset, autoclears)
|
||||
+ * 08: - Software reset channel 0 (1 = reset, autoclears)
|
||||
+ * 07: - Microprocessor reset (0 = normal operation, 1 = reset)
|
||||
+ * 06: - Software reset BIU (1 = reset, autoclears)
|
||||
+ * 05: - Software reset TWS slave (1 = reset, autoclears)
|
||||
+ * 04: - Software reset TWS master (1 = reset, autoclears)
|
||||
+ * 03: - Software reset MDIO (1 = reset, autoclears)
|
||||
+ * 02: - Software reset UART (1 = reset, autoclears)
|
||||
+ * 01: - Global register reset (1 = reset, autoclears)
|
||||
+ * 00: - Software reset chip (1 = reset, autoclears)
|
||||
+ */
|
||||
+#define GBL_BLOCK_LVL_SW_RESET (MII_ADDR_C45 | 0x1e0002)
|
||||
+#define GBL_GPIO_0_CONFIG1_STATUS (MII_ADDR_C45 | 0x1e0100)
|
||||
+#define GBL_GPIO_0_CONFIG2 (MII_ADDR_C45 | 0x1e0101)
|
||||
+#define GBL_DEVICE_ID (MII_ADDR_C45 | 0x1e0000)
|
||||
+#define GBL_FW_CHECKSUM (MII_ADDR_C45 | 0x1e7fe0)
|
||||
+#define GBL_FW_WATCHDOG (MII_ADDR_C45 | 0x1e7fe1)
|
||||
+#define GBL_FW_VERSION (MII_ADDR_C45 | 0x1e7fe2)
|
||||
+#define GBL_FW_VAR_ACC_CTRL (MII_ADDR_C45 | 0x1e7fe3)
|
||||
+#define GBL_FW_VAR_ACC_DATA (MII_ADDR_C45 | 0x1e7fe4)
|
||||
+
|
||||
+/* The Vitesse VSC848X series are 10G PHYs.
|
||||
+ *
|
||||
+ * Some of these devices contain multiple PHYs in a single package and
|
||||
+ * some features are controlled by a global set of registers shared between
|
||||
+ * all of the PHY devices. Because of this a nexus is used to handle all
|
||||
+ * of the PHYs on the same device.
|
||||
+ *
|
||||
+ * Unlike some PHY devices, it is up to the driver to read the SFP module
|
||||
+ * serial EEPROM in order to put the PHY into the right mode. The VSC848X
|
||||
+ * does not provide an I2C interface so the PHY driver relies on the
|
||||
+ * external AT24 I2C EEPROM driver to read the module whenever it is inserted.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+/* Enable LOPC detection (see 0x5B for target state)
|
||||
+ * 15:12 - channel 3
|
||||
+ * 11:08 - channel 2
|
||||
+ * 07:04 - channel 1
|
||||
+ * 03:00 - channel 0
|
||||
+ * 1 = enable (default), 0 = disable
|
||||
+ */
|
||||
+#define FW_VAR_ENABLE_LOPC 0x58
|
||||
+/* While in tracking mode, go to this state in response to LOPC assertion
|
||||
+ * 1 = reset, 2 = wait (default), 3 = converging, 4 = tracking, 5 = freeze
|
||||
+ */
|
||||
+#define FW_VAR_LOPC_ASSERT_MODE 0x5B
|
||||
+/* While in freeze mode, enable state transition upon deassertion of LOPC (see
|
||||
+ * 0x61 for target state)
|
||||
+ * 1 - reset, 2 = wait, 3 = converging, 4 = tracking (default), 5 = freeze
|
||||
+ */
|
||||
+#define FW_VAR_FREEZE_DEASSERT_MODE 0x61
|
||||
+/* Current functional mode
|
||||
+ * See VITESSE_FUNC_MODE_XXX below for values
|
||||
+ * NOTE: When the firmware is done servicing the mode change request, bit 4
|
||||
+ * will be set to 1.
|
||||
+ */
|
||||
+#define FW_VAR_FUNCTIONAL_MODE 0x94
|
||||
+/* Current state of graded SPSA process
|
||||
+ * 3: channel 3
|
||||
+ * 2: channel 2
|
||||
+ * 1: channel 1
|
||||
+ * 0: channel 0
|
||||
+ * 1 = busy, 2 = done
|
||||
+ */
|
||||
+#define FW_VAR_GRADED_SPSA_STATE 0x95
|
||||
+/* BerScore at start of SPSA cycle */
|
||||
+#define FW_VAR_BERSCORE_START 0x96
|
||||
+/* BerScore at end of SPSA cycle */
|
||||
+#define FW_VAR_BERSCORE_END 0x97
|
||||
+/* Enable/Disable aggressive track phase on entering tracking state
|
||||
+ * 15:12 - channel 3
|
||||
+ * 11:08 - channel 2
|
||||
+ * 07:04 - channel 1
|
||||
+ * 03:00 - channel 0
|
||||
+ * 0 = disable, 1 = enable (default)
|
||||
+ */
|
||||
+#define FW_VAR_AGG_TRACKING 0xAF
|
||||
+
|
||||
+/* Modes for the PHY firmware */
|
||||
+#define VITESSE_FUNC_MODE_LIMITING 2 /* Optical */
|
||||
+#define VITESSE_FUNC_MODE_COPPER 3 /* Copper */
|
||||
+#define VITESSE_FUNC_MODE_LINEAR 4
|
||||
+#define VITESSE_FUNC_MODE_KR 5
|
||||
+#define VITESSE_FUNC_MODE_ZR 7
|
||||
+#define VITESSE_FUNC_MODE_1G 8
|
||||
+
|
||||
+
|
||||
+struct vsc848x_nexus_mdiobus {
|
||||
+ struct mii_bus *mii_bus;
|
||||
+ struct mii_bus *parent_mii_bus;
|
||||
+ int reg_offset;
|
||||
+ struct mutex lock; /* Lock used for global register sequences */
|
||||
+ int phy_irq[PHY_MAX_ADDR];
|
||||
+};
|
||||
+
|
||||
+struct vsc848x_phy_info {
|
||||
+ int sfp_conn; /* Module connected? */
|
||||
+ int tx_en_gpio; /* GPIO that enables transmit */
|
||||
+ int mod_abs_gpio; /* Module Absent GPIO line */
|
||||
+ int tx_fault_gpio; /* TX Fault GPIO line */
|
||||
+ int inta_gpio, intb_gpio; /* Interrupt GPIO line (output) */
|
||||
+ uint8_t mode; /* Mode for module */
|
||||
+ uint8_t channel; /* channel in multi-phy devices */
|
||||
+ struct device_node *sfp_node; /* EEPROM NODE for SFP */
|
||||
+ struct memory_accessor *macc; /* memory access routines for EEPROM */
|
||||
+ struct vsc848x_nexus_mdiobus *nexus; /* Nexus for lock */
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * Maps GPIO lines to the global GPIO config registers.
|
||||
+ *
|
||||
+ * Please see the data sheet since the configuration for each GPIO line is
|
||||
+ * different.
|
||||
+ */
|
||||
+static const struct {
|
||||
+ uint32_t config1_status_reg;
|
||||
+ uint32_t config2_reg;
|
||||
+} vcs848x_gpio_to_reg[12] = {
|
||||
+ { (MII_ADDR_C45 | 0x1e0100), (MII_ADDR_C45 | 0x1e0101) }, /* 0 */
|
||||
+ { (MII_ADDR_C45 | 0x1e0102), (MII_ADDR_C45 | 0x1e0103) }, /* 1 */
|
||||
+ { (MII_ADDR_C45 | 0x1e0104), (MII_ADDR_C45 | 0x1e0105) }, /* 2 */
|
||||
+ { (MII_ADDR_C45 | 0x1e0106), (MII_ADDR_C45 | 0x1e0107) }, /* 3 */
|
||||
+ { (MII_ADDR_C45 | 0x1e0108), (MII_ADDR_C45 | 0x1e0109) }, /* 4 */
|
||||
+ { (MII_ADDR_C45 | 0x1e010A), (MII_ADDR_C45 | 0x1e010B) }, /* 5 */
|
||||
+ { (MII_ADDR_C45 | 0x1e0124), (MII_ADDR_C45 | 0x1e0125) }, /* 6 */
|
||||
+ { (MII_ADDR_C45 | 0x1e0126), (MII_ADDR_C45 | 0x1e0127) }, /* 7 */
|
||||
+ { (MII_ADDR_C45 | 0x1e0128), (MII_ADDR_C45 | 0x1e0129) }, /* 8 */
|
||||
+ { (MII_ADDR_C45 | 0x1e012a), (MII_ADDR_C45 | 0x1e012b) }, /* 9 */
|
||||
+ { (MII_ADDR_C45 | 0x1e012c), (MII_ADDR_C45 | 0x1e012d) }, /* 10 */
|
||||
+ { (MII_ADDR_C45 | 0x1e012e), (MII_ADDR_C45 | 0x1e012f) }, /* 11 */
|
||||
+};
|
||||
+
|
||||
+static int vsc848x_probe(struct phy_device *phydev)
|
||||
+{
|
||||
+ struct vsc848x_phy_info *dev_info;
|
||||
+ int ret;
|
||||
+
|
||||
+ dev_info = devm_kzalloc(&phydev->dev, sizeof(*dev_info), GFP_KERNEL);
|
||||
+ if (dev_info == NULL)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ phydev->priv = dev_info;
|
||||
+ dev_info->mode = VITESSE_FUNC_MODE_LIMITING; /* Default to optical */
|
||||
+ phydev->priv = dev_info;
|
||||
+ dev_info->nexus = phydev->bus->priv;
|
||||
+
|
||||
+ ret = of_property_read_u32(phydev->dev.of_node, "mod_abs",
|
||||
+ &dev_info->mod_abs_gpio);
|
||||
+ if (ret) {
|
||||
+ dev_err(&phydev->dev, "%s has invalid mod_abs address\n",
|
||||
+ phydev->dev.of_node->full_name);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = of_property_read_u32(phydev->dev.of_node, "tx_fault",
|
||||
+ &dev_info->tx_fault_gpio);
|
||||
+ if (ret) {
|
||||
+ dev_err(&phydev->dev, "%s has invalid tx_fault address\n",
|
||||
+ phydev->dev.of_node->full_name);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = of_property_read_u32(phydev->dev.of_node, "inta",
|
||||
+ &dev_info->inta_gpio);
|
||||
+ if (ret)
|
||||
+ dev_info->inta_gpio = -1;
|
||||
+
|
||||
+ ret = of_property_read_u32(phydev->dev.of_node, "intb",
|
||||
+ &dev_info->intb_gpio);
|
||||
+ if (ret)
|
||||
+ dev_info->intb_gpio = -1;
|
||||
+
|
||||
+ ret = of_property_read_u32(phydev->dev.of_node, "txon",
|
||||
+ &dev_info->tx_en_gpio);
|
||||
+ if (ret) {
|
||||
+ dev_err(&phydev->dev, "%s has invalid txon gpio address\n",
|
||||
+ phydev->dev.of_node->full_name);
|
||||
+ return -ENXIO;
|
||||
+ }
|
||||
+
|
||||
+ dev_info->sfp_node = of_parse_phandle(phydev->dev.of_node,
|
||||
+ "sfp-eeprom", 0);
|
||||
+ if (!dev_info->sfp_node) {
|
||||
+ dev_err(&phydev->dev, "%s has invalid sfp-eeprom node\n",
|
||||
+ phydev->dev.of_node->full_name);
|
||||
+ return -ENXIO;
|
||||
+ }
|
||||
+
|
||||
+ dev_info->macc = of_memory_accessor_get(dev_info->sfp_node);
|
||||
+
|
||||
+ ret = phy_read(phydev, GBL_DEVICE_ID);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(&phydev->dev, "%s error reading PHY\n",
|
||||
+ phydev->dev.of_node->full_name);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Check how many devices are in the package to figure out the channel
|
||||
+ * number.
|
||||
+ */
|
||||
+ switch (ret) {
|
||||
+ case 0x8487: /* Single */
|
||||
+ case 0x8486:
|
||||
+ dev_info->channel = 0;
|
||||
+ break;
|
||||
+ case 0x8488: /* Dual */
|
||||
+ dev_info->channel = phydev->addr & 1;
|
||||
+ break;
|
||||
+ case 0x8484: /* Quad */
|
||||
+ dev_info->channel = phydev->addr & 3;
|
||||
+ break;
|
||||
+ default:
|
||||
+ dev_err(&phydev->dev, "%s Unknown Vitesse PHY model %04x\n",
|
||||
+ phydev->dev.of_node->full_name, ret);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void vsc848x_remove(struct phy_device *phydev)
|
||||
+{
|
||||
+ struct vsc848x_phy_info *dev_info = phydev->priv;
|
||||
+
|
||||
+ dev_info(&phydev->dev, "%s Exiting\n", phydev->dev.of_node->full_name);
|
||||
+
|
||||
+ of_memory_accessor_put(dev_info->sfp_node);
|
||||
+
|
||||
+ kfree(dev_info);
|
||||
+}
|
||||
+
|
||||
+static int vsc848x_config_init(struct phy_device *phydev)
|
||||
+{
|
||||
+ phydev->supported = SUPPORTED_10000baseR_FEC;
|
||||
+ phydev->advertising = ADVERTISED_10000baseR_FEC;
|
||||
+ phydev->state = PHY_NOLINK;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int vsc848x_config_aneg(struct phy_device *phydev)
|
||||
+{
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+static int vsc848x_write_global_var(struct phy_device *phydev, uint8_t channel,
|
||||
+ uint8_t addr, uint16_t value)
|
||||
+{
|
||||
+ struct vsc848x_phy_info *dev_info = phydev->priv;
|
||||
+ int timeout = 1000;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ mutex_lock(&(dev_info->nexus->lock));
|
||||
+
|
||||
+ /* Wait for firmware download to complete */
|
||||
+ timeout = 100000;
|
||||
+ do {
|
||||
+ ret = phy_read(phydev, MII_ADDR_C45 | 0x1e7fe0);
|
||||
+ if (ret < 0)
|
||||
+ goto error;
|
||||
+ if (ret == 3)
|
||||
+ break;
|
||||
+ udelay(100);
|
||||
+ } while (timeout-- > 0);
|
||||
+ if (timeout <= 0) {
|
||||
+ dev_err(&phydev->dev, "%s Timeout waiting for PHY firmware to load\n",
|
||||
+ phydev->dev.of_node->full_name);
|
||||
+ ret = -EIO;
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ do {
|
||||
+ ret = phy_read(phydev, (MII_ADDR_C45 | 0x1e7fe3));
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ if (ret == 0)
|
||||
+ break;
|
||||
+ mdelay(1);
|
||||
+ } while (timeout-- > 0);
|
||||
+ if (timeout <= 0) {
|
||||
+ dev_err(&phydev->dev, "%s timed out waiting to write global\n",
|
||||
+ phydev->dev.of_node->full_name);
|
||||
+ ret = -EIO;
|
||||
+ goto error;
|
||||
+ }
|
||||
+ ret = phy_write(phydev, (MII_ADDR_C45 | 0x1e7fe4), value);
|
||||
+ if (ret < 0)
|
||||
+ goto error;
|
||||
+
|
||||
+ ret = phy_write(phydev, (MII_ADDR_C45 | 0x1e7fe3),
|
||||
+ 0x8000 | ((channel & 3) << 8) | addr);
|
||||
+ if (ret < 0)
|
||||
+ goto error;
|
||||
+
|
||||
+ /* Wait for value to be written */
|
||||
+ do {
|
||||
+ ret = phy_read(phydev, (MII_ADDR_C45 | 0x1e7fe3));
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ if (ret == 0)
|
||||
+ break;
|
||||
+ mdelay(1);
|
||||
+ } while (timeout-- > 0);
|
||||
+ if (timeout <= 0) {
|
||||
+ dev_err(&phydev->dev, "%s timed out waiting to write global\n",
|
||||
+ phydev->dev.of_node->full_name);
|
||||
+ ret = -EIO;
|
||||
+ goto error;
|
||||
+ }
|
||||
+ ret = 0;
|
||||
+
|
||||
+error:
|
||||
+ mutex_unlock(&(dev_info->nexus->lock));
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * Dumps out the contents of the SFP EEPROM when errors are detected
|
||||
+ *
|
||||
+ * @param eeprom - contents of SFP+ EEPROM
|
||||
+ */
|
||||
+static void dump_sfp_eeprom(const uint8_t eeprom[64])
|
||||
+{
|
||||
+ int addr = 0;
|
||||
+ int i;
|
||||
+ char line[17];
|
||||
+ line[16] = '\0';
|
||||
+
|
||||
+ pr_info("SFP+ EEPROM contents:\n");
|
||||
+ while (addr < 64) {
|
||||
+ pr_info(" %02x: ", addr);
|
||||
+ for (i = 0; i < 16; i++)
|
||||
+ pr_cont("%02x ", eeprom[addr + i]);
|
||||
+ for (i = 0; i < 16; i++) {
|
||||
+ if (!isprint(eeprom[addr + i]) ||
|
||||
+ eeprom[addr + i] >= 0x80)
|
||||
+ line[i] = '.';
|
||||
+ else
|
||||
+ line[i] = eeprom[addr + i];
|
||||
+ }
|
||||
+ pr_cont(" %s\n", line);
|
||||
+ addr += 16;
|
||||
+ }
|
||||
+ pr_info("\n");
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * Read the SFP+ module EEPROM and program the Vitesse PHY accordingly.
|
||||
+ *
|
||||
+ * @param phydev - Phy device
|
||||
+ *
|
||||
+ * @returns 0 for success, error otherwise.
|
||||
+ */
|
||||
+static int vsc848x_read_sfp(struct phy_device *phydev)
|
||||
+{
|
||||
+ struct vsc848x_phy_info *dev_info = phydev->priv;
|
||||
+ uint8_t sfp_buffer[64];
|
||||
+ ssize_t size;
|
||||
+ uint8_t csum;
|
||||
+ uint8_t mode = VITESSE_FUNC_MODE_LIMITING;
|
||||
+ const char *mode_str = "Unknown";
|
||||
+ int i;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ /* For details on the SFP+ EEPROM contents see the SFF-8472
|
||||
+ * Diagnostic Monitoring Interface for Optical Transceivers.
|
||||
+ *
|
||||
+ * This is based on revision 11.1, October 26, 2012.
|
||||
+ */
|
||||
+ if (!dev_info->macc) {
|
||||
+ dev_info->macc = of_memory_accessor_get(dev_info->sfp_node);
|
||||
+ if (!dev_info->macc) {
|
||||
+ dev_info(&phydev->dev,
|
||||
+ "Could not connect to sfp memory accessor %s\n",
|
||||
+ dev_info->sfp_node->full_name);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+ }
|
||||
+ size = dev_info->macc->read(dev_info->macc,
|
||||
+ (char *)sfp_buffer, 0, sizeof(sfp_buffer));
|
||||
+ if (size != sizeof(sfp_buffer)) {
|
||||
+ dev_err(&phydev->dev, "%s cannot read SFP module EEPROM\n",
|
||||
+ phydev->dev.of_node->full_name);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ /* Validate SFP checksum */
|
||||
+ csum = 0;
|
||||
+ for (i = 0; i < 63; i++)
|
||||
+ csum += sfp_buffer[i];
|
||||
+ if (csum != sfp_buffer[63]) {
|
||||
+ dev_err(&phydev->dev, "%s SFP EEPROM checksum bad, calculated 0x%02x, should be 0x%02x\n",
|
||||
+ phydev->dev.of_node->full_name, csum, sfp_buffer[63]);
|
||||
+ dump_sfp_eeprom(sfp_buffer);
|
||||
+ return -ENXIO;
|
||||
+ }
|
||||
+
|
||||
+ /* Make sure it's a SFP or SFP+ module */
|
||||
+ if (sfp_buffer[0] != 3) {
|
||||
+ dev_err(&phydev->dev, "%s module is not SFP or SFP+\n",
|
||||
+ phydev->dev.of_node->full_name);
|
||||
+ dump_sfp_eeprom(sfp_buffer);
|
||||
+ return -ENXIO;
|
||||
+ }
|
||||
+
|
||||
+ /* Check connector type */
|
||||
+ switch (sfp_buffer[2]) {
|
||||
+ case 0x01: /* SC */
|
||||
+ mode = VITESSE_FUNC_MODE_LIMITING;
|
||||
+ break;
|
||||
+ case 0x07: /* LC */
|
||||
+ mode = VITESSE_FUNC_MODE_LIMITING;
|
||||
+ break;
|
||||
+ case 0x0B: /* Optical pigtail */
|
||||
+ mode = VITESSE_FUNC_MODE_LIMITING;
|
||||
+ break;
|
||||
+ case 0x21: /* Copper pigtail */
|
||||
+ case 0x22: /* RJ45 */
|
||||
+ mode = VITESSE_FUNC_MODE_COPPER;
|
||||
+ break;
|
||||
+ default:
|
||||
+ dev_err(&phydev->dev, "%s Unknown Connector Type 0x%x\n",
|
||||
+ phydev->dev.of_node->full_name, sfp_buffer[2]);
|
||||
+ dump_sfp_eeprom(sfp_buffer);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (mode == VITESSE_FUNC_MODE_LIMITING) {
|
||||
+ if (mode_str[3] & 0x10)
|
||||
+ mode_str = "10GBase-SR";
|
||||
+ else if (mode_str[3] & 0x20)
|
||||
+ mode_str = "10GBase-LR";
|
||||
+ else if (mode_str[3] & 0x40)
|
||||
+ mode_str = "10GBase-LRM";
|
||||
+ else if (mode_str[3] & 0x80)
|
||||
+ mode_str = "10GBase-ER";
|
||||
+ else
|
||||
+ dev_err(&phydev->dev, "%s unknown SFP compatibility\n"
|
||||
+ "type ID: 0x%02x, extended ID: 0x%02x, Connector type code: 0x%02x\n"
|
||||
+ "Transceiver compatibility code: (%02x) %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
+ phydev->dev.of_node->full_name, sfp_buffer[0],
|
||||
+ sfp_buffer[1], sfp_buffer[2], sfp_buffer[36],
|
||||
+ sfp_buffer[3], sfp_buffer[4], sfp_buffer[5],
|
||||
+ sfp_buffer[6], sfp_buffer[7], sfp_buffer[8],
|
||||
+ sfp_buffer[9], sfp_buffer[10]);
|
||||
+ } else if (mode == VITESSE_FUNC_MODE_COPPER) {
|
||||
+ if (sfp_buffer[8] & 0x4) {
|
||||
+ mode_str = "10G Passive Copper";
|
||||
+ } else if (sfp_buffer[8] & 0x8) {
|
||||
+ mode_str = "10G Active Copper";
|
||||
+ mode = VITESSE_FUNC_MODE_LIMITING;
|
||||
+ } else {
|
||||
+ dev_err(&phydev->dev, "%s Unknown SFP+ copper cable capability 0x%02x\n"
|
||||
+ "Transceiver compatibility code: (%02x) %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
+ phydev->dev.of_node->full_name, sfp_buffer[8],
|
||||
+ sfp_buffer[36], sfp_buffer[3], sfp_buffer[4],
|
||||
+ sfp_buffer[5], sfp_buffer[6], sfp_buffer[7],
|
||||
+ sfp_buffer[8], sfp_buffer[9], sfp_buffer[10]);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ } else {
|
||||
+ dev_err(&phydev->dev, "%s Unsupported phy mode %d\n",
|
||||
+ phydev->dev.of_node->full_name, mode);
|
||||
+ dump_sfp_eeprom(sfp_buffer);
|
||||
+ }
|
||||
+
|
||||
+ vsc848x_write_global_var(phydev, dev_info->channel, 0x94, mode);
|
||||
+
|
||||
+ /* Adjust PMA_TXOUTCTRL2 based on cable length. Vitesse recommends
|
||||
+ * 0x1606 for copper cable lengths 5M and longer.
|
||||
+ *
|
||||
+ * The default value is 0x1300.
|
||||
+ */
|
||||
+ if (mode == VITESSE_FUNC_MODE_COPPER) {
|
||||
+ if (sfp_buffer[18] >= 5)
|
||||
+ ret = phy_write(phydev, PMA_TXOUTCTRL2, 0x1606);
|
||||
+ else
|
||||
+ ret = phy_write(phydev, PMA_TXOUTCTRL2, 0x1300);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Reset the state machine */
|
||||
+ ret = phy_write(phydev, MII_ADDR_C45 | 0x18034, 0x11);
|
||||
+
|
||||
+ dev_info(&phydev->dev, "%s configured for %s\n",
|
||||
+ phydev->dev.of_node->full_name, mode_str);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int vsc848x_read_status(struct phy_device *phydev)
|
||||
+{
|
||||
+ struct vsc848x_phy_info *dev_info = phydev->priv;
|
||||
+ int rx_signal_detect;
|
||||
+ int pcs_status;
|
||||
+ int xgxs_lane_status;
|
||||
+ int value;
|
||||
+ int sfp_conn;
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Check if a module is plugged in */
|
||||
+ value = phy_read(phydev, vcs848x_gpio_to_reg[dev_info->mod_abs_gpio]
|
||||
+ .config1_status_reg);
|
||||
+ if (value < 0)
|
||||
+ return value;
|
||||
+
|
||||
+ sfp_conn = !(value & 0x400);
|
||||
+
|
||||
+ if (sfp_conn != dev_info->sfp_conn) {
|
||||
+ /* We detect a module being plugged in */
|
||||
+ if (sfp_conn) {
|
||||
+ ret = vsc848x_read_sfp(phydev);
|
||||
+ if (ret < 0)
|
||||
+ goto no_link;
|
||||
+ dev_info->sfp_conn = sfp_conn;
|
||||
+ } else {
|
||||
+ dev_info(&phydev->dev, "%s module unplugged\n",
|
||||
+ phydev->dev.of_node->full_name);
|
||||
+ dev_info->sfp_conn = sfp_conn;
|
||||
+ goto no_link;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ rx_signal_detect = phy_read(phydev, PMD_RX_SIGNAL_DETECT);
|
||||
+ if (rx_signal_detect < 0)
|
||||
+ return rx_signal_detect;
|
||||
+
|
||||
+ if ((rx_signal_detect & 1) == 0)
|
||||
+ goto no_link;
|
||||
+
|
||||
+ pcs_status = phy_read(phydev, BASER_PCS_STATUS);
|
||||
+ if (pcs_status < 0)
|
||||
+ return pcs_status;
|
||||
+
|
||||
+ if ((pcs_status & 1) == 0)
|
||||
+ goto no_link;
|
||||
+
|
||||
+ xgxs_lane_status = phy_read(phydev, XGXS_LANE_STATUS);
|
||||
+ if (xgxs_lane_status < 0)
|
||||
+ return xgxs_lane_status;
|
||||
+
|
||||
+ if ((xgxs_lane_status & 0x1000) == 0)
|
||||
+ goto no_link;
|
||||
+
|
||||
+ phydev->speed = 10000;
|
||||
+ phydev->link = 1;
|
||||
+ phydev->duplex = 1;
|
||||
+ return 0;
|
||||
+no_link:
|
||||
+ phydev->link = 0;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct of_device_id vsc848x_match[] = {
|
||||
+ {
|
||||
+ .compatible = "vitesse,vsc8488",
|
||||
+ },
|
||||
+ {
|
||||
+ .compatible = "vitesse,vsc8486",
|
||||
+ },
|
||||
+ {
|
||||
+ .compatible = "vitesse,vsc8484",
|
||||
+ },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, vsc848x_match);
|
||||
+
|
||||
+static struct phy_driver vsc848x_phy_driver = {
|
||||
+ .phy_id = 0x00070400,
|
||||
+ .phy_id_mask = 0xfffffff0,
|
||||
+ .name = "Vitesse VSC848X",
|
||||
+ .config_init = vsc848x_config_init,
|
||||
+ .probe = vsc848x_probe,
|
||||
+ .remove = vsc848x_remove,
|
||||
+ .config_aneg = vsc848x_config_aneg,
|
||||
+ .read_status = vsc848x_read_status,
|
||||
+ .driver = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .of_match_table = vsc848x_match,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+/* Phy nexus support below. */
|
||||
+
|
||||
+static int vsc848x_nexus_read(struct mii_bus *bus, int phy_id, int regnum)
|
||||
+{
|
||||
+ struct vsc848x_nexus_mdiobus *p = bus->priv;
|
||||
+ return p->parent_mii_bus->read(p->parent_mii_bus,
|
||||
+ phy_id + p->reg_offset,
|
||||
+ regnum);
|
||||
+}
|
||||
+
|
||||
+static int vsc848x_nexus_write(struct mii_bus *bus, int phy_id,
|
||||
+ int regnum, u16 val)
|
||||
+{
|
||||
+ struct vsc848x_nexus_mdiobus *p = bus->priv;
|
||||
+ return p->parent_mii_bus->write(p->parent_mii_bus,
|
||||
+ phy_id + p->reg_offset,
|
||||
+ regnum, val);
|
||||
+}
|
||||
+
|
||||
+static int vsc848x_nexus_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct vsc848x_nexus_mdiobus *bus;
|
||||
+ const char *bus_id;
|
||||
+ int len;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
|
||||
+ if (!bus)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ bus->parent_mii_bus = container_of(pdev->dev.parent,
|
||||
+ struct mii_bus, dev);
|
||||
+
|
||||
+ /* The PHY nexux must have a reg property in the range [0-31] */
|
||||
+ err = of_property_read_u32(pdev->dev.of_node, "reg", &bus->reg_offset);
|
||||
+ if (err) {
|
||||
+ dev_err(&pdev->dev, "%s has invalid PHY address\n",
|
||||
+ pdev->dev.of_node->full_name);
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ bus->mii_bus = mdiobus_alloc();
|
||||
+ if (!bus->mii_bus)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ bus->mii_bus->priv = bus;
|
||||
+ bus->mii_bus->irq = bus->phy_irq;
|
||||
+ bus->mii_bus->name = "vsc848x_nexus";
|
||||
+ bus_id = bus->parent_mii_bus->id;
|
||||
+ len = strlen(bus_id);
|
||||
+ if (len > MII_BUS_ID_SIZE - 4)
|
||||
+ bus_id += len - (MII_BUS_ID_SIZE - 4);
|
||||
+ snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%s:%02x",
|
||||
+ bus_id, bus->reg_offset);
|
||||
+ bus->mii_bus->parent = &pdev->dev;
|
||||
+
|
||||
+ bus->mii_bus->read = vsc848x_nexus_read;
|
||||
+ bus->mii_bus->write = vsc848x_nexus_write;
|
||||
+ mutex_init(&bus->lock);
|
||||
+
|
||||
+ dev_set_drvdata(&pdev->dev, bus);
|
||||
+
|
||||
+ err = of_mdiobus_register(bus->mii_bus, pdev->dev.of_node);
|
||||
+ if (err) {
|
||||
+ dev_err(&pdev->dev, "Error registering with device tree\n");
|
||||
+ goto fail_register;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+fail_register:
|
||||
+ dev_err(&pdev->dev, "Failed to register\n");
|
||||
+ mdiobus_free(bus->mii_bus);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int vsc848x_nexus_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct of_device_id vsc848x_nexus_match[] = {
|
||||
+ {
|
||||
+ .compatible = "vitesse,vsc8488-nexus",
|
||||
+ },
|
||||
+ {
|
||||
+ .compatible = "vitesse,vsc8486-nexus",
|
||||
+ },
|
||||
+ {
|
||||
+ .compatible = "vitesse,vsc8484-nexus",
|
||||
+ },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, vsc848x_nexus_match);
|
||||
+
|
||||
+static struct platform_driver vsc848x_nexus_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "vsc848x-nexus",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .of_match_table = vsc848x_nexus_match,
|
||||
+ },
|
||||
+ .probe = vsc848x_nexus_probe,
|
||||
+ .remove = vsc848x_nexus_remove,
|
||||
+};
|
||||
+
|
||||
+static int __init vsc848x_mod_init(void)
|
||||
+{
|
||||
+ int rv;
|
||||
+
|
||||
+ rv = platform_driver_register(&vsc848x_nexus_driver);
|
||||
+ if (rv)
|
||||
+ return rv;
|
||||
+
|
||||
+ rv = phy_driver_register(&vsc848x_phy_driver);
|
||||
+
|
||||
+ return rv;
|
||||
+}
|
||||
+module_init(vsc848x_mod_init);
|
||||
+
|
||||
+static void __exit vsc848x_mod_exit(void)
|
||||
+{
|
||||
+ phy_driver_unregister(&vsc848x_phy_driver);
|
||||
+ platform_driver_unregister(&vsc848x_nexus_driver);
|
||||
+}
|
||||
+module_exit(vsc848x_mod_exit);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Driver for Vitesse VSC848X PHY");
|
||||
+MODULE_AUTHOR("David Daney and Aaron Williams");
|
||||
+MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,310 @@
|
||||
From: Abhishek Paliwal <abhishek.paliwal@aricent.com>
|
||||
Date: Fri, 13 Feb 2015 12:47:36 +0530
|
||||
Subject: of: Add of_memory_accessor to map device tree node to memory accessor
|
||||
functions.
|
||||
|
||||
From: Aaron Williams <aaron.williams@cavium.com>
|
||||
|
||||
Currently there is no easy way to map a device tree node to a memory
|
||||
accessor function for devices like I2C EEPROMs. For example, the Vitesse
|
||||
vsc848x 10G PHY driver needs to be able to use the I2C at24 serial EEPROM
|
||||
memory accessor function in order to read the SFP+ eeprom.
|
||||
|
||||
This provides a way where the vsc848x module can parse its device tree and
|
||||
easily gain the accessor functions for the eeprom through a phandle.
|
||||
|
||||
This may be useful for any module which provides memory accessor functions.
|
||||
|
||||
Signed-off-by: Aaron Williams <aaron.williams@cavium.com>
|
||||
Signed-off-by: Leonid Rosenboim <lrosenboim@caviumnetworks.com>
|
||||
Signed-off-by: Abhishek Paliwal <abhishek.paliwal@aricent.com>
|
||||
--- a/drivers/of/Kconfig
|
||||
+++ b/drivers/of/Kconfig
|
||||
@@ -107,4 +107,10 @@
|
||||
# arches should select this if DMA is coherent by default for OF devices
|
||||
bool
|
||||
|
||||
+config OF_MEMORY_ACCESSOR
|
||||
+ def_bool y
|
||||
+ help
|
||||
+ OpenFirmware memory accessor support for accessing devices like
|
||||
+ i2c and SPI eeproms.
|
||||
+
|
||||
endif # OF
|
||||
|
||||
--- a/drivers/of/Makefile
|
||||
+++ b/drivers/of/Makefile
|
||||
@@ -16,3 +16,4 @@
|
||||
obj-$(CONFIG_OF_NUMA) += of_numa.o
|
||||
|
||||
obj-$(CONFIG_OF_UNITTEST) += unittest-data/
|
||||
+obj-$(CONFIG_OF_MEMORY_ACCESSOR) += of_memory_accessor.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/of/of_memory_accessor.c
|
||||
@@ -0,0 +1,192 @@
|
||||
+/*
|
||||
+ * Memory accessor OF helpers
|
||||
+ *
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2012 Cavium Inc.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/mutex.h>
|
||||
+#include <linux/mod_devicetable.h>
|
||||
+#include <linux/of_memory_accessor.h>
|
||||
+#include <linux/list.h>
|
||||
+#include <linux/memory.h>
|
||||
+
|
||||
+struct of_macc_entry {
|
||||
+ struct list_head list;
|
||||
+ struct device *dev;
|
||||
+ struct memory_accessor *macc;
|
||||
+ int ref;
|
||||
+};
|
||||
+
|
||||
+static DEFINE_MUTEX(lock);
|
||||
+static LIST_HEAD(macc_list);
|
||||
+
|
||||
+/**
|
||||
+ * Adds a mapping of a device node to a memory accessor
|
||||
+ *
|
||||
+ * @param[in] dev - device
|
||||
+ * @param[in] macc - memory accessor
|
||||
+ *
|
||||
+ * @returns 0 for success or -ENOMEM
|
||||
+ */
|
||||
+int of_memory_accessor_register(struct device *dev,
|
||||
+ struct memory_accessor *macc)
|
||||
+{
|
||||
+ struct of_macc_entry *mentry;
|
||||
+
|
||||
+ mentry = kmalloc(sizeof(*mentry), GFP_KERNEL);
|
||||
+ if (mentry == NULL)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ mentry->dev = dev;
|
||||
+ mentry->macc = macc;
|
||||
+ mentry->ref = 0;
|
||||
+
|
||||
+ mutex_lock(&lock);
|
||||
+
|
||||
+ list_add(&(mentry->list), &macc_list);
|
||||
+
|
||||
+ mutex_unlock(&lock);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL(of_memory_accessor_register);
|
||||
+
|
||||
+/**
|
||||
+ * removes the mapping of a device node to a memory accessor
|
||||
+ *
|
||||
+ * @param[in] devnode - device node to remove
|
||||
+ *
|
||||
+ * @returns 0 for success or -ENODEV if device node not found, -EBUSY if still
|
||||
+ * in use
|
||||
+ */
|
||||
+
|
||||
+int of_memory_accessor_remove(struct device *dev)
|
||||
+{
|
||||
+ struct of_macc_entry *mentry;
|
||||
+ struct list_head *pos, *q;
|
||||
+ int ret = -ENODEV;
|
||||
+
|
||||
+ mutex_lock(&lock);
|
||||
+
|
||||
+ list_for_each_safe(pos, q, &macc_list) {
|
||||
+ mentry = list_entry(pos, struct of_macc_entry, list);
|
||||
+ if (mentry->dev == dev) {
|
||||
+ if (mentry->ref > 0) {
|
||||
+ ret = -EBUSY;
|
||||
+ goto done;
|
||||
+ }
|
||||
+ list_del(pos);
|
||||
+ kfree(mentry);
|
||||
+ ret = 0;
|
||||
+ goto done;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Not found */
|
||||
+done:
|
||||
+ mutex_unlock(&lock);
|
||||
+ return ret;
|
||||
+}
|
||||
+EXPORT_SYMBOL(of_memory_accessor_remove);
|
||||
+
|
||||
+/**
|
||||
+ * Returns the memory accessor for a device node and increments a reference
|
||||
+ * count
|
||||
+ *
|
||||
+ * @param[in] devnode - device node to look up
|
||||
+ *
|
||||
+ * @returns memory accessor for device node or NULL if none found.
|
||||
+ */
|
||||
+struct memory_accessor *
|
||||
+of_memory_accessor_get(const struct device_node *devnode)
|
||||
+{
|
||||
+ struct of_macc_entry *mentry;
|
||||
+ struct list_head *pos;
|
||||
+ struct memory_accessor *macc = NULL;
|
||||
+
|
||||
+ mutex_lock(&lock);
|
||||
+
|
||||
+ list_for_each(pos, &macc_list) {
|
||||
+ mentry = list_entry(pos, struct of_macc_entry, list);
|
||||
+ if (mentry->dev->of_node == devnode) {
|
||||
+ macc = mentry->macc;
|
||||
+ if (!mentry->ref) {
|
||||
+ if (!try_module_get(mentry->dev->driver->owner)) {
|
||||
+ macc = NULL;
|
||||
+ pr_info("Warning: module for %s not found!",
|
||||
+ mentry->dev->of_node->full_name);
|
||||
+ }
|
||||
+ }
|
||||
+ mentry->ref++;
|
||||
+ goto done;
|
||||
+ }
|
||||
+ }
|
||||
+done:
|
||||
+ mutex_unlock(&lock);
|
||||
+ return macc;
|
||||
+}
|
||||
+EXPORT_SYMBOL(of_memory_accessor_get);
|
||||
+
|
||||
+/**
|
||||
+ * Decrements the reference count for the memory accessor attached to the
|
||||
+ * device node.
|
||||
+ *
|
||||
+ * @param[in] devnode - device node to look up
|
||||
+ *
|
||||
+ * @returns 0 for success or -ENODEV if the device node was not found.
|
||||
+ */
|
||||
+int of_memory_accessor_put(const struct device_node *devnode)
|
||||
+{
|
||||
+ struct of_macc_entry *mentry;
|
||||
+ struct list_head *pos;
|
||||
+ int ret = -ENODEV;
|
||||
+
|
||||
+ mutex_lock(&lock);
|
||||
+ list_for_each(pos, &macc_list) {
|
||||
+ mentry = list_entry(pos, struct of_macc_entry, list);
|
||||
+ if (mentry->dev->of_node == devnode) {
|
||||
+ if (mentry->ref > 0)
|
||||
+ mentry->ref--;
|
||||
+ if (!mentry->ref)
|
||||
+ module_put(mentry->dev->driver->owner);
|
||||
+
|
||||
+ module_put(THIS_MODULE);
|
||||
+ ret = 0;
|
||||
+ goto done;
|
||||
+ }
|
||||
+ }
|
||||
+done:
|
||||
+ mutex_unlock(&lock);
|
||||
+ return ret;
|
||||
+}
|
||||
+EXPORT_SYMBOL(of_memory_accessor_put);
|
||||
+
|
||||
+static void __exit of_memory_accessor_exit(void)
|
||||
+{
|
||||
+ struct of_macc_entry *mentry;
|
||||
+ struct list_head *pos, *q;
|
||||
+
|
||||
+ list_for_each_safe(pos, q, &macc_list) {
|
||||
+ mentry = list_entry(pos, struct of_macc_entry, list);
|
||||
+ if (mentry->ref)
|
||||
+ module_put(mentry->dev->driver->owner);
|
||||
+ list_del(pos);
|
||||
+ kfree(mentry);
|
||||
+ }
|
||||
+
|
||||
+ /* Not found */
|
||||
+ mutex_destroy(&lock);
|
||||
+ list_del(&macc_list);
|
||||
+}
|
||||
+module_exit(of_memory_accessor_exit);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Driver for mapping device nodes to memory accessors");
|
||||
+MODULE_AUTHOR("Aaron Williams");
|
||||
+MODULE_LICENSE("GPL");
|
||||
--- /dev/null
|
||||
+++ b/include/linux/of_memory_accessor.h
|
||||
@@ -0,0 +1,71 @@
|
||||
+#ifndef _LINUX_OF_MEMORY_ACCESSOR_H
|
||||
+#define _LINUX_OF_MEMORY_ACCESSOR_H
|
||||
+/*
|
||||
+ * Memory accessor OF helpers
|
||||
+ *
|
||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
||||
+ * License. See the file "COPYING" in the main directory of this archive
|
||||
+ * for more details.
|
||||
+ *
|
||||
+ * Copyright (C) 2012 Cavium Inc.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/memory.h>
|
||||
+
|
||||
+/**
|
||||
+ * Adds a mapping of a device node to a memory accessor
|
||||
+ *
|
||||
+ * @param[in] dev - device
|
||||
+ * @param[in] macc - memory accessor
|
||||
+ *
|
||||
+ * @returns 0 for success or -ENOMEM
|
||||
+ */
|
||||
+#ifdef CONFIG_OF_MEMORY_ACCESSOR
|
||||
+int of_memory_accessor_register(struct device *dev,
|
||||
+ struct memory_accessor *macc);
|
||||
+#else
|
||||
+static inline int of_memory_accessor_register(struct device *dev,
|
||||
+ struct memory_accessor *macc)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+/**
|
||||
+ * removes the mapping of a device node to a memory accessor
|
||||
+ *
|
||||
+ * @param[in] devnode - device node to remove
|
||||
+ *
|
||||
+ * @returns 0 for success or 1 if device node not found
|
||||
+ */
|
||||
+#ifdef CONFIG_OF_MEMORY_ACCESSOR
|
||||
+int of_memory_accessor_remove(struct device *dev);
|
||||
+#else
|
||||
+static inline int of_memory_accessor_remove(struct device *dev)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+/**
|
||||
+ * Returns the memory accessor for a device node
|
||||
+ *
|
||||
+ * @param[in] devnode - device node to look up
|
||||
+ *
|
||||
+ * @returns memory accessor for device node or NULL if none found.
|
||||
+ */
|
||||
+struct memory_accessor *
|
||||
+of_memory_accessor_get(const struct device_node *devnode);
|
||||
+
|
||||
+/**
|
||||
+ * Decrements the reference count for the memory accessor attached to the
|
||||
+ * device node.
|
||||
+ *
|
||||
+ * @param[in] devnode - device node to look up
|
||||
+ *
|
||||
+ * @returns 0 for success or -1 if the device node was not found.
|
||||
+ */
|
||||
+int of_memory_accessor_put(const struct device_node *devnode);
|
||||
+
|
||||
+#endif /* _LINUX_OF_MEMORY_ACCESSOR_H */
|
||||
@@ -0,0 +1,42 @@
|
||||
From: Abhishek Paliwal <abhishek.paliwal@aricent.com>
|
||||
Date: Fri, 13 Feb 2015 12:48:16 +0530
|
||||
Subject: misc/at24: Register memory accessor functions with of_memory_accessor
|
||||
|
||||
From: Aaron Williams <aaron.williams@cavium.com>
|
||||
|
||||
The at24 module will now register its memory accessor functions with its
|
||||
device tree entry so that other modules may call these functions based on
|
||||
the device tree node.
|
||||
|
||||
Signed-off-by: Aaron Williams <aaron.williams@cavium.com>
|
||||
Signed-off-by: Leonid Rosenboim <lrosenboim@caviumnetworks.com>
|
||||
Signed-off-by: Abhishek Paliwal <abhishek.paliwal@aricent.com>
|
||||
--- a/drivers/misc/eeprom/at24.c
|
||||
+++ b/drivers/misc/eeprom/at24.c
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
+#include <linux/of_memory_accessor.h>
|
||||
|
||||
/* Address pointer is 16 bit. */
|
||||
#define AT24_FLAG_ADDR16 BIT(7)
|
||||
@@ -720,6 +721,9 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
byte_len, client->name,
|
||||
writable ? "writable" : "read-only", at24->write_max);
|
||||
|
||||
+ if (client->dev.of_node)
|
||||
+ of_memory_accessor_register(&client->dev, &at24->macc);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -728,5 +732,8 @@ static int at24_remove(struct i2c_client *client)
|
||||
pm_runtime_disable(&client->dev);
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
|
||||
+ if (client->dev.of_node)
|
||||
+ of_memory_accessor_remove(&client->dev);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
--- a/drivers/staging/octeon/ethernet.c
|
||||
+++ b/drivers/staging/octeon/ethernet.c
|
||||
@@ -860,8 +860,10 @@ static int cvm_oct_probe(struct platform_device *pdev)
|
||||
break;
|
||||
|
||||
case CVMX_HELPER_INTERFACE_MODE_XAUI:
|
||||
- dev->netdev_ops = &cvm_oct_xaui_netdev_ops;
|
||||
- strscpy(dev->name, "xaui%d", sizeof(dev->name));
|
||||
+ if (0) { //of_device_is_available(priv->of_node)) {
|
||||
+ dev->netdev_ops = &cvm_oct_xaui_netdev_ops;
|
||||
+ strscpy(dev->name, "xaui%d", sizeof(dev->name));
|
||||
+ }
|
||||
break;
|
||||
|
||||
case CVMX_HELPER_INTERFACE_MODE_LOOP:
|
||||
79
target/linux/octeon/patches-5.4/703-debug-it-all.patch
Normal file
79
target/linux/octeon/patches-5.4/703-debug-it-all.patch
Normal file
@@ -0,0 +1,79 @@
|
||||
--- a/arch/mips/cavium-octeon/executive/cvmx-helper.c
|
||||
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper.c
|
||||
@@ -1041,12 +1041,14 @@ int cvmx_helper_initialize_packet_io_global(void)
|
||||
result |= __cvmx_helper_interface_setup_ipd(interface);
|
||||
result |= __cvmx_helper_interface_setup_pko(interface);
|
||||
}
|
||||
-
|
||||
+ cvmx_dprintf("Gets past end of interfaces setup\n");
|
||||
result |= __cvmx_helper_global_setup_ipd();
|
||||
result |= __cvmx_helper_global_setup_pko();
|
||||
|
||||
+ cvmx_dprintf("Sets up global helpers\n");
|
||||
/* Enable any flow control and backpressure */
|
||||
result |= __cvmx_helper_global_setup_backpressure();
|
||||
+ cvmx_dprintf("Sets up backpressure helpers\n");
|
||||
|
||||
#if CVMX_HELPER_ENABLE_IPD
|
||||
result |= cvmx_helper_ipd_and_packet_input_enable();
|
||||
--- a/drivers/staging/octeon/ethernet.c
|
||||
+++ b/drivers/staging/octeon/ethernet.c
|
||||
@@ -700,6 +700,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
|
||||
cvm_oct_configure_common_hw();
|
||||
|
||||
cvmx_helper_initialize_packet_io_global();
|
||||
+ pr_err("OK, we got out of packet_io_global()\n");
|
||||
|
||||
if (receive_group_order) {
|
||||
if (receive_group_order > 4)
|
||||
@@ -709,9 +710,11 @@ static int cvm_oct_probe(struct platform_device *pdev)
|
||||
pow_receive_groups = BIT(pow_receive_group);
|
||||
}
|
||||
|
||||
+ pr_err("We got through receive_group_order\n");
|
||||
/* Change the input group for all ports before input is enabled */
|
||||
num_interfaces = cvmx_helper_get_number_of_interfaces();
|
||||
for (interface = 0; interface < num_interfaces; interface++) {
|
||||
+ pr_err("We are starting on interface %d\n", interface);
|
||||
int num_ports = cvmx_helper_ports_on_interface(interface);
|
||||
int port;
|
||||
|
||||
@@ -752,14 +755,14 @@ static int cvm_oct_probe(struct platform_device *pdev)
|
||||
pip_prt_tagx.s.grptag = 0;
|
||||
pip_prt_tagx.s.grp = pow_receive_group;
|
||||
}
|
||||
-
|
||||
+ pr_err("COULD IT BE CSR WRITES???\n");
|
||||
cvmx_write_csr(CVMX_PIP_PRT_TAGX(port),
|
||||
pip_prt_tagx.u64);
|
||||
}
|
||||
}
|
||||
-
|
||||
+ pr_err("COULD it be cvmx_helper_ipd_and_packet_input_enable???\n");
|
||||
cvmx_helper_ipd_and_packet_input_enable();
|
||||
-
|
||||
+ pr_err("COULD it be this memset??\n");
|
||||
memset(cvm_oct_device, 0, sizeof(cvm_oct_device));
|
||||
|
||||
/*
|
||||
@@ -804,6 +807,7 @@ static int cvm_oct_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
+ pr_err("OK, we got THIS far, all the way to the interface init. Which is weird, we shoulda crashed by now\n");
|
||||
num_interfaces = cvmx_helper_get_number_of_interfaces();
|
||||
for (interface = 0; interface < num_interfaces; interface++) {
|
||||
cvmx_helper_interface_mode_t imode =
|
||||
@@ -860,8 +864,10 @@ static int cvm_oct_probe(struct platform_device *pdev)
|
||||
break;
|
||||
|
||||
case CVMX_HELPER_INTERFACE_MODE_XAUI:
|
||||
- dev->netdev_ops = &cvm_oct_xaui_netdev_ops;
|
||||
- strscpy(dev->name, "xaui%d", sizeof(dev->name));
|
||||
+ if (of_device_is_available(priv->of_node)) {
|
||||
+ dev->netdev_ops = &cvm_oct_xaui_netdev_ops;
|
||||
+ strscpy(dev->name, "xaui%d", sizeof(dev->name));
|
||||
+ }
|
||||
break;
|
||||
|
||||
case CVMX_HELPER_INTERFACE_MODE_LOOP:
|
||||
48
target/linux/octeon/patches-5.4/704-more-debugs.patch
Normal file
48
target/linux/octeon/patches-5.4/704-more-debugs.patch
Normal file
@@ -0,0 +1,48 @@
|
||||
--- a/arch/mips/cavium-octeon/executive/cvmx-helper.c
|
||||
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper.c
|
||||
@@ -971,6 +971,7 @@ int cvmx_helper_ipd_and_packet_input_enable(void)
|
||||
int interface;
|
||||
|
||||
/* Enable IPD */
|
||||
+ cvmx_dprintf("COULD IT BE cvmx_ipd_enable???\n");
|
||||
cvmx_ipd_enable();
|
||||
|
||||
/*
|
||||
@@ -978,13 +979,16 @@ int cvmx_helper_ipd_and_packet_input_enable(void)
|
||||
* that at this point IPD/PIP must be fully functional and PKO
|
||||
* must be disabled
|
||||
*/
|
||||
+ cvmx_dprintf("COULD IT BE getting no of interfaces????\n");
|
||||
num_interfaces = cvmx_helper_get_number_of_interfaces();
|
||||
for (interface = 0; interface < num_interfaces; interface++) {
|
||||
+ cvmx_dprintf("COULD IT BE interface # %d ??ces????\n", interface);
|
||||
if (cvmx_helper_ports_on_interface(interface) > 0)
|
||||
__cvmx_helper_packet_hardware_enable(interface);
|
||||
}
|
||||
|
||||
/* Finally enable PKO now that the entire path is up and running */
|
||||
+ cvmx_dprintf("COULD IT BE PKO???\n");
|
||||
cvmx_pko_enable();
|
||||
|
||||
if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1)
|
||||
--- a/arch/mips/include/asm/octeon/cvmx-ipd.h
|
||||
+++ b/arch/mips/include/asm/octeon/cvmx-ipd.h
|
||||
@@ -129,15 +129,18 @@ static inline void cvmx_ipd_config(uint64_t mbuff_size,
|
||||
static inline void cvmx_ipd_enable(void)
|
||||
{
|
||||
union cvmx_ipd_ctl_status ipd_reg;
|
||||
+ cvmx_dprintf("COULD IT BE THIS ONE CSR READ IN cvmx_ipd_enable ??\n");
|
||||
ipd_reg.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS);
|
||||
if (ipd_reg.s.ipd_en) {
|
||||
cvmx_dprintf
|
||||
("Warning: Enabling IPD when IPD already enabled.\n");
|
||||
}
|
||||
+ cvmx_dprintf("OK IT PASSED THE READ. BUT THERE'S THIS CVMX_ENABLE_LEN_M8_FIX THAT COULD APPLY??\n");
|
||||
ipd_reg.s.ipd_en = 1;
|
||||
#if CVMX_ENABLE_LEN_M8_FIX
|
||||
if (!OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2))
|
||||
ipd_reg.s.len_m8 = TRUE;
|
||||
#endif
|
||||
+ cvmx_dprintf("COULD IT BE THIS ONE CSR WRITE??? IN cvmx_ipd_enable ??\n");
|
||||
cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_reg.u64);
|
||||
}
|
||||
186
target/linux/octeon/patches-5.4/705-last-debugs.patch
Normal file
186
target/linux/octeon/patches-5.4/705-last-debugs.patch
Normal file
@@ -0,0 +1,186 @@
|
||||
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c b/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c
|
||||
index 93a498d05184..27733d710355 100644
|
||||
--- a/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c
|
||||
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-xaui.c
|
||||
@@ -121,58 +121,80 @@ int __cvmx_helper_xaui_enable(int interface)
|
||||
union cvmx_gmxx_tx_int_en gmx_tx_int_en;
|
||||
union cvmx_pcsxx_int_en_reg pcsx_int_en_reg;
|
||||
|
||||
+ cvmx_dprintf("COULD IT BE THE FEATURE CHECK FOR PKND??\n");
|
||||
/* Setup PKND */
|
||||
if (octeon_has_feature(OCTEON_FEATURE_PKND)) {
|
||||
+ cvmx_dprintf("COULD IT BE THE FIRST CSR READ??\n");
|
||||
gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
|
||||
+ cvmx_dprintf("COULD IT BE THE second CSR READ??\n");
|
||||
gmx_cfg.s.pknd = cvmx_helper_get_ipd_port(interface, 0);
|
||||
+ cvmx_dprintf("COULD IT BE THE third CSR /write READ??\n");
|
||||
cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
|
||||
}
|
||||
|
||||
/* (1) Interface has already been enabled. */
|
||||
|
||||
/* (2) Disable GMX. */
|
||||
+ cvmx_dprintf("step2 start!?? could it be the csr read??\n");
|
||||
xauiMiscCtl.u64 = cvmx_read_csr(CVMX_PCSXX_MISC_CTL_REG(interface));
|
||||
xauiMiscCtl.s.gmxeno = 1;
|
||||
+ cvmx_dprintf("step2 could it be the csr write to disable gmx??\n");
|
||||
cvmx_write_csr(CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64);
|
||||
|
||||
/* (3) Disable GMX and PCSX interrupts. */
|
||||
+ cvmx_dprintf("step3 start. could it be the csr read??\n");
|
||||
gmx_rx_int_en.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_EN(0, interface));
|
||||
+ cvmx_dprintf("step3 start. could it be the write for disabling interrupts???\n");
|
||||
cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(0, interface), 0x0);
|
||||
+ cvmx_dprintf("step3 start. could it be read for setting up the gmx_tx_int_en???\n");
|
||||
gmx_tx_int_en.u64 = cvmx_read_csr(CVMX_GMXX_TX_INT_EN(interface));
|
||||
+ cvmx_dprintf("step3 start. could it be the cvmx_gmxx write???\n");
|
||||
cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), 0x0);
|
||||
+ cvmx_dprintf("step3 start almost done. show up tell us about the PCSXX write???\n");
|
||||
pcsx_int_en_reg.u64 = cvmx_read_csr(CVMX_PCSXX_INT_EN_REG(interface));
|
||||
+ cvmx_dprintf("step3, this final csr write?\n");
|
||||
cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(interface), 0x0);
|
||||
|
||||
/* (4) Bring up the PCSX and GMX reconciliation layer. */
|
||||
/* (4)a Set polarity and lane swapping. */
|
||||
/* (4)b */
|
||||
+ cvmx_dprintf("4.1\n");
|
||||
gmxXauiTxCtl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface));
|
||||
/* Enable better IFG packing and improves performance */
|
||||
gmxXauiTxCtl.s.dic_en = 1;
|
||||
gmxXauiTxCtl.s.uni_en = 0;
|
||||
+ cvmx_dprintf("4.2\n");
|
||||
cvmx_write_csr(CVMX_GMXX_TX_XAUI_CTL(interface), gmxXauiTxCtl.u64);
|
||||
|
||||
/* (4)c Aply reset sequence */
|
||||
+ cvmx_dprintf("4.3\n");
|
||||
xauiCtl.u64 = cvmx_read_csr(CVMX_PCSXX_CONTROL1_REG(interface));
|
||||
xauiCtl.s.lo_pwr = 0;
|
||||
|
||||
/* Issuing a reset here seems to hang some CN68XX chips. */
|
||||
if (!OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_X) &&
|
||||
- !OCTEON_IS_MODEL(OCTEON_CN68XX_PASS2_X))
|
||||
+ !OCTEON_IS_MODEL(OCTEON_CN68XX_PASS2_X) &&
|
||||
+ 0)
|
||||
xauiCtl.s.reset = 1;
|
||||
|
||||
+ cvmx_dprintf("4.4\n");
|
||||
cvmx_write_csr(CVMX_PCSXX_CONTROL1_REG(interface), xauiCtl.u64);
|
||||
|
||||
+ cvmx_dprintf("4.5\n");
|
||||
/* Wait for PCS to come out of reset */
|
||||
if (CVMX_WAIT_FOR_FIELD64
|
||||
(CVMX_PCSXX_CONTROL1_REG(interface), union cvmx_pcsxx_control1_reg,
|
||||
reset, ==, 0, 10000))
|
||||
return -1;
|
||||
+
|
||||
+ cvmx_dprintf("4.6\n");
|
||||
/* Wait for PCS to be aligned */
|
||||
if (CVMX_WAIT_FOR_FIELD64
|
||||
(CVMX_PCSXX_10GBX_STATUS_REG(interface),
|
||||
union cvmx_pcsxx_10gbx_status_reg, alignd, ==, 1, 10000))
|
||||
return -1;
|
||||
+
|
||||
+ cvmx_dprintf("4.7\n");
|
||||
/* Wait for RX to be ready */
|
||||
if (CVMX_WAIT_FOR_FIELD64
|
||||
(CVMX_GMXX_RX_XAUI_CTL(interface), union cvmx_gmxx_rx_xaui_ctl,
|
||||
@@ -180,8 +202,11 @@ int __cvmx_helper_xaui_enable(int interface)
|
||||
return -1;
|
||||
|
||||
/* (6) Configure GMX */
|
||||
+ cvmx_dprintf("6.1\n");
|
||||
gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
|
||||
+
|
||||
gmx_cfg.s.en = 0;
|
||||
+ cvmx_dprintf("6.2\n");
|
||||
cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
|
||||
|
||||
/* Wait for GMX RX to be idle */
|
||||
@@ -189,62 +214,87 @@ int __cvmx_helper_xaui_enable(int interface)
|
||||
(CVMX_GMXX_PRTX_CFG(0, interface), union cvmx_gmxx_prtx_cfg,
|
||||
rx_idle, ==, 1, 10000))
|
||||
return -1;
|
||||
+ cvmx_dprintf("6.3\n");
|
||||
/* Wait for GMX TX to be idle */
|
||||
if (CVMX_WAIT_FOR_FIELD64
|
||||
(CVMX_GMXX_PRTX_CFG(0, interface), union cvmx_gmxx_prtx_cfg,
|
||||
tx_idle, ==, 1, 10000))
|
||||
return -1;
|
||||
|
||||
+ cvmx_dprintf("6.4\n");
|
||||
/* GMX configure */
|
||||
gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
|
||||
gmx_cfg.s.speed = 1;
|
||||
gmx_cfg.s.speed_msb = 0;
|
||||
gmx_cfg.s.slottime = 1;
|
||||
+ cvmx_dprintf("6.5\n");
|
||||
cvmx_write_csr(CVMX_GMXX_TX_PRTS(interface), 1);
|
||||
+ cvmx_dprintf("6.6\n");
|
||||
cvmx_write_csr(CVMX_GMXX_TXX_SLOT(0, interface), 512);
|
||||
+ cvmx_dprintf("6.7\n");
|
||||
cvmx_write_csr(CVMX_GMXX_TXX_BURST(0, interface), 8192);
|
||||
+ cvmx_dprintf("6.8\n");
|
||||
cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
|
||||
|
||||
/* (7) Clear out any error state */
|
||||
+ cvmx_dprintf("7.1\n");
|
||||
cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(0, interface),
|
||||
cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(0, interface)));
|
||||
+ cvmx_dprintf("7.2\n");
|
||||
cvmx_write_csr(CVMX_GMXX_TX_INT_REG(interface),
|
||||
cvmx_read_csr(CVMX_GMXX_TX_INT_REG(interface)));
|
||||
+ cvmx_dprintf("7.3\n");
|
||||
cvmx_write_csr(CVMX_PCSXX_INT_REG(interface),
|
||||
cvmx_read_csr(CVMX_PCSXX_INT_REG(interface)));
|
||||
|
||||
+ cvmx_dprintf("7.4\n");
|
||||
/* Wait for receive link */
|
||||
if (CVMX_WAIT_FOR_FIELD64
|
||||
(CVMX_PCSXX_STATUS1_REG(interface), union cvmx_pcsxx_status1_reg,
|
||||
rcv_lnk, ==, 1, 10000))
|
||||
return -1;
|
||||
+ cvmx_dprintf("7.5\n");
|
||||
if (CVMX_WAIT_FOR_FIELD64
|
||||
(CVMX_PCSXX_STATUS2_REG(interface), union cvmx_pcsxx_status2_reg,
|
||||
xmtflt, ==, 0, 10000))
|
||||
return -1;
|
||||
+ cvmx_dprintf("7.6\n");
|
||||
if (CVMX_WAIT_FOR_FIELD64
|
||||
(CVMX_PCSXX_STATUS2_REG(interface), union cvmx_pcsxx_status2_reg,
|
||||
rcvflt, ==, 0, 10000))
|
||||
return -1;
|
||||
|
||||
+ cvmx_dprintf("7.7\n");
|
||||
cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(0, interface), gmx_rx_int_en.u64);
|
||||
+ cvmx_dprintf("7.8\n");
|
||||
cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), gmx_tx_int_en.u64);
|
||||
+ cvmx_dprintf("7.9\n");
|
||||
cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(interface), pcsx_int_en_reg.u64);
|
||||
|
||||
/* (8) Enable packet reception */
|
||||
xauiMiscCtl.s.gmxeno = 0;
|
||||
+ cvmx_dprintf("8.1\n");
|
||||
cvmx_write_csr(CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64);
|
||||
|
||||
+ cvmx_dprintf("8.2\n");
|
||||
gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface));
|
||||
gmx_cfg.s.en = 1;
|
||||
+ cvmx_dprintf("8.3\n");
|
||||
cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64);
|
||||
|
||||
+ cvmx_dprintf("8.4\n");
|
||||
__cvmx_interrupt_pcsx_intx_en_reg_enable(0, interface);
|
||||
+ cvmx_dprintf("8.5\n");
|
||||
__cvmx_interrupt_pcsx_intx_en_reg_enable(1, interface);
|
||||
+ cvmx_dprintf("8.6\n");
|
||||
__cvmx_interrupt_pcsx_intx_en_reg_enable(2, interface);
|
||||
+ cvmx_dprintf("8.7\n");
|
||||
__cvmx_interrupt_pcsx_intx_en_reg_enable(3, interface);
|
||||
+ cvmx_dprintf("8.8\n");
|
||||
__cvmx_interrupt_pcsxx_int_en_reg_enable(interface);
|
||||
+ cvmx_dprintf("8.9\n");
|
||||
__cvmx_interrupt_gmxx_enable(interface);
|
||||
+ cvmx_dprintf("8.10\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user