1/*
2 * Copyright 2008-2013 Freescale Semiconductor Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *     * Redistributions of source code must retain the above copyright
7 *       notice, this list of conditions and the following disclaimer.
8 *     * Redistributions in binary form must reproduce the above copyright
9 *       notice, this list of conditions and the following disclaimer in the
10 *       documentation and/or other materials provided with the distribution.
11 *     * Neither the name of Freescale Semiconductor nor the
12 *       names of its contributors may be used to endorse or promote products
13 *       derived from this software without specific prior written permission.
14 *
15 *
16 * ALTERNATIVELY, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL") as published by the Free Software
18 * Foundation, either version 2 of that License or (at your option) any
19 * later version.
20 *
21 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33
34#include "fsl_fman_memac_mii_acc.h"
35
36static void write_phy_reg_10g(struct memac_mii_access_mem_map *mii_regs,
37	uint8_t phy_addr, uint8_t reg, uint16_t data)
38{
39	uint32_t                tmp_reg;
40
41	tmp_reg = ioread32be(&mii_regs->mdio_cfg);
42	/* Leave only MDIO_CLK_DIV bits set on */
43	tmp_reg &= MDIO_CFG_CLK_DIV_MASK;
44	/* Set maximum MDIO_HOLD value to allow phy to see
45	change of data signal */
46	tmp_reg |= MDIO_CFG_HOLD_MASK;
47	/* Add 10G interface mode */
48	tmp_reg |= MDIO_CFG_ENC45;
49	iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
50
51	/* Wait for command completion */
52	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
53		udelay(1);
54
55	/* Specify phy and register to be accessed */
56	iowrite32be(phy_addr, &mii_regs->mdio_ctrl);
57	iowrite32be(reg, &mii_regs->mdio_addr);
58	wmb();
59
60	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
61		udelay(1);
62
63	/* Write data */
64	iowrite32be(data, &mii_regs->mdio_data);
65	wmb();
66
67	/* Wait for write transaction end */
68	while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
69		udelay(1);
70}
71
72static uint32_t read_phy_reg_10g(struct memac_mii_access_mem_map *mii_regs,
73	uint8_t phy_addr, uint8_t reg, uint16_t *data)
74{
75	uint32_t                tmp_reg;
76
77	tmp_reg = ioread32be(&mii_regs->mdio_cfg);
78	/* Leave only MDIO_CLK_DIV bits set on */
79	tmp_reg &= MDIO_CFG_CLK_DIV_MASK;
80	/* Set maximum MDIO_HOLD value to allow phy to see
81	change of data signal */
82	tmp_reg |= MDIO_CFG_HOLD_MASK;
83	/* Add 10G interface mode */
84	tmp_reg |= MDIO_CFG_ENC45;
85	iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
86
87	/* Wait for command completion */
88	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
89		udelay(1);
90
91	/* Specify phy and register to be accessed */
92	iowrite32be(phy_addr, &mii_regs->mdio_ctrl);
93	iowrite32be(reg, &mii_regs->mdio_addr);
94	wmb();
95
96	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
97		udelay(1);
98
99	/* Read cycle */
100	tmp_reg = phy_addr;
101	tmp_reg |= MDIO_CTL_READ;
102	iowrite32be(tmp_reg, &mii_regs->mdio_ctrl);
103	wmb();
104
105	/* Wait for data to be available */
106	while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
107		udelay(1);
108
109	*data =  (uint16_t)ioread32be(&mii_regs->mdio_data);
110
111	/* Check if there was an error */
112	return ioread32be(&mii_regs->mdio_cfg);
113}
114
115static void write_phy_reg_1g(struct memac_mii_access_mem_map *mii_regs,
116	uint8_t phy_addr, uint8_t reg, uint16_t data)
117{
118	uint32_t                tmp_reg;
119
120	/* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */
121	tmp_reg = ioread32be(&mii_regs->mdio_cfg);
122	tmp_reg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK);
123	iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
124
125	/* Wait for command completion */
126	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
127		udelay(1);
128
129	/* Write transaction */
130	tmp_reg = (phy_addr << MDIO_CTL_PHY_ADDR_SHIFT);
131	tmp_reg |= reg;
132	iowrite32be(tmp_reg, &mii_regs->mdio_ctrl);
133
134	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
135		udelay(1);
136
137	iowrite32be(data, &mii_regs->mdio_data);
138
139	wmb();
140
141	/* Wait for write transaction to end */
142	while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
143		udelay(1);
144}
145
146static uint32_t read_phy_reg_1g(struct memac_mii_access_mem_map *mii_regs,
147	uint8_t phy_addr, uint8_t reg, uint16_t *data)
148{
149	uint32_t tmp_reg;
150
151	/* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */
152	tmp_reg = ioread32be(&mii_regs->mdio_cfg);
153	tmp_reg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK);
154	iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
155
156	/* Wait for command completion */
157	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
158		udelay(1);
159
160	/* Read transaction */
161	tmp_reg = (phy_addr << MDIO_CTL_PHY_ADDR_SHIFT);
162	tmp_reg |= reg;
163	tmp_reg |= MDIO_CTL_READ;
164	iowrite32be(tmp_reg, &mii_regs->mdio_ctrl);
165
166	while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
167		udelay(1);
168
169	/* Wait for data to be available */
170	while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
171		udelay(1);
172
173	*data =  (uint16_t)ioread32be(&mii_regs->mdio_data);
174
175	/* Check error */
176	return ioread32be(&mii_regs->mdio_cfg);
177}
178
179/*****************************************************************************/
180int fman_memac_mii_write_phy_reg(struct memac_mii_access_mem_map *mii_regs,
181	uint8_t phy_addr, uint8_t reg, uint16_t data,
182	enum enet_speed enet_speed)
183{
184	/* Figure out interface type - 10G vs 1G.
185	In 10G interface both phy_addr and devAddr present. */
186	if (enet_speed == E_ENET_SPEED_10000)
187		write_phy_reg_10g(mii_regs, phy_addr, reg, data);
188	else
189		write_phy_reg_1g(mii_regs, phy_addr, reg, data);
190
191	return 0;
192}
193
194/*****************************************************************************/
195int fman_memac_mii_read_phy_reg(struct memac_mii_access_mem_map *mii_regs,
196	uint8_t phy_addr, uint8_t reg, uint16_t *data,
197	enum enet_speed enet_speed)
198{
199	uint32_t ans;
200	/* Figure out interface type - 10G vs 1G.
201	In 10G interface both phy_addr and devAddr present. */
202	if (enet_speed == E_ENET_SPEED_10000)
203		ans = read_phy_reg_10g(mii_regs, phy_addr, reg, data);
204	else
205		ans = read_phy_reg_1g(mii_regs, phy_addr, reg, data);
206
207	if (ans & MDIO_CFG_READ_ERR)
208		return -EINVAL;
209	return 0;
210}
211
212/* ......................................................................... */
213
214