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