xref: /linux/drivers/net/ethernet/asix/ax88796c_spi.c (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
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