linux/drivers/usb/c67x00/c67x00-ll-hpi.c
<<
>>
Prefs
   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}
 478