Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Abilis Systems Single DVB-T Receiver
0004  * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
0005  * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
0006  */
0007 #include <linux/kernel.h>
0008 #include <linux/errno.h>
0009 #include <linux/ctype.h>
0010 #include <linux/delay.h>
0011 #include <linux/firmware.h>
0012 
0013 #include "as102_drv.h"
0014 #include "as102_fw.h"
0015 
0016 static const char as102_st_fw1[] = "as102_data1_st.hex";
0017 static const char as102_st_fw2[] = "as102_data2_st.hex";
0018 static const char as102_dt_fw1[] = "as102_data1_dt.hex";
0019 static const char as102_dt_fw2[] = "as102_data2_dt.hex";
0020 
0021 static unsigned char atohx(unsigned char *dst, char *src)
0022 {
0023     unsigned char value = 0;
0024 
0025     char msb = tolower(*src) - '0';
0026     char lsb = tolower(*(src + 1)) - '0';
0027 
0028     if (msb > 9)
0029         msb -= 7;
0030     if (lsb > 9)
0031         lsb -= 7;
0032 
0033     *dst = value = ((msb & 0xF) << 4) | (lsb & 0xF);
0034     return value;
0035 }
0036 
0037 /*
0038  * Parse INTEL HEX firmware file to extract address and data.
0039  */
0040 static int parse_hex_line(unsigned char *fw_data, unsigned char *addr,
0041               unsigned char *data, int *dataLength,
0042               unsigned char *addr_has_changed) {
0043 
0044     int count = 0;
0045     unsigned char *src, dst;
0046 
0047     if (*fw_data++ != ':') {
0048         pr_err("invalid firmware file\n");
0049         return -EFAULT;
0050     }
0051 
0052     /* locate end of line */
0053     for (src = fw_data; *src != '\n'; src += 2) {
0054         atohx(&dst, src);
0055         /* parse line to split addr / data */
0056         switch (count) {
0057         case 0:
0058             *dataLength = dst;
0059             break;
0060         case 1:
0061             addr[2] = dst;
0062             break;
0063         case 2:
0064             addr[3] = dst;
0065             break;
0066         case 3:
0067             /* check if data is an address */
0068             if (dst == 0x04)
0069                 *addr_has_changed = 1;
0070             else
0071                 *addr_has_changed = 0;
0072             break;
0073         case  4:
0074         case  5:
0075             if (*addr_has_changed)
0076                 addr[(count - 4)] = dst;
0077             else
0078                 data[(count - 4)] = dst;
0079             break;
0080         default:
0081             data[(count - 4)] = dst;
0082             break;
0083         }
0084         count++;
0085     }
0086 
0087     /* return read value + ':' + '\n' */
0088     return (count * 2) + 2;
0089 }
0090 
0091 static int as102_firmware_upload(struct as10x_bus_adapter_t *bus_adap,
0092                  unsigned char *cmd,
0093                  const struct firmware *firmware) {
0094 
0095     struct as10x_fw_pkt_t *fw_pkt;
0096     int total_read_bytes = 0, errno = 0;
0097     unsigned char addr_has_changed = 0;
0098 
0099     fw_pkt = kmalloc(sizeof(*fw_pkt), GFP_KERNEL);
0100     if (!fw_pkt)
0101         return -ENOMEM;
0102 
0103 
0104     for (total_read_bytes = 0; total_read_bytes < firmware->size; ) {
0105         int read_bytes = 0, data_len = 0;
0106 
0107         /* parse intel hex line */
0108         read_bytes = parse_hex_line(
0109                 (u8 *) (firmware->data + total_read_bytes),
0110                 fw_pkt->raw.address,
0111                 fw_pkt->raw.data,
0112                 &data_len,
0113                 &addr_has_changed);
0114 
0115         if (read_bytes <= 0)
0116             goto error;
0117 
0118         /* detect the end of file */
0119         total_read_bytes += read_bytes;
0120         if (total_read_bytes == firmware->size) {
0121             fw_pkt->u.request[0] = 0x00;
0122             fw_pkt->u.request[1] = 0x03;
0123 
0124             /* send EOF command */
0125             errno = bus_adap->ops->upload_fw_pkt(bus_adap,
0126                                  (uint8_t *)
0127                                  fw_pkt, 2, 0);
0128             if (errno < 0)
0129                 goto error;
0130         } else {
0131             if (!addr_has_changed) {
0132                 /* prepare command to send */
0133                 fw_pkt->u.request[0] = 0x00;
0134                 fw_pkt->u.request[1] = 0x01;
0135 
0136                 data_len += sizeof(fw_pkt->u.request);
0137                 data_len += sizeof(fw_pkt->raw.address);
0138 
0139                 /* send cmd to device */
0140                 errno = bus_adap->ops->upload_fw_pkt(bus_adap,
0141                                      (uint8_t *)
0142                                      fw_pkt,
0143                                      data_len,
0144                                      0);
0145                 if (errno < 0)
0146                     goto error;
0147             }
0148         }
0149     }
0150 error:
0151     kfree(fw_pkt);
0152     return (errno == 0) ? total_read_bytes : errno;
0153 }
0154 
0155 int as102_fw_upload(struct as10x_bus_adapter_t *bus_adap)
0156 {
0157     int errno = -EFAULT;
0158     const struct firmware *firmware = NULL;
0159     unsigned char *cmd_buf = NULL;
0160     const char *fw1, *fw2;
0161     struct usb_device *dev = bus_adap->usb_dev;
0162 
0163     /* select fw file to upload */
0164     if (dual_tuner) {
0165         fw1 = as102_dt_fw1;
0166         fw2 = as102_dt_fw2;
0167     } else {
0168         fw1 = as102_st_fw1;
0169         fw2 = as102_st_fw2;
0170     }
0171 
0172     /* allocate buffer to store firmware upload command and data */
0173     cmd_buf = kzalloc(MAX_FW_PKT_SIZE, GFP_KERNEL);
0174     if (cmd_buf == NULL) {
0175         errno = -ENOMEM;
0176         goto error;
0177     }
0178 
0179     /* request kernel to locate firmware file: part1 */
0180     errno = request_firmware(&firmware, fw1, &dev->dev);
0181     if (errno < 0) {
0182         pr_err("%s: unable to locate firmware file: %s\n",
0183                DRIVER_NAME, fw1);
0184         goto error;
0185     }
0186 
0187     /* initiate firmware upload */
0188     errno = as102_firmware_upload(bus_adap, cmd_buf, firmware);
0189     if (errno < 0) {
0190         pr_err("%s: error during firmware upload part1\n",
0191                DRIVER_NAME);
0192         goto error;
0193     }
0194 
0195     pr_info("%s: firmware: %s loaded with success\n",
0196         DRIVER_NAME, fw1);
0197     release_firmware(firmware);
0198     firmware = NULL;
0199 
0200     /* wait for boot to complete */
0201     mdelay(100);
0202 
0203     /* request kernel to locate firmware file: part2 */
0204     errno = request_firmware(&firmware, fw2, &dev->dev);
0205     if (errno < 0) {
0206         pr_err("%s: unable to locate firmware file: %s\n",
0207                DRIVER_NAME, fw2);
0208         goto error;
0209     }
0210 
0211     /* initiate firmware upload */
0212     errno = as102_firmware_upload(bus_adap, cmd_buf, firmware);
0213     if (errno < 0) {
0214         pr_err("%s: error during firmware upload part2\n",
0215                DRIVER_NAME);
0216         goto error;
0217     }
0218 
0219     pr_info("%s: firmware: %s loaded with success\n",
0220         DRIVER_NAME, fw2);
0221 error:
0222     kfree(cmd_buf);
0223     release_firmware(firmware);
0224 
0225     return errno;
0226 }