1a97c69baSŁukasz Stelmach // SPDX-License-Identifier: GPL-2.0-only 2a97c69baSŁukasz Stelmach /* 3a97c69baSŁukasz Stelmach * Copyright (c) 2010 ASIX Electronics Corporation 4a97c69baSŁukasz Stelmach * Copyright (c) 2020 Samsung Electronics Co., Ltd. 5a97c69baSŁukasz Stelmach * 6a97c69baSŁukasz Stelmach * ASIX AX88796C SPI Fast Ethernet Linux driver 7a97c69baSŁukasz Stelmach */ 8a97c69baSŁukasz Stelmach 9a97c69baSŁukasz Stelmach #define pr_fmt(fmt) "ax88796c: " fmt 10a97c69baSŁukasz Stelmach 11a97c69baSŁukasz Stelmach #include <linux/string.h> 12a97c69baSŁukasz Stelmach #include <linux/spi/spi.h> 13a97c69baSŁukasz Stelmach 14a97c69baSŁukasz Stelmach #include "ax88796c_spi.h" 15a97c69baSŁukasz Stelmach 16a97c69baSŁukasz Stelmach const u8 ax88796c_rx_cmd_buf[5] = {AX_SPICMD_READ_RXQ, 0xFF, 0xFF, 0xFF, 0xFF}; 17a97c69baSŁukasz Stelmach const u8 ax88796c_tx_cmd_buf[4] = {AX_SPICMD_WRITE_TXQ, 0xFF, 0xFF, 0xFF}; 18a97c69baSŁukasz Stelmach 19a97c69baSŁukasz Stelmach /* driver bus management functions */ 20a97c69baSŁukasz Stelmach int axspi_wakeup(struct axspi_data *ax_spi) 21a97c69baSŁukasz Stelmach { 22a97c69baSŁukasz Stelmach int ret; 23a97c69baSŁukasz Stelmach 24a97c69baSŁukasz Stelmach ax_spi->cmd_buf[0] = AX_SPICMD_EXIT_PWD; /* OP */ 25a97c69baSŁukasz Stelmach ret = spi_write(ax_spi->spi, ax_spi->cmd_buf, 1); 26a97c69baSŁukasz Stelmach if (ret) 27a97c69baSŁukasz Stelmach dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret); 28a97c69baSŁukasz Stelmach return ret; 29a97c69baSŁukasz Stelmach } 30a97c69baSŁukasz Stelmach 31a97c69baSŁukasz Stelmach int axspi_read_status(struct axspi_data *ax_spi, struct spi_status *status) 32a97c69baSŁukasz Stelmach { 33a97c69baSŁukasz Stelmach int ret; 34a97c69baSŁukasz Stelmach 35a97c69baSŁukasz Stelmach /* OP */ 36a97c69baSŁukasz Stelmach ax_spi->cmd_buf[0] = AX_SPICMD_READ_STATUS; 37*f93fd0caSNicolas Iooss ret = spi_write_then_read(ax_spi->spi, ax_spi->cmd_buf, 1, (u8 *)status, 3); 38a97c69baSŁukasz Stelmach if (ret) 39a97c69baSŁukasz Stelmach dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret); 40a97c69baSŁukasz Stelmach else 41a97c69baSŁukasz Stelmach le16_to_cpus(&status->isr); 42a97c69baSŁukasz Stelmach 43a97c69baSŁukasz Stelmach return ret; 44a97c69baSŁukasz Stelmach } 45a97c69baSŁukasz Stelmach 46a97c69baSŁukasz Stelmach int axspi_read_rxq(struct axspi_data *ax_spi, void *data, int len) 47a97c69baSŁukasz Stelmach { 48a97c69baSŁukasz Stelmach struct spi_transfer *xfer = ax_spi->spi_rx_xfer; 49a97c69baSŁukasz Stelmach int ret; 50a97c69baSŁukasz Stelmach 51a97c69baSŁukasz Stelmach memcpy(ax_spi->cmd_buf, ax88796c_rx_cmd_buf, 5); 52a97c69baSŁukasz Stelmach 53a97c69baSŁukasz Stelmach xfer->tx_buf = ax_spi->cmd_buf; 54a97c69baSŁukasz Stelmach xfer->rx_buf = NULL; 55a97c69baSŁukasz Stelmach xfer->len = ax_spi->comp ? 2 : 5; 56a97c69baSŁukasz Stelmach xfer->bits_per_word = 8; 57a97c69baSŁukasz Stelmach spi_message_add_tail(xfer, &ax_spi->rx_msg); 58a97c69baSŁukasz Stelmach 59a97c69baSŁukasz Stelmach xfer++; 60a97c69baSŁukasz Stelmach xfer->rx_buf = data; 61a97c69baSŁukasz Stelmach xfer->tx_buf = NULL; 62a97c69baSŁukasz Stelmach xfer->len = len; 63a97c69baSŁukasz Stelmach xfer->bits_per_word = 8; 64a97c69baSŁukasz Stelmach spi_message_add_tail(xfer, &ax_spi->rx_msg); 65a97c69baSŁukasz Stelmach ret = spi_sync(ax_spi->spi, &ax_spi->rx_msg); 66a97c69baSŁukasz Stelmach if (ret) 67a97c69baSŁukasz Stelmach dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret); 68a97c69baSŁukasz Stelmach 69a97c69baSŁukasz Stelmach return ret; 70a97c69baSŁukasz Stelmach } 71a97c69baSŁukasz Stelmach 72a97c69baSŁukasz Stelmach int axspi_write_txq(const struct axspi_data *ax_spi, void *data, int len) 73a97c69baSŁukasz Stelmach { 74a97c69baSŁukasz Stelmach return spi_write(ax_spi->spi, data, len); 75a97c69baSŁukasz Stelmach } 76a97c69baSŁukasz Stelmach 77a97c69baSŁukasz Stelmach u16 axspi_read_reg(struct axspi_data *ax_spi, u8 reg) 78a97c69baSŁukasz Stelmach { 79a97c69baSŁukasz Stelmach int ret; 80a97c69baSŁukasz Stelmach int len = ax_spi->comp ? 3 : 4; 81a97c69baSŁukasz Stelmach 82a97c69baSŁukasz Stelmach ax_spi->cmd_buf[0] = 0x03; /* OP code read register */ 83a97c69baSŁukasz Stelmach ax_spi->cmd_buf[1] = reg; /* register address */ 84a97c69baSŁukasz Stelmach ax_spi->cmd_buf[2] = 0xFF; /* dumy cycle */ 85a97c69baSŁukasz Stelmach ax_spi->cmd_buf[3] = 0xFF; /* dumy cycle */ 86a97c69baSŁukasz Stelmach ret = spi_write_then_read(ax_spi->spi, 87a97c69baSŁukasz Stelmach ax_spi->cmd_buf, len, 88a97c69baSŁukasz Stelmach ax_spi->rx_buf, 2); 89a97c69baSŁukasz Stelmach if (ret) { 90a97c69baSŁukasz Stelmach dev_err(&ax_spi->spi->dev, 91a97c69baSŁukasz Stelmach "%s() failed: ret = %d\n", __func__, ret); 92a97c69baSŁukasz Stelmach return 0xFFFF; 93a97c69baSŁukasz Stelmach } 94a97c69baSŁukasz Stelmach 95a97c69baSŁukasz Stelmach le16_to_cpus((u16 *)ax_spi->rx_buf); 96a97c69baSŁukasz Stelmach 97a97c69baSŁukasz Stelmach return *(u16 *)ax_spi->rx_buf; 98a97c69baSŁukasz Stelmach } 99a97c69baSŁukasz Stelmach 100a97c69baSŁukasz Stelmach int axspi_write_reg(struct axspi_data *ax_spi, u8 reg, u16 value) 101a97c69baSŁukasz Stelmach { 102a97c69baSŁukasz Stelmach int ret; 103a97c69baSŁukasz Stelmach 104a97c69baSŁukasz Stelmach memset(ax_spi->cmd_buf, 0, sizeof(ax_spi->cmd_buf)); 105a97c69baSŁukasz Stelmach ax_spi->cmd_buf[0] = AX_SPICMD_WRITE_REG; /* OP code read register */ 106a97c69baSŁukasz Stelmach ax_spi->cmd_buf[1] = reg; /* register address */ 107a97c69baSŁukasz Stelmach ax_spi->cmd_buf[2] = value; 108a97c69baSŁukasz Stelmach ax_spi->cmd_buf[3] = value >> 8; 109a97c69baSŁukasz Stelmach 110a97c69baSŁukasz Stelmach ret = spi_write(ax_spi->spi, ax_spi->cmd_buf, 4); 111a97c69baSŁukasz Stelmach if (ret) 112a97c69baSŁukasz Stelmach dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret); 113a97c69baSŁukasz Stelmach return ret; 114a97c69baSŁukasz Stelmach } 115a97c69baSŁukasz Stelmach 116