27 #include "../switchtec_priv.h" 28 #include "switchtec/utils.h" 36 #define gas_reg_read8(dev, reg) __gas_read8(dev, &dev->gas_map->reg) 37 #define gas_reg_read16(dev, reg) __gas_read16(dev, &dev->gas_map->reg) 38 #define gas_reg_read32(dev, reg) __gas_read32(dev, &dev->gas_map->reg) 39 #define gas_reg_read64(dev, reg) __gas_read64(dev, &dev->gas_map->reg) 41 #define gas_reg_write8(dev, val, reg) __gas_write8(dev, val, \ 43 #define gas_reg_write16(dev, val, reg) __gas_write16(dev, val, \ 45 #define gas_reg_write32(dev, val, reg) __gas_write32(dev, val, \ 47 #define gas_reg_write64(dev, val, reg) __gas_write64(dev, val, \ 50 static const char gasop_noretry_cmds[] = {
51 [MRPC_SECURITY_CONFIG_SET] = 1,
52 [MRPC_KMSK_ENTRY_SET] = 1,
53 [MRPC_SECURE_STATE_SET] = 1,
54 [MRPC_BOOTUP_RESUME] = 1,
55 [MRPC_DBG_UNLOCK] = 1,
57 static const int gasop_noretry_cmds_count =
sizeof(gasop_noretry_cmds) /
60 static inline bool gasop_is_no_retry_cmd(uint32_t cmd)
62 cmd &= SWITCHTEC_CMD_MASK;
64 if (cmd >= gasop_noretry_cmds_count)
66 return gasop_noretry_cmds[cmd];
69 int gasop_access_check(
struct switchtec_dev *dev)
73 device_id = gas_reg_read32(dev, sys_info.device_id);
79 void gasop_set_partition_info(
struct switchtec_dev *dev)
81 dev->partition = gas_reg_read8(dev, top.partition_id);
82 dev->partition_count = gas_reg_read8(dev, top.partition_count);
85 int gasop_cmd(
struct switchtec_dev *dev, uint32_t cmd,
86 const void *payload,
size_t payload_len,
void *resp,
89 struct mrpc_regs __gas *mrpc = &dev->gas_map->mrpc;
93 __memcpy_to_gas(dev, &mrpc->input_data, payload, payload_len);
108 if (gasop_is_no_retry_cmd(cmd))
109 __gas_write32_no_retry(dev, cmd, &mrpc->cmd);
111 __gas_write32(dev, cmd, &mrpc->cmd);
116 status = __gas_read32(dev, &mrpc->status);
117 if (status != SWITCHTEC_MRPC_STATUS_INPROGRESS)
121 if (status == SWITCHTEC_MRPC_STATUS_INTERRUPTED) {
126 if(status == SWITCHTEC_MRPC_STATUS_ERROR) {
127 errno = __gas_read32(dev, &mrpc->ret_value);
131 if (status != SWITCHTEC_MRPC_STATUS_DONE) {
136 ret = __gas_read32(dev, &mrpc->ret_value);
141 __memcpy_from_gas(dev, resp, &mrpc->output_data, resp_len);
146 int gasop_get_device_id(
struct switchtec_dev *dev)
148 return gas_reg_read32(dev, sys_info.device_id);
151 int gasop_get_fw_version(
struct switchtec_dev *dev,
char *buf,
156 ver = gas_reg_read32(dev, sys_info.firmware_version);
157 version_to_string(ver, buf, buflen);
162 int gasop_pff_to_port(
struct switchtec_dev *dev,
int pff,
163 int *partition,
int *port)
171 for (part = 0; part < dev->partition_count; part++) {
172 pcfg = &dev->gas_map->part_cfg[part];
175 reg = __gas_read32(dev, &pcfg->usp_pff_inst_id);
181 reg = __gas_read32(dev, &pcfg->vep_pff_inst_id);
183 *port = SWITCHTEC_PFF_PORT_VEP;
187 for (i = 0; i < ARRAY_SIZE(pcfg->dsp_pff_inst_id); i++) {
188 reg = __gas_read32(dev, &pcfg->dsp_pff_inst_id[i]);
204 int gasop_port_to_pff(
struct switchtec_dev *dev,
int partition,
210 partition = dev->partition;
211 }
else if (partition >= dev->partition_count) {
216 pcfg = &dev->gas_map->part_cfg[partition];
220 *pff = __gas_read32(dev, &pcfg->usp_pff_inst_id);
222 case SWITCHTEC_PFF_PORT_VEP:
223 *pff = __gas_read32(dev, &pcfg->vep_pff_inst_id);
226 if (port > ARRAY_SIZE(pcfg->dsp_pff_inst_id)) {
231 *pff = __gas_read32(dev, &pcfg->dsp_pff_inst_id[port - 1]);
238 static void set_fw_info_part(
struct switchtec_dev *dev,
240 struct partition_info __gas *pi)
242 info->
part_addr = __gas_read32(dev, &pi->address);
243 info->
part_len = __gas_read32(dev, &pi->length);
246 int gasop_flash_part(
struct switchtec_dev *dev,
248 enum switchtec_fw_image_part_id_gen3 part)
252 uint32_t active_addr = -1;
255 memset(info, 0,
sizeof(*info));
258 case SWITCHTEC_FW_PART_ID_G3_IMG0:
259 active_addr = __gas_read32(dev, &fi->active_img.address);
260 set_fw_info_part(dev, info, &fi->img0);
262 val = __gas_read16(dev, &si->img_running);
263 if (val == SWITCHTEC_IMG0_RUNNING)
264 info->running =
true;
267 case SWITCHTEC_FW_PART_ID_G3_IMG1:
268 active_addr = __gas_read32(dev, &fi->active_img.address);
269 set_fw_info_part(dev, info, &fi->img1);
271 val = __gas_read16(dev, &si->img_running);
272 if (val == SWITCHTEC_IMG1_RUNNING)
273 info->running =
true;
276 case SWITCHTEC_FW_PART_ID_G3_DAT0:
277 active_addr = __gas_read32(dev, &fi->active_cfg.address);
278 set_fw_info_part(dev, info, &fi->cfg0);
280 val = __gas_read16(dev, &si->cfg_running);
281 if (val == SWITCHTEC_CFG0_RUNNING)
282 info->running =
true;
285 case SWITCHTEC_FW_PART_ID_G3_DAT1:
286 active_addr = __gas_read32(dev, &fi->active_cfg.address);
287 set_fw_info_part(dev, info, &fi->cfg1);
289 val = __gas_read16(dev, &si->cfg_running);
290 if (val == SWITCHTEC_CFG1_RUNNING)
291 info->running =
true;
294 case SWITCHTEC_FW_PART_ID_G3_NVLOG:
295 set_fw_info_part(dev, info, &fi->nvlog);
308 int gasop_event_summary(
struct switchtec_dev *dev,
317 memset(sum, 0,
sizeof(*sum));
319 sum->
global = gas_reg_read32(dev, sw_event.global_summary);
320 sum->
part_bitmap = gas_reg_read64(dev, sw_event.part_event_bitmap);
322 for (i = 0; i < dev->partition_count; i++) {
323 reg = gas_reg_read32(dev, part_cfg[i].part_event_summary);
325 if (i == dev->partition)
329 for (i = 0; i < SWITCHTEC_MAX_PFF_CSR; i++) {
330 reg = gas_reg_read16(dev, pff_csr[i].vendor_id);
331 if (reg != MICROSEMI_VENDOR_ID)
334 sum->
pff[i] = gas_reg_read32(dev, pff_csr[i].pff_event_summary);
340 static uint32_t __gas *global_ev_reg(
struct switchtec_dev *dev,
341 size_t offset,
int index)
343 return (
void __gas *)&dev->gas_map->sw_event + offset;
346 static uint32_t __gas *part_ev_reg(
struct switchtec_dev *dev,
347 size_t offset,
int index)
349 return (
void __gas *)&dev->gas_map->part_cfg[index] + offset;
352 static uint32_t __gas *pff_ev_reg(
struct switchtec_dev *dev,
353 size_t offset,
int index)
355 return (
void __gas *)&dev->gas_map->pff_csr[index] + offset;
358 #define EV_GLB(i, r)[SWITCHTEC_GLOBAL_EVT_ ## i] = \ 359 {offsetof(struct sw_event_regs, r), global_ev_reg} 360 #define EV_PAR(i, r)[SWITCHTEC_PART_EVT_ ## i] = \ 361 {offsetof(struct part_cfg_regs, r), part_ev_reg} 362 #define EV_PFF(i, r)[SWITCHTEC_PFF_EVT_ ## i] = \ 363 {offsetof(struct pff_csr_regs, r), pff_ev_reg} 367 uint32_t __gas *(*map_reg)(
struct switchtec_dev *stdev,
368 size_t offset,
int index);
370 EV_GLB(STACK_ERROR, stack_error_event_hdr),
371 EV_GLB(PPU_ERROR, ppu_error_event_hdr),
372 EV_GLB(ISP_ERROR, isp_error_event_hdr),
373 EV_GLB(SYS_RESET, sys_reset_event_hdr),
374 EV_GLB(FW_EXC, fw_exception_hdr),
375 EV_GLB(FW_NMI, fw_nmi_hdr),
376 EV_GLB(FW_NON_FATAL, fw_non_fatal_hdr),
377 EV_GLB(FW_FATAL, fw_fatal_hdr),
378 EV_GLB(TWI_MRPC_COMP, twi_mrpc_comp_hdr),
379 EV_GLB(TWI_MRPC_COMP_ASYNC, twi_mrpc_comp_async_hdr),
380 EV_GLB(CLI_MRPC_COMP, cli_mrpc_comp_hdr),
381 EV_GLB(CLI_MRPC_COMP_ASYNC, cli_mrpc_comp_async_hdr),
382 EV_GLB(GPIO_INT, gpio_interrupt_hdr),
383 EV_GLB(GFMS, gfms_event_hdr),
384 EV_PAR(PART_RESET, part_reset_hdr),
385 EV_PAR(MRPC_COMP, mrpc_comp_hdr),
386 EV_PAR(MRPC_COMP_ASYNC, mrpc_comp_async_hdr),
387 EV_PAR(DYN_PART_BIND_COMP, dyn_binding_hdr),
388 EV_PFF(AER_IN_P2P, aer_in_p2p_hdr),
389 EV_PFF(AER_IN_VEP, aer_in_vep_hdr),
390 EV_PFF(DPC, dpc_hdr),
391 EV_PFF(CTS, cts_hdr),
392 EV_PFF(UEC, uec_hdr),
393 EV_PFF(HOTPLUG, hotplug_hdr),
394 EV_PFF(IER, ier_hdr),
395 EV_PFF(THRESH, threshold_hdr),
396 EV_PFF(POWER_MGMT, power_mgmt_hdr),
397 EV_PFF(TLP_THROTTLING, tlp_throttling_hdr),
398 EV_PFF(FORCE_SPEED, force_speed_hdr),
399 EV_PFF(CREDIT_TIMEOUT, credit_timeout_hdr),
400 EV_PFF(LINK_STATE, link_state_hdr),
403 static uint32_t __gas *event_hdr_addr(
struct switchtec_dev *dev,
409 if (e < 0 || e >= SWITCHTEC_MAX_EVENTS)
412 off = event_regs[e].offset;
414 if (event_regs[e].map_reg == part_ev_reg) {
416 index = dev->partition;
417 else if (index >= dev->partition_count)
419 }
else if (event_regs[e].map_reg == pff_ev_reg) {
420 if (index < 0 || index >= SWITCHTEC_MAX_PFF_CSR)
424 return event_regs[e].map_reg(dev, off, index);
428 int index,
int flags, uint32_t data[5])
434 reg = event_hdr_addr(dev, e, index);
440 hdr = __gas_read32(dev, reg);
442 for (i = 0; i < 5; i++)
443 data[i] = __gas_read32(dev, ®[i + 1]);
445 if (!(flags & SWITCHTEC_EVT_FLAG_CLEAR))
446 hdr &= ~SWITCHTEC_EVENT_CLEAR;
447 if (flags & SWITCHTEC_EVT_FLAG_EN_POLL)
448 hdr |= SWITCHTEC_EVENT_EN_IRQ;
449 if (flags & SWITCHTEC_EVT_FLAG_EN_LOG)
450 hdr |= SWITCHTEC_EVENT_EN_LOG;
451 if (flags & SWITCHTEC_EVT_FLAG_EN_CLI)
452 hdr |= SWITCHTEC_EVENT_EN_CLI;
453 if (flags & SWITCHTEC_EVT_FLAG_EN_FATAL)
454 hdr |= SWITCHTEC_EVENT_FATAL;
455 if (flags & SWITCHTEC_EVT_FLAG_DIS_POLL)
456 hdr &= ~SWITCHTEC_EVENT_EN_IRQ;
457 if (flags & SWITCHTEC_EVT_FLAG_DIS_LOG)
458 hdr &= ~SWITCHTEC_EVENT_EN_LOG;
459 if (flags & SWITCHTEC_EVT_FLAG_DIS_CLI)
460 hdr &= ~SWITCHTEC_EVENT_EN_CLI;
461 if (flags & SWITCHTEC_EVT_FLAG_DIS_FATAL)
462 hdr &= ~SWITCHTEC_EVENT_FATAL;
465 __gas_write32(dev, hdr, reg);
467 return (hdr >> 5) & 0xFF;
471 int index,
int flags, uint32_t data[5])
476 if (e >= SWITCHTEC_MAX_EVENTS)
479 if (index == SWITCHTEC_EVT_IDX_ALL) {
480 if (event_regs[e].map_reg == global_ev_reg)
482 else if (event_regs[e].map_reg == part_ev_reg)
483 nr_idxs = dev->partition_count;
484 else if (event_regs[e].map_reg == pff_ev_reg)
485 nr_idxs = gas_reg_read8(dev, top.pff_count);
489 for (index = 0; index < nr_idxs; index++) {
490 ret = event_ctl(dev, e, index, flags, data);
495 ret = event_ctl(dev, e, index, flags, data);
505 int gasop_event_wait_for(
struct switchtec_dev *dev,
511 long long start, now;
520 SWITCHTEC_EVT_FLAG_CLEAR |
521 SWITCHTEC_EVT_FLAG_EN_POLL,
526 ret = gettimeofday(&tv, NULL);
530 now = start = ((tv.tv_sec) * 1000 + tv.tv_usec / 1000);
540 ret = gettimeofday(&tv, NULL);
544 now = ((tv.tv_sec) * 1000 + tv.tv_usec / 1000);
546 if (timeout_ms > 0 && now - start >= timeout_ms)
size_t part_addr
Address of the partition.
int switchtec_event_check(struct switchtec_dev *dev, struct switchtec_event_summary *chk, struct switchtec_event_summary *res)
Check if one or more events have occurred.
switchtec_event_id
Enumeration of all possible events.
Information about a firmware image or partition.
int switchtec_event_summary_set(struct switchtec_event_summary *sum, enum switchtec_event_id e, int index)
Set a bit corresponding to an event in a summary structure.
uint64_t part_bitmap
Bitmap of partitions with active events.
uint64_t global
Bitmap of global events.
unsigned pff[SWITCHTEC_MAX_PFF_CSR]
Bitmap of events in each port function.
unsigned part[SWITCHTEC_MAX_PARTS]
Bitmap of events in each partition.
size_t part_len
Length of the partition.
int switchtec_event_ctl(struct switchtec_dev *dev, enum switchtec_event_id e, int index, int flags, uint32_t data[5])
Enable, disable and clear events or retrieve event data.
unsigned local_part
Bitmap of events in the local partition.