|  | /* 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; | 
|  | } |