180503b23SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2630cf097SAkinobu Mita /* 335ef7d68SAkinobu Mita * Ethernet driver for the WIZnet W5100/W5200/W5500 chip. 4630cf097SAkinobu Mita * 5630cf097SAkinobu Mita * Copyright (C) 2016 Akinobu Mita <akinobu.mita@gmail.com> 6630cf097SAkinobu Mita * 70c165ff2SAkinobu Mita * Datasheet: 80c165ff2SAkinobu Mita * http://www.wiznet.co.kr/wp-content/uploads/wiznethome/Chip/W5100/Document/W5100_Datasheet_v1.2.6.pdf 90c165ff2SAkinobu Mita * http://wiznethome.cafe24.com/wp-content/uploads/wiznethome/Chip/W5200/Documents/W5200_DS_V140E.pdf 1035ef7d68SAkinobu Mita * http://wizwiki.net/wiki/lib/exe/fetch.php?media=products:w5500:w5500_ds_v106e_141230.pdf 11630cf097SAkinobu Mita */ 12630cf097SAkinobu Mita 13630cf097SAkinobu Mita #include <linux/kernel.h> 14630cf097SAkinobu Mita #include <linux/module.h> 15630cf097SAkinobu Mita #include <linux/delay.h> 16630cf097SAkinobu Mita #include <linux/netdevice.h> 17c3875ca7SAkinobu Mita #include <linux/of_net.h> 18b9dd694eSNicolas Saenz Julienne #include <linux/of_device.h> 19630cf097SAkinobu Mita #include <linux/spi/spi.h> 20630cf097SAkinobu Mita 21630cf097SAkinobu Mita #include "w5100.h" 22630cf097SAkinobu Mita 23630cf097SAkinobu Mita #define W5100_SPI_WRITE_OPCODE 0xf0 24630cf097SAkinobu Mita #define W5100_SPI_READ_OPCODE 0x0f 25630cf097SAkinobu Mita 2635ef7d68SAkinobu Mita static int w5100_spi_read(struct net_device *ndev, u32 addr) 27630cf097SAkinobu Mita { 28630cf097SAkinobu Mita struct spi_device *spi = to_spi_device(ndev->dev.parent); 29630cf097SAkinobu Mita u8 cmd[3] = { W5100_SPI_READ_OPCODE, addr >> 8, addr & 0xff }; 30630cf097SAkinobu Mita u8 data; 31630cf097SAkinobu Mita int ret; 32630cf097SAkinobu Mita 33630cf097SAkinobu Mita ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, 1); 34630cf097SAkinobu Mita 35630cf097SAkinobu Mita return ret ? ret : data; 36630cf097SAkinobu Mita } 37630cf097SAkinobu Mita 3835ef7d68SAkinobu Mita static int w5100_spi_write(struct net_device *ndev, u32 addr, u8 data) 39630cf097SAkinobu Mita { 40630cf097SAkinobu Mita struct spi_device *spi = to_spi_device(ndev->dev.parent); 41630cf097SAkinobu Mita u8 cmd[4] = { W5100_SPI_WRITE_OPCODE, addr >> 8, addr & 0xff, data}; 42630cf097SAkinobu Mita 43630cf097SAkinobu Mita return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0); 44630cf097SAkinobu Mita } 45630cf097SAkinobu Mita 4635ef7d68SAkinobu Mita static int w5100_spi_read16(struct net_device *ndev, u32 addr) 47630cf097SAkinobu Mita { 48630cf097SAkinobu Mita u16 data; 49630cf097SAkinobu Mita int ret; 50630cf097SAkinobu Mita 51630cf097SAkinobu Mita ret = w5100_spi_read(ndev, addr); 52630cf097SAkinobu Mita if (ret < 0) 53630cf097SAkinobu Mita return ret; 54630cf097SAkinobu Mita data = ret << 8; 55630cf097SAkinobu Mita ret = w5100_spi_read(ndev, addr + 1); 56630cf097SAkinobu Mita 57630cf097SAkinobu Mita return ret < 0 ? ret : data | ret; 58630cf097SAkinobu Mita } 59630cf097SAkinobu Mita 6035ef7d68SAkinobu Mita static int w5100_spi_write16(struct net_device *ndev, u32 addr, u16 data) 61630cf097SAkinobu Mita { 62630cf097SAkinobu Mita int ret; 63630cf097SAkinobu Mita 64630cf097SAkinobu Mita ret = w5100_spi_write(ndev, addr, data >> 8); 65630cf097SAkinobu Mita if (ret) 66630cf097SAkinobu Mita return ret; 67630cf097SAkinobu Mita 68630cf097SAkinobu Mita return w5100_spi_write(ndev, addr + 1, data & 0xff); 69630cf097SAkinobu Mita } 70630cf097SAkinobu Mita 7135ef7d68SAkinobu Mita static int w5100_spi_readbulk(struct net_device *ndev, u32 addr, u8 *buf, 72630cf097SAkinobu Mita int len) 73630cf097SAkinobu Mita { 74630cf097SAkinobu Mita int i; 75630cf097SAkinobu Mita 76630cf097SAkinobu Mita for (i = 0; i < len; i++) { 77630cf097SAkinobu Mita int ret = w5100_spi_read(ndev, addr + i); 78630cf097SAkinobu Mita 79630cf097SAkinobu Mita if (ret < 0) 80630cf097SAkinobu Mita return ret; 81630cf097SAkinobu Mita buf[i] = ret; 82630cf097SAkinobu Mita } 83630cf097SAkinobu Mita 84630cf097SAkinobu Mita return 0; 85630cf097SAkinobu Mita } 86630cf097SAkinobu Mita 8735ef7d68SAkinobu Mita static int w5100_spi_writebulk(struct net_device *ndev, u32 addr, const u8 *buf, 88630cf097SAkinobu Mita int len) 89630cf097SAkinobu Mita { 90630cf097SAkinobu Mita int i; 91630cf097SAkinobu Mita 92630cf097SAkinobu Mita for (i = 0; i < len; i++) { 93630cf097SAkinobu Mita int ret = w5100_spi_write(ndev, addr + i, buf[i]); 94630cf097SAkinobu Mita 95630cf097SAkinobu Mita if (ret) 96630cf097SAkinobu Mita return ret; 97630cf097SAkinobu Mita } 98630cf097SAkinobu Mita 99630cf097SAkinobu Mita return 0; 100630cf097SAkinobu Mita } 101630cf097SAkinobu Mita 102630cf097SAkinobu Mita static const struct w5100_ops w5100_spi_ops = { 103630cf097SAkinobu Mita .may_sleep = true, 1040c165ff2SAkinobu Mita .chip_id = W5100, 105630cf097SAkinobu Mita .read = w5100_spi_read, 106630cf097SAkinobu Mita .write = w5100_spi_write, 107630cf097SAkinobu Mita .read16 = w5100_spi_read16, 108630cf097SAkinobu Mita .write16 = w5100_spi_write16, 109630cf097SAkinobu Mita .readbulk = w5100_spi_readbulk, 110630cf097SAkinobu Mita .writebulk = w5100_spi_writebulk, 111630cf097SAkinobu Mita }; 112630cf097SAkinobu Mita 1130c165ff2SAkinobu Mita #define W5200_SPI_WRITE_OPCODE 0x80 1140c165ff2SAkinobu Mita 1150c165ff2SAkinobu Mita struct w5200_spi_priv { 1160c165ff2SAkinobu Mita /* Serialize access to cmd_buf */ 1170c165ff2SAkinobu Mita struct mutex cmd_lock; 1180c165ff2SAkinobu Mita 1190c165ff2SAkinobu Mita /* DMA (thus cache coherency maintenance) requires the 1200c165ff2SAkinobu Mita * transfer buffers to live in their own cache lines. 1210c165ff2SAkinobu Mita */ 1220c165ff2SAkinobu Mita u8 cmd_buf[4] ____cacheline_aligned; 1230c165ff2SAkinobu Mita }; 1240c165ff2SAkinobu Mita 1250c165ff2SAkinobu Mita static struct w5200_spi_priv *w5200_spi_priv(struct net_device *ndev) 1260c165ff2SAkinobu Mita { 1270c165ff2SAkinobu Mita return w5100_ops_priv(ndev); 1280c165ff2SAkinobu Mita } 1290c165ff2SAkinobu Mita 1300c165ff2SAkinobu Mita static int w5200_spi_init(struct net_device *ndev) 1310c165ff2SAkinobu Mita { 1320c165ff2SAkinobu Mita struct w5200_spi_priv *spi_priv = w5200_spi_priv(ndev); 1330c165ff2SAkinobu Mita 1340c165ff2SAkinobu Mita mutex_init(&spi_priv->cmd_lock); 1350c165ff2SAkinobu Mita 1360c165ff2SAkinobu Mita return 0; 1370c165ff2SAkinobu Mita } 1380c165ff2SAkinobu Mita 13935ef7d68SAkinobu Mita static int w5200_spi_read(struct net_device *ndev, u32 addr) 1400c165ff2SAkinobu Mita { 1410c165ff2SAkinobu Mita struct spi_device *spi = to_spi_device(ndev->dev.parent); 1420c165ff2SAkinobu Mita u8 cmd[4] = { addr >> 8, addr & 0xff, 0, 1 }; 1430c165ff2SAkinobu Mita u8 data; 1440c165ff2SAkinobu Mita int ret; 1450c165ff2SAkinobu Mita 1460c165ff2SAkinobu Mita ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, 1); 1470c165ff2SAkinobu Mita 1480c165ff2SAkinobu Mita return ret ? ret : data; 1490c165ff2SAkinobu Mita } 1500c165ff2SAkinobu Mita 15135ef7d68SAkinobu Mita static int w5200_spi_write(struct net_device *ndev, u32 addr, u8 data) 1520c165ff2SAkinobu Mita { 1530c165ff2SAkinobu Mita struct spi_device *spi = to_spi_device(ndev->dev.parent); 1540c165ff2SAkinobu Mita u8 cmd[5] = { addr >> 8, addr & 0xff, W5200_SPI_WRITE_OPCODE, 1, data }; 1550c165ff2SAkinobu Mita 1560c165ff2SAkinobu Mita return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0); 1570c165ff2SAkinobu Mita } 1580c165ff2SAkinobu Mita 15935ef7d68SAkinobu Mita static int w5200_spi_read16(struct net_device *ndev, u32 addr) 1600c165ff2SAkinobu Mita { 1610c165ff2SAkinobu Mita struct spi_device *spi = to_spi_device(ndev->dev.parent); 1620c165ff2SAkinobu Mita u8 cmd[4] = { addr >> 8, addr & 0xff, 0, 2 }; 1630c165ff2SAkinobu Mita __be16 data; 1640c165ff2SAkinobu Mita int ret; 1650c165ff2SAkinobu Mita 1660c165ff2SAkinobu Mita ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, sizeof(data)); 1670c165ff2SAkinobu Mita 1680c165ff2SAkinobu Mita return ret ? ret : be16_to_cpu(data); 1690c165ff2SAkinobu Mita } 1700c165ff2SAkinobu Mita 17135ef7d68SAkinobu Mita static int w5200_spi_write16(struct net_device *ndev, u32 addr, u16 data) 1720c165ff2SAkinobu Mita { 1730c165ff2SAkinobu Mita struct spi_device *spi = to_spi_device(ndev->dev.parent); 1740c165ff2SAkinobu Mita u8 cmd[6] = { 1750c165ff2SAkinobu Mita addr >> 8, addr & 0xff, 1760c165ff2SAkinobu Mita W5200_SPI_WRITE_OPCODE, 2, 1770c165ff2SAkinobu Mita data >> 8, data & 0xff 1780c165ff2SAkinobu Mita }; 1790c165ff2SAkinobu Mita 1800c165ff2SAkinobu Mita return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0); 1810c165ff2SAkinobu Mita } 1820c165ff2SAkinobu Mita 18335ef7d68SAkinobu Mita static int w5200_spi_readbulk(struct net_device *ndev, u32 addr, u8 *buf, 1840c165ff2SAkinobu Mita int len) 1850c165ff2SAkinobu Mita { 1860c165ff2SAkinobu Mita struct spi_device *spi = to_spi_device(ndev->dev.parent); 1870c165ff2SAkinobu Mita struct w5200_spi_priv *spi_priv = w5200_spi_priv(ndev); 1880c165ff2SAkinobu Mita struct spi_transfer xfer[] = { 1890c165ff2SAkinobu Mita { 1900c165ff2SAkinobu Mita .tx_buf = spi_priv->cmd_buf, 1910c165ff2SAkinobu Mita .len = sizeof(spi_priv->cmd_buf), 1920c165ff2SAkinobu Mita }, 1930c165ff2SAkinobu Mita { 1940c165ff2SAkinobu Mita .rx_buf = buf, 1950c165ff2SAkinobu Mita .len = len, 1960c165ff2SAkinobu Mita }, 1970c165ff2SAkinobu Mita }; 1980c165ff2SAkinobu Mita int ret; 1990c165ff2SAkinobu Mita 2000c165ff2SAkinobu Mita mutex_lock(&spi_priv->cmd_lock); 2010c165ff2SAkinobu Mita 2020c165ff2SAkinobu Mita spi_priv->cmd_buf[0] = addr >> 8; 2030c165ff2SAkinobu Mita spi_priv->cmd_buf[1] = addr; 2040c165ff2SAkinobu Mita spi_priv->cmd_buf[2] = len >> 8; 2050c165ff2SAkinobu Mita spi_priv->cmd_buf[3] = len; 2060c165ff2SAkinobu Mita ret = spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer)); 2070c165ff2SAkinobu Mita 2080c165ff2SAkinobu Mita mutex_unlock(&spi_priv->cmd_lock); 2090c165ff2SAkinobu Mita 2100c165ff2SAkinobu Mita return ret; 2110c165ff2SAkinobu Mita } 2120c165ff2SAkinobu Mita 21335ef7d68SAkinobu Mita static int w5200_spi_writebulk(struct net_device *ndev, u32 addr, const u8 *buf, 2140c165ff2SAkinobu Mita int len) 2150c165ff2SAkinobu Mita { 2160c165ff2SAkinobu Mita struct spi_device *spi = to_spi_device(ndev->dev.parent); 2170c165ff2SAkinobu Mita struct w5200_spi_priv *spi_priv = w5200_spi_priv(ndev); 2180c165ff2SAkinobu Mita struct spi_transfer xfer[] = { 2190c165ff2SAkinobu Mita { 2200c165ff2SAkinobu Mita .tx_buf = spi_priv->cmd_buf, 2210c165ff2SAkinobu Mita .len = sizeof(spi_priv->cmd_buf), 2220c165ff2SAkinobu Mita }, 2230c165ff2SAkinobu Mita { 2240c165ff2SAkinobu Mita .tx_buf = buf, 2250c165ff2SAkinobu Mita .len = len, 2260c165ff2SAkinobu Mita }, 2270c165ff2SAkinobu Mita }; 2280c165ff2SAkinobu Mita int ret; 2290c165ff2SAkinobu Mita 2300c165ff2SAkinobu Mita mutex_lock(&spi_priv->cmd_lock); 2310c165ff2SAkinobu Mita 2320c165ff2SAkinobu Mita spi_priv->cmd_buf[0] = addr >> 8; 2330c165ff2SAkinobu Mita spi_priv->cmd_buf[1] = addr; 2340c165ff2SAkinobu Mita spi_priv->cmd_buf[2] = W5200_SPI_WRITE_OPCODE | (len >> 8); 2350c165ff2SAkinobu Mita spi_priv->cmd_buf[3] = len; 2360c165ff2SAkinobu Mita ret = spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer)); 2370c165ff2SAkinobu Mita 2380c165ff2SAkinobu Mita mutex_unlock(&spi_priv->cmd_lock); 2390c165ff2SAkinobu Mita 2400c165ff2SAkinobu Mita return ret; 2410c165ff2SAkinobu Mita } 2420c165ff2SAkinobu Mita 2430c165ff2SAkinobu Mita static const struct w5100_ops w5200_ops = { 2440c165ff2SAkinobu Mita .may_sleep = true, 2450c165ff2SAkinobu Mita .chip_id = W5200, 2460c165ff2SAkinobu Mita .read = w5200_spi_read, 2470c165ff2SAkinobu Mita .write = w5200_spi_write, 2480c165ff2SAkinobu Mita .read16 = w5200_spi_read16, 2490c165ff2SAkinobu Mita .write16 = w5200_spi_write16, 2500c165ff2SAkinobu Mita .readbulk = w5200_spi_readbulk, 2510c165ff2SAkinobu Mita .writebulk = w5200_spi_writebulk, 2520c165ff2SAkinobu Mita .init = w5200_spi_init, 2530c165ff2SAkinobu Mita }; 2540c165ff2SAkinobu Mita 25535ef7d68SAkinobu Mita #define W5500_SPI_BLOCK_SELECT(addr) (((addr) >> 16) & 0x1f) 25635ef7d68SAkinobu Mita #define W5500_SPI_READ_CONTROL(addr) (W5500_SPI_BLOCK_SELECT(addr) << 3) 25735ef7d68SAkinobu Mita #define W5500_SPI_WRITE_CONTROL(addr) \ 25835ef7d68SAkinobu Mita ((W5500_SPI_BLOCK_SELECT(addr) << 3) | BIT(2)) 25935ef7d68SAkinobu Mita 26035ef7d68SAkinobu Mita struct w5500_spi_priv { 26135ef7d68SAkinobu Mita /* Serialize access to cmd_buf */ 26235ef7d68SAkinobu Mita struct mutex cmd_lock; 26335ef7d68SAkinobu Mita 26435ef7d68SAkinobu Mita /* DMA (thus cache coherency maintenance) requires the 26535ef7d68SAkinobu Mita * transfer buffers to live in their own cache lines. 26635ef7d68SAkinobu Mita */ 26735ef7d68SAkinobu Mita u8 cmd_buf[3] ____cacheline_aligned; 26835ef7d68SAkinobu Mita }; 26935ef7d68SAkinobu Mita 27035ef7d68SAkinobu Mita static struct w5500_spi_priv *w5500_spi_priv(struct net_device *ndev) 27135ef7d68SAkinobu Mita { 27235ef7d68SAkinobu Mita return w5100_ops_priv(ndev); 27335ef7d68SAkinobu Mita } 27435ef7d68SAkinobu Mita 27535ef7d68SAkinobu Mita static int w5500_spi_init(struct net_device *ndev) 27635ef7d68SAkinobu Mita { 27735ef7d68SAkinobu Mita struct w5500_spi_priv *spi_priv = w5500_spi_priv(ndev); 27835ef7d68SAkinobu Mita 27935ef7d68SAkinobu Mita mutex_init(&spi_priv->cmd_lock); 28035ef7d68SAkinobu Mita 28135ef7d68SAkinobu Mita return 0; 28235ef7d68SAkinobu Mita } 28335ef7d68SAkinobu Mita 28435ef7d68SAkinobu Mita static int w5500_spi_read(struct net_device *ndev, u32 addr) 28535ef7d68SAkinobu Mita { 28635ef7d68SAkinobu Mita struct spi_device *spi = to_spi_device(ndev->dev.parent); 28735ef7d68SAkinobu Mita u8 cmd[3] = { 28835ef7d68SAkinobu Mita addr >> 8, 28935ef7d68SAkinobu Mita addr, 29035ef7d68SAkinobu Mita W5500_SPI_READ_CONTROL(addr) 29135ef7d68SAkinobu Mita }; 29235ef7d68SAkinobu Mita u8 data; 29335ef7d68SAkinobu Mita int ret; 29435ef7d68SAkinobu Mita 29535ef7d68SAkinobu Mita ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, 1); 29635ef7d68SAkinobu Mita 29735ef7d68SAkinobu Mita return ret ? ret : data; 29835ef7d68SAkinobu Mita } 29935ef7d68SAkinobu Mita 30035ef7d68SAkinobu Mita static int w5500_spi_write(struct net_device *ndev, u32 addr, u8 data) 30135ef7d68SAkinobu Mita { 30235ef7d68SAkinobu Mita struct spi_device *spi = to_spi_device(ndev->dev.parent); 30335ef7d68SAkinobu Mita u8 cmd[4] = { 30435ef7d68SAkinobu Mita addr >> 8, 30535ef7d68SAkinobu Mita addr, 30635ef7d68SAkinobu Mita W5500_SPI_WRITE_CONTROL(addr), 30735ef7d68SAkinobu Mita data 30835ef7d68SAkinobu Mita }; 30935ef7d68SAkinobu Mita 31035ef7d68SAkinobu Mita return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0); 31135ef7d68SAkinobu Mita } 31235ef7d68SAkinobu Mita 31335ef7d68SAkinobu Mita static int w5500_spi_read16(struct net_device *ndev, u32 addr) 31435ef7d68SAkinobu Mita { 31535ef7d68SAkinobu Mita struct spi_device *spi = to_spi_device(ndev->dev.parent); 31635ef7d68SAkinobu Mita u8 cmd[3] = { 31735ef7d68SAkinobu Mita addr >> 8, 31835ef7d68SAkinobu Mita addr, 31935ef7d68SAkinobu Mita W5500_SPI_READ_CONTROL(addr) 32035ef7d68SAkinobu Mita }; 32135ef7d68SAkinobu Mita __be16 data; 32235ef7d68SAkinobu Mita int ret; 32335ef7d68SAkinobu Mita 32435ef7d68SAkinobu Mita ret = spi_write_then_read(spi, cmd, sizeof(cmd), &data, sizeof(data)); 32535ef7d68SAkinobu Mita 32635ef7d68SAkinobu Mita return ret ? ret : be16_to_cpu(data); 32735ef7d68SAkinobu Mita } 32835ef7d68SAkinobu Mita 32935ef7d68SAkinobu Mita static int w5500_spi_write16(struct net_device *ndev, u32 addr, u16 data) 33035ef7d68SAkinobu Mita { 33135ef7d68SAkinobu Mita struct spi_device *spi = to_spi_device(ndev->dev.parent); 33235ef7d68SAkinobu Mita u8 cmd[5] = { 33335ef7d68SAkinobu Mita addr >> 8, 33435ef7d68SAkinobu Mita addr, 33535ef7d68SAkinobu Mita W5500_SPI_WRITE_CONTROL(addr), 33635ef7d68SAkinobu Mita data >> 8, 33735ef7d68SAkinobu Mita data 33835ef7d68SAkinobu Mita }; 33935ef7d68SAkinobu Mita 34035ef7d68SAkinobu Mita return spi_write_then_read(spi, cmd, sizeof(cmd), NULL, 0); 34135ef7d68SAkinobu Mita } 34235ef7d68SAkinobu Mita 34335ef7d68SAkinobu Mita static int w5500_spi_readbulk(struct net_device *ndev, u32 addr, u8 *buf, 34435ef7d68SAkinobu Mita int len) 34535ef7d68SAkinobu Mita { 34635ef7d68SAkinobu Mita struct spi_device *spi = to_spi_device(ndev->dev.parent); 34735ef7d68SAkinobu Mita struct w5500_spi_priv *spi_priv = w5500_spi_priv(ndev); 34835ef7d68SAkinobu Mita struct spi_transfer xfer[] = { 34935ef7d68SAkinobu Mita { 35035ef7d68SAkinobu Mita .tx_buf = spi_priv->cmd_buf, 35135ef7d68SAkinobu Mita .len = sizeof(spi_priv->cmd_buf), 35235ef7d68SAkinobu Mita }, 35335ef7d68SAkinobu Mita { 35435ef7d68SAkinobu Mita .rx_buf = buf, 35535ef7d68SAkinobu Mita .len = len, 35635ef7d68SAkinobu Mita }, 35735ef7d68SAkinobu Mita }; 35835ef7d68SAkinobu Mita int ret; 35935ef7d68SAkinobu Mita 36035ef7d68SAkinobu Mita mutex_lock(&spi_priv->cmd_lock); 36135ef7d68SAkinobu Mita 36235ef7d68SAkinobu Mita spi_priv->cmd_buf[0] = addr >> 8; 36335ef7d68SAkinobu Mita spi_priv->cmd_buf[1] = addr; 36435ef7d68SAkinobu Mita spi_priv->cmd_buf[2] = W5500_SPI_READ_CONTROL(addr); 36535ef7d68SAkinobu Mita ret = spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer)); 36635ef7d68SAkinobu Mita 36735ef7d68SAkinobu Mita mutex_unlock(&spi_priv->cmd_lock); 36835ef7d68SAkinobu Mita 36935ef7d68SAkinobu Mita return ret; 37035ef7d68SAkinobu Mita } 37135ef7d68SAkinobu Mita 37235ef7d68SAkinobu Mita static int w5500_spi_writebulk(struct net_device *ndev, u32 addr, const u8 *buf, 37335ef7d68SAkinobu Mita int len) 37435ef7d68SAkinobu Mita { 37535ef7d68SAkinobu Mita struct spi_device *spi = to_spi_device(ndev->dev.parent); 37635ef7d68SAkinobu Mita struct w5500_spi_priv *spi_priv = w5500_spi_priv(ndev); 37735ef7d68SAkinobu Mita struct spi_transfer xfer[] = { 37835ef7d68SAkinobu Mita { 37935ef7d68SAkinobu Mita .tx_buf = spi_priv->cmd_buf, 38035ef7d68SAkinobu Mita .len = sizeof(spi_priv->cmd_buf), 38135ef7d68SAkinobu Mita }, 38235ef7d68SAkinobu Mita { 38335ef7d68SAkinobu Mita .tx_buf = buf, 38435ef7d68SAkinobu Mita .len = len, 38535ef7d68SAkinobu Mita }, 38635ef7d68SAkinobu Mita }; 38735ef7d68SAkinobu Mita int ret; 38835ef7d68SAkinobu Mita 38935ef7d68SAkinobu Mita mutex_lock(&spi_priv->cmd_lock); 39035ef7d68SAkinobu Mita 39135ef7d68SAkinobu Mita spi_priv->cmd_buf[0] = addr >> 8; 39235ef7d68SAkinobu Mita spi_priv->cmd_buf[1] = addr; 39335ef7d68SAkinobu Mita spi_priv->cmd_buf[2] = W5500_SPI_WRITE_CONTROL(addr); 39435ef7d68SAkinobu Mita ret = spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer)); 39535ef7d68SAkinobu Mita 39635ef7d68SAkinobu Mita mutex_unlock(&spi_priv->cmd_lock); 39735ef7d68SAkinobu Mita 39835ef7d68SAkinobu Mita return ret; 39935ef7d68SAkinobu Mita } 40035ef7d68SAkinobu Mita 40135ef7d68SAkinobu Mita static const struct w5100_ops w5500_ops = { 40235ef7d68SAkinobu Mita .may_sleep = true, 40335ef7d68SAkinobu Mita .chip_id = W5500, 40435ef7d68SAkinobu Mita .read = w5500_spi_read, 40535ef7d68SAkinobu Mita .write = w5500_spi_write, 40635ef7d68SAkinobu Mita .read16 = w5500_spi_read16, 40735ef7d68SAkinobu Mita .write16 = w5500_spi_write16, 40835ef7d68SAkinobu Mita .readbulk = w5500_spi_readbulk, 40935ef7d68SAkinobu Mita .writebulk = w5500_spi_writebulk, 41035ef7d68SAkinobu Mita .init = w5500_spi_init, 41135ef7d68SAkinobu Mita }; 41235ef7d68SAkinobu Mita 413b9dd694eSNicolas Saenz Julienne static const struct of_device_id w5100_of_match[] = { 414b9dd694eSNicolas Saenz Julienne { .compatible = "wiznet,w5100", .data = (const void*)W5100, }, 415b9dd694eSNicolas Saenz Julienne { .compatible = "wiznet,w5200", .data = (const void*)W5200, }, 416b9dd694eSNicolas Saenz Julienne { .compatible = "wiznet,w5500", .data = (const void*)W5500, }, 417b9dd694eSNicolas Saenz Julienne { }, 418b9dd694eSNicolas Saenz Julienne }; 419b9dd694eSNicolas Saenz Julienne MODULE_DEVICE_TABLE(of, w5100_of_match); 420b9dd694eSNicolas Saenz Julienne 421630cf097SAkinobu Mita static int w5100_spi_probe(struct spi_device *spi) 422630cf097SAkinobu Mita { 423b9dd694eSNicolas Saenz Julienne const struct of_device_id *of_id; 4240c165ff2SAkinobu Mita const struct w5100_ops *ops; 425b9dd694eSNicolas Saenz Julienne kernel_ulong_t driver_data; 4260c165ff2SAkinobu Mita int priv_size; 427c3875ca7SAkinobu Mita const void *mac = of_get_mac_address(spi->dev.of_node); 4280c165ff2SAkinobu Mita 429b9dd694eSNicolas Saenz Julienne if (spi->dev.of_node) { 430b9dd694eSNicolas Saenz Julienne of_id = of_match_device(w5100_of_match, &spi->dev); 431b9dd694eSNicolas Saenz Julienne if (!of_id) 432b9dd694eSNicolas Saenz Julienne return -ENODEV; 433b9dd694eSNicolas Saenz Julienne driver_data = (kernel_ulong_t)of_id->data; 434b9dd694eSNicolas Saenz Julienne } else { 435b9dd694eSNicolas Saenz Julienne driver_data = spi_get_device_id(spi)->driver_data; 436b9dd694eSNicolas Saenz Julienne } 437b9dd694eSNicolas Saenz Julienne 438b9dd694eSNicolas Saenz Julienne switch (driver_data) { 4390c165ff2SAkinobu Mita case W5100: 4400c165ff2SAkinobu Mita ops = &w5100_spi_ops; 4410c165ff2SAkinobu Mita priv_size = 0; 4420c165ff2SAkinobu Mita break; 4430c165ff2SAkinobu Mita case W5200: 4440c165ff2SAkinobu Mita ops = &w5200_ops; 4450c165ff2SAkinobu Mita priv_size = sizeof(struct w5200_spi_priv); 4460c165ff2SAkinobu Mita break; 44735ef7d68SAkinobu Mita case W5500: 44835ef7d68SAkinobu Mita ops = &w5500_ops; 44935ef7d68SAkinobu Mita priv_size = sizeof(struct w5500_spi_priv); 45035ef7d68SAkinobu Mita break; 4510c165ff2SAkinobu Mita default: 4520c165ff2SAkinobu Mita return -EINVAL; 4530c165ff2SAkinobu Mita } 4540c165ff2SAkinobu Mita 455c3875ca7SAkinobu Mita return w5100_probe(&spi->dev, ops, priv_size, mac, spi->irq, -EINVAL); 456630cf097SAkinobu Mita } 457630cf097SAkinobu Mita 458630cf097SAkinobu Mita static int w5100_spi_remove(struct spi_device *spi) 459630cf097SAkinobu Mita { 460630cf097SAkinobu Mita return w5100_remove(&spi->dev); 461630cf097SAkinobu Mita } 462630cf097SAkinobu Mita 463630cf097SAkinobu Mita static const struct spi_device_id w5100_spi_ids[] = { 4640c165ff2SAkinobu Mita { "w5100", W5100 }, 4650c165ff2SAkinobu Mita { "w5200", W5200 }, 46635ef7d68SAkinobu Mita { "w5500", W5500 }, 467630cf097SAkinobu Mita {} 468630cf097SAkinobu Mita }; 469630cf097SAkinobu Mita MODULE_DEVICE_TABLE(spi, w5100_spi_ids); 470630cf097SAkinobu Mita 471630cf097SAkinobu Mita static struct spi_driver w5100_spi_driver = { 472630cf097SAkinobu Mita .driver = { 473630cf097SAkinobu Mita .name = "w5100", 474630cf097SAkinobu Mita .pm = &w5100_pm_ops, 475b9dd694eSNicolas Saenz Julienne .of_match_table = w5100_of_match, 476630cf097SAkinobu Mita }, 477630cf097SAkinobu Mita .probe = w5100_spi_probe, 478630cf097SAkinobu Mita .remove = w5100_spi_remove, 479630cf097SAkinobu Mita .id_table = w5100_spi_ids, 480630cf097SAkinobu Mita }; 481630cf097SAkinobu Mita module_spi_driver(w5100_spi_driver); 482630cf097SAkinobu Mita 48335ef7d68SAkinobu Mita MODULE_DESCRIPTION("WIZnet W5100/W5200/W5500 Ethernet driver for SPI mode"); 484630cf097SAkinobu Mita MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>"); 485630cf097SAkinobu Mita MODULE_LICENSE("GPL"); 486