aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhao Qiang <qiang.zhao@nxp.com>2016-06-06 02:30:02 -0400
committerDavid S. Miller <davem@davemloft.net>2016-06-07 18:56:31 -0400
commitc19b6d246a35627c3a69b2fa6bdece212b48214b (patch)
treec7f5748156aed7f2f2c0eb0e33eab1f7ef23e172
parent35ef1c20fdb26779b6c3c4fd74bbdd5028e70005 (diff)
drivers/net: support hdlc function for QE-UCC
The driver add hdlc support for Freescale QUICC Engine. It support NMSI and TSA mode. Signed-off-by: Zhao Qiang <qiang.zhao@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--MAINTAINERS7
-rw-r--r--drivers/net/wan/Kconfig11
-rw-r--r--drivers/net/wan/Makefile1
-rw-r--r--drivers/net/wan/fsl_ucc_hdlc.c1192
-rw-r--r--drivers/net/wan/fsl_ucc_hdlc.h147
-rw-r--r--include/soc/fsl/qe/qe.h1
-rw-r--r--include/soc/fsl/qe/ucc_fast.h22
7 files changed, 1379 insertions, 2 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index f8d5a3772e47..16e1500d7c52 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4870,6 +4870,13 @@ F: drivers/net/ethernet/freescale/gianfar*
4870X: drivers/net/ethernet/freescale/gianfar_ptp.c 4870X: drivers/net/ethernet/freescale/gianfar_ptp.c
4871F: Documentation/devicetree/bindings/net/fsl-tsec-phy.txt 4871F: Documentation/devicetree/bindings/net/fsl-tsec-phy.txt
4872 4872
4873FREESCALE QUICC ENGINE UCC HDLC DRIVER
4874M: Zhao Qiang <qiang.zhao@nxp.com>
4875L: netdev@vger.kernel.org
4876L: linuxppc-dev@lists.ozlabs.org
4877S: Maintained
4878F: drivers/net/wan/fsl_ucc_hdlc*
4879
4873FREESCALE QUICC ENGINE UCC UART DRIVER 4880FREESCALE QUICC ENGINE UCC UART DRIVER
4874M: Timur Tabi <timur@tabi.org> 4881M: Timur Tabi <timur@tabi.org>
4875L: linuxppc-dev@lists.ozlabs.org 4882L: linuxppc-dev@lists.ozlabs.org
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index a2fdd15f285a..9e314b791150 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -280,6 +280,17 @@ config DSCC4
280 To compile this driver as a module, choose M here: the 280 To compile this driver as a module, choose M here: the
281 module will be called dscc4. 281 module will be called dscc4.
282 282
283config FSL_UCC_HDLC
284 tristate "Freescale QUICC Engine HDLC support"
285 depends on HDLC
286 depends on QUICC_ENGINE
287 help
288 Driver for Freescale QUICC Engine HDLC controller. The driver
289 supports HDLC in NMSI and TDM mode.
290
291 To compile this driver as a module, choose M here: the
292 module will be called fsl_ucc_hdlc.
293
283config DSCC4_PCISYNC 294config DSCC4_PCISYNC
284 bool "Etinc PCISYNC features" 295 bool "Etinc PCISYNC features"
285 depends on DSCC4 296 depends on DSCC4
diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile
index c135ef47cbca..25fec40d4353 100644
--- a/drivers/net/wan/Makefile
+++ b/drivers/net/wan/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_WANXL) += wanxl.o
32obj-$(CONFIG_PCI200SYN) += pci200syn.o 32obj-$(CONFIG_PCI200SYN) += pci200syn.o
33obj-$(CONFIG_PC300TOO) += pc300too.o 33obj-$(CONFIG_PC300TOO) += pc300too.o
34obj-$(CONFIG_IXP4XX_HSS) += ixp4xx_hss.o 34obj-$(CONFIG_IXP4XX_HSS) += ixp4xx_hss.o
35obj-$(CONFIG_FSL_UCC_HDLC) += fsl_ucc_hdlc.o
35 36
36clean-files := wanxlfw.inc 37clean-files := wanxlfw.inc
37$(obj)/wanxl.o: $(obj)/wanxlfw.inc 38$(obj)/wanxl.o: $(obj)/wanxlfw.inc
diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c
new file mode 100644
index 000000000000..19174ac1e338
--- /dev/null
+++ b/drivers/net/wan/fsl_ucc_hdlc.c
@@ -0,0 +1,1192 @@
1/* Freescale QUICC Engine HDLC Device Driver
2 *
3 * Copyright 2016 Freescale Semiconductor Inc.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 */
10
11#include <linux/delay.h>
12#include <linux/dma-mapping.h>
13#include <linux/hdlc.h>
14#include <linux/init.h>
15#include <linux/interrupt.h>
16#include <linux/io.h>
17#include <linux/irq.h>
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/netdevice.h>
21#include <linux/of_address.h>
22#include <linux/of_irq.h>
23#include <linux/of_platform.h>
24#include <linux/platform_device.h>
25#include <linux/sched.h>
26#include <linux/skbuff.h>
27#include <linux/slab.h>
28#include <linux/spinlock.h>
29#include <linux/stddef.h>
30#include <soc/fsl/qe/qe_tdm.h>
31#include <uapi/linux/if_arp.h>
32
33#include "fsl_ucc_hdlc.h"
34
35#define DRV_DESC "Freescale QE UCC HDLC Driver"
36#define DRV_NAME "ucc_hdlc"
37
38#define TDM_PPPOHT_SLIC_MAXIN
39#define BROKEN_FRAME_INFO
40
41static struct ucc_tdm_info utdm_primary_info = {
42 .uf_info = {
43 .tsa = 0,
44 .cdp = 0,
45 .cds = 1,
46 .ctsp = 1,
47 .ctss = 1,
48 .revd = 0,
49 .urfs = 256,
50 .utfs = 256,
51 .urfet = 128,
52 .urfset = 192,
53 .utfet = 128,
54 .utftt = 0x40,
55 .ufpt = 256,
56 .mode = UCC_FAST_PROTOCOL_MODE_HDLC,
57 .ttx_trx = UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL,
58 .tenc = UCC_FAST_TX_ENCODING_NRZ,
59 .renc = UCC_FAST_RX_ENCODING_NRZ,
60 .tcrc = UCC_FAST_16_BIT_CRC,
61 .synl = UCC_FAST_SYNC_LEN_NOT_USED,
62 },
63
64 .si_info = {
65#ifdef TDM_PPPOHT_SLIC_MAXIN
66 .simr_rfsd = 1,
67 .simr_tfsd = 2,
68#else
69 .simr_rfsd = 0,
70 .simr_tfsd = 0,
71#endif
72 .simr_crt = 0,
73 .simr_sl = 0,
74 .simr_ce = 1,
75 .simr_fe = 1,
76 .simr_gm = 0,
77 },
78};
79
80static struct ucc_tdm_info utdm_info[MAX_HDLC_NUM];
81
82static int uhdlc_init(struct ucc_hdlc_private *priv)
83{
84 struct ucc_tdm_info *ut_info;
85 struct ucc_fast_info *uf_info;
86 u32 cecr_subblock;
87 u16 bd_status;
88 int ret, i;
89 void *bd_buffer;
90 dma_addr_t bd_dma_addr;
91 u32 riptr;
92 u32 tiptr;
93 u32 gumr;
94
95 ut_info = priv->ut_info;
96 uf_info = &ut_info->uf_info;
97
98 if (priv->tsa) {
99 uf_info->tsa = 1;
100 uf_info->ctsp = 1;
101 }
102 uf_info->uccm_mask = ((UCC_HDLC_UCCE_RXB | UCC_HDLC_UCCE_RXF |
103 UCC_HDLC_UCCE_TXB) << 16);
104
105 ret = ucc_fast_init(uf_info, &priv->uccf);
106 if (ret) {
107 dev_err(priv->dev, "Failed to init uccf.");
108 return ret;
109 }
110
111 priv->uf_regs = priv->uccf->uf_regs;
112 ucc_fast_disable(priv->uccf, COMM_DIR_RX | COMM_DIR_TX);
113
114 /* Loopback mode */
115 if (priv->loopback) {
116 dev_info(priv->dev, "Loopback Mode\n");
117 gumr = ioread32be(&priv->uf_regs->gumr);
118 gumr |= (UCC_FAST_GUMR_LOOPBACK | UCC_FAST_GUMR_CDS |
119 UCC_FAST_GUMR_TCI);
120 gumr &= ~(UCC_FAST_GUMR_CTSP | UCC_FAST_GUMR_RSYN);
121 iowrite32be(gumr, &priv->uf_regs->gumr);
122 }
123
124 /* Initialize SI */
125 if (priv->tsa)
126 ucc_tdm_init(priv->utdm, priv->ut_info);
127
128 /* Write to QE CECR, UCCx channel to Stop Transmission */
129 cecr_subblock = ucc_fast_get_qe_cr_subblock(uf_info->ucc_num);
130 ret = qe_issue_cmd(QE_STOP_TX, cecr_subblock,
131 QE_CR_PROTOCOL_UNSPECIFIED, 0);
132
133 /* Set UPSMR normal mode (need fixed)*/
134 iowrite32be(0, &priv->uf_regs->upsmr);
135
136 priv->rx_ring_size = RX_BD_RING_LEN;
137 priv->tx_ring_size = TX_BD_RING_LEN;
138 /* Alloc Rx BD */
139 priv->rx_bd_base = dma_alloc_coherent(priv->dev,
140 RX_BD_RING_LEN * sizeof(struct qe_bd *),
141 &priv->dma_rx_bd, GFP_KERNEL);
142
143 if (!priv->rx_bd_base) {
144 dev_err(priv->dev, "Cannot allocate MURAM memory for RxBDs\n");
145 ret = -ENOMEM;
146 goto rxbd_alloc_error;
147 }
148