• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/octeon/
1/***********************license start***************
2 * Author: Cavium Networks
3 *
4 * Contact: support@caviumnetworks.com
5 * This file is part of the OCTEON SDK
6 *
7 * Copyright (c) 2003-2008 Cavium Networks
8 *
9 * This file is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License, Version 2, as
11 * published by the Free Software Foundation.
12 *
13 * This file is distributed in the hope that it will be useful, but
14 * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
16 * NONINFRINGEMENT.  See the GNU General Public License for more
17 * details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this file; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 * or visit http://www.gnu.org/licenses/.
23 *
24 * This file may also be available under a different license from Cavium.
25 * Contact Cavium Networks for more information
26 ***********************license end**************************************/
27
28/*
29 *
30 * Interface to the SMI/MDIO hardware, including support for both IEEE 802.3
31 * clause 22 and clause 45 operations.
32 *
33 */
34
35#ifndef __CVMX_MIO_H__
36#define __CVMX_MIO_H__
37
38#include "cvmx-smix-defs.h"
39
40/**
41 * PHY register 0 from the 802.3 spec
42 */
43#define CVMX_MDIO_PHY_REG_CONTROL 0
44typedef union {
45	uint16_t u16;
46	struct {
47		uint16_t reset:1;
48		uint16_t loopback:1;
49		uint16_t speed_lsb:1;
50		uint16_t autoneg_enable:1;
51		uint16_t power_down:1;
52		uint16_t isolate:1;
53		uint16_t restart_autoneg:1;
54		uint16_t duplex:1;
55		uint16_t collision_test:1;
56		uint16_t speed_msb:1;
57		uint16_t unidirectional_enable:1;
58		uint16_t reserved_0_4:5;
59	} s;
60} cvmx_mdio_phy_reg_control_t;
61
62/**
63 * PHY register 1 from the 802.3 spec
64 */
65#define CVMX_MDIO_PHY_REG_STATUS 1
66typedef union {
67	uint16_t u16;
68	struct {
69		uint16_t capable_100base_t4:1;
70		uint16_t capable_100base_x_full:1;
71		uint16_t capable_100base_x_half:1;
72		uint16_t capable_10_full:1;
73		uint16_t capable_10_half:1;
74		uint16_t capable_100base_t2_full:1;
75		uint16_t capable_100base_t2_half:1;
76		uint16_t capable_extended_status:1;
77		uint16_t capable_unidirectional:1;
78		uint16_t capable_mf_preamble_suppression:1;
79		uint16_t autoneg_complete:1;
80		uint16_t remote_fault:1;
81		uint16_t capable_autoneg:1;
82		uint16_t link_status:1;
83		uint16_t jabber_detect:1;
84		uint16_t capable_extended_registers:1;
85
86	} s;
87} cvmx_mdio_phy_reg_status_t;
88
89/**
90 * PHY register 2 from the 802.3 spec
91 */
92#define CVMX_MDIO_PHY_REG_ID1 2
93typedef union {
94	uint16_t u16;
95	struct {
96		uint16_t oui_bits_3_18;
97	} s;
98} cvmx_mdio_phy_reg_id1_t;
99
100/**
101 * PHY register 3 from the 802.3 spec
102 */
103#define CVMX_MDIO_PHY_REG_ID2 3
104typedef union {
105	uint16_t u16;
106	struct {
107		uint16_t oui_bits_19_24:6;
108		uint16_t model:6;
109		uint16_t revision:4;
110	} s;
111} cvmx_mdio_phy_reg_id2_t;
112
113/**
114 * PHY register 4 from the 802.3 spec
115 */
116#define CVMX_MDIO_PHY_REG_AUTONEG_ADVER 4
117typedef union {
118	uint16_t u16;
119	struct {
120		uint16_t next_page:1;
121		uint16_t reserved_14:1;
122		uint16_t remote_fault:1;
123		uint16_t reserved_12:1;
124		uint16_t asymmetric_pause:1;
125		uint16_t pause:1;
126		uint16_t advert_100base_t4:1;
127		uint16_t advert_100base_tx_full:1;
128		uint16_t advert_100base_tx_half:1;
129		uint16_t advert_10base_tx_full:1;
130		uint16_t advert_10base_tx_half:1;
131		uint16_t selector:5;
132	} s;
133} cvmx_mdio_phy_reg_autoneg_adver_t;
134
135/**
136 * PHY register 5 from the 802.3 spec
137 */
138#define CVMX_MDIO_PHY_REG_LINK_PARTNER_ABILITY 5
139typedef union {
140	uint16_t u16;
141	struct {
142		uint16_t next_page:1;
143		uint16_t ack:1;
144		uint16_t remote_fault:1;
145		uint16_t reserved_12:1;
146		uint16_t asymmetric_pause:1;
147		uint16_t pause:1;
148		uint16_t advert_100base_t4:1;
149		uint16_t advert_100base_tx_full:1;
150		uint16_t advert_100base_tx_half:1;
151		uint16_t advert_10base_tx_full:1;
152		uint16_t advert_10base_tx_half:1;
153		uint16_t selector:5;
154	} s;
155} cvmx_mdio_phy_reg_link_partner_ability_t;
156
157/**
158 * PHY register 6 from the 802.3 spec
159 */
160#define CVMX_MDIO_PHY_REG_AUTONEG_EXPANSION 6
161typedef union {
162	uint16_t u16;
163	struct {
164		uint16_t reserved_5_15:11;
165		uint16_t parallel_detection_fault:1;
166		uint16_t link_partner_next_page_capable:1;
167		uint16_t local_next_page_capable:1;
168		uint16_t page_received:1;
169		uint16_t link_partner_autoneg_capable:1;
170
171	} s;
172} cvmx_mdio_phy_reg_autoneg_expansion_t;
173
174/**
175 * PHY register 9 from the 802.3 spec
176 */
177#define CVMX_MDIO_PHY_REG_CONTROL_1000 9
178typedef union {
179	uint16_t u16;
180	struct {
181		uint16_t test_mode:3;
182		uint16_t manual_master_slave:1;
183		uint16_t master:1;
184		uint16_t port_type:1;
185		uint16_t advert_1000base_t_full:1;
186		uint16_t advert_1000base_t_half:1;
187		uint16_t reserved_0_7:8;
188	} s;
189} cvmx_mdio_phy_reg_control_1000_t;
190
191/**
192 * PHY register 10 from the 802.3 spec
193 */
194#define CVMX_MDIO_PHY_REG_STATUS_1000 10
195typedef union {
196	uint16_t u16;
197	struct {
198		uint16_t master_slave_fault:1;
199		uint16_t is_master:1;
200		uint16_t local_receiver_ok:1;
201		uint16_t remote_receiver_ok:1;
202		uint16_t remote_capable_1000base_t_full:1;
203		uint16_t remote_capable_1000base_t_half:1;
204		uint16_t reserved_8_9:2;
205		uint16_t idle_error_count:8;
206	} s;
207} cvmx_mdio_phy_reg_status_1000_t;
208
209/**
210 * PHY register 15 from the 802.3 spec
211 */
212#define CVMX_MDIO_PHY_REG_EXTENDED_STATUS 15
213typedef union {
214	uint16_t u16;
215	struct {
216		uint16_t capable_1000base_x_full:1;
217		uint16_t capable_1000base_x_half:1;
218		uint16_t capable_1000base_t_full:1;
219		uint16_t capable_1000base_t_half:1;
220		uint16_t reserved_0_11:12;
221	} s;
222} cvmx_mdio_phy_reg_extended_status_t;
223
224/**
225 * PHY register 13 from the 802.3 spec
226 */
227#define CVMX_MDIO_PHY_REG_MMD_CONTROL 13
228typedef union {
229	uint16_t u16;
230	struct {
231		uint16_t function:2;
232		uint16_t reserved_5_13:9;
233		uint16_t devad:5;
234	} s;
235} cvmx_mdio_phy_reg_mmd_control_t;
236
237/**
238 * PHY register 14 from the 802.3 spec
239 */
240#define CVMX_MDIO_PHY_REG_MMD_ADDRESS_DATA 14
241typedef union {
242	uint16_t u16;
243	struct {
244		uint16_t address_data:16;
245	} s;
246} cvmx_mdio_phy_reg_mmd_address_data_t;
247
248/* Operating request encodings. */
249#define MDIO_CLAUSE_22_WRITE    0
250#define MDIO_CLAUSE_22_READ     1
251
252#define MDIO_CLAUSE_45_ADDRESS  0
253#define MDIO_CLAUSE_45_WRITE    1
254#define MDIO_CLAUSE_45_READ_INC 2
255#define MDIO_CLAUSE_45_READ     3
256
257/* MMD identifiers, mostly for accessing devices withing XENPAK modules. */
258#define CVMX_MMD_DEVICE_PMA_PMD      1
259#define CVMX_MMD_DEVICE_WIS          2
260#define CVMX_MMD_DEVICE_PCS          3
261#define CVMX_MMD_DEVICE_PHY_XS       4
262#define CVMX_MMD_DEVICE_DTS_XS       5
263#define CVMX_MMD_DEVICE_TC           6
264#define CVMX_MMD_DEVICE_CL22_EXT     29
265#define CVMX_MMD_DEVICE_VENDOR_1     30
266#define CVMX_MMD_DEVICE_VENDOR_2     31
267
268/* Helper function to put MDIO interface into clause 45 mode */
269static inline void __cvmx_mdio_set_clause45_mode(int bus_id)
270{
271	union cvmx_smix_clk smi_clk;
272	/* Put bus into clause 45 mode */
273	smi_clk.u64 = cvmx_read_csr(CVMX_SMIX_CLK(bus_id));
274	smi_clk.s.mode = 1;
275	smi_clk.s.preamble = 1;
276	cvmx_write_csr(CVMX_SMIX_CLK(bus_id), smi_clk.u64);
277}
278
279/* Helper function to put MDIO interface into clause 22 mode */
280static inline void __cvmx_mdio_set_clause22_mode(int bus_id)
281{
282	union cvmx_smix_clk smi_clk;
283	/* Put bus into clause 22 mode */
284	smi_clk.u64 = cvmx_read_csr(CVMX_SMIX_CLK(bus_id));
285	smi_clk.s.mode = 0;
286	cvmx_write_csr(CVMX_SMIX_CLK(bus_id), smi_clk.u64);
287}
288
289/**
290 * Perform an MII read. This function is used to read PHY
291 * registers controlling auto negotiation.
292 *
293 * @bus_id:   MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
294 *                 support multiple busses.
295 * @phy_id:   The MII phy id
296 * @location: Register location to read
297 *
298 * Returns Result from the read or -1 on failure
299 */
300static inline int cvmx_mdio_read(int bus_id, int phy_id, int location)
301{
302	union cvmx_smix_cmd smi_cmd;
303	union cvmx_smix_rd_dat smi_rd;
304	int timeout = 1000;
305
306	if (octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45))
307		__cvmx_mdio_set_clause22_mode(bus_id);
308
309	smi_cmd.u64 = 0;
310	smi_cmd.s.phy_op = MDIO_CLAUSE_22_READ;
311	smi_cmd.s.phy_adr = phy_id;
312	smi_cmd.s.reg_adr = location;
313	cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
314
315	do {
316		cvmx_wait(1000);
317		smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id));
318	} while (smi_rd.s.pending && timeout--);
319
320	if (smi_rd.s.val)
321		return smi_rd.s.dat;
322	else
323		return -1;
324}
325
326/**
327 * Perform an MII write. This function is used to write PHY
328 * registers controlling auto negotiation.
329 *
330 * @bus_id:   MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
331 *                 support multiple busses.
332 * @phy_id:   The MII phy id
333 * @location: Register location to write
334 * @val:      Value to write
335 *
336 * Returns -1 on error
337 *         0 on success
338 */
339static inline int cvmx_mdio_write(int bus_id, int phy_id, int location, int val)
340{
341	union cvmx_smix_cmd smi_cmd;
342	union cvmx_smix_wr_dat smi_wr;
343	int timeout = 1000;
344
345	if (octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45))
346		__cvmx_mdio_set_clause22_mode(bus_id);
347
348	smi_wr.u64 = 0;
349	smi_wr.s.dat = val;
350	cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
351
352	smi_cmd.u64 = 0;
353	smi_cmd.s.phy_op = MDIO_CLAUSE_22_WRITE;
354	smi_cmd.s.phy_adr = phy_id;
355	smi_cmd.s.reg_adr = location;
356	cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
357
358	do {
359		cvmx_wait(1000);
360		smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
361	} while (smi_wr.s.pending && --timeout);
362	if (timeout <= 0)
363		return -1;
364
365	return 0;
366}
367
368/**
369 * Perform an IEEE 802.3 clause 45 MII read. This function is used to
370 * read PHY registers controlling auto negotiation.
371 *
372 * @bus_id:   MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
373 *                 support multiple busses.
374 * @phy_id:   The MII phy id
375 * @device:   MDIO Managable Device (MMD) id
376 * @location: Register location to read
377 *
378 * Returns Result from the read or -1 on failure
379 */
380
381static inline int cvmx_mdio_45_read(int bus_id, int phy_id, int device,
382				    int location)
383{
384	union cvmx_smix_cmd smi_cmd;
385	union cvmx_smix_rd_dat smi_rd;
386	union cvmx_smix_wr_dat smi_wr;
387	int timeout = 1000;
388
389	if (!octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45))
390		return -1;
391
392	__cvmx_mdio_set_clause45_mode(bus_id);
393
394	smi_wr.u64 = 0;
395	smi_wr.s.dat = location;
396	cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
397
398	smi_cmd.u64 = 0;
399	smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS;
400	smi_cmd.s.phy_adr = phy_id;
401	smi_cmd.s.reg_adr = device;
402	cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
403
404	do {
405		cvmx_wait(1000);
406		smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
407	} while (smi_wr.s.pending && --timeout);
408	if (timeout <= 0) {
409		cvmx_dprintf("cvmx_mdio_45_read: bus_id %d phy_id %2d "
410			     "device %2d register %2d   TIME OUT(address)\n",
411		     bus_id, phy_id, device, location);
412		return -1;
413	}
414
415	smi_cmd.u64 = 0;
416	smi_cmd.s.phy_op = MDIO_CLAUSE_45_READ;
417	smi_cmd.s.phy_adr = phy_id;
418	smi_cmd.s.reg_adr = device;
419	cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
420
421	do {
422		cvmx_wait(1000);
423		smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(bus_id));
424	} while (smi_rd.s.pending && --timeout);
425
426	if (timeout <= 0) {
427		cvmx_dprintf("cvmx_mdio_45_read: bus_id %d phy_id %2d "
428			     "device %2d register %2d   TIME OUT(data)\n",
429		     bus_id, phy_id, device, location);
430		return -1;
431	}
432
433	if (smi_rd.s.val)
434		return smi_rd.s.dat;
435	else {
436		cvmx_dprintf("cvmx_mdio_45_read: bus_id %d phy_id %2d "
437			     "device %2d register %2d   INVALID READ\n",
438		     bus_id, phy_id, device, location);
439		return -1;
440	}
441}
442
443/**
444 * Perform an IEEE 802.3 clause 45 MII write. This function is used to
445 * write PHY registers controlling auto negotiation.
446 *
447 * @bus_id:   MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
448 *                 support multiple busses.
449 * @phy_id:   The MII phy id
450 * @device:   MDIO Managable Device (MMD) id
451 * @location: Register location to write
452 * @val:      Value to write
453 *
454 * Returns -1 on error
455 *         0 on success
456 */
457static inline int cvmx_mdio_45_write(int bus_id, int phy_id, int device,
458				     int location, int val)
459{
460	union cvmx_smix_cmd smi_cmd;
461	union cvmx_smix_wr_dat smi_wr;
462	int timeout = 1000;
463
464	if (!octeon_has_feature(OCTEON_FEATURE_MDIO_CLAUSE_45))
465		return -1;
466
467	__cvmx_mdio_set_clause45_mode(bus_id);
468
469	smi_wr.u64 = 0;
470	smi_wr.s.dat = location;
471	cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
472
473	smi_cmd.u64 = 0;
474	smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS;
475	smi_cmd.s.phy_adr = phy_id;
476	smi_cmd.s.reg_adr = device;
477	cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
478
479	do {
480		cvmx_wait(1000);
481		smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
482	} while (smi_wr.s.pending && --timeout);
483	if (timeout <= 0)
484		return -1;
485
486	smi_wr.u64 = 0;
487	smi_wr.s.dat = val;
488	cvmx_write_csr(CVMX_SMIX_WR_DAT(bus_id), smi_wr.u64);
489
490	smi_cmd.u64 = 0;
491	smi_cmd.s.phy_op = MDIO_CLAUSE_45_WRITE;
492	smi_cmd.s.phy_adr = phy_id;
493	smi_cmd.s.reg_adr = device;
494	cvmx_write_csr(CVMX_SMIX_CMD(bus_id), smi_cmd.u64);
495
496	do {
497		cvmx_wait(1000);
498		smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(bus_id));
499	} while (smi_wr.s.pending && --timeout);
500	if (timeout <= 0)
501		return -1;
502
503	return 0;
504}
505
506#endif
507