aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter E. Berger <pberger@brimson.com>2015-09-16 04:13:00 -0400
committerJohan Hovold <johan@kernel.org>2015-10-09 06:05:22 -0400
commitbebf1f185c216308367aee98f8b986be104c286b (patch)
tree07467ab1be2764ba430872eac77c2d7db597dca9
parentef9324b2bd2bb879a5512cfb9210d86e8ed6093f (diff)
USB: io_ti: Move download and boot mode code out of download_fw
Separate the download and boot mode code from download_fw() into two new helper functions: do_download_mode() and do_boot_mode(). Signed-off-by: Peter E. Berger <pberger@brimson.com> Signed-off-by: Johan Hovold <johan@kernel.org>
-rw-r--r--drivers/usb/serial/io_ti.c362
1 files changed, 195 insertions, 167 deletions
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index d41ba747220d..b371a0a961be 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -223,6 +223,11 @@ static void edge_set_termios(struct tty_struct *tty,
223 struct usb_serial_port *port, struct ktermios *old_termios); 223 struct usb_serial_port *port, struct ktermios *old_termios);
224static void edge_send(struct usb_serial_port *port, struct tty_struct *tty); 224static void edge_send(struct usb_serial_port *port, struct tty_struct *tty);
225 225
226static int do_download_mode(struct edgeport_serial *serial,
227 const struct firmware *fw);
228static int do_boot_mode(struct edgeport_serial *serial,
229 const struct firmware *fw);
230
226/* sysfs attributes */ 231/* sysfs attributes */
227static int edge_create_sysfs_attrs(struct usb_serial_port *port); 232static int edge_create_sysfs_attrs(struct usb_serial_port *port);
228static int edge_remove_sysfs_attrs(struct usb_serial_port *port); 233static int edge_remove_sysfs_attrs(struct usb_serial_port *port);
@@ -991,11 +996,7 @@ static int download_fw(struct edgeport_serial *serial,
991{ 996{
992 struct device *dev = &serial->serial->interface->dev; 997 struct device *dev = &serial->serial->interface->dev;
993 int status = 0; 998 int status = 0;
994 int start_address;
995 struct edge_ti_manuf_descriptor *ti_manuf_desc;
996 struct usb_interface_descriptor *interface; 999 struct usb_interface_descriptor *interface;
997 int download_cur_ver;
998 int download_new_ver;
999 struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data; 1000 struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
1000 1001
1001 if (check_fw_sanity(serial, fw)) 1002 if (check_fw_sanity(serial, fw))
@@ -1029,190 +1030,207 @@ static int download_fw(struct edgeport_serial *serial,
1029 * if we have more than one endpoint we are definitely in download 1030 * if we have more than one endpoint we are definitely in download
1030 * mode 1031 * mode
1031 */ 1032 */
1032 if (interface->bNumEndpoints > 1) 1033 if (interface->bNumEndpoints > 1) {
1033 serial->product_info.TiMode = TI_MODE_DOWNLOAD; 1034 serial->product_info.TiMode = TI_MODE_DOWNLOAD;
1034 else 1035 return do_download_mode(serial, fw);
1035 /* Otherwise we will remain in configuring mode */ 1036 }
1036 serial->product_info.TiMode = TI_MODE_CONFIGURING;
1037 1037
1038 /********************************************************************/ 1038 /* Otherwise we will remain in configuring mode */
1039 /* Download Mode */ 1039 serial->product_info.TiMode = TI_MODE_CONFIGURING;
1040 /********************************************************************/ 1040 return do_boot_mode(serial, fw);
1041 if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) {
1042 struct ti_i2c_desc *rom_desc;
1043 1041
1044 dev_dbg(dev, "%s - RUNNING IN DOWNLOAD MODE\n", __func__); 1042}
1045 1043
1046 status = check_i2c_image(serial); 1044static int do_download_mode(struct edgeport_serial *serial,
1047 if (status) { 1045 const struct firmware *fw)
1048 dev_dbg(dev, "%s - DOWNLOAD MODE -- BAD I2C\n", __func__); 1046{
1049 return status; 1047 struct device *dev = &serial->serial->interface->dev;
1050 } 1048 int status = 0;
1049 int start_address;
1050 struct edge_ti_manuf_descriptor *ti_manuf_desc;
1051 int download_cur_ver;
1052 int download_new_ver;
1053 struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
1054 struct ti_i2c_desc *rom_desc;
1051 1055
1052 /* Validate Hardware version number 1056 dev_dbg(dev, "%s - RUNNING IN DOWNLOAD MODE\n", __func__);
1053 * Read Manufacturing Descriptor from TI Based Edgeport
1054 */
1055 ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL);
1056 if (!ti_manuf_desc)
1057 return -ENOMEM;
1058 1057
1059 status = get_manuf_info(serial, (__u8 *)ti_manuf_desc); 1058 status = check_i2c_image(serial);
1060 if (status) { 1059 if (status) {
1061 kfree(ti_manuf_desc); 1060 dev_dbg(dev, "%s - DOWNLOAD MODE -- BAD I2C\n", __func__);
1062 return status; 1061 return status;
1063 } 1062 }
1064 1063
1065 /* Check version number of ION descriptor */ 1064 /* Validate Hardware version number
1066 if (!ignore_cpu_rev && ti_cpu_rev(ti_manuf_desc) < 2) { 1065 * Read Manufacturing Descriptor from TI Based Edgeport
1067 dev_dbg(dev, "%s - Wrong CPU Rev %d (Must be 2)\n", 1066 */
1068 __func__, ti_cpu_rev(ti_manuf_desc)); 1067 ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL);
1069 kfree(ti_manuf_desc); 1068 if (!ti_manuf_desc)
1070 return -EINVAL; 1069 return -ENOMEM;
1071 }
1072 1070
1073 rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL); 1071 status = get_manuf_info(serial, (__u8 *)ti_manuf_desc);
1074 if (!rom_desc) { 1072 if (status) {
1073 kfree(ti_manuf_desc);
1074 return status;
1075 }
1076
1077 /* Check version number of ION descriptor */
1078 if (!ignore_cpu_rev && ti_cpu_rev(ti_manuf_desc) < 2) {
1079 dev_dbg(dev, "%s - Wrong CPU Rev %d (Must be 2)\n",
1080 __func__, ti_cpu_rev(ti_manuf_desc));
1081 kfree(ti_manuf_desc);
1082 return -EINVAL;
1083 }
1084
1085 rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
1086 if (!rom_desc) {
1087 kfree(ti_manuf_desc);
1088 return -ENOMEM;
1089 }
1090
1091 /* Search for type 2 record (firmware record) */
1092 start_address = get_descriptor_addr(serial,
1093 I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc);
1094 if (start_address != 0) {
1095 struct ti_i2c_firmware_rec *firmware_version;
1096 u8 *record;
1097
1098 dev_dbg(dev, "%s - Found Type FIRMWARE (Type 2) record\n",
1099 __func__);
1100
1101 firmware_version = kmalloc(sizeof(*firmware_version),
1102 GFP_KERNEL);
1103 if (!firmware_version) {
1104 kfree(rom_desc);
1075 kfree(ti_manuf_desc); 1105 kfree(ti_manuf_desc);
1076 return -ENOMEM; 1106 return -ENOMEM;
1077 } 1107 }
1078 1108
1079 /* Search for type 2 record (firmware record) */ 1109 /* Validate version number
1080 start_address = get_descriptor_addr(serial, 1110 * Read the descriptor data
1081 I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc); 1111 */
1082 if (start_address != 0) { 1112 status = read_rom(serial, start_address +
1083 struct ti_i2c_firmware_rec *firmware_version; 1113 sizeof(struct ti_i2c_desc),
1084 u8 *record; 1114 sizeof(struct ti_i2c_firmware_rec),
1115 (__u8 *)firmware_version);
1116 if (status) {
1117 kfree(firmware_version);
1118 kfree(rom_desc);
1119 kfree(ti_manuf_desc);
1120 return status;
1121 }
1085 1122
1086 dev_dbg(dev, "%s - Found Type FIRMWARE (Type 2) record\n", __func__); 1123 /* Check version number of download with current
1124 * version in I2c */
1125 download_cur_ver = (firmware_version->Ver_Major << 8) +
1126 (firmware_version->Ver_Minor);
1127 download_new_ver = (fw_hdr->major_version << 8) +
1128 (fw_hdr->minor_version);
1129
1130 dev_dbg(dev, "%s - >> FW Versions Device %d.%d Driver %d.%d\n",
1131 __func__, firmware_version->Ver_Major,
1132 firmware_version->Ver_Minor,
1133 fw_hdr->major_version, fw_hdr->minor_version);
1134
1135 /* Check if we have an old version in the I2C and
1136 * update if necessary */
1137 if (download_cur_ver < download_new_ver) {
1138 dev_dbg(dev, "%s - Update I2C dld from %d.%d to %d.%d\n",
1139 __func__,
1140 firmware_version->Ver_Major,
1141 firmware_version->Ver_Minor,
1142 fw_hdr->major_version,
1143 fw_hdr->minor_version);
1087 1144
1088 firmware_version = kmalloc(sizeof(*firmware_version), 1145 record = kmalloc(1, GFP_KERNEL);
1089 GFP_KERNEL); 1146 if (!record) {
1090 if (!firmware_version) { 1147 kfree(firmware_version);
1091 kfree(rom_desc); 1148 kfree(rom_desc);
1092 kfree(ti_manuf_desc); 1149 kfree(ti_manuf_desc);
1093 return -ENOMEM; 1150 return -ENOMEM;
1094 } 1151 }
1095 1152 /*
1096 /* Validate version number 1153 * In order to update the I2C firmware we must
1097 * Read the descriptor data 1154 * change the type 2 record to type 0xF2. This
1155 * will force the UMP to come up in Boot Mode.
1156 * Then while in boot mode, the driver will
1157 * download the latest firmware (padded to
1158 * 15.5k) into the UMP ram. Finally when the
1159 * device comes back up in download mode the
1160 * driver will cause the new firmware to be
1161 * copied from the UMP Ram to I2C and the
1162 * firmware will update the record type from
1163 * 0xf2 to 0x02.
1098 */ 1164 */
1099 status = read_rom(serial, start_address + 1165 *record = I2C_DESC_TYPE_FIRMWARE_BLANK;
1100 sizeof(struct ti_i2c_desc), 1166
1101 sizeof(struct ti_i2c_firmware_rec), 1167 /* Change the I2C Firmware record type to
1102 (__u8 *)firmware_version); 1168 * 0xf2 to trigger an update */
1169 status = write_rom(serial, start_address,
1170 sizeof(*record), record);
1103 if (status) { 1171 if (status) {
1172 kfree(record);
1104 kfree(firmware_version); 1173 kfree(firmware_version);
1105 kfree(rom_desc); 1174 kfree(rom_desc);
1106 kfree(ti_manuf_desc); 1175 kfree(ti_manuf_desc);
1107 return status; 1176 return status;
1108 } 1177 }
1109 1178
1110 /* Check version number of download with current 1179 /* verify the write -- must do this in order
1111 version in I2c */ 1180 * for write to complete before we do the
1112 download_cur_ver = (firmware_version->Ver_Major << 8) + 1181 * hardware reset
1113 (firmware_version->Ver_Minor); 1182 */
1114 download_new_ver = (fw_hdr->major_version << 8) + 1183 status = read_rom(serial,
1115 (fw_hdr->minor_version); 1184 start_address,
1116 1185 sizeof(*record),
1117 dev_dbg(dev, "%s - >> FW Versions Device %d.%d Driver %d.%d\n", 1186 record);
1118 __func__, firmware_version->Ver_Major, 1187 if (status) {
1119 firmware_version->Ver_Minor, 1188 kfree(record);
1120 fw_hdr->major_version, fw_hdr->minor_version); 1189 kfree(firmware_version);
1190 kfree(rom_desc);
1191 kfree(ti_manuf_desc);
1192 return status;
1193 }
1121 1194
1122 /* Check if we have an old version in the I2C and 1195 if (*record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
1123 update if necessary */ 1196 dev_err(dev, "%s - error resetting device\n",
1124 if (download_cur_ver < download_new_ver) { 1197 __func__);
1125 dev_dbg(dev, "%s - Update I2C dld from %d.%d to %d.%d\n",
1126 __func__,
1127 firmware_version->Ver_Major,
1128 firmware_version->Ver_Minor,
1129 fw_hdr->major_version,
1130 fw_hdr->minor_version);
1131
1132 record = kmalloc(1, GFP_KERNEL);
1133 if (!record) {
1134 kfree(firmware_version);
1135 kfree(rom_desc);
1136 kfree(ti_manuf_desc);
1137 return -ENOMEM;
1138 }
1139 /* In order to update the I2C firmware we must
1140 * change the type 2 record to type 0xF2. This
1141 * will force the UMP to come up in Boot Mode.
1142 * Then while in boot mode, the driver will
1143 * download the latest firmware (padded to
1144 * 15.5k) into the UMP ram. Finally when the
1145 * device comes back up in download mode the
1146 * driver will cause the new firmware to be
1147 * copied from the UMP Ram to I2C and the
1148 * firmware will update the record type from
1149 * 0xf2 to 0x02.
1150 */
1151 *record = I2C_DESC_TYPE_FIRMWARE_BLANK;
1152
1153 /* Change the I2C Firmware record type to
1154 0xf2 to trigger an update */
1155 status = write_rom(serial, start_address,
1156 sizeof(*record), record);
1157 if (status) {
1158 kfree(record);
1159 kfree(firmware_version);
1160 kfree(rom_desc);
1161 kfree(ti_manuf_desc);
1162 return status;
1163 }
1164
1165 /* verify the write -- must do this in order
1166 * for write to complete before we do the
1167 * hardware reset
1168 */
1169 status = read_rom(serial,
1170 start_address,
1171 sizeof(*record),
1172 record);
1173 if (status) {
1174 kfree(record);
1175 kfree(firmware_version);
1176 kfree(rom_desc);
1177 kfree(ti_manuf_desc);
1178 return status;
1179 }
1180
1181 if (*record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
1182 dev_err(dev, "%s - error resetting device\n", __func__);
1183 kfree(record);
1184 kfree(firmware_version);
1185 kfree(rom_desc);
1186 kfree(ti_manuf_desc);
1187 return -ENODEV;
1188 }
1189
1190 dev_dbg(dev, "%s - HARDWARE RESET\n", __func__);
1191
1192 /* Reset UMP -- Back to BOOT MODE */
1193 status = ti_vsend_sync(serial->serial->dev,
1194 UMPC_HARDWARE_RESET,
1195 0, 0, NULL, 0,
1196 TI_VSEND_TIMEOUT_DEFAULT);
1197
1198 dev_dbg(dev, "%s - HARDWARE RESET return %d\n", __func__, status);
1199
1200 /* return an error on purpose. */
1201 kfree(record); 1198 kfree(record);
1202 kfree(firmware_version); 1199 kfree(firmware_version);
1203 kfree(rom_desc); 1200 kfree(rom_desc);
1204 kfree(ti_manuf_desc); 1201 kfree(ti_manuf_desc);
1205 return -ENODEV; 1202 return -ENODEV;
1206 } else {
1207 /* Same or newer fw version is already loaded */
1208 serial->fw_version = download_cur_ver;
1209 } 1203 }
1204
1205 dev_dbg(dev, "%s - HARDWARE RESET\n", __func__);
1206
1207 /* Reset UMP -- Back to BOOT MODE */
1208 status = ti_vsend_sync(serial->serial->dev,
1209 UMPC_HARDWARE_RESET,
1210 0, 0, NULL, 0,
1211 TI_VSEND_TIMEOUT_DEFAULT);
1212
1213 dev_dbg(dev, "%s - HARDWARE RESET return %d\n",
1214 __func__, status);
1215
1216 /* return an error on purpose. */
1217 kfree(record);
1210 kfree(firmware_version); 1218 kfree(firmware_version);
1219 kfree(rom_desc);
1220 kfree(ti_manuf_desc);
1221 return -ENODEV;
1211 } 1222 }
1212 /* Search for type 0xF2 record (firmware blank record) */ 1223 /* Same or newer fw version is already loaded */
1213 else if ((start_address = get_descriptor_addr(serial, I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc)) != 0) { 1224 serial->fw_version = download_cur_ver;
1225 kfree(firmware_version);
1226 }
1227 /* Search for type 0xF2 record (firmware blank record) */
1228 else {
1229 start_address = get_descriptor_addr(serial,
1230 I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc);
1231 if (start_address != 0) {
1214#define HEADER_SIZE (sizeof(struct ti_i2c_desc) + \ 1232#define HEADER_SIZE (sizeof(struct ti_i2c_desc) + \
1215 sizeof(struct ti_i2c_firmware_rec)) 1233 sizeof(struct ti_i2c_firmware_rec))
1216 __u8 *header; 1234 __u8 *header;
1217 __u8 *vheader; 1235 __u8 *vheader;
1218 1236
@@ -1231,7 +1249,8 @@ static int download_fw(struct edgeport_serial *serial,
1231 return -ENOMEM; 1249 return -ENOMEM;
1232 } 1250 }
1233 1251
1234 dev_dbg(dev, "%s - Found Type BLANK FIRMWARE (Type F2) record\n", __func__); 1252 dev_dbg(dev, "%s - Found Type BLANK FIRMWARE (Type F2) record\n",
1253 __func__);
1235 1254
1236 /* 1255 /*
1237 * In order to update the I2C firmware we must change 1256 * In order to update the I2C firmware we must change
@@ -1254,7 +1273,7 @@ static int download_fw(struct edgeport_serial *serial,
1254 } 1273 }
1255 1274
1256 /* Update I2C with type 0xf2 record with correct 1275 /* Update I2C with type 0xf2 record with correct
1257 size and checksum */ 1276 * size and checksum */
1258 status = write_rom(serial, 1277 status = write_rom(serial,
1259 start_address, 1278 start_address,
1260 HEADER_SIZE, 1279 HEADER_SIZE,
@@ -1268,12 +1287,13 @@ static int download_fw(struct edgeport_serial *serial,
1268 } 1287 }
1269 1288
1270 /* verify the write -- must do this in order for 1289 /* verify the write -- must do this in order for
1271 write to complete before we do the hardware reset */ 1290 * write to complete before we do the hardware reset */
1272 status = read_rom(serial, start_address, 1291 status = read_rom(serial, start_address,
1273 HEADER_SIZE, vheader); 1292 HEADER_SIZE, vheader);
1274 1293
1275 if (status) { 1294 if (status) {
1276 dev_dbg(dev, "%s - can't read header back\n", __func__); 1295 dev_dbg(dev, "%s - can't read header back\n",
1296 __func__);
1277 kfree(vheader); 1297 kfree(vheader);
1278 kfree(header); 1298 kfree(header);
1279 kfree(rom_desc); 1299 kfree(rom_desc);
@@ -1281,7 +1301,8 @@ static int download_fw(struct edgeport_serial *serial,
1281 return status; 1301 return status;
1282 } 1302 }
1283 if (memcmp(vheader, header, HEADER_SIZE)) { 1303 if (memcmp(vheader, header, HEADER_SIZE)) {
1284 dev_dbg(dev, "%s - write download record failed\n", __func__); 1304 dev_dbg(dev, "%s - write download record failed\n",
1305 __func__);
1285 kfree(vheader); 1306 kfree(vheader);
1286 kfree(header); 1307 kfree(header);
1287 kfree(rom_desc); 1308 kfree(rom_desc);
@@ -1300,26 +1321,33 @@ static int download_fw(struct edgeport_serial *serial,
1300 0, 0, NULL, 0, 1321 0, 0, NULL, 0,
1301 TI_VSEND_TIMEOUT_FW_DOWNLOAD); 1322 TI_VSEND_TIMEOUT_FW_DOWNLOAD);
1302 1323
1303 dev_dbg(dev, "%s - Update complete 0x%x\n", __func__, status); 1324 dev_dbg(dev, "%s - Update complete 0x%x\n", __func__,
1325 status);
1304 if (status) { 1326 if (status) {
1305 dev_err(dev, 1327 dev_err(dev,
1306 "%s - UMPC_COPY_DNLD_TO_I2C failed\n", 1328 "%s - UMPC_COPY_DNLD_TO_I2C failed\n",
1307 __func__); 1329 __func__);
1308 kfree(rom_desc); 1330 kfree(rom_desc);
1309 kfree(ti_manuf_desc); 1331 kfree(ti_manuf_desc);
1310 return status; 1332 return status;
1311 } 1333 }
1312 } 1334 }
1313
1314 // The device is running the download code
1315 kfree(rom_desc);
1316 kfree(ti_manuf_desc);
1317 return 0;
1318 } 1335 }
1319 1336
1320 /********************************************************************/ 1337 /* The device is running the download code */
1321 /* Boot Mode */ 1338 kfree(rom_desc);
1322 /********************************************************************/ 1339 kfree(ti_manuf_desc);
1340 return 0;
1341}
1342
1343static int do_boot_mode(struct edgeport_serial *serial,
1344 const struct firmware *fw)
1345{
1346 struct device *dev = &serial->serial->interface->dev;
1347 int status = 0;
1348 struct edge_ti_manuf_descriptor *ti_manuf_desc;
1349 struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
1350
1323 dev_dbg(dev, "%s - RUNNING IN BOOT MODE\n", __func__); 1351 dev_dbg(dev, "%s - RUNNING IN BOOT MODE\n", __func__);
1324 1352
1325 /* Configure the TI device so we can use the BULK pipes for download */ 1353 /* Configure the TI device so we can use the BULK pipes for download */