1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) 2010 ASIX Electronics Corporation
4 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
5 *
6 * ASIX AX88796C SPI Fast Ethernet Linux driver
7 */
8
9#define pr_fmt(fmt) "ax88796c: " fmt
10
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(spi: ax_spi->spi, buf: ax_spi->cmd_buf, len: 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(spi: ax_spi->spi, txbuf: ax_spi->cmd_buf, n_tx: 1, rxbuf: (u8 *)status, n_rx: 3);
38 if (ret)
39 dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret);
40 else
41 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(t: xfer, m: &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(t: xfer, m: &ax_spi->rx_msg);
65 ret = spi_sync(spi: ax_spi->spi, message: &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(spi: ax_spi->spi, buf: 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(spi: ax_spi->spi,
87 txbuf: ax_spi->cmd_buf, n_tx: len,
88 rxbuf: ax_spi->rx_buf, n_rx: 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(spi: ax_spi->spi, buf: ax_spi->cmd_buf, len: 4);
111 if (ret)
112 dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret);
113 return ret;
114}
115
116

source code of linux/drivers/net/ethernet/asix/ax88796c_spi.c