blob: 2f95c6ddb79c95c57ac2c1fbfab848298fed3fc4 [file] [log] [blame]
/*
* host_platform.c
*
* Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Texas Instruments nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "tidef.h"
#include <linux/kernel.h>
#include <asm/io.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/wifi_tiwlan.h>
#include "host_platform.h"
#include "ioctl_init.h"
#include "WlanDrvIf.h"
#include "Device1273.h"
#define OS_API_MEM_ADDR 0x0000000
#define OS_API_REG_ADDR 0x0300000
#define SDIO_ATTEMPT_LONGER_DELAY_LINUX 150
static struct wifi_platform_data *wifi_control_data = NULL;
static struct resource *wifi_irqres = NULL;
static int wifi_probe( struct platform_device *pdev )
{
struct wifi_platform_data *wifi_ctrl = (struct wifi_platform_data *)(pdev->dev.platform_data);
/* printk("%s\n", __FUNCTION__); */
wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "device_wifi_irq");
#if 0
if (wifi_irqres) {
printk("wifi_irqres->start = %lu\n", (unsigned long)(wifi_irqres->start));
printk("wifi_irqres->flags = %lx\n", wifi_irqres->flags);
}
#endif
if( wifi_ctrl ) {
wifi_control_data = wifi_ctrl;
#if 0
if( wifi_ctrl->set_power )
wifi_ctrl->set_power(1); /* Power On */
if( wifi_ctrl->set_reset )
wifi_ctrl->set_reset(0); /* Reset clear */
if( wifi_ctrl->set_carddetect )
wifi_ctrl->set_carddetect(1); /* CardDetect (0->1) */
#endif
}
return 0;
}
static int wifi_remove( struct platform_device *pdev )
{
struct wifi_platform_data *wifi_ctrl = (struct wifi_platform_data *)(pdev->dev.platform_data);
/* printk("%s\n", __FUNCTION__); */
if( wifi_ctrl ) {
if( wifi_ctrl->set_carddetect )
wifi_ctrl->set_carddetect(0); /* CardDetect (1->0) */
if( wifi_ctrl->set_reset )
wifi_ctrl->set_reset(1); /* Reset active */
if( wifi_ctrl->set_power )
wifi_ctrl->set_power(0); /* Power Off */
}
return 0;
}
static struct platform_driver wifi_device = {
.probe = wifi_probe,
.remove = wifi_remove,
.suspend = NULL,
.resume = NULL,
.driver = {
.name = "device_wifi",
},
};
static int wifi_add_dev( void )
{
/* printk("%s\n", __FUNCTION__); */
return platform_driver_register( &wifi_device );
}
static void wifi_del_dev( void )
{
/* printk("%s\n", __FUNCTION__); */
platform_driver_unregister( &wifi_device );
}
int wifi_set_carddetect( int on )
{
/* printk("%s = %d\n", __FUNCTION__, on); */
if( wifi_control_data && wifi_control_data->set_carddetect ) {
wifi_control_data->set_carddetect(on);
}
return 0;
}
int wifi_set_power( int on, unsigned long msec )
{
/* printk("%s = %d\n", __FUNCTION__, on); */
if( wifi_control_data && wifi_control_data->set_power ) {
wifi_control_data->set_power(on);
}
else {
gpio_set_value(PMENA_GPIO, on);
}
if( msec )
mdelay(msec);
return 0;
}
int wifi_set_reset( int on, unsigned long msec )
{
/* printk("%s = %d\n", __FUNCTION__, on); */
if( wifi_control_data && wifi_control_data->set_reset ) {
wifi_control_data->set_reset(on);
}
if( msec )
mdelay(msec);
return 0;
}
/*-----------------------------------------------------------------------------
Routine Name: hPlatform_hardResetTnetw
Routine Description: set the GPIO to low after awaking the TNET from ELP.
Arguments: None
Return Value: 0 - Ok
-----------------------------------------------------------------------------*/
int hPlatform_hardResetTnetw( void )
{
int err;
/* Turn power OFF */
if ((err = wifi_set_power(0, 15)) == 0) {
/* Turn power ON*/
err = wifi_set_power(1, 70);
}
return err;
} /* hPlatform_hardResetTnetw() */
/* Turn device power off */
int hPlatform_DevicePowerOff( void )
{
int err;
err = wifi_set_power(0, 15);
return err;
}
/* Turn device power off according to a given delay */
int hPlatform_DevicePowerOffSetLongerDelay(void)
{
int err;
err = wifi_set_power(0, SDIO_ATTEMPT_LONGER_DELAY_LINUX);
return err;
}
/* Turn device power on */
int hPlatform_DevicePowerOn( void )
{
int err;
wifi_set_power(1, 15); /* Fixed power sequence */
wifi_set_power(0, 1);
/* Should not be changed, 50 msec cause failures */
err = wifi_set_power(1, 70);
return err;
}
/*---------------------------------------------------------------------------*/
int hPlatform_Wlan_Hardware_Init(void *tnet_drv)
{
TWlanDrvIfObj *drv = tnet_drv;
printk("%s\n", __FUNCTION__);
wifi_add_dev();
if (wifi_irqres) {
drv->irq = wifi_irqres->start;
drv->irq_flags = wifi_irqres->flags & IRQF_TRIGGER_MASK;
}
else {
drv->irq = TNETW_IRQ;
drv->irq_flags = (unsigned long)IRQF_TRIGGER_FALLING;
}
return 0;
}
/*-----------------------------------------------------------------------------
Routine Name:
InitInterrupt
Routine Description:
this function init the interrupt to the Wlan ISR routine.
Arguments:
tnet_drv - Golbal Tnet driver pointer.
Return Value:
status
-----------------------------------------------------------------------------*/
int hPlatform_initInterrupt( void *tnet_drv, void* handle_add )
{
TWlanDrvIfObj *drv = tnet_drv;
int rc;
if (drv->irq == 0 || handle_add == NULL)
{
print_err("hPlatform_initInterrupt() bad param drv->irq=%d handle_add=0x%x !!!\n",drv->irq,(int)handle_add);
return -EINVAL;
}
printk("drv->irq = %u, %lx\n", drv->irq, drv->irq_flags);
if ((rc = request_irq(drv->irq, handle_add, drv->irq_flags, drv->netdev->name, drv)))
{
print_err("TIWLAN: Failed to register interrupt handler\n");
return rc;
}
set_irq_wake(drv->irq, 1);
return rc;
} /* hPlatform_initInterrupt() */
/*--------------------------------------------------------------------------------------*/
void hPlatform_freeInterrupt( void *tnet_drv )
{
TWlanDrvIfObj *drv = tnet_drv;
set_irq_wake(drv->irq, 0);
free_irq(drv->irq, drv);
}
/****************************************************************************************
* hPlatform_hwGetRegistersAddr()
****************************************************************************************
DESCRIPTION:
ARGUMENTS:
RETURN:
NOTES:
*****************************************************************************************/
void *hPlatform_hwGetRegistersAddr(TI_HANDLE OsContext)
{
return (void *)OS_API_REG_ADDR;
}
/****************************************************************************************
* hPlatform_hwGetMemoryAddr()
****************************************************************************************
DESCRIPTION:
ARGUMENTS:
RETURN:
NOTES:
*****************************************************************************************/
void *hPlatform_hwGetMemoryAddr(TI_HANDLE OsContext)
{
return (void *)OS_API_MEM_ADDR;
}
void hPlatform_Wlan_Hardware_DeInit(void)
{
wifi_del_dev();
}