Home | History | Annotate | Download | only in pfe_eth
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright 2015-2016 Freescale Semiconductor, Inc.
      4  * Copyright 2017 NXP
      5  */
      6 #include <common.h>
      7 #include <dm.h>
      8 #include <dm/platform_data/pfe_dm_eth.h>
      9 #include <net.h>
     10 #include <net/pfe_eth/pfe_eth.h>
     11 
     12 extern struct gemac_s gem_info[];
     13 #if defined(CONFIG_PHYLIB)
     14 
     15 #define MDIO_TIMEOUT    5000
     16 static int pfe_write_addr(struct mii_dev *bus, int phy_addr, int dev_addr,
     17 			  int reg_addr)
     18 {
     19 	void *reg_base = bus->priv;
     20 	u32 devadr;
     21 	u32 phy;
     22 	u32 reg_data;
     23 	int timeout = MDIO_TIMEOUT;
     24 
     25 	devadr = ((dev_addr & EMAC_MII_DATA_RA_MASK) << EMAC_MII_DATA_RA_SHIFT);
     26 	phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT);
     27 
     28 	reg_data = (EMAC_MII_DATA_TA | phy | devadr | reg_addr);
     29 
     30 	writel(reg_data, reg_base + EMAC_MII_DATA_REG);
     31 
     32 	/*
     33 	 * wait for the MII interrupt
     34 	 */
     35 	while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) {
     36 		if (timeout-- <= 0) {
     37 			printf("Phy MDIO read/write timeout\n");
     38 			return -1;
     39 		}
     40 	}
     41 
     42 	/*
     43 	 * clear MII interrupt
     44 	 */
     45 	writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG);
     46 
     47 	return 0;
     48 }
     49 
     50 static int pfe_phy_read(struct mii_dev *bus, int phy_addr, int dev_addr,
     51 			int reg_addr)
     52 {
     53 	void *reg_base = bus->priv;
     54 	u32 reg;
     55 	u32 phy;
     56 	u32 reg_data;
     57 	u16 val;
     58 	int timeout = MDIO_TIMEOUT;
     59 
     60 	if (dev_addr == MDIO_DEVAD_NONE) {
     61 		reg = ((reg_addr & EMAC_MII_DATA_RA_MASK) <<
     62 			EMAC_MII_DATA_RA_SHIFT);
     63 	} else {
     64 		pfe_write_addr(bus, phy_addr, dev_addr, reg_addr);
     65 		reg = ((dev_addr & EMAC_MII_DATA_RA_MASK) <<
     66 		       EMAC_MII_DATA_RA_SHIFT);
     67 	}
     68 
     69 	phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT);
     70 
     71 	if (dev_addr == MDIO_DEVAD_NONE)
     72 		reg_data = (EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_RD |
     73 			    EMAC_MII_DATA_TA | phy | reg);
     74 	else
     75 		reg_data = (EMAC_MII_DATA_OP_CL45_RD | EMAC_MII_DATA_TA |
     76 			    phy | reg);
     77 
     78 	writel(reg_data, reg_base + EMAC_MII_DATA_REG);
     79 
     80 	/*
     81 	 * wait for the MII interrupt
     82 	 */
     83 	while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) {
     84 		if (timeout-- <= 0) {
     85 			printf("Phy MDIO read/write timeout\n");
     86 			return -1;
     87 		}
     88 	}
     89 
     90 	/*
     91 	 * clear MII interrupt
     92 	 */
     93 	writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG);
     94 
     95 	/*
     96 	 * it's now safe to read the PHY's register
     97 	 */
     98 	val = (u16)readl(reg_base + EMAC_MII_DATA_REG);
     99 	debug("%s: %p phy: 0x%x reg:0x%08x val:%#x\n", __func__, reg_base,
    100 	      phy_addr, reg_addr, val);
    101 
    102 	return val;
    103 }
    104 
    105 static int pfe_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr,
    106 			 int reg_addr, u16 data)
    107 {
    108 	void *reg_base = bus->priv;
    109 	u32 reg;
    110 	u32 phy;
    111 	u32 reg_data;
    112 	int timeout = MDIO_TIMEOUT;
    113 	int val;
    114 
    115 	if (dev_addr == MDIO_DEVAD_NONE) {
    116 		reg = ((reg_addr & EMAC_MII_DATA_RA_MASK) <<
    117 		       EMAC_MII_DATA_RA_SHIFT);
    118 	} else {
    119 		pfe_write_addr(bus, phy_addr, dev_addr, reg_addr);
    120 		reg = ((dev_addr & EMAC_MII_DATA_RA_MASK) <<
    121 		       EMAC_MII_DATA_RA_SHIFT);
    122 	}
    123 
    124 	phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT);
    125 
    126 	if (dev_addr == MDIO_DEVAD_NONE)
    127 		reg_data = (EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_WR |
    128 			    EMAC_MII_DATA_TA | phy | reg | data);
    129 	else
    130 		reg_data = (EMAC_MII_DATA_OP_CL45_WR | EMAC_MII_DATA_TA |
    131 			    phy | reg | data);
    132 
    133 	writel(reg_data, reg_base + EMAC_MII_DATA_REG);
    134 
    135 	/*
    136 	 * wait for the MII interrupt
    137 	 */
    138 	while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) {
    139 		if (timeout-- <= 0) {
    140 			printf("Phy MDIO read/write timeout\n");
    141 			return -1;
    142 		}
    143 	}
    144 
    145 	/*
    146 	 * clear MII interrupt
    147 	 */
    148 	writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG);
    149 
    150 	debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phy_addr,
    151 	      reg_addr, data);
    152 
    153 	return val;
    154 }
    155 
    156 static void pfe_configure_serdes(struct pfe_eth_dev *priv)
    157 {
    158 	struct mii_dev bus;
    159 	int value, sgmii_2500 = 0;
    160 	struct gemac_s *gem = priv->gem;
    161 
    162 	if (gem->phy_mode == PHY_INTERFACE_MODE_SGMII_2500)
    163 		sgmii_2500 = 1;
    164 
    165 	printf("%s %d\n", __func__, priv->gemac_port);
    166 
    167 	/* PCS configuration done with corresponding GEMAC */
    168 	bus.priv = gem_info[priv->gemac_port].gemac_base;
    169 
    170 	pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x0);
    171 	pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x1);
    172 	pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x2);
    173 	pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x3);
    174 
    175 	/* Reset serdes */
    176 	pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x0, 0x8000);
    177 
    178 	/* SGMII IF mode + AN enable only for 1G SGMII, not for 2.5G */
    179 	value = PHY_SGMII_IF_MODE_SGMII;
    180 	if (!sgmii_2500)
    181 		value |= PHY_SGMII_IF_MODE_AN;
    182 	else
    183 		value |= PHY_SGMII_IF_MODE_SGMII_GBT;
    184 
    185 	pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x14, value);
    186 
    187 	/* Dev ability according to SGMII specification */
    188 	value = PHY_SGMII_DEV_ABILITY_SGMII;
    189 	pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x4, value);
    190 
    191 	/* These values taken from validation team */
    192 	if (!sgmii_2500) {
    193 		pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x13, 0x0);
    194 		pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x12, 0x400);
    195 	} else {
    196 		pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x13, 0x7);
    197 		pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x12, 0xa120);
    198 	}
    199 
    200 	/* Restart AN */
    201 	value = PHY_SGMII_CR_DEF_VAL;
    202 	if (!sgmii_2500)
    203 		value |= PHY_SGMII_CR_RESET_AN;
    204 	/* Disable Auto neg for 2.5G SGMII as it doesn't support auto neg*/
    205 	if (sgmii_2500)
    206 		value &= ~PHY_SGMII_ENABLE_AN;
    207 	pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0, value);
    208 }
    209 
    210 int pfe_phy_configure(struct pfe_eth_dev *priv, int dev_id, int phy_id)
    211 {
    212 	struct phy_device *phydev = NULL;
    213 	struct udevice *dev = priv->dev;
    214 	struct gemac_s *gem = priv->gem;
    215 	struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR;
    216 
    217 	if (!gem->bus)
    218 		return -1;
    219 
    220 	/* Configure SGMII  PCS */
    221 	if (gem->phy_mode == PHY_INTERFACE_MODE_SGMII ||
    222 	    gem->phy_mode == PHY_INTERFACE_MODE_SGMII_2500) {
    223 		out_be32(&scfg->mdioselcr, 0x00000000);
    224 		pfe_configure_serdes(priv);
    225 	}
    226 
    227 	mdelay(100);
    228 
    229 	/* By this time on-chip SGMII initialization is done
    230 	 * we can switch mdio interface to external PHYs
    231 	 */
    232 	out_be32(&scfg->mdioselcr, 0x80000000);
    233 
    234 	phydev = phy_connect(gem->bus, phy_id, dev, gem->phy_mode);
    235 	if (!phydev) {
    236 		printf("phy_connect failed\n");
    237 		return -ENODEV;
    238 	}
    239 
    240 	phy_config(phydev);
    241 
    242 	priv->phydev = phydev;
    243 
    244 	return 0;
    245 }
    246 #endif
    247 
    248 struct mii_dev *pfe_mdio_init(struct pfe_mdio_info *mdio_info)
    249 {
    250 	struct mii_dev *bus;
    251 	int ret;
    252 	u32 mdio_speed;
    253 	u32 pclk = 250000000;
    254 
    255 	bus = mdio_alloc();
    256 	if (!bus) {
    257 		printf("mdio_alloc failed\n");
    258 		return NULL;
    259 	}
    260 	bus->read = pfe_phy_read;
    261 	bus->write = pfe_phy_write;
    262 
    263 	/* MAC1 MDIO used to communicate with external PHYS */
    264 	bus->priv = mdio_info->reg_base;
    265 	sprintf(bus->name, mdio_info->name);
    266 
    267 	/* configure mdio speed */
    268 	mdio_speed = (DIV_ROUND_UP(pclk, 4000000) << EMAC_MII_SPEED_SHIFT);
    269 	mdio_speed |= EMAC_HOLDTIME(0x5);
    270 	writel(mdio_speed, mdio_info->reg_base + EMAC_MII_CTRL_REG);
    271 
    272 	ret = mdio_register(bus);
    273 	if (ret) {
    274 		printf("mdio_register failed\n");
    275 		free(bus);
    276 		return NULL;
    277 	}
    278 	return bus;
    279 }
    280 
    281 void pfe_set_mdio(int dev_id, struct mii_dev *bus)
    282 {
    283 	gem_info[dev_id].bus = bus;
    284 }
    285 
    286 void pfe_set_phy_address_mode(int dev_id, int phy_id, int phy_mode)
    287 {
    288 	gem_info[dev_id].phy_address = phy_id;
    289 	gem_info[dev_id].phy_mode  = phy_mode;
    290 }
    291