lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Wed, 16 Oct 2013 17:25:35 +0200
From:	Christophe Leroy <christophe.leroy@....fr>
To:	Rob Herring <rob.herring@...xeda.com>,
	Pawel Moll <pawel.moll@....com>,
	Mark Rutland <mark.rutland@....com>,
	Stephen Warren <swarren@...dotorg.org>,
	Ian Campbell <ijc+devicetree@...lion.org.uk>,
	Rob Landley <rob@...dley.net>,
	Grant Likely <grant.likely@...aro.org>,
	Krzysztof Halasa <khc@...waw.pl>
CC:	devicetree@...r.kernel.org, linux-doc@...r.kernel.org,
	linux-kernel@...r.kernel.org, netdev@...r.kernel.org,
	devicetree@...r.kernel.org, jerome.chantelauze@....fr
Subject: [PATCH] WAN: Adding support for Infineon PEF2256 E1 chipset

The patch adds WAN support for Infineon PEF2256 E1 Chipset.

Signed-off-by: Jerome Chantelauze <jerome.chantelauze@....fr>
Acked-by: Christophe Leroy <christophe.leroy@....fr>

diff -urN a/drivers/net/wan/pef2256.c b/drivers/net/wan/pef2256.c
--- a/drivers/net/wan/pef2256.c	1970-01-01 01:00:00.000000000 +0100
+++ b/drivers/net/wan/pef2256.c	2013-10-13 13:05:01.000000000 +0200
@@ -0,0 +1,1124 @@
+/*
+ * drivers/net/wan/pef2256.c : a PEF2256 HDLC driver for Linux
+ *
+ * This software may be used and distributed according to the terms of the
+ * GNU General Public License.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <linux/cache.h>
+#include <asm/byteorder.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <asm/irq.h>
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/hdlc.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+#include <linux/etherdevice.h>
+#include "pef2256.h"
+
+static irqreturn_t pef2256_irq(int irq, void *dev_priv);
+static int Config_HDLC(struct pef2256_dev_priv *priv);
+static int init_FALC(struct pef2256_dev_priv *priv);
+static int pef2256_open(struct net_device *netdev);
+static int pef2256_close(struct net_device *netdev);
+
+void print_regs(struct device *dev)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct pef2256_dev_priv *priv = dev_to_hdlc(ndev)->priv;
+	struct pef2256_regs *base_addr = (struct pef2256_regs *)priv->base_addr;
+
+	netdev_info(ndev, "	MODE = 0x%02x\n", base_addr->MODE);
+	netdev_info(ndev, "	RAH1 = 0x%02x\n", base_addr->RAH1);
+	netdev_info(ndev, "	RAH2 = 0x%02x\n", base_addr->RAH2);
+	netdev_info(ndev, "	RAL1 = 0x%02x\n", base_addr->RAL1);
+	netdev_info(ndev, "	RAL2 = 0x%02x\n", base_addr->RAL2);
+	netdev_info(ndev, "	IPC = 0x%02x\n", base_addr->IPC);
+	netdev_info(ndev, "	CCR1 = 0x%02x\n", base_addr->CCR1);
+	netdev_info(ndev, "	CCR2 = 0x%02x\n", base_addr->CCR2);
+	netdev_info(ndev, "	RTR1 = 0x%02x\n", base_addr->RTR1);
+	netdev_info(ndev, "	RTR2 = 0x%02x\n", base_addr->RTR2);
+	netdev_info(ndev, "	RTR3 = 0x%02x\n", base_addr->RTR3);
+	netdev_info(ndev, "	RTR4 = 0x%02x\n", base_addr->RTR4);
+	netdev_info(ndev, "	TTR1 = 0x%02x\n", base_addr->TTR1);
+	netdev_info(ndev, "	TTR2 = 0x%02x\n", base_addr->TTR2);
+	netdev_info(ndev, "	TTR3 = 0x%02x\n", base_addr->TTR3);
+	netdev_info(ndev, "	TTR4 = 0x%02x\n", base_addr->TTR4);
+	netdev_info(ndev, "	IMR0 = 0x%02x\n", base_addr->IMR0);
+	netdev_info(ndev, "	IMR1 = 0x%02x\n", base_addr->IMR1);
+	netdev_info(ndev, "	IMR2 = 0x%02x\n", base_addr->IMR2);
+	netdev_info(ndev, "	IMR3 = 0x%02x\n", base_addr->IMR3);
+	netdev_info(ndev, "	IMR4 = 0x%02x\n", base_addr->IMR4);
+	netdev_info(ndev, "	IMR5 = 0x%02x\n", base_addr->IMR5);
+	netdev_info(ndev, "	IERR = 0x%02x\n", base_addr->IERR);
+	netdev_info(ndev, "	FMR0 = 0x%02x\n", base_addr->FMR0);
+	netdev_info(ndev, "	FMR1 = 0x%02x\n", base_addr->FMR1);
+	netdev_info(ndev, "	FMR2 = 0x%02x\n", base_addr->FMR2);
+	netdev_info(ndev, "	LOOP = 0x%02x\n", base_addr->LOOP);
+	netdev_info(ndev, "	XSW = 0x%02x\n", base_addr->XSW);
+	netdev_info(ndev, "	XSP = 0x%02x\n", base_addr->XSP);
+	netdev_info(ndev, "	XC0 = 0x%02x\n", base_addr->XC0);
+	netdev_info(ndev, "	XC1 = 0x%02x\n", base_addr->XC1);
+	netdev_info(ndev, "	RC0 = 0x%02x\n", base_addr->RC0);
+	netdev_info(ndev, "	RC1 = 0x%02x\n", base_addr->RC1);
+	netdev_info(ndev, "	XPM0 = 0x%02x\n", base_addr->XPM0);
+	netdev_info(ndev, "	XPM1 = 0x%02x\n", base_addr->XPM1);
+	netdev_info(ndev, "	XPM2 = 0x%02x\n", base_addr->XPM2);
+	netdev_info(ndev, "	TSWM = 0x%02x\n", base_addr->TSWM);
+	netdev_info(ndev, "	IDLE = 0x%02x\n", base_addr->IDLE);
+	netdev_info(ndev, "	XSA4 = 0x%02x\n", base_addr->XSA4);
+	netdev_info(ndev, "	XSA5 = 0x%02x\n", base_addr->XSA5);
+	netdev_info(ndev, "	XSA6 = 0x%02x\n", base_addr->XSA6);
+	netdev_info(ndev, "	XSA7 = 0x%02x\n", base_addr->XSA7);
+	netdev_info(ndev, "	XSA8 = 0x%02x\n", base_addr->XSA8);
+	netdev_info(ndev, "	FMR3 = 0x%02x\n", base_addr->FMR3);
+	netdev_info(ndev, "	ICB1 = 0x%02x\n", base_addr->ICB1);
+	netdev_info(ndev, "	ICB2 = 0x%02x\n", base_addr->ICB2);
+	netdev_info(ndev, "	ICB3 = 0x%02x\n", base_addr->ICB3);
+	netdev_info(ndev, "	ICB4 = 0x%02x\n", base_addr->ICB4);
+	netdev_info(ndev, "	LIM0 = 0x%02x\n", base_addr->LIM0);
+	netdev_info(ndev, "	LIM1 = 0x%02x\n", base_addr->LIM1);
+	netdev_info(ndev, "	PCD = 0x%02x\n", base_addr->PCD);
+	netdev_info(ndev, "	PCR = 0x%02x\n", base_addr->PCR);
+	netdev_info(ndev, "	LIM2 = 0x%02x\n", base_addr->LIM2);
+	netdev_info(ndev, "	LCR1 = 0x%02x\n", base_addr->LCR1);
+	netdev_info(ndev, "	LCR2 = 0x%02x\n", base_addr->LCR2);
+	netdev_info(ndev, "	LCR3 = 0x%02x\n", base_addr->LCR3);
+	netdev_info(ndev, "	SIC1 = 0x%02x\n", base_addr->SIC1);
+	netdev_info(ndev, "	SIC2 = 0x%02x\n", base_addr->SIC2);
+	netdev_info(ndev, "	SIC3 = 0x%02x\n", base_addr->SIC3);
+	netdev_info(ndev, "	CMR1 = 0x%02x\n", base_addr->CMR1);
+	netdev_info(ndev, "	CMR2 = 0x%02x\n", base_addr->CMR2);
+	netdev_info(ndev, "	GCR = 0x%02x\n", base_addr->GCR);
+	netdev_info(ndev, "	ESM = 0x%02x\n", base_addr->ESM);
+	netdev_info(ndev, "	CMR3 = 0x%02x\n", base_addr->CMR3);
+	netdev_info(ndev, "	PC1 = 0x%02x\n", base_addr->PC1);
+	netdev_info(ndev, "	PC2 = 0x%02x\n", base_addr->PC2);
+	netdev_info(ndev, "	PC3 = 0x%02x\n", base_addr->PC3);
+	netdev_info(ndev, "	PC4 = 0x%02x\n", base_addr->PC4);
+	netdev_info(ndev, "	PC5 = 0x%02x\n", base_addr->PC5);
+	netdev_info(ndev, "	GPC1 = 0x%02x\n", base_addr->GPC1);
+	netdev_info(ndev, "	PC6 = 0x%02x\n", base_addr->PC6);
+	netdev_info(ndev, "	CCR3 = 0x%02x\n", base_addr->CCR3);
+	netdev_info(ndev, "	CCR4 = 0x%02x\n", base_addr->CCR4);
+	netdev_info(ndev, "	CCR5 = 0x%02x\n", base_addr->CCR5);
+	netdev_info(ndev, "	MODE2 = 0x%02x\n", base_addr->MODE2);
+	netdev_info(ndev, "	MODE3 = 0x%02x\n", base_addr->MODE3);
+	netdev_info(ndev, "	RBC2 = 0x%02x\n", base_addr->RBC2);
+	netdev_info(ndev, "	RBC3 = 0x%02x\n", base_addr->RBC3);
+	netdev_info(ndev, "	GCM1 = 0x%02x\n", base_addr->GCM1);
+	netdev_info(ndev, "	GCM2 = 0x%02x\n", base_addr->GCM2);
+	netdev_info(ndev, "	GCM3 = 0x%02x\n", base_addr->GCM3);
+	netdev_info(ndev, "	GCM4 = 0x%02x\n", base_addr->GCM4);
+	netdev_info(ndev, "	GCM5 = 0x%02x\n", base_addr->GCM5);
+	netdev_info(ndev, "	GCM6 = 0x%02x\n", base_addr->GCM6);
+	netdev_info(ndev, "	SIS2/GCM7 = 0x%02x\n", base_addr->Dif1.SIS2);
+	netdev_info(ndev, "	RSIS2/GCM8 = 0x%02x\n",
+						base_addr->Dif2.RSIS2);
+	netdev_info(ndev, "	TSEO = 0x%02x\n", base_addr->TSEO);
+	netdev_info(ndev, "	TSBS1 = 0x%02x\n", base_addr->TSBS1);
+	netdev_info(ndev, "	TSBS2 = 0x%02x\n", base_addr->TSBS2);
+	netdev_info(ndev, "	TSBS3 = 0x%02x\n", base_addr->TSBS3);
+	netdev_info(ndev, "	TSS2 = 0x%02x\n", base_addr->TSS2);
+	netdev_info(ndev, "	TSS3 = 0x%02x\n", base_addr->TSS3);
+	netdev_info(ndev, "	Res10 = 0x%02x\n", base_addr->Res10);
+	netdev_info(ndev, "	Res11 = 0x%02x\n", base_addr->Res11);
+	netdev_info(ndev, "	TPC0 = 0x%02x\n", base_addr->TPC0);
+	netdev_info(ndev, "	GLC1 = 0x%02x\n", base_addr->GLC1);
+}
+
+static ssize_t fs_attr_regs_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	print_regs(dev);
+	return sprintf(buf, "*** printk DEBUG ***\n");
+}
+
+static DEVICE_ATTR(regs, S_IRUGO, fs_attr_regs_show, NULL);
+
+static ssize_t fs_attr_mode_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct pef2256_dev_priv *priv = dev_to_hdlc(ndev)->priv;
+
+	return sprintf(buf, "%d\n", priv->mode);
+}
+
+
+static ssize_t fs_attr_mode_store(struct device *dev,
+			struct device_attribute *attr,  const char *buf,
+			size_t count)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct pef2256_dev_priv *priv = dev_to_hdlc(ndev)->priv;
+	u32 value;
+	int ret = kstrtol(buf, 10, (long int *)&value);
+	int reconfigure = (value != priv->mode);
+
+	if (ret != 0)
+		return ret;
+
+	if (value != MASTER_MODE && value != SLAVE_MODE)
+		return -EINVAL;
+
+	priv->mode = value;
+	if (reconfigure && priv->init_done) {
+		pef2256_close(ndev);
+		init_FALC(priv);
+		pef2256_open(ndev);
+	}
+
+	return count;
+}
+
+static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR, fs_attr_mode_show,
+						fs_attr_mode_store);
+
+
+
+static ssize_t fs_attr_Tx_TS_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct pef2256_dev_priv *priv = dev_to_hdlc(ndev)->priv;
+
+	return sprintf(buf, "0x%08x\n", priv->Tx_TS);
+}
+
+
+static ssize_t fs_attr_Tx_TS_store(struct device *dev,
+			struct device_attribute *attr,  const char *buf,
+			size_t count)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct pef2256_dev_priv *priv = dev_to_hdlc(ndev)->priv;
+	u32 value;
+	int ret = kstrtol(buf, 10, (long int *)&value);
+	int reconfigure = (value != priv->mode);
+
+	if (ret != 0)
+		return ret;
+
+	/* TS 0 is reserved */
+	if (value & 0x80000000)
+		return -EINVAL;
+
+	priv->Tx_TS = value;
+	if (reconfigure && priv->init_done)
+		Config_HDLC(priv);
+
+	return count;
+}
+
+static DEVICE_ATTR(Tx_TS, S_IRUGO | S_IWUSR, fs_attr_Tx_TS_show,
+			fs_attr_Tx_TS_store);
+
+
+static ssize_t fs_attr_Rx_TS_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct pef2256_dev_priv *priv = dev_to_hdlc(ndev)->priv;
+
+	return sprintf(buf, "0x%08x\n", priv->Rx_TS);
+}
+
+
+static ssize_t fs_attr_Rx_TS_store(struct device *dev,
+			struct device_attribute *attr,  const char *buf,
+			size_t count)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct pef2256_dev_priv *priv = dev_to_hdlc(ndev)->priv;
+	u32 value;
+	int ret = kstrtol(buf, 10, (long int *)&value);
+	int reconfigure = (value != priv->mode);
+
+	if (ret != 0)
+		return ret;
+
+	/* TS 0 is reserved */
+	if (value & 0x80000000)
+		return -EINVAL;
+
+	priv->Rx_TS = value;
+	if (reconfigure && priv->init_done)
+		Config_HDLC(priv);
+
+	return count;
+}
+
+static DEVICE_ATTR(Rx_TS, S_IRUGO | S_IWUSR, fs_attr_Rx_TS_show,
+	 fs_attr_Rx_TS_store);
+
+/*
+ * Setting up HDLC channel
+ */
+int Config_HDLC(struct pef2256_dev_priv *priv)
+{
+	int i;
+	int TS_idx;
+	struct pef2256_regs *base_addr;
+	u8 dummy;
+
+	/* Set framer E1 address */
+	base_addr = (struct pef2256_regs *)priv->base_addr;
+
+	/* Read to remove pending IT */
+	dummy = base_addr->ISR0;
+	dummy = base_addr->ISR1;
+
+	/* Mask HDLC 1 Transmit IT */
+	base_addr->IMR1 |= 1;
+	base_addr->IMR1 |= 1 << 4;
+	base_addr->IMR1 |= 1 << 5;
+
+	/* Mask HDLC 1 Receive IT */
+	base_addr->IMR0 |= 1;
+	base_addr->IMR0 |= 1 << 7;
+	base_addr->IMR1 |= 1 << 6;
+
+	udelay((2 * 32) * 125);
+
+	/* MODE.HRAC = 0 (Receiver inactive)
+	   MODE.DIV = 0 (Data normal operation)
+	   for FALC V2.2 : MODE.HDLCI = 0 (normal operation) */
+	/* MODE.MDS2:0 = 100 (No address comparison) */
+	/* MODE.HRAC = 1 (Receiver active) */
+	out_8(&(base_addr->MODE), 1 << 3);
+	/* CCR1.EITS = 1 (Enable internal Time Slot 31:0 Signaling)
+	   CCR1.XMFA = 0 (No transmit multiframe alignment)
+	   CCR1.RFT1:0 = 00 (RFIFO sur 32 bytes) */
+	/* setting up Interframe Time Fill */
+	/* CCR1.ITF = 1 (Interframe Time Fill Continuous flag) */
+	out_8(&(base_addr->CCR1), 0x10 | (1 << 3));
+	/* CCR2.XCRC = 0 (Transmit CRC ON)
+	   CCR2.RCRC = 0 (Receive CRC ON, no write in RFIFO)
+	   CCR2.RADD = 0 (No write address in RFIFO) */
+	out_8(&(base_addr->CCR2), 0x00);
+
+	udelay((2 * 32) * 125);
+
+	/* MODE.HRAC = 0 (Receiver inactive)
+	   MODE.DIV = 0 (Data normal operation)
+	   for FALC V2.2 : MODE.HDLCI = 0 (normal operation) */
+	/* MODE.MDS2:0 = 100 (No address comparison) */
+	/* MODE.HRAC = 1 (Receiver active) */
+	out_8(&(base_addr->MODE), 1 << 3);
+	/* CCR1.EITS = 1 (Enable internal Time Slot 31:0 Signaling)
+	   CCR1.XMFA = 0 (No transmit multiframe alignment)
+	   CCR1.RFT1:0 = 00 (RFIFO sur 32 bytes) */
+	/* setting up Interframe Time Fill */
+	/* CCR1.ITF = 1 (Interframe Time Fill Continuous flag) */
+	out_8(&(base_addr->CCR1), 0x10 | (1 << 3));
+	/* CCR2.XCRC = 0 (Transmit CRC ON)
+	   CCR2.RCRC = 0 (Receive CRC ON, no write in RFIFO)
+	   CCR2.RADD = 0 (No write address in RFIFO) */
+	out_8(&(base_addr->CCR2), 0x00);
+
+	udelay((2 * 32) * 125);
+
+	/* MODE.HRAC = 0 (Receiver inactive)
+	   MODE.DIV = 0 (Data normal operation)
+	   for FALC V2.2 : MODE.HDLCI = 0 (normal operation) */
+	/* MODE.MDS2:0 = 100 (No address comparison) */
+	/* MODE.HRAC = 1 (Receiver active) */
+	out_8(&(base_addr->MODE), 1 << 3);
+	/* CCR1.EITS = 1 (Enable internal Time Slot 31:0 Signaling)
+	   CCR1.XMFA = 0 (No transmit multiframe alignment)
+	   CCR1.RFT1:0 = 00 (RFIFO sur 32 bytes) */
+	/* setting up Interframe Time Fill */
+	/* CCR1.ITF = 1 (Interframe Time Fill Continuous flag) */
+	out_8(&(base_addr->CCR1), 0x10 | (1 << 3));
+	/* CCR2.XCRC = 0 (Transmit CRC ON)
+	   CCR2.RCRC = 0 (Receive CRC ON, no write in RFIFO)
+	   CCR2.RADD = 0 (No write address in RFIFO) */
+	out_8(&(base_addr->CCR2), 0x00);
+
+	udelay((2 * 32) * 125);
+
+	/* Init  Time Slot select */
+	out_8(&(base_addr->TTR1), 0x00);
+	out_8(&(base_addr->TTR2), 0x00);
+	out_8(&(base_addr->TTR3), 0x00);
+	out_8(&(base_addr->TTR4), 0x00);
+	out_8(&(base_addr->RTR1), 0x00);
+	out_8(&(base_addr->RTR2), 0x00);
+	out_8(&(base_addr->RTR3), 0x00);
+	out_8(&(base_addr->RTR4), 0x00);
+	/* Set selected TS bits */
+	/* Starting at TS 1, TS 0 is reserved */
+	for (TS_idx = 1; TS_idx < 32; TS_idx++) {
+		i = 7 - (TS_idx % 8);
+		switch (TS_idx / 8) {
+		case 0:
+			if (priv->Tx_TS & (1 << (31 - TS_idx)))
+				setbits8(&(base_addr->TTR1), 1 << i);
+			if (priv->Rx_TS & (1 << (31 - TS_idx)))
+				setbits8(&(base_addr->RTR1), 1 << i);
+			break;
+		case 1:
+			if (priv->Tx_TS & (1 << (31 - TS_idx)))
+				setbits8(&(base_addr->TTR2), 1 << i);
+			if (priv->Rx_TS & (1 << (31 - TS_idx)))
+				setbits8(&(base_addr->RTR2), 1 << i);
+			break;
+		case 2:
+			if (priv->Tx_TS & (1 << (31 - TS_idx)))
+				setbits8(&(base_addr->TTR3), 1 << i);
+			if (priv->Rx_TS & (1 << (31 - TS_idx)))
+				setbits8(&(base_addr->RTR3), 1 << i);
+			break;
+		case 3:
+			if (priv->Tx_TS & (1 << (31 - TS_idx)))
+				setbits8(&(base_addr->TTR4), 1 << i);
+			if (priv->Rx_TS & (1 << (31 - TS_idx)))
+				setbits8(&(base_addr->RTR4), 1 << i);
+			break;
+		}
+	}
+
+	/* Unmask HDLC 1 Transmit IT */
+	base_addr->IMR1 &= ~1;
+	base_addr->IMR1 &= ~(1 << 4);
+	base_addr->IMR1 &= ~(1 << 5);
+
+	/* Unmask HDLC 1 Receive IT */
+	base_addr->IMR0 &= ~1;
+	base_addr->IMR0 &= ~(1 << 7);
+	base_addr->IMR1 &= ~(1 << 6);
+
+	return 0;
+}
+
+
+/*
+ * Init FALC56
+ */
+static int init_FALC(struct pef2256_dev_priv *priv)
+{
+	struct pef2256_regs *base_addr;
+	int Version;
+
+	/* Get controller version */
+	Version = priv->component_id;
+
+	/* Init FALC56 */
+	base_addr = (struct pef2256_regs *)priv->base_addr;
+	/* RCLK output : DPLL clock, DCO-X enabled, DCO-X internal reference
+	   clock */
+	out_8(&(base_addr->CMR1), 0x00);
+	/* SCLKR selected, SCLKX selected, receive synchro pulse sourced by
+	   SYPR, transmit synchro pulse sourced by SYPX */
+	out_8(&(base_addr->CMR2), 0x00);
+	/* NRZ coding, no alarm simulation */
+	out_8(&(base_addr->FMR0), 0x00);
+	/* E1 double frame format, 2 Mbit/s system data rate, no AIS
+	   transmission to remote end or system interface, payload loop
+	   off, transmit remote alarm on */
+	out_8(&(base_addr->FMR1), 0x00);
+	out_8(&(base_addr->FMR2), 0x02);
+	/* E1 default for LIM2 */
+	out_8(&(base_addr->LIM2), 0x20);
+	if (priv->mode == MASTER_MODE)
+		/* SEC input, active high */
+		out_8(&(base_addr->GPC1), 0x00);
+	else
+		/* FSC output, active high */
+		out_8(&(base_addr->GPC1), 0x40);
+	/* internal second timer, power on */
+	out_8(&(base_addr->GCR), 0x00);
+	/* slave mode, local loop off, mode short-haul */
+	if (Version == VERSION_1_2)
+		out_8(&(base_addr->LIM0), 0x00);
+	else
+		out_8(&(base_addr->LIM0), 0x08);
+	/* analog interface selected, remote loop off */
+	out_8(&(base_addr->LIM1), 0x00);
+	if (Version == VERSION_1_2) {
+		/* function of ports RP(A to D) : output receive sync pulse
+		   function of ports XP(A to D) : output transmit line clock */
+		out_8(&(base_addr->PC1), 0x77);
+		out_8(&(base_addr->PC2), 0x77);
+		out_8(&(base_addr->PC3), 0x77);
+		out_8(&(base_addr->PC4), 0x77);
+	} else {
+		/* function of ports RP(A to D) : output high
+		   function of ports XP(A to D) : output high */
+		out_8(&(base_addr->PC1), 0xAA);
+		out_8(&(base_addr->PC2), 0xAA);
+		out_8(&(base_addr->PC3), 0xAA);
+		out_8(&(base_addr->PC4), 0xAA);
+	}
+	/* function of port RPA : input SYPR
+	   function of port XPA : input SYPX */
+	out_8(&(base_addr->PC1), 0x00);
+	/* SCLKR, SCLKX, RCLK configured to inputs,
+	   XFMS active low, CLK1 and CLK2 pin configuration */
+	out_8(&(base_addr->PC5), 0x00);
+	out_8(&(base_addr->PC6), 0x00);
+	/* the receive clock offset is cleared
+	   the receive time slot offset is cleared */
+	out_8(&(base_addr->RC0), 0x00);
+	out_8(&(base_addr->RC1), 0x9C);
+	/* 2.048 MHz system clocking rate, receive buffer 2 frames, transmit
+	   buffer bypass, data sampled and transmitted on the falling edge of
+	   SCLKR/X, automatic freeze signaling, data is active in the first
+	   channel phase */
+	out_8(&(base_addr->SIC1), 0x00);
+	out_8(&(base_addr->SIC2), 0x00);
+	out_8(&(base_addr->SIC3), 0x00);
+	/* channel loop-back and single frame mode are disabled */
+	out_8(&(base_addr->LOOP), 0x00);
+	/* all bits of the transmitted service word are cleared */
+	out_8(&(base_addr->XSW), 0x1F);
+	/* spare bit values are cleared */
+	out_8(&(base_addr->XSP), 0x00);
+	/* no transparent mode active */
+	out_8(&(base_addr->TSWM), 0x00);
+	/* the transmit clock offset is cleared
+	   the transmit time slot offset is cleared */
+	out_8(&(base_addr->XC0), 0x00);
+	out_8(&(base_addr->XC1), 0x9C);
+	/* transmitter in tristate mode */
+	out_8(&(base_addr->XPM2), 0x40);
+	/* transmit pulse mask */
+	if (Version != VERSION_1_2)
+		out_8(&(base_addr->XPM0), 0x9C);
+
+	if (Version == VERSION_1_2) {
+		/* master clock is 16,384 MHz (flexible master clock) */
+		out_8(&(base_addr->GCM2), 0x58);
+		out_8(&(base_addr->GCM3), 0xD2);
+		out_8(&(base_addr->GCM4), 0xC2);
+		out_8(&(base_addr->GCM5), 0x07);
+		out_8(&(base_addr->GCM6), 0x10);
+	} else {
+		/* master clock is 16,384 MHz (flexible master clock) */
+		out_8(&(base_addr->GCM2), 0x18);
+		out_8(&(base_addr->GCM3), 0xFB);
+		out_8(&(base_addr->GCM4), 0x0B);
+		out_8(&(base_addr->GCM5), 0x01);
+		out_8(&(base_addr->GCM6), 0x0B);
+		out_8(&(base_addr->Dif1.GCM7), 0xDB);
+		out_8(&(base_addr->Dif2.GCM8), 0xDF);
+	}
+
+	/* master mode => LIM0.MAS = 1 (bit 0) */
+	if (priv->mode == MASTER_MODE)
+		setbits8(&(base_addr->LIM0), 1 << 0);
+
+	/* transmit line in normal operation => XPM2.XLT = 0 (bit 6) */
+	clrbits8(&(base_addr->XPM2), 1 << 6);
+
+	if (Version == VERSION_1_2) {
+		/* receive input threshold = 0,21V =>
+			LIM1.RIL2:0 = 101 (bits 6, 5 et 4) */
+		setbits8(&(base_addr->LIM1), 1 << 4);
+		setbits8(&(base_addr->LIM1), 1 << 6);
+	} else {
+		/* receive input threshold = 0,21V =>
+			LIM1.RIL2:0 = 100 (bits 6, 5 et 4) */
+		setbits8(&(base_addr->LIM1), 1 << 6);
+	}
+	/* transmit line coding = HDB3 => FMR0.XC1:0 = 11 (bits 7 et 6) */
+	setbits8(&(base_addr->FMR0), 1 << 6);
+	setbits8(&(base_addr->FMR0), 1 << 7);
+	/* receive line coding = HDB3 => FMR0.RC1:0 = 11 (bits 5 et 4) */
+	setbits8(&(base_addr->FMR0), 1 << 4);
+	setbits8(&(base_addr->FMR0), 1 << 5);
+	/* detection of LOS alarm = 176 pulses (soit (10 + 1) * 16) */
+	out_8(&(base_addr->PCD), 10);
+	/* recovery of LOS alarm = 22 pulses (soit 21 + 1) */
+	out_8(&(base_addr->PCR), 21);
+	/* DCO-X center frequency => CMR2.DCOXC = 1 (bit 5) */
+	setbits8(&(base_addr->CMR2), 1 << 5);
+	if (priv->mode == SLAVE_MODE) {
+		/* select RCLK source = 2M => CMR1.RS(1:0) = 10 (bits 5 et 4) */
+		setbits8(&(base_addr->CMR1), 1 << 5);
+		/* disable switching RCLK -> SYNC => CMR1.DCS = 1 (bit 3) */
+		setbits8(&(base_addr->CMR1), 1 << 3);
+	}
+	if (Version != VERSION_1_2)
+		/* during inactive channel phase RDO into tri-state mode */
+		setbits8(&(base_addr->SIC3), 1 << 5);
+	if (!strcmp(priv->rising_edge_sync_pulse, "transmit")) {
+		/* rising edge sync pulse transmit => SIC3.RESX = 1 (bit 3) */
+		setbits8(&(base_addr->SIC3), 1 << 3);
+	} else {
+		/* rising edge sync pulse receive => SIC3.RESR = 1 (bit 2) */
+		setbits8(&(base_addr->SIC3), 1 << 2);
+	}
+	/* transmit offset counter = 4
+	   => XC0.XCO10:8 = 000 (bits 2, 1 et 0);
+	      XC1.XCO7:0 = 4 (bits 7 ... 0) */
+	out_8(&(base_addr->XC1), 4);
+	/* receive offset counter = 4
+	   => RC0.RCO10:8 = 000 (bits 2, 1 et 0);
+	      RC1.RCO7:0 = 4 (bits 7 ... 0) */
+	out_8(&(base_addr->RC1), 4);
+
+	/* clocking rate 8M and data rate 2M on the system highway */
+	setbits8(&(base_addr->SIC1), 1 << 7);
+	/* data rate 4M on the system highway */
+	if (priv->data_rate == DATA_RATE_4M)
+		setbits8(&(base_addr->FMR1), 1 << 1);
+	/* data rate 8M on the system highway */
+	if (priv->data_rate == DATA_RATE_8M)
+		setbits8(&(base_addr->SIC1), 1 << 6);
+	/* channel phase for FALC56 */
+	if ((priv->channel_phase == CHANNEL_PHASE_1)
+		|| (priv->channel_phase == CHANNEL_PHASE_3))
+		setbits8(&(base_addr->SIC2), 1 << 1);
+	if ((priv->channel_phase == CHANNEL_PHASE_2)
+		|| (priv->channel_phase == CHANNEL_PHASE_3))
+		setbits8(&(base_addr->SIC2), 1 << 2);
+
+	if (priv->mode == SLAVE_MODE) {
+		/* transmit buffer size = 2 frames =>
+			SIC1.XBS1:0 = 10 (bits 1 et 0) */
+		setbits8(&(base_addr->SIC1), 1 << 1);
+	}
+
+	/* transmit in multiframe => FMR1.XFS = 1 (bit 3) */
+	setbits8(&(base_addr->FMR1), 1 << 3);
+	/* receive in multiframe => FMR2.RFS1:0 = 10 (bits 7 et 6) */
+	setbits8(&(base_addr->FMR2), 1 << 7);
+	/* Automatic transmission of submultiframe status =>
+		XSP.AXS = 1 (bit 3) */
+	setbits8(&(base_addr->XSP), 1 << 3);
+
+	/* error counter mode toutes les 1s => FMR1.ECM = 1 (bit 2) */
+	setbits8(&(base_addr->FMR1), 1 << 2);
+	/* error counter mode COFA => GCR.ECMC = 1 (bit 4) */
+	setbits8(&(base_addr->GCR), 1 << 4);
+	/* errors in service words with no influence => RC0.SWD = 1 (bit 7) */
+	setbits8(&(base_addr->RC0), 1 << 7);
+	/* 4 consecutive incorrect FAS = loss of sync => RC0.ASY4 = 1 (bit 6) */
+	setbits8(&(base_addr->RC0), 1 << 6);
+	/* Si-Bit in service word from XDI => XSW.XSIS = 1 (bit 7) */
+	setbits8(&(base_addr->XSW), 1 << 7);
+	/* Si-Bit in FAS word from XDI => XSP.XSIF = 1 (bit 2) */
+	setbits8(&(base_addr->XSP), 1 << 2);
+
+	/* port RCLK is output => PC5.CRP = 1 (bit 0) */
+	setbits8(&(base_addr->PC5), 1 << 0);
+	/* visibility of the masked interrupts => GCR.VIS = 1 (bit 7) */
+	setbits8(&(base_addr->GCR), 1 << 7);
+	/* reset lines
+	   => CMDR.RRES = 1 (bit 6); CMDR.XRES = 1 (bit 4);
+	      CMDR.SRES = 1 (bit 0) */
+	out_8(&(base_addr->CMDR), 0x51);
+
+	return 0;
+}
+
+
+
+static int pef2256_open(struct net_device *netdev)
+{
+	struct pef2256_dev_priv *priv = dev_to_hdlc(netdev)->priv;
+	struct pef2256_regs *base_addr = (struct pef2256_regs *)priv->base_addr;
+	int ret;
+
+	if (hdlc_open(netdev))
+		return -EAGAIN;
+
+	ret = request_irq(priv->irq, pef2256_irq, 0, "e1-wan", priv);
+	if (ret) {
+		dev_err(priv->dev, "Cannot request irq. Device seems busy.\n");
+		return -EBUSY;
+	}
+
+	if (priv->component_id != VERSION_UNDEF) {
+		ret = init_FALC(priv);
+	} else {
+		dev_err(priv->dev, "Composant ident (%X/%X) = %d\n",
+			base_addr->VSTR, base_addr->WID, priv->component_id);
+		ret = -ENODEV;
+	}
+
+	if (ret < 0)
+		return ret;
+
+	priv->tx_skb = NULL;
+	priv->rx_len = 0;
+
+	Config_HDLC(priv);
+
+	netif_carrier_on(netdev);
+	netif_start_queue(netdev);
+
+	priv->init_done = 1;
+
+	return 0;
+}
+
+
+static int pef2256_close(struct net_device *netdev)
+{
+	struct pef2256_dev_priv *priv = dev_to_hdlc(netdev)->priv;
+
+	if (!priv->init_done)
+		return 0;
+
+	priv->init_done = 0;
+	netif_stop_queue(netdev);
+	hdlc_close(netdev);
+	free_irq(priv->irq, priv);
+
+	/* Do E1 stuff */
+
+	return 0;
+}
+
+
+
+static int pef2256_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	int ret;
+
+	ret = hdlc_ioctl(dev, ifr, cmd);
+	return ret;
+}
+
+static int pef2256_rx(struct pef2256_dev_priv *priv)
+{
+	struct sk_buff *skb;
+	int idx, size;
+	struct pef2256_regs *base_addr;
+
+	base_addr = priv->base_addr;
+
+	/* RDO has been received -> wait for RME */
+	if (priv->rx_len == -1) {
+		/* Acknowledge the FIFO */
+		setbits8(&(base_addr->CMDR), 1 << 7);
+
+		if (priv->ISR0 & (1 << 7))
+			priv->rx_len = 0;
+
+		return 0;
+	}
+
+	/* RPF : a block is available in the receive FIFO */
+	if (priv->ISR0 & 1) {
+		for (idx = 0; idx < 32; idx++)
+			priv->rx_buff[priv->rx_len + idx] =
+				base_addr->FIFO.RFIFO[idx & 1];
+
+		/* Acknowledge the FIFO */
+		setbits8(&(base_addr->CMDR), 1 << 7);
+
+		priv->rx_len += 32;
+	}
+
+	/* RME : Message end : Read the receive FIFO */
+	if (priv->ISR0 & (1 << 7)) {
+		/* Get size of last block */
+		size = base_addr->RBCL & 0x1F;
+
+		/* Read last block */
+		for (idx = 0; idx < size; idx++)
+			priv->rx_buff[priv->rx_len + idx] =
+				base_addr->FIFO.RFIFO[idx & 1];
+
+		/* Acknowledge the FIFO */
+		setbits8(&(base_addr->CMDR), 1 << 7);
+
+		priv->rx_len += size;
+
+		/* Packet received */
+		if (priv->rx_len > 0) {
+			skb = dev_alloc_skb(priv->rx_len);
+			if (!skb) {
+				priv->rx_len = 0;
+				priv->netdev->stats.rx_dropped++;
+				return -ENOMEM;
+			}
+			memcpy(skb->data, priv->rx_buff, priv->rx_len);
+			skb_put(skb, priv->rx_len);
+			priv->rx_len = 0;
+			skb->protocol = hdlc_type_trans(skb, priv->netdev);
+			priv->netdev->stats.rx_packets++;
+			priv->netdev->stats.rx_bytes += skb->len;
+			netif_rx(skb);
+		}
+	}
+
+	return 0;
+}
+
+
+static int pef2256_tx(struct pef2256_dev_priv *priv)
+{
+	int idx, size;
+	struct pef2256_regs *base_addr;
+	u8 *tx_buff = priv->tx_skb->data;
+
+	base_addr = (struct pef2256_regs *)priv->base_addr;
+
+	/* ALLS : transmit all done */
+	if (priv->ISR1 & (1 << 5)) {
+		priv->netdev->stats.tx_packets++;
+		priv->netdev->stats.tx_bytes += priv->tx_skb->len;
+		/* dev_kfree_skb(priv->tx_skb); */
+		priv->tx_skb = NULL;
+		priv->tx_len = 0;
+		netif_wake_queue(priv->netdev);
+	}
+	/* XPR : write a new block in transmit FIFO */
+	else if (priv->tx_len < priv->tx_skb->len) {
+		size = priv->tx_skb->len - priv->tx_len;
+		if (size > 32)
+			size = 32;
+
+		for (idx = 0; idx < size; idx++)
+			base_addr->FIFO.XFIFO[idx & 1] =
+				tx_buff[priv->tx_len + idx];
+
+		priv->tx_len += size;
+
+		if (priv->tx_len == priv->tx_skb->len)
+			base_addr->CMDR |= ((1 << 3) | (1 << 1));
+		else
+			setbits8(&(base_addr->CMDR), 1 << 3);
+	}
+
+	return 0;
+}
+
+
+irqreturn_t pef2256_irq(int irq, void *dev_priv)
+{
+	struct pef2256_dev_priv *priv = (struct pef2256_dev_priv *)dev_priv;
+	struct pef2256_regs *base_addr;
+	u8 GIS;
+
+	base_addr = (struct pef2256_regs *)priv->base_addr;
+	GIS = base_addr->GIS;
+
+	priv->ISR0 = priv->ISR1 = 0;
+
+	/* We only care about ISR0 and ISR1 */
+	/* ISR0 */
+	if (GIS & 1)
+		priv->ISR0 = base_addr->ISR0 & ~(base_addr->IMR0);
+	/* ISR1 */
+	if (GIS & (1 << 1))
+		priv->ISR1 = base_addr->ISR1 & ~(base_addr->IMR1);
+
+	/* Don't do anything else before init is done */
+	if (!priv->init_done)
+		return IRQ_HANDLED;
+
+	/* RDO : Receive data overflow -> RX error */
+	if (priv->ISR1 & (1 << 6)) {
+		/* Acknowledge the FIFO */
+		setbits8(&(base_addr->CMDR), 1 << 7);
+		priv->netdev->stats.rx_errors++;
+		/* RME received ? */
+		if (priv->ISR0 & (1 << 7))
+			priv->rx_len = 0;
+		else
+			priv->rx_len = -1;
+		return IRQ_HANDLED;
+	}
+
+	/* XDU : Transmit data underrun -> TX error */
+	if (priv->ISR1 & (1 << 4)) {
+		priv->netdev->stats.tx_errors++;
+		/* dev_kfree_skb(priv->tx_skb); */
+		priv->tx_skb = NULL;
+		netif_wake_queue(priv->netdev);
+		return IRQ_HANDLED;
+	}
+
+	/* RPF or RME : FIFO received */
+	if (priv->ISR0 & (1 | (1 << 7)))
+		pef2256_rx(priv);
+
+	/* XPR or ALLS : FIFO sent */
+	if (priv->ISR1 & (1 | (1 << 5)))
+		pef2256_tx(priv);
+
+	return IRQ_HANDLED;
+}
+
+
+static netdev_tx_t pef2256_start_xmit(struct sk_buff *skb,
+					  struct net_device *netdev)
+{
+	struct pef2256_dev_priv *priv = dev_to_hdlc(netdev)->priv;
+	int idx, size;
+	struct pef2256_regs *base_addr;
+	u8 *tx_buff = skb->data;
+
+	base_addr = (struct pef2256_regs *)priv->base_addr;
+
+	priv->tx_skb = skb;
+	priv->tx_len = 0;
+
+	size = priv->tx_skb->len - priv->tx_len;
+	if (size > 32)
+		size = 32;
+
+	for (idx = 0; idx < size; idx++)
+		base_addr->FIFO.XFIFO[idx & 1] = tx_buff[priv->tx_len + idx];
+
+	priv->tx_len += size;
+
+	setbits8(&(base_addr->CMDR), 1 << 3);
+	if (priv->tx_len == priv->tx_skb->len)
+		setbits8(&(base_addr->CMDR), 1 << 1);
+
+	netif_stop_queue(netdev);
+	return NETDEV_TX_OK;
+}
+
+static const struct net_device_ops pef2256_ops = {
+	.ndo_open       = pef2256_open,
+	.ndo_stop       = pef2256_close,
+	.ndo_change_mtu = hdlc_change_mtu,
+	.ndo_start_xmit = hdlc_start_xmit,
+	.ndo_do_ioctl   = pef2256_ioctl,
+};
+
+
+static int pef2256_hdlc_attach(struct net_device *netdev,
+				unsigned short encoding, unsigned short parity)
+{
+	struct pef2256_dev_priv *priv = dev_to_hdlc(netdev)->priv;
+
+	if (encoding != ENCODING_NRZ &&
+	    encoding != ENCODING_NRZI &&
+	    encoding != ENCODING_FM_MARK &&
+	    encoding != ENCODING_FM_SPACE &&
+	    encoding != ENCODING_MANCHESTER)
+		return -EINVAL;
+
+	if (parity != PARITY_NONE &&
+	    parity != PARITY_CRC16_PR0_CCITT &&
+	    parity != PARITY_CRC16_PR1_CCITT &&
+	    parity != PARITY_CRC32_PR0_CCITT &&
+	    parity != PARITY_CRC32_PR1_CCITT)
+		return -EINVAL;
+
+	priv->encoding = encoding;
+	priv->parity = parity;
+	return 0;
+}
+
+
+/*
+ * Loading module
+ */
+static const struct of_device_id pef2256_match[];
+static int pef2256_probe(struct platform_device *ofdev)
+{
+	const struct of_device_id *match;
+	struct pef2256_dev_priv *priv;
+	int ret = -ENOMEM;
+	struct net_device *netdev;
+	hdlc_device *hdlc;
+	int sys_ret;
+	struct pef2256_regs *base_addr;
+	struct device_node *np = (&ofdev->dev)->of_node;
+	const u32 *data;
+	int len;
+
+	match = of_match_device(pef2256_match, &ofdev->dev);
+	if (!match)
+		return -EINVAL;
+
+	dev_err(&ofdev->dev, "Found PEF2256\n");
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return ret;
+
+	priv->dev = &ofdev->dev;
+
+	data = of_get_property(np, "data-rate", &len);
+	if (!data || len != 4) {
+		dev_err(&ofdev->dev, "failed to read data-rate -> using 8Mb\n");
+		priv->data_rate = DATA_RATE_8M;
+	} else
+		priv->data_rate = *data;
+
+	data = of_get_property(np, "channel-phase", &len);
+	if (!data || len != 4) {
+		dev_err(&ofdev->dev, "failed to read channel phase -> using 0\n");
+		priv->channel_phase = CHANNEL_PHASE_0;
+	} else
+		priv->channel_phase = *data;
+
+	data = of_get_property(np, "rising-edge-sync-pulse", NULL);
+	if (!data) {
+		dev_err(&ofdev->dev, "failed to read rising edge sync pulse -> using \"transmit\"\n");
+		strcpy(priv->rising_edge_sync_pulse, "transmit");
+	} else if (strcmp((char *)data, "transmit") &&
+			strcmp((char *)data, "receive")) {
+		dev_err(&ofdev->dev, "invalid rising edge sync pulse -> using \"transmit\"\n");
+		strcpy(priv->rising_edge_sync_pulse, "transmit");
+	} else
+		strncpy(priv->rising_edge_sync_pulse, (char *)data, 10);
+
+	priv->irq = of_irq_to_resource(np, 0, NULL);
+	if (!priv->irq) {
+		dev_err(priv->dev, "no irq defined\n");
+		return -EINVAL;
+	}
+
+	priv->base_addr = of_iomap(np, 0);
+	if (!priv->base_addr) {
+		dev_err(&ofdev->dev, "of_iomap failed\n");
+		kfree(priv);
+		return ret;
+	}
+
+	/* Get the component Id */
+	base_addr = (struct pef2256_regs *)priv->base_addr;
+	priv->component_id = VERSION_UNDEF;
+	if (base_addr->VSTR == 0x00) {
+		if ((base_addr->WID & WID_IDENT_1) ==
+			WID_IDENT_1_2)
+			priv->component_id = VERSION_1_2;
+	} else if (base_addr->VSTR == 0x05) {
+		if ((base_addr->WID & WID_IDENT_2) ==
+			WID_IDENT_2_1)
+			priv->component_id = VERSION_2_1;
+		else if ((base_addr->WID & WID_IDENT_2) == WID_IDENT_2_2)
+			priv->component_id = VERSION_2_2;
+	}
+
+	priv->tx_skb = NULL;
+
+	/* Default settings ; Rx and Tx use TS 1, mode = MASTER */
+	priv->Rx_TS = 0x40000000;
+	priv->Tx_TS = 0x40000000;
+	priv->mode = 0;
+
+	netdev = alloc_hdlcdev(priv);
+	if (!netdev) {
+		ret = -ENOMEM;
+		return ret;
+	}
+
+	priv->netdev = netdev;
+	hdlc = dev_to_hdlc(netdev);
+	netdev->netdev_ops = &pef2256_ops;
+	SET_NETDEV_DEV(netdev, &ofdev->dev);
+	hdlc->attach = pef2256_hdlc_attach;
+	hdlc->xmit = pef2256_start_xmit;
+
+	dev_set_drvdata(&ofdev->dev, netdev);
+
+	ret = register_hdlc_device(netdev);
+	if (ret < 0) {
+		pr_err("unable to register\n");
+		return ret;
+	}
+
+	sys_ret = 0;
+	sys_ret |= device_create_file(priv->dev, &dev_attr_mode);
+	sys_ret |= device_create_file(priv->dev, &dev_attr_Tx_TS);
+	sys_ret |= device_create_file(priv->dev, &dev_attr_Rx_TS);
+	sys_ret |= device_create_file(priv->dev, &dev_attr_regs);
+
+	if (sys_ret) {
+		device_remove_file(priv->dev, &dev_attr_mode);
+		unregister_hdlc_device(priv->netdev);
+		free_netdev(priv->netdev);
+	}
+
+	priv->init_done = 0;
+
+	return 0;
+}
+
+
+/*
+ * Suppression du module
+ */
+static int pef2256_remove(struct platform_device *ofdev)
+{
+	struct net_device *ndev = dev_get_drvdata(&ofdev->dev);
+	struct pef2256_dev_priv *priv = dev_to_hdlc(ndev)->priv;
+
+	device_remove_file(priv->dev, &dev_attr_Rx_TS);
+	device_remove_file(priv->dev, &dev_attr_Tx_TS);
+	device_remove_file(priv->dev, &dev_attr_mode);
+
+	unregister_hdlc_device(priv->netdev);
+	free_netdev(priv->netdev);
+
+	/* Do E1 stuff */
+
+	dev_set_drvdata(&ofdev->dev, NULL);
+	kfree(ofdev);
+	return 0;
+}
+
+static const struct of_device_id pef2256_match[] = {
+	{
+		.compatible = "infineon,pef2256",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, pef2256_match);
+
+
+static struct platform_driver pef2256_driver = {
+	.probe		= pef2256_probe,
+	.remove		= pef2256_remove,
+	.driver		= {
+		.name	= "pef2256",
+		.owner	= THIS_MODULE,
+		.of_match_table	= pef2256_match,
+	},
+};
+
+
+static int __init pef2256_init(void)
+{
+	int ret;
+	ret = platform_driver_register(&pef2256_driver);
+	return ret;
+}
+module_init(pef2256_init);
+
+
+static void __exit pef2256_exit(void)
+{
+	platform_driver_unregister(&pef2256_driver);
+}
+module_exit(pef2256_exit);
+
+
+/* GENERAL INFORMATIONS */
+MODULE_AUTHOR("CHANTELAUZE Jerome - April 2013");
+MODULE_VERSION("0.1");
+MODULE_DESCRIPTION("Infineon PEF 2256 E1 Controller");
+MODULE_LICENSE("GPL");
diff -urN a/drivers/net/wan/pef2256.h b/drivers/net/wan/pef2256.h
--- a/drivers/net/wan/pef2256.h	1970-01-01 01:00:00.000000000 +0100
+++ b/drivers/net/wan/pef2256.h	2013-10-13 13:06:00.000000000 +0200
@@ -0,0 +1,269 @@
+/*
+ * drivers/net/wan/pef2256.c : a PEF2256 HDLC driver for Linux
+ *
+ * This software may be used and distributed according to the terms of the
+ * GNU General Public License.
+ *
+ */
+
+#ifndef _PEF2256_H
+#define _PEF2256_H
+
+#define MASTER_MODE 0
+#define SLAVE_MODE  1
+
+#define CHANNEL_PHASE_0 0
+#define CHANNEL_PHASE_1 1
+#define CHANNEL_PHASE_2 2
+#define CHANNEL_PHASE_3 3
+
+#define DATA_RATE_4M 4
+#define DATA_RATE_8M 8
+
+#define RX_TIMEOUT 500
+
+enum versions {
+	VERSION_UNDEF = 0,
+	VERSION_1_2 = 0x12,
+	VERSION_2_1 = 0x21,
+	VERSION_2_2 = 0x22,
+};
+
+#define WID_IDENT_1		0x03
+#define WID_IDENT_1_2		0x03
+#define WID_IDENT_2		0xC0
+#define WID_IDENT_2_1		0x00
+#define WID_IDENT_2_2		0x40
+
+
+struct pef2256_dev_priv {
+	struct sk_buff *tx_skb;
+	u16 tx_len;
+	struct device *dev;
+
+	int init_done;
+
+	void *base_addr;
+	int component_id;
+	int mode;	/* MASTER or SLAVE */
+	int board_type;
+	int channel_phase;
+	int data_rate;
+	char rising_edge_sync_pulse[10];
+
+	u16 rx_len;
+	u8 rx_buff[2048];
+
+	u32 Tx_TS;	/* Transmit Time Slots */
+	u32 Rx_TS;	/* Receive Time Slots */
+
+	unsigned short encoding;
+	unsigned short parity;
+	struct net_device *netdev;
+
+	int irq;
+
+	u8 ISR0;			/* ISR0 register */
+	u8 ISR1;			/* ISR1 register */
+};
+
+
+/* Framer E1 registers */
+union pef2256_Fifo {
+	u8	XFIFO[sizeof(u16)];		/* Transmit FIFO */
+	u8	RFIFO[sizeof(u16)];		/* Receive FIFO */
+};
+
+union pef2256_60 {
+	unsigned char	DEC;	/* Disable Error Counter */
+	unsigned char	RSA8;	/* Receive Sa8-Bit Regiter */
+};
+
+union pef2256_CAS {
+	unsigned char	XS;	/* Transmit CAS Register */
+	unsigned char	RS;	/* Receive CAS Regiter */
+};
+
+union pef2256_Dif1 {
+	unsigned char	SIS2;	/* V1.2 : Signaling Status Register 2 */
+	unsigned char	GCM7;	/* V2.2 : Global Counter Mode 7 */
+};
+
+union pef2256_Dif2 {
+	unsigned char	RSIS2;	/* V1.2 : Rx Signaling Status Register 2 */
+	unsigned char	GCM8;	/* V2.2 : Global Counter Mode 8 */
+};
+
+struct pef2256_regs {
+	union pef2256_Fifo	FIFO;	/* 0x00/0x01	FIFO (Tx or rx) */
+	unsigned char	CMDR;	/* 0x02	Command Register */
+	unsigned char	MODE;	/* 0x03	Mode Register */
+	unsigned char	RAH1;	/* 0x04	Receive Address High 1 */
+	unsigned char	RAH2;	/* 0x05	Receive Address High 2 */
+	unsigned char	RAL1;	/* 0x06	Receive Address Low 1 */
+	unsigned char	RAL2;	/* 0x07	Receive Address Low 2 */
+	unsigned char	IPC;	/* 0x08	Interrupt Port Configuration */
+	unsigned char	CCR1;	/* 0x09	Common Configuration Register 1 */
+	unsigned char	CCR2;	/* 0x0A	Common Configuration Register 2 */
+	unsigned char	Res1;	/* 0x0B	Free Register 1 */
+	unsigned char	RTR1;	/* 0x0C	Receive Time Slot Register 1 */
+	unsigned char	RTR2;	/* 0x0D	Receive Time Slot Register 2 */
+	unsigned char	RTR3;	/* 0x0E	Receive Time Slot Register 3 */
+	unsigned char	RTR4;	/* 0x0F	Receive Time Slot Register 4 */
+	unsigned char	TTR1;	/* 0x10	Transmit Time Slot Register 1 */
+	unsigned char	TTR2;	/* 0x11	Transmit Time Slot Register 2 */
+	unsigned char	TTR3;	/* 0x12	Transmit Time Slot Register 3 */
+	unsigned char	TTR4;	/* 0x13	Transmit Time Slot Register 4 */
+	unsigned char	IMR0;	/* 0x14	Interrupt Mask Register 0 */
+	unsigned char	IMR1;	/* 0x15	Interrupt Mask Register 1 */
+	unsigned char	IMR2;	/* 0x16	Interrupt Mask Register 2 */
+	unsigned char	IMR3;	/* 0x17	Interrupt Mask Register 3 */
+	unsigned char	IMR4;	/* 0x18	Interrupt Mask Register 4 */
+	unsigned char	IMR5;	/* 0x19	Interrupt Mask Register 5 */
+	unsigned char	Res2;	/* 0x1A	Free Register 2 */
+	unsigned char	IERR;	/* 0x1B	Single Bit Error Insertion Register */
+	unsigned char	FMR0;	/* 0x1C	Framer Mode Register 0 */
+	unsigned char	FMR1;	/* 0x1D	Framer Mode Register 1 */
+	unsigned char	FMR2;	/* 0x1E	Framer Mode Register 2 */
+	unsigned char	LOOP;	/* 0x1F	Channel Loop-Back */
+	unsigned char	XSW;	/* 0x20	Transmit Service Word */
+	unsigned char	XSP;	/* 0x21	Transmit Spare Bits */
+	unsigned char	XC0;	/* 0x22	Transmit Control 0 */
+	unsigned char	XC1;	/* 0x23	Transmit Control 1 */
+	unsigned char	RC0;	/* 0x24	Receive Control 0 */
+	unsigned char	RC1;	/* 0x25	Receive Control 1 */
+	unsigned char	XPM0;	/* 0x26	Transmit Pulse Mask 0 */
+	unsigned char	XPM1;	/* 0x27	Transmit Pulse Mask 1 */
+	unsigned char	XPM2;	/* 0x28	Transmit Pulse Mask 2 */
+	unsigned char	TSWM;	/* 0x29	Transparent Service Word Mask */
+	unsigned char	Res3;	/* 0x2A	Free Register 3 */
+	unsigned char	IDLE;	/* 0x2B	Idle Channel Code */
+	unsigned char	XSA4;	/* 0x2C	Transmit Sa4-Bit Register */
+	unsigned char	XSA5;	/* 0x2D	Transmit Sa5-Bit Register */
+	unsigned char	XSA6;	/* 0x2E	Transmit Sa6-Bit Register */
+	unsigned char	XSA7;	/* 0x2F	Transmit Sa7-Bit Register */
+	unsigned char	XSA8;	/* 0x30	Transmit Sa8-Bit Register */
+	unsigned char	FMR3;	/* 0x31	Framer Mode Register 3 */
+	unsigned char	ICB1;	/* 0x32	Idle Channel Register 1 */
+	unsigned char	ICB2;	/* 0x33	Idle Channel Register 2 */
+	unsigned char	ICB3;	/* 0x34	Idle Channel Register 3 */
+	unsigned char	ICB4;	/* 0x35	Idle Channel Register 4 */
+	unsigned char	LIM0;	/* 0x36	Line Interface Mode 0 */
+	unsigned char	LIM1;	/* 0x37	Line Interface Mode 1 */
+	unsigned char	PCD;	/* 0x38	Pulse Count Detection */
+	unsigned char	PCR;	/* 0x39	Pulse Count Recovery */
+	unsigned char	LIM2;	/* 0x3A	Line Interface Mode 2 */
+	unsigned char	LCR1;	/* 0x3B	Loop Code Register 1 */
+	unsigned char	LCR2;	/* 0x3C	Loop Code Register 2 */
+	unsigned char	LCR3;	/* 0x3D	Loop Code Register 3 */
+	unsigned char	SIC1;	/* 0x3E	System Interface Control 1 */
+	unsigned char	SIC2;	/* 0x3F	System Interface Control 2 */
+	unsigned char	SIC3;	/* 0x40	System Interface Control 3 */
+	unsigned char	Res4;	/* 0x41	Free Register 4 */
+	unsigned char	Res5;	/* 0x42	Free Register 5 */
+	unsigned char	Res6;	/* 0x43	Free Register 6 */
+	unsigned char	CMR1;	/* 0x44	Clock Mode Register 1 */
+	unsigned char	CMR2;	/* 0x45	Clock Mode Register 2 */
+	unsigned char	GCR;	/* 0x46	Global Configuration Register */
+	unsigned char	ESM;	/* 0x47	Errored Second Mask */
+	unsigned char	CMR3;	/* 0x48	Clock Mode Register 3 en V2.2 */
+	unsigned char	RBD;	/* 0x49	Receive Buffer Delay */
+	unsigned char	VSTR;	/* 0x4A	Version Status Regiter */
+	unsigned char	RES;	/* 0x4B	Receive Equalizer Status */
+	unsigned char	FRS0;	/* 0x4C	Framer Receive Status 0 */
+	unsigned char	FRS1;	/* 0x4D	Framer Receive Status 1 */
+	unsigned char	RSW;	/* 0x4E	Receive Service Word */
+	unsigned char	RSP;	/* 0x4F	Receive Spare Bits */
+	unsigned short	FEC;	/* 0x50/0x51 Framing Error Counter */
+	unsigned short	CVC;	/* 0x52/0x53 Code Violation Counter */
+	unsigned short	CEC1;	/* 0x54/0x55 CRC Error Counter 1 */
+	unsigned short	EBC;	/* 0x56/0x57 E-Bit Error Counter */
+	unsigned short	CEC2;	/* 0x58/0x59 CRC Error Counter 2 */
+	unsigned short	CEC3;	/* 0x5A/0x5B CRC Error Counter 3 */
+	unsigned char	RSA4;	/* 0x5C	Receive Sa4-Bit Register */
+	unsigned char	RSA5;	/* 0x5D	Receive Sa5-Bit Register */
+	unsigned char	RSA6;	/* 0x5E	Receive Sa6-Bit Register */
+	unsigned char	RSA7;	/* 0x5F	Receive Sa7-Bit Register */
+	union pef2256_60	Reg60;	/* 0x60	Common Register */
+	unsigned char	RSA6S;	/* 0x61	Receive Sa6-Bit Status Register */
+	unsigned char	RSP1;	/* 0x62	Receive Signaling Pointer 1 */
+	unsigned char	RSP2;	/* 0x63	Receive Signaling Pointer 2 */
+	unsigned char	SIS;	/* 0x64	Signaling Status Register */
+	unsigned char	RSIS;	/* 0x65	Receive Signaling Status Register */
+	unsigned char	RBCL;	/* 0x66	Receive Byte Control */
+	unsigned char	RBCH;	/* 0x67	Receive Byte Control */
+	unsigned char	ISR0;	/* 0x68	Interrupt Status Register 0 */
+	unsigned char	ISR1;	/* 0x69	Interrupt Status Register 1 */
+	unsigned char	ISR2;	/* 0x6A	Interrupt Status Register 2 */
+	unsigned char	ISR3;	/* 0x6B	Interrupt Status Register 3 */
+	unsigned char	ISR4;	/* 0x6C	Interrupt Status Register 4 */
+	unsigned char	ISR5;	/* 0x6D	Interrupt Status Register 5 */
+	unsigned char	GIS;	/* 0x6E	Global Interrupt Status */
+	unsigned char	Res8;	/* 0x6F	Free Register 8 */
+	union pef2256_CAS	CAS1;	/* 0x70	CAS Register 1 */
+	union pef2256_CAS	CAS2;	/* 0x71	CAS Register 2 */
+	union pef2256_CAS	CAS3;	/* 0x72	CAS Register 3 */
+	union pef2256_CAS	CAS4;	/* 0x73	CAS Register 4 */
+	union pef2256_CAS	CAS5;	/* 0x74	CAS Register 5 */
+	union pef2256_CAS	CAS6;	/* 0x75	CAS Register 6 */
+	union pef2256_CAS	CAS7;	/* 0x76	CAS Register 7 */
+	union pef2256_CAS	CAS8;	/* 0x77	CAS Register 8 */
+	union pef2256_CAS	CAS9;	/* 0x78	CAS Register 9 */
+	union pef2256_CAS	CAS10;	/* 0x79	CAS Register 10 */
+	union pef2256_CAS	CAS11;	/* 0x7A	CAS Register 11 */
+	union pef2256_CAS	CAS12;	/* 0x7B	CAS Register 12 */
+	union pef2256_CAS	CAS13;	/* 0x7C	CAS Register 13 */
+	union pef2256_CAS	CAS14;	/* 0x7D	CAS Register 14 */
+	union pef2256_CAS	CAS15;	/* 0x7E	CAS Register 15 */
+	union pef2256_CAS	CAS16;	/* 0x7F	CAS Register 16 */
+	unsigned char	PC1;	/* 0x80	Port Configuration 1 */
+	unsigned char	PC2;	/* 0x81	Port Configuration 2 */
+	unsigned char	PC3;	/* 0x82	Port Configuration 3 */
+	unsigned char	PC4;	/* 0x83	Port Configuration 4 */
+	unsigned char	PC5;	/* 0x84	Port Configuration 5 */
+	unsigned char	GPC1;	/* 0x85	Global Port Configuration 1 */
+	unsigned char	PC6;	/* 0x86	Port Configuration 6 */
+	unsigned char	CMDR2;	/* 0x87	Command Register 2 */
+	unsigned char	CMDR3;	/* 0x88	Command Register 3 */
+	unsigned char	CMDR4;	/* 0x89	Command Register 4 */
+	unsigned char	Res9;	/* 0x8A	Free Register 9 */
+	unsigned char	CCR3;	/* 0x8B	Common Control Register 3 */
+	unsigned char	CCR4;	/* 0x8C	Common Control Register 4 */
+	unsigned char	CCR5;	/* 0x8D	Common Control Register 5 */
+	unsigned char	MODE2;	/* 0x8E	Mode Register 2 */
+	unsigned char	MODE3;	/* 0x8F	Mode Register 3 */
+	unsigned char	RBC2;	/* 0x90	Receive Byte Count Register 2 */
+	unsigned char	RBC3;	/* 0x91	Receive Byte Count Register 3 */
+	unsigned char	GCM1;	/* 0x92	Global Counter Mode 1 */
+	unsigned char	GCM2;	/* 0x93	Global Counter Mode 2 */
+	unsigned char	GCM3;	/* 0x94	Global Counter Mode 3 */
+	unsigned char	GCM4;	/* 0x95	Global Counter Mode 4 */
+	unsigned char	GCM5;	/* 0x96	Global Counter Mode 5 */
+	unsigned char	GCM6;	/* 0x97	Global Counter Mode 6 */
+	union pef2256_Dif1	Dif1;	/* 0x98	SIS2 en V1.2, GCM7 en V2.2 */
+	union pef2256_Dif2	Dif2;	/* 0x99	RSIS2 en V1.2, GCM8 en V2.2 */
+	unsigned char	SIS3;	/* 0x9A	Signaling Status Register 3 */
+	unsigned char	RSIS3;	/* 0x9B	Receive Signaling Status Register 3 */
+	union pef2256_Fifo	FIFO2;	/* 0x9C/0x9D FIFO 2 (Tx or rx) */
+	union pef2256_Fifo	FIFO3;	/* 0x9E/0x9F FIFO 3 (Tx or rx) */
+	unsigned char	TSEO;	/* 0xA0	Time Slot Even/Odd select */
+	unsigned char	TSBS1;	/* 0xA1	Time Slot Bit select 1 */
+	unsigned char	TSBS2;	/* 0xA2	Time Slot Bit select 2 */
+	unsigned char	TSBS3;	/* 0xA3	Time Slot Bit select 3 */
+	unsigned char	TSS2;	/* 0xA4	Time Slot select 2 */
+	unsigned char	TSS3;	/* 0xA5	Time Slot select 3 */
+	unsigned char	Res10;	/* 0xA6	Free Register 10 */
+	unsigned char	Res11;	/* 0xA7	Free Register 11 */
+	unsigned char	TPC0;	/* 0xA8	Test Pattern Control Register 0 */
+	unsigned char	SIS2;	/* 0xA9	Signaling Status Register 2 (V2.2) */
+	unsigned char	RSIS2;	/* 0xAA	Rx Signaling Status Register 2 (V2.2) */
+	unsigned char	MFPI;	/* 0xAB	Multi Function Port Input Status */
+	unsigned char	Res12;	/* 0xAC	Free Register 12 */
+	unsigned char	Res13;	/* 0xAD	Free Register 13 */
+	unsigned char	Res14;	/* 0xAE	Free Register 14 */
+	unsigned char	GLC1;	/* 0xAF	Global Line Control Register 1 */
+	unsigned char	Res[0xEB-0xAF];	/* 0xB0/0xEB Free Registers */
+	unsigned char	WID;	/* 0xEC	Identification Register */
+};
+
+#endif /* _PEF2256_H */
diff -urN a/Documentation/devicetree/bindings/net/pef2256.txt b/Documentation/devicetree/bindings/net/pef2256.txt
--- a/Documentation/devicetree/bindings/net/pef2256.txt	1970-01-01 01:00:00.000000000 +0100
+++ b/Documentation/devicetree/bindings/net/pef2256.txt	2013-10-13 15:05:42.000000000 +0200
@@ -0,0 +1,29 @@
+* Wan on Infineon pef2256 E1 controller
+
+Required properties:
+- compatible: Should be "infineon,pef2256"
+- reg: Address and length of the register set for the device
+- interrupts: Should contain interrupts
+
+Optional properties:
+- data-rate: Data rate on the system highway.
+  Supported values are: 2, 4, 8, 16.
+  8 if not defined.
+- channel-phase: First time slot transmission channel phase.
+  Supported values are: 0, 1, 2, 3, 4, 5, 6, 7.
+  0 if not defined.
+- rising-edge-sync-pulse: rising edge synchronous pulse.
+  Supported values are: "receive", "transmit".
+  "transmit" if not defined.
+
+Examples:
+
+	e1-wan@4,2000000 {
+		compatible = "infineon,pef2256";
+		reg = <4 0x2000000 0xFF>;
+		interrupts = <8 1>;
+		interrupt-parent = <&PIC>;
+		data-rate = <4>;
+		channel-phase = <1>;
+		rising-edge-sync-pulse = "transmit";
+	};
diff -urN a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile
--- a/drivers/net/wan/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ b/drivers/net/wan/Makefile	2013-10-13 13:05:01.000000000 +0200
@@ -22,6 +22,7 @@
 obj-$(CONFIG_COSA)		+= cosa.o
 obj-$(CONFIG_FARSYNC)		+= farsync.o
 obj-$(CONFIG_DSCC4)             += dscc4.o
+obj-$(CONFIG_PEF2256)           += pef2256.o
 obj-$(CONFIG_X25_ASY)		+= x25_asy.o
 
 obj-$(CONFIG_LANMEDIA)		+= lmc/
diff -urN a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
--- a/drivers/net/wan/Kconfig	1970-01-01 01:00:00.000000000 +0100
+++ b/drivers/net/wan/Kconfig	2013-10-13 13:05:01.000000000 +0200
@@ -266,6 +266,16 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called farsync.
 
+config PEF2256
+	tristate "PEF2256 support"
+	depends on HDLC && OF && SYSFS
+	help
+	  Driver for Infineon FALC56 E1/T1/J1 Framer and Line Interface
+	  based on PEF2256 chipset.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pef2256.
+
 config DSCC4
 	tristate "Etinc PCISYNC serial board support"
 	depends on HDLC && PCI && m


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ