Skip to content

Commit e2bf6cd

Browse files
committed
fixup! xhci-pci: asmedia: Add a firmware loader for ASM2214a chips
1 parent b0363a0 commit e2bf6cd

1 file changed

Lines changed: 97 additions & 15 deletions

File tree

drivers/usb/host/xhci-pci-asmedia.c

Lines changed: 97 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,27 @@
3838
/* BAR0 registers */
3939
#define ASMT_REG_ADDR 0x3000
4040

41-
#define ASMT_REG_DATA 0x3004
41+
#define ASMT_REG_WDATA 0x3004
42+
#define ASMT_REG_RDATA 0x3008
4243

4344
#define ASMT_REG_STATUS 0x3009
4445
#define ASMT_REG_STATUS_BUSY BIT(7)
4546

46-
#define ASMT_REG_WDATA 0x3010
47-
#define ASMT_REG_RDATA 0x3018
47+
#define ASMT_REG_CODE_WDATA 0x3010
48+
#define ASMT_REG_CODE_RDATA 0x3018
49+
50+
#define ASMT_MMIO_CPU_MISC 0x500e
51+
#define ASMT_MMIO_CPU_MISC_CODE_RAM_WR BIT(0)
52+
53+
#define ASMT_MMIO_CPU_MODE_NEXT 0x5040
54+
#define ASMT_MMIO_CPU_MODE_CUR 0x5041
55+
56+
#define ASMT_MMIO_CPU_MODE_RAM BIT(0)
57+
#define ASMT_MMIO_CPU_MODE_HALFSPEED BIT(1)
58+
59+
#define ASMT_MMIO_CPU_EXEC_CTRL 0x5042
60+
#define ASMT_MMIO_CPU_EXEC_CTRL_RESET BIT(0)
61+
#define ASMT_MMIO_CPU_EXEC_CTRL_HALT BIT(1)
4862

4963
#define TIMEOUT_USEC 10000
5064
#define RESET_TIMEOUT_USEC 500000
@@ -178,11 +192,41 @@ static int asmedia_wait_reset(struct pci_dev *pdev)
178192
return ret;
179193
}
180194

181-
static void asmedia_write_reg(struct usb_hcd *hcd, u16 addr, u8 data) {
195+
static u8 asmedia_read_reg(struct usb_hcd *hcd, u16 addr) {
182196
void __iomem *regs = hcd->regs;
183197
u8 status;
184198
int ret;
185199

200+
ret = readb_poll_timeout(regs + ASMT_REG_STATUS,
201+
status, !(status & ASMT_REG_STATUS_BUSY),
202+
1000, TIMEOUT_USEC);
203+
204+
if (ret) {
205+
dev_err(hcd->self.controller,
206+
"Read reg wait timed out ([%04x])\n", addr);
207+
return ~0;
208+
}
209+
210+
writew_relaxed(addr, regs + ASMT_REG_ADDR);
211+
212+
ret = readb_poll_timeout(regs + ASMT_REG_STATUS,
213+
status, !(status & ASMT_REG_STATUS_BUSY),
214+
1000, TIMEOUT_USEC);
215+
216+
if (ret) {
217+
dev_err(hcd->self.controller,
218+
"Read reg addr timed out ([%04x])\n", addr);
219+
return ~0;
220+
}
221+
222+
return readb_relaxed(regs + ASMT_REG_RDATA);
223+
}
224+
225+
static void asmedia_write_reg(struct usb_hcd *hcd, u16 addr, u8 data, bool wait) {
226+
void __iomem *regs = hcd->regs;
227+
u8 status;
228+
int ret, i;
229+
186230
writew_relaxed(addr, regs + ASMT_REG_ADDR);
187231

188232
ret = readb_poll_timeout(regs + ASMT_REG_STATUS,
@@ -191,44 +235,66 @@ static void asmedia_write_reg(struct usb_hcd *hcd, u16 addr, u8 data) {
191235

192236
if (ret)
193237
dev_err(hcd->self.controller,
194-
"Write addr timed out ([%04x] = %02x)\n",
238+
"Write reg addr timed out ([%04x] = %02x)\n",
195239
addr, data);
196240

197-
writeb_relaxed(data, regs + ASMT_REG_DATA);
241+
writeb_relaxed(data, regs + ASMT_REG_WDATA);
198242

199243
ret = readb_poll_timeout(regs + ASMT_REG_STATUS,
200244
status, !(status & ASMT_REG_STATUS_BUSY),
201245
1000, TIMEOUT_USEC);
202246

203247
if (ret)
204248
dev_err(hcd->self.controller,
205-
"Write data timed out ([%04x] = %02x)\n",
249+
"Write reg data timed out ([%04x] = %02x)\n",
250+
addr, data);
251+
252+
if (!wait)
253+
return;
254+
255+
for (i = 0; i < TIMEOUT_USEC; i++) {
256+
if (asmedia_read_reg(hcd, addr) == data)
257+
break;
258+
}
259+
260+
if (i >= TIMEOUT_USEC) {
261+
dev_err(hcd->self.controller,
262+
"Verify register timed out ([%04x] = %02x)\n",
206263
addr, data);
264+
}
207265
}
208266

209267
static int asmedia_load_fw(struct pci_dev *pdev, const struct firmware *fw)
210268
{
211269
struct usb_hcd *hcd;
212270
void __iomem *regs;
213271
const u16 *fw_data = (const u16 *)fw->data;
272+
u16 raddr;
214273
u32 data;
215274
size_t index = 0, addr = 0;
216275
size_t words = fw->size >> 1;
217-
int ret;
276+
int ret, i;
218277

219278
hcd = dev_get_drvdata(&pdev->dev);
220279
regs = hcd->regs;
221280

222-
asmedia_write_reg(hcd, 0x5040, 2);
223-
asmedia_write_reg(hcd, 0x5042, 1);
281+
asmedia_write_reg(hcd, ASMT_MMIO_CPU_MODE_NEXT,
282+
ASMT_MMIO_CPU_MODE_HALFSPEED, false);
283+
284+
asmedia_write_reg(hcd, ASMT_MMIO_CPU_EXEC_CTRL,
285+
ASMT_MMIO_CPU_EXEC_CTRL_RESET, false);
224286

225287
ret = asmedia_wait_reset(pdev);
226288
if (ret) {
227289
dev_err(hcd->self.controller, "Failed pre-upload reset\n");
228290
return ret;
229291
}
230292

231-
asmedia_write_reg(hcd, 0x500e, 1);
293+
asmedia_write_reg(hcd, ASMT_MMIO_CPU_EXEC_CTRL,
294+
ASMT_MMIO_CPU_EXEC_CTRL_HALT, false);
295+
296+
asmedia_write_reg(hcd, ASMT_MMIO_CPU_MISC,
297+
ASMT_MMIO_CPU_MISC_CODE_RAM_WR, true);
232298

233299
pci_write_config_byte(pdev, ASMT_CFG_SRAM_ACCESS,
234300
ASMT_CFG_SRAM_ACCESS_ENABLE);
@@ -243,18 +309,34 @@ static int asmedia_load_fw(struct pci_dev *pdev, const struct firmware *fw)
243309
pci_write_config_word(pdev, ASMT_CFG_SRAM_ADDR,
244310
addr);
245311

246-
writel_relaxed(data, regs + ASMT_REG_WDATA);
312+
writel_relaxed(data, regs + ASMT_REG_CODE_WDATA);
313+
314+
for (i = 0; i < TIMEOUT_USEC; i++) {
315+
pci_read_config_word(pdev, ASMT_CFG_SRAM_ADDR, &raddr);
316+
if (raddr != addr)
317+
break;
318+
udelay(1);
319+
}
320+
321+
if (raddr == addr) {
322+
dev_err(hcd->self.controller, "Word write timed out\n");
323+
return -ETIMEDOUT;
324+
}
247325

248326
if (++index & 0x4000)
249327
index += 0x4000;
250328
addr += 2;
251329
}
252330

253-
asmedia_write_reg(hcd, 0x5040, 3);
254-
255331
pci_write_config_byte(pdev, ASMT_CFG_SRAM_ACCESS, 0);
256332

257-
asmedia_write_reg(hcd, 0x500e, 0);
333+
asmedia_write_reg(hcd, ASMT_MMIO_CPU_MISC, 0, true);
334+
335+
asmedia_write_reg(hcd, ASMT_MMIO_CPU_MODE_NEXT,
336+
ASMT_MMIO_CPU_MODE_RAM |
337+
ASMT_MMIO_CPU_MODE_HALFSPEED, false);
338+
339+
asmedia_write_reg(hcd, ASMT_MMIO_CPU_EXEC_CTRL, 0, false);
258340

259341
ret = asmedia_wait_reset(pdev);
260342
if (ret) {

0 commit comments

Comments
 (0)