/
open_alliance.h
197 lines (173 loc) · 5.45 KB
/
open_alliance.h
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/**
* Open Alliance SPI protocol driver for 10BASE-T1x Ethernet MAC-PHY
*
* Copyright 2021 Analog Devices Inc.
*/
#ifndef __OPEN_ALLIANCE_H
#define __OPEN_ALLIANCE_H
#include <linux/cache.h>
#include <linux/kernel.h>
#include <linux/kfifo.h>
#include <linux/netdevice.h>
#include <linux/spi/spi.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <asm/unaligned.h>
/* Register Memory Maps */
#define OPEN_ALLIANCE_CTRL_ST 0
/* Register Memory Map 0 - Standard Control and Status Registers */
/* Configuration Register #0 */
#define OPEN_ALLIANCE_CONFIG0 0x0004
#define OPEN_ALLIANCE_CONFIG0_SYNC BIT(15)
#define OPEN_ALLIANCE_CONFIG0_ZARFE BIT(12)
/* Buffer Status Register */
#define OPEN_ALLIANCE_BUFSTS 0x000B
#define OPEN_ALLIANCE_BUFSTS_TXC GENMASK(15, 8)
#define OPEN_ALLIANCE_BUFSTS_RCA GENMASK(7, 0)
/* Transmit/Receiver Data common bitfields */
#define OPEN_ALLIANCE_VS GENMASK(23, 22)
#define OPEN_ALLIANCE_DV BIT(21)
#define OPEN_ALLIANCE_SV BIT(20)
#define OPEN_ALLIANCE_SWO GENMASK(19, 16)
#define OPEN_ALLIANCE_EV BIT(14)
#define OPEN_ALLIANCE_EBO GENMASK(13, 8)
#define OPEN_ALLIANCE_P BIT(0)
/* Transmit Data Header bitfields */
#define OPEN_ALLIANCE_DNC BIT(31)
#define OPEN_ALLIANCE_SEQ BIT(30)
#define OPEN_ALLIANCE_NORX BIT(29)
#define OPEN_ALLIANCE_TSC GENMASK(7, 6)
/* Receive Data Footer bitfields */
#define OPEN_ALLIANCE_EXST BIT(31)
#define OPEN_ALLIANCE_HDRB BIT(30)
#define OPEN_ALLIANCE_SYNC BIT(29)
#define OPEN_ALLIANCE_RCA GENMASK(28, 24)
#define OPEN_ALLIANCE_FD BIT(15)
#define OPEN_ALLIANCE_RTSA BIT(7)
#define OPEN_ALLIANCE_RTSP BIT(6)
#define OPEN_ALLIANCE_TXC GENMASK(5, 1)
/* Control Command Header bitfields */
#define OPEN_ALLIANCE_WNR BIT(29)
#define OPEN_ALLIANCE_AID BIT(28)
#define OPEN_ALLIANCE_MMS GENMASK(27, 24)
#define OPEN_ALLIANCE_ADDR GENMASK(23, 8)
#define OPEN_ALLIANCE_LEN GENMASK(7, 1)
/* Register Memory Maps */
#define OPEN_ALLIANCE_MMS_CTRL 0
#define OPEN_ALLIANCE_MMS_MAC 1
#define OPEN_ALLIANCE_MAX_BUFF 2048
#define OPEN_ALLIANCE_MAX_CHUNKS_NR 2048
#define OPEN_ALLIANCE_MAX_CHUNK_DATA 64
#define OPEN_ALLIANCE_HEADER_SIZE 4
#define OPEN_ALLIANCE_MAX_REG_SIZE 4
#define OPEN_ALLIANCE_MAX_PORTS 4
struct open_alliance_data_tx_chunk {
u8 dnc:1;
u8 seq:1;
u8 norx:1;
u8 vs:2;
u8 dv:1;
u8 sv:1;
u8 swo:4;
u8 ev:1;
u8 ebo:6;
u8 tsc:2;
u8 data[OPEN_ALLIANCE_MAX_CHUNK_DATA];
};
struct open_alliance_data_rx_chunk {
u8 exst:1;
u8 hdrb:1;
u8 sync:1;
u8 rca:5;
u8 vs:2;
u8 dv:1;
u8 sv:1;
u8 swo:4;
u8 fd:1;
u8 ev:1;
u8 ebo:6;
u8 rtsa:1;
u8 rtsp:1;
u8 txc:5;
u8 tsc:2;
u8 data[OPEN_ALLIANCE_MAX_CHUNK_DATA];
};
struct open_alliance_ctrl_tx_chunk {
u8 wnr:1;
u8 aid:1;
u8 mms:3;
u16 addr;
u8 len:7;
u8 data[OPEN_ALLIANCE_MAX_CHUNK_DATA];
};
struct open_alliance_rx_frame {
int port;
int chunks_len;
};
enum open_alliance_stats {
OA_RX_CHUNKS_RECEIVED = 0,
OA_TX_CHUNKS_SENT,
OA_RX_END_VALID_RECEIVED,
OA_RX_CHUNKS_TO_FRAMES,
OA_CHUNKS_TRANSFERED,
};
struct open_alliance_statistic {
enum open_alliance_stats nr;
const char name[ETH_GSTRING_LEN];
};
static const struct open_alliance_statistic open_alliance_statistics[] = {
{ OA_RX_CHUNKS_RECEIVED, "RX valid data chunks received", },
{ OA_TX_CHUNKS_SENT, "TX chunks sent", },
{ OA_RX_END_VALID_RECEIVED, "RX end valid chunks received", },
{ OA_RX_CHUNKS_TO_FRAMES, "RX chunks to frames", },
{ OA_CHUNKS_TRANSFERED, "OA chunks transfered", },
};
struct open_alliance {
struct mutex spi_lock; /* protect spi */
spinlock_t rx_lock; /* protect rx chunks fifo */
spinlock_t tx_lock; /* protect tx chunks fifo */
struct spi_device *spidev;
struct net_device *netdevs[OPEN_ALLIANCE_MAX_PORTS];
u64 statistics[ARRAY_SIZE(open_alliance_statistics)];
u32 chunk_size;
bool protected;
u32 nr_ports;
u32 vs_mask;
struct napi_struct napi;
bool enabled;
int (*set_rx_irq)(void *, bool);
void *priv;
struct work_struct irq_rx_work; /* enable/disable RX Ready IRQs */
struct task_struct *spi_thread;
u32 txc;
u32 rca;
bool rx_irq_masked;
DECLARE_KFIFO_PTR(tx_chunks_kfifo, struct open_alliance_data_tx_chunk);
DECLARE_KFIFO_PTR(rx_ports_fifo, struct open_alliance_rx_frame);
DECLARE_KFIFO_PTR(rx_chunks_fifos, struct open_alliance_data_rx_chunk)[OPEN_ALLIANCE_MAX_PORTS];
u8 frame_data[OPEN_ALLIANCE_MAX_BUFF];
u8 tx_data[OPEN_ALLIANCE_MAX_BUFF];
u8 rx_data[OPEN_ALLIANCE_MAX_BUFF] ____cacheline_aligned;
};
int open_alliance_net_open(struct open_alliance *oa);
int open_alliance_net_stop(struct open_alliance *oa);
int open_alliance_write_reg(struct open_alliance *oa, u8 mms, u16 addr,
u32 val);
int open_alliance_read_reg(struct open_alliance *oa, u8 mms, u16 addr,
u32 *val);
int open_alliance_write_txb(struct open_alliance *oa, struct sk_buff *txb, u8 vs);
int open_alliance_read_rxb(struct open_alliance *oa);
int open_alliance_tx_space(struct open_alliance *oa);
struct open_alliance *open_alliance_init(struct spi_device *spidev,
struct net_device *netdevs[OPEN_ALLIANCE_MAX_PORTS],
u32 nr_ports,
u32 vs_mask,
int (*set_rx_irq)(void *, bool),
void *p);
int open_alliance_remove(struct open_alliance *oa);
void open_alliance_ethtool_get_strings(struct open_alliance *oa, u32 sset, u8 *data);
int open_alliance_ethtool_get_sset_count(struct open_alliance *oa, int sset);
void open_alliance_ethtool_get_stats(struct open_alliance *oa, struct ethtool_stats *stats,
u64 *data);
#endif /* __OPEN_ALLIANCE_H */