1/* 2 * arch/ubicom32/mach-common/usb_tio.c 3 * Linux side Ubicom USB TIO driver 4 * 5 * (C) Copyright 2009, Ubicom, Inc. 6 * 7 * This file is part of the Ubicom32 Linux Kernel Port. 8 * 9 * The Ubicom32 Linux Kernel Port is free software: you can redistribute 10 * it and/or modify it under the terms of the GNU General Public License 11 * as published by the Free Software Foundation, either version 2 of the 12 * License, or (at your option) any later version. 13 * 14 * The Ubicom32 Linux Kernel Port is distributed in the hope that it 15 * will be useful, but WITHOUT ANY WARRANTY; without even the implied 16 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 17 * the GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with the Ubicom32 Linux Kernel Port. If not, 21 * see <http://www.gnu.org/licenses/>. 22 * 23 * Ubicom32 implementation derived from (with many thanks): 24 * arch/m68knommu 25 * arch/blackfin 26 * arch/parisc 27 */ 28#include <linux/module.h> 29#include <linux/spinlock.h> 30#include <linux/slab.h> 31#include <asm/devtree.h> 32#include "usb_tio.h" 33 34#ifdef CONFIG_SMP 35static DEFINE_SPINLOCK(tio_lock); 36#define USB_TIO_LOCK(lock, flag) spin_lock_irqsave(lock, flag) 37#define USB_TIO_UNLOCK(lock, flag) spin_unlock_irqrestore(lock, flag) 38#define USB_TIO_LOCK_ISLOCKED(lock) spin_try_lock(lock) 39#else 40#define USB_TIO_LOCK(lock, flag) local_irq_save(flag) 41#define USB_TIO_UNLOCK(lock, flag) local_irq_restore(flag) 42#endif 43 44spinlock_t usb_tio_lock; 45 46/* 47 * usb_tio_set_hrt_interrupt() 48 */ 49static inline void usb_tio_set_hrt_interrupt(void) 50{ 51 ubicom32_set_interrupt(usb_node->dn.sendirq); 52} 53 54static inline void usb_tio_wait_hrt(void) 55{ 56 while (unlikely(usb_node->pdesc)); 57} 58 59#if defined(USB_TIO_DEBUG) 60static void usb_tio_request_verify_magic(volatile struct usb_tio_request *req) 61{ 62 BUG_ON(req->magic != USB_TIO_REQUEST_MAGIC2); 63} 64 65static void usb_tio_request_clear_magic(volatile struct usb_tio_request *req) 66{ 67 req->magic = 0; 68} 69#endif 70 71static void usb_tio_request_set_magic(volatile struct usb_tio_request *req) 72{ 73 req->magic = USB_TIO_REQUEST_MAGIC1; 74} 75 76/* 77 * usb_tio_commit_request() 78 */ 79static inline void usb_tio_commit_request(volatile struct usb_tio_request *request) 80{ 81 wmb(); 82 usb_node->pdesc = request; 83 84 /* 85 * next thing to do is alway checking if (usb_node->pdesc == NULL) 86 * to see if the request is done, so add a mb() here 87 */ 88 mb(); 89 usb_tio_set_hrt_interrupt(); 90} 91 92/* 93 * usb_tio_read_u16() 94 * Synchronously read 16 bits. 95 */ 96u8_t usb_tio_read_u16(u32_t address, u16_t *data) 97{ 98 volatile struct usb_tio_request *tio_req = &usb_node->request; 99 unsigned long flag; 100 101 /* 102 * Wait for any previous request to complete and then make this request. 103 */ 104 USB_TIO_LOCK(&tio_lock, flag); 105 usb_tio_wait_hrt(); 106 107 /* 108 * Fill in the request. 109 */ 110 tio_req->address = address; 111 tio_req->cmd = USB_TIO_READ16_SYNC; 112 USB_TIO_REQUEST_SET_MAGIC(tio_req); 113 usb_tio_commit_request(tio_req); 114 115 /* 116 * Wait for the result to show up. 117 */ 118 usb_tio_wait_hrt(); 119 USB_TIO_REQUEST_VERIFY_MAGIC(tio_req); 120 *data = (u16_t)tio_req->data; 121 USB_TIO_REQUEST_CLEAR_MAGIC(tio_req); 122 USB_TIO_UNLOCK(&tio_lock, flag); 123 return USB_TIO_OK; 124} 125 126/* 127 * usb_tio_read_u8() 128 * Synchronously read 16 bits. 129 */ 130u8_t usb_tio_read_u8(u32_t address, u8_t *data) 131{ 132 volatile struct usb_tio_request *tio_req = &usb_node->request; 133 unsigned long flag; 134 135 /* 136 * Wait for any previous request to complete and then make this request. 137 */ 138 USB_TIO_LOCK(&tio_lock, flag); 139 usb_tio_wait_hrt(); 140 141 /* 142 * Fill in the request. 143 */ 144 tio_req->address = address; 145 tio_req->cmd = USB_TIO_READ8_SYNC; 146 USB_TIO_REQUEST_SET_MAGIC(tio_req); 147 148 /* 149 * commit the request 150 */ 151 usb_tio_commit_request(tio_req); 152 153 /* 154 * Wait for the result to show up. 155 */ 156 usb_tio_wait_hrt(); 157 USB_TIO_REQUEST_VERIFY_MAGIC(tio_req); 158 *data = (u8_t)tio_req->data; 159 USB_TIO_REQUEST_CLEAR_MAGIC(tio_req); 160 USB_TIO_UNLOCK(&tio_lock, flag); 161 return USB_TIO_OK; 162} 163 164/* 165 * usb_tio_write_u16() 166 * Asynchronously write 16 bits. 167 */ 168u8_t usb_tio_write_u16(u32_t address, u16_t data) 169{ 170 volatile struct usb_tio_request *tio_req = &usb_node->request; 171 unsigned long flag; 172 173 /* 174 * Wait for any previous write or pending read to complete. 175 */ 176 USB_TIO_LOCK(&tio_lock, flag); 177 usb_tio_wait_hrt(); 178 179 tio_req->address = address; 180 tio_req->data = data; 181 tio_req->cmd = USB_TIO_WRITE16_ASYNC; 182 USB_TIO_REQUEST_SET_MAGIC(tio_req); 183 184 /* 185 * commit the request 186 */ 187 usb_tio_commit_request(tio_req); 188 USB_TIO_UNLOCK(&tio_lock, flag); 189 return USB_TIO_OK; 190} 191 192/* 193 * usb_tio_write_u8() 194 * Asynchronously write 8 bits. 195 */ 196u8_t usb_tio_write_u8(u32_t address, u8_t data) 197{ 198 volatile struct usb_tio_request *tio_req = &usb_node->request; 199 unsigned long flag; 200 201 /* 202 * Wait for any previous write or pending read to complete. 203 */ 204 USB_TIO_LOCK(&tio_lock, flag); 205 usb_tio_wait_hrt(); 206 207 tio_req->address = address; 208 tio_req->data = data; 209 tio_req->cmd = USB_TIO_WRITE8_ASYNC; 210 USB_TIO_REQUEST_SET_MAGIC(tio_req); 211 212 /* 213 * commit the request 214 */ 215 usb_tio_commit_request(tio_req); 216 USB_TIO_UNLOCK(&tio_lock, flag); 217 return USB_TIO_OK; 218} 219 220/* 221 * usb_tio_read_fifo() 222 * Synchronously read FIFO. 223 */ 224u8_t usb_tio_read_fifo(u32_t address, u32_t buffer, u32_t bytes) 225{ 226 volatile struct usb_tio_request *tio_req = &usb_node->request; 227 unsigned long flag; 228 229 /* 230 * Wait for any previous request to complete and then make this request. 231 */ 232 USB_TIO_LOCK(&tio_lock, flag); 233 usb_tio_wait_hrt(); 234 235 /* 236 * Fill in the request. 237 */ 238 tio_req->address = address; 239 tio_req->cmd = USB_TIO_READ_FIFO_SYNC; 240 tio_req->buffer = buffer; 241 tio_req->transfer_length = bytes; 242 USB_TIO_REQUEST_SET_MAGIC(tio_req); 243 244 /* 245 * commit the request 246 */ 247 usb_tio_commit_request(tio_req); 248 249 /* 250 * Wait for the result to show up. 251 */ 252 usb_tio_wait_hrt(); 253 USB_TIO_REQUEST_VERIFY_MAGIC(tio_req); 254 USB_TIO_REQUEST_CLEAR_MAGIC(tio_req); 255 USB_TIO_UNLOCK(&tio_lock, flag); 256 return USB_TIO_OK; 257} 258 259/* 260 * usb_tio_write_fifo() 261 * Synchronously write 32 bits. 262 */ 263u8_t usb_tio_write_fifo(u32_t address, u32_t buffer, u32_t bytes) 264{ 265 volatile struct usb_tio_request *tio_req = &usb_node->request; 266 unsigned long flag; 267 268 USB_TIO_LOCK(&tio_lock, flag); 269 usb_tio_wait_hrt(); 270 271 tio_req->address = address; 272 tio_req->buffer = buffer; 273 tio_req->cmd = USB_TIO_WRITE_FIFO_SYNC; 274 tio_req->transfer_length = bytes; 275 USB_TIO_REQUEST_SET_MAGIC(tio_req); 276 /* 277 * commit the request 278 */ 279 usb_tio_commit_request(tio_req); 280 281 /* 282 * Wait for the result to show up. 283 */ 284 usb_tio_wait_hrt(); 285 USB_TIO_REQUEST_VERIFY_MAGIC(tio_req); 286 USB_TIO_REQUEST_CLEAR_MAGIC(tio_req); 287 USB_TIO_UNLOCK(&tio_lock, flag); 288 return USB_TIO_OK; 289} 290 291/* 292 * usb_tio_write_fifo_async() 293 * Asynchronously write 32 bits. 294 */ 295u8_t usb_tio_write_fifo_async(u32_t address, u32_t buffer, u32_t bytes) 296{ 297 volatile struct usb_tio_request *tio_req = &usb_node->request; 298 unsigned long flag; 299 300 USB_TIO_LOCK(&tio_lock, flag); 301 usb_tio_wait_hrt(); 302 303 tio_req->address = address; 304 305 /* 306 * Is it necessary to make a local copy of the buffer? Any chance the URB is aborted before TIO finished the FIFO write? 307 */ 308 tio_req->buffer = buffer; 309 tio_req->cmd = USB_TIO_WRITE_FIFO_SYNC; 310 tio_req->transfer_length = bytes; 311 USB_TIO_REQUEST_SET_MAGIC(tio_req); 312 /* 313 * commit the request 314 */ 315 usb_tio_commit_request(tio_req); 316 USB_TIO_UNLOCK(&tio_lock, flag); 317 return USB_TIO_OK; 318} 319 320/* 321 * usb_tio_read_int_status() 322 * read and clear the interrupt status registers 323 */ 324void usb_tio_read_int_status(u8_t *int_usb, u16_t *int_tx, u16_t *int_rx) 325{ 326 327 /* 328 * clear the interrupt must be syncronized with the TIO thread to prevent the racing condiiton 329 * that TIO thread try to set it at same time 330 */ 331 asm volatile ( 332 "1: bset (%0), (%0), #0 \n\t" \ 333 " jmpne.f 1b \n\t" \ 334 : 335 : "a" (&usb_node->usb_vp_control) 336 : "memory", "cc" 337 ); 338 339 *int_usb = usb_node->usb_vp_hw_int_usb; 340 *int_tx = cpu_to_le16(usb_node->usb_vp_hw_int_tx); 341 *int_rx = cpu_to_le16(usb_node->usb_vp_hw_int_rx); 342 343 //printk(KERN_INFO "int read %x, %x, %x\n", *int_usb, *int_tx, *int_rx); 344 345 /* 346 * The interrupt status register is read-clean, so clear it now 347 */ 348 usb_node->usb_vp_hw_int_usb = 0; 349 usb_node->usb_vp_hw_int_tx = 0; 350 usb_node->usb_vp_hw_int_rx = 0; 351 352 /* 353 * release the lock bit 354 */ 355 usb_node->usb_vp_control &= 0xfffe; 356} 357