Message ID | 20201028214012.9712-1-l.stelmach@samsung.com |
---|---|
Headers | show |
Series | AX88796C SPI Ethernet Adapter | expand |
> +static void > +ax88796c_get_regs(struct net_device *ndev, struct ethtool_regs *regs, void *_p) > +{ > + struct ax88796c_device *ax_local = to_ax88796c_device(ndev); > + u16 *p = _p; > + int offset, i; You missed a reverse christmass tree fix here. > +static int comp; > +static int msg_enable = NETIF_MSG_PROBE | > + NETIF_MSG_LINK | > + /* NETIF_MSG_TIMER | */ > + /* NETIF_MSG_IFDOWN | */ > + /* NETIF_MSG_IFUP | */ > + NETIF_MSG_RX_ERR | > + NETIF_MSG_TX_ERR | > + /* NETIF_MSG_TX_QUEUED | */ > + /* NETIF_MSG_INTR | */ > + /* NETIF_MSG_TX_DONE | */ > + /* NETIF_MSG_RX_STATUS | */ > + /* NETIF_MSG_PKTDATA | */ > + /* NETIF_MSG_HW | */ > + /* NETIF_MSG_WOL | */ > + 0; You should probably delete anything which is commented out. > + > +static char *no_regs_list = "80018001,e1918001,8001a001,fc0d0000"; > +unsigned long ax88796c_no_regs_mask[AX88796C_REGDUMP_LEN / (sizeof(unsigned long) * 8)]; > + > +module_param(comp, int, 0444); > +MODULE_PARM_DESC(comp, "0=Non-Compression Mode, 1=Compression Mode"); I think you need to find a different way to configure this. How much does compression bring you anyway? > +module_param(msg_enable, int, 0444); > +MODULE_PARM_DESC(msg_enable, "Message mask (see linux/netdevice.h for bitmap)"); I know a lot of drivers have msg_enable, but DaveM is generally against module parameters. So i would remove this. > +static void ax88796c_set_hw_multicast(struct net_device *ndev) > +{ > + struct ax88796c_device *ax_local = to_ax88796c_device(ndev); > + u16 rx_ctl = RXCR_AB; > + int mc_count = netdev_mc_count(ndev); reverse christmass tree. > +static struct sk_buff * > +ax88796c_tx_fixup(struct net_device *ndev, struct sk_buff_head *q) > +{ > + struct ax88796c_device *ax_local = to_ax88796c_device(ndev); > + struct sk_buff *skb, *tx_skb; > + struct tx_pkt_info *info; > + struct skb_data *entry; > + int headroom; > + int tailroom; > + u8 need_pages; > + u16 tol_len, pkt_len; > + u8 padlen, seq_num; > + u8 spi_len = ax_local->ax_spi.comp ? 1 : 4; reverse christmass tree. > +static int ax88796c_receive(struct net_device *ndev) > +{ > + struct ax88796c_device *ax_local = to_ax88796c_device(ndev); > + struct sk_buff *skb; > + struct skb_data *entry; > + u16 w_count, pkt_len; > + u8 pkt_cnt; Reverse christmass tree > + > +static int ax88796c_process_isr(struct ax88796c_device *ax_local) > +{ > + u16 isr; > + u8 done = 0; > + struct net_device *ndev = ax_local->ndev; ... > +static irqreturn_t ax88796c_interrupt(int irq, void *dev_instance) > +{ > + struct net_device *ndev = dev_instance; > + struct ax88796c_device *ax_local = to_ax88796c_device(ndev); ... > +static int > +ax88796c_open(struct net_device *ndev) > +{ > + struct ax88796c_device *ax_local = to_ax88796c_device(ndev); > + int ret; > + unsigned long irq_flag = IRQF_SHARED; > + int fc = AX_FC_NONE; ... > +static int ax88796c_probe(struct spi_device *spi) > +{ > + struct net_device *ndev; > + struct ax88796c_device *ax_local; > + char phy_id[MII_BUS_ID_SIZE + 3]; > + int ret; > + u16 temp; ... The mdio/phy/ethtool code looks O.K. now. I've not really looked at any of the frame transfer code, so i cannot comment on that. Andrew
It was <2020-10-29 czw 01:31>, when Andrew Lunn wrote: >> +static void >> +ax88796c_get_regs(struct net_device *ndev, struct ethtool_regs *regs, void *_p) >> +{ >> + struct ax88796c_device *ax_local = to_ax88796c_device(ndev); >> + u16 *p = _p; >> + int offset, i; > > You missed a reverse christmass tree fix here. > Done. >> +static int comp; >> +static int msg_enable = NETIF_MSG_PROBE | >> + NETIF_MSG_LINK | >> + /* NETIF_MSG_TIMER | */ >> + /* NETIF_MSG_IFDOWN | */ >> + /* NETIF_MSG_IFUP | */ >> + NETIF_MSG_RX_ERR | >> + NETIF_MSG_TX_ERR | >> + /* NETIF_MSG_TX_QUEUED | */ >> + /* NETIF_MSG_INTR | */ >> + /* NETIF_MSG_TX_DONE | */ >> + /* NETIF_MSG_RX_STATUS | */ >> + /* NETIF_MSG_PKTDATA | */ >> + /* NETIF_MSG_HW | */ >> + /* NETIF_MSG_WOL | */ >> + 0; > > You should probably delete anything which is commented out. > Done. >> + >> +static char *no_regs_list = "80018001,e1918001,8001a001,fc0d0000"; >> +unsigned long ax88796c_no_regs_mask[AX88796C_REGDUMP_LEN / (sizeof(unsigned long) * 8)]; >> + >> +module_param(comp, int, 0444); >> +MODULE_PARM_DESC(comp, "0=Non-Compression Mode, 1=Compression Mode"); > > I think you need to find a different way to configure this. How much > does compression bring you anyway? > Anything between almost 0 for large transfers, to 50 for tiniest. ~5% for ~500 byte transfers. Considering the chip is rather for small devices, that won't transfer large amounts of data, I'd rather keep some way to control it. >> +module_param(msg_enable, int, 0444); >> +MODULE_PARM_DESC(msg_enable, "Message mask (see linux/netdevice.h for bitmap)"); > > I know a lot of drivers have msg_enable, but DaveM is generally > against module parameters. So i would remove this. > These two parameters have something in common: no(?) other way to pass the information at the right time. Compression might be tuned in runtime, if there is an interface (via ethtool?) for setting custom knobs? Ther is such interface for msg_level level but it can be used before a device is probed and userland is running. Hence, there is no way to control msg_level during boot. I can remove those parameters, but I really would like to be able to control these parameter, especially msg_level during boot. If there is any other way, do let me know. >> +static void ax88796c_set_hw_multicast(struct net_device *ndev) >> +{ >> + struct ax88796c_device *ax_local = to_ax88796c_device(ndev); >> + u16 rx_ctl = RXCR_AB; >> + int mc_count = netdev_mc_count(ndev); > > reverse christmass tree. > Done. >> +static struct sk_buff * >> +ax88796c_tx_fixup(struct net_device *ndev, struct sk_buff_head *q) >> +{ >> + struct ax88796c_device *ax_local = to_ax88796c_device(ndev); >> + struct sk_buff *skb, *tx_skb; >> + struct tx_pkt_info *info; >> + struct skb_data *entry; >> + int headroom; >> + int tailroom; >> + u8 need_pages; >> + u16 tol_len, pkt_len; >> + u8 padlen, seq_num; >> + u8 spi_len = ax_local->ax_spi.comp ? 1 : 4; > > reverse christmass tree. > Done. >> +static int ax88796c_receive(struct net_device *ndev) >> +{ >> + struct ax88796c_device *ax_local = to_ax88796c_device(ndev); >> + struct sk_buff *skb; >> + struct skb_data *entry; >> + u16 w_count, pkt_len; >> + u8 pkt_cnt; > > Reverse christmass tree > Done. >> + >> +static int ax88796c_process_isr(struct ax88796c_device *ax_local) >> +{ >> + u16 isr; >> + u8 done = 0; >> + struct net_device *ndev = ax_local->ndev; > > ... > Done. >> +static irqreturn_t ax88796c_interrupt(int irq, void *dev_instance) >> +{ >> + struct net_device *ndev = dev_instance; >> + struct ax88796c_device *ax_local = to_ax88796c_device(ndev); > > ... > Done. >> +static int >> +ax88796c_open(struct net_device *ndev) >> +{ >> + struct ax88796c_device *ax_local = to_ax88796c_device(ndev); >> + int ret; >> + unsigned long irq_flag = IRQF_SHARED; >> + int fc = AX_FC_NONE; > > ... > Done. >> +static int ax88796c_probe(struct spi_device *spi) >> +{ >> + struct net_device *ndev; >> + struct ax88796c_device *ax_local; >> + char phy_id[MII_BUS_ID_SIZE + 3]; >> + int ret; >> + u16 temp; > > ... > Done. > The mdio/phy/ethtool code looks O.K. now. I've not really looked at > any of the frame transfer code, so i cannot comment on that. > > Andrew > > Thanks.
On 10/28/20 10:40 PM, Łukasz Stelmach wrote: > ASIX AX88796[1] is a versatile ethernet adapter chip, that can be > connected to a CPU with a 8/16-bit bus or with an SPI. This driver > supports SPI connection. > > The driver has been ported from the vendor kernel for ARTIK5[2] > boards. Several changes were made to adapt it to the current kernel > which include: > > + updated DT configuration, > + clock configuration moved to DT, > + new timer, ethtool and gpio APIs, > + dev_* instead of pr_* and custom printk() wrappers, > + removed awkward vendor power managemtn. > > [1] https://www.asix.com.tw/products.php?op=pItemdetail&PItemID=104;65;86&PLine=65 > [2] https://git.tizen.org/cgit/profile/common/platform/kernel/linux-3.10-artik/ > > The other ax88796 driver is for NE2000 compatible AX88796L chip. These > chips are not compatible. Hence, two separate drivers are required. > > Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com> > --- > MAINTAINERS | 6 + > drivers/net/ethernet/Kconfig | 1 + > drivers/net/ethernet/Makefile | 1 + > drivers/net/ethernet/asix/Kconfig | 22 + > drivers/net/ethernet/asix/Makefile | 6 + > drivers/net/ethernet/asix/ax88796c_ioctl.c | 197 ++++ > drivers/net/ethernet/asix/ax88796c_ioctl.h | 26 + > drivers/net/ethernet/asix/ax88796c_main.c | 1144 ++++++++++++++++++++ > drivers/net/ethernet/asix/ax88796c_main.h | 578 ++++++++++ > drivers/net/ethernet/asix/ax88796c_spi.c | 111 ++ > drivers/net/ethernet/asix/ax88796c_spi.h | 69 ++ > 11 files changed, 2161 insertions(+) > create mode 100644 drivers/net/ethernet/asix/Kconfig > create mode 100644 drivers/net/ethernet/asix/Makefile > create mode 100644 drivers/net/ethernet/asix/ax88796c_ioctl.c > create mode 100644 drivers/net/ethernet/asix/ax88796c_ioctl.h > create mode 100644 drivers/net/ethernet/asix/ax88796c_main.c > create mode 100644 drivers/net/ethernet/asix/ax88796c_main.h > create mode 100644 drivers/net/ethernet/asix/ax88796c_spi.c > create mode 100644 drivers/net/ethernet/asix/ax88796c_spi.h [...] > +enum watchdog_state { > + chk_link = 0, > + chk_cable, > + ax_nop, > +}; > + > +struct ax88796c_device { > + struct resource *addr_res; /* resources found */ > + struct resource *addr_req; /* resources requested */ > + struct resource *irq_res; > + > + struct spi_device *spi; > + struct net_device *ndev; > + struct net_device_stats stats; > + > + struct timer_list watchdog; > + enum watchdog_state w_state; > + size_t w_ticks; are these used? > + > + struct work_struct ax_work; > + > + struct mutex spi_lock; /* device access */ > + > + struct sk_buff_head tx_wait_q; > + > + struct axspi_data ax_spi; > + > + struct mii_bus *mdiobus; > + struct phy_device *phydev; > + > + int msg_enable; > + > + u16 seq_num; > + > + u8 multi_filter[AX_MCAST_FILTER_SIZE]; > + > + int link; > + int speed; > + int duplex; > + int pause; > + int asym_pause; > + int flowctrl; > + #define AX_FC_NONE 0 > + #define AX_FC_RX BIT(0) > + #define AX_FC_TX BIT(1) > + #define AX_FC_ANEG BIT(2) > + > + unsigned long capabilities; > + #define AX_CAP_DMA BIT(0) > + #define AX_CAP_COMP BIT(1) > + #define AX_CAP_BIDIR BIT(2) > + > + u8 plat_endian; > + #define PLAT_LITTLE_ENDIAN 0 > + #define PLAT_BIG_ENDIAN 1 > + > + unsigned long flags; > + #define EVENT_INTR BIT(0) > + #define EVENT_TX BIT(1) > + #define EVENT_SET_MULTI BIT(2) > + > +}; > + > +#define to_ax88796c_device(ndev) ((struct ax88796c_device *)netdev_priv(ndev)) > + > +enum skb_state { > + illegal = 0, > + tx_done, > + rx_done, > + rx_err, > +}; > + > +struct skb_data { > + enum skb_state state; > + struct net_device *ndev; > + struct sk_buff *skb; > + size_t len; > + dma_addr_t phy_addr; unused? [...] > diff --git a/drivers/net/ethernet/asix/ax88796c_spi.c b/drivers/net/ethernet/asix/ax88796c_spi.c > new file mode 100644 > index 000000000000..1a20bbeb4dc1 > --- /dev/null > +++ b/drivers/net/ethernet/asix/ax88796c_spi.c > @@ -0,0 +1,111 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Copyright (c) 2010 ASIX Electronics Corporation > + * Copyright (c) 2020 Samsung Electronics Co., Ltd. > + * > + * ASIX AX88796C SPI Fast Ethernet Linux driver > + */ > + > +#define pr_fmt(fmt) "ax88796c: " fmt > + > +#include <linux/string.h> > +#include <linux/spi/spi.h> > + > +#include "ax88796c_spi.h" > + > +/* driver bus management functions */ > +int axspi_wakeup(const struct axspi_data *ax_spi) > +{ > + u8 tx_buf; > + int ret; > + > + tx_buf = AX_SPICMD_EXIT_PWD; /* OP */ > + ret = spi_write(ax_spi->spi, &tx_buf, 1); spi_write() needs a DMA safe buffer. > + if (ret) > + dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret); > + return ret; > +} > + > +int axspi_read_status(const struct axspi_data *ax_spi, struct spi_status *status) > +{ > + u8 tx_buf; > + int ret; > + > + /* OP */ > + tx_buf = AX_SPICMD_READ_STATUS; > + ret = spi_write_then_read(ax_spi->spi, &tx_buf, 1, (u8 *)&status, 3); > + if (ret) > + dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret); > + else > + le16_to_cpus(&status->isr); > + > + return ret; > +} > + > +int axspi_read_rxq(struct axspi_data *ax_spi, void *data, int len) > +{ > + struct spi_transfer *xfer = ax_spi->spi_rx_xfer; > + int ret; > + > + memcpy(ax_spi->cmd_buf, rx_cmd_buf, 5); > + > + xfer->tx_buf = ax_spi->cmd_buf; > + xfer->rx_buf = NULL; > + xfer->len = ax_spi->comp ? 2 : 5; > + xfer->bits_per_word = 8; > + spi_message_add_tail(xfer, &ax_spi->rx_msg); > + > + xfer++; > + xfer->rx_buf = data; > + xfer->tx_buf = NULL; > + xfer->len = len; > + xfer->bits_per_word = 8; > + spi_message_add_tail(xfer, &ax_spi->rx_msg); > + ret = spi_sync(ax_spi->spi, &ax_spi->rx_msg); > + if (ret) > + dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret); > + > + return ret; > +} > + > +int axspi_write_txq(const struct axspi_data *ax_spi, void *data, int len) > +{ > + return spi_write(ax_spi->spi, data, len); > +} > + > +u16 axspi_read_reg(const struct axspi_data *ax_spi, u8 reg) > +{ > + u8 tx_buf[4]; > + u16 rx_buf = 0; > + int ret; > + int len = ax_spi->comp ? 3 : 4; > + > + tx_buf[0] = 0x03; /* OP code read register */ > + tx_buf[1] = reg; /* register address */ > + tx_buf[2] = 0xFF; /* dumy cycle */ > + tx_buf[3] = 0xFF; /* dumy cycle */ > + ret = spi_write_then_read(ax_spi->spi, tx_buf, len, (u8 *)&rx_buf, 2); > + if (ret) > + dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret); > + else > + le16_to_cpus(&rx_buf); > + > + return rx_buf; > +} > + > +int axspi_write_reg(const struct axspi_data *ax_spi, u8 reg, u16 value) > +{ > + u8 tx_buf[4]; > + int ret; > + > + tx_buf[0] = AX_SPICMD_WRITE_REG; /* OP code read register */ > + tx_buf[1] = reg; /* register address */ > + tx_buf[2] = value; > + tx_buf[3] = value >> 8; > + > + ret = spi_write(ax_spi->spi, tx_buf, 4); I think you need DMA safe mem for spi_write(). Marc
It was <2020-10-29 czw 01:31>, when Andrew Lunn wrote: > > Reverse christmass tree > >> + >> +static int ax88796c_process_isr(struct ax88796c_device *ax_local) >> +{ >> + u16 isr; >> + u8 done = 0; >> + struct net_device *ndev = ax_local->ndev; > > ... > >> +static irqreturn_t ax88796c_interrupt(int irq, void *dev_instance) >> +{ >> + struct net_device *ndev = dev_instance; >> + struct ax88796c_device *ax_local = to_ax88796c_device(ndev); > > ... > Doesn't work here - dependency. What next?
> >> +static irqreturn_t ax88796c_interrupt(int irq, void *dev_instance) > >> +{ > >> + struct net_device *ndev = dev_instance; > >> + struct ax88796c_device *ax_local = to_ax88796c_device(ndev); Do the assignment later. Andrew
It was <2020-10-29 czw 18:27>, when Marc Kleine-Budde wrote: > On 10/28/20 10:40 PM, Łukasz Stelmach wrote: >> ASIX AX88796[1] is a versatile ethernet adapter chip, that can be >> connected to a CPU with a 8/16-bit bus or with an SPI. This driver >> supports SPI connection. >> >> The driver has been ported from the vendor kernel for ARTIK5[2] >> boards. Several changes were made to adapt it to the current kernel >> which include: >> >> + updated DT configuration, >> + clock configuration moved to DT, >> + new timer, ethtool and gpio APIs, >> + dev_* instead of pr_* and custom printk() wrappers, >> + removed awkward vendor power managemtn. >> >> [1] >> https://protect2.fireeye.com/v1/url?k=9aaa9891-c7611faf-9aab13de-0cc47a31309a-7f8f6d6347765df4&q=1&e=78d1d40c-ff31-47e7-91fd-0c29963c1913&u=https%3A%2F%2Fwww.asix.com.tw%2Fproducts.php%3Fop%3DpItemdetail%26PItemID%3D104%3B65%3B86%26PLine%3D65 >> [2] >> https://protect2.fireeye.com/v1/url?k=407e4fb6-1db5c888-407fc4f9-0cc47a31309a-aaf46a5c37be27ea&q=1&e=78d1d40c-ff31-47e7-91fd-0c29963c1913&u=https%3A%2F%2Fgit.tizen.org%2Fcgit%2Fprofile%2Fcommon%2Fplatform%2Fkernel%2Flinux-3.10-artik%2F >> >> The other ax88796 driver is for NE2000 compatible AX88796L chip. These >> chips are not compatible. Hence, two separate drivers are required. >> >> Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com> >> --- >> MAINTAINERS | 6 + >> drivers/net/ethernet/Kconfig | 1 + >> drivers/net/ethernet/Makefile | 1 + >> drivers/net/ethernet/asix/Kconfig | 22 + >> drivers/net/ethernet/asix/Makefile | 6 + >> drivers/net/ethernet/asix/ax88796c_ioctl.c | 197 ++++ >> drivers/net/ethernet/asix/ax88796c_ioctl.h | 26 + >> drivers/net/ethernet/asix/ax88796c_main.c | 1144 ++++++++++++++++++++ >> drivers/net/ethernet/asix/ax88796c_main.h | 578 ++++++++++ >> drivers/net/ethernet/asix/ax88796c_spi.c | 111 ++ >> drivers/net/ethernet/asix/ax88796c_spi.h | 69 ++ >> 11 files changed, 2161 insertions(+) >> create mode 100644 drivers/net/ethernet/asix/Kconfig >> create mode 100644 drivers/net/ethernet/asix/Makefile >> create mode 100644 drivers/net/ethernet/asix/ax88796c_ioctl.c >> create mode 100644 drivers/net/ethernet/asix/ax88796c_ioctl.h >> create mode 100644 drivers/net/ethernet/asix/ax88796c_main.c >> create mode 100644 drivers/net/ethernet/asix/ax88796c_main.h >> create mode 100644 drivers/net/ethernet/asix/ax88796c_spi.c >> create mode 100644 drivers/net/ethernet/asix/ax88796c_spi.h > > [...] > >> +enum watchdog_state { >> + chk_link = 0, >> + chk_cable, >> + ax_nop, >> +}; >> + >> +struct ax88796c_device { >> + struct resource *addr_res; /* resources found */ >> + struct resource *addr_req; /* resources requested */ >> + struct resource *irq_res; >> + >> + struct spi_device *spi; >> + struct net_device *ndev; >> + struct net_device_stats stats; >> + >> + struct timer_list watchdog; >> + enum watchdog_state w_state; >> + size_t w_ticks; > > are these used? > Nope. Removed. Thanks. >> + >> + struct work_struct ax_work; >> + >> + struct mutex spi_lock; /* device access */ >> + >> + struct sk_buff_head tx_wait_q; >> + >> + struct axspi_data ax_spi; >> + >> + struct mii_bus *mdiobus; >> + struct phy_device *phydev; >> + >> + int msg_enable; >> + >> + u16 seq_num; >> + >> + u8 multi_filter[AX_MCAST_FILTER_SIZE]; >> + >> + int link; >> + int speed; >> + int duplex; >> + int pause; >> + int asym_pause; >> + int flowctrl; >> + #define AX_FC_NONE 0 >> + #define AX_FC_RX BIT(0) >> + #define AX_FC_TX BIT(1) >> + #define AX_FC_ANEG BIT(2) >> + >> + unsigned long capabilities; >> + #define AX_CAP_DMA BIT(0) >> + #define AX_CAP_COMP BIT(1) >> + #define AX_CAP_BIDIR BIT(2) >> + >> + u8 plat_endian; >> + #define PLAT_LITTLE_ENDIAN 0 >> + #define PLAT_BIG_ENDIAN 1 >> + >> + unsigned long flags; >> + #define EVENT_INTR BIT(0) >> + #define EVENT_TX BIT(1) >> + #define EVENT_SET_MULTI BIT(2) >> + >> +}; >> + >> +#define to_ax88796c_device(ndev) ((struct ax88796c_device *)netdev_priv(ndev)) >> + >> +enum skb_state { >> + illegal = 0, >> + tx_done, >> + rx_done, >> + rx_err, >> +}; >> + >> +struct skb_data { >> + enum skb_state state; >> + struct net_device *ndev; >> + struct sk_buff *skb; >> + size_t len; >> + dma_addr_t phy_addr; > > unused? > > [...] > Ditto. >> diff --git a/drivers/net/ethernet/asix/ax88796c_spi.c b/drivers/net/ethernet/asix/ax88796c_spi.c >> new file mode 100644 >> index 000000000000..1a20bbeb4dc1 >> --- /dev/null >> +++ b/drivers/net/ethernet/asix/ax88796c_spi.c >> @@ -0,0 +1,111 @@ >> +// SPDX-License-Identifier: GPL-2.0-only >> +/* >> + * Copyright (c) 2010 ASIX Electronics Corporation >> + * Copyright (c) 2020 Samsung Electronics Co., Ltd. >> + * >> + * ASIX AX88796C SPI Fast Ethernet Linux driver >> + */ >> + >> +#define pr_fmt(fmt) "ax88796c: " fmt >> + >> +#include <linux/string.h> >> +#include <linux/spi/spi.h> >> + >> +#include "ax88796c_spi.h" >> + >> +/* driver bus management functions */ >> +int axspi_wakeup(const struct axspi_data *ax_spi) >> +{ >> + u8 tx_buf; >> + int ret; >> + >> + tx_buf = AX_SPICMD_EXIT_PWD; /* OP */ >> + ret = spi_write(ax_spi->spi, &tx_buf, 1); > > spi_write() needs a DMA safe buffer. > Done. >> + if (ret) >> + dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret); >> + return ret; >> +} >> + >> +int axspi_read_status(const struct axspi_data *ax_spi, struct spi_status *status) >> +{ >> + u8 tx_buf; >> + int ret; >> + >> + /* OP */ >> + tx_buf = AX_SPICMD_READ_STATUS; >> + ret = spi_write_then_read(ax_spi->spi, &tx_buf, 1, (u8 *)&status, 3); >> + if (ret) >> + dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret); >> + else >> + le16_to_cpus(&status->isr); >> + >> + return ret; >> +} >> + >> +int axspi_read_rxq(struct axspi_data *ax_spi, void *data, int len) >> +{ >> + struct spi_transfer *xfer = ax_spi->spi_rx_xfer; >> + int ret; >> + >> + memcpy(ax_spi->cmd_buf, rx_cmd_buf, 5); >> + >> + xfer->tx_buf = ax_spi->cmd_buf; >> + xfer->rx_buf = NULL; >> + xfer->len = ax_spi->comp ? 2 : 5; >> + xfer->bits_per_word = 8; >> + spi_message_add_tail(xfer, &ax_spi->rx_msg); >> + >> + xfer++; >> + xfer->rx_buf = data; >> + xfer->tx_buf = NULL; >> + xfer->len = len; >> + xfer->bits_per_word = 8; >> + spi_message_add_tail(xfer, &ax_spi->rx_msg); >> + ret = spi_sync(ax_spi->spi, &ax_spi->rx_msg); >> + if (ret) >> + dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret); >> + >> + return ret; >> +} >> + >> +int axspi_write_txq(const struct axspi_data *ax_spi, void *data, int len) >> +{ >> + return spi_write(ax_spi->spi, data, len); >> +} >> + >> +u16 axspi_read_reg(const struct axspi_data *ax_spi, u8 reg) >> +{ >> + u8 tx_buf[4]; >> + u16 rx_buf = 0; >> + int ret; >> + int len = ax_spi->comp ? 3 : 4; >> + >> + tx_buf[0] = 0x03; /* OP code read register */ >> + tx_buf[1] = reg; /* register address */ >> + tx_buf[2] = 0xFF; /* dumy cycle */ >> + tx_buf[3] = 0xFF; /* dumy cycle */ >> + ret = spi_write_then_read(ax_spi->spi, tx_buf, len, (u8 *)&rx_buf, 2); >> + if (ret) >> + dev_err(&ax_spi->spi->dev, "%s() failed: ret = %d\n", __func__, ret); >> + else >> + le16_to_cpus(&rx_buf); >> + >> + return rx_buf; >> +} >> + >> +int axspi_write_reg(const struct axspi_data *ax_spi, u8 reg, u16 value) >> +{ >> + u8 tx_buf[4]; >> + int ret; >> + >> + tx_buf[0] = AX_SPICMD_WRITE_REG; /* OP code read register */ >> + tx_buf[1] = reg; /* register address */ >> + tx_buf[2] = value; >> + tx_buf[3] = value >> 8; >> + >> + ret = spi_write(ax_spi->spi, tx_buf, 4); > > I think you need DMA safe mem for spi_write(). "Moved" the bufferers to axspi_data struct. Thank you.