]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
063c1263 | 2 | /* |
5be00a01 | 3 | * Copyright 2009-2010, 2013 Freescale Semiconductor, Inc. |
063c1263 AF |
4 | * Jun-jie Zhang <[email protected]> |
5 | * Mingkai Hu <[email protected]> | |
063c1263 | 6 | */ |
9872b736 | 7 | |
063c1263 AF |
8 | #include <common.h> |
9 | #include <miiphy.h> | |
10 | #include <phy.h> | |
11 | #include <fsl_mdio.h> | |
12 | #include <asm/io.h> | |
1221ce45 | 13 | #include <linux/errno.h> |
063c1263 | 14 | |
5be00a01 | 15 | void tsec_local_mdio_write(struct tsec_mii_mng __iomem *phyregs, int port_addr, |
063c1263 AF |
16 | int dev_addr, int regnum, int value) |
17 | { | |
18 | int timeout = 1000000; | |
19 | ||
20 | out_be32(&phyregs->miimadd, (port_addr << 8) | (regnum & 0x1f)); | |
21 | out_be32(&phyregs->miimcon, value); | |
d2614ea0 AW |
22 | /* Memory barrier */ |
23 | mb(); | |
063c1263 AF |
24 | |
25 | while ((in_be32(&phyregs->miimind) & MIIMIND_BUSY) && timeout--) | |
26 | ; | |
27 | } | |
28 | ||
5be00a01 | 29 | int tsec_local_mdio_read(struct tsec_mii_mng __iomem *phyregs, int port_addr, |
063c1263 AF |
30 | int dev_addr, int regnum) |
31 | { | |
32 | int value; | |
33 | int timeout = 1000000; | |
34 | ||
9872b736 | 35 | /* Put the address of the phy, and the register number into MIIMADD */ |
063c1263 AF |
36 | out_be32(&phyregs->miimadd, (port_addr << 8) | (regnum & 0x1f)); |
37 | ||
38 | /* Clear the command register, and wait */ | |
39 | out_be32(&phyregs->miimcom, 0); | |
d2614ea0 AW |
40 | /* Memory barrier */ |
41 | mb(); | |
063c1263 AF |
42 | |
43 | /* Initiate a read command, and wait */ | |
44 | out_be32(&phyregs->miimcom, MIIMCOM_READ_CYCLE); | |
d2614ea0 AW |
45 | /* Memory barrier */ |
46 | mb(); | |
063c1263 AF |
47 | |
48 | /* Wait for the the indication that the read is done */ | |
49 | while ((in_be32(&phyregs->miimind) & (MIIMIND_NOTVALID | MIIMIND_BUSY)) | |
50 | && timeout--) | |
51 | ; | |
52 | ||
53 | /* Grab the value read from the PHY */ | |
54 | value = in_be32(&phyregs->miimstat); | |
55 | ||
56 | return value; | |
57 | } | |
58 | ||
59 | static int fsl_pq_mdio_reset(struct mii_dev *bus) | |
60 | { | |
5be00a01 CM |
61 | struct tsec_mii_mng __iomem *regs = |
62 | (struct tsec_mii_mng __iomem *)bus->priv; | |
063c1263 AF |
63 | |
64 | /* Reset MII (due to new addresses) */ | |
65 | out_be32(®s->miimcfg, MIIMCFG_RESET_MGMT); | |
66 | ||
67 | out_be32(®s->miimcfg, MIIMCFG_INIT_VALUE); | |
68 | ||
69 | while (in_be32(®s->miimind) & MIIMIND_BUSY) | |
70 | ; | |
71 | ||
72 | return 0; | |
73 | } | |
74 | ||
75 | int tsec_phy_read(struct mii_dev *bus, int addr, int dev_addr, int regnum) | |
76 | { | |
5be00a01 CM |
77 | struct tsec_mii_mng __iomem *phyregs = |
78 | (struct tsec_mii_mng __iomem *)bus->priv; | |
063c1263 AF |
79 | |
80 | return tsec_local_mdio_read(phyregs, addr, dev_addr, regnum); | |
81 | } | |
82 | ||
83 | int tsec_phy_write(struct mii_dev *bus, int addr, int dev_addr, int regnum, | |
84 | u16 value) | |
85 | { | |
5be00a01 CM |
86 | struct tsec_mii_mng __iomem *phyregs = |
87 | (struct tsec_mii_mng __iomem *)bus->priv; | |
063c1263 AF |
88 | |
89 | tsec_local_mdio_write(phyregs, addr, dev_addr, regnum, value); | |
90 | ||
91 | return 0; | |
92 | } | |
93 | ||
94 | int fsl_pq_mdio_init(bd_t *bis, struct fsl_pq_mdio_info *info) | |
95 | { | |
96 | struct mii_dev *bus = mdio_alloc(); | |
97 | ||
98 | if (!bus) { | |
99 | printf("Failed to allocate FSL MDIO bus\n"); | |
100 | return -1; | |
101 | } | |
102 | ||
103 | bus->read = tsec_phy_read; | |
104 | bus->write = tsec_phy_write; | |
105 | bus->reset = fsl_pq_mdio_reset; | |
192bc694 | 106 | strcpy(bus->name, info->name); |
063c1263 | 107 | |
5be00a01 | 108 | bus->priv = (void *)info->regs; |
063c1263 AF |
109 | |
110 | return mdio_register(bus); | |
111 | } |