blob: c6059f49b7df2563c4e8e0de4bb89d2874a73c65 [file] [log] [blame]
/**
Copyright (c) 2008 - 2013 Quantenna Communications Inc
All Rights Reserved
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
#ifndef AUTOCONF_INCLUDED
#include <linux/config.h>
#endif
#include <linux/version.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/firmware.h>
#include <linux/elf.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include "qdrv_features.h"
#include "qdrv_debug.h"
#include "qdrv_mac.h"
#include "qdrv_soc.h"
#include "qdrv_muc.h"
#include "qdrv_hal.h"
#include "qdrv_wlan.h"
#include "qdrv_fw.h"
#include <asm/board/board_config.h>
#include <asm/board/gpio.h>
static int
adjust_muc_firmware_path( char *muc_firmware, size_t max_firmware_len )
{
int retval = 0;
enum {
SPI_shift_count = 7,
RFIC_prj_shift_count = 5,
RFIC_prj_mask = 0x07,
RFIC3_value = 0,
RFIC4_value = 1
};
const char *default_suffix =".bin";
const char *RFIC3_suffix =".bin";
const char *RFIC4_suffix =".RFIC4.bin";
#ifdef FIXME_NOW
u32 *RFIC_ver_addr = ioremap_nocache(RFIC_VERSION, 4);
u32 RFIC_ver_val = *RFIC_ver_addr;
u32 RFIC_prj_val = *RFIC_ver_addr;
#else
u32 RFIC_prj_val = RFIC3_value;
#endif
char *tmpaddr = strstr( muc_firmware, default_suffix );
unsigned int cur_firmware_len = 0;
if (tmpaddr != NULL)
*tmpaddr = '\0';
cur_firmware_len = strnlen( muc_firmware, max_firmware_len );
if (cur_firmware_len + strlen( RFIC4_suffix ) >= max_firmware_len)
return( -1 );
#ifdef FIXME_NOW
RFIC_ver_val = RFIC_ver_val >> SPI_shift_count;
RFIC_prj_val = ((RFIC_ver_val >> RFIC_prj_shift_count) & RFIC_prj_mask);
#endif
switch (RFIC_prj_val) {
case RFIC3_value:
strcat( muc_firmware, RFIC3_suffix );
break;
#ifdef FIXME_NOW
case RFIC4_value:
strcat( muc_firmware, RFIC4_suffix );
break;
default:
retval = -1;
break;
#endif
}
return( retval );
}
int qdrv_muc_init(struct qdrv_cb *qcb)
{
u32 muc_start_addr = 0;
DBGPRINTF(DBG_LL_ALL, QDRV_LF_TRACE, "-->Enter\n");
if (get_bootcfg_scancnt() == 0) {
#ifndef TOPAZ_AMBER_IP
gpio_config(RUBY_GPIO_LNA_TOGGLE, RUBY_GPIO_ALT_OUTPUT);
#else
/*
* In Amber GPIO pins are not shared. No need to set up alternate function.
*/
#endif
}
if (adjust_muc_firmware_path( qcb->muc_firmware, sizeof( qcb->muc_firmware )) < 0) {
DBGPRINTF_E( "Adjusting firmware path failed\n");
DBGPRINTF(DBG_LL_ALL, QDRV_LF_TRACE, "<--Exit\n");
return( -1 );
}
if (qdrv_fw_load_muc(qcb->dev, qcb->muc_firmware, &muc_start_addr) < 0) {
DBGPRINTF_E( "Failed to load firmware\n");
DBGPRINTF(DBG_LL_ALL, QDRV_LF_TRACE, "<--Exit\n");
return(-1);
}
#ifdef FIXME_NOW
hal_rf_enable();
#endif
hal_enable_muc(muc_start_addr);
DBGPRINTF(DBG_LL_ALL, QDRV_LF_TRACE, "<--Exit\n");
return(0);
}
int qdrv_muc_exit(struct qdrv_cb *qcb)
{
DBGPRINTF(DBG_LL_ALL, QDRV_LF_TRACE, "-->Enter\n");
hal_disable_muc();
DBGPRINTF(DBG_LL_ALL, QDRV_LF_TRACE, "<--Exit\n");
return(0);
}