diff options
| author | Zhao Qiang <qiang.zhao@nxp.com> | 2016-06-06 02:30:02 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2016-06-07 18:56:31 -0400 |
| commit | c19b6d246a35627c3a69b2fa6bdece212b48214b (patch) | |
| tree | c7f5748156aed7f2f2c0eb0e33eab1f7ef23e172 | |
| parent | 35ef1c20fdb26779b6c3c4fd74bbdd5028e70005 (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-- | MAINTAINERS | 7 | ||||
| -rw-r--r-- | drivers/net/wan/Kconfig | 11 | ||||
| -rw-r--r-- | drivers/net/wan/Makefile | 1 | ||||
| -rw-r--r-- | drivers/net/wan/fsl_ucc_hdlc.c | 1192 | ||||
| -rw-r--r-- | drivers/net/wan/fsl_ucc_hdlc.h | 147 | ||||
| -rw-r--r-- | include/soc/fsl/qe/qe.h | 1 | ||||
| -rw-r--r-- | include/soc/fsl/qe/ucc_fast.h | 22 |
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* | |||
| 4870 | X: drivers/net/ethernet/freescale/gianfar_ptp.c | 4870 | X: drivers/net/ethernet/freescale/gianfar_ptp.c |
| 4871 | F: Documentation/devicetree/bindings/net/fsl-tsec-phy.txt | 4871 | F: Documentation/devicetree/bindings/net/fsl-tsec-phy.txt |
| 4872 | 4872 | ||
| 4873 | FREESCALE QUICC ENGINE UCC HDLC DRIVER | ||
| 4874 | M: Zhao Qiang <qiang.zhao@nxp.com> | ||
| 4875 | L: netdev@vger.kernel.org | ||
| 4876 | L: linuxppc-dev@lists.ozlabs.org | ||
| 4877 | S: Maintained | ||
| 4878 | F: drivers/net/wan/fsl_ucc_hdlc* | ||
| 4879 | |||
| 4873 | FREESCALE QUICC ENGINE UCC UART DRIVER | 4880 | FREESCALE QUICC ENGINE UCC UART DRIVER |
| 4874 | M: Timur Tabi <timur@tabi.org> | 4881 | M: Timur Tabi <timur@tabi.org> |
| 4875 | L: linuxppc-dev@lists.ozlabs.org | 4882 | L: 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 | ||
| 283 | config 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 | |||
| 283 | config DSCC4_PCISYNC | 294 | config 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 | |||
| 32 | obj-$(CONFIG_PCI200SYN) += pci200syn.o | 32 | obj-$(CONFIG_PCI200SYN) += pci200syn.o |
| 33 | obj-$(CONFIG_PC300TOO) += pc300too.o | 33 | obj-$(CONFIG_PC300TOO) += pc300too.o |
| 34 | obj-$(CONFIG_IXP4XX_HSS) += ixp4xx_hss.o | 34 | obj-$(CONFIG_IXP4XX_HSS) += ixp4xx_hss.o |
| 35 | obj-$(CONFIG_FSL_UCC_HDLC) += fsl_ucc_hdlc.o | ||
| 35 | 36 | ||
| 36 | clean-files := wanxlfw.inc | 37 | clean-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 | |||
| 41 | static 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 | |||
| 80 | static struct ucc_tdm_info utdm_info[MAX_HDLC_NUM]; | ||
| 81 | |||
| 82 | static 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 | |||
