1 /* 2 * c67x00-ll-hpi.c: Cypress C67X00 USB Low level interface using HPI 3 * 4 * Copyright (C) 2006-2008 Barco N.V. 5 * Derived from the Cypress cy7c67200/300 ezusb linux driver and 6 * based on multiple host controller drivers inside the linux kernel. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21 * MA 02110-1301 USA. 22 */ 23 24 #include <asm/byteorder.h> 25 #include <linux/io.h> 26 #include <linux/jiffies.h> 27 #include <linux/usb/c67x00.h> 28 #include "c67x00.h" 29 30 #define COMM_REGS 14 31 32 struct c67x00_lcp_int_data { 33 u16 regs[COMM_REGS]; 34 }; 35 36 /* -------------------------------------------------------------------------- */ 37 /* Interface definitions */ 38 39 #define COMM_ACK 0x0FED 40 #define COMM_NAK 0xDEAD 41 42 #define COMM_RESET 0xFA50 43 #define COMM_EXEC_INT 0xCE01 44 #define COMM_INT_NUM 0x01C2 45 46 /* Registers 0 to COMM_REGS-1 */ 47 #define COMM_R(x) (0x01C4 + 2 * (x)) 48 49 #define HUSB_SIE_pCurrentTDPtr(x) ((x) ? 0x01B2 : 0x01B0) 50 #define HUSB_SIE_pTDListDone_Sem(x) ((x) ? 0x01B8 : 0x01B6) 51 #define HUSB_pEOT 0x01B4 52 53 /* Software interrupts */ 54 /* 114, 115: */ 55 #define HUSB_SIE_INIT_INT(x) ((x) ? 0x0073 : 0x0072) 56 #define HUSB_RESET_INT 0x0074 57 58 #define SUSB_INIT_INT 0x0071 59 #define SUSB_INIT_INT_LOC (SUSB_INIT_INT * 2) 60 61 /* ----------------------------------------------------------------------- 62 * HPI implementation 63 * 64 * The c67x00 chip also support control via SPI or HSS serial 65 * interfaces. However, this driver assumes that register access can 66 * be performed from IRQ context. While this is a safe assuption with 67 * the HPI interface, it is not true for the serial interfaces. 68 */ 69 70 /* HPI registers */ 71 #define HPI_DATA 0 72 #define HPI_MAILBOX 1 73 #define HPI_ADDR 2 74 #define HPI_STATUS 3 75 76 static inline u16 hpi_read_reg(struct c67x00_device *dev, int reg) 77 { 78 return __raw_readw(dev->hpi.base + reg * dev->hpi.regstep); 79 } 80 81 static inline void hpi_write_reg(struct c67x00_device *dev, int reg, u16 value) 82 { 83 __raw_writew(value, dev->hpi.base + reg * dev->hpi.regstep); 84 } 85 86 static inline u16 hpi_read_word_nolock(struct c67x00_device *dev, u16 reg) 87 { 88 hpi_write_reg(dev, HPI_ADDR, reg); 89 return hpi_read_reg(dev, HPI_DATA); 90 } 91 92 static u16 hpi_read_word(struct c67x00_device *dev, u16 reg) 93 { 94 u16 value; 95 unsigned long flags; 96 97 spin_lock_irqsave(&dev->hpi.lock, flags); 98 value = hpi_read_word_nolock(dev, reg); 99 spin_unlock_irqrestore(&dev->hpi.lock, flags); 100 101 return value; 102 } 103 104 static void hpi_write_word_nolock(struct c67x00_device *dev, u16 reg, u16 value) 105 { 106 hpi_write_reg(dev, HPI_ADDR, reg); 107 hpi_write_reg(dev, HPI_DATA, value); 108 } 109 110 static void hpi_write_word(struct c67x00_device *dev, u16 reg, u16 value) 111 { 112 unsigned long flags; 113 114 spin_lock_irqsave(&dev->hpi.lock, flags); 115 hpi_write_word_nolock(dev, reg, value); 116 spin_unlock_irqrestore(&dev->hpi.lock, flags); 117 } 118 119 /* 120 * Only data is little endian, addr has cpu endianess 121 */ 122 static void hpi_write_words_le16(struct c67x00_device *dev, u16 addr, 123 u16 *data, u16 count) 124 { 125 unsigned long flags; 126 int i; 127 128 spin_lock_irqsave(&dev->hpi.lock, flags); 129 130 hpi_write_reg(dev, HPI_ADDR, addr); 131 for (i = 0; i < count; i++) 132 hpi_write_reg(dev, HPI_DATA, cpu_to_le16(*data++)); 133 134 spin_unlock_irqrestore(&dev->hpi.lock, flags); 135 } 136 137 /* 138 * Only data is little endian, addr has cpu endianess 139 */ 140 static void hpi_read_words_le16(struct c67x00_device *dev, u16 addr, 141 u16 *data, u16 count) 142 { 143 unsigned long flags; 144 int i; 145 146 spin_lock_irqsave(&dev->hpi.lock, flags); 147 hpi_write_reg(dev, HPI_ADDR, addr); 148 for (i = 0; i < count; i++) 149 *data++ = le16_to_cpu(hpi_read_reg(dev, HPI_DATA)); 150 151 spin_unlock_irqrestore(&dev->hpi.lock, flags); 152 } 153 154 static void hpi_set_bits(struct c67x00_device *dev, u16 reg, u16 mask) 155 { 156 u16 value; 157 unsigned long flags; 158 159 spin_lock_irqsave(&dev->hpi.lock, flags); 160 value = hpi_read_word_nolock(dev, reg); 161 hpi_write_word_nolock(dev, reg, value | mask); 162 spin_unlock_irqrestore(&dev->hpi.lock, flags); 163 } 164 165 static void hpi_clear_bits(struct c67x00_device *dev, u16 reg, u16 mask) 166 { 167 u16 value; 168 unsigned long flags; 169 170 spin_lock_irqsave(&dev->hpi.lock, flags); 171 value = hpi_read_word_nolock(dev, reg); 172 hpi_write_word_nolock(dev, reg, value & ~mask); 173 spin_unlock_irqrestore(&dev->hpi.lock, flags); 174 } 175 176 static u16 hpi_recv_mbox(struct c67x00_device *dev) 177 { 178 u16 value; 179 unsigned long flags; 180 181 spin_lock_irqsave(&dev->hpi.lock, flags); 182 value = hpi_read_reg(dev, HPI_MAILBOX); 183 spin_unlock_irqrestore(&dev->hpi.lock, flags); 184 185 return value; 186 } 187 188 static u16 hpi_send_mbox(struct c67x00_device *dev, u16 value) 189 { 190 unsigned long flags; 191 192 spin_lock_irqsave(&dev->hpi.lock, flags); 193 hpi_write_reg(dev, HPI_MAILBOX, value); 194 spin_unlock_irqrestore(&dev->hpi.lock, flags); 195 196 return value; 197 } 198 199 u16 c67x00_ll_hpi_status(struct c67x00_device *dev) 200 { 201 u16 value; 202 unsigned long flags; 203 204 spin_lock_irqsave(&dev->hpi.lock, flags); 205 value = hpi_read_reg(dev, HPI_STATUS); 206 spin_unlock_irqrestore(&dev->hpi.lock, flags); 207 208 return value; 209 } 210 211 void c67x00_ll_hpi_reg_init(struct c67x00_device *dev) 212 { 213 int i; 214 215 hpi_recv_mbox(dev); 216 c67x00_ll_hpi_status(dev); 217 hpi_write_word(dev, HPI_IRQ_ROUTING_REG, 0); 218 219 for (i = 0; i < C67X00_SIES; i++) { 220 hpi_write_word(dev, SIEMSG_REG(i), 0); 221 hpi_read_word(dev, SIEMSG_REG(i)); 222 } 223 } 224 225 void c67x00_ll_hpi_enable_sofeop(struct c67x00_sie *sie) 226 { 227 hpi_set_bits(sie->dev, HPI_IRQ_ROUTING_REG, 228 SOFEOP_TO_HPI_EN(sie->sie_num)); 229 } 230 231 void c67x00_ll_hpi_disable_sofeop(struct c67x00_sie *sie) 232 { 233 hpi_clear_bits(sie->dev, HPI_IRQ_ROUTING_REG, 234 SOFEOP_TO_HPI_EN(sie->sie_num)); 235 } 236 237 /* -------------------------------------------------------------------------- */ 238 /* Transactions */ 239 240 static inline u16 ll_recv_msg(struct c67x00_device *dev) 241 { 242 u16 res; 243 244 res = wait_for_completion_timeout(&dev->hpi.lcp.msg_received, 5 * HZ); 245 WARN_ON(!res); 246 247 return (res == 0) ? -EIO : 0; 248 } 249 250 /* -------------------------------------------------------------------------- */ 251 /* General functions */ 252 253 u16 c67x00_ll_fetch_siemsg(struct c67x00_device *dev, int sie_num) 254 { 255 u16 val; 256 257 val = hpi_read_word(dev, SIEMSG_REG(sie_num)); 258 /* clear register to allow next message */ 259 hpi_write_word(dev, SIEMSG_REG(sie_num), 0); 260 261 return val; 262 } 263 264 u16 c67x00_ll_get_usb_ctl(struct c67x00_sie *sie) 265 { 266 return hpi_read_word(sie->dev, USB_CTL_REG(sie->sie_num)); 267 } 268 269 /** 270 * c67x00_ll_usb_clear_status - clear the USB status bits 271 */ 272 void c67x00_ll_usb_clear_status(struct c67x00_sie *sie, u16 bits) 273 { 274 hpi_write_word(sie->dev, USB_STAT_REG(sie->sie_num), bits); 275 } 276 277 u16 c67x00_ll_usb_get_status(struct c67x00_sie *sie) 278 { 279 return hpi_read_word(sie->dev, USB_STAT_REG(sie->sie_num)); 280 } 281 282 /* -------------------------------------------------------------------------- */ 283 284 static int c67x00_comm_exec_int(struct c67x00_device *dev, u16 nr, 285 struct c67x00_lcp_int_data *data) 286 { 287 int i, rc; 288 289 mutex_lock(&dev->hpi.lcp.mutex); 290 hpi_write_word(dev, COMM_INT_NUM, nr); 291 for (i = 0; i < COMM_REGS; i++) 292 hpi_write_word(dev, COMM_R(i), data->regs[i]); 293 hpi_send_mbox(dev, COMM_EXEC_INT); 294 rc = ll_recv_msg(dev); 295 mutex_unlock(&dev->hpi.lcp.mutex); 296 297 return rc; 298 } 299 300 /* -------------------------------------------------------------------------- */ 301 /* Host specific functions */ 302 303 void c67x00_ll_set_husb_eot(struct c67x00_device *dev, u16 value) 304 { 305 mutex_lock(&dev->hpi.lcp.mutex); 306 hpi_write_word(dev, HUSB_pEOT, value); 307 mutex_unlock(&dev->hpi.lcp.mutex); 308 } 309 310 static inline void c67x00_ll_husb_sie_init(struct c67x00_sie *sie) 311 { 312 struct c67x00_device *dev = sie->dev; 313 struct c67x00_lcp_int_data data; 314 int rc; 315 316 rc = c67x00_comm_exec_int(dev, HUSB_SIE_INIT_INT(sie->sie_num), &data); 317 BUG_ON(rc); /* No return path for error code; crash spectacularly */ 318 } 319 320 void c67x00_ll_husb_reset(struct c67x00_sie *sie, int port) 321 { 322 struct c67x00_device *dev = sie->dev; 323 struct c67x00_lcp_int_data data; 324 int rc; 325 326 data.regs[0] = 50; /* Reset USB port for 50ms */ 327 data.regs[1] = port | (sie->sie_num << 1); 328 rc = c67x00_comm_exec_int(dev, HUSB_RESET_INT, &data); 329 BUG_ON(rc); /* No return path for error code; crash spectacularly */ 330 } 331 332 void c67x00_ll_husb_set_current_td(struct c67x00_sie *sie, u16 addr) 333 { 334 hpi_write_word(sie->dev, HUSB_SIE_pCurrentTDPtr(sie->sie_num), addr); 335 } 336 337 u16 c67x00_ll_husb_get_current_td(struct c67x00_sie *sie) 338 { 339 return hpi_read_word(sie->dev, HUSB_SIE_pCurrentTDPtr(sie->sie_num)); 340 } 341 342 u16 c67x00_ll_husb_get_frame(struct c67x00_sie *sie) 343 { 344 return hpi_read_word(sie->dev, HOST_FRAME_REG(sie->sie_num)); 345 } 346 347 void c67x00_ll_husb_init_host_port(struct c67x00_sie *sie) 348 { 349 /* Set port into host mode */ 350 hpi_set_bits(sie->dev, USB_CTL_REG(sie->sie_num), HOST_MODE); 351 c67x00_ll_husb_sie_init(sie); 352 /* Clear interrupts */ 353 c67x00_ll_usb_clear_status(sie, HOST_STAT_MASK); 354 /* Check */ 355 if (!(hpi_read_word(sie->dev, USB_CTL_REG(sie->sie_num)) & HOST_MODE)) 356 dev_warn(sie_dev(sie), 357 "SIE %d not set to host mode\n", sie->sie_num); 358 } 359 360 void c67x00_ll_husb_reset_port(struct c67x00_sie *sie, int port) 361 { 362 /* Clear connect change */ 363 c67x00_ll_usb_clear_status(sie, PORT_CONNECT_CHANGE(port)); 364 365 /* Enable interrupts */ 366 hpi_set_bits(sie->dev, HPI_IRQ_ROUTING_REG, 367 SOFEOP_TO_CPU_EN(sie->sie_num)); 368 hpi_set_bits(sie->dev, HOST_IRQ_EN_REG(sie->sie_num), 369 SOF_EOP_IRQ_EN | DONE_IRQ_EN); 370 371 /* Enable pull down transistors */ 372 hpi_set_bits(sie->dev, USB_CTL_REG(sie->sie_num), PORT_RES_EN(port)); 373 } 374 375 /* -------------------------------------------------------------------------- */ 376 377 void c67x00_ll_irq(struct c67x00_device *dev, u16 int_status) 378 { 379 if ((int_status & MBX_OUT_FLG) == 0) 380 return; 381 382 dev->hpi.lcp.last_msg = hpi_recv_mbox(dev); 383 complete(&dev->hpi.lcp.msg_received); 384 } 385 386 /* -------------------------------------------------------------------------- */ 387 388 int c67x00_ll_reset(struct c67x00_device *dev) 389 { 390 int rc; 391 392 mutex_lock(&dev->hpi.lcp.mutex); 393 hpi_send_mbox(dev, COMM_RESET); 394 rc = ll_recv_msg(dev); 395 mutex_unlock(&dev->hpi.lcp.mutex); 396 397 return rc; 398 } 399 400 /* -------------------------------------------------------------------------- */ 401 402 /** 403 * c67x00_ll_write_mem_le16 - write into c67x00 memory 404 * Only data is little endian, addr has cpu endianess. 405 */ 406 void c67x00_ll_write_mem_le16(struct c67x00_device *dev, u16 addr, 407 void *data, int len) 408 { 409 u8 *buf = data; 410 411 /* Sanity check */ 412 if (addr + len > 0xffff) { 413 dev_err(&dev->pdev->dev, 414 "Trying to write beyond writable region!\n"); 415 return; 416 } 417 418 if (addr & 0x01) { 419 /* unaligned access */ 420 u16 tmp; 421 tmp = hpi_read_word(dev, addr - 1); 422 tmp = (tmp & 0x00ff) | (*buf++ << 8); 423 hpi_write_word(dev, addr - 1, tmp); 424 addr++; 425 len--; 426 } 427 428 hpi_write_words_le16(dev, addr, (u16 *)buf, len / 2); 429 buf += len & ~0x01; 430 addr += len & ~0x01; 431 len &= 0x01; 432 433 if (len) { 434 u16 tmp; 435 tmp = hpi_read_word(dev, addr); 436 tmp = (tmp & 0xff00) | *buf; 437 hpi_write_word(dev, addr, tmp); 438 } 439 } 440 441 /** 442 * c67x00_ll_read_mem_le16 - read from c67x00 memory 443 * Only data is little endian, addr has cpu endianess. 444 */ 445 void c67x00_ll_read_mem_le16(struct c67x00_device *dev, u16 addr, 446 void *data, int len) 447 { 448 u8 *buf = data; 449 450 if (addr & 0x01) { 451 /* unaligned access */ 452 u16 tmp; 453 tmp = hpi_read_word(dev, addr - 1); 454 *buf++ = (tmp >> 8) & 0x00ff; 455 addr++; 456 len--; 457 } 458 459 hpi_read_words_le16(dev, addr, (u16 *)buf, len / 2); 460 buf += len & ~0x01; 461 addr += len & ~0x01; 462 len &= 0x01; 463 464 if (len) { 465 u16 tmp; 466 tmp = hpi_read_word(dev, addr); 467 *buf = tmp & 0x00ff; 468 } 469 } 470 471 /* -------------------------------------------------------------------------- */ 472 473 void c67x00_ll_init(struct c67x00_device *dev) 474 { 475 mutex_init(&dev->hpi.lcp.mutex); 476 init_completion(&dev->hpi.lcp.msg_received); 477 } 478 479 void c67x00_ll_release(struct c67x00_device *dev) 480 { 481 } 482