xref: /rk3399_rockchip-uboot/drivers/net/fm/memac_phy.c (revision 192bc6948b02ff4168cab16162fffb507946dc2b)
1111fd19eSRoy Zang /*
2111fd19eSRoy Zang  * Copyright 2012 Freescale Semiconductor, Inc.
3b21f87a3SAndy Fleming  *	Andy Fleming <afleming@gmail.com>
4111fd19eSRoy Zang  *	Roy Zang <tie-fei.zang@freescale.com>
5111fd19eSRoy Zang  *
61a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
7111fd19eSRoy Zang  * Some part is taken from tsec.c
8111fd19eSRoy Zang  */
9111fd19eSRoy Zang #include <common.h>
10111fd19eSRoy Zang #include <miiphy.h>
11111fd19eSRoy Zang #include <phy.h>
12111fd19eSRoy Zang #include <asm/io.h>
13cd348efaSShaohui Xie #include <fsl_memac.h>
14111fd19eSRoy Zang #include <fm_eth.h>
15111fd19eSRoy Zang 
16cd348efaSShaohui Xie #ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN
17cd348efaSShaohui Xie #define memac_out_32(a, v)	out_le32(a, v)
18cd348efaSShaohui Xie #define memac_clrbits_32(a, v)	clrbits_le32(a, v)
19cd348efaSShaohui Xie #define memac_setbits_32(a, v)	setbits_le32(a, v)
20cd348efaSShaohui Xie #else
21cd348efaSShaohui Xie #define memac_out_32(a, v)	out_be32(a, v)
22cd348efaSShaohui Xie #define memac_clrbits_32(a, v)	clrbits_be32(a, v)
23cd348efaSShaohui Xie #define memac_setbits_32(a, v)	setbits_be32(a, v)
24cd348efaSShaohui Xie #endif
25cd348efaSShaohui Xie 
memac_in_32(u32 * reg)26cd348efaSShaohui Xie static u32 memac_in_32(u32 *reg)
27cd348efaSShaohui Xie {
28cd348efaSShaohui Xie #ifdef CONFIG_SYS_MEMAC_LITTLE_ENDIAN
29cd348efaSShaohui Xie 	return in_le32(reg);
30cd348efaSShaohui Xie #else
31cd348efaSShaohui Xie 	return in_be32(reg);
32cd348efaSShaohui Xie #endif
33cd348efaSShaohui Xie }
34cd348efaSShaohui Xie 
35111fd19eSRoy Zang /*
36111fd19eSRoy Zang  * Write value to the PHY for this device to the register at regnum, waiting
37111fd19eSRoy Zang  * until the write is done before it returns.  All PHY configuration has to be
38111fd19eSRoy Zang  * done through the TSEC1 MIIM regs
39111fd19eSRoy Zang  */
memac_mdio_write(struct mii_dev * bus,int port_addr,int dev_addr,int regnum,u16 value)40111fd19eSRoy Zang int memac_mdio_write(struct mii_dev *bus, int port_addr, int dev_addr,
41111fd19eSRoy Zang 			int regnum, u16 value)
42111fd19eSRoy Zang {
43111fd19eSRoy Zang 	u32 mdio_ctl;
44111fd19eSRoy Zang 	struct memac_mdio_controller *regs = bus->priv;
45111fd19eSRoy Zang 	u32 c45 = 1; /* Default to 10G interface */
46111fd19eSRoy Zang 
47111fd19eSRoy Zang 	if (dev_addr == MDIO_DEVAD_NONE) {
48111fd19eSRoy Zang 		c45 = 0; /* clause 22 */
49111fd19eSRoy Zang 		dev_addr = regnum & 0x1f;
50cd348efaSShaohui Xie 		memac_clrbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
513a7ed5aaSShaohui Xie 	} else
52cd348efaSShaohui Xie 		memac_setbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
53111fd19eSRoy Zang 
54111fd19eSRoy Zang 	/* Wait till the bus is free */
55cd348efaSShaohui Xie 	while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
56111fd19eSRoy Zang 		;
57111fd19eSRoy Zang 
58111fd19eSRoy Zang 	/* Set the port and dev addr */
59111fd19eSRoy Zang 	mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
60cd348efaSShaohui Xie 	memac_out_32(&regs->mdio_ctl, mdio_ctl);
61111fd19eSRoy Zang 
62111fd19eSRoy Zang 	/* Set the register address */
63111fd19eSRoy Zang 	if (c45)
64cd348efaSShaohui Xie 		memac_out_32(&regs->mdio_addr, regnum & 0xffff);
65111fd19eSRoy Zang 
66111fd19eSRoy Zang 	/* Wait till the bus is free */
67cd348efaSShaohui Xie 	while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
68111fd19eSRoy Zang 		;
69111fd19eSRoy Zang 
70111fd19eSRoy Zang 	/* Write the value to the register */
71cd348efaSShaohui Xie 	memac_out_32(&regs->mdio_data, MDIO_DATA(value));
72111fd19eSRoy Zang 
73111fd19eSRoy Zang 	/* Wait till the MDIO write is complete */
74cd348efaSShaohui Xie 	while ((memac_in_32(&regs->mdio_data)) & MDIO_DATA_BSY)
75111fd19eSRoy Zang 		;
76111fd19eSRoy Zang 
77111fd19eSRoy Zang 	return 0;
78111fd19eSRoy Zang }
79111fd19eSRoy Zang 
80111fd19eSRoy Zang /*
81111fd19eSRoy Zang  * Reads from register regnum in the PHY for device dev, returning the value.
82111fd19eSRoy Zang  * Clears miimcom first.  All PHY configuration has to be done through the
83111fd19eSRoy Zang  * TSEC1 MIIM regs
84111fd19eSRoy Zang  */
memac_mdio_read(struct mii_dev * bus,int port_addr,int dev_addr,int regnum)85111fd19eSRoy Zang int memac_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr,
86111fd19eSRoy Zang 			int regnum)
87111fd19eSRoy Zang {
88111fd19eSRoy Zang 	u32 mdio_ctl;
89111fd19eSRoy Zang 	struct memac_mdio_controller *regs = bus->priv;
90111fd19eSRoy Zang 	u32 c45 = 1;
91111fd19eSRoy Zang 
92111fd19eSRoy Zang 	if (dev_addr == MDIO_DEVAD_NONE) {
93ff5fb2a3SShaohui Xie 		if (!strcmp(bus->name, DEFAULT_FM_TGEC_MDIO_NAME))
94ff5fb2a3SShaohui Xie 			return 0xffff;
95111fd19eSRoy Zang 		c45 = 0; /* clause 22 */
96111fd19eSRoy Zang 		dev_addr = regnum & 0x1f;
97cd348efaSShaohui Xie 		memac_clrbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
983a7ed5aaSShaohui Xie 	} else
99cd348efaSShaohui Xie 		memac_setbits_32(&regs->mdio_stat, MDIO_STAT_ENC);
100111fd19eSRoy Zang 
101111fd19eSRoy Zang 	/* Wait till the bus is free */
102cd348efaSShaohui Xie 	while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
103111fd19eSRoy Zang 		;
104111fd19eSRoy Zang 
105111fd19eSRoy Zang 	/* Set the Port and Device Addrs */
106111fd19eSRoy Zang 	mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
107cd348efaSShaohui Xie 	memac_out_32(&regs->mdio_ctl, mdio_ctl);
108111fd19eSRoy Zang 
109111fd19eSRoy Zang 	/* Set the register address */
110111fd19eSRoy Zang 	if (c45)
111cd348efaSShaohui Xie 		memac_out_32(&regs->mdio_addr, regnum & 0xffff);
112111fd19eSRoy Zang 
113111fd19eSRoy Zang 	/* Wait till the bus is free */
114cd348efaSShaohui Xie 	while ((memac_in_32(&regs->mdio_stat)) & MDIO_STAT_BSY)
115111fd19eSRoy Zang 		;
116111fd19eSRoy Zang 
117111fd19eSRoy Zang 	/* Initiate the read */
118111fd19eSRoy Zang 	mdio_ctl |= MDIO_CTL_READ;
119cd348efaSShaohui Xie 	memac_out_32(&regs->mdio_ctl, mdio_ctl);
120111fd19eSRoy Zang 
121111fd19eSRoy Zang 	/* Wait till the MDIO write is complete */
122cd348efaSShaohui Xie 	while ((memac_in_32(&regs->mdio_data)) & MDIO_DATA_BSY)
123111fd19eSRoy Zang 		;
124111fd19eSRoy Zang 
125111fd19eSRoy Zang 	/* Return all Fs if nothing was there */
126cd348efaSShaohui Xie 	if (memac_in_32(&regs->mdio_stat) & MDIO_STAT_RD_ER)
127111fd19eSRoy Zang 		return 0xffff;
128111fd19eSRoy Zang 
129cd348efaSShaohui Xie 	return memac_in_32(&regs->mdio_data) & 0xffff;
130111fd19eSRoy Zang }
131111fd19eSRoy Zang 
memac_mdio_reset(struct mii_dev * bus)132111fd19eSRoy Zang int memac_mdio_reset(struct mii_dev *bus)
133111fd19eSRoy Zang {
134111fd19eSRoy Zang 	return 0;
135111fd19eSRoy Zang }
136111fd19eSRoy Zang 
fm_memac_mdio_init(bd_t * bis,struct memac_mdio_info * info)137111fd19eSRoy Zang int fm_memac_mdio_init(bd_t *bis, struct memac_mdio_info *info)
138111fd19eSRoy Zang {
139111fd19eSRoy Zang 	struct mii_dev *bus = mdio_alloc();
140111fd19eSRoy Zang 
141111fd19eSRoy Zang 	if (!bus) {
142111fd19eSRoy Zang 		printf("Failed to allocate FM TGEC MDIO bus\n");
143111fd19eSRoy Zang 		return -1;
144111fd19eSRoy Zang 	}
145111fd19eSRoy Zang 
146111fd19eSRoy Zang 	bus->read = memac_mdio_read;
147111fd19eSRoy Zang 	bus->write = memac_mdio_write;
148111fd19eSRoy Zang 	bus->reset = memac_mdio_reset;
149*192bc694SBen Whitten 	strcpy(bus->name, info->name);
150111fd19eSRoy Zang 
151111fd19eSRoy Zang 	bus->priv = info->regs;
152111fd19eSRoy Zang 
1532ee6c52eSPriyanka Jain 	/*
1542ee6c52eSPriyanka Jain 	 * On some platforms like B4860, default value of MDIO_CLK_DIV bits
1552ee6c52eSPriyanka Jain 	 * in mdio_stat(mdio_cfg) register generates MDIO clock too high
1562ee6c52eSPriyanka Jain 	 * (much higher than 2.5MHz), violating the IEEE specs.
1572ee6c52eSPriyanka Jain 	 * On other platforms like T1040, default value of MDIO_CLK_DIV bits
1582ee6c52eSPriyanka Jain 	 * is zero, so MDIO clock is disabled.
1592ee6c52eSPriyanka Jain 	 * So, for proper functioning of MDIO, MDIO_CLK_DIV bits needs to
1602ee6c52eSPriyanka Jain 	 * be properly initialized.
161ae6b4583SShaohui Xie 	 * NEG bit default should be '1' as per FMAN-v3 RM, but on platform
162ae6b4583SShaohui Xie 	 * like T2080QDS, this bit default is '0', which leads to MDIO failure
163ae6b4583SShaohui Xie 	 * on XAUI PHY, so set this bit definitely.
1642ee6c52eSPriyanka Jain 	 */
165cd348efaSShaohui Xie 	memac_setbits_32(
166cd348efaSShaohui Xie 		&((struct memac_mdio_controller *)info->regs)->mdio_stat,
167ae6b4583SShaohui Xie 		MDIO_STAT_CLKDIV(258) | MDIO_STAT_NEG);
1682ee6c52eSPriyanka Jain 
169111fd19eSRoy Zang 	return mdio_register(bus);
170111fd19eSRoy Zang }
171