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