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