On Mon, 2004-09-13 at 09:59, Olav Kongas wrote:
> Hi Lothar,
> 
> On Sat, 11 Sep 2004, Dimitris Lampridis wrote:
> 
> > On Fri, 2004-09-10 at 16:56, Lothar Wassmann wrote:
> > > No. The device could be used as a slave DMA device, but:
> > >   1) in our hardware the data register is located on a non-DMAable
> > >      address (PXA DMA addresses must be aligned to double word
> > >      boundary)
> > >   2) the SL811 requires CPU intervention for every data packet that is
> > >      sent or received anyway and could possibly transfer at most 240
> > >      byte in a single packet. Thus it's not worth the effort of using
> > >      DMA to move data to/from the chip.
> > > For the ISP116x/1362 it's a different story.
> 
> I guess these are your answers to Dimitris' questions about
> your sl811 driver. It seems that you posted these directly
> to Dimitris. Also, I couldn't find the 1362 header file
> Dimitris was talking about. Could you please repost all this
> to the list as well.
> 
> Thanks in advance,
> Olav
Propably true. Since Lothar hasn't replied, i'll send it.

Dimitris

/*
 * ISP1362 HCD (Host Controller Driver) for USB.
 * 
 * COPYRIGHT (C) by L. Wassmann <[EMAIL PROTECTED]>
 *
 *
 */

#include <asm/arch/bitfield.h>

#ifdef CONFIG_ARCH_KARO
#include <asm/arch/karo.h>
#endif

// settings used for debugging:
#define DEBUG
#ifdef DEBUG
#define BUFFER_TEST
#define TEST_BUF_SIZE	4096
#endif

#define FLIP_BUFFERS	32
#define USB_RESET_WIDTH	50

#define REG_WIDTH_16	0x000
#define REG_WIDTH_32	0x100
#define REG_WIDTH_MASK	0x100
#define REG_NO_MASK	0x0ff

#define REG_ACCESS_R	0x200
#define REG_ACCESS_W	0x400
#define REG_ACCESS_RW	0x600
#define REG_ACCESS_M	0x800		// reg needs to be merged with shadow reg
#define REG_ACCESS_MASK	0x600

//#define PTD_BLK_SIZE	64
#define ISP1362_BUF_SIZE		4096
#define ISP1362_REG_WRITE_OFFSET	0x80

#ifdef DEBUG
typedef const unsigned int isp1362_reg_t;
#define _BUG_ON(x) BUG_ON(x)
#define ISP1362_REG(name,addr,width,rw)					\
static isp1362_reg_t ISP1362_REG_##name = ((addr) | (width) | (rw));
#else
typedef const unsigned char isp1362_reg_t;
#define _BUG_ON(x) do {} while(0)
#define ISP1362_REG(name,addr,width,rw)					\
static isp1362_reg_t ISP1362_REG_##name = addr;
#endif

// OHCI compatible registers
/*
 * some of the ISP1362 'OHCI' registers implement only a subset of the
 * bits defined in the OHCI spec. For those registers we keep a shadow
 * copy in 'struct ohci_regs' that maintains the state of the bits that
 * are not defined in the ISP1362 controller register.
 * Those registers have to be read/written with the ohci_{read|write}_masked() functions.
 * Bitmasks for the individual bits of these registers are defined in "ohci.h"
 */
ISP1362_REG(HCREVISION,	0x00,	REG_WIDTH_32,	REG_ACCESS_R);
ISP1362_REG(HCCONTROL,	0x01,	REG_WIDTH_32,	REG_ACCESS_RW | REG_ACCESS_M);
#define ISP1362_MASK_HCCONTROL	(OHCI_CTRL_HCFS | OHCI_CTRL_RWE | OHCI_CTRL_RWC)
ISP1362_REG(HCCMDSTAT,	0x02,	REG_WIDTH_32,	REG_ACCESS_RW | REG_ACCESS_M);
#define ISP1362_MASK_HCCMDSTAT	(OHCI_HCR | OHCI_SOC)
ISP1362_REG(HCINTSTAT,	0x03,	REG_WIDTH_32,	REG_ACCESS_RW | REG_ACCESS_M);
#define ISP1362_MASK_HCINTSTAT	(OHCI_INTR_SO | OHCI_INTR_SF | OHCI_INTR_RD | OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC)
ISP1362_REG(HCINTENB,	0x04,	REG_WIDTH_32,	REG_ACCESS_RW | REG_ACCESS_M);
#define ISP1362_MASK_HCINTENB	(ISP1362_MASK_HCINTSTAT | OHCI_INTR_MIE)
ISP1362_REG(HCINTDIS,	0x05,	REG_WIDTH_32,	REG_ACCESS_RW | REG_ACCESS_M);
// OHCI_INTR_SF is required for internal housekeeping and shouldn't be disabled by OHCI layer
#define ISP1362_MASK_HCINTDIS	(ISP1362_MASK_HCINTENB & ~OHCI_INTR_SF)
ISP1362_REG(HCFMINTVL,	0x0d,	REG_WIDTH_32,	REG_ACCESS_RW);
ISP1362_REG(HCFMREM,	0x0e,	REG_WIDTH_32,	REG_ACCESS_RW);
ISP1362_REG(HCFMNUM,	0x0f,	REG_WIDTH_32,	REG_ACCESS_RW);
ISP1362_REG(HCLSTHRESH,	0x11,	REG_WIDTH_32,	REG_ACCESS_RW);
ISP1362_REG(HCRHDESCA,	0x12,	REG_WIDTH_32,	REG_ACCESS_RW);
ISP1362_REG(HCRHDESCB,	0x13,	REG_WIDTH_32,	REG_ACCESS_RW);
ISP1362_REG(HCRHSTATUS,	0x14,	REG_WIDTH_32,	REG_ACCESS_RW);
ISP1362_REG(HCRHPORT1,	0x15,	REG_WIDTH_32,	REG_ACCESS_RW);
ISP1362_REG(HCRHPORT2,	0x16,	REG_WIDTH_32,	REG_ACCESS_RW);

// Philips ISP1362 specific registers
ISP1362_REG(HCHWCFG,	0x20,	REG_WIDTH_16,	REG_ACCESS_RW);
#define HCHWCFG_DISABLE_SUSPEND	(1 << 15)
#define HCHWCFG_GLOBAL_PWRDOWN	(1 << 14)
#define HCHWCFG_PULLDOWN_DS1	(1 << 13)
#define HCHWCFG_PULLDOWN_DS2	(1 << 12)
#define HCHWCFG_CLKNOTSTOP	(1 << 11)
#define HCHWCFG_ANALOG_OC	(1 << 10)
#define HCHWCFG_ONEINT		(1 << 9)
#define HCHWCFG_DACK_MODE	(1 << 8)
#define HCHWCFG_ONEDMA		(1 << 7)
#define HCHWCFG_DACK_POL	(1 << 6)
#define HCHWCFG_DREQ_POL	(1 << 5)
#define HCHWCFG_DBWIDTH_MASK	(0x03 << 3)
#define HCHWCFG_DBWIDTH(n)	(((n) << 3) & HCHWCFG_DBWIDTH_MASK)
#define HCHWCFG_INT_POL		(1 << 2)
#define HCHWCFG_INT_TRIGGER	(1 << 1)
#define HCHWCFG_INT_ENABLE	(1 << 0)

ISP1362_REG(HCDMACFG,	0x21,	REG_WIDTH_16,	REG_ACCESS_RW);
#define HCDMACFG_CTR_ENABLE	(1 << 7)
#define HCDMACFG_BURST_LEN_MASK	(0x03 << 5)
#define HCDMACFG_BURST_LEN(n)	(((n) << 5) & HCDMACFG_BURST_LEN__MASK)
#define HCDMACFG_BURST_LEN_1	HCDMACFG_BURST_LEN(0)
#define HCDMACFG_BURST_LEN_4	HCDMACFG_BURST_LEN(1)
#define HCDMACFG_BURST_LEN_8	HCDMACFG_BURST_LEN(2)
#define HCDMACFG_DMA_ENABLE	(1 << 4)
#define HCDMACFG_BUF_TYPE_MASK	(0x07 << 1)
#define HCDMACFG_BUF_TYPE(n)	(((n) << 1) & HCDMACFG_BURST_LEN__MASK)
#define HCDMACFG_BUF_ISTL0	HCDMACFG_BUF_TYPE(0)
#define HCDMACFG_BUF_ISTL1	HCDMACFG_BUF_TYPE(1)
#define HCDMACFG_BUF_INTL	HCDMACFG_BUF_TYPE(2)
#define HCDMACFG_BUF_ATL	HCDMACFG_BUF_TYPE(3)
#define HCDMACFG_BUF_DIRECT	HCDMACFG_BUF_TYPE(4)
#define HCDMACFG_DMA_RW_SELECT	(1 << 0)

ISP1362_REG(HCXFERCTR,	0x22,	REG_WIDTH_16,	REG_ACCESS_RW);

ISP1362_REG(HCuPINT,	0x24,	REG_WIDTH_16,	REG_ACCESS_RW);
#define HCuPINT_SOF		(1 << 0)
#define HCuPINT_ISTL0		(1 << 1)
#define HCuPINT_ISTL1		(1 << 2)
#define HCuPINT_EOT		(1 << 3)
#define HCuPINT_OPR		(1 << 4)
#define HCuPINT_SUSP		(1 << 5)
#define HCuPINT_CLKRDY		(1 << 6)
#define HCuPINT_INTL		(1 << 7)
#define HCuPINT_ATL		(1 << 8)
#define HCuPINT_OTG		(1 << 9)

ISP1362_REG(HCuPINTENB,	0x25,	REG_WIDTH_16,	REG_ACCESS_RW);
// same bit definitions apply as for HCuPINT

ISP1362_REG(HCCHIPID,	0x27,	REG_WIDTH_16,	REG_ACCESS_R);
#define HCCHIPID_MASK		0xff00
#define HCCHIPID_MAGIC		0x3600

ISP1362_REG(HCSCRATCH,	0x28,	REG_WIDTH_16,	REG_ACCESS_RW);

ISP1362_REG(HCSWRES,	0x29,	REG_WIDTH_16,	REG_ACCESS_W);
#define HCSWRES_MAGIC		0x00f6

ISP1362_REG(HCBUFSTAT,	0x2c,	REG_WIDTH_16,	REG_ACCESS_RW);
#define HCBUFSTAT_ISTL0_FULL	(1 << 0)
#define HCBUFSTAT_ISTL1_FULL	(1 << 1)
#define HCBUFSTAT_INTL_ACTIVE	(1 << 2)
#define HCBUFSTAT_ATL_ACTIVE	(1 << 3)
#define HCBUFSTAT_RESET_HWPP	(1 << 4)
#define HCBUFSTAT_ISTL0_ACTIVE	(1 << 5)
#define HCBUFSTAT_ISTL1_ACTIVE	(1 << 6)
#define HCBUFSTAT_ISTL0_DONE	(1 << 8)
#define HCBUFSTAT_ISTL1_DONE	(1 << 9)
#define HCBUFSTAT_PAIRED_PTDPP	(1 << 10)

ISP1362_REG(HCDIRADDR,	0x32,	REG_WIDTH_32,	REG_ACCESS_RW);
#define _HCDIRADDR_ADDR		Fld(16, 0)
#define HCDIRADDR_ADDR_MASK	FMsk(_HCDIRADDR_ADDR)
#define HCDIRADDR_ADDR(n)	(FInsrt(n, _HCDIRADDR_ADDR) & FMsk(_HCDIRADDR_ADDR))
#define _HCDIRADDR_COUNT		Fld(16, 16)
#define HCDIRADDR_COUNT_MASK	FMsk(_HCDIRADDR_COUNT)
#define HCDIRADDR_COUNT(n)	(FInsrt(n, _HCDIRADDR_COUNT) & FMsk(_HCDIRADDR_COUNT))
ISP1362_REG(HCDIRDATA,	0x45,	REG_WIDTH_16,	REG_ACCESS_RW);

ISP1362_REG(HCISTLBUFSZ, 0x30,	REG_WIDTH_16,	REG_ACCESS_RW);
ISP1362_REG(HCISTL0PORT, 0x40,	REG_WIDTH_16,	REG_ACCESS_RW);
ISP1362_REG(HCISTL1PORT, 0x42,	REG_WIDTH_16,	REG_ACCESS_RW);
ISP1362_REG(HCISTLRATE,	0x47,	REG_WIDTH_16,	REG_ACCESS_RW);

ISP1362_REG(HCINTLBUFSZ, 0x33,	REG_WIDTH_16,	REG_ACCESS_RW);
ISP1362_REG(HCINTLPORT,	0x43,	REG_WIDTH_16,	REG_ACCESS_RW);
ISP1362_REG(HCINTLBLKSZ, 0x53,	REG_WIDTH_16,	REG_ACCESS_RW);
ISP1362_REG(HCINTLDONE,	0x17,	REG_WIDTH_32,	REG_ACCESS_R);
ISP1362_REG(HCINTLSKIP,	0x18,	REG_WIDTH_32,	REG_ACCESS_RW);
ISP1362_REG(HCINTLLAST,	0x19,	REG_WIDTH_32,	REG_ACCESS_RW);
ISP1362_REG(HCINTLCURR,	0x1a,	REG_WIDTH_16,	REG_ACCESS_R);

ISP1362_REG(HCATLBUFSZ, 0x34,	REG_WIDTH_16,	REG_ACCESS_RW);
ISP1362_REG(HCATLPORT,	0x44,	REG_WIDTH_16,	REG_ACCESS_RW);
ISP1362_REG(HCATLBLKSZ, 0x54,	REG_WIDTH_16,	REG_ACCESS_RW);
ISP1362_REG(HCATLDONE,	0x1b,	REG_WIDTH_32,	REG_ACCESS_R);
ISP1362_REG(HCATLSKIP,	0x1c,	REG_WIDTH_32,	REG_ACCESS_RW);
ISP1362_REG(HCATLLAST,	0x1d,	REG_WIDTH_32,	REG_ACCESS_RW);
ISP1362_REG(HCATLCURR,	0x1e,	REG_WIDTH_16,	REG_ACCESS_R);

ISP1362_REG(HCATLDTC,	0x51,	REG_WIDTH_16,	REG_ACCESS_RW);
ISP1362_REG(HCATLDTCTO,	0x52,	REG_WIDTH_16,	REG_ACCESS_RW);

/*
 * define initial values for the HW configuration registers
 * Since those values are implementation specific we define
 * them here for conveniently changing them according to the
 * machine type.
 */
#ifdef CONFIG_ARCH_KARO
#define HCHWCFG_INIT_VAL	(HCHWCFG_GLOBAL_PWRDOWN |	\
				 HCHWCFG_ANALOG_OC |		\
				 HCHWCFG_DREQ_POL |		\
				 HCHWCFG_CLKNOTSTOP |		\
				 HCHWCFG_DBWIDTH(1) |		\
				 HCHWCFG_INT_POL |		\
				 HCHWCFG_INT_ENABLE)
#else
#error Specify appropriate initialization values for HW configuration registers
#define HCHWCFG_INIT_VAL	()
#endif

#define ohci_to_hcd(ohci) (&(ohci)->hcd)
#define hcd_to_isp1362_dev(hcd)	((struct hc_isp1362_dev *)dev_get_drvdata(hcd->self.controller))
#define ohci_to_isp1362_dev(ohci)	((struct hc_isp1362_dev *)dev_get_drvdata(ohci->hcd.self.controller))
#define hc_isp1362_dev_to_hcd(dev) ((struct usb_hcd *)dev_get_drvdata(&dev->dev))

struct ptd {
	u8 count;
	u8 cc_toggle;
	u8 mps;
	u8 ep_spd;
	u8 len;
	u8 dir;
	u8 func_addr;
	u8 pr_sf;
} __attribute__((packed));
#define _PTD_COUNT		Fld(10, 0)
#define PTD_COUNT(v)		FInsrt(v, _PTD_COUNT)
#define PTD_GET_COUNT(p)	FExtr(*(u16*)(&(p)->count), _PTD_COUNT)

#define _PTD_TOGGLE		Fld(1, 2)
#define PTD_TOGGLE(v)		FInsrt(v, _PTD_TOGGLE)
#define PTD_GET_TOGGLE(p)	FExtr((p)->cc_toggle, _PTD_TOGGLE)
#define _PTD_ACTIVE		Fld(1, 3)
#define PTD_ACTIVE(v)		FInsrt(v, _PTD_ACTIVE)
#define PTD_GET_ACTIVE(p)	FExtr((p)->cc_toggle, _PTD_ACTIVE)
#define _PTD_CC			Fld(4, 12)
#define PTD_CC(v)		FInsrt(v, _PTD_CC)
#define PTD_GET_CC(p)		FExtr((p)->cc_toggle, _PTD_CC)

#define _PTD_MPS		Fld(10, 0)
#define PTD_MPS(v)		FInsrt(v, _PTD_MPS)
#define PTD_GET_MPS(p)		FExtr(*(u16*)(&(p)->dir), _PTD_MPS)

#define _PTD_MPS_H		Fld(2, 0)
#define PTD_MPS_H(v)		FInsrt(v, _PTD_MPS_H)
#define _PTD_SPD		Fld(1, 2)
#define PTD_SPD(v)		FInsrt(v, _PTD_SPD)
#define PTD_GET_SPD(p)		FExtr((p)->ep_spd, _PTD_SPD)
#define _PTD_LAST_ISO		Fld(1, 3)
#define PTD_LAST_ISO(v)		FInsrt(v, _PTD_LAST_ISO)
#define PTD_GET_LAST_ISO(p)	FExtr((p)->ep_spd, _PTD_LAST_ISO)
#define _PTD_EP			Fld(4, 4)
#define PTD_EP(v)		FInsrt(v, _PTD_EP)
#define PTD_GET_EP(p)		FExtr((p)->ep_spd, _PTD_EP)

#define _PTD_LEN		Fld(10, 0)
#define PTD_LEN(v)		FInsrt(v, _PTD_LEN)
#define PTD_GET_LEN(p)		FExtr(*(u16*)(&(p)->len), _PTD_LEN)

#define _PTD_LEN_H		Fld(2, 0)
#define PTD_LEN_H(v)		FInsrt(v, _PTD_LEN_H)
#define _PTD_DIR		Fld(2, 2)
#define PTD_DIR(v)		FInsrt(v, _PTD_DIR)
#define PTD_GET_DIR(p)		FExtr((p)->dir, _PTD_DIR)

#define _PTD_SF			Fld(4, 0)
#define PTD_SF(v)		FInsrt(v, _PTD_SF)
#define PTD_GET_SF(p)		FExtr(*(u16*)(&(p)->pr_sf), _PTD_SF)
#define _PTD_PR			Fld(3, 5)
#define PTD_PR(v)		FInsrt(v, _PTD_PR)
#define PTD_GET_PR(p)		FExtr(*(u16*)(&(p)->pr_sf), _PTD_PR)

#define PID_SETUP		0
#define PID_OUT			1
#define PID_IN			2

#define PTD_HEADER_SIZE		sizeof(struct ptd)

struct xfer_buf {
	struct ptd	ptd;
	struct td	*td;
	int		xfer_type:2;
	int		port:1;
	u16		buf_addr;
//	int		buf_len;
} __attribute__((packed));

struct ptd_queue {
	struct xfer_buf	*buf_list;
	unsigned long	buf_map;
	u16		buf_start;
	u16		blk_size;
	u8		num_bufs;
};

struct hc_isp1362_dev {
	struct device	dev;
	void		*addr_reg;
	void		*data_reg;
	int		hwres_pin;
	int		irq;
#ifdef CONFIG_USB_OHCI_DMA
	int		dma;
#endif
	int		pm_state;
	int		iso_flip:1;
	int		bulk_flip:1;
#if 0
	struct ptd_queue *ptd_queues[4];
	enum {
		PTD_Q_ISTL0,
		PTD_Q_ISTL1,
		PTD_Q_INTL,
		PTD_Q_ATL,
	} ptd_q_type;
#else
	void		*ptd_mem;
	ssize_t		ptd_mem_size;
#ifdef ONE_ISTL_Q
	struct ptd_queue *ptd_queues[3];
	struct ptd_queue istl_queue;
#else
	struct ptd_queue *ptd_queues[4];
	struct ptd_queue istl0_queue;
	struct ptd_queue istl1_queue;
#endif
	struct ptd_queue intl_queue;
	struct ptd_queue atl_queue;
#endif
	int 		cbc;
	int 		intrdelay;
	u8 		hw_rev;
};

struct hc_isp1362_driver {
	struct device_driver	drv;
	unsigned int		devid;
	int (*probe)(struct hc_isp1362_dev *dev);
	int (*remove)(struct hc_isp1362_dev *dev);
	int (*suspend)(struct hc_isp1362_dev *dev, u32 state);
	int (*resume)(struct hc_isp1362_dev *dev);
// TODO: define these and init them from platform specific code
//	void (*reset_chip)(struct hc_isp1362_dev *dev, int flag);
//	void (*start_stop_clock)(struct hc_isp1362_dev *dev, int flag);
};

#define ISP1362_DRV(_d)		container_of((_d), struct hc_isp1362_driver, drv)

/*
 * ISP1362 HW Interface
 */

#define hc_isp1362_addr_reg (dev->addr_reg)
#define hc_isp1362_data_reg (dev->data_reg)

// basic access functions for ISP1362 chip registers
static inline void HC_ISP1362_WRITE_ADDR(struct hc_isp1362_dev *dev, isp1362_reg_t reg)
{
	//DDPRINTK("A>[EMAIL PROTECTED]", reg, (u32)hc_isp1362_addr_reg);
	__asm__ volatile ("/* HC_ISP1362_WRITE_ADDR START */");
	_BUG_ON((reg & 0x80) && !(reg & REG_ACCESS_W));
	writew(reg, hc_isp1362_addr_reg);
	__asm__ volatile ("/* HC_ISP1362_WRITE_ADDR END */");
}

static inline void HC_ISP1362_WRITE_DATA16(struct hc_isp1362_dev *dev, u16 val)
{
	__asm__ volatile ("/* HC_ISP1362_WRITE_DATA16 START */");
	writew(val, hc_isp1362_data_reg);
	__asm__ volatile ("/* HC_ISP1362_WRITE_DATA16 END */");
}

static inline u16 HC_ISP1362_READ_DATA16(struct hc_isp1362_dev *dev)
{
	u16 val;

	__asm__ volatile ("/* HC_ISP1362_READ_DATA16 START */");
	val = readw(hc_isp1362_data_reg);
	//DDPRINTK("D<[EMAIL PROTECTED]", val, (u32)hc_isp1362_data_reg);

	__asm__ volatile ("/* HC_ISP1362_READ_DATA16 END */");
	return val;
}

static inline void HC_ISP1362_WRITE_DATA32(struct hc_isp1362_dev *dev, u32 val)
{
	__asm__ volatile ("/* HC_ISP1362_WRITE_DATA32 START */");
	writel(val, hc_isp1362_data_reg);
	__asm__ volatile ("/* HC_ISP1362_WRITE_DATA32 END */");
}

static inline u32 HC_ISP1362_READ_DATA32(struct hc_isp1362_dev *dev)
{
	u32 val;

	__asm__ volatile ("/* HC_ISP1362_READ_DATA32 START */");
	val = readl(hc_isp1362_data_reg);
	//DDPRINTK("D<[EMAIL PROTECTED]", val, (u32)hc_isp1362_data_reg);

	__asm__ volatile ("/* HC_ISP1362_READ_DATA32 END */");
	return val;
}

#define __isp1362_read_reg16(d, r)		({			\
	u16 __v;							\
	_BUG_ON(((ISP1362_REG_##r) & REG_WIDTH_MASK) != REG_WIDTH_16);	\
	HC_ISP1362_WRITE_ADDR(d, ISP1362_REG_##r);			\
	__v = HC_ISP1362_READ_DATA16(d);				\
})

#define isp1362_read_reg16(d, r) ({		\
	u16 __v;				\
	unsigned long __f;			\
	local_irq_save(__f);			\
	__v = __isp1362_read_reg16(d, r);	\
	local_irq_restore(__f);			\
	__v;					\
})

#define __isp1362_read_reg32(d, r)		({			\
	u32 __v;							\
	_BUG_ON(((ISP1362_REG_##r) & REG_WIDTH_MASK) != REG_WIDTH_32);	\
	HC_ISP1362_WRITE_ADDR(d, ISP1362_REG_##r);			\
	__v = HC_ISP1362_READ_DATA32(d);				\
})

#define __isp1362_write_reg16(d, r, v)	{					\
	_BUG_ON(((ISP1362_REG_##r) & REG_WIDTH_MASK) != REG_WIDTH_16);		\
	HC_ISP1362_WRITE_ADDR(d, (ISP1362_REG_##r) | ISP1362_REG_WRITE_OFFSET);	\
	HC_ISP1362_WRITE_DATA16(d, v);						\
}

#define __isp1362_write_reg32(d, r, v)	{					\
	_BUG_ON(((ISP1362_REG_##r) & REG_WIDTH_MASK) != REG_WIDTH_32);		\
	HC_ISP1362_WRITE_ADDR(d, (ISP1362_REG_##r) | ISP1362_REG_WRITE_OFFSET);	\
	HC_ISP1362_WRITE_DATA32(d, v);						\
}

#define isp1362_write_reg16(d, r, v) {	\
	unsigned long flags;		\
	local_irq_save(flags);		\
	__isp1362_write_reg16(d, r, v);	\
	local_irq_restore(flags);	\
}

#if 0
// access functions for ISP1362 specific (16bit) registers
static inline u16 __hc_isp1362_read_reg(struct hc_isp1362_dev *dev, isp1362_reg_t reg)
{
	u16 val;

	__asm__ volatile ("/* __hc_isp1362_read_reg START */");
	_BUG_ON((reg & REG_WIDTH_MASK) != REG_WIDTH_16);
	HC_ISP1362_WRITE_ADDR(dev, reg);
	val = HC_ISP1362_READ_DATA16(dev);
	__asm__ volatile ("/* __hc_isp1362_read_reg END */");
	return val;
}

static inline u16 hc_isp1362_read_reg(struct hc_isp1362_dev *dev, isp1362_reg_t reg)
{
	u16 val;
	unsigned long flags;

	local_irq_save(flags);
	val = __hc_isp1362_read_reg(dev, reg);
	local_irq_restore(flags);

	return val;
}

static inline void __hc_isp1362_write_reg(struct hc_isp1362_dev *dev, isp1362_reg_t reg, u16 val)
{
	__asm__ volatile ("/* __hc_isp1362_write_reg START */");
	_BUG_ON((reg & REG_WIDTH_MASK) != REG_WIDTH_16);
	HC_ISP1362_WRITE_ADDR(dev, reg | ISP1362_REG_WRITE_OFFSET);
	HC_ISP1362_WRITE_DATA16(dev, val);
	__asm__ volatile ("/* __hc_isp1362_write_reg END */");
}

static inline void hc_isp1362_write_reg(struct hc_isp1362_dev *dev, isp1362_reg_t reg, u16 val)
{
	unsigned long flags;

	local_irq_save(flags);
	__hc_isp1362_write_reg(dev, reg, val);
	local_irq_restore(flags);
}
#endif

#define __isp1362_set_mask16(d,r,m) {		\
	u16 __v;				\
	__v = __isp1362_read_reg16(dev, r);	\
	__v |= m;				\
	__isp1362_write_reg16(dev, r, __v);	\
}

#define isp1362_set_mask16(d,r,m) {	\
	unsigned long flags;		\
					\
	local_irq_save(flags);		\
	__isp1362_set_mask16(d, r, m);	\
	local_irq_restore(flags);	\
}

#define __isp1362_clr_mask16(d,r,m) {		\
	u16 __v;				\
	__v = __isp1362_read_reg16(dev, r);	\
	__v |= m;				\
	__isp1362_write_reg16(dev, r, __v);	\
}
#define isp1362_clr_mask16(d,r,m) {	\
	unsigned long flags;		\
					\
	local_irq_save(flags);		\
	__isp1362_clr_mask16(d, r, m);	\
	local_irq_restore(flags);	\
}

static inline int __isp1362_read_buffer(struct hc_isp1362_dev *dev, void *buf, u16 offset, u16 len)
{
	int ret;
	u8 *dp = buf;
	u16 data;
	int i;

	__isp1362_write_reg32(dev, HCDIRADDR, HCDIRADDR_ADDR(offset) | HCDIRADDR_COUNT(len));
	for (i = 0; i < len - 1; i += 2) {
		data = __isp1362_read_reg16(dev, HCDIRDATA);
		*dp++ = data;
		*dp++ = data >> 8;
	}
	if (len & 1) {
		data = __isp1362_read_reg16(dev, HCDIRDATA);
		*dp++ = data;
	}

	return ret;
}

static inline int __isp1362_write_buffer(struct hc_isp1362_dev *dev, void *buf, u16 offset, u16 len)
{
	int ret;
	u8 *dp = buf;
	u16 data;
	int i;

	__isp1362_write_reg32(dev, HCDIRADDR, HCDIRADDR_ADDR(offset) | HCDIRADDR_COUNT(len));
	for (i = 0; i < len - 1; i += 2) {
		data = *dp++;
		data = (data << 8) | *dp++;
		__isp1362_write_reg16(dev, HCDIRDATA, data);
	}
	if (len & 1) {
		data = *dp++;
		__isp1362_write_reg16(dev, HCDIRDATA, data);
	}

	return ret;
}

static inline void hc_isp1362_dump_regs(struct hc_isp1362_dev *dev)
{

}

#if defined(CONFIG_ARCH_KARO)
static inline void isp1362_set_hw_reset(struct hc_isp1362_dev *dev)
{
	if (dev->hwres_pin) {
		DPRINTK("%s: ***ASSERTING HW RESET***\n", __FUNCTION__);
		if (dev->hwres_pin < 0) {
			gpio_clr_bit(dev->hwres_pin & 0xff);
		} else {
			gpio_set_bit(dev->hwres_pin & 0xff);
		}
	} else {
		DPRINTK("%s: ***PERFORMING SW RESET***\n", __FUNCTION__);
		isp1362_write_reg16(dev, HCSWRES, HCSWRES_MAGIC);
	}
}

static inline void isp1362_clr_hw_reset(struct hc_isp1362_dev *dev)
{
	if (dev->hwres_pin) {
		DPRINTK("%s: --DEASSERTING HW RESET--\n", __FUNCTION__);
		if (dev->hwres_pin < 0) {
			gpio_set_bit(dev->hwres_pin & 0xff);
		} else {
			gpio_clr_bit(dev->hwres_pin & 0xff);
		}
	}
}
#define isp1362_start_clock(dev)
#define isp1362_stop_clock(dev)
#else
#error Define your hardware specific reset functions here
#endif

// function prototypes
static __inline void retire_td(struct usb_hcd *hcd, struct td *td, struct ed *ed);

Reply via email to