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