cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

c67x00-ll-hpi.c (11801B)


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