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(®s->mdio_stat, MDIO_STAT_ENC);
513a7ed5aaSShaohui Xie } else
52cd348efaSShaohui Xie memac_setbits_32(®s->mdio_stat, MDIO_STAT_ENC);
53111fd19eSRoy Zang
54111fd19eSRoy Zang /* Wait till the bus is free */
55cd348efaSShaohui Xie while ((memac_in_32(®s->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(®s->mdio_ctl, mdio_ctl);
61111fd19eSRoy Zang
62111fd19eSRoy Zang /* Set the register address */
63111fd19eSRoy Zang if (c45)
64cd348efaSShaohui Xie memac_out_32(®s->mdio_addr, regnum & 0xffff);
65111fd19eSRoy Zang
66111fd19eSRoy Zang /* Wait till the bus is free */
67cd348efaSShaohui Xie while ((memac_in_32(®s->mdio_stat)) & MDIO_STAT_BSY)
68111fd19eSRoy Zang ;
69111fd19eSRoy Zang
70111fd19eSRoy Zang /* Write the value to the register */
71cd348efaSShaohui Xie memac_out_32(®s->mdio_data, MDIO_DATA(value));
72111fd19eSRoy Zang
73111fd19eSRoy Zang /* Wait till the MDIO write is complete */
74cd348efaSShaohui Xie while ((memac_in_32(®s->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(®s->mdio_stat, MDIO_STAT_ENC);
983a7ed5aaSShaohui Xie } else
99cd348efaSShaohui Xie memac_setbits_32(®s->mdio_stat, MDIO_STAT_ENC);
100111fd19eSRoy Zang
101111fd19eSRoy Zang /* Wait till the bus is free */
102cd348efaSShaohui Xie while ((memac_in_32(®s->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(®s->mdio_ctl, mdio_ctl);
108111fd19eSRoy Zang
109111fd19eSRoy Zang /* Set the register address */
110111fd19eSRoy Zang if (c45)
111cd348efaSShaohui Xie memac_out_32(®s->mdio_addr, regnum & 0xffff);
112111fd19eSRoy Zang
113111fd19eSRoy Zang /* Wait till the bus is free */
114cd348efaSShaohui Xie while ((memac_in_32(®s->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(®s->mdio_ctl, mdio_ctl);
120111fd19eSRoy Zang
121111fd19eSRoy Zang /* Wait till the MDIO write is complete */
122cd348efaSShaohui Xie while ((memac_in_32(®s->mdio_data)) & MDIO_DATA_BSY)
123111fd19eSRoy Zang ;
124111fd19eSRoy Zang
125111fd19eSRoy Zang /* Return all Fs if nothing was there */
126cd348efaSShaohui Xie if (memac_in_32(®s->mdio_stat) & MDIO_STAT_RD_ER)
127111fd19eSRoy Zang return 0xffff;
128111fd19eSRoy Zang
129cd348efaSShaohui Xie return memac_in_32(®s->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