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