• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* tnetw_sdio.c
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 as
5  * published by the Free Software Foundation.
6  *
7  * Copyright � Texas Instruments Incorporated (Oct 2005)
8  * THIS CODE/PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
9  * EITHER EXPRESS OR IMPLIED, INCLUDED BUT NOT LIMITED TO , THE IMPLIED
10  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11  * This program has been modified from its original operation by Texas
12  * Instruments Incorporated. These changes are covered under version 2
13  * of the GNU General Public License, dated June 1991.
14  *
15  * Copyright � Google Inc (Feb 2008)
16  */
17 /*-------------------------------------------------------------------*/
18 #ifdef TIWLAN_MSM7000
19 #include <linux/mm.h>
20 #include <linux/vmalloc.h>
21 #include <linux/pagemap.h>
22 #include <asm/pgtable.h>
23 #include <asm/cacheflush.h>
24 
25 #include <linux/delay.h>
26 #include <linux/mmc/core.h>
27 #include <linux/mmc/card.h>
28 #include <linux/mmc/host.h>
29 #include <linux/mmc/sdio_func.h>
30 #include <linux/mmc/sdio_ids.h>
31 #include "esta_drv.h"
32 #include "mmc_omap_api.h"
33 #include "osApi.h"
34 
35 /*-------------------------------------------------------------------*/
36 extern int tiwlan_sdio_init(struct sdio_func *func);
37 extern int sdio_reset_comm(struct mmc_card *card);
38 
39 /*-------------------------------------------------------------------*/
40 static struct sdio_func *tiwlan_func = NULL;
41 static int sdio_reset_flag = 0;
42 
43 #define DMA_THRESHOLD_SIZE  64
44 static void *sdio_dma_ptr = NULL;
45 #define USE_SKETCHY_WRITES 0
46 
47 /*-------------------------------------------------------------------*/
SDIO_SetFunc(struct sdio_func * func)48 void SDIO_SetFunc( struct sdio_func *func )
49 {
50 	tiwlan_func = func;
51 }
52 
SDIO_GetFunc(void)53 struct sdio_func *SDIO_GetFunc( void )
54 {
55 	return tiwlan_func;
56 }
57 
SDIO_Init(SDIO_ConfigParams * ConfigParams,SDIO_Handle * Handle)58 SDIO_Status SDIO_Init(SDIO_ConfigParams *ConfigParams, SDIO_Handle *Handle)
59 {
60 	if (Handle == NULL) {
61 		printk(KERN_ERR "Error: SDIO_Init() called with NULL!\n");
62 		return SDIO_FAILURE;
63 	}
64 
65 	*Handle = (SDIO_Handle)SDIO_GetFunc();
66 	if ((*Handle) == NULL) {
67 		printk(KERN_ERR "SDIO_Init() called before init!\n");
68 		return SDIO_FAILURE;
69 	}
70 
71 	if (!sdio_dma_ptr) {
72 		if (!(sdio_dma_ptr = kmalloc(PAGE_SIZE, GFP_KERNEL))) {
73 			printk(KERN_ERR "Failed to alloc DMA bounce buffer\n");
74 			return SDIO_FAILURE;
75 		}
76 	}
77 	return SDIO_SUCCESS;
78 }
79 
SDIO_Shutdown(SDIO_Handle Handle)80 SDIO_Status SDIO_Shutdown(SDIO_Handle Handle)
81 {
82 	if (sdio_dma_ptr) {
83 		kfree(sdio_dma_ptr);
84 		sdio_dma_ptr = NULL;
85 	}
86 	return SDIO_SUCCESS;
87 }
88 
SDIO_Start(SDIO_Handle Handle)89 SDIO_Status SDIO_Start(SDIO_Handle Handle)
90 {
91 	struct sdio_func *func = (struct sdio_func *)Handle;
92 
93 	if (func) {
94 		if (sdio_reset_flag) {
95 			sdio_reset_flag = 0;
96 			if (tiwlan_sdio_init(func)) {
97 				printk("TI: tiwlan_sdio_init Error!\n");
98 				return SDIO_FAILURE;
99 			}
100 
101 		}
102 	}
103 	return SDIO_SUCCESS;
104 }
105 
SDIO_Reset(SDIO_Handle Handle)106 SDIO_Status SDIO_Reset(SDIO_Handle Handle)
107 {
108 	struct sdio_func *func = (struct sdio_func *)Handle;
109 
110 	if (func && func->card) {
111 		sdio_release_host(func);
112 		sdio_reset_comm(func->card);
113 		sdio_claim_host(func);
114 	}
115 	return SDIO_SUCCESS;
116 }
117 
SDIO_Stop(SDIO_Handle Handle,unsigned long Wait_Window)118 SDIO_Status SDIO_Stop(SDIO_Handle Handle, unsigned long Wait_Window)
119 {
120 	sdio_reset_flag = 1;
121 	return SDIO_Reset(Handle);
122 }
123 
spans_page(void * s,int len)124 static inline int spans_page(void *s, int len)
125 {
126 	if (((unsigned long) s + len) <= ((((unsigned long) s) & ~(PAGE_SIZE-1)) + PAGE_SIZE))
127 		return 0;
128 	return 1;
129 }
130 
vmalloc_to_unity(void * a)131 static void *vmalloc_to_unity(void *a)
132 {
133 	pte_t *pte;
134 	unsigned long virt = (unsigned long) a;
135 	unsigned long phys;
136 
137 	pte = pte_offset_map(pmd_offset(pgd_offset_k(virt), virt), virt);
138 	phys = (pte_val(*pte) & ~(PAGE_SIZE -1)) | (virt & (PAGE_SIZE -1));
139 	pte_unmap(pte);
140 	return phys_to_virt(phys);
141 }
142 
SDIO_SyncRead(SDIO_Handle Handle,SDIO_Request_t * Req)143 SDIO_Status SDIO_SyncRead(SDIO_Handle Handle, SDIO_Request_t *Req)
144 {
145 	struct sdio_func *func = (struct sdio_func *)Handle;
146 	int rc;
147 	void *tgt = Req->buffer;
148 
149 	if (Req->buffer_len >= DMA_THRESHOLD_SIZE) {
150 		if (is_vmalloc_addr(tgt)) {
151 			if (!spans_page(tgt, Req->buffer_len)) {
152 				tgt = vmalloc_to_unity(tgt);
153 				dmac_flush_range(Req->buffer,
154 						 Req->buffer + Req->buffer_len);
155 			} else
156 				tgt = sdio_dma_ptr;
157 		}
158 	}
159 
160 	if ((rc = sdio_memcpy_fromio(func, tgt, Req->peripheral_addr,
161 				     Req->buffer_len))) {
162 		printk(KERN_ERR "%s: failed (%d)\n", __func__, rc);
163 		return SDIO_FAILURE;
164 	}
165 
166 	if (tgt == sdio_dma_ptr)
167 		memcpy(Req->buffer, sdio_dma_ptr, Req->buffer_len);
168 
169 	return SDIO_SUCCESS;
170 }
171 
SDIO_SyncWrite(SDIO_Handle Handle,SDIO_Request_t * Req)172 SDIO_Status SDIO_SyncWrite(SDIO_Handle Handle, SDIO_Request_t *Req)
173 {
174 	struct sdio_func *func = (struct sdio_func *)Handle;
175 	int rc;
176 	void *src = Req->buffer;
177 
178 	if (Req->buffer_len >= DMA_THRESHOLD_SIZE) {
179 #if USE_SKETCHY_WRITES
180 		if (is_vmalloc_addr(src)) {
181 			if (!spans_page(src, Req->buffer_len)) {
182 				src = vmalloc_to_unity(src);
183 				dmac_clean_range(Req->buffer,
184 						 Req->buffer + Req->buffer_len);
185 			} else {
186 #endif
187 				src = sdio_dma_ptr;
188 				memcpy(src, Req->buffer, Req->buffer_len);
189 #if USE_SKETCHY_WRITES
190 			}
191 		}
192 #endif
193 	}
194 
195 	rc = sdio_memcpy_toio(func, Req->peripheral_addr, src,
196 			      Req->buffer_len);
197 
198 	if (!rc)
199 		return SDIO_SUCCESS;
200 
201 	printk(KERN_ERR "%s: failed (%d)\n", __func__, rc);
202 	return SDIO_FAILURE;
203 }
204 #endif
205