1 /* 10G controller driver for Samsung SoCs
2  *
3  * Copyright (C) 2013 Samsung Electronics Co., Ltd.
4  *		http://www.samsung.com
5  *
6  * Author: Siva Reddy Kallam <siva.kallam@samsung.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12 #include <linux/bitops.h>
13 #include <linux/kernel.h>
14 #include <linux/netdevice.h>
15 #include <linux/phy.h>
16 #include "sxgbe_common.h"
17 #include "sxgbe_xpcs.h"
18 
sxgbe_xpcs_read(struct net_device * ndev,unsigned int reg)19 static int sxgbe_xpcs_read(struct net_device *ndev, unsigned int reg)
20 {
21 	u32 value;
22 	struct sxgbe_priv_data *priv = netdev_priv(ndev);
23 
24 	value = readl(priv->ioaddr + XPCS_OFFSET + reg);
25 
26 	return value;
27 }
28 
sxgbe_xpcs_write(struct net_device * ndev,int reg,int data)29 static int sxgbe_xpcs_write(struct net_device *ndev, int reg, int data)
30 {
31 	struct sxgbe_priv_data *priv = netdev_priv(ndev);
32 
33 	writel(data, priv->ioaddr + XPCS_OFFSET + reg);
34 
35 	return 0;
36 }
37 
sxgbe_xpcs_init(struct net_device * ndev)38 int sxgbe_xpcs_init(struct net_device *ndev)
39 {
40 	u32 value;
41 
42 	value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1);
43 	/* 10G XAUI mode */
44 	sxgbe_xpcs_write(ndev, SR_PCS_CONTROL2, XPCS_TYPE_SEL_X);
45 	sxgbe_xpcs_write(ndev, VR_PCS_MMD_XAUI_MODE_CONTROL, XPCS_XAUI_MODE);
46 	sxgbe_xpcs_write(ndev, VR_PCS_MMD_XAUI_MODE_CONTROL, value | BIT(13));
47 	sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value | BIT(11));
48 
49 	do {
50 		value = sxgbe_xpcs_read(ndev, VR_PCS_MMD_DIGITAL_STATUS);
51 	} while ((value & XPCS_QSEQ_STATE_MPLLOFF) == XPCS_QSEQ_STATE_STABLE);
52 
53 	value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1);
54 	sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value & ~BIT(11));
55 
56 	do {
57 		value = sxgbe_xpcs_read(ndev, VR_PCS_MMD_DIGITAL_STATUS);
58 	} while ((value & XPCS_QSEQ_STATE_MPLLOFF) != XPCS_QSEQ_STATE_STABLE);
59 
60 	return 0;
61 }
62 
sxgbe_xpcs_init_1G(struct net_device * ndev)63 int sxgbe_xpcs_init_1G(struct net_device *ndev)
64 {
65 	int value;
66 
67 	/* 10GBASE-X PCS (1G) mode */
68 	sxgbe_xpcs_write(ndev, SR_PCS_CONTROL2, XPCS_TYPE_SEL_X);
69 	sxgbe_xpcs_write(ndev, VR_PCS_MMD_XAUI_MODE_CONTROL, XPCS_XAUI_MODE);
70 	value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1);
71 	sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value & ~BIT(13));
72 
73 	value = sxgbe_xpcs_read(ndev, SR_MII_MMD_CONTROL);
74 	sxgbe_xpcs_write(ndev, SR_MII_MMD_CONTROL, value | BIT(6));
75 	sxgbe_xpcs_write(ndev, SR_MII_MMD_CONTROL, value & ~BIT(13));
76 	value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1);
77 	sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value | BIT(11));
78 
79 	do {
80 		value = sxgbe_xpcs_read(ndev, VR_PCS_MMD_DIGITAL_STATUS);
81 	} while ((value & XPCS_QSEQ_STATE_MPLLOFF) != XPCS_QSEQ_STATE_STABLE);
82 
83 	value = sxgbe_xpcs_read(ndev, SR_PCS_MMD_CONTROL1);
84 	sxgbe_xpcs_write(ndev, SR_PCS_MMD_CONTROL1, value & ~BIT(11));
85 
86 	/* Auto Negotiation cluase 37 enable */
87 	value = sxgbe_xpcs_read(ndev, SR_MII_MMD_CONTROL);
88 	sxgbe_xpcs_write(ndev, SR_MII_MMD_CONTROL, value | BIT(12));
89 
90 	return 0;
91 }
92