MIPS: octeon: Add interface mode detection for Octeon II
authorAlex Smith <alex.smith@imgtec.com>
Thu, 29 May 2014 10:10:01 +0000 (11:10 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Thu, 29 May 2014 21:02:42 +0000 (23:02 +0200)
Add interface mode detection for Octeon II. This is necessary to detect
the interface modes correctly on the UBNT E200 board. Code is taken
from the UBNT GPL source release, with some alterations: SRIO, ILK and
RXAUI interface modes are removed and instead return disabled as these
modes are not currently supported.

Signed-off-by: Alex Smith <alex.smith@imgtec.com>
Tested-by: David Daney <david.daney@cavium.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/7039/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/cavium-octeon/executive/cvmx-helper.c

index 8553ad5c72b61f7f5d2d9ad5c5c719977aad66f8..7e5cf7a5e2f3264b637e820dca92635d468e7465 100644 (file)
@@ -105,6 +105,158 @@ int cvmx_helper_ports_on_interface(int interface)
 }
 EXPORT_SYMBOL_GPL(cvmx_helper_ports_on_interface);
 
+/**
+ * @INTERNAL
+ * Return interface mode for CN68xx.
+ */
+static cvmx_helper_interface_mode_t __cvmx_get_mode_cn68xx(int interface)
+{
+       union cvmx_mio_qlmx_cfg qlm_cfg;
+       switch (interface) {
+       case 0:
+               qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
+               /* QLM is disabled when QLM SPD is 15. */
+               if (qlm_cfg.s.qlm_spd == 15)
+                       return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+
+               if (qlm_cfg.s.qlm_cfg == 2)
+                       return CVMX_HELPER_INTERFACE_MODE_SGMII;
+               else if (qlm_cfg.s.qlm_cfg == 3)
+                       return CVMX_HELPER_INTERFACE_MODE_XAUI;
+               else
+                       return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+       case 2:
+       case 3:
+       case 4:
+               qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(interface));
+               /* QLM is disabled when QLM SPD is 15. */
+               if (qlm_cfg.s.qlm_spd == 15)
+                       return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+
+               if (qlm_cfg.s.qlm_cfg == 2)
+                       return CVMX_HELPER_INTERFACE_MODE_SGMII;
+               else if (qlm_cfg.s.qlm_cfg == 3)
+                       return CVMX_HELPER_INTERFACE_MODE_XAUI;
+               else
+                       return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+       case 7:
+               qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(3));
+               /* QLM is disabled when QLM SPD is 15. */
+               if (qlm_cfg.s.qlm_spd == 15) {
+                       return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+               } else if (qlm_cfg.s.qlm_cfg != 0) {
+                       qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
+                       if (qlm_cfg.s.qlm_cfg != 0)
+                               return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+               }
+               return CVMX_HELPER_INTERFACE_MODE_NPI;
+       case 8:
+               return CVMX_HELPER_INTERFACE_MODE_LOOP;
+       default:
+               return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+       }
+}
+
+/**
+ * @INTERNAL
+ * Return interface mode for an Octeon II
+ */
+static cvmx_helper_interface_mode_t __cvmx_get_mode_octeon2(int interface)
+{
+       union cvmx_gmxx_inf_mode mode;
+
+       if (OCTEON_IS_MODEL(OCTEON_CN68XX))
+               return __cvmx_get_mode_cn68xx(interface);
+
+       if (interface == 2)
+               return CVMX_HELPER_INTERFACE_MODE_NPI;
+
+       if (interface == 3)
+               return CVMX_HELPER_INTERFACE_MODE_LOOP;
+
+       /* Only present in CN63XX & CN66XX Octeon model */
+       if ((OCTEON_IS_MODEL(OCTEON_CN63XX) &&
+            (interface == 4 || interface == 5)) ||
+           (OCTEON_IS_MODEL(OCTEON_CN66XX) &&
+            interface >= 4 && interface <= 7)) {
+               return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+       }
+
+       if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {
+               union cvmx_mio_qlmx_cfg mio_qlm_cfg;
+
+               /* QLM2 is SGMII0 and QLM1 is SGMII1 */
+               if (interface == 0)
+                       mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
+               else if (interface == 1)
+                       mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
+               else
+                       return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+
+               if (mio_qlm_cfg.s.qlm_spd == 15)
+                       return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+
+               if (mio_qlm_cfg.s.qlm_cfg == 9)
+                       return CVMX_HELPER_INTERFACE_MODE_SGMII;
+               else if (mio_qlm_cfg.s.qlm_cfg == 11)
+                       return CVMX_HELPER_INTERFACE_MODE_XAUI;
+               else
+                       return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+       } else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) {
+               union cvmx_mio_qlmx_cfg qlm_cfg;
+
+               if (interface == 0) {
+                       qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
+                       if (qlm_cfg.s.qlm_cfg == 2)
+                               return CVMX_HELPER_INTERFACE_MODE_SGMII;
+                       else if (qlm_cfg.s.qlm_cfg == 3)
+                               return CVMX_HELPER_INTERFACE_MODE_XAUI;
+                       else
+                               return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+               } else if (interface == 1) {
+                       qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
+                       if (qlm_cfg.s.qlm_cfg == 2)
+                               return CVMX_HELPER_INTERFACE_MODE_SGMII;
+                       else if (qlm_cfg.s.qlm_cfg == 3)
+                               return CVMX_HELPER_INTERFACE_MODE_XAUI;
+                       else
+                               return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+               }
+       } else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) {
+               if (interface == 0) {
+                       union cvmx_mio_qlmx_cfg qlm_cfg;
+                       qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
+                       if (qlm_cfg.s.qlm_cfg == 2)
+                               return CVMX_HELPER_INTERFACE_MODE_SGMII;
+               }
+               return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+       }
+
+       if (interface == 1 && OCTEON_IS_MODEL(OCTEON_CN63XX))
+               return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+
+       mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
+
+       if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {
+               switch (mode.cn63xx.mode) {
+               case 0:
+                       return CVMX_HELPER_INTERFACE_MODE_SGMII;
+               case 1:
+                       return CVMX_HELPER_INTERFACE_MODE_XAUI;
+               default:
+                       return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+               }
+       } else {
+               if (!mode.s.en)
+                       return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+
+               if (mode.s.type)
+                       return CVMX_HELPER_INTERFACE_MODE_GMII;
+               else
+                       return CVMX_HELPER_INTERFACE_MODE_RGMII;
+       }
+}
+
 /**
  * Get the operating mode of an interface. Depending on the Octeon
  * chip and configuration, this function returns an enumeration
@@ -118,6 +270,20 @@ EXPORT_SYMBOL_GPL(cvmx_helper_ports_on_interface);
 cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)
 {
        union cvmx_gmxx_inf_mode mode;
+
+       if (interface < 0 ||
+           interface >= cvmx_helper_get_number_of_interfaces())
+               return CVMX_HELPER_INTERFACE_MODE_DISABLED;
+
+       /*
+        * Octeon II models
+        */
+       if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))
+               return __cvmx_get_mode_octeon2(interface);
+
+       /*
+        * Octeon and Octeon Plus models
+        */
        if (interface == 2)
                return CVMX_HELPER_INTERFACE_MODE_NPI;