Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / u-boot / drivers / net / fm / tgec_phy.c
1 /*
2  * Copyright 2009-2011 Freescale Semiconductor, Inc.
3  *      Andy Fleming <afleming@freescale.com>
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  * Some part is taken from tsec.c
7  */
8 #include <common.h>
9 #include <miiphy.h>
10 #include <phy.h>
11 #include <asm/io.h>
12 #include <asm/fsl_tgec.h>
13 #include <fm_eth.h>
14
15 /*
16  * Write value to the PHY for this device to the register at regnum, waiting
17  * until the write is done before it returns.  All PHY configuration has to be
18  * done through the TSEC1 MIIM regs
19  */
20 static int tgec_mdio_write(struct mii_dev *bus, int port_addr, int dev_addr,
21                            int regnum, u16 value)
22 {
23         u32 mdio_ctl;
24         u32 stat_val;
25         struct tgec_mdio_controller *regs = bus->priv;
26
27         if (dev_addr == MDIO_DEVAD_NONE)
28                 return 0;
29
30         /* Wait till the bus is free */
31         stat_val = MDIO_STAT_CLKDIV(100);
32         out_be32(&regs->mdio_stat, stat_val);
33         while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
34                 ;
35
36         /* Set the port and dev addr */
37         mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
38         out_be32(&regs->mdio_ctl, mdio_ctl);
39
40         /* Set the register address */
41         out_be32(&regs->mdio_addr, regnum & 0xffff);
42
43         /* Wait till the bus is free */
44         while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
45                 ;
46
47         /* Write the value to the register */
48         out_be32(&regs->mdio_data, MDIO_DATA(value));
49
50         /* Wait till the MDIO write is complete */
51         while ((in_be32(&regs->mdio_data)) & MDIO_DATA_BSY)
52                 ;
53
54         return 0;
55 }
56
57 /*
58  * Reads from register regnum in the PHY for device dev, returning the value.
59  * Clears miimcom first.  All PHY configuration has to be done through the
60  * TSEC1 MIIM regs
61  */
62 static int tgec_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr,
63                           int regnum)
64 {
65         u32 mdio_ctl;
66         u32 stat_val;
67         struct tgec_mdio_controller *regs = bus->priv;
68
69         if (dev_addr == MDIO_DEVAD_NONE)
70                 return 0xffff;
71
72         stat_val = MDIO_STAT_CLKDIV(100);
73         out_be32(&regs->mdio_stat, stat_val);
74         /* Wait till the bus is free */
75         while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
76                 ;
77
78         /* Set the Port and Device Addrs */
79         mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
80         out_be32(&regs->mdio_ctl, mdio_ctl);
81
82         /* Set the register address */
83         out_be32(&regs->mdio_addr, regnum & 0xffff);
84
85         /* Wait till the bus is free */
86         while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
87                 ;
88
89         /* Initiate the read */
90         mdio_ctl |= MDIO_CTL_READ;
91         out_be32(&regs->mdio_ctl, mdio_ctl);
92
93         /* Wait till the MDIO write is complete */
94         while ((in_be32(&regs->mdio_data)) & MDIO_DATA_BSY)
95                 ;
96
97         /* Return all Fs if nothing was there */
98         if (in_be32(&regs->mdio_stat) & MDIO_STAT_RD_ER)
99                 return 0xffff;
100
101         return in_be32(&regs->mdio_data) & 0xffff;
102 }
103
104 static int tgec_mdio_reset(struct mii_dev *bus)
105 {
106         return 0;
107 }
108
109 int fm_tgec_mdio_init(bd_t *bis, struct tgec_mdio_info *info)
110 {
111         struct mii_dev *bus = mdio_alloc();
112
113         if (!bus) {
114                 printf("Failed to allocate FM TGEC MDIO bus\n");
115                 return -1;
116         }
117
118         bus->read = tgec_mdio_read;
119         bus->write = tgec_mdio_write;
120         bus->reset = tgec_mdio_reset;
121         sprintf(bus->name, info->name);
122
123         bus->priv = info->regs;
124
125         return mdio_register(bus);
126 }