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