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 
16 const u8 ax88796c_rx_cmd_buf[5] = {AX_SPICMD_READ_RXQ, 0xFF, 0xFF, 0xFF, 0xFF};
17 const u8 ax88796c_tx_cmd_buf[4] = {AX_SPICMD_WRITE_TXQ, 0xFF, 0xFF, 0xFF};
18 
19 /* driver bus management functions */
axspi_wakeup(struct axspi_data * ax_spi)20 int 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 
axspi_read_status(struct axspi_data * ax_spi,struct spi_status * status)31 int 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 	else
41 		le16_to_cpus(&status->isr);
42 
43 	return ret;
44 }
45 
axspi_read_rxq(struct axspi_data * ax_spi,void * data,int len)46 int 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 
axspi_write_txq(const struct axspi_data * ax_spi,void * data,int len)72 int 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 
axspi_read_reg(struct axspi_data * ax_spi,u8 reg)77 u16 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 
axspi_write_reg(struct axspi_data * ax_spi,u8 reg,u16 value)100 int 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