Commit 2bb295f3 authored by David S. Miller's avatar David S. Miller

Merge branch 'net-hisilicon-Add-support-for-HI13X1-to-hip04_eth'

Jiangfeng Xiao says:

====================
net: hisilicon: Add support for HI13X1 to hip04_eth

The main purpose of this patch series is to extend the
hip04_eth driver to support HI13X1_GMAC.

The offset and bitmap of some registers of HI13X1_GMAC
are different from hip04_eth common soc. In addition,
the definition of send descriptor and parsing descriptor
are different from hip04_eth common soc. So the macro
of the register offset is redefined to adapt the HI13X1_GMAC.

Clean up the sparse warning by the way.

Change since v1:
* Add a cover letter.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 03a49a14 d413779c
......@@ -10,6 +10,7 @@ Required properties:
phandle, specifies a reference to the syscon ppe node
port, port number connected to the controller
channel, recv channel start from channel * number (RX_DESC_NUM)
group, field in the pkg desc, in general, it is the same as the port.
- phy-mode: see ethernet.txt [1].
Optional properties:
......@@ -66,7 +67,7 @@ Example:
reg = <0x28b0000 0x10000>;
interrupts = <0 413 4>;
phy-mode = "mii";
port-handle = <&ppe 31 0>;
port-handle = <&ppe 31 0 31>;
};
ge0: ethernet@2800000 {
......@@ -74,7 +75,7 @@ Example:
reg = <0x2800000 0x10000>;
interrupts = <0 402 4>;
phy-mode = "sgmii";
port-handle = <&ppe 0 1>;
port-handle = <&ppe 0 1 0>;
phy-handle = <&phy0>;
};
......@@ -83,6 +84,6 @@ Example:
reg = <0x2880000 0x10000>;
interrupts = <0 410 4>;
phy-mode = "sgmii";
port-handle = <&ppe 8 2>;
port-handle = <&ppe 8 2 8>;
phy-handle = <&phy1>;
};
......@@ -46,6 +46,16 @@ config HIP04_ETH
If you wish to compile a kernel for a hardware with hisilicon p04 SoC and
want to use the internal ethernet then you should answer Y to this.
config HI13X1_GMAC
bool "Hisilicon HI13X1 Network Device Support"
depends on HIP04_ETH
help
If you wish to compile a kernel for a hardware with hisilicon hi13x1_gamc
then you should answer Y to this. This makes this driver suitable for use
on certain boards such as the HI13X1.
If you are unsure, say N.
config HNS_MDIO
tristate
select PHYLIB
......
......@@ -16,6 +16,8 @@
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#define SC_PPE_RESET_DREQ 0x026C
#define PPE_CFG_RX_ADDR 0x100
#define PPE_CFG_POOL_GRP 0x300
#define PPE_CFG_RX_BUF_SIZE 0x400
......@@ -33,10 +35,23 @@
#define GE_MODE_CHANGE_REG 0x1b4
#define GE_RECV_CONTROL_REG 0x1e0
#define GE_STATION_MAC_ADDRESS 0x210
#define PPE_CFG_CPU_ADD_ADDR 0x580
#define PPE_CFG_MAX_FRAME_LEN_REG 0x408
#define PPE_CFG_BUS_CTRL_REG 0x424
#define PPE_CFG_RX_CTRL_REG 0x428
#if defined(CONFIG_HI13X1_GMAC)
#define PPE_CFG_CPU_ADD_ADDR 0x6D0
#define PPE_CFG_MAX_FRAME_LEN_REG 0x500
#define PPE_CFG_RX_PKT_MODE_REG 0x504
#define PPE_CFG_QOS_VMID_GEN 0x520
#define PPE_CFG_RX_PKT_INT 0x740
#define PPE_INTEN 0x700
#define PPE_INTSTS 0x708
#define PPE_RINT 0x704
#define PPE_CFG_STS_MODE 0x880
#else
#define PPE_CFG_CPU_ADD_ADDR 0x580
#define PPE_CFG_MAX_FRAME_LEN_REG 0x408
#define PPE_CFG_RX_PKT_MODE_REG 0x438
#define PPE_CFG_QOS_VMID_GEN 0x500
#define PPE_CFG_RX_PKT_INT 0x538
......@@ -44,8 +59,12 @@
#define PPE_INTSTS 0x608
#define PPE_RINT 0x604
#define PPE_CFG_STS_MODE 0x700
#endif /* CONFIG_HI13X1_GMAC */
#define PPE_HIS_RX_PKT_CNT 0x804
#define RESET_DREQ_ALL 0xffffffff
/* REG_INTERRUPT */
#define RCV_INT BIT(10)
#define RCV_NOBUF BIT(8)
......@@ -57,8 +76,15 @@
/* TX descriptor config */
#define TX_FREE_MEM BIT(0)
#define TX_READ_ALLOC_L3 BIT(1)
#define TX_FINISH_CACHE_INV BIT(2)
#if defined(CONFIG_HI13X1_GMAC)
#define TX_CLEAR_WB BIT(7)
#define TX_RELEASE_TO_PPE BIT(4)
#define TX_FINISH_CACHE_INV BIT(6)
#define TX_POOL_SHIFT 16
#else
#define TX_CLEAR_WB BIT(4)
#define TX_FINISH_CACHE_INV BIT(2)
#endif
#define TX_L3_CHECKSUM BIT(5)
#define TX_LOOP_BACK BIT(11)
......@@ -93,18 +119,35 @@
#define GE_RX_PORT_EN BIT(1)
#define GE_TX_PORT_EN BIT(2)
#define PPE_CFG_STS_RX_PKT_CNT_RC BIT(12)
#define PPE_CFG_RX_PKT_ALIGN BIT(18)
#define PPE_CFG_QOS_VMID_MODE BIT(14)
#if defined(CONFIG_HI13X1_GMAC)
#define PPE_CFG_QOS_VMID_GRP_SHIFT 4
#define PPE_CFG_RX_CTRL_ALIGN_SHIFT 7
#define PPE_CFG_STS_RX_PKT_CNT_RC BIT(0)
#define PPE_CFG_QOS_VMID_MODE BIT(15)
#define PPE_CFG_BUS_LOCAL_REL (BIT(9) | BIT(15) | BIT(19) | BIT(23))
/* buf unit size is cache_line_size, which is 64, so the shift is 6 */
#define PPE_BUF_SIZE_SHIFT 6
#define PPE_TX_BUF_HOLD BIT(31)
#define CACHE_LINE_MASK 0x3F
#else
#define PPE_CFG_QOS_VMID_GRP_SHIFT 8
#define PPE_CFG_RX_CTRL_ALIGN_SHIFT 11
#define PPE_CFG_STS_RX_PKT_CNT_RC BIT(12)
#define PPE_CFG_QOS_VMID_MODE BIT(14)
#define PPE_CFG_BUS_LOCAL_REL BIT(14)
/* buf unit size is 1, so the shift is 6 */
#define PPE_BUF_SIZE_SHIFT 0
#define PPE_TX_BUF_HOLD 0
#endif /* CONFIG_HI13X1_GMAC */
#define PPE_CFG_RX_FIFO_FSFU BIT(11)
#define PPE_CFG_RX_DEPTH_SHIFT 16
#define PPE_CFG_RX_START_SHIFT 0
#define PPE_CFG_RX_CTRL_ALIGN_SHIFT 11
#define PPE_CFG_BUS_LOCAL_REL BIT(14)
#define PPE_CFG_BUS_BIG_ENDIEN BIT(0)
#define RX_DESC_NUM 128
......@@ -128,26 +171,50 @@
#define HIP04_MIN_TX_COALESCE_FRAMES 100
struct tx_desc {
#if defined(CONFIG_HI13X1_GMAC)
u32 reserved1[2];
u32 send_addr;
u16 send_size;
u16 data_offset;
u32 reserved2[7];
u32 cfg;
u32 wb_addr;
u32 reserved3[3];
#else
u32 send_addr;
u32 send_size;
u32 next_addr;
u32 cfg;
u32 wb_addr;
#endif
} __aligned(64);
struct rx_desc {
#if defined(CONFIG_HI13X1_GMAC)
u32 reserved1[3];
u16 pkt_len;
u16 reserved_16;
u32 reserved2[6];
u32 pkt_err;
u32 reserved3[5];
#else
u16 reserved_16;
u16 pkt_len;
u32 reserve1[3];
u32 pkt_err;
u32 reserve2[4];
#endif
};
struct hip04_priv {
void __iomem *base;
#if defined(CONFIG_HI13X1_GMAC)
void __iomem *sysctrl_base;
#endif
int phy_mode;
int chan;
unsigned int port;
unsigned int group;
unsigned int speed;
unsigned int duplex;
unsigned int reg_inten;
......@@ -221,6 +288,13 @@ static void hip04_config_port(struct net_device *ndev, u32 speed, u32 duplex)
writel_relaxed(val, priv->base + GE_MODE_CHANGE_REG);
}
static void hip04_reset_dreq(struct hip04_priv *priv)
{
#if defined(CONFIG_HI13X1_GMAC)
writel_relaxed(RESET_DREQ_ALL, priv->sysctrl_base + SC_PPE_RESET_DREQ);
#endif
}
static void hip04_reset_ppe(struct hip04_priv *priv)
{
u32 val, tmp, timeout = 0;
......@@ -241,14 +315,14 @@ static void hip04_config_fifo(struct hip04_priv *priv)
val |= PPE_CFG_STS_RX_PKT_CNT_RC;
writel_relaxed(val, priv->base + PPE_CFG_STS_MODE);
val = BIT(priv->port);
val = BIT(priv->group);
regmap_write(priv->map, priv->port * 4 + PPE_CFG_POOL_GRP, val);
val = priv->port << PPE_CFG_QOS_VMID_GRP_SHIFT;
val = priv->group << PPE_CFG_QOS_VMID_GRP_SHIFT;
val |= PPE_CFG_QOS_VMID_MODE;
writel_relaxed(val, priv->base + PPE_CFG_QOS_VMID_GEN);
val = RX_BUF_SIZE;
val = RX_BUF_SIZE >> PPE_BUF_SIZE_SHIFT;
regmap_write(priv->map, priv->port * 4 + PPE_CFG_RX_BUF_SIZE, val);
val = RX_DESC_NUM << PPE_CFG_RX_DEPTH_SHIFT;
......@@ -285,8 +359,10 @@ static void hip04_config_fifo(struct hip04_priv *priv)
val |= GE_RX_STRIP_PAD | GE_RX_PAD_EN;
writel_relaxed(val, priv->base + GE_RECV_CONTROL_REG);
#ifndef CONFIG_HI13X1_GMAC
val = GE_AUTO_NEG_CTL;
writel_relaxed(val, priv->base + GE_TX_LOCAL_PAGE_REG);
#endif
}
static void hip04_mac_enable(struct net_device *ndev)
......@@ -329,12 +405,18 @@ static void hip04_mac_disable(struct net_device *ndev)
static void hip04_set_xmit_desc(struct hip04_priv *priv, dma_addr_t phys)
{
writel(phys, priv->base + PPE_CFG_CPU_ADD_ADDR);
u32 val;
val = phys >> PPE_BUF_SIZE_SHIFT | PPE_TX_BUF_HOLD;
writel(val, priv->base + PPE_CFG_CPU_ADD_ADDR);
}
static void hip04_set_recv_desc(struct hip04_priv *priv, dma_addr_t phys)
{
regmap_write(priv->map, priv->port * 4 + PPE_CFG_RX_ADDR, phys);
u32 val;
val = phys >> PPE_BUF_SIZE_SHIFT;
regmap_write(priv->map, priv->port * 4 + PPE_CFG_RX_ADDR, val);
}
static u32 hip04_recv_cnt(struct hip04_priv *priv)
......@@ -442,11 +524,20 @@ hip04_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
priv->tx_skb[tx_head] = skb;
priv->tx_phys[tx_head] = phys;
desc->send_addr = cpu_to_be32(phys);
desc->send_size = cpu_to_be32(skb->len);
desc->cfg = cpu_to_be32(TX_CLEAR_WB | TX_FINISH_CACHE_INV);
desc->send_size = (__force u32)cpu_to_be32(skb->len);
#if defined(CONFIG_HI13X1_GMAC)
desc->cfg = (__force u32)cpu_to_be32(TX_CLEAR_WB | TX_FINISH_CACHE_INV
| TX_RELEASE_TO_PPE | priv->port << TX_POOL_SHIFT);
desc->data_offset = (__force u32)cpu_to_be32(phys & CACHE_LINE_MASK);
desc->send_addr = (__force u32)cpu_to_be32(phys & ~CACHE_LINE_MASK);
#else
desc->cfg = (__force u32)cpu_to_be32(TX_CLEAR_WB | TX_FINISH_CACHE_INV);
desc->send_addr = (__force u32)cpu_to_be32(phys);
#endif
phys = priv->tx_desc_dma + tx_head * sizeof(struct tx_desc);
desc->wb_addr = cpu_to_be32(phys);
desc->wb_addr = (__force u32)cpu_to_be32(phys +
offsetof(struct tx_desc, send_addr));
skb_tx_timestamp(skb);
hip04_set_xmit_desc(priv, phys);
......@@ -507,8 +598,8 @@ static int hip04_rx_poll(struct napi_struct *napi, int budget)
priv->rx_phys[priv->rx_head] = 0;
desc = (struct rx_desc *)skb->data;
len = be16_to_cpu(desc->pkt_len);
err = be32_to_cpu(desc->pkt_err);
len = be16_to_cpu((__force __be16)desc->pkt_len);
err = be32_to_cpu((__force __be32)desc->pkt_err);
if (0 == len) {
dev_kfree_skb_any(skb);
......@@ -828,7 +919,16 @@ static int hip04_mac_probe(struct platform_device *pdev)
goto init_fail;
}
ret = of_parse_phandle_with_fixed_args(node, "port-handle", 2, 0, &arg);
#if defined(CONFIG_HI13X1_GMAC)
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
priv->sysctrl_base = devm_ioremap_resource(d, res);
if (IS_ERR(priv->sysctrl_base)) {
ret = PTR_ERR(priv->sysctrl_base);
goto init_fail;
}
#endif
ret = of_parse_phandle_with_fixed_args(node, "port-handle", 3, 0, &arg);
if (ret < 0) {
dev_warn(d, "no port-handle\n");
goto init_fail;
......@@ -836,6 +936,7 @@ static int hip04_mac_probe(struct platform_device *pdev)
priv->port = arg.args[0];
priv->chan = arg.args[1] * RX_DESC_NUM;
priv->group = arg.args[2];
hrtimer_init(&priv->tx_coalesce_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
......@@ -896,6 +997,7 @@ static int hip04_mac_probe(struct platform_device *pdev)
ndev->irq = irq;
netif_napi_add(ndev, &priv->napi, hip04_rx_poll, NAPI_POLL_WEIGHT);
hip04_reset_dreq(priv);
hip04_reset_ppe(priv);
if (priv->phy_mode == PHY_INTERFACE_MODE_MII)
hip04_config_port(ndev, SPEED_100, DUPLEX_FULL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment