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

w5100-spi.c (11266B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Ethernet driver for the WIZnet W5100/W5200/W5500 chip.
      4 *
      5 * Copyright (C) 2016 Akinobu Mita <akinobu.mita@gmail.com>
      6 *
      7 * Datasheet:
      8 * http://www.wiznet.co.kr/wp-content/uploads/wiznethome/Chip/W5100/Document/W5100_Datasheet_v1.2.6.pdf
      9 * http://wiznethome.cafe24.com/wp-content/uploads/wiznethome/Chip/W5200/Documents/W5200_DS_V140E.pdf
     10 * http://wizwiki.net/wiki/lib/exe/fetch.php?media=products:w5500:w5500_ds_v106e_141230.pdf
     11 */
     12
     13#include <linux/kernel.h>
     14#include <linux/module.h>
     15#include <linux/delay.h>
     16#include <linux/netdevice.h>
     17#include <linux/of_net.h>
     18#include <linux/of_device.h>
     19#include <linux/spi/spi.h>
     20
     21#include "w5100.h"
     22
     23#define W5100_SPI_WRITE_OPCODE 0xf0
     24#define W5100_SPI_READ_OPCODE 0x0f
     25
     26static int w5100_spi_read(struct net_device *ndev, u32 addr)
     27{
     28	struct spi_device *spi = to_spi_device(ndev->dev.parent);
     29	u8 cmd[3] = { W5100_SPI_READ_OPCODE, addr >> 8, addr & 0xff };
     30	u8 data;
     31	int ret;
     32
     33	ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, 1);
     34
     35	return ret ? ret : data;
     36}
     37
     38static int w5100_spi_write(struct net_device *ndev, u32 addr, u8 data)
     39{
     40	struct spi_device *spi = to_spi_device(ndev->dev.parent);
     41	u8 cmd[4] = { W5100_SPI_WRITE_OPCODE, addr >> 8, addr & 0xff, data};
     42
     43	return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0);
     44}
     45
     46static int w5100_spi_read16(struct net_device *ndev, u32 addr)
     47{
     48	u16 data;
     49	int ret;
     50
     51	ret = w5100_spi_read(ndev, addr);
     52	if (ret < 0)
     53		return ret;
     54	data = ret << 8;
     55	ret = w5100_spi_read(ndev, addr + 1);
     56
     57	return ret < 0 ? ret : data | ret;
     58}
     59
     60static int w5100_spi_write16(struct net_device *ndev, u32 addr, u16 data)
     61{
     62	int ret;
     63
     64	ret = w5100_spi_write(ndev, addr, data >> 8);
     65	if (ret)
     66		return ret;
     67
     68	return w5100_spi_write(ndev, addr + 1, data & 0xff);
     69}
     70
     71static int w5100_spi_readbulk(struct net_device *ndev, u32 addr, u8 *buf,
     72			      int len)
     73{
     74	int i;
     75
     76	for (i = 0; i < len; i++) {
     77		int ret = w5100_spi_read(ndev, addr + i);
     78
     79		if (ret < 0)
     80			return ret;
     81		buf[i] = ret;
     82	}
     83
     84	return 0;
     85}
     86
     87static int w5100_spi_writebulk(struct net_device *ndev, u32 addr, const u8 *buf,
     88			       int len)
     89{
     90	int i;
     91
     92	for (i = 0; i < len; i++) {
     93		int ret = w5100_spi_write(ndev, addr + i, buf[i]);
     94
     95		if (ret)
     96			return ret;
     97	}
     98
     99	return 0;
    100}
    101
    102static const struct w5100_ops w5100_spi_ops = {
    103	.may_sleep = true,
    104	.chip_id = W5100,
    105	.read = w5100_spi_read,
    106	.write = w5100_spi_write,
    107	.read16 = w5100_spi_read16,
    108	.write16 = w5100_spi_write16,
    109	.readbulk = w5100_spi_readbulk,
    110	.writebulk = w5100_spi_writebulk,
    111};
    112
    113#define W5200_SPI_WRITE_OPCODE 0x80
    114
    115struct w5200_spi_priv {
    116	/* Serialize access to cmd_buf */
    117	struct mutex cmd_lock;
    118
    119	/* DMA (thus cache coherency maintenance) requires the
    120	 * transfer buffers to live in their own cache lines.
    121	 */
    122	u8 cmd_buf[4] ____cacheline_aligned;
    123};
    124
    125static struct w5200_spi_priv *w5200_spi_priv(struct net_device *ndev)
    126{
    127	return w5100_ops_priv(ndev);
    128}
    129
    130static int w5200_spi_init(struct net_device *ndev)
    131{
    132	struct w5200_spi_priv *spi_priv = w5200_spi_priv(ndev);
    133
    134	mutex_init(&spi_priv->cmd_lock);
    135
    136	return 0;
    137}
    138
    139static int w5200_spi_read(struct net_device *ndev, u32 addr)
    140{
    141	struct spi_device *spi = to_spi_device(ndev->dev.parent);
    142	u8 cmd[4] = { addr >> 8, addr & 0xff, 0, 1 };
    143	u8 data;
    144	int ret;
    145
    146	ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, 1);
    147
    148	return ret ? ret : data;
    149}
    150
    151static int w5200_spi_write(struct net_device *ndev, u32 addr, u8 data)
    152{
    153	struct spi_device *spi = to_spi_device(ndev->dev.parent);
    154	u8 cmd[5] = { addr >> 8, addr & 0xff, W5200_SPI_WRITE_OPCODE, 1, data };
    155
    156	return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0);
    157}
    158
    159static int w5200_spi_read16(struct net_device *ndev, u32 addr)
    160{
    161	struct spi_device *spi = to_spi_device(ndev->dev.parent);
    162	u8 cmd[4] = { addr >> 8, addr & 0xff, 0, 2 };
    163	__be16 data;
    164	int ret;
    165
    166	ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, sizeof(data));
    167
    168	return ret ? ret : be16_to_cpu(data);
    169}
    170
    171static int w5200_spi_write16(struct net_device *ndev, u32 addr, u16 data)
    172{
    173	struct spi_device *spi = to_spi_device(ndev->dev.parent);
    174	u8 cmd[6] = {
    175		addr >> 8, addr & 0xff,
    176		W5200_SPI_WRITE_OPCODE, 2,
    177		data >> 8, data & 0xff
    178	};
    179
    180	return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0);
    181}
    182
    183static int w5200_spi_readbulk(struct net_device *ndev, u32 addr, u8 *buf,
    184			      int len)
    185{
    186	struct spi_device *spi = to_spi_device(ndev->dev.parent);
    187	struct w5200_spi_priv *spi_priv = w5200_spi_priv(ndev);
    188	struct spi_transfer xfer[] = {
    189		{
    190			.tx_buf = spi_priv->cmd_buf,
    191			.len = sizeof(spi_priv->cmd_buf),
    192		},
    193		{
    194			.rx_buf = buf,
    195			.len = len,
    196		},
    197	};
    198	int ret;
    199
    200	mutex_lock(&spi_priv->cmd_lock);
    201
    202	spi_priv->cmd_buf[0] = addr >> 8;
    203	spi_priv->cmd_buf[1] = addr;
    204	spi_priv->cmd_buf[2] = len >> 8;
    205	spi_priv->cmd_buf[3] = len;
    206	ret = spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
    207
    208	mutex_unlock(&spi_priv->cmd_lock);
    209
    210	return ret;
    211}
    212
    213static int w5200_spi_writebulk(struct net_device *ndev, u32 addr, const u8 *buf,
    214			       int len)
    215{
    216	struct spi_device *spi = to_spi_device(ndev->dev.parent);
    217	struct w5200_spi_priv *spi_priv = w5200_spi_priv(ndev);
    218	struct spi_transfer xfer[] = {
    219		{
    220			.tx_buf = spi_priv->cmd_buf,
    221			.len = sizeof(spi_priv->cmd_buf),
    222		},
    223		{
    224			.tx_buf = buf,
    225			.len = len,
    226		},
    227	};
    228	int ret;
    229
    230	mutex_lock(&spi_priv->cmd_lock);
    231
    232	spi_priv->cmd_buf[0] = addr >> 8;
    233	spi_priv->cmd_buf[1] = addr;
    234	spi_priv->cmd_buf[2] = W5200_SPI_WRITE_OPCODE | (len >> 8);
    235	spi_priv->cmd_buf[3] = len;
    236	ret = spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
    237
    238	mutex_unlock(&spi_priv->cmd_lock);
    239
    240	return ret;
    241}
    242
    243static const struct w5100_ops w5200_ops = {
    244	.may_sleep = true,
    245	.chip_id = W5200,
    246	.read = w5200_spi_read,
    247	.write = w5200_spi_write,
    248	.read16 = w5200_spi_read16,
    249	.write16 = w5200_spi_write16,
    250	.readbulk = w5200_spi_readbulk,
    251	.writebulk = w5200_spi_writebulk,
    252	.init = w5200_spi_init,
    253};
    254
    255#define W5500_SPI_BLOCK_SELECT(addr) (((addr) >> 16) & 0x1f)
    256#define W5500_SPI_READ_CONTROL(addr) (W5500_SPI_BLOCK_SELECT(addr) << 3)
    257#define W5500_SPI_WRITE_CONTROL(addr)	\
    258	((W5500_SPI_BLOCK_SELECT(addr) << 3) | BIT(2))
    259
    260struct w5500_spi_priv {
    261	/* Serialize access to cmd_buf */
    262	struct mutex cmd_lock;
    263
    264	/* DMA (thus cache coherency maintenance) requires the
    265	 * transfer buffers to live in their own cache lines.
    266	 */
    267	u8 cmd_buf[3] ____cacheline_aligned;
    268};
    269
    270static struct w5500_spi_priv *w5500_spi_priv(struct net_device *ndev)
    271{
    272	return w5100_ops_priv(ndev);
    273}
    274
    275static int w5500_spi_init(struct net_device *ndev)
    276{
    277	struct w5500_spi_priv *spi_priv = w5500_spi_priv(ndev);
    278
    279	mutex_init(&spi_priv->cmd_lock);
    280
    281	return 0;
    282}
    283
    284static int w5500_spi_read(struct net_device *ndev, u32 addr)
    285{
    286	struct spi_device *spi = to_spi_device(ndev->dev.parent);
    287	u8 cmd[3] = {
    288		addr >> 8,
    289		addr,
    290		W5500_SPI_READ_CONTROL(addr)
    291	};
    292	u8 data;
    293	int ret;
    294
    295	ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, 1);
    296
    297	return ret ? ret : data;
    298}
    299
    300static int w5500_spi_write(struct net_device *ndev, u32 addr, u8 data)
    301{
    302	struct spi_device *spi = to_spi_device(ndev->dev.parent);
    303	u8 cmd[4] = {
    304		addr >> 8,
    305		addr,
    306		W5500_SPI_WRITE_CONTROL(addr),
    307		data
    308	};
    309
    310	return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0);
    311}
    312
    313static int w5500_spi_read16(struct net_device *ndev, u32 addr)
    314{
    315	struct spi_device *spi = to_spi_device(ndev->dev.parent);
    316	u8 cmd[3] = {
    317		addr >> 8,
    318		addr,
    319		W5500_SPI_READ_CONTROL(addr)
    320	};
    321	__be16 data;
    322	int ret;
    323
    324	ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, sizeof(data));
    325
    326	return ret ? ret : be16_to_cpu(data);
    327}
    328
    329static int w5500_spi_write16(struct net_device *ndev, u32 addr, u16 data)
    330{
    331	struct spi_device *spi = to_spi_device(ndev->dev.parent);
    332	u8 cmd[5] = {
    333		addr >> 8,
    334		addr,
    335		W5500_SPI_WRITE_CONTROL(addr),
    336		data >> 8,
    337		data
    338	};
    339
    340	return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0);
    341}
    342
    343static int w5500_spi_readbulk(struct net_device *ndev, u32 addr, u8 *buf,
    344			      int len)
    345{
    346	struct spi_device *spi = to_spi_device(ndev->dev.parent);
    347	struct w5500_spi_priv *spi_priv = w5500_spi_priv(ndev);
    348	struct spi_transfer xfer[] = {
    349		{
    350			.tx_buf = spi_priv->cmd_buf,
    351			.len = sizeof(spi_priv->cmd_buf),
    352		},
    353		{
    354			.rx_buf = buf,
    355			.len = len,
    356		},
    357	};
    358	int ret;
    359
    360	mutex_lock(&spi_priv->cmd_lock);
    361
    362	spi_priv->cmd_buf[0] = addr >> 8;
    363	spi_priv->cmd_buf[1] = addr;
    364	spi_priv->cmd_buf[2] = W5500_SPI_READ_CONTROL(addr);
    365	ret = spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
    366
    367	mutex_unlock(&spi_priv->cmd_lock);
    368
    369	return ret;
    370}
    371
    372static int w5500_spi_writebulk(struct net_device *ndev, u32 addr, const u8 *buf,
    373			       int len)
    374{
    375	struct spi_device *spi = to_spi_device(ndev->dev.parent);
    376	struct w5500_spi_priv *spi_priv = w5500_spi_priv(ndev);
    377	struct spi_transfer xfer[] = {
    378		{
    379			.tx_buf = spi_priv->cmd_buf,
    380			.len = sizeof(spi_priv->cmd_buf),
    381		},
    382		{
    383			.tx_buf = buf,
    384			.len = len,
    385		},
    386	};
    387	int ret;
    388
    389	mutex_lock(&spi_priv->cmd_lock);
    390
    391	spi_priv->cmd_buf[0] = addr >> 8;
    392	spi_priv->cmd_buf[1] = addr;
    393	spi_priv->cmd_buf[2] = W5500_SPI_WRITE_CONTROL(addr);
    394	ret = spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
    395
    396	mutex_unlock(&spi_priv->cmd_lock);
    397
    398	return ret;
    399}
    400
    401static const struct w5100_ops w5500_ops = {
    402	.may_sleep = true,
    403	.chip_id = W5500,
    404	.read = w5500_spi_read,
    405	.write = w5500_spi_write,
    406	.read16 = w5500_spi_read16,
    407	.write16 = w5500_spi_write16,
    408	.readbulk = w5500_spi_readbulk,
    409	.writebulk = w5500_spi_writebulk,
    410	.init = w5500_spi_init,
    411};
    412
    413static const struct of_device_id w5100_of_match[] = {
    414	{ .compatible = "wiznet,w5100", .data = (const void*)W5100, },
    415	{ .compatible = "wiznet,w5200", .data = (const void*)W5200, },
    416	{ .compatible = "wiznet,w5500", .data = (const void*)W5500, },
    417	{ },
    418};
    419MODULE_DEVICE_TABLE(of, w5100_of_match);
    420
    421static int w5100_spi_probe(struct spi_device *spi)
    422{
    423	const struct of_device_id *of_id;
    424	const struct w5100_ops *ops;
    425	kernel_ulong_t driver_data;
    426	const void *mac = NULL;
    427	u8 tmpmac[ETH_ALEN];
    428	int priv_size;
    429	int ret;
    430
    431	ret = of_get_mac_address(spi->dev.of_node, tmpmac);
    432	if (!ret)
    433		mac = tmpmac;
    434
    435	if (spi->dev.of_node) {
    436		of_id = of_match_device(w5100_of_match, &spi->dev);
    437		if (!of_id)
    438			return -ENODEV;
    439		driver_data = (kernel_ulong_t)of_id->data;
    440	} else {
    441		driver_data = spi_get_device_id(spi)->driver_data;
    442	}
    443
    444	switch (driver_data) {
    445	case W5100:
    446		ops = &w5100_spi_ops;
    447		priv_size = 0;
    448		break;
    449	case W5200:
    450		ops = &w5200_ops;
    451		priv_size = sizeof(struct w5200_spi_priv);
    452		break;
    453	case W5500:
    454		ops = &w5500_ops;
    455		priv_size = sizeof(struct w5500_spi_priv);
    456		break;
    457	default:
    458		return -EINVAL;
    459	}
    460
    461	return w5100_probe(&spi->dev, ops, priv_size, mac, spi->irq, -EINVAL);
    462}
    463
    464static void w5100_spi_remove(struct spi_device *spi)
    465{
    466	w5100_remove(&spi->dev);
    467}
    468
    469static const struct spi_device_id w5100_spi_ids[] = {
    470	{ "w5100", W5100 },
    471	{ "w5200", W5200 },
    472	{ "w5500", W5500 },
    473	{}
    474};
    475MODULE_DEVICE_TABLE(spi, w5100_spi_ids);
    476
    477static struct spi_driver w5100_spi_driver = {
    478	.driver		= {
    479		.name	= "w5100",
    480		.pm	= &w5100_pm_ops,
    481		.of_match_table = w5100_of_match,
    482	},
    483	.probe		= w5100_spi_probe,
    484	.remove		= w5100_spi_remove,
    485	.id_table	= w5100_spi_ids,
    486};
    487module_spi_driver(w5100_spi_driver);
    488
    489MODULE_DESCRIPTION("WIZnet W5100/W5200/W5500 Ethernet driver for SPI mode");
    490MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");
    491MODULE_LICENSE("GPL");