r8a66597-udc.h 6.6 KB
Newer Older
1 2 3 4 5
/*
 * R8A66597 UDC
 *
 * Copyright (C) 2007-2009 Renesas Solutions Corp.
 *
6
 * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
7 8 9 10 11 12 13 14 15
 *
 * 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; version 2 of the License.
 */

#ifndef __R8A66597_H__
#define __R8A66597_H__

16 17 18 19
#ifdef CONFIG_HAVE_CLK
#include <linux/clk.h>
#endif

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
#include <linux/usb/r8a66597.h>

#define R8A66597_MAX_SAMPLING	10

#define R8A66597_MAX_NUM_PIPE	8
#define R8A66597_MAX_NUM_BULK	3
#define R8A66597_MAX_NUM_ISOC	2
#define R8A66597_MAX_NUM_INT	2

#define R8A66597_BASE_PIPENUM_BULK	3
#define R8A66597_BASE_PIPENUM_ISOC	1
#define R8A66597_BASE_PIPENUM_INT	6

#define R8A66597_BASE_BUFNUM	6
#define R8A66597_MAX_BUFNUM	0x4F

#define is_bulk_pipe(pipenum)	\
	((pipenum >= R8A66597_BASE_PIPENUM_BULK) && \
	 (pipenum < (R8A66597_BASE_PIPENUM_BULK + R8A66597_MAX_NUM_BULK)))
#define is_interrupt_pipe(pipenum)	\
	((pipenum >= R8A66597_BASE_PIPENUM_INT) && \
	 (pipenum < (R8A66597_BASE_PIPENUM_INT + R8A66597_MAX_NUM_INT)))
#define is_isoc_pipe(pipenum)	\
	((pipenum >= R8A66597_BASE_PIPENUM_ISOC) && \
	 (pipenum < (R8A66597_BASE_PIPENUM_ISOC + R8A66597_MAX_NUM_ISOC)))

struct r8a66597_pipe_info {
	u16	pipe;
	u16	epnum;
	u16	maxpacket;
	u16	type;
	u16	interval;
	u16	dir_in;
};

struct r8a66597_request {
	struct usb_request	req;
	struct list_head	queue;
};

struct r8a66597_ep {
	struct usb_ep		ep;
	struct r8a66597		*r8a66597;

	struct list_head	queue;
	unsigned		busy:1;
66
	unsigned		wedge:1;
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
	unsigned		internal_ccpl:1;	/* use only control */

	/* this member can able to after r8a66597_enable */
	unsigned		use_dma:1;
	u16			pipenum;
	u16			type;
	const struct usb_endpoint_descriptor	*desc;
	/* register address */
	unsigned char		fifoaddr;
	unsigned char		fifosel;
	unsigned char		fifoctr;
	unsigned char		fifotrn;
	unsigned char		pipectr;
};

struct r8a66597 {
	spinlock_t		lock;
84
	void __iomem		*reg;
85

86 87 88
#ifdef CONFIG_HAVE_CLK
	struct clk *clk;
#endif
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
	struct r8a66597_platdata	*pdata;

	struct usb_gadget		gadget;
	struct usb_gadget_driver	*driver;

	struct r8a66597_ep	ep[R8A66597_MAX_NUM_PIPE];
	struct r8a66597_ep	*pipenum2ep[R8A66597_MAX_NUM_PIPE];
	struct r8a66597_ep	*epaddr2ep[16];

	struct timer_list	timer;
	struct usb_request	*ep0_req;	/* for internal request */
	u16			ep0_data;	/* for internal request */
	u16			old_vbus;
	u16			scount;
	u16			old_dvsq;

	/* pipe config */
	unsigned char bulk;
	unsigned char interrupt;
	unsigned char isochronous;
	unsigned char num_dma;

	unsigned irq_sense_low:1;
};

#define gadget_to_r8a66597(_gadget)	\
		container_of(_gadget, struct r8a66597, gadget)
#define r8a66597_to_gadget(r8a66597) (&r8a66597->gadget)
117
#define r8a66597_to_dev(r8a66597)	(r8a66597->gadget.dev.parent)
118 119 120

static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset)
{
121
	return ioread16(r8a66597->reg + offset);
122 123 124
}

static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597,
M
Magnus Damm 已提交
125 126
				      unsigned long offset,
				      unsigned char *buf,
127 128
				      int len)
{
129
	void __iomem *fifoaddr = r8a66597->reg + offset;
130
	unsigned int data = 0;
M
Magnus Damm 已提交
131 132
	int i;

133
	if (r8a66597->pdata->on_chip) {
M
Magnus Damm 已提交
134 135 136 137
		/* 32-bit accesses for on_chip controllers */

		/* aligned buf case */
		if (len >= 4 && !((unsigned long)buf & 0x03)) {
138
			ioread32_rep(fifoaddr, buf, len / 4);
M
Magnus Damm 已提交
139 140 141 142 143 144 145
			buf += len & ~0x03;
			len &= 0x03;
		}

		/* unaligned buf case */
		for (i = 0; i < len; i++) {
			if (!(i & 0x03))
146
				data = ioread32(fifoaddr);
M
Magnus Damm 已提交
147 148

			buf[i] = (data >> ((i & 0x03) * 8)) & 0xff;
149 150
		}
	} else {
M
Magnus Damm 已提交
151 152 153 154
		/* 16-bit accesses for external controllers */

		/* aligned buf case */
		if (len >= 2 && !((unsigned long)buf & 0x01)) {
155
			ioread16_rep(fifoaddr, buf, len / 2);
M
Magnus Damm 已提交
156 157 158 159 160 161 162
			buf += len & ~0x01;
			len &= 0x01;
		}

		/* unaligned buf case */
		for (i = 0; i < len; i++) {
			if (!(i & 0x01))
163
				data = ioread16(fifoaddr);
M
Magnus Damm 已提交
164 165 166

			buf[i] = (data >> ((i & 0x01) * 8)) & 0xff;
		}
167 168 169 170 171 172
	}
}

static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val,
				  unsigned long offset)
{
173
	iowrite16(val, r8a66597->reg + offset);
174 175
}

176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
static inline void r8a66597_mdfy(struct r8a66597 *r8a66597,
				 u16 val, u16 pat, unsigned long offset)
{
	u16 tmp;
	tmp = r8a66597_read(r8a66597, offset);
	tmp = tmp & (~pat);
	tmp = tmp | val;
	r8a66597_write(r8a66597, tmp, offset);
}

#define r8a66597_bclr(r8a66597, val, offset)	\
			r8a66597_mdfy(r8a66597, 0, val, offset)
#define r8a66597_bset(r8a66597, val, offset)	\
			r8a66597_mdfy(r8a66597, val, 0, offset)

191
static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597,
192
				       struct r8a66597_ep *ep,
M
Magnus Damm 已提交
193
				       unsigned char *buf,
194 195
				       int len)
{
196
	void __iomem *fifoaddr = r8a66597->reg + ep->fifoaddr;
M
Magnus Damm 已提交
197 198
	int adj = 0;
	int i;
199 200

	if (r8a66597->pdata->on_chip) {
M
Magnus Damm 已提交
201 202
		/* 32-bit access only if buf is 32-bit aligned */
		if (len >= 4 && !((unsigned long)buf & 0x03)) {
203
			iowrite32_rep(fifoaddr, buf, len / 4);
M
Magnus Damm 已提交
204 205
			buf += len & ~0x03;
			len &= 0x03;
206 207
		}
	} else {
M
Magnus Damm 已提交
208 209
		/* 16-bit access only if buf is 16-bit aligned */
		if (len >= 2 && !((unsigned long)buf & 0x01)) {
210
			iowrite16_rep(fifoaddr, buf, len / 2);
M
Magnus Damm 已提交
211 212
			buf += len & ~0x01;
			len &= 0x01;
213 214
		}
	}
M
Magnus Damm 已提交
215 216 217 218 219 220 221 222 223

	/* adjust fifo address in the little endian case */
	if (!(r8a66597_read(r8a66597, CFIFOSEL) & BIGEND)) {
		if (r8a66597->pdata->on_chip)
			adj = 0x03; /* 32-bit wide */
		else
			adj = 0x01; /* 16-bit wide */
	}

224 225
	if (r8a66597->pdata->wr0_shorted_to_wr1)
		r8a66597_bclr(r8a66597, MBW_16, ep->fifosel);
M
Magnus Damm 已提交
226
	for (i = 0; i < len; i++)
227
		iowrite8(buf[i], fifoaddr + adj - (i & adj));
228 229
	if (r8a66597->pdata->wr0_shorted_to_wr1)
		r8a66597_bclr(r8a66597, MBW_16, ep->fifosel);
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
}

static inline u16 get_xtal_from_pdata(struct r8a66597_platdata *pdata)
{
	u16 clock = 0;

	switch (pdata->xtal) {
	case R8A66597_PLATDATA_XTAL_12MHZ:
		clock = XTAL12;
		break;
	case R8A66597_PLATDATA_XTAL_24MHZ:
		clock = XTAL24;
		break;
	case R8A66597_PLATDATA_XTAL_48MHZ:
		clock = XTAL48;
		break;
	default:
		printk(KERN_ERR "r8a66597: platdata clock is wrong.\n");
		break;
	}

	return clock;
}

#define get_pipectr_addr(pipenum)	(PIPE1CTR + (pipenum - 1) * 2)

#define enable_irq_ready(r8a66597, pipenum)	\
	enable_pipe_irq(r8a66597, pipenum, BRDYENB)
#define disable_irq_ready(r8a66597, pipenum)	\
	disable_pipe_irq(r8a66597, pipenum, BRDYENB)
#define enable_irq_empty(r8a66597, pipenum)	\
	enable_pipe_irq(r8a66597, pipenum, BEMPENB)
#define disable_irq_empty(r8a66597, pipenum)	\
	disable_pipe_irq(r8a66597, pipenum, BEMPENB)
#define enable_irq_nrdy(r8a66597, pipenum)	\
	enable_pipe_irq(r8a66597, pipenum, NRDYENB)
#define disable_irq_nrdy(r8a66597, pipenum)	\
	disable_pipe_irq(r8a66597, pipenum, NRDYENB)

#endif	/* __R8A66597_H__ */