c67x00-ll-hpi.c (11801B)
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 19struct 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 70static 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 76static 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 82static 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 88static 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 100static 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 106static 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 */ 118static 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 */ 136static 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 150static 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 161static 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 172static 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 184static 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 195u16 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 207void 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 221void 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 227void 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 236static 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 249u16 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 260u16 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 */ 268void 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 273u16 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 280static 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 299void 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 306static 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 316void 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 328void 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 333u16 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 338u16 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 343void 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 356void 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 373void 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 384int 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 */ 402void 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 */ 441void 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 469void 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 475void c67x00_ll_release(struct c67x00_device *dev) 476{ 477}