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

spi-sc18is602.c (8325B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * NXP SC18IS602/603 SPI driver
      4 *
      5 * Copyright (C) Guenter Roeck <linux@roeck-us.net>
      6 */
      7
      8#include <linux/kernel.h>
      9#include <linux/err.h>
     10#include <linux/module.h>
     11#include <linux/spi/spi.h>
     12#include <linux/i2c.h>
     13#include <linux/delay.h>
     14#include <linux/pm_runtime.h>
     15#include <linux/of_device.h>
     16#include <linux/of.h>
     17#include <linux/platform_data/sc18is602.h>
     18#include <linux/gpio/consumer.h>
     19
     20enum chips { sc18is602, sc18is602b, sc18is603 };
     21
     22#define SC18IS602_BUFSIZ		200
     23#define SC18IS602_CLOCK			7372000
     24
     25#define SC18IS602_MODE_CPHA		BIT(2)
     26#define SC18IS602_MODE_CPOL		BIT(3)
     27#define SC18IS602_MODE_LSB_FIRST	BIT(5)
     28#define SC18IS602_MODE_CLOCK_DIV_4	0x0
     29#define SC18IS602_MODE_CLOCK_DIV_16	0x1
     30#define SC18IS602_MODE_CLOCK_DIV_64	0x2
     31#define SC18IS602_MODE_CLOCK_DIV_128	0x3
     32
     33struct sc18is602 {
     34	struct spi_master	*master;
     35	struct device		*dev;
     36	u8			ctrl;
     37	u32			freq;
     38	u32			speed;
     39
     40	/* I2C data */
     41	struct i2c_client	*client;
     42	enum chips		id;
     43	u8			buffer[SC18IS602_BUFSIZ + 1];
     44	int			tlen;	/* Data queued for tx in buffer */
     45	int			rindex;	/* Receive data index in buffer */
     46
     47	struct gpio_desc	*reset;
     48};
     49
     50static int sc18is602_wait_ready(struct sc18is602 *hw, int len)
     51{
     52	int i, err;
     53	int usecs = 1000000 * len / hw->speed + 1;
     54	u8 dummy[1];
     55
     56	for (i = 0; i < 10; i++) {
     57		err = i2c_master_recv(hw->client, dummy, 1);
     58		if (err >= 0)
     59			return 0;
     60		usleep_range(usecs, usecs * 2);
     61	}
     62	return -ETIMEDOUT;
     63}
     64
     65static int sc18is602_txrx(struct sc18is602 *hw, struct spi_message *msg,
     66			  struct spi_transfer *t, bool do_transfer)
     67{
     68	unsigned int len = t->len;
     69	int ret;
     70
     71	if (hw->tlen == 0) {
     72		/* First byte (I2C command) is chip select */
     73		hw->buffer[0] = 1 << msg->spi->chip_select;
     74		hw->tlen = 1;
     75		hw->rindex = 0;
     76	}
     77	/*
     78	 * We can not immediately send data to the chip, since each I2C message
     79	 * resembles a full SPI message (from CS active to CS inactive).
     80	 * Enqueue messages up to the first read or until do_transfer is true.
     81	 */
     82	if (t->tx_buf) {
     83		memcpy(&hw->buffer[hw->tlen], t->tx_buf, len);
     84		hw->tlen += len;
     85		if (t->rx_buf)
     86			do_transfer = true;
     87		else
     88			hw->rindex = hw->tlen - 1;
     89	} else if (t->rx_buf) {
     90		/*
     91		 * For receive-only transfers we still need to perform a dummy
     92		 * write to receive data from the SPI chip.
     93		 * Read data starts at the end of transmit data (minus 1 to
     94		 * account for CS).
     95		 */
     96		hw->rindex = hw->tlen - 1;
     97		memset(&hw->buffer[hw->tlen], 0, len);
     98		hw->tlen += len;
     99		do_transfer = true;
    100	}
    101
    102	if (do_transfer && hw->tlen > 1) {
    103		ret = sc18is602_wait_ready(hw, SC18IS602_BUFSIZ);
    104		if (ret < 0)
    105			return ret;
    106		ret = i2c_master_send(hw->client, hw->buffer, hw->tlen);
    107		if (ret < 0)
    108			return ret;
    109		if (ret != hw->tlen)
    110			return -EIO;
    111
    112		if (t->rx_buf) {
    113			int rlen = hw->rindex + len;
    114
    115			ret = sc18is602_wait_ready(hw, hw->tlen);
    116			if (ret < 0)
    117				return ret;
    118			ret = i2c_master_recv(hw->client, hw->buffer, rlen);
    119			if (ret < 0)
    120				return ret;
    121			if (ret != rlen)
    122				return -EIO;
    123			memcpy(t->rx_buf, &hw->buffer[hw->rindex], len);
    124		}
    125		hw->tlen = 0;
    126	}
    127	return len;
    128}
    129
    130static int sc18is602_setup_transfer(struct sc18is602 *hw, u32 hz, u8 mode)
    131{
    132	u8 ctrl = 0;
    133	int ret;
    134
    135	if (mode & SPI_CPHA)
    136		ctrl |= SC18IS602_MODE_CPHA;
    137	if (mode & SPI_CPOL)
    138		ctrl |= SC18IS602_MODE_CPOL;
    139	if (mode & SPI_LSB_FIRST)
    140		ctrl |= SC18IS602_MODE_LSB_FIRST;
    141
    142	/* Find the closest clock speed */
    143	if (hz >= hw->freq / 4) {
    144		ctrl |= SC18IS602_MODE_CLOCK_DIV_4;
    145		hw->speed = hw->freq / 4;
    146	} else if (hz >= hw->freq / 16) {
    147		ctrl |= SC18IS602_MODE_CLOCK_DIV_16;
    148		hw->speed = hw->freq / 16;
    149	} else if (hz >= hw->freq / 64) {
    150		ctrl |= SC18IS602_MODE_CLOCK_DIV_64;
    151		hw->speed = hw->freq / 64;
    152	} else {
    153		ctrl |= SC18IS602_MODE_CLOCK_DIV_128;
    154		hw->speed = hw->freq / 128;
    155	}
    156
    157	/*
    158	 * Don't do anything if the control value did not change. The initial
    159	 * value of 0xff for hw->ctrl ensures that the correct mode will be set
    160	 * with the first call to this function.
    161	 */
    162	if (ctrl == hw->ctrl)
    163		return 0;
    164
    165	ret = i2c_smbus_write_byte_data(hw->client, 0xf0, ctrl);
    166	if (ret < 0)
    167		return ret;
    168
    169	hw->ctrl = ctrl;
    170
    171	return 0;
    172}
    173
    174static int sc18is602_check_transfer(struct spi_device *spi,
    175				    struct spi_transfer *t, int tlen)
    176{
    177	if (t && t->len + tlen > SC18IS602_BUFSIZ + 1)
    178		return -EINVAL;
    179
    180	return 0;
    181}
    182
    183static int sc18is602_transfer_one(struct spi_master *master,
    184				  struct spi_message *m)
    185{
    186	struct sc18is602 *hw = spi_master_get_devdata(master);
    187	struct spi_device *spi = m->spi;
    188	struct spi_transfer *t;
    189	int status = 0;
    190
    191	hw->tlen = 0;
    192	list_for_each_entry(t, &m->transfers, transfer_list) {
    193		bool do_transfer;
    194
    195		status = sc18is602_check_transfer(spi, t, hw->tlen);
    196		if (status < 0)
    197			break;
    198
    199		status = sc18is602_setup_transfer(hw, t->speed_hz, spi->mode);
    200		if (status < 0)
    201			break;
    202
    203		do_transfer = t->cs_change || list_is_last(&t->transfer_list,
    204							   &m->transfers);
    205
    206		if (t->len) {
    207			status = sc18is602_txrx(hw, m, t, do_transfer);
    208			if (status < 0)
    209				break;
    210			m->actual_length += status;
    211		}
    212		status = 0;
    213
    214		spi_transfer_delay_exec(t);
    215	}
    216	m->status = status;
    217	spi_finalize_current_message(master);
    218
    219	return status;
    220}
    221
    222static size_t sc18is602_max_transfer_size(struct spi_device *spi)
    223{
    224	return SC18IS602_BUFSIZ;
    225}
    226
    227static int sc18is602_setup(struct spi_device *spi)
    228{
    229	struct sc18is602 *hw = spi_master_get_devdata(spi->master);
    230
    231	/* SC18IS602 does not support CS2 */
    232	if (hw->id == sc18is602 && spi->chip_select == 2)
    233		return -ENXIO;
    234
    235	return 0;
    236}
    237
    238static int sc18is602_probe(struct i2c_client *client,
    239			   const struct i2c_device_id *id)
    240{
    241	struct device *dev = &client->dev;
    242	struct device_node *np = dev->of_node;
    243	struct sc18is602_platform_data *pdata = dev_get_platdata(dev);
    244	struct sc18is602 *hw;
    245	struct spi_master *master;
    246
    247	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
    248				     I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
    249		return -EINVAL;
    250
    251	master = devm_spi_alloc_master(dev, sizeof(struct sc18is602));
    252	if (!master)
    253		return -ENOMEM;
    254
    255	hw = spi_master_get_devdata(master);
    256	i2c_set_clientdata(client, hw);
    257
    258	/* assert reset and then release */
    259	hw->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
    260	if (IS_ERR(hw->reset))
    261		return PTR_ERR(hw->reset);
    262	gpiod_set_value_cansleep(hw->reset, 0);
    263
    264	hw->master = master;
    265	hw->client = client;
    266	hw->dev = dev;
    267	hw->ctrl = 0xff;
    268
    269	if (client->dev.of_node)
    270		hw->id = (enum chips)of_device_get_match_data(&client->dev);
    271	else
    272		hw->id = id->driver_data;
    273
    274	switch (hw->id) {
    275	case sc18is602:
    276	case sc18is602b:
    277		master->num_chipselect = 4;
    278		hw->freq = SC18IS602_CLOCK;
    279		break;
    280	case sc18is603:
    281		master->num_chipselect = 2;
    282		if (pdata) {
    283			hw->freq = pdata->clock_frequency;
    284		} else {
    285			const __be32 *val;
    286			int len;
    287
    288			val = of_get_property(np, "clock-frequency", &len);
    289			if (val && len >= sizeof(__be32))
    290				hw->freq = be32_to_cpup(val);
    291		}
    292		if (!hw->freq)
    293			hw->freq = SC18IS602_CLOCK;
    294		break;
    295	}
    296	master->bus_num = np ? -1 : client->adapter->nr;
    297	master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST;
    298	master->bits_per_word_mask = SPI_BPW_MASK(8);
    299	master->setup = sc18is602_setup;
    300	master->transfer_one_message = sc18is602_transfer_one;
    301	master->max_transfer_size = sc18is602_max_transfer_size;
    302	master->max_message_size = sc18is602_max_transfer_size;
    303	master->dev.of_node = np;
    304	master->min_speed_hz = hw->freq / 128;
    305	master->max_speed_hz = hw->freq / 4;
    306
    307	return devm_spi_register_master(dev, master);
    308}
    309
    310static const struct i2c_device_id sc18is602_id[] = {
    311	{ "sc18is602", sc18is602 },
    312	{ "sc18is602b", sc18is602b },
    313	{ "sc18is603", sc18is603 },
    314	{ }
    315};
    316MODULE_DEVICE_TABLE(i2c, sc18is602_id);
    317
    318static const struct of_device_id sc18is602_of_match[] = {
    319	{
    320		.compatible = "nxp,sc18is602",
    321		.data = (void *)sc18is602
    322	},
    323	{
    324		.compatible = "nxp,sc18is602b",
    325		.data = (void *)sc18is602b
    326	},
    327	{
    328		.compatible = "nxp,sc18is603",
    329		.data = (void *)sc18is603
    330	},
    331	{ },
    332};
    333MODULE_DEVICE_TABLE(of, sc18is602_of_match);
    334
    335static struct i2c_driver sc18is602_driver = {
    336	.driver = {
    337		.name = "sc18is602",
    338		.of_match_table = of_match_ptr(sc18is602_of_match),
    339	},
    340	.probe = sc18is602_probe,
    341	.id_table = sc18is602_id,
    342};
    343
    344module_i2c_driver(sc18is602_driver);
    345
    346MODULE_DESCRIPTION("SC18IS602/603 SPI Master Driver");
    347MODULE_AUTHOR("Guenter Roeck");
    348MODULE_LICENSE("GPL");