-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathael2005_conf.c
151 lines (131 loc) · 3.61 KB
/
ael2005_conf.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include "nf10.h"
#include "ael2005_conf.h"
irqreturn_t mdio_access_interrupt_handler(int irq, void *dev_id)
{
struct pci_dev *pdev = dev_id;
struct nf10_adapter *adapter = (struct nf10_adapter *)pci_get_drvdata(pdev);
/* signals mdio write finished */
atomic_set(&adapter->mdio_access_rdy, 1);
return IRQ_HANDLED;
}
int configure_ael2005_phy_chips(struct nf10_adapter *adapter)
{
int ret = -ENODEV;
u8 OP_CODE;
u8 PRTAD;
u8 DEVAD;
u16 ADDR, WRITE_DATA;
int size, i;
int timeout = 0;
pr_info("PHY: AEL2005 Initialization Start...\n");
/* We only need interface 3 in this project
* don't forget that the nearest port to PCIe is hardwired to 0x2 */
for(PRTAD = 3; PRTAD < 4; PRTAD++) {
DEVAD = MDIO_MMD_PMAPMD;
/* Step 1: write reset registers */
size = sizeof(reset) / sizeof(u16);
for(i = 0; i < size; i += 2) {
/* MDIO clause 45 Set Address Transaction */
atomic_set(&adapter->mdio_access_rdy, 0);
/* Send Memory Write Request TLP */
OP_CODE = 0x0;
ADDR = reset[i];
*(((u32 *)adapter->bar0) + 4) =
(OP_CODE << 26) |
(PRTAD << 21) |
(DEVAD << 16) |
ADDR;
do {
msleep(2);
timeout++;
/* if it takes too long,
* hw is not working properly */
if (timeout > 20)
return ret;
} while (!atomic_read(&adapter->mdio_access_rdy));
/* MDIO clause 45 Write Transaction */
atomic_set(&adapter->mdio_access_rdy, 0);
/* Send Memory Write Request TLP */
OP_CODE = 0x1;
WRITE_DATA = reset[i+1];
*(((u32 *)adapter->bar0) + 4) =
(OP_CODE << 26) |
(PRTAD << 21) |
(DEVAD << 16) |
WRITE_DATA;
do {
msleep(2);
} while (!atomic_read(&adapter->mdio_access_rdy));
}
/* Step 2: write sr_edc or twinax_edc registers.
* (depending on the sfp+ modules) */
size = sizeof(sr_edc) / sizeof(u16);
for (i = 0; i < size; i += 2) {
/* MDIO clause 45 Set Address Transaction */
atomic_set(&adapter->mdio_access_rdy, 0);
/* Send Memory Write Request TLP */
OP_CODE = 0x0;
ADDR = sr_edc[i];
*(((u32 *)adapter->bar0) + 4) =
(OP_CODE << 26) |
(PRTAD << 21) |
(DEVAD << 16) |
ADDR;
do {
msleep(2);
} while (!atomic_read(&adapter->mdio_access_rdy));
/* MDIO clause 45 Write Transaction */
atomic_set(&adapter->mdio_access_rdy, 0);
/* Send Memory Write Request TLP */
OP_CODE = 0x1;
WRITE_DATA = sr_edc[i+1];
*(((u32 *)adapter->bar0) + 4) =
(OP_CODE << 26) |
(PRTAD << 21) |
(DEVAD << 16) |
WRITE_DATA;
do {
msleep(2);
} while (!atomic_read(&adapter->mdio_access_rdy));
}
/* Step 1: write regs1 registers */
size = sizeof(regs1) / sizeof(u16);
for(i = 0; i < size; i += 2) {
/* MDIO clause 45 Set Address Transaction */
atomic_set(&adapter->mdio_access_rdy, 0);
/* Send Memory Write Request TLP */
OP_CODE = 0x0;
ADDR = regs1[i];
*(((u32 *)adapter->bar0) + 4) =
(OP_CODE << 26) |
(PRTAD << 21) |
(DEVAD << 16) |
ADDR;
do {
msleep(2);
} while (!atomic_read(&adapter->mdio_access_rdy));
/* MDIO clause 45 Write Transaction */
atomic_set(&adapter->mdio_access_rdy, 0);
/* Send Memory Write Request TLP */
OP_CODE = 0x1;
WRITE_DATA = regs1[i+1];
*(((u32 *)adapter->bar0) + 4) =
(OP_CODE << 26) |
(PRTAD << 21) |
(DEVAD << 16) |
WRITE_DATA;
do {
msleep(2);
} while (!atomic_read(&adapter->mdio_access_rdy));
}
}
pr_info("PHY: AEL2005 Initialization Finished...\n");
return 0;
}