Re: [linux-sunxi] [PATCH RFC 1/3] ethernet: add sun8i-emac driver

2016-02-25 Thread Andre Przywara
Hi,

just some comments I have on the usage of the internal PHY.

On 22/02/16 15:45, LABBE Corentin wrote:
> This patch add support for sun8i-emac ethernet MAC hardware.
> It could be found in Allwinner H3/A83T/A64 SoCs.
> 
> Signed-off-by: LABBE Corentin 
> ---
>  drivers/net/ethernet/allwinner/Kconfig  |   14 +
>  drivers/net/ethernet/allwinner/Makefile |1 +
>  drivers/net/ethernet/allwinner/sun8i-emac.c | 1493 
> +++
>  3 files changed, 1508 insertions(+)
>  create mode 100644 drivers/net/ethernet/allwinner/sun8i-emac.c
> 
> diff --git a/drivers/net/ethernet/allwinner/sun8i-emac.c 
> b/drivers/net/ethernet/allwinner/sun8i-emac.c
> new file mode 100644
> index 000..a4e52cf
> --- /dev/null
> +++ b/drivers/net/ethernet/allwinner/sun8i-emac.c
> @@ -0,0 +1,1493 @@
> +/*
> + * sun8i-h3-emac driver
> + *
> + * Copyright (C) 2015-2016 Corentin LABBE 
> + *
> + * This is the driver for Allwinner Ethernet MAC found in H3/A83T/A64 SoC
> + *
> + * This is a mono block driver that need to be splited:
> + * - A classic ethernet MAC driver
> + * - A PHY driver
> + * - A clk driver
> + */
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +/* for A83T */
> +#include 
> +
> +#define SUN8I_EMAC_BASIC_CTL0 0x00
> +#define SUN8I_EMAC_BASIC_CTL1 0x04
> +
> +#define SUN8I_EMAC_MDIO_CMD 0x48
> +#define SUN8I_EMAC_MDIO_DATA 0x4C
> +
> +#define SUN8I_EMAC_RX_CTL0 0x24
> +#define SUN8I_EMAC_RX_CTL1 0x28
> +
> +#define SUN8I_EMAC_TX_CTL0 0x10
> +#define SUN8I_EMAC_TX_CTL1 0x14
> +
> +#define SUN8I_EMAC_TX_FLOW_CTL 0x1C
> +
> +#define SUN8I_EMAC_INT_STA 0x08
> +#define SUN8I_EMAC_INT_EN 0x0C
> +#define SUN8I_EMAC_RGMII_STA 0xD0
> +
> +#define SUN8I_EMAC_TX_DMA_STA 0xB0
> +#define SUN8I_EMAC_TX_CUR_DDESC 0xB4
> +#define SUN8I_EMAC_RX_DMA_STA 0xC0
> +
> +#define MII_BUSY BIT(0)
> +#define MII_WRITEBIT(1)
> +
> +#define SUN8I_EMAC_MACADDR_HI0x50
> +#define SUN8I_EMAC_MACADDR_LO0x54
> +
> +#define SUN8I_EMAC_RX_DESC_LIST 0x34
> +#define SUN8I_EMAC_TX_DESC_LIST 0x20
> +
> +#define SUN8I_COULD_BE_USED_BY_DMA BIT(31)
> +
> +struct dma_desc {
> + u32 status;
> + u32 st;
> + u32 buf_addr;
> + u32 next;
> +} __attribute__((packed, aligned(4)));
> +
> +static int flow_ctrl;
> +static int pause = 0x400;
> +
> +static int nbdesc = 4;
> +struct sun8i_emac_priv {
> + void __iomem *base;
> + int irq;
> + struct device *dev;
> + struct net_device *ndev;
> + struct mii_bus *mii;
> + spinlock_t lock;
> + spinlock_t tx_lock;
> + int duplex;
> + int speed;
> + int link;
> + u32 phy_interface;
> + struct clk *busclk;
> + struct clk *miiclk;
> + u32 mdc;
> +
> + struct reset_control *rst_phy;
> + struct reset_control *rst_mac;
> +
> + struct dma_desc *dd_rx cacheline_aligned;
> + dma_addr_t dd_rx_phy cacheline_aligned;
> + struct dma_desc *dd_tx;
> + dma_addr_t dd_tx_phy;
> + struct sk_buff **rx_sk;
> + struct sk_buff **tx_sk;
> +
> + struct regulator *power;
> +};
> +
> +/* allocate a sk in a dma descriptor
> +*/
> +static int sun8i_emac_rx_sk(struct net_device *ndev, int i)
> +{
> + struct sun8i_emac_priv *priv = netdev_priv(ndev);
> + struct dma_desc *ddesc;
> + struct sk_buff *sk;
> +
> + ddesc = priv->dd_rx + i;
> +
> + ddesc->st = 0;
> +
> + sk = netdev_alloc_skb_ip_align(ndev, ndev->mtu);
> + if (!sk)
> + return -ENOMEM;
> +
> + if (priv->rx_sk[i]) {
> + dev_warn(priv->dev, "WARN: Leaking a skbuff\n");
> + /* TODO should not happen */
> + }
> +
> + priv->rx_sk[i] = sk;
> +
> + ddesc->buf_addr = dma_map_single(priv->dev, sk->data,
> +  ndev->mtu, DMA_FROM_DEVICE);
> + if (dma_mapping_error(priv->dev, ddesc->buf_addr)) {
> + dev_err(priv->dev, "ERROR: Cannot dma_map RX\n");
> + dev_kfree_skb(sk);
> + return -EINVAL;
> + }
> + ddesc->st |= ndev->mtu;
> + ddesc->status = BIT(31);
> +
> + dev_info(priv->dev, "Init ddesc %02d at %pad buff=%p %x status=(%x 
> %x)\n",
> +  i, , >data, ddesc->buf_addr, ddesc->status, 
> ddesc->st);
> +
> + return 0;
> +}
> +
> +/* Set MAC address for slot index
> + * */
> +void sun8i_emac_set_macaddr(struct sun8i_emac_priv *priv, unsigned char 
> *addr,
> + int index)
> +{
> + u32 v;
> +
> + if (!is_valid_ether_addr(addr)) {
> + random_ether_addr(priv->ndev->dev_addr);
> + addr = priv->ndev->dev_addr;
> + }
> + dev_info(priv->dev, "%s %x %x %x %x %x %x\n", __func__,
> + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]),
> +
> + v 

[linux-sunxi] [PATCH RFC 1/3] ethernet: add sun8i-emac driver

2016-02-22 Thread LABBE Corentin
This patch add support for sun8i-emac ethernet MAC hardware.
It could be found in Allwinner H3/A83T/A64 SoCs.

Signed-off-by: LABBE Corentin 
---
 drivers/net/ethernet/allwinner/Kconfig  |   14 +
 drivers/net/ethernet/allwinner/Makefile |1 +
 drivers/net/ethernet/allwinner/sun8i-emac.c | 1493 +++
 3 files changed, 1508 insertions(+)
 create mode 100644 drivers/net/ethernet/allwinner/sun8i-emac.c

diff --git a/drivers/net/ethernet/allwinner/Kconfig 
b/drivers/net/ethernet/allwinner/Kconfig
index 47da7e7..43cf91f 100644
--- a/drivers/net/ethernet/allwinner/Kconfig
+++ b/drivers/net/ethernet/allwinner/Kconfig
@@ -33,4 +33,18 @@ config SUN4I_EMAC
   To compile this driver as a module, choose M here.  The module
   will be called sun4i-emac.
 
+config SUN8I_EMAC
+tristate "Allwinner H3 EMAC support"
+   depends on ARCH_SUNXI
+   depends on OF
+   select CRC32
+   select MII
+   select PHYLIB
+   select MDIO_SUN4I
+---help---
+  Support for Allwinner H3 EMAC ethernet driver.
+
+  To compile this driver as a module, choose M here.  The module
+  will be called sun8i-emac.
+
 endif # NET_VENDOR_ALLWINNER
diff --git a/drivers/net/ethernet/allwinner/Makefile 
b/drivers/net/ethernet/allwinner/Makefile
index 03129f7..8bd1693c 100644
--- a/drivers/net/ethernet/allwinner/Makefile
+++ b/drivers/net/ethernet/allwinner/Makefile
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_SUN4I_EMAC) += sun4i-emac.o
+obj-$(CONFIG_SUN8I_EMAC) += sun8i-emac.o
diff --git a/drivers/net/ethernet/allwinner/sun8i-emac.c 
b/drivers/net/ethernet/allwinner/sun8i-emac.c
new file mode 100644
index 000..a4e52cf
--- /dev/null
+++ b/drivers/net/ethernet/allwinner/sun8i-emac.c
@@ -0,0 +1,1493 @@
+/*
+ * sun8i-h3-emac driver
+ *
+ * Copyright (C) 2015-2016 Corentin LABBE 
+ *
+ * This is the driver for Allwinner Ethernet MAC found in H3/A83T/A64 SoC
+ *
+ * This is a mono block driver that need to be splited:
+ * - A classic ethernet MAC driver
+ * - A PHY driver
+ * - A clk driver
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+/* for A83T */
+#include 
+
+#define SUN8I_EMAC_BASIC_CTL0 0x00
+#define SUN8I_EMAC_BASIC_CTL1 0x04
+
+#define SUN8I_EMAC_MDIO_CMD 0x48
+#define SUN8I_EMAC_MDIO_DATA 0x4C
+
+#define SUN8I_EMAC_RX_CTL0 0x24
+#define SUN8I_EMAC_RX_CTL1 0x28
+
+#define SUN8I_EMAC_TX_CTL0 0x10
+#define SUN8I_EMAC_TX_CTL1 0x14
+
+#define SUN8I_EMAC_TX_FLOW_CTL 0x1C
+
+#define SUN8I_EMAC_INT_STA 0x08
+#define SUN8I_EMAC_INT_EN 0x0C
+#define SUN8I_EMAC_RGMII_STA 0xD0
+
+#define SUN8I_EMAC_TX_DMA_STA 0xB0
+#define SUN8I_EMAC_TX_CUR_DDESC 0xB4
+#define SUN8I_EMAC_RX_DMA_STA 0xC0
+
+#define MII_BUSY   BIT(0)
+#define MII_WRITE  BIT(1)
+
+#define SUN8I_EMAC_MACADDR_HI  0x50
+#define SUN8I_EMAC_MACADDR_LO  0x54
+
+#define SUN8I_EMAC_RX_DESC_LIST 0x34
+#define SUN8I_EMAC_TX_DESC_LIST 0x20
+
+#define SUN8I_COULD_BE_USED_BY_DMA BIT(31)
+
+struct dma_desc {
+   u32 status;
+   u32 st;
+   u32 buf_addr;
+   u32 next;
+} __attribute__((packed, aligned(4)));
+
+static int flow_ctrl;
+static int pause = 0x400;
+
+static int nbdesc = 4;
+struct sun8i_emac_priv {
+   void __iomem *base;
+   int irq;
+   struct device *dev;
+   struct net_device *ndev;
+   struct mii_bus *mii;
+   spinlock_t lock;
+   spinlock_t tx_lock;
+   int duplex;
+   int speed;
+   int link;
+   u32 phy_interface;
+   struct clk *busclk;
+   struct clk *miiclk;
+   u32 mdc;
+
+   struct reset_control *rst_phy;
+   struct reset_control *rst_mac;
+
+   struct dma_desc *dd_rx cacheline_aligned;
+   dma_addr_t dd_rx_phy cacheline_aligned;
+   struct dma_desc *dd_tx;
+   dma_addr_t dd_tx_phy;
+   struct sk_buff **rx_sk;
+   struct sk_buff **tx_sk;
+
+   struct regulator *power;
+};
+
+/* allocate a sk in a dma descriptor
+*/
+static int sun8i_emac_rx_sk(struct net_device *ndev, int i)
+{
+   struct sun8i_emac_priv *priv = netdev_priv(ndev);
+   struct dma_desc *ddesc;
+   struct sk_buff *sk;
+
+   ddesc = priv->dd_rx + i;
+
+   ddesc->st = 0;
+
+   sk = netdev_alloc_skb_ip_align(ndev, ndev->mtu);
+   if (!sk)
+   return -ENOMEM;
+
+   if (priv->rx_sk[i]) {
+   dev_warn(priv->dev, "WARN: Leaking a skbuff\n");
+   /* TODO should not happen */
+   }
+
+   priv->rx_sk[i] = sk;
+
+   ddesc->buf_addr = dma_map_single(priv->dev, sk->data,
+ndev->mtu, DMA_FROM_DEVICE);
+   if (dma_mapping_error(priv->dev, ddesc->buf_addr)) {
+   dev_err(priv->dev, "ERROR: Cannot dma_map RX\n");
+   dev_kfree_skb(sk);
+