1/*
2 * host_platform.c
3 *
4 * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 *  * Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 *  * Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in
15 *    the documentation and/or other materials provided with the
16 *    distribution.
17 *  * Neither the name Texas Instruments nor the names of its
18 *    contributors may be used to endorse or promote products derived
19 *    from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33#include "tidef.h"
34#include <linux/kernel.h>
35#include <asm/io.h>
36#include <linux/delay.h>
37#include <linux/platform_device.h>
38#include <linux/wifi_tiwlan.h>
39
40#include "host_platform.h"
41#include "ioctl_init.h"
42#include "WlanDrvIf.h"
43#include "Device1273.h"
44
45#define OS_API_MEM_ADDR		0x0000000
46#define OS_API_REG_ADDR		0x0300000
47#define SDIO_ATTEMPT_LONGER_DELAY_LINUX  150
48
49static struct wifi_platform_data *wifi_control_data = NULL;
50static struct resource *wifi_irqres = NULL;
51
52static int wifi_probe( struct platform_device *pdev )
53{
54	struct wifi_platform_data *wifi_ctrl = (struct wifi_platform_data *)(pdev->dev.platform_data);
55
56	/* printk("%s\n", __FUNCTION__); */
57	wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "device_wifi_irq");
58#if 0
59	if (wifi_irqres) {
60		printk("wifi_irqres->start = %lu\n", (unsigned long)(wifi_irqres->start));
61		printk("wifi_irqres->flags = %lx\n", wifi_irqres->flags);
62	}
63#endif
64	if( wifi_ctrl ) {
65		wifi_control_data = wifi_ctrl;
66#if 0
67		if( wifi_ctrl->set_power )
68			wifi_ctrl->set_power(1);	/* Power On */
69		if( wifi_ctrl->set_reset )
70			wifi_ctrl->set_reset(0);	/* Reset clear */
71		if( wifi_ctrl->set_carddetect )
72			wifi_ctrl->set_carddetect(1);	/* CardDetect (0->1) */
73#endif
74	}
75	return 0;
76}
77
78static int wifi_remove( struct platform_device *pdev )
79{
80	struct wifi_platform_data *wifi_ctrl = (struct wifi_platform_data *)(pdev->dev.platform_data);
81
82	/* printk("%s\n", __FUNCTION__); */
83	if( wifi_ctrl ) {
84		if( wifi_ctrl->set_carddetect )
85			wifi_ctrl->set_carddetect(0);	/* CardDetect (1->0) */
86		if( wifi_ctrl->set_reset )
87			wifi_ctrl->set_reset(1);	/* Reset active */
88		if( wifi_ctrl->set_power )
89			wifi_ctrl->set_power(0);	/* Power Off */
90	}
91	return 0;
92}
93
94static struct platform_driver wifi_device = {
95	.probe          = wifi_probe,
96	.remove         = wifi_remove,
97	.suspend        = NULL,
98	.resume         = NULL,
99	.driver         = {
100		.name   = "device_wifi",
101	},
102};
103
104static int wifi_add_dev( void )
105{
106	/* printk("%s\n", __FUNCTION__); */
107	return platform_driver_register( &wifi_device );
108}
109
110static void wifi_del_dev( void )
111{
112	/* printk("%s\n", __FUNCTION__); */
113	platform_driver_unregister( &wifi_device );
114}
115
116int wifi_set_carddetect( int on )
117{
118	/* printk("%s = %d\n", __FUNCTION__, on); */
119	if( wifi_control_data && wifi_control_data->set_carddetect ) {
120		wifi_control_data->set_carddetect(on);
121	}
122	return 0;
123}
124
125int wifi_set_power( int on, unsigned long msec )
126{
127	/* printk("%s = %d\n", __FUNCTION__, on); */
128	if( wifi_control_data && wifi_control_data->set_power ) {
129		wifi_control_data->set_power(on);
130	}
131	else {
132		gpio_set_value(PMENA_GPIO, on);
133	}
134	if( msec )
135		mdelay(msec);
136	return 0;
137}
138
139int wifi_set_reset( int on, unsigned long msec )
140{
141	/* printk("%s = %d\n", __FUNCTION__, on); */
142	if( wifi_control_data && wifi_control_data->set_reset ) {
143		wifi_control_data->set_reset(on);
144	}
145	if( msec )
146		mdelay(msec);
147	return 0;
148}
149
150/*-----------------------------------------------------------------------------
151Routine Name: hPlatform_hardResetTnetw
152Routine Description: set the GPIO to low after awaking the TNET from ELP.
153Arguments: None
154Return Value: 0 - Ok
155-----------------------------------------------------------------------------*/
156
157int hPlatform_hardResetTnetw( void )
158{
159	int err;
160
161	/* Turn power OFF */
162	if ((err = wifi_set_power(0, 15)) == 0) {
163		/* Turn power ON*/
164		err = wifi_set_power(1, 70);
165	}
166	return err;
167} /* hPlatform_hardResetTnetw() */
168
169/* Turn device power off */
170int hPlatform_DevicePowerOff( void )
171{
172	int err;
173
174	err = wifi_set_power(0, 15);
175	return err;
176}
177
178
179/* Turn device power off according to a given delay */
180int hPlatform_DevicePowerOffSetLongerDelay(void)
181{
182    int err;
183
184    err = wifi_set_power(0, SDIO_ATTEMPT_LONGER_DELAY_LINUX);
185
186    return err;
187}
188
189/* Turn device power on */
190int hPlatform_DevicePowerOn( void )
191{
192	int err;
193
194	wifi_set_power(1, 15); /* Fixed power sequence */
195	wifi_set_power(0, 1);
196	/* Should not be changed, 50 msec cause failures */
197	err = wifi_set_power(1, 70);
198	return err;
199}
200
201/*---------------------------------------------------------------------------*/
202
203int hPlatform_Wlan_Hardware_Init(void *tnet_drv)
204{
205	TWlanDrvIfObj *drv = tnet_drv;
206
207	printk("%s\n", __FUNCTION__);
208	wifi_add_dev();
209	if (wifi_irqres) {
210		drv->irq = wifi_irqres->start;
211		drv->irq_flags = wifi_irqres->flags & IRQF_TRIGGER_MASK;
212	}
213	else {
214		drv->irq = TNETW_IRQ;
215		drv->irq_flags = (unsigned long)IRQF_TRIGGER_FALLING;
216	}
217	return 0;
218}
219
220/*-----------------------------------------------------------------------------
221
222Routine Name:
223
224        InitInterrupt
225
226Routine Description:
227
228        this function init the interrupt to the Wlan ISR routine.
229
230Arguments:
231
232        tnet_drv - Golbal Tnet driver pointer.
233
234Return Value:
235
236        status
237
238-----------------------------------------------------------------------------*/
239
240int hPlatform_initInterrupt( void *tnet_drv, void* handle_add )
241{
242	TWlanDrvIfObj *drv = tnet_drv;
243	int rc;
244
245	if (drv->irq == 0 || handle_add == NULL)
246	{
247		print_err("hPlatform_initInterrupt() bad param drv->irq=%d handle_add=0x%x !!!\n",drv->irq,(int)handle_add);
248		return -EINVAL;
249	}
250	printk("drv->irq = %u, %lx\n", drv->irq, drv->irq_flags);
251	if ((rc = request_irq(drv->irq, handle_add, drv->irq_flags, drv->netdev->name, drv)))
252	{
253		print_err("TIWLAN: Failed to register interrupt handler\n");
254		return rc;
255	}
256	set_irq_wake(drv->irq, 1);
257	return rc;
258
259} /* hPlatform_initInterrupt() */
260
261/*--------------------------------------------------------------------------------------*/
262
263void hPlatform_freeInterrupt( void *tnet_drv )
264{
265	TWlanDrvIfObj *drv = tnet_drv;
266
267	set_irq_wake(drv->irq, 0);
268	free_irq(drv->irq, drv);
269}
270
271/****************************************************************************************
272 *                        hPlatform_hwGetRegistersAddr()
273 ****************************************************************************************
274DESCRIPTION:
275
276ARGUMENTS:
277
278RETURN:
279
280NOTES:
281*****************************************************************************************/
282void *hPlatform_hwGetRegistersAddr(TI_HANDLE OsContext)
283{
284	return (void *)OS_API_REG_ADDR;
285}
286
287/****************************************************************************************
288 *                        hPlatform_hwGetMemoryAddr()
289 ****************************************************************************************
290DESCRIPTION:
291
292ARGUMENTS:
293
294RETURN:
295
296NOTES:
297*****************************************************************************************/
298void *hPlatform_hwGetMemoryAddr(TI_HANDLE OsContext)
299{
300	return (void *)OS_API_MEM_ADDR;
301}
302
303
304void hPlatform_Wlan_Hardware_DeInit(void)
305{
306	wifi_del_dev();
307}
308