2019-05-23 12:14:55 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2011-10-31 19:24:39 +04:00
/*
* Abilis Systems Single DVB - T Receiver
* Copyright ( C ) 2008 Pierrick Hascoet < pierrick . hascoet @ abilis . com >
2011-10-31 19:24:41 +04:00
* Copyright ( C ) 2010 Devin Heitmueller < dheitmueller @ kernellabs . com >
2011-10-31 19:24:39 +04:00
*/
# include <linux/kernel.h>
# include <linux/errno.h>
# include <linux/ctype.h>
# include <linux/delay.h>
# include <linux/firmware.h>
# include "as102_drv.h"
# include "as102_fw.h"
2013-11-26 18:15:20 +04:00
static const char as102_st_fw1 [ ] = " as102_data1_st.hex " ;
static const char as102_st_fw2 [ ] = " as102_data2_st.hex " ;
static const char as102_dt_fw1 [ ] = " as102_data1_dt.hex " ;
static const char as102_dt_fw2 [ ] = " as102_data2_dt.hex " ;
2011-10-31 19:24:39 +04:00
2011-10-31 19:24:41 +04:00
static unsigned char atohx ( unsigned char * dst , char * src )
{
2011-10-31 19:24:39 +04:00
unsigned char value = 0 ;
char msb = tolower ( * src ) - ' 0 ' ;
2011-10-31 19:24:41 +04:00
char lsb = tolower ( * ( src + 1 ) ) - ' 0 ' ;
2011-10-31 19:24:39 +04:00
2011-10-31 19:24:41 +04:00
if ( msb > 9 )
2011-10-31 19:24:39 +04:00
msb - = 7 ;
2011-10-31 19:24:41 +04:00
if ( lsb > 9 )
2011-10-31 19:24:39 +04:00
lsb - = 7 ;
* dst = value = ( ( msb & 0xF ) < < 4 ) | ( lsb & 0xF ) ;
return value ;
}
/*
* Parse INTEL HEX firmware file to extract address and data .
*/
static int parse_hex_line ( unsigned char * fw_data , unsigned char * addr ,
unsigned char * data , int * dataLength ,
unsigned char * addr_has_changed ) {
int count = 0 ;
unsigned char * src , dst ;
if ( * fw_data + + ! = ' : ' ) {
2011-11-06 23:31:45 +04:00
pr_err ( " invalid firmware file \n " ) ;
2011-10-31 19:24:39 +04:00
return - EFAULT ;
}
/* locate end of line */
2011-10-31 19:24:41 +04:00
for ( src = fw_data ; * src ! = ' \n ' ; src + = 2 ) {
2011-10-31 19:24:39 +04:00
atohx ( & dst , src ) ;
/* parse line to split addr / data */
switch ( count ) {
2011-10-31 19:24:41 +04:00
case 0 :
* dataLength = dst ;
break ;
case 1 :
addr [ 2 ] = dst ;
break ;
case 2 :
addr [ 3 ] = dst ;
break ;
case 3 :
/* check if data is an address */
if ( dst = = 0x04 )
* addr_has_changed = 1 ;
else
* addr_has_changed = 0 ;
break ;
case 4 :
case 5 :
if ( * addr_has_changed )
addr [ ( count - 4 ) ] = dst ;
else
2011-10-31 19:24:39 +04:00
data [ ( count - 4 ) ] = dst ;
2011-10-31 19:24:41 +04:00
break ;
default :
data [ ( count - 4 ) ] = dst ;
break ;
2011-10-31 19:24:39 +04:00
}
count + + ;
}
/* return read value + ':' + '\n' */
2011-10-31 19:24:41 +04:00
return ( count * 2 ) + 2 ;
2011-10-31 19:24:39 +04:00
}
2011-11-06 23:31:50 +04:00
static int as102_firmware_upload ( struct as10x_bus_adapter_t * bus_adap ,
2011-10-31 19:24:39 +04:00
unsigned char * cmd ,
const struct firmware * firmware ) {
2017-11-06 16:50:22 +03:00
struct as10x_fw_pkt_t * fw_pkt ;
2011-10-31 19:24:39 +04:00
int total_read_bytes = 0 , errno = 0 ;
unsigned char addr_has_changed = 0 ;
2017-11-06 16:50:22 +03:00
fw_pkt = kmalloc ( sizeof ( * fw_pkt ) , GFP_KERNEL ) ;
if ( ! fw_pkt )
return - ENOMEM ;
2011-10-31 19:24:39 +04:00
for ( total_read_bytes = 0 ; total_read_bytes < firmware - > size ; ) {
int read_bytes = 0 , data_len = 0 ;
/* parse intel hex line */
read_bytes = parse_hex_line (
( u8 * ) ( firmware - > data + total_read_bytes ) ,
2017-11-06 16:50:22 +03:00
fw_pkt - > raw . address ,
fw_pkt - > raw . data ,
2011-10-31 19:24:39 +04:00
& data_len ,
& addr_has_changed ) ;
2011-10-31 19:24:41 +04:00
if ( read_bytes < = 0 )
2011-10-31 19:24:39 +04:00
goto error ;
/* detect the end of file */
2011-10-31 19:24:41 +04:00
total_read_bytes + = read_bytes ;
if ( total_read_bytes = = firmware - > size ) {
2017-11-06 16:50:22 +03:00
fw_pkt - > u . request [ 0 ] = 0x00 ;
fw_pkt - > u . request [ 1 ] = 0x03 ;
2011-10-31 19:24:39 +04:00
/* send EOF command */
2011-10-31 19:24:41 +04:00
errno = bus_adap - > ops - > upload_fw_pkt ( bus_adap ,
( uint8_t * )
2017-11-06 16:50:22 +03:00
fw_pkt , 2 , 0 ) ;
2011-10-31 19:24:41 +04:00
if ( errno < 0 )
2011-10-31 19:24:39 +04:00
goto error ;
} else {
if ( ! addr_has_changed ) {
/* prepare command to send */
2017-11-06 16:50:22 +03:00
fw_pkt - > u . request [ 0 ] = 0x00 ;
fw_pkt - > u . request [ 1 ] = 0x01 ;
2011-10-31 19:24:39 +04:00
2017-11-06 16:50:22 +03:00
data_len + = sizeof ( fw_pkt - > u . request ) ;
data_len + = sizeof ( fw_pkt - > raw . address ) ;
2011-10-31 19:24:39 +04:00
/* send cmd to device */
2011-10-31 19:24:41 +04:00
errno = bus_adap - > ops - > upload_fw_pkt ( bus_adap ,
( uint8_t * )
2017-11-06 16:50:22 +03:00
fw_pkt ,
2011-10-31 19:24:41 +04:00
data_len ,
0 ) ;
if ( errno < 0 )
2011-10-31 19:24:39 +04:00
goto error ;
}
}
}
error :
2017-11-06 16:50:22 +03:00
kfree ( fw_pkt ) ;
2011-10-31 19:24:39 +04:00
return ( errno = = 0 ) ? total_read_bytes : errno ;
}
2011-11-06 23:31:50 +04:00
int as102_fw_upload ( struct as10x_bus_adapter_t * bus_adap )
2011-10-31 19:24:41 +04:00
{
2011-10-31 19:24:39 +04:00
int errno = - EFAULT ;
2012-03-25 01:39:18 +04:00
const struct firmware * firmware = NULL ;
2011-10-31 19:24:39 +04:00
unsigned char * cmd_buf = NULL ;
2013-11-26 18:15:20 +04:00
const char * fw1 , * fw2 ;
2011-10-31 19:24:39 +04:00
struct usb_device * dev = bus_adap - > usb_dev ;
2011-11-06 23:31:40 +04:00
2011-10-31 19:24:39 +04:00
/* select fw file to upload */
if ( dual_tuner ) {
fw1 = as102_dt_fw1 ;
fw2 = as102_dt_fw2 ;
} else {
fw1 = as102_st_fw1 ;
fw2 = as102_st_fw2 ;
}
/* allocate buffer to store firmware upload command and data */
2011-10-31 19:24:41 +04:00
cmd_buf = kzalloc ( MAX_FW_PKT_SIZE , GFP_KERNEL ) ;
if ( cmd_buf = = NULL ) {
2011-10-31 19:24:39 +04:00
errno = - ENOMEM ;
goto error ;
}
/* request kernel to locate firmware file: part1 */
2011-10-31 19:24:41 +04:00
errno = request_firmware ( & firmware , fw1 , & dev - > dev ) ;
if ( errno < 0 ) {
2011-11-06 23:31:45 +04:00
pr_err ( " %s: unable to locate firmware file: %s \n " ,
DRIVER_NAME , fw1 ) ;
2011-10-31 19:24:39 +04:00
goto error ;
}
/* initiate firmware upload */
2011-10-31 19:24:41 +04:00
errno = as102_firmware_upload ( bus_adap , cmd_buf , firmware ) ;
if ( errno < 0 ) {
2011-11-06 23:31:45 +04:00
pr_err ( " %s: error during firmware upload part1 \n " ,
DRIVER_NAME ) ;
2011-10-31 19:24:39 +04:00
goto error ;
}
2011-11-06 23:31:45 +04:00
pr_info ( " %s: firmware: %s loaded with success \n " ,
DRIVER_NAME , fw1 ) ;
2011-10-31 19:24:39 +04:00
release_firmware ( firmware ) ;
2015-10-24 00:26:18 +03:00
firmware = NULL ;
2011-10-31 19:24:39 +04:00
/* wait for boot to complete */
mdelay ( 100 ) ;
/* request kernel to locate firmware file: part2 */
2011-10-31 19:24:41 +04:00
errno = request_firmware ( & firmware , fw2 , & dev - > dev ) ;
if ( errno < 0 ) {
2011-11-06 23:31:45 +04:00
pr_err ( " %s: unable to locate firmware file: %s \n " ,
DRIVER_NAME , fw2 ) ;
2011-10-31 19:24:39 +04:00
goto error ;
}
/* initiate firmware upload */
2011-10-31 19:24:41 +04:00
errno = as102_firmware_upload ( bus_adap , cmd_buf , firmware ) ;
if ( errno < 0 ) {
2011-11-06 23:31:45 +04:00
pr_err ( " %s: error during firmware upload part2 \n " ,
DRIVER_NAME ) ;
2011-10-31 19:24:39 +04:00
goto error ;
}
2011-11-06 23:31:45 +04:00
pr_info ( " %s: firmware: %s loaded with success \n " ,
DRIVER_NAME , fw2 ) ;
2011-10-31 19:24:39 +04:00
error :
kfree ( cmd_buf ) ;
2012-04-09 23:51:48 +04:00
release_firmware ( firmware ) ;
2011-11-06 23:31:41 +04:00
2011-10-31 19:24:39 +04:00
return errno ;
}