Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / net / ethernet / samsung / sxgbe / sxgbe_xpcs.c
diff --git a/kernel/drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.c b/kernel/drivers/net/ethernet/samsung/sxgbe/sxgbe_xpcs.c
new file mode 100644 (file)
index 0000000..51c3219
--- /dev/null
@@ -0,0 +1,91 @@
+/* 10G controller driver for Samsung SoCs
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Author: Siva Reddy Kallam <siva.kallam@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include "sxgbe_common.h"
+#include "sxgbe_xpcs.h"
+
+static int sxgbe_xpcs_read(struct net_device *ndev, unsigned int reg)
+{
+       u32 value;
+       struct sxgbe_priv_data *priv = netdev_priv(ndev);
+
+       value = readl(priv->ioaddr + XPCS_OFFSET + reg);
+
+       return value;
+}
+
+static int sxgbe_xpcs_write(struct net_device *ndev, int reg, int data)
+{
+       struct sxgbe_priv_data *priv = netdev_priv(ndev);
+
+       writel(data, priv->ioaddr + XPCS_OFFSET + reg);
+
+       return 0;
+}
+
+int sxgbe_xpcs_init(struct net_device *ndev)
+{
+       u32 value;
+
+       value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1);
+       /* 10G XAUI mode */
+       sxgbe_xpcs_write(ndev, SR_PCS_CONTROL2, XPCS_TYPE_SEL_X);
+       sxgbe_xpcs_write(ndev, VR_PCS_MMD_XAUI_MODE_CONTROL, XPCS_XAUI_MODE);
+       sxgbe_xpcs_write(ndev, VR_PCS_MMD_XAUI_MODE_CONTROL, value | BIT(13));
+       sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value | BIT(11));
+
+       do {
+               value = sxgbe_xpcs_read(ndev, VR_PCS_MMD_DIGITAL_STATUS);
+       } while ((value & XPCS_QSEQ_STATE_MPLLOFF) == XPCS_QSEQ_STATE_STABLE);
+
+       value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1);
+       sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value & ~BIT(11));
+
+       do {
+               value = sxgbe_xpcs_read(ndev, VR_PCS_MMD_DIGITAL_STATUS);
+       } while ((value & XPCS_QSEQ_STATE_MPLLOFF) != XPCS_QSEQ_STATE_STABLE);
+
+       return 0;
+}
+
+int sxgbe_xpcs_init_1G(struct net_device *ndev)
+{
+       int value;
+
+       /* 10GBASE-X PCS (1G) mode */
+       sxgbe_xpcs_write(ndev, SR_PCS_CONTROL2, XPCS_TYPE_SEL_X);
+       sxgbe_xpcs_write(ndev, VR_PCS_MMD_XAUI_MODE_CONTROL, XPCS_XAUI_MODE);
+       value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1);
+       sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value & ~BIT(13));
+
+       value = sxgbe_xpcs_read(ndev, SR_MII_MMD_CONTROL);
+       sxgbe_xpcs_write(ndev, SR_MII_MMD_CONTROL, value | BIT(6));
+       sxgbe_xpcs_write(ndev, SR_MII_MMD_CONTROL, value & ~BIT(13));
+       value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1);
+       sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value | BIT(11));
+
+       do {
+               value = sxgbe_xpcs_read(ndev, VR_PCS_MMD_DIGITAL_STATUS);
+       } while ((value & XPCS_QSEQ_STATE_MPLLOFF) != XPCS_QSEQ_STATE_STABLE);
+
+       value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1);
+       sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value & ~BIT(11));
+
+       /* Auto Negotiation cluase 37 enable */
+       value = sxgbe_xpcs_read(ndev, SR_MII_MMD_CONTROL);
+       sxgbe_xpcs_write(ndev, SR_MII_MMD_CONTROL, value | BIT(12));
+
+       return 0;
+}