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