xref: /dpdk/drivers/net/ionic/ionic_dev.c (revision 23bf4ddb)
1 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2  * Copyright(c) 2018-2019 Pensando Systems, Inc. All rights reserved.
3  */
4 
5 #include <rte_malloc.h>
6 
7 #include "ionic_dev.h"
8 #include "ionic.h"
9 
10 int
11 ionic_dev_setup(struct ionic_adapter *adapter)
12 {
13 	struct ionic_dev_bar *bar = adapter->bars;
14 	unsigned int num_bars = adapter->num_bars;
15 	struct ionic_dev *idev = &adapter->idev;
16 	uint32_t sig;
17 	u_char *bar0_base;
18 
19 	/* BAR0: dev_cmd and interrupts */
20 	if (num_bars < 1) {
21 		IONIC_PRINT(ERR, "No bars found, aborting");
22 		return -EFAULT;
23 	}
24 
25 	if (bar->len < IONIC_BAR0_SIZE) {
26 		IONIC_PRINT(ERR,
27 			"Resource bar size %lu too small, aborting",
28 			bar->len);
29 		return -EFAULT;
30 	}
31 
32 	bar0_base = bar->vaddr;
33 	idev->dev_info = (union ionic_dev_info_regs *)
34 		&bar0_base[IONIC_BAR0_DEV_INFO_REGS_OFFSET];
35 	idev->dev_cmd = (union ionic_dev_cmd_regs *)
36 		&bar0_base[IONIC_BAR0_DEV_CMD_REGS_OFFSET];
37 	idev->intr_status = (struct ionic_intr_status *)
38 		&bar0_base[IONIC_BAR0_INTR_STATUS_OFFSET];
39 	idev->intr_ctrl = (struct ionic_intr *)
40 		&bar0_base[IONIC_BAR0_INTR_CTRL_OFFSET];
41 
42 	sig = ioread32(&idev->dev_info->signature);
43 	if (sig != IONIC_DEV_INFO_SIGNATURE) {
44 		IONIC_PRINT(ERR, "Incompatible firmware signature %" PRIx32 "",
45 			sig);
46 		return -EFAULT;
47 	}
48 
49 	/* BAR1: doorbells */
50 	bar++;
51 	if (num_bars < 2) {
52 		IONIC_PRINT(ERR, "Doorbell bar missing, aborting");
53 		return -EFAULT;
54 	}
55 
56 	idev->db_pages = bar->vaddr;
57 	idev->phy_db_pages = bar->bus_addr;
58 
59 	return 0;
60 }
61 
62 /* Devcmd Interface */
63 
64 uint8_t
65 ionic_dev_cmd_status(struct ionic_dev *idev)
66 {
67 	return ioread8(&idev->dev_cmd->comp.comp.status);
68 }
69 
70 bool
71 ionic_dev_cmd_done(struct ionic_dev *idev)
72 {
73 	return ioread32(&idev->dev_cmd->done) & IONIC_DEV_CMD_DONE;
74 }
75 
76 void
77 ionic_dev_cmd_comp(struct ionic_dev *idev, void *mem)
78 {
79 	union ionic_dev_cmd_comp *comp = mem;
80 	unsigned int i;
81 	uint32_t comp_size = sizeof(comp->words) /
82 		sizeof(comp->words[0]);
83 
84 	for (i = 0; i < comp_size; i++)
85 		comp->words[i] = ioread32(&idev->dev_cmd->comp.words[i]);
86 }
87 
88 void
89 ionic_dev_cmd_go(struct ionic_dev *idev, union ionic_dev_cmd *cmd)
90 {
91 	unsigned int i;
92 	uint32_t cmd_size = sizeof(cmd->words) /
93 		sizeof(cmd->words[0]);
94 
95 	for (i = 0; i < cmd_size; i++)
96 		iowrite32(cmd->words[i], &idev->dev_cmd->cmd.words[i]);
97 
98 	iowrite32(0, &idev->dev_cmd->done);
99 	iowrite32(1, &idev->dev_cmd->doorbell);
100 }
101 
102 /* Device commands */
103 
104 void
105 ionic_dev_cmd_identify(struct ionic_dev *idev, uint8_t ver)
106 {
107 	union ionic_dev_cmd cmd = {
108 		.identify.opcode = IONIC_CMD_IDENTIFY,
109 		.identify.ver = ver,
110 	};
111 
112 	ionic_dev_cmd_go(idev, &cmd);
113 }
114 
115 void
116 ionic_dev_cmd_init(struct ionic_dev *idev)
117 {
118 	union ionic_dev_cmd cmd = {
119 		.init.opcode = IONIC_CMD_INIT,
120 		.init.type = 0,
121 	};
122 
123 	ionic_dev_cmd_go(idev, &cmd);
124 }
125 
126 void
127 ionic_dev_cmd_reset(struct ionic_dev *idev)
128 {
129 	union ionic_dev_cmd cmd = {
130 		.reset.opcode = IONIC_CMD_RESET,
131 	};
132 
133 	ionic_dev_cmd_go(idev, &cmd);
134 }
135 
136 /* Port commands */
137 
138 void
139 ionic_dev_cmd_port_identify(struct ionic_dev *idev)
140 {
141 	union ionic_dev_cmd cmd = {
142 		.port_init.opcode = IONIC_CMD_PORT_IDENTIFY,
143 		.port_init.index = 0,
144 	};
145 
146 	ionic_dev_cmd_go(idev, &cmd);
147 }
148 
149 void
150 ionic_dev_cmd_port_init(struct ionic_dev *idev)
151 {
152 	union ionic_dev_cmd cmd = {
153 		.port_init.opcode = IONIC_CMD_PORT_INIT,
154 		.port_init.index = 0,
155 		.port_init.info_pa = idev->port_info_pa,
156 	};
157 
158 	ionic_dev_cmd_go(idev, &cmd);
159 }
160 
161 void
162 ionic_dev_cmd_port_reset(struct ionic_dev *idev)
163 {
164 	union ionic_dev_cmd cmd = {
165 		.port_reset.opcode = IONIC_CMD_PORT_RESET,
166 		.port_reset.index = 0,
167 	};
168 
169 	ionic_dev_cmd_go(idev, &cmd);
170 }
171 
172 void
173 ionic_dev_cmd_port_state(struct ionic_dev *idev, uint8_t state)
174 {
175 	union ionic_dev_cmd cmd = {
176 		.port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
177 		.port_setattr.index = 0,
178 		.port_setattr.attr = IONIC_PORT_ATTR_STATE,
179 		.port_setattr.state = state,
180 	};
181 
182 	ionic_dev_cmd_go(idev, &cmd);
183 }
184 
185 void
186 ionic_dev_cmd_port_speed(struct ionic_dev *idev, uint32_t speed)
187 {
188 	union ionic_dev_cmd cmd = {
189 		.port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
190 		.port_setattr.index = 0,
191 		.port_setattr.attr = IONIC_PORT_ATTR_SPEED,
192 		.port_setattr.speed = speed,
193 	};
194 
195 	ionic_dev_cmd_go(idev, &cmd);
196 }
197 
198 void
199 ionic_dev_cmd_port_mtu(struct ionic_dev *idev, uint32_t mtu)
200 {
201 	union ionic_dev_cmd cmd = {
202 		.port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
203 		.port_setattr.index = 0,
204 		.port_setattr.attr = IONIC_PORT_ATTR_MTU,
205 		.port_setattr.mtu = mtu,
206 	};
207 
208 	ionic_dev_cmd_go(idev, &cmd);
209 }
210 
211 void
212 ionic_dev_cmd_port_autoneg(struct ionic_dev *idev, uint8_t an_enable)
213 {
214 	union ionic_dev_cmd cmd = {
215 		.port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
216 		.port_setattr.index = 0,
217 		.port_setattr.attr = IONIC_PORT_ATTR_AUTONEG,
218 		.port_setattr.an_enable = an_enable,
219 	};
220 
221 	ionic_dev_cmd_go(idev, &cmd);
222 }
223 
224 void
225 ionic_dev_cmd_port_fec(struct ionic_dev *idev, uint8_t fec_type)
226 {
227 	union ionic_dev_cmd cmd = {
228 		.port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
229 		.port_setattr.index = 0,
230 		.port_setattr.attr = IONIC_PORT_ATTR_FEC,
231 		.port_setattr.fec_type = fec_type,
232 	};
233 
234 	ionic_dev_cmd_go(idev, &cmd);
235 }
236 
237 void
238 ionic_dev_cmd_port_pause(struct ionic_dev *idev, uint8_t pause_type)
239 {
240 	union ionic_dev_cmd cmd = {
241 		.port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
242 		.port_setattr.index = 0,
243 		.port_setattr.attr = IONIC_PORT_ATTR_PAUSE,
244 		.port_setattr.pause_type = pause_type,
245 	};
246 
247 	ionic_dev_cmd_go(idev, &cmd);
248 }
249 
250 void
251 ionic_dev_cmd_port_loopback(struct ionic_dev *idev, uint8_t loopback_mode)
252 {
253 	union ionic_dev_cmd cmd = {
254 		.port_setattr.opcode = IONIC_CMD_PORT_SETATTR,
255 		.port_setattr.index = 0,
256 		.port_setattr.attr = IONIC_PORT_ATTR_LOOPBACK,
257 		.port_setattr.loopback_mode = loopback_mode,
258 	};
259 
260 	ionic_dev_cmd_go(idev, &cmd);
261 }
262