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