2 * Intel Wireless UWB Link 1480
3 * PHY parameters upload
5 * Copyright (C) 2005-2006 Intel Corporation
6 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 * Code for uploading the PHY parameters to the PHY through the UWB
24 * Radio Control interface.
26 * We just send the data through the MPI interface using HWA-like
27 * commands and then reset the PHY to make sure it is ok.
29 #include <linux/delay.h>
30 #include <linux/device.h>
31 #include <linux/firmware.h>
32 #include <linux/usb/wusb.h>
33 #include "i1480-dfu.h"
37 * Write a value array to an address of the MPI interface
39 * @i1480: Device descriptor
40 * @data: Data array to write
41 * @size: Size of the data array
42 * @returns: 0 if ok, < 0 errno code on error.
44 * The data array is organized into pairs:
48 * ADDRESS is BE 16 bit unsigned, VALUE 8 bit unsigned. Size thus has
49 * to be a multiple of three.
52 int i1480_mpi_write(struct i1480
*i1480
, const void *data
, size_t size
)
55 struct i1480_cmd_mpi_write
*cmd
= i1480
->cmd_buf
;
56 struct i1480_evt_confirm
*reply
= i1480
->evt_buf
;
60 cmd
->rccb
.bCommandType
= i1480_CET_VS1
;
61 cmd
->rccb
.wCommand
= cpu_to_le16(i1480_CMD_MPI_WRITE
);
62 cmd
->size
= cpu_to_le16(size
);
63 memcpy(cmd
->data
, data
, size
);
64 reply
->rceb
.bEventType
= i1480_CET_VS1
;
65 reply
->rceb
.wEvent
= i1480_CMD_MPI_WRITE
;
66 result
= i1480_cmd(i1480
, "MPI-WRITE", sizeof(*cmd
) + size
, sizeof(*reply
));
69 if (reply
->bResultCode
!= UWB_RC_RES_SUCCESS
) {
70 dev_err(i1480
->dev
, "MPI-WRITE: command execution failed: %d\n",
80 * Read a value array to from an address of the MPI interface
82 * @i1480: Device descriptor
83 * @data: where to place the read array
84 * @srcaddr: Where to read from
85 * @size: Size of the data read array
86 * @returns: 0 if ok, < 0 errno code on error.
88 * The command data array is organized into pairs ADDR0 ADDR1..., and
89 * the returned data in ADDR0 VALUE0 ADDR1 VALUE1...
91 * We generate the command array to be a sequential read and then
92 * rearrange the result.
94 * We use the i1480->cmd_buf for the command, i1480->evt_buf for the reply.
96 * As the reply has to fit in 512 bytes (i1480->evt_buffer), the max amount
97 * of values we can read is (512 - sizeof(*reply)) / 3
100 int i1480_mpi_read(struct i1480
*i1480
, u8
*data
, u16 srcaddr
, size_t size
)
103 struct i1480_cmd_mpi_read
*cmd
= i1480
->cmd_buf
;
104 struct i1480_evt_mpi_read
*reply
= i1480
->evt_buf
;
107 memset(i1480
->cmd_buf
, 0x69, 512);
108 memset(i1480
->evt_buf
, 0x69, 512);
110 BUG_ON(size
> (i1480
->buf_size
- sizeof(*reply
)) / 3);
112 cmd
->rccb
.bCommandType
= i1480_CET_VS1
;
113 cmd
->rccb
.wCommand
= cpu_to_le16(i1480_CMD_MPI_READ
);
114 cmd
->size
= cpu_to_le16(3*size
);
115 for (cnt
= 0; cnt
< size
; cnt
++) {
116 cmd
->data
[cnt
].page
= (srcaddr
+ cnt
) >> 8;
117 cmd
->data
[cnt
].offset
= (srcaddr
+ cnt
) & 0xff;
119 reply
->rceb
.bEventType
= i1480_CET_VS1
;
120 reply
->rceb
.wEvent
= i1480_CMD_MPI_READ
;
121 result
= i1480_cmd(i1480
, "MPI-READ", sizeof(*cmd
) + 2*size
,
122 sizeof(*reply
) + 3*size
);
125 if (reply
->bResultCode
!= UWB_RC_RES_SUCCESS
) {
126 dev_err(i1480
->dev
, "MPI-READ: command execution failed: %d\n",
131 for (cnt
= 0; cnt
< size
; cnt
++) {
132 if (reply
->data
[cnt
].page
!= (srcaddr
+ cnt
) >> 8)
133 dev_err(i1480
->dev
, "MPI-READ: page inconsistency at "
134 "index %u: expected 0x%02x, got 0x%02x\n", cnt
,
135 (srcaddr
+ cnt
) >> 8, reply
->data
[cnt
].page
);
136 if (reply
->data
[cnt
].offset
!= ((srcaddr
+ cnt
) & 0x00ff))
137 dev_err(i1480
->dev
, "MPI-READ: offset inconsistency at "
138 "index %u: expected 0x%02x, got 0x%02x\n", cnt
,
139 (srcaddr
+ cnt
) & 0x00ff,
140 reply
->data
[cnt
].offset
);
141 data
[cnt
] = reply
->data
[cnt
].value
;
150 * Upload a PHY firmware, wait for it to start
152 * @i1480: Device instance
153 * @fw_name: Name of the file that contains the firmware
155 * We assume the MAC fw is up and running. This means we can use the
156 * MPI interface to write the PHY firmware. Once done, we issue an
157 * MBOA Reset, which will force the MAC to reset and reinitialize the
158 * PHY. If that works, we are ready to go.
160 * Max packet size for the MPI write is 512, so the max buffer is 480
161 * (which gives us 160 byte triads of MSB, LSB and VAL for the data).
163 int i1480_phy_fw_upload(struct i1480
*i1480
)
166 const struct firmware
*fw
;
167 const char *data_itr
, *data_top
;
168 const size_t MAX_BLK_SIZE
= 480; /* 160 triads */
172 result
= request_firmware(&fw
, i1480
->phy_fw_name
, i1480
->dev
);
175 /* Loop writing data in chunks as big as possible until done. */
176 for (data_itr
= fw
->data
, data_top
= data_itr
+ fw
->size
;
177 data_itr
< data_top
; data_itr
+= MAX_BLK_SIZE
) {
178 data_size
= min(MAX_BLK_SIZE
, (size_t) (data_top
- data_itr
));
179 result
= i1480_mpi_write(i1480
, data_itr
, data_size
);
181 goto error_mpi_write
;
183 /* Read MPI page 0, offset 6; if 0, PHY was initialized correctly. */
184 result
= i1480_mpi_read(i1480
, &phy_stat
, 0x0006, 1);
186 dev_err(i1480
->dev
, "PHY: can't get status: %d\n", result
);
187 goto error_mpi_status
;
191 dev_info(i1480
->dev
, "error, PHY not ready: %u\n", phy_stat
);
192 goto error_phy_status
;
194 dev_info(i1480
->dev
, "PHY fw '%s': uploaded\n", i1480
->phy_fw_name
);
198 release_firmware(fw
);
200 dev_err(i1480
->dev
, "PHY fw '%s': failed to upload (%d), "
201 "power cycle device\n", i1480
->phy_fw_name
, result
);