Commit | Line | Data |
---|---|---|
04672fe6 | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
1ba47da5 IPG |
2 | /* |
3 | * i1480 Device Firmware Upload | |
4 | * | |
5 | * Copyright (C) 2005-2006 Intel Corporation | |
6 | * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> | |
7 | * | |
1ba47da5 IPG |
8 | * This driver is the firmware uploader for the Intel Wireless UWB |
9 | * Link 1480 device (both in the USB and PCI incarnations). | |
10 | * | |
11 | * The process is quite simple: we stop the device, write the firmware | |
12 | * to its memory and then restart it. Wait for the device to let us | |
13 | * know it is done booting firmware. Ready. | |
14 | * | |
15 | * We might have to upload before or after a phy firmware (which might | |
16 | * be done in two methods, using a normal firmware image or through | |
17 | * the MPI port). | |
18 | * | |
19 | * Because USB and PCI use common methods, we just make ops out of the | |
20 | * common operations (read, write, wait_init_done and cmd) and | |
21 | * implement them in usb.c and pci.c. | |
22 | * | |
23 | * The flow is (some parts omitted): | |
24 | * | |
25 | * i1480_{usb,pci}_probe() On enumerate/discovery | |
26 | * i1480_fw_upload() | |
27 | * i1480_pre_fw_upload() | |
28 | * __mac_fw_upload() | |
29 | * fw_hdrs_load() | |
30 | * mac_fw_hdrs_push() | |
31 | * i1480->write() [i1480_{usb,pci}_write()] | |
32 | * i1480_fw_cmp() | |
33 | * i1480->read() [i1480_{usb,pci}_read()] | |
34 | * i1480_mac_fw_upload() | |
35 | * __mac_fw_upload() | |
36 | * i1480->setup(() | |
37 | * i1480->wait_init_done() | |
38 | * i1480_cmd_reset() | |
39 | * i1480->cmd() [i1480_{usb,pci}_cmd()] | |
40 | * ... | |
41 | * i1480_phy_fw_upload() | |
42 | * request_firmware() | |
43 | * i1480_mpi_write() | |
44 | * i1480->cmd() [i1480_{usb,pci}_cmd()] | |
1ba47da5 IPG |
45 | * |
46 | * Once the probe function enumerates the device and uploads the | |
47 | * firmware, we just exit with -ENODEV, as we don't really want to | |
48 | * attach to the device. | |
49 | */ | |
50 | #ifndef __i1480_DFU_H__ | |
51 | #define __i1480_DFU_H__ | |
52 | ||
1ba47da5 IPG |
53 | #include <linux/types.h> |
54 | #include <linux/completion.h> | |
71ed79b0 | 55 | #include "../../include/spec.h" |
1ba47da5 IPG |
56 | |
57 | #define i1480_FW_UPLOAD_MODE_MASK (cpu_to_le32(0x00000018)) | |
58 | ||
59 | #if i1480_FW > 0x00000302 | |
60 | #define i1480_RCEB_EXTENDED | |
61 | #endif | |
62 | ||
63 | struct uwb_rccb; | |
64 | struct uwb_rceb; | |
65 | ||
66 | /* | |
67 | * Common firmware upload handlers | |
68 | * | |
69 | * Normally you embed this struct in another one specific to your hw. | |
70 | * | |
71 | * @write Write to device's memory from buffer. | |
72 | * @read Read from device's memory to i1480->evt_buf. | |
73 | * @setup Setup device after basic firmware is uploaded | |
74 | * @wait_init_done | |
75 | * Wait for the device to send a notification saying init | |
76 | * is done. | |
77 | * @cmd FOP for issuing the command to the hardware. The | |
78 | * command data is contained in i1480->cmd_buf and the size | |
79 | * is supplied as an argument. The command replied is put | |
80 | * in i1480->evt_buf and the size in i1480->evt_result (or if | |
81 | * an error, a < 0 errno code). | |
82 | * | |
83 | * @cmd_buf Memory buffer used to send commands to the device. | |
84 | * Allocated by the upper layers i1480_fw_upload(). | |
85 | * Size has to be @buf_size. | |
86 | * @evt_buf Memory buffer used to place the async notifications | |
87 | * received by the hw. Allocated by the upper layers | |
88 | * i1480_fw_upload(). | |
89 | * Size has to be @buf_size. | |
90 | * @cmd_complete | |
91 | * Low level driver uses this to notify code waiting afor | |
92 | * an event that the event has arrived and data is in | |
93 | * i1480->evt_buf (and size/result in i1480->evt_result). | |
94 | * @hw_rev | |
95 | * Use this value to activate dfu code to support new revisions | |
96 | * of hardware. i1480_init() sets this to a default value. | |
97 | * It should be updated by the USB and PCI code. | |
98 | */ | |
99 | struct i1480 { | |
100 | struct device *dev; | |
101 | ||
102 | int (*write)(struct i1480 *, u32 addr, const void *, size_t); | |
103 | int (*read)(struct i1480 *, u32 addr, size_t); | |
104 | int (*rc_setup)(struct i1480 *); | |
105 | void (*rc_release)(struct i1480 *); | |
106 | int (*wait_init_done)(struct i1480 *); | |
107 | int (*cmd)(struct i1480 *, const char *cmd_name, size_t cmd_size); | |
108 | const char *pre_fw_name; | |
109 | const char *mac_fw_name; | |
110 | const char *mac_fw_name_deprecate; /* FIXME: Will go away */ | |
111 | const char *phy_fw_name; | |
112 | u8 hw_rev; | |
113 | ||
114 | size_t buf_size; /* size of both evt_buf and cmd_buf */ | |
115 | void *evt_buf, *cmd_buf; | |
116 | ssize_t evt_result; | |
117 | struct completion evt_complete; | |
1ba47da5 IPG |
118 | }; |
119 | ||
120 | static inline | |
121 | void i1480_init(struct i1480 *i1480) | |
122 | { | |
123 | i1480->hw_rev = 1; | |
124 | init_completion(&i1480->evt_complete); | |
125 | } | |
126 | ||
127 | extern int i1480_fw_upload(struct i1480 *); | |
128 | extern int i1480_pre_fw_upload(struct i1480 *); | |
129 | extern int i1480_mac_fw_upload(struct i1480 *); | |
130 | extern int i1480_phy_fw_upload(struct i1480 *); | |
131 | extern ssize_t i1480_cmd(struct i1480 *, const char *, size_t, size_t); | |
132 | extern int i1480_rceb_check(const struct i1480 *, | |
133 | const struct uwb_rceb *, const char *, u8, | |
b5784f10 | 134 | u8, unsigned); |
1ba47da5 IPG |
135 | |
136 | enum { | |
137 | /* Vendor specific command type */ | |
138 | i1480_CET_VS1 = 0xfd, | |
139 | /* i1480 commands */ | |
140 | i1480_CMD_SET_IP_MAS = 0x000e, | |
141 | i1480_CMD_GET_MAC_PHY_INFO = 0x0003, | |
142 | i1480_CMD_MPI_WRITE = 0x000f, | |
143 | i1480_CMD_MPI_READ = 0x0010, | |
144 | /* i1480 events */ | |
145 | #if i1480_FW > 0x00000302 | |
146 | i1480_EVT_CONFIRM = 0x0002, | |
147 | i1480_EVT_RM_INIT_DONE = 0x0101, | |
148 | i1480_EVT_DEV_ADD = 0x0103, | |
149 | i1480_EVT_DEV_RM = 0x0104, | |
150 | i1480_EVT_DEV_ID_CHANGE = 0x0105, | |
151 | i1480_EVT_GET_MAC_PHY_INFO = i1480_CMD_GET_MAC_PHY_INFO, | |
152 | #else | |
153 | i1480_EVT_CONFIRM = 0x0002, | |
154 | i1480_EVT_RM_INIT_DONE = 0x0101, | |
155 | i1480_EVT_DEV_ADD = 0x0103, | |
156 | i1480_EVT_DEV_RM = 0x0104, | |
157 | i1480_EVT_DEV_ID_CHANGE = 0x0105, | |
158 | i1480_EVT_GET_MAC_PHY_INFO = i1480_EVT_CONFIRM, | |
159 | #endif | |
160 | }; | |
161 | ||
162 | ||
163 | struct i1480_evt_confirm { | |
164 | struct uwb_rceb rceb; | |
165 | #ifdef i1480_RCEB_EXTENDED | |
166 | __le16 wParamLength; | |
167 | #endif | |
168 | u8 bResultCode; | |
169 | } __attribute__((packed)); | |
170 | ||
171 | ||
172 | struct i1480_rceb { | |
173 | struct uwb_rceb rceb; | |
174 | #ifdef i1480_RCEB_EXTENDED | |
175 | __le16 wParamLength; | |
176 | #endif | |
177 | } __attribute__((packed)); | |
178 | ||
179 | ||
180 | /** | |
181 | * Get MAC & PHY Information confirm event structure | |
182 | * | |
183 | * Confirm event returned by the command. | |
184 | */ | |
185 | struct i1480_evt_confirm_GMPI { | |
186 | #if i1480_FW > 0x00000302 | |
187 | struct uwb_rceb rceb; | |
188 | __le16 wParamLength; | |
189 | __le16 status; | |
190 | u8 mac_addr[6]; /* EUI-64 bit IEEE address [still 8 bytes?] */ | |
191 | u8 dev_addr[2]; | |
192 | __le16 mac_fw_rev; /* major = v >> 8; minor = v & 0xff */ | |
193 | u8 hw_rev; | |
194 | u8 phy_vendor; | |
195 | u8 phy_rev; /* major v = >> 8; minor = v & 0xff */ | |
196 | __le16 mac_caps; | |
197 | u8 phy_caps[3]; | |
198 | u8 key_stores; | |
199 | __le16 mcast_addr_stores; | |
200 | u8 sec_mode_supported; | |
201 | #else | |
202 | struct uwb_rceb rceb; | |
203 | u8 status; | |
204 | u8 mac_addr[8]; /* EUI-64 bit IEEE address [still 8 bytes?] */ | |
205 | u8 dev_addr[2]; | |
206 | __le16 mac_fw_rev; /* major = v >> 8; minor = v & 0xff */ | |
207 | __le16 phy_fw_rev; /* major v = >> 8; minor = v & 0xff */ | |
208 | __le16 mac_caps; | |
209 | u8 phy_caps; | |
210 | u8 key_stores; | |
211 | __le16 mcast_addr_stores; | |
212 | u8 sec_mode_supported; | |
213 | #endif | |
214 | } __attribute__((packed)); | |
215 | ||
216 | ||
217 | struct i1480_cmd_mpi_write { | |
218 | struct uwb_rccb rccb; | |
219 | __le16 size; | |
220 | u8 data[]; | |
221 | }; | |
222 | ||
223 | ||
224 | struct i1480_cmd_mpi_read { | |
225 | struct uwb_rccb rccb; | |
226 | __le16 size; | |
227 | struct { | |
228 | u8 page, offset; | |
229 | } __attribute__((packed)) data[]; | |
230 | } __attribute__((packed)); | |
231 | ||
232 | ||
233 | struct i1480_evt_mpi_read { | |
234 | struct uwb_rceb rceb; | |
235 | #ifdef i1480_RCEB_EXTENDED | |
236 | __le16 wParamLength; | |
237 | #endif | |
238 | u8 bResultCode; | |
239 | __le16 size; | |
240 | struct { | |
241 | u8 page, offset, value; | |
242 | } __attribute__((packed)) data[]; | |
243 | } __attribute__((packed)); | |
244 | ||
245 | ||
246 | #endif /* #ifndef __i1480_DFU_H__ */ |