xref: /dpdk/drivers/net/ionic/ionic_dev.c (revision 5ef51809)
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