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 */
axspi_wakeup(struct axspi_data * ax_spi)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
axspi_read_status(struct axspi_data * ax_spi,struct spi_status * status)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
axspi_read_rxq(struct axspi_data * ax_spi,void * data,int len)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
axspi_write_txq(const struct axspi_data * ax_spi,void * data,int len)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
axspi_read_reg(struct axspi_data * ax_spi,u8 reg)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
axspi_write_reg(struct axspi_data * ax_spi,u8 reg,u16 value)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