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
19static 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
29static 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
38int 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
63int 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