diff options
| -rw-r--r-- | drivers/usb/c67x00/c67x00-ll-hpi.c | 405 | ||||
| -rw-r--r-- | drivers/usb/c67x00/c67x00.h | 285 | 
2 files changed, 690 insertions, 0 deletions
diff --git a/drivers/usb/c67x00/c67x00-ll-hpi.c b/drivers/usb/c67x00/c67x00-ll-hpi.c new file mode 100644 index 00000000000..e921991bc36 --- /dev/null +++ b/drivers/usb/c67x00/c67x00-ll-hpi.c @@ -0,0 +1,405 @@ +/* + * c67x00-ll-hpi.c: Cypress C67X00 USB Low level interface using HPI + * + * Copyright (C) 2006-2008 Barco N.V. + *    Derived from the Cypress cy7c67200/300 ezusb linux driver and + *    based on multiple host controller drivers inside the linux kernel. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA  02110-1301  USA. + */ + +#include <asm/byteorder.h> +#include <linux/io.h> +#include <linux/usb/c67x00.h> +#include "c67x00.h" + +#define COMM_REGS 14 + +struct c67x00_lcp_int_data { +	u16 regs[COMM_REGS]; +}; + +/* -------------------------------------------------------------------------- */ +/* Interface definitions */ + +#define COMM_ACK			0x0FED +#define COMM_NAK			0xDEAD + +#define COMM_RESET			0xFA50 +#define COMM_EXEC_INT			0xCE01 +#define COMM_INT_NUM			0x01C2 + +/* Registers 0 to COMM_REGS-1 */ +#define COMM_R(x)			(0x01C4 + 2 * (x)) + +#define HUSB_SIE_pCurrentTDPtr(x)	((x) ? 0x01B2 : 0x01B0) +#define HUSB_SIE_pTDListDone_Sem(x)	((x) ? 0x01B8 : 0x01B6) +#define HUSB_pEOT			0x01B4 + +/* Software interrupts */ +/* 114, 115: */ +#define HUSB_SIE_INIT_INT(x)		((x) ? 0x0073 : 0x0072) +#define HUSB_RESET_INT			0x0074 + +#define SUSB_INIT_INT			0x0071 +#define SUSB_INIT_INT_LOC		(SUSB_INIT_INT * 2) + +/* ----------------------------------------------------------------------- + * HPI implementation + * + * The c67x00 chip also support control via SPI or HSS serial + * interfaces.  However, this driver assumes that register access can + * be performed from IRQ context.  While this is a safe assuption with + * the HPI interface, it is not true for the serial interfaces. + */ + +/* HPI registers */ +#define HPI_DATA	0 +#define HPI_MAILBOX	1 +#define HPI_ADDR	2 +#define HPI_STATUS	3 + +static inline u16 hpi_read_reg(struct c67x00_device *dev, int reg) +{ +	return __raw_readw(dev->hpi.base + reg * dev->hpi.regstep); +} + +static inline void hpi_write_reg(struct c67x00_device *dev, int reg, u16 value) +{ +	__raw_writew(value, dev->hpi.base + reg * dev->hpi.regstep); +} + +static inline u16 hpi_read_word_nolock(struct c67x00_device *dev, u16 reg) +{ +	hpi_write_reg(dev, HPI_ADDR, reg); +	return hpi_read_reg(dev, HPI_DATA); +} + +static u16 hpi_read_word(struct c67x00_device *dev, u16 reg) +{ +	u16 value; +	unsigned long flags; + +	spin_lock_irqsave(&dev->hpi.lock, flags); +	value = hpi_read_word_nolock(dev, reg); +	spin_unlock_irqrestore(&dev->hpi.lock, flags); + +	return value; +} + +static void hpi_write_word_nolock(struct c67x00_device *dev, u16 reg, u16 value) +{ +	hpi_write_reg(dev, HPI_ADDR, reg); +	hpi_write_reg(dev, HPI_DATA, value); +} + +static void hpi_write_word(struct c67x00_device *dev, u16 reg, u16 value) +{ +	unsigned long flags; + +	spin_lock_irqsave(&dev->hpi.lock, flags); +	hpi_write_word_nolock(dev, reg, value); +	spin_unlock_irqrestore(&dev->hpi.lock, flags); +} + +/* + * Only data is little endian, addr has cpu endianess + */ +static void hpi_write_words_le16(struct c67x00_device *dev, u16 addr, +				 u16 *data, u16 count) +{ +	unsigned long flags; +	int i; + +	spin_lock_irqsave(&dev->hpi.lock, flags); + +	hpi_write_reg(dev, HPI_ADDR, addr); +	for (i = 0; i < count; i++) +		hpi_write_reg(dev, HPI_DATA, cpu_to_le16(*data++)); + +	spin_unlock_irqrestore(&dev->hpi.lock, flags); +} + +/* + * Only data is little endian, addr has cpu endianess + */ +static void hpi_read_words_le16(struct c67x00_device *dev, u16 addr, +				u16 *data, u16 count) +{ +	unsigned long flags; +	int i; + +	spin_lock_irqsave(&dev->hpi.lock, flags); +	hpi_write_reg(dev, HPI_ADDR, addr); +	for (i = 0; i < count; i++) +		*data++ = le16_to_cpu(hpi_read_reg(dev, HPI_DATA)); + +	spin_unlock_irqrestore(&dev->hpi.lock, flags); +} + +static void hpi_set_bits(struct c67x00_device *dev, u16 reg, u16 mask) +{ +	u16 value; +	unsigned long flags; + +	spin_lock_irqsave(&dev->hpi.lock, flags); +	value = hpi_read_word_nolock(dev, reg); +	hpi_write_word_nolock(dev, reg, value | mask); +	spin_unlock_irqrestore(&dev->hpi.lock, flags); +} + +static void hpi_clear_bits(struct c67x00_device *dev, u16 reg, u16 mask) +{ +	u16 value; +	unsigned long flags; + +	spin_lock_irqsave(&dev->hpi.lock, flags); +	value = hpi_read_word_nolock(dev, reg); +	hpi_write_word_nolock(dev, reg, value & ~mask); +	spin_unlock_irqrestore(&dev->hpi.lock, flags); +} + +static u16 hpi_recv_mbox(struct c67x00_device *dev) +{ +	u16 value; +	unsigned long flags; + +	spin_lock_irqsave(&dev->hpi.lock, flags); +	value = hpi_read_reg(dev, HPI_MAILBOX); +	spin_unlock_irqrestore(&dev->hpi.lock, flags); + +	return value; +} + +static u16 hpi_send_mbox(struct c67x00_device *dev, u16 value) +{ +	unsigned long flags; + +	spin_lock_irqsave(&dev->hpi.lock, flags); +	hpi_write_reg(dev, HPI_MAILBOX, value); +	spin_unlock_irqrestore(&dev->hpi.lock, flags); + +	return value; +} + +u16 c67x00_ll_hpi_status(struct c67x00_device *dev) +{ +	u16 value; +	unsigned long flags; + +	spin_lock_irqsave(&dev->hpi.lock, flags); +	value = hpi_read_reg(dev, HPI_STATUS); +	spin_unlock_irqrestore(&dev->hpi.lock, flags); + +	return value; +} + +void c67x00_ll_hpi_reg_init(struct c67x00_device *dev) +{ +	int i; + +	hpi_recv_mbox(dev); +	c67x00_ll_hpi_status(dev); +	hpi_write_word(dev, HPI_IRQ_ROUTING_REG, 0); + +	for (i = 0; i < C67X00_SIES; i++) { +		hpi_write_word(dev, SIEMSG_REG(i), 0); +		hpi_read_word(dev, SIEMSG_REG(i)); +	} +} + +void c67x00_ll_hpi_enable_sofeop(struct c67x00_sie *sie) +{ +	hpi_set_bits(sie->dev, HPI_IRQ_ROUTING_REG, +		     SOFEOP_TO_HPI_EN(sie->sie_num)); +} + +void c67x00_ll_hpi_disable_sofeop(struct c67x00_sie *sie) +{ +	hpi_clear_bits(sie->dev, HPI_IRQ_ROUTING_REG, +		       SOFEOP_TO_HPI_EN(sie->sie_num)); +} + +/* -------------------------------------------------------------------------- */ +/* Transactions */ + +static inline u16 ll_recv_msg(struct c67x00_device *dev) +{ +	u16 res; + +	res = wait_for_completion_timeout(&dev->hpi.lcp.msg_received, 5 * HZ); +	WARN_ON(!res); + +	return (res == 0) ? -EIO : 0; +} + +/* -------------------------------------------------------------------------- */ +/* General functions */ + +u16 c67x00_ll_fetch_siemsg(struct c67x00_device *dev, int sie_num) +{ +	u16 val; + +	val = hpi_read_word(dev, SIEMSG_REG(sie_num)); +	/* clear register to allow next message */ +	hpi_write_word(dev, SIEMSG_REG(sie_num), 0); + +	return val; +} + +u16 c67x00_ll_get_usb_ctl(struct c67x00_sie *sie) +{ +	return hpi_read_word(sie->dev, USB_CTL_REG(sie->sie_num)); +} + +/** + * c67x00_ll_usb_clear_status - clear the USB status bits + */ +void c67x00_ll_usb_clear_status(struct c67x00_sie *sie, u16 bits) +{ +	hpi_write_word(sie->dev, USB_STAT_REG(sie->sie_num), bits); +} + +u16 c67x00_ll_usb_get_status(struct c67x00_sie *sie) +{ +	return hpi_read_word(sie->dev, USB_STAT_REG(sie->sie_num)); +} + +/* -------------------------------------------------------------------------- */ + +static int c67x00_comm_exec_int(struct c67x00_device *dev, u16 nr, +				struct c67x00_lcp_int_data *data) +{ +	int i, rc; + +	mutex_lock(&dev->hpi.lcp.mutex); +	hpi_write_word(dev, COMM_INT_NUM, nr); +	for (i = 0; i < COMM_REGS; i++) +		hpi_write_word(dev, COMM_R(i), data->regs[i]); +	hpi_send_mbox(dev, COMM_EXEC_INT); +	rc = ll_recv_msg(dev); +	mutex_unlock(&dev->hpi.lcp.mutex); + +	return rc; +} + +/* -------------------------------------------------------------------------- */ + +void c67x00_ll_irq(struct c67x00_device *dev, u16 int_status) +{ +	if ((int_status & MBX_OUT_FLG) == 0) +		return; + +	dev->hpi.lcp.last_msg = hpi_recv_mbox(dev); +	complete(&dev->hpi.lcp.msg_received); +} + +/* -------------------------------------------------------------------------- */ + +int c67x00_ll_reset(struct c67x00_device *dev) +{ +	int rc; + +	mutex_lock(&dev->hpi.lcp.mutex); +	hpi_send_mbox(dev, COMM_RESET); +	rc = ll_recv_msg(dev); +	mutex_unlock(&dev->hpi.lcp.mutex); + +	return rc; +} + +/* -------------------------------------------------------------------------- */ + +/** + * c67x00_ll_write_mem_le16 - write into c67x00 memory + * Only data is little endian, addr has cpu endianess. + */ +void c67x00_ll_write_mem_le16(struct c67x00_device *dev, u16 addr, +			      void *data, int len) +{ +	u8 *buf = data; + +	/* Sanity check */ +	if (addr + len > 0xffff) { +		dev_err(&dev->pdev->dev, +			"Trying to write beyond writable region!\n"); +		return; +	} + +	if (addr & 0x01) { +		/* unaligned access */ +		u16 tmp; +		tmp = hpi_read_word(dev, addr - 1); +		tmp = (tmp & 0x00ff) | (*buf++ << 8); +		hpi_write_word(dev, addr - 1, tmp); +		addr++; +		len--; +	} + +	hpi_write_words_le16(dev, addr, (u16 *)buf, len / 2); +	buf += len & ~0x01; +	addr += len & ~0x01; +	len &= 0x01; + +	if (len) { +		u16 tmp; +		tmp = hpi_read_word(dev, addr); +		tmp = (tmp & 0xff00) | *buf; +		hpi_write_word(dev, addr, tmp); +	} +} + +/** + * c67x00_ll_read_mem_le16 - read from c67x00 memory + * Only data is little endian, addr has cpu endianess. + */ +void c67x00_ll_read_mem_le16(struct c67x00_device *dev, u16 addr, +			     void *data, int len) +{ +	u8 *buf = data; + +	if (addr & 0x01) { +		/* unaligned access */ +		u16 tmp; +		tmp = hpi_read_word(dev, addr - 1); +		*buf++ = (tmp >> 8) & 0x00ff; +		addr++; +		len--; +	} + +	hpi_read_words_le16(dev, addr, (u16 *)buf, len / 2); +	buf += len & ~0x01; +	addr += len & ~0x01; +	len &= 0x01; + +	if (len) { +		u16 tmp; +		tmp = hpi_read_word(dev, addr); +		*buf = tmp & 0x00ff; +	} +} + +/* -------------------------------------------------------------------------- */ + +void c67x00_ll_init(struct c67x00_device *dev) +{ +	mutex_init(&dev->hpi.lcp.mutex); +	init_completion(&dev->hpi.lcp.msg_received); +} + +void c67x00_ll_release(struct c67x00_device *dev) +{ +} diff --git a/drivers/usb/c67x00/c67x00.h b/drivers/usb/c67x00/c67x00.h new file mode 100644 index 00000000000..1f1a2eef9a2 --- /dev/null +++ b/drivers/usb/c67x00/c67x00.h @@ -0,0 +1,285 @@ +/* + * c67x00.h: Cypress C67X00 USB register and field definitions + * + * Copyright (C) 2006-2008 Barco N.V. + *    Derived from the Cypress cy7c67200/300 ezusb linux driver and + *    based on multiple host controller drivers inside the linux kernel. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA  02110-1301  USA. + */ + +#ifndef _USB_C67X00_H +#define _USB_C67X00_H + +#include <linux/spinlock.h> +#include <linux/platform_device.h> +#include <linux/completion.h> +#include <linux/mutex.h> + +/* --------------------------------------------------------------------- + * Cypress C67x00 register definitions + */ + +/* Hardware Revision Register */ +#define HW_REV_REG		0xC004 + +/* General USB registers */ +/* ===================== */ + +/* USB Control Register */ +#define USB_CTL_REG(x)		((x) ? 0xC0AA : 0xC08A) + +#define LOW_SPEED_PORT(x)	((x) ? 0x0800 : 0x0400) +#define HOST_MODE		0x0200 +#define PORT_RES_EN(x)		((x) ? 0x0100 : 0x0080) +#define SOF_EOP_EN(x)		((x) ? 0x0002 : 0x0001) + +/* USB status register - Notice it has different content in hcd/udc mode */ +#define USB_STAT_REG(x)		((x) ? 0xC0B0 : 0xC090) + +#define EP0_IRQ_FLG		0x0001 +#define EP1_IRQ_FLG		0x0002 +#define EP2_IRQ_FLG		0x0004 +#define EP3_IRQ_FLG		0x0008 +#define EP4_IRQ_FLG		0x0010 +#define EP5_IRQ_FLG		0x0020 +#define EP6_IRQ_FLG		0x0040 +#define EP7_IRQ_FLG		0x0080 +#define RESET_IRQ_FLG		0x0100 +#define SOF_EOP_IRQ_FLG		0x0200 +#define ID_IRQ_FLG		0x4000 +#define VBUS_IRQ_FLG		0x8000 + +/* USB Host only registers */ +/* ======================= */ + +/* Host n Control Register */ +#define HOST_CTL_REG(x)		((x) ? 0xC0A0 : 0xC080) + +#define PREAMBLE_EN		0x0080	/* Preamble enable */ +#define SEQ_SEL			0x0040	/* Data Toggle Sequence Bit Select */ +#define ISO_EN			0x0010	/* Isochronous enable  */ +#define ARM_EN			0x0001	/* Arm operation */ + +/* Host n Interrupt Enable Register */ +#define HOST_IRQ_EN_REG(x)	((x) ? 0xC0AC : 0xC08C) + +#define SOF_EOP_IRQ_EN		0x0200	/* SOF/EOP Interrupt Enable  */ +#define SOF_EOP_TMOUT_IRQ_EN	0x0800	/* SOF/EOP Timeout Interrupt Enable  */ +#define ID_IRQ_EN		0x4000	/* ID interrupt enable */ +#define VBUS_IRQ_EN		0x8000	/* VBUS interrupt enable */ +#define DONE_IRQ_EN		0x0001	/* Done Interrupt Enable  */ + +/* USB status register */ +#define HOST_STAT_MASK		0x02FD +#define PORT_CONNECT_CHANGE(x)	((x) ? 0x0020 : 0x0010) +#define PORT_SE0_STATUS(x)	((x) ? 0x0008 : 0x0004) + +/* Host Frame Register */ +#define HOST_FRAME_REG(x)	((x) ? 0xC0B6 : 0xC096) + +#define HOST_FRAME_MASK		0x07FF + +/* USB Peripheral only registers */ +/* ============================= */ + +/* Device n Port Sel reg */ +#define DEVICE_N_PORT_SEL(x)	((x) ? 0xC0A4 : 0xC084) + +/* Device n Interrupt Enable Register */ +#define DEVICE_N_IRQ_EN_REG(x)	((x) ? 0xC0AC : 0xC08C) + +#define DEVICE_N_ENDPOINT_N_CTL_REG(dev, ep)	((dev)  		\ +						 ? (0x0280 + (ep << 4)) \ +						 : (0x0200 + (ep << 4))) +#define DEVICE_N_ENDPOINT_N_STAT_REG(dev, ep)	((dev)			\ +						 ? (0x0286 + (ep << 4)) \ +						 : (0x0206 + (ep << 4))) + +#define DEVICE_N_ADDRESS(dev)	((dev) ? (0xC0AE) : (0xC08E)) + +/* HPI registers */ +/* ============= */ + +/* HPI Status register */ +#define SOFEOP_FLG(x)		(1 << ((x) ? 12 : 10)) +#define SIEMSG_FLG(x)		(1 << (4 + (x))) +#define RESET_FLG(x)		((x) ? 0x0200 : 0x0002) +#define DONE_FLG(x)		(1 << (2 + (x))) +#define RESUME_FLG(x)		(1 << (6 + (x))) +#define MBX_OUT_FLG		0x0001	/* Message out available */ +#define MBX_IN_FLG		0x0100 +#define ID_FLG			0x4000 +#define VBUS_FLG		0x8000 + +/* Interrupt routing register */ +#define HPI_IRQ_ROUTING_REG	0x0142 + +#define HPI_SWAP_ENABLE(x)	((x) ? 0x0100 : 0x0001) +#define RESET_TO_HPI_ENABLE(x)	((x) ? 0x0200 : 0x0002) +#define DONE_TO_HPI_ENABLE(x)	((x) ? 0x0008 : 0x0004) +#define RESUME_TO_HPI_ENABLE(x)	((x) ? 0x0080 : 0x0040) +#define SOFEOP_TO_HPI_EN(x)	((x) ? 0x2000 : 0x0800) +#define SOFEOP_TO_CPU_EN(x)	((x) ? 0x1000 : 0x0400) +#define ID_TO_HPI_ENABLE	0x4000 +#define VBUS_TO_HPI_ENABLE	0x8000 + +/* SIE msg registers */ +#define SIEMSG_REG(x)		((x) ? 0x0148 : 0x0144) + +#define HUSB_TDListDone		0x1000 + +#define SUSB_EP0_MSG		0x0001 +#define SUSB_EP1_MSG		0x0002 +#define SUSB_EP2_MSG		0x0004 +#define SUSB_EP3_MSG		0x0008 +#define SUSB_EP4_MSG		0x0010 +#define SUSB_EP5_MSG		0x0020 +#define SUSB_EP6_MSG		0x0040 +#define SUSB_EP7_MSG		0x0080 +#define SUSB_RST_MSG		0x0100 +#define SUSB_SOF_MSG		0x0200 +#define SUSB_CFG_MSG		0x0400 +#define SUSB_SUS_MSG		0x0800 +#define SUSB_ID_MSG	       	0x4000 +#define SUSB_VBUS_MSG		0x8000 + +/* BIOS interrupt routines */ + +#define SUSBx_RECEIVE_INT(x)	((x) ? 97 : 81) +#define SUSBx_SEND_INT(x)	((x) ? 96 : 80) + +#define SUSBx_DEV_DESC_VEC(x)	((x) ? 0x00D4 : 0x00B4) +#define SUSBx_CONF_DESC_VEC(x)	((x) ? 0x00D6 : 0x00B6) +#define SUSBx_STRING_DESC_VEC(x) ((x) ? 0x00D8 : 0x00B8) + +#define CY_HCD_BUF_ADDR		0x500	/* Base address for host */ +#define SIE_TD_SIZE		0x200	/* size of the td list */ +#define SIE_TD_BUF_SIZE		0x400	/* size of the data buffer */ + +#define SIE_TD_OFFSET(host)	((host) ? (SIE_TD_SIZE+SIE_TD_BUF_SIZE) : 0) +#define SIE_BUF_OFFSET(host)	(SIE_TD_OFFSET(host) + SIE_TD_SIZE) + +/* Base address of HCD + 2 x TD_SIZE + 2 x TD_BUF_SIZE */ +#define CY_UDC_REQ_HEADER_BASE	0x1100 +/* 8- byte request headers for IN/OUT transfers */ +#define CY_UDC_REQ_HEADER_SIZE	8 + +#define CY_UDC_REQ_HEADER_ADDR(ep_num)	(CY_UDC_REQ_HEADER_BASE + \ +					 ((ep_num) * CY_UDC_REQ_HEADER_SIZE)) +#define CY_UDC_DESC_BASE_ADDRESS	(CY_UDC_REQ_HEADER_ADDR(8)) + +#define CY_UDC_BIOS_REPLACE_BASE	0x1800 +#define CY_UDC_REQ_BUFFER_BASE		0x2000 +#define CY_UDC_REQ_BUFFER_SIZE		0x0400 +#define CY_UDC_REQ_BUFFER_ADDR(ep_num)	(CY_UDC_REQ_BUFFER_BASE + \ +					 ((ep_num) * CY_UDC_REQ_BUFFER_SIZE)) + +/* --------------------------------------------------------------------- + * Driver data structures + */ + +struct c67x00_device; + +/** + * struct c67x00_sie - Common data associated with a SIE + * @lock: lock to protect this struct and the associated chip registers + * @private_data: subdriver dependent data + * @irq: subdriver dependent irq handler, set NULL when not used + * @dev: link to common driver structure + * @sie_num: SIE number on chip, starting from 0 + * @mode: SIE mode (host/peripheral/otg/not used) + */ +struct c67x00_sie { +	/* Entries to be used by the subdrivers */ +	spinlock_t lock;	/* protect this structure */ +	void *private_data; +	void (*irq) (struct c67x00_sie *sie, u16 int_status, u16 msg); + +	/* Read only: */ +	struct c67x00_device *dev; +	int sie_num; +	int mode; +}; + +#define sie_dev(s)	(&(s)->dev->pdev->dev) + +/** + * struct c67x00_lcp + */ +struct c67x00_lcp { +	/* Internal use only */ +	struct mutex mutex; +	struct completion msg_received; +	u16 last_msg; +}; + +/* + * struct c67x00_hpi + */ +struct c67x00_hpi { +	void __iomem *base; +	int regstep; +	spinlock_t lock; +	struct c67x00_lcp lcp; +}; + +#define C67X00_SIES	2 +#define C67X00_PORTS	2 + +/** + * struct c67x00_device - Common data associated with a c67x00 instance + * @hpi: hpi addresses + * @sie: array of sie's on this chip + * @pdev: platform device of instance + * @pdata: configuration provided by the platform + */ +struct c67x00_device { +	struct c67x00_hpi hpi; +	struct c67x00_sie sie[C67X00_SIES]; +	struct platform_device *pdev; +	struct c67x00_platform_data *pdata; +}; + +/* --------------------------------------------------------------------- + * Low level interface functions + */ + +/* Host Port Interface (HPI) functions */ +u16 c67x00_ll_hpi_status(struct c67x00_device *dev); +void c67x00_ll_hpi_reg_init(struct c67x00_device *dev); +void c67x00_ll_hpi_enable_sofeop(struct c67x00_sie *sie); +void c67x00_ll_hpi_disable_sofeop(struct c67x00_sie *sie); + +/* General functions */ +u16 c67x00_ll_fetch_siemsg(struct c67x00_device *dev, int sie_num); +u16 c67x00_ll_get_usb_ctl(struct c67x00_sie *sie); +void c67x00_ll_usb_clear_status(struct c67x00_sie *sie, u16 bits); +u16 c67x00_ll_usb_get_status(struct c67x00_sie *sie); +void c67x00_ll_write_mem_le16(struct c67x00_device *dev, u16 addr, +			      void *data, int len); +void c67x00_ll_read_mem_le16(struct c67x00_device *dev, u16 addr, +			     void *data, int len); + +/* Called by c67x00_irq to handle lcp interrupts */ +void c67x00_ll_irq(struct c67x00_device *dev, u16 int_status); + +/* Setup and teardown */ +void c67x00_ll_init(struct c67x00_device *dev); +void c67x00_ll_release(struct c67x00_device *dev); +int c67x00_ll_reset(struct c67x00_device *dev); + +#endif				/* _USB_C67X00_H */  |