* [PATCH v2] WAN: Adding support for Infineon PEF2256 E1 chipset (FALC56)
@ 2013-11-01 15:01 Christophe Leroy
2013-11-01 15:36 ` Govindarajulu Varadarajan
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Christophe Leroy @ 2013-11-01 15:01 UTC (permalink / raw)
To: Rob Herring, Pawel Moll, Mark Rutland, Stephen Warren,
Ian Campbell, Rob Landley, Grant Likely, Krzysztof Halasa
Cc: devicetree, linux-doc, linux-kernel, netdev
The patch adds WAN support for Infineon FALC56 - PEF2256 E1 Chipset.
Signed-off-by: Jerome Chantelauze <jerome.chantelauze.ext@c-s.fr>
Acked-by: Christophe Leroy <christophe.leroy@c-s.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,1197 @@
+/* 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;
+ unsigned char *base_addr = priv->base_addr;
+
+ netdev_info(ndev, " MODE = 0x%02x\n", readb(base_addr + MODE));
+ netdev_info(ndev, " RAH1 = 0x%02x\n", readb(base_addr + RAH1));
+ netdev_info(ndev, " RAH2 = 0x%02x\n", readb(base_addr + RAH2));
+ netdev_info(ndev, " RAL1 = 0x%02x\n", readb(base_addr + RAL1));
+ netdev_info(ndev, " RAL2 = 0x%02x\n", readb(base_addr + RAL2));
+ netdev_info(ndev, " IPC = 0x%02x\n", readb(base_addr + IPC));
+ netdev_info(ndev, " CCR1 = 0x%02x\n", readb(base_addr + CCR1));
+ netdev_info(ndev, " CCR2 = 0x%02x\n", readb(base_addr + CCR2));
+ netdev_info(ndev, " RTR1 = 0x%02x\n", readb(base_addr + RTR1));
+ netdev_info(ndev, " RTR2 = 0x%02x\n", readb(base_addr + RTR2));
+ netdev_info(ndev, " RTR3 = 0x%02x\n", readb(base_addr + RTR3));
+ netdev_info(ndev, " RTR4 = 0x%02x\n", readb(base_addr + RTR4));
+ netdev_info(ndev, " TTR1 = 0x%02x\n", readb(base_addr + TTR1));
+ netdev_info(ndev, " TTR2 = 0x%02x\n", readb(base_addr + TTR2));
+ netdev_info(ndev, " TTR3 = 0x%02x\n", readb(base_addr + TTR3));
+ netdev_info(ndev, " TTR4 = 0x%02x\n", readb(base_addr + TTR4));
+ netdev_info(ndev, " IMR0 = 0x%02x\n", readb(base_addr + IMR0));
+ netdev_info(ndev, " IMR1 = 0x%02x\n", readb(base_addr + IMR1));
+ netdev_info(ndev, " IMR2 = 0x%02x\n", readb(base_addr + IMR2));
+ netdev_info(ndev, " IMR3 = 0x%02x\n", readb(base_addr + IMR3));
+ netdev_info(ndev, " IMR4 = 0x%02x\n", readb(base_addr + IMR4));
+ netdev_info(ndev, " IMR5 = 0x%02x\n", readb(base_addr + IMR5));
+ netdev_info(ndev, " IERR = 0x%02x\n", readb(base_addr + IERR));
+ netdev_info(ndev, " FMR0 = 0x%02x\n", readb(base_addr + FMR0));
+ netdev_info(ndev, " FMR1 = 0x%02x\n", readb(base_addr + FMR1));
+ netdev_info(ndev, " FMR2 = 0x%02x\n", readb(base_addr + FMR2));
+ netdev_info(ndev, " LOOP = 0x%02x\n", readb(base_addr + LOOP));
+ netdev_info(ndev, " XSW = 0x%02x\n", readb(base_addr + XSW));
+ netdev_info(ndev, " XSP = 0x%02x\n", readb(base_addr + XSP));
+ netdev_info(ndev, " XC0 = 0x%02x\n", readb(base_addr + XC0));
+ netdev_info(ndev, " XC1 = 0x%02x\n", readb(base_addr + XC1));
+ netdev_info(ndev, " RC0 = 0x%02x\n", readb(base_addr + RC0));
+ netdev_info(ndev, " RC1 = 0x%02x\n", readb(base_addr + RC1));
+ netdev_info(ndev, " XPM0 = 0x%02x\n", readb(base_addr + XPM0));
+ netdev_info(ndev, " XPM1 = 0x%02x\n", readb(base_addr + XPM1));
+ netdev_info(ndev, " XPM2 = 0x%02x\n", readb(base_addr + XPM2));
+ netdev_info(ndev, " TSWM = 0x%02x\n", readb(base_addr + TSWM));
+ netdev_info(ndev, " IDLE = 0x%02x\n", readb(base_addr + IDLE));
+ netdev_info(ndev, " XSA4 = 0x%02x\n", readb(base_addr + XSA4));
+ netdev_info(ndev, " XSA5 = 0x%02x\n", readb(base_addr + XSA5));
+ netdev_info(ndev, " XSA6 = 0x%02x\n", readb(base_addr + XSA6));
+ netdev_info(ndev, " XSA7 = 0x%02x\n", readb(base_addr + XSA7));
+ netdev_info(ndev, " XSA8 = 0x%02x\n", readb(base_addr + XSA8));
+ netdev_info(ndev, " FMR3 = 0x%02x\n", readb(base_addr + FMR3));
+ netdev_info(ndev, " ICB1 = 0x%02x\n", readb(base_addr + ICB1));
+ netdev_info(ndev, " ICB2 = 0x%02x\n", readb(base_addr + ICB2));
+ netdev_info(ndev, " ICB3 = 0x%02x\n", readb(base_addr + ICB3));
+ netdev_info(ndev, " ICB4 = 0x%02x\n", readb(base_addr + ICB4));
+ netdev_info(ndev, " LIM0 = 0x%02x\n", readb(base_addr + LIM0));
+ netdev_info(ndev, " LIM1 = 0x%02x\n", readb(base_addr + LIM1));
+ netdev_info(ndev, " PCD = 0x%02x\n", readb(base_addr + PCD));
+ netdev_info(ndev, " PCR = 0x%02x\n", readb(base_addr + PCR));
+ netdev_info(ndev, " LIM2 = 0x%02x\n", readb(base_addr + LIM2));
+ netdev_info(ndev, " LCR1 = 0x%02x\n", readb(base_addr + LCR1));
+ netdev_info(ndev, " LCR2 = 0x%02x\n", readb(base_addr + LCR2));
+ netdev_info(ndev, " LCR3 = 0x%02x\n", readb(base_addr + LCR3));
+ netdev_info(ndev, " SIC1 = 0x%02x\n", readb(base_addr + SIC1));
+ netdev_info(ndev, " SIC2 = 0x%02x\n", readb(base_addr + SIC2));
+ netdev_info(ndev, " SIC3 = 0x%02x\n", readb(base_addr + SIC3));
+ netdev_info(ndev, " CMR1 = 0x%02x\n", readb(base_addr + CMR1));
+ netdev_info(ndev, " CMR2 = 0x%02x\n", readb(base_addr + CMR2));
+ netdev_info(ndev, " GCR = 0x%02x\n", readb(base_addr + GCR));
+ netdev_info(ndev, " ESM = 0x%02x\n", readb(base_addr + ESM));
+ netdev_info(ndev, " CMR3 = 0x%02x\n", readb(base_addr + CMR3));
+ netdev_info(ndev, " PC1 = 0x%02x\n", readb(base_addr + PC1));
+ netdev_info(ndev, " PC2 = 0x%02x\n", readb(base_addr + PC2));
+ netdev_info(ndev, " PC3 = 0x%02x\n", readb(base_addr + PC3));
+ netdev_info(ndev, " PC4 = 0x%02x\n", readb(base_addr + PC4));
+ netdev_info(ndev, " PC5 = 0x%02x\n", readb(base_addr + PC5));
+ netdev_info(ndev, " GPC1 = 0x%02x\n", readb(base_addr + GPC1));
+ netdev_info(ndev, " PC6 = 0x%02x\n", readb(base_addr + PC6));
+ netdev_info(ndev, " CCR3 = 0x%02x\n", readb(base_addr + CCR3));
+ netdev_info(ndev, " CCR4 = 0x%02x\n", readb(base_addr + CCR4));
+ netdev_info(ndev, " CCR5 = 0x%02x\n", readb(base_addr + CCR5));
+ netdev_info(ndev, " MODE2 = 0x%02x\n", readb(base_addr + MODE2));
+ netdev_info(ndev, " MODE3 = 0x%02x\n", readb(base_addr + MODE3));
+ netdev_info(ndev, " RBC2 = 0x%02x\n", readb(base_addr + RBC2));
+ netdev_info(ndev, " RBC3 = 0x%02x\n", readb(base_addr + RBC3));
+ netdev_info(ndev, " GCM1 = 0x%02x\n", readb(base_addr + GCM1));
+ netdev_info(ndev, " GCM2 = 0x%02x\n", readb(base_addr + GCM2));
+ netdev_info(ndev, " GCM3 = 0x%02x\n", readb(base_addr + GCM3));
+ netdev_info(ndev, " GCM4 = 0x%02x\n", readb(base_addr + GCM4));
+ netdev_info(ndev, " GCM5 = 0x%02x\n", readb(base_addr + GCM5));
+ netdev_info(ndev, " GCM6 = 0x%02x\n", readb(base_addr + GCM6));
+ netdev_info(ndev, " SIS2/GCM7 = 0x%02x\n",
+ readb(base_addr + SIS2_1));
+ netdev_info(ndev, " RSIS2/GCM8 = 0x%02x\n",
+ readb(base_addr + RSIS2_1));
+ netdev_info(ndev, " TSEO = 0x%02x\n", readb(base_addr + TSEO));
+ netdev_info(ndev, " TSBS1 = 0x%02x\n", readb(base_addr + TSBS1));
+ netdev_info(ndev, " TSBS2 = 0x%02x\n", readb(base_addr + TSBS2));
+ netdev_info(ndev, " TSBS3 = 0x%02x\n", readb(base_addr + TSBS3));
+ netdev_info(ndev, " TSS2 = 0x%02x\n", readb(base_addr + TSS2));
+ netdev_info(ndev, " TSS3 = 0x%02x\n", readb(base_addr + TSS3));
+ netdev_info(ndev, " Res10 = 0x%02x\n", readb(base_addr + Res10));
+ netdev_info(ndev, " Res11 = 0x%02x\n", readb(base_addr + Res11));
+ netdev_info(ndev, " TPC0 = 0x%02x\n", readb(base_addr + TPC0));
+ netdev_info(ndev, " GLC1 = 0x%02x\n", readb(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;
+ long int value;
+ int ret = kstrtol(buf, 10, &value);
+ int reconfigure = (value != priv->mode);
+
+ if (value != MASTER_MODE && value != SLAVE_MODE)
+ ret = -EINVAL;
+
+ if (ret < 0)
+ netdev_info(ndev, "Invalid mode (0 or 1 expected\n");
+ else {
+ priv->mode = value;
+ if (reconfigure && priv->init_done) {
+ pef2256_close(ndev);
+ init_FALC(priv);
+ pef2256_open(ndev);
+ }
+ }
+
+ return strnlen(buf, 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;
+ unsigned long value;
+ int ret = kstrtoul(buf, 16, (long int *)&value);
+ int reconfigure = (value != priv->mode);
+
+ /* TS 0 is reserved */
+ if (ret < 0 || value > TS_0)
+ ret = -EINVAL;
+
+ if (ret < 0)
+ netdev_info(ndev, "Invalid Tx_TS (hex number > 0 and < 0x80000000 expected\n");
+ else {
+ priv->Tx_TS = value;
+ if (reconfigure && priv->init_done)
+ Config_HDLC(priv);
+ }
+
+ return strnlen(buf, 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;
+ unsigned long value;
+ int ret = kstrtoul(buf, 16, &value);
+ int reconfigure = (value != priv->mode);
+
+ /* TS 0 is reserved */
+ if (ret < 0 || value > TS_0)
+ ret = -EINVAL;
+
+ if (ret < 0)
+ netdev_info(ndev, "Invalid Rx_TS (hex number > 0 and < 0x80000000 expected\n");
+ else {
+ priv->Rx_TS = value;
+ if (reconfigure && priv->init_done)
+ Config_HDLC(priv);
+ }
+
+ return strnlen(buf, 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;
+ unsigned char *base_addr;
+ u8 dummy;
+
+ /* Set framer E1 address */
+ base_addr = priv->base_addr;
+
+ /* Read to remove pending IT */
+ dummy = readb(base_addr + ISR0);
+ dummy = readb(base_addr + ISR1);
+
+ /* Mask HDLC 1 Transmit IT */
+ writeb(readb(base_addr + IMR1) | 1, base_addr + IMR1);
+ writeb(readb(base_addr + IMR1) | (1 << 4), base_addr + IMR1);
+ writeb(readb(base_addr + IMR1) | (1 << 5), base_addr + IMR1);
+
+ /* Mask HDLC 1 Receive IT */
+ writeb(readb(base_addr + IMR0) | 1, base_addr + IMR0);
+ writeb(readb(base_addr + IMR0) | (1 << 7), base_addr + IMR0);
+ writeb(readb(base_addr + IMR1) | (1 << 6), base_addr + IMR1);
+
+ /* The hardware requires a delay up to 2*32*125 usec to take commands
+ * into account
+ */
+ 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)
+ */
+ writeb(1 << 3, base_addr + MODE);
+ /* CCR1.EITS = 1 (Enable internal Time Slot 31:0 Signaling)
+ * CCR1.XMFA = 0 (No transmit multiframe alignment)
+ * CCR1.RFT1:0 = 00 (RFIFO is 32 bytes)
+ * setting up Interframe Time Fill
+ * CCR1.ITF = 1 (Interframe Time Fill Continuous flag)
+ */
+ writeb(0x10 | (1 << 3), base_addr + CCR1);
+ /* CCR2.XCRC = 0 (Transmit CRC ON)
+ * CCR2.RCRC = 0 (Receive CRC ON, no write in RFIFO)
+ * CCR2.RADD = 0 (No write address in RFIFO)
+ */
+ writeb(0x00, base_addr + CCR2);
+
+ /* The hardware requires a delay up to 2*32*125 usec to take commands
+ * into account
+ */
+ 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)
+ */
+ writeb(1 << 3, base_addr + MODE);
+ /* CCR1.EITS = 1 (Enable internal Time Slot 31:0 Signaling)
+ * CCR1.XMFA = 0 (No transmit multiframe alignment)
+ * CCR1.RFT1:0 = 00 (RFIFO is 32 bytes)
+ * setting up Interframe Time Fill
+ * CCR1.ITF = 1 (Interframe Time Fill Continuous flag)
+ */
+ writeb(0x10 | (1 << 3), base_addr + CCR1);
+ /* CCR2.XCRC = 0 (Transmit CRC ON)
+ * CCR2.RCRC = 0 (Receive CRC ON, no write in RFIFO)
+ * CCR2.RADD = 0 (No write address in RFIFO)
+ */
+ writeb(0x00, base_addr + CCR2);
+
+ /* The hardware requires a delay up to 2*32*125 usec to take commands
+ * into account
+ */
+ 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)
+ */
+ writeb(1 << 3, base_addr + MODE);
+ /* CCR1.EITS = 1 (Enable internal Time Slot 31:0 Signaling)
+ * CCR1.XMFA = 0 (No transmit multiframe alignment)
+ * CCR1.RFT1:0 = 00 (RFIFO is 32 bytes)
+ * setting up Interframe Time Fill
+ * CCR1.ITF = 1 (Interframe Time Fill Continuous flag)
+ */
+ writeb(0x10 | (1 << 3), base_addr + CCR1);
+ /* CCR2.XCRC = 0 (Transmit CRC ON)
+ * CCR2.RCRC = 0 (Receive CRC ON, no write in RFIFO)
+ * CCR2.RADD = 0 (No write address in RFIFO)
+ */
+ writeb(0x00, base_addr + CCR2);
+
+ /* The hardware requires a delay up to 2*32*125 usec to take commands
+ * into account
+ */
+ udelay((2 * 32) * 125);
+
+ /* Init Time Slot select */
+ writeb(0x00, base_addr + TTR1);
+ writeb(0x00, base_addr + TTR2);
+ writeb(0x00, base_addr + TTR3);
+ writeb(0x00, base_addr + TTR4);
+ writeb(0x00, base_addr + RTR1);
+ writeb(0x00, base_addr + RTR2);
+ writeb(0x00, base_addr + RTR3);
+ writeb(0x00, base_addr + RTR4);
+ /* 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)))
+ writeb(readb(base_addr + TTR1) | (1 << i),
+ base_addr + TTR1);
+ if (priv->Rx_TS & (1 << (31 - TS_idx)))
+ writeb(readb(base_addr + RTR1) | (1 << i),
+ base_addr + RTR1);
+ break;
+ case 1:
+ if (priv->Tx_TS & (1 << (31 - TS_idx)))
+ writeb(readb(base_addr + TTR2) | (1 << i),
+ base_addr + TTR2);
+ if (priv->Rx_TS & (1 << (31 - TS_idx)))
+ writeb(readb(base_addr + RTR2) | (1 << i),
+ base_addr + RTR2);
+ break;
+ case 2:
+ if (priv->Tx_TS & (1 << (31 - TS_idx)))
+ writeb(readb(base_addr + TTR3) | (1 << i),
+ base_addr + TTR3);
+ if (priv->Rx_TS & (1 << (31 - TS_idx)))
+ writeb(readb(base_addr + RTR3) | (1 << i),
+ base_addr + RTR3);
+ break;
+ case 3:
+ if (priv->Tx_TS & (1 << (31 - TS_idx)))
+ writeb(readb(base_addr + TTR4) | (1 << i),
+ base_addr + TTR4);
+ if (priv->Rx_TS & (1 << (31 - TS_idx)))
+ writeb(readb(base_addr + RTR4) | (1 << i),
+ base_addr + RTR4);
+ break;
+ }
+ }
+
+ /* The hardware requires a delay up to 2*32*125 usec to take commands
+ * into account
+ */
+ udelay((2 * 32) * 125);
+
+ /* Unmask HDLC 1 Transmit IT */
+ writeb(readb(base_addr + IMR1) & ~1, base_addr + IMR1);
+ writeb(readb(base_addr + IMR1) & ~(1 << 4), base_addr + IMR1);
+ writeb(readb(base_addr + IMR1) & ~(1 << 5), base_addr + IMR1);
+
+ /* Unmask HDLC 1 Receive IT */
+ writeb(readb(base_addr + IMR0) & ~1, base_addr + IMR0);
+ writeb(readb(base_addr + IMR0) & ~(1 << 7), base_addr + IMR0);
+ writeb(readb(base_addr + IMR1) & ~(1 << 6), base_addr + IMR1);
+
+ /* The hardware requires a delay up to 2*32*125 usec to take commands
+ * into account
+ */
+ udelay((2 * 32) * 125);
+
+ return 0;
+}
+
+
+/* Init FALC56 */
+static int init_FALC(struct pef2256_dev_priv *priv)
+{
+ unsigned char *base_addr;
+ int Version;
+
+ /* Get controller version */
+ Version = priv->component_id;
+
+ /* Init FALC56 */
+ base_addr = priv->base_addr;
+ /* RCLK output : DPLL clock, DCO-X enabled, DCO-X internal reference
+ * clock
+ */
+ writeb(0x00, base_addr + CMR1);
+ /* SCLKR selected, SCLKX selected, receive synchro pulse sourced by
+ * SYPR, transmit synchro pulse sourced by SYPX
+ */
+ writeb(0x00, base_addr + CMR2);
+ /* NRZ coding, no alarm simulation */
+ writeb(0x00, base_addr + FMR0);
+ /* 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
+ */
+ writeb(0x00, base_addr + FMR1);
+ writeb(0x02, base_addr + FMR2);
+ /* E1 default for LIM2 */
+ writeb(0x20, base_addr + LIM2);
+ if (priv->mode == MASTER_MODE)
+ /* SEC input, active high */
+ writeb(0x00, base_addr + GPC1);
+ else
+ /* FSC output, active high */
+ writeb(0x40, base_addr + GPC1);
+ /* internal second timer, power on */
+ writeb(0x00, base_addr + GCR);
+ /* slave mode, local loop off, mode short-haul */
+ if (Version == VERSION_1_2)
+ writeb(0x00, base_addr + LIM0);
+ else
+ writeb(0x08, base_addr + LIM0);
+ /* analog interface selected, remote loop off */
+ writeb(0x00, base_addr + LIM1);
+ 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
+ */
+ writeb(0x77, base_addr + PC1);
+ writeb(0x77, base_addr + PC2);
+ writeb(0x77, base_addr + PC3);
+ writeb(0x77, base_addr + PC4);
+ } else {
+ /* function of ports RP(A to D) : output high
+ * function of ports XP(A to D) : output high
+ */
+ writeb(0xAA, base_addr + PC1);
+ writeb(0xAA, base_addr + PC2);
+ writeb(0xAA, base_addr + PC3);
+ writeb(0xAA, base_addr + PC4);
+ }
+ /* function of port RPA : input SYPR
+ * function of port XPA : input SYPX
+ */
+ writeb(0x00, base_addr + PC1);
+ /* SCLKR, SCLKX, RCLK configured to inputs,
+ * XFMS active low, CLK1 and CLK2 pin configuration
+ */
+ writeb(0x00, base_addr + PC5);
+ writeb(0x00, base_addr + PC6);
+ /* the receive clock offset is cleared
+ * the receive time slot offset is cleared
+ */
+ writeb(0x00, base_addr + RC0);
+ writeb(0x9C, base_addr + RC1);
+ /* 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
+ */
+ writeb(0x00, base_addr + SIC1);
+ writeb(0x00, base_addr + SIC2);
+ writeb(0x00, base_addr + SIC3);
+ /* channel loop-back and single frame mode are disabled */
+ writeb(0x00, base_addr + LOOP);
+ /* all bits of the transmitted service word are cleared */
+ writeb(0x1F, base_addr + XSW);
+ /* spare bit values are cleared */
+ writeb(0x00, base_addr + XSP);
+ /* no transparent mode active */
+ writeb(0x00, base_addr + TSWM);
+ /* the transmit clock offset is cleared
+ * the transmit time slot offset is cleared
+ */
+ writeb(0x00, base_addr + XC0);
+ writeb(0x9C, base_addr + XC1);
+ /* transmitter in tristate mode */
+ writeb(0x40, base_addr + XPM2);
+ /* transmit pulse mask */
+ if (Version != VERSION_1_2)
+ writeb(0x9C, base_addr + XPM0);
+
+ if (Version == VERSION_1_2) {
+ /* master clock is 16,384 MHz (flexible master clock) */
+ writeb(0x58, base_addr + GCM2);
+ writeb(0xD2, base_addr + GCM3);
+ writeb(0xC2, base_addr + GCM4);
+ writeb(0x07, base_addr + GCM5);
+ writeb(0x10, base_addr + GCM6);
+ } else {
+ /* master clock is 16,384 MHz (flexible master clock) */
+ writeb(0x18, base_addr + GCM2);
+ writeb(0xFB, base_addr + GCM3);
+ writeb(0x0B, base_addr + GCM4);
+ writeb(0x01, base_addr + GCM5);
+ writeb(0x0B, base_addr + GCM6);
+ writeb(0xDB, base_addr + GCM7);
+ writeb(0xDF, base_addr + GCM8);
+ }
+
+ /* master mode => LIM0.MAS = 1 (bit 0) */
+ if (priv->mode == MASTER_MODE)
+ writeb(readb(base_addr + LIM0) | (1 << 0), base_addr + LIM0);
+
+ /* transmit line in normal operation => XPM2.XLT = 0 (bit 6) */
+ writeb(readb(base_addr + XPM2) & ~(1 << 6), base_addr + XPM2);
+
+ if (Version == VERSION_1_2) {
+ /* receive input threshold = 0,21V =>
+ * LIM1.RIL2:0 = 101 (bits 6, 5 et 4)
+ */
+ writeb(readb(base_addr + LIM1) | (1 << 4), base_addr + LIM1);
+ writeb(readb(base_addr + LIM1) | (1 << 6), base_addr + LIM1);
+ } else {
+ /* receive input threshold = 0,21V =>
+ * LIM1.RIL2:0 = 100 (bits 6, 5 et 4)
+ */
+ writeb(readb(base_addr + LIM1) | (1 << 6), base_addr + LIM1);
+ }
+ /* transmit line coding = HDB3 => FMR0.XC1:0 = 11 (bits 7 et 6) */
+ writeb(readb(base_addr + FMR0) | (1 << 6), base_addr + FMR0);
+ writeb(readb(base_addr + FMR0) | (1 << 7), base_addr + FMR0);
+ /* receive line coding = HDB3 => FMR0.RC1:0 = 11 (bits 5 et 4) */
+ writeb(readb(base_addr + FMR0) | (1 << 4), base_addr + FMR0);
+ writeb(readb(base_addr + FMR0) | (1 << 5), base_addr + FMR0);
+ /* detection of LOS alarm = 176 pulses (soit (10 + 1) * 16) */
+ writeb(10, base_addr + PCD);
+ /* recovery of LOS alarm = 22 pulses (soit 21 + 1) */
+ writeb(21, base_addr + PCR);
+ /* DCO-X center frequency => CMR2.DCOXC = 1 (bit 5) */
+ writeb(readb(base_addr + CMR2) | (1 << 5), base_addr + CMR2);
+ if (priv->mode == SLAVE_MODE) {
+ /* select RCLK source = 2M => CMR1.RS(1:0) = 10 (bits 5 et 4) */
+ writeb(readb(base_addr + CMR1) | (1 << 5), base_addr + CMR1);
+ /* disable switching RCLK -> SYNC => CMR1.DCS = 1 (bit 3) */
+ writeb(readb(base_addr + CMR1) | (1 << 3), base_addr + CMR1);
+ }
+ if (Version != VERSION_1_2)
+ /* during inactive channel phase RDO into tri-state mode */
+ writeb(readb(base_addr + SIC3) | (1 << 5), base_addr + SIC3);
+ if (!strcmp(priv->rising_edge_sync_pulse, "transmit")) {
+ /* rising edge sync pulse transmit => SIC3.RESX = 1 (bit 3) */
+ writeb(readb(base_addr + SIC3) | (1 << 3), base_addr + SIC3);
+ } else {
+ /* rising edge sync pulse receive => SIC3.RESR = 1 (bit 2) */
+ writeb(readb(base_addr + SIC3) | (1 << 2), base_addr + SIC3);
+ }
+ /* transmit offset counter = 4
+ * => XC0.XCO10:8 = 000 (bits 2, 1 et 0);
+ * XC1.XCO7:0 = 4 (bits 7 ... 0)
+ */
+ writeb(4, base_addr + XC1);
+ /* receive offset counter = 4
+ * => RC0.RCO10:8 = 000 (bits 2, 1 et 0);
+ * RC1.RCO7:0 = 4 (bits 7 ... 0)
+ */
+ writeb(4, base_addr + RC1);
+
+ /* Nothing to do if clock rate = 8 Mhz or data rate = 2 Mb/s */
+
+ /* clocking rate 4M */
+ if (priv->clock_rate == CLOCK_RATE_4M)
+ writeb(readb(base_addr + SIC1) | (1 << 3), base_addr + SIC1);
+ /* clocking rate 8M */
+ if (priv->clock_rate == CLOCK_RATE_8M)
+ writeb(readb(base_addr + SIC1) | (1 << 7), base_addr + SIC1);
+ /* clocking rate 16M */
+ if (priv->clock_rate == CLOCK_RATE_16M) {
+ writeb(readb(base_addr + SIC1) | (1 << 3), base_addr + SIC1);
+ writeb(readb(base_addr + SIC1) | (1 << 7), base_addr + SIC1);
+ }
+
+ /* data rate 4M on the system data bus */
+ if (priv->data_rate == DATA_RATE_4M)
+ writeb(readb(base_addr + FMR1) | (1 << 1), base_addr + FMR1);
+ /* data rate 8M on the system data bus */
+ if (priv->data_rate == DATA_RATE_8M)
+ writeb(readb(base_addr + SIC1) | (1 << 6), base_addr + SIC1);
+ /* data rate 16M on the system data bus */
+ if (priv->data_rate == DATA_RATE_16M) {
+ writeb(readb(base_addr + FMR1) | (1 << 1), base_addr + FMR1);
+ writeb(readb(base_addr + SIC1) | (1 << 6), base_addr + SIC1);
+ }
+
+ /* channel phase for FALC56 */
+ if ((priv->channel_phase == CHANNEL_PHASE_1)
+ || (priv->channel_phase == CHANNEL_PHASE_3))
+ writeb(readb(base_addr + SIC2) | (1 << 1), base_addr + SIC2);
+ if ((priv->channel_phase == CHANNEL_PHASE_2)
+ || (priv->channel_phase == CHANNEL_PHASE_3))
+ writeb(readb(base_addr + SIC2) | (1 << 2), base_addr + SIC2);
+
+ if (priv->mode == SLAVE_MODE) {
+ /* transmit buffer size = 2 frames =>
+ * SIC1.XBS1:0 = 10 (bits 1 et 0)
+ */
+ writeb(readb(base_addr + SIC1) | (1 << 1), base_addr + SIC1);
+ }
+
+ /* transmit in multiframe => FMR1.XFS = 1 (bit 3) */
+ writeb(readb(base_addr + FMR1) | (1 << 3), base_addr + FMR1);
+ /* receive in multiframe => FMR2.RFS1:0 = 10 (bits 7 et 6) */
+ writeb(readb(base_addr + FMR2) | (1 << 7), base_addr + FMR2);
+ /* Automatic transmission of submultiframe status =>
+ * SP.AXS = 1 (bit 3)
+ */
+ writeb(readb(base_addr + XSP) | (1 << 3), base_addr + XSP);
+
+ /* error counter mode toutes les 1s => FMR1.ECM = 1 (bit 2) */
+ writeb(readb(base_addr + FMR1) | (1 << 2), base_addr + FMR1);
+ /* error counter mode COFA => GCR.ECMC = 1 (bit 4) */
+ writeb(readb(base_addr + GCR) | (1 << 4), base_addr + GCR);
+ /* errors in service words with no influence => RC0.SWD = 1 (bit 7) */
+ writeb(readb(base_addr + RC0) | (1 << 7), base_addr + RC0);
+ /* 4 consecutive incorrect FAS = loss of sync => RC0.ASY4 = 1 (bit 6) */
+ writeb(readb(base_addr + RC0) | (1 << 6), base_addr + RC0);
+ /* Si-Bit in service word from XDI => XSW.XSIS = 1 (bit 7) */
+ writeb(readb(base_addr + XSW) | (1 << 7), base_addr + XSW);
+ /* Si-Bit in FAS word from XDI => XSP.XSIF = 1 (bit 2) */
+ writeb(readb(base_addr + XSP) | (1 << 2), base_addr + XSP);
+
+ /* port RCLK is output => PC5.CRP = 1 (bit 0) */
+ writeb(readb(base_addr + PC5) | (1 << 0), base_addr + PC5);
+ /* visibility of the masked interrupts => GCR.VIS = 1 (bit 7) */
+ writeb(readb(base_addr + GCR) | (1 << 7), base_addr + GCR);
+ /* reset lines
+ * => CMDR.RRES = 1 (bit 6); CMDR.XRES = 1 (bit 4);
+ * CMDR.SRES = 1 (bit 0)
+ */
+ writeb(0x51, base_addr + CMDR);
+
+ return 0;
+}
+
+
+
+static int pef2256_open(struct net_device *netdev)
+{
+ struct pef2256_dev_priv *priv = dev_to_hdlc(netdev)->priv;
+ unsigned char *base_addr = 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",
+ readb(base_addr + VSTR), readb(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);
+
+ return 0;
+}
+
+
+
+static int pef2256_rx(struct pef2256_dev_priv *priv)
+{
+ struct sk_buff *skb;
+ int idx, size;
+ unsigned char *base_addr;
+
+ base_addr = priv->base_addr;
+
+ /* RDO has been received -> wait for RME */
+ if (priv->rx_len == -1) {
+ /* Acknowledge the FIFO */
+ writeb(readb(base_addr + CMDR) | (1 << 7), base_addr + CMDR);
+
+ if (priv->R_ISR0 & (1 << 7))
+ priv->rx_len = 0;
+
+ return 0;
+ }
+
+ /* RPF : a block is available in the receive FIFO */
+ if (priv->R_ISR0 & 1) {
+ for (idx = 0; idx < 32; idx++)
+ priv->rx_buff[priv->rx_len + idx] =
+ readb(base_addr + RFIFO + (idx & 1));
+
+ /* Acknowledge the FIFO */
+ writeb(readb(base_addr + CMDR) | (1 << 7), base_addr + CMDR);
+
+ priv->rx_len += 32;
+ }
+
+ /* RME : Message end : Read the receive FIFO */
+ if (priv->R_ISR0 & (1 << 7)) {
+ /* Get size of last block */
+ size = readb(base_addr + RBCL) & 0x1F;
+
+ /* Read last block */
+ for (idx = 0; idx < size; idx++)
+ priv->rx_buff[priv->rx_len + idx] =
+ readb(base_addr + RFIFO + (idx & 1));
+
+ /* Acknowledge the FIFO */
+ writeb(readb(base_addr + CMDR) | (1 << 7), base_addr + CMDR);
+
+ 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;
+ unsigned char *base_addr;
+ u8 *tx_buff = priv->tx_skb->data;
+
+ base_addr = priv->base_addr;
+
+ /* ALLS : transmit all done */
+ if (priv->R_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++)
+ writeb(tx_buff[priv->tx_len + idx],
+ base_addr + XFIFO + (idx & 1));
+
+ priv->tx_len += size;
+
+ if (priv->tx_len == priv->tx_skb->len)
+ writeb(readb(base_addr + CMDR) | ((1 << 3) | (1 << 1)),
+ base_addr + CMDR);
+ else
+ writeb(readb(base_addr + CMDR) | (1 << 3),
+ base_addr + CMDR);
+ }
+
+ return 0;
+}
+
+
+irqreturn_t pef2256_irq(int irq, void *dev_priv)
+{
+ struct pef2256_dev_priv *priv = (struct pef2256_dev_priv *)dev_priv;
+ unsigned char *base_addr;
+ u8 R_GIS;
+
+ base_addr = priv->base_addr;
+ R_GIS = readb(base_addr + GIS);
+
+ priv->R_ISR0 = priv->R_ISR1 = 0;
+
+ /* We only care about ISR0 and ISR1 */
+ /* ISR0 */
+ if (R_GIS & 1)
+ priv->R_ISR0 =
+ readb(base_addr + ISR0) & ~(readb(base_addr + IMR0));
+
+ /* ISR1 */
+ if (R_GIS & (1 << 1))
+ priv->R_ISR1 =
+ readb(base_addr + ISR1) & ~(readb(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->R_ISR1 & (1 << 6)) {
+ /* Acknowledge the FIFO */
+ writeb(readb(base_addr + CMDR) | (1 << 7), base_addr + CMDR);
+ priv->netdev->stats.rx_errors++;
+ /* RME received ? */
+ if (priv->R_ISR0 & (1 << 7))
+ priv->rx_len = 0;
+ else
+ priv->rx_len = -1;
+ return IRQ_HANDLED;
+ }
+
+ /* XDU : Transmit data underrun -> TX error */
+ if (priv->R_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->R_ISR0 & (1 | (1 << 7)))
+ pef2256_rx(priv);
+
+ /* XPR or ALLS : FIFO sent */
+ if (priv->R_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;
+ unsigned char *base_addr;
+ u8 *tx_buff = skb->data;
+
+ base_addr = 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++)
+ writeb(tx_buff[priv->tx_len + idx],
+ base_addr + XFIFO + (idx & 1));
+
+ priv->tx_len += size;
+
+ writeb(readb(base_addr + CMDR) | (1 << 3), base_addr + CMDR);
+ if (priv->tx_len == priv->tx_skb->len)
+ writeb(readb(base_addr + CMDR) | (1 << 1), base_addr + CMDR);
+
+ 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 = hdlc_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 int pef2256_probe(struct platform_device *pdev)
+{
+ struct pef2256_dev_priv *priv;
+ int ret = -ENOMEM;
+ struct net_device *netdev;
+ hdlc_device *hdlc;
+ unsigned char *base_addr;
+ struct device_node *np = (&pdev->dev)->of_node;
+ const char *str_data;
+
+ if (!pdev->dev.of_node)
+ return -EINVAL;
+
+ dev_err(&pdev->dev, "Found PEF2256\n");
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return ret;
+
+ priv->dev = &pdev->dev;
+
+ if (of_property_read_u32(np, "clock-rate", &priv->clock_rate)) {
+ dev_err(&pdev->dev, "failed to read clock-rate -> using 8Mhz\n");
+ priv->clock_rate = CLOCK_RATE_8M;
+ }
+
+ if (of_property_read_u32(np, "data-rate", &priv->data_rate)) {
+ dev_err(&pdev->dev, "failed to read data-rate -> using 8Mb\n");
+ priv->data_rate = DATA_RATE_8M;
+ }
+
+ if (of_property_read_u32(np, "channel-phase", &priv->channel_phase)) {
+ dev_err(&pdev->dev, "failed to read channel phase -> using 0\n");
+ priv->channel_phase = CHANNEL_PHASE_0;
+ }
+
+ if (of_property_read_string(np, "rising-edge-sync-pulse", &str_data)) {
+ dev_err(&pdev->dev,
+"failed to read rising edge sync pulse -> using \"transmit\"\n");
+ strcpy(priv->rising_edge_sync_pulse, "transmit");
+ } else if (strcmp(str_data, "transmit") &&
+ strcmp(str_data, "receive")) {
+ dev_err(&pdev->dev,
+"invalid rising edge sync pulse \"%s\" -> using \"transmit\"\n", str_data);
+ strcpy(priv->rising_edge_sync_pulse, "transmit");
+ } else
+ strncpy(priv->rising_edge_sync_pulse, str_data, 10);
+
+ priv->irq = platform_get_irq(pdev, 0);
+ 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(&pdev->dev, "of_iomap failed\n");
+ goto free_priv;
+ }
+
+ /* Get the component Id */
+ base_addr = priv->base_addr;
+ priv->component_id = VERSION_UNDEF;
+ if (readb(base_addr + VSTR) == 0x00) {
+ if ((readb(base_addr + WID) & WID_IDENT_1) ==
+ WID_IDENT_1_2)
+ priv->component_id = VERSION_1_2;
+ } else if (readb(base_addr + VSTR) == 0x05) {
+ if ((readb(base_addr + WID) & WID_IDENT_2) ==
+ WID_IDENT_2_1)
+ priv->component_id = VERSION_2_1;
+ else if ((readb(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) {
+ dev_err(&pdev->dev, "alloc_hdlcdev failed\n");
+ ret = -ENOMEM;
+ goto free_regs;
+ }
+
+ priv->netdev = netdev;
+ hdlc = dev_to_hdlc(netdev);
+ netdev->netdev_ops = &pef2256_ops;
+ SET_NETDEV_DEV(netdev, &pdev->dev);
+ hdlc->attach = pef2256_hdlc_attach;
+ hdlc->xmit = pef2256_start_xmit;
+
+ dev_set_drvdata(&pdev->dev, netdev);
+
+ ret = register_hdlc_device(netdev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Can't register hdlc device\n");
+ goto free_dev;
+ }
+
+ /* These files are required to configure HDLC : mode
+ * (master or slave), time slots used to transmit and
+ * receive data. They are mandatory.
+ */
+ ret = device_create_file(priv->dev, &dev_attr_mode);
+ ret |= device_create_file(priv->dev, &dev_attr_Tx_TS);
+ ret |= device_create_file(priv->dev, &dev_attr_Rx_TS);
+
+ if (ret)
+ goto remove_files;
+
+ /* This file is only used to display debug infos.
+ * A failure can be safely ignored.
+ */
+ device_create_file(priv->dev, &dev_attr_regs);
+
+ priv->init_done = 0;
+
+ return 0;
+
+remove_files:
+ device_remove_file(priv->dev, &dev_attr_Tx_TS);
+ device_remove_file(priv->dev, &dev_attr_Rx_TS);
+ device_remove_file(priv->dev, &dev_attr_mode);
+
+ unregister_hdlc_device(priv->netdev);
+free_dev:
+ free_netdev(priv->netdev);
+free_regs:
+ iounmap(priv->base_addr);
+free_priv:;
+ kfree(priv);
+
+ return ret;
+}
+
+
+/* Removing module */
+static int pef2256_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = dev_get_drvdata(&pdev->dev);
+ struct pef2256_dev_priv *priv = dev_to_hdlc(ndev)->priv;
+
+
+ device_remove_file(priv->dev, &dev_attr_regs);
+ device_remove_file(priv->dev, &dev_attr_Tx_TS);
+ device_remove_file(priv->dev, &dev_attr_Rx_TS);
+ device_remove_file(priv->dev, &dev_attr_mode);
+
+ unregister_hdlc_device(priv->netdev);
+
+ free_netdev(priv->netdev);
+
+ iounmap(priv->base_addr);
+
+ kfree(priv);
+
+ dev_set_drvdata(&pdev->dev, NULL);
+ kfree(pdev);
+ 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,
+ },
+};
+
+
+module_platform_driver(pef2256_driver);
+
+/* 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,256 @@
+/* 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 CLOCK_RATE_2M 2
+#define CLOCK_RATE_4M 4
+#define CLOCK_RATE_8M 8
+#define CLOCK_RATE_16M 16
+
+#define DATA_RATE_2M 2
+#define DATA_RATE_4M 4
+#define DATA_RATE_8M 8
+#define DATA_RATE_16M 16
+
+#define RX_TIMEOUT 500
+
+#define TS_0 0x80000000
+
+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;
+
+ unsigned char *base_addr;
+ int component_id;
+ int mode; /* MASTER or SLAVE */
+ int board_type;
+ int channel_phase;
+ int clock_rate;
+ 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 R_ISR0; /* ISR0 register */
+ u8 R_ISR1; /* ISR1 register */
+};
+
+
+/* Framer E1 registers offsets */
+#define XFIFO 0x00 /* 0x00/0x01 Tx FIFO */
+#define RFIFO 0x00 /* 0x00/0x01 Rx FIFO */
+#define CMDR 0x02 /* 0x02 Command Register */
+#define MODE 0x03 /* 0x03 Mode Register */
+#define RAH1 0x04 /* 0x04 Receive Address High 1 */
+#define RAH2 0x05 /* 0x05 Receive Address High 2 */
+#define RAL1 0x06 /* 0x06 Receive Address Low 1 */
+#define RAL2 0x07 /* 0x07 Receive Address Low 2 */
+#define IPC 0x08 /* 0x08 Interrupt Port Configuration */
+#define CCR1 0x09 /* 0x09 Common Configuration Register 1 */
+#define CCR2 0x0A /* 0x0A Common Configuration Register 2 */
+#define Res1 0x0B /* 0x0B Free Register 1 */
+#define RTR1 0x0C /* 0x0C Receive Time Slot Register 1 */
+#define RTR2 0x0D /* 0x0D Receive Time Slot Register 2 */
+#define RTR3 0x0E /* 0x0E Receive Time Slot Register 3 */
+#define RTR4 0x0F /* 0x0F Receive Time Slot Register 4 */
+#define TTR1 0x10 /* 0x10 Transmit Time Slot Register 1 */
+#define TTR2 0x11 /* 0x11 Transmit Time Slot Register 2 */
+#define TTR3 0x12 /* 0x12 Transmit Time Slot Register 3 */
+#define TTR4 0x13 /* 0x13 Transmit Time Slot Register 4 */
+#define IMR0 0x14 /* 0x14 Interrupt Mask Register 0 */
+#define IMR1 0x15 /* 0x15 Interrupt Mask Register 1 */
+#define IMR2 0x16 /* 0x16 Interrupt Mask Register 2 */
+#define IMR3 0x17 /* 0x17 Interrupt Mask Register 3 */
+#define IMR4 0x18 /* 0x18 Interrupt Mask Register 4 */
+#define IMR5 0x19 /* 0x19 Interrupt Mask Register 5 */
+#define Res2 0x1A /* 0x1A Free Register 2 */
+#define IERR 0x1B /* 0x1B Single Bit Error Insertion Register */
+#define FMR0 0x1C /* 0x1C Framer Mode Register 0 */
+#define FMR1 0x1D /* 0x1D Framer Mode Register 1 */
+#define FMR2 0x1E /* 0x1E Framer Mode Register 2 */
+#define LOOP 0x1F /* 0x1F Channel Loop-Back */
+#define XSW 0x20 /* 0x20 Transmit Service Word */
+#define XSP 0x21 /* 0x21 Transmit Spare Bits */
+#define XC0 0x22 /* 0x22 Transmit Control 0 */
+#define XC1 0x23 /* 0x23 Transmit Control 1 */
+#define RC0 0x24 /* 0x24 Receive Control 0 */
+#define RC1 0x25 /* 0x25 Receive Control 1 */
+#define XPM0 0x26 /* 0x26 Transmit Pulse Mask 0 */
+#define XPM1 0x27 /* 0x27 Transmit Pulse Mask 1 */
+#define XPM2 0x28 /* 0x28 Transmit Pulse Mask 2 */
+#define TSWM 0x29 /* 0x29 Transparent Service Word Mask */
+#define Res3 0x2A /* 0x2A Free Register 3 */
+#define IDLE 0x2B /* 0x2B Idle Channel Code */
+#define XSA4 0x2C /* 0x2C Transmit Sa4-Bit Register */
+#define XSA5 0x2D /* 0x2D Transmit Sa5-Bit Register */
+#define XSA6 0x2E /* 0x2E Transmit Sa6-Bit Register */
+#define XSA7 0x2F /* 0x2F Transmit Sa7-Bit Register */
+#define XSA8 0x30 /* 0x30 Transmit Sa8-Bit Register */
+#define FMR3 0x31 /* 0x31 Framer Mode Register 3 */
+#define ICB1 0x32 /* 0x32 Idle Channel Register 1 */
+#define ICB2 0x33 /* 0x33 Idle Channel Register 2 */
+#define ICB3 0x34 /* 0x34 Idle Channel Register 3 */
+#define ICB4 0x35 /* 0x35 Idle Channel Register 4 */
+#define LIM0 0x36 /* 0x36 Line Interface Mode 0 */
+#define LIM1 0x37 /* 0x37 Line Interface Mode 1 */
+#define PCD 0x38 /* 0x38 Pulse Count Detection */
+#define PCR 0x39 /* 0x39 Pulse Count Recovery */
+#define LIM2 0x3A /* 0x3A Line Interface Mode 2 */
+#define LCR1 0x3B /* 0x3B Loop Code Register 1 */
+#define LCR2 0x3C /* 0x3C Loop Code Register 2 */
+#define LCR3 0x3D /* 0x3D Loop Code Register 3 */
+#define SIC1 0x3E /* 0x3E System Interface Control 1 */
+#define SIC2 0x3F /* 0x3F System Interface Control 2 */
+#define SIC3 0x40 /* 0x40 System Interface Control 3 */
+#define Res4 0x41 /* 0x41 Free Register 4 */
+#define Res5 0x42 /* 0x42 Free Register 5 */
+#define Res6 0x43 /* 0x43 Free Register 6 */
+#define CMR1 0x44 /* 0x44 Clock Mode Register 1 */
+#define CMR2 0x45 /* 0x45 Clock Mode Register 2 */
+#define GCR 0x46 /* 0x46 Global Configuration Register */
+#define ESM 0x47 /* 0x47 Errored Second Mask */
+#define CMR3 0x48 /* 0x48 Clock Mode Register 3 en V2.2 */
+#define RBD 0x49 /* 0x49 Receive Buffer Delay */
+#define VSTR 0x4A /* 0x4A Version Status Regiter */
+#define RES 0x4B /* 0x4B Receive Equalizer Status */
+#define FRS0 0x4C /* 0x4C Framer Receive Status 0 */
+#define FRS1 0x4D /* 0x4D Framer Receive Status 1 */
+#define RSW 0x4E /* 0x4E Receive Service Word */
+#define RSP 0x4F /* 0x4F Receive Spare Bits */
+#define FEC 0x50 /* 0x50/0x51 Framing Error Counter */
+#define CVC 0x52 /* 0x52/0x53 Code Violation Counter */
+#define CEC1 0x54 /* 0x54/0x55 CRC Error Counter 1 */
+#define EBC 0x56 /* 0x56/0x57 E-Bit Error Counter */
+#define CEC2 0x58 /* 0x58/0x59 CRC Error Counter 2 */
+#define CEC3 0x5A /* 0x5A/0x5B CRC Error Counter 3 */
+#define RSA4 0x5C /* 0x5C Receive Sa4-Bit Register */
+#define RSA5 0x5D /* 0x5D Receive Sa5-Bit Register */
+#define RSA6 0x5E /* 0x5E Receive Sa6-Bit Register */
+#define RSA7 0x5F /* 0x5F Receive Sa7-Bit Register */
+#define DEC 0x60 /* 0x60 Common Register - Disable Error Counter */
+#define RSA8 0x60 /* 0x60 Common Register - Receive Sa8-Bit Regiter */
+#define RSA6S 0x61 /* 0x61 Receive Sa6-Bit Status Register */
+#define RSP1 0x62 /* 0x62 Receive Signaling Pointer 1 */
+#define RSP2 0x63 /* 0x63 Receive Signaling Pointer 2 */
+#define SIS 0x64 /* 0x64 Signaling Status Register */
+#define RSIS 0x65 /* 0x65 Receive Signaling Status Register */
+#define RBCL 0x66 /* 0x66 Receive Byte Control */
+#define RBCH 0x67 /* 0x67 Receive Byte Control */
+#define ISR0 0x68 /* 0x68 Interrupt Status Register 0 */
+#define ISR1 0x69 /* 0x69 Interrupt Status Register 1 */
+#define ISR2 0x6A /* 0x6A Interrupt Status Register 2 */
+#define ISR3 0x6B /* 0x6B Interrupt Status Register 3 */
+#define ISR4 0x6C /* 0x6C Interrupt Status Register 4 */
+#define ISR5 0x6D /* 0x6D Interrupt Status Register 5 */
+#define GIS 0x6E /* 0x6E Global Interrupt Status */
+#define Res8 0x6F /* 0x6F Free Register 8 */
+#define CAS1 0x70 /* 0x70 CAS Register 1 */
+#define CAS2 0x71 /* 0x71 CAS Register 2 */
+#define CAS3 0x72 /* 0x72 CAS Register 3 */
+#define CAS4 0x73 /* 0x73 CAS Register 4 */
+#define CAS5 0x74 /* 0x74 CAS Register 5 */
+#define CAS6 0x75 /* 0x75 CAS Register 6 */
+#define CAS7 0x76 /* 0x76 CAS Register 7 */
+#define CAS8 0x77 /* 0x77 CAS Register 8 */
+#define CAS9 0x78 /* 0x78 CAS Register 9 */
+#define CAS10 0x79 /* 0x79 CAS Register 10 */
+#define CAS11 0x7A /* 0x7A CAS Register 11 */
+#define CAS12 0x7B /* 0x7B CAS Register 12 */
+#define CAS13 0x7C /* 0x7C CAS Register 13 */
+#define CAS14 0x7D /* 0x7D CAS Register 14 */
+#define CAS15 0x7E /* 0x7E CAS Register 15 */
+#define CAS16 0x7F /* 0x7F CAS Register 16 */
+#define PC1 0x80 /* 0x80 Port Configuration 1 */
+#define PC2 0x81 /* 0x81 Port Configuration 2 */
+#define PC3 0x82 /* 0x82 Port Configuration 3 */
+#define PC4 0x83 /* 0x83 Port Configuration 4 */
+#define PC5 0x84 /* 0x84 Port Configuration 5 */
+#define GPC1 0x85 /* 0x85 Global Port Configuration 1 */
+#define PC6 0x86 /* 0x86 Port Configuration 6 */
+#define CMDR2 0x87 /* 0x87 Command Register 2 */
+#define CMDR3 0x88 /* 0x88 Command Register 3 */
+#define CMDR4 0x89 /* 0x89 Command Register 4 */
+#define Res9 0x8A /* 0x8A Free Register 9 */
+#define CCR3 0x8B /* 0x8B Common Control Register 3 */
+#define CCR4 0x8C /* 0x8C Common Control Register 4 */
+#define CCR5 0x8D /* 0x8D Common Control Register 5 */
+#define MODE2 0x8E /* 0x8E Mode Register 2 */
+#define MODE3 0x8F /* 0x8F Mode Register 3 */
+#define RBC2 0x90 /* 0x90 Receive Byte Count Register 2 */
+#define RBC3 0x91 /* 0x91 Receive Byte Count Register 3 */
+#define GCM1 0x92 /* 0x92 Global Counter Mode 1 */
+#define GCM2 0x93 /* 0x93 Global Counter Mode 2 */
+#define GCM3 0x94 /* 0x94 Global Counter Mode 3 */
+#define GCM4 0x95 /* 0x95 Global Counter Mode 4 */
+#define GCM5 0x96 /* 0x96 Global Counter Mode 5 */
+#define GCM6 0x97 /* 0x97 Global Counter Mode 6 */
+#define SIS2_1 0x98 /* 0x98 V1.2 : Signaling Status Register 2 */
+#define GCM7 0x98 /* 0x98 V2.2 : Global Counter Mode 7 */
+#define RSIS2_1 0x99 /* 0x99 V1.2 : Rx Signaling Status Register 2 */
+#define GCM8 0x99 /* 0x99 V2.2 : Global Counter Mode 8 */
+#define SIS3 0x9A /* 0x9A Signaling Status Register 3 */
+#define RSIS3 0x9B /* 0x9B Receive Signaling Status Register 3 */
+#define XFIFO2 0x9C /* 0x9C/0x9D Tx FIFO 2 */
+#define RFIFO2 0x9C /* 0x9C/0x9D Rx FIFO 2 */
+#define XFIFO3 0x9E /* 0x9E/0x9F Tx FIFO 3 */
+#define RFIFO3 0x9E /* 0x9E/0x9F Rx FIFO 3 */
+#define TSEO 0xA0 /* 0xA0 Time Slot Even/Odd select */
+#define TSBS1 0xA1 /* 0xA1 Time Slot Bit select 1 */
+#define TSBS2 0xA2 /* 0xA2 Time Slot Bit select 2 */
+#define TSBS3 0xA3 /* 0xA3 Time Slot Bit select 3 */
+#define TSS2 0xA4 /* 0xA4 Time Slot select 2 */
+#define TSS3 0xA5 /* 0xA5 Time Slot select 3 */
+#define Res10 0xA6 /* 0xA6 Free Register 10 */
+#define Res11 0xA7 /* 0xA7 Free Register 11 */
+#define TPC0 0xA8 /* 0xA8 Test Pattern Control Register 0 */
+#define SIS2 0xA9 /* 0xA9 Signaling Status Register 2 (V2.2) */
+#define RSIS2 0xAA /* 0xAA Rx Signaling Status Register 2 (V2.2) */
+#define MFPI 0xAB /* 0xAB Multi Function Port Input Status */
+#define Res12 0xAC /* 0xAC Free Register 12 */
+#define Res13 0xAD /* 0xAD Free Register 13 */
+#define Res14 0xAE /* 0xAE Free Register 14 */
+#define GLC1 0xAF /* 0xAF Global Line Control Register 1 */
+#define Res15 0xB0 /* 0xB0/0xEB Free Registers */
+#define WID 0xEC /* 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,74 @@
+* Wan on Infineon PEF2256 E1 controller, also known as FALC56
+
+The PEF2256 is a E1/T1/J1 Framer and Line Interface Component for Long- and
+Short-Haul Applications.
+Its datashhet can be downloaded at
+http://www.datasheetcatalog.com/datasheets_pdf/P/E/F/2/PEF2256E.shtml
+
+The FALC56 framer and line interface component is designed to fulfill all
+required interfacing between analog E1 lines and the digital PCM system
+highway, H.100/H.110 or H-MVIP bus.
+
+Required properties:
+- compatible: Should contain "infineon,pef2256"
+- reg: Address and length of the register set for the device.
+ There should be a single continuous bank.
+- interrupts: Should contain the single interrupt used by the component to
+ notify special events (error, data received, data transmitted, ...).
+
+Optional properties:
+
+These properties can be defined to adjust the system interface in E1 mode.
+
+The FALC56 offers a flexible feature for system designers where for transmit and
+receive direction different system clocks and system pulses are necessary. The
+interface to the receive system highway is realized by two data buses, one for
+the data RDO and one for the signaling data RSIG. The receive highway is clocked
+on pin SCLKR, while the interface to the transmit system highway is
+independently clocked on pin SCLKX. The frequency of these working clocks and
+the data rate of 2.048/4.096/8.192/16.384 Mbit/s for the receive and transmit
+system interface is programmable.
+
+- clock-rate:
+ Supported values are: 2 (2.048 Mhz), 4 (4.096 Mhz), 8 (8.192 Mhz),
+ 16 (16.384 Mhz).
+ 8 if not defined.
+
+- data-rate:
+ Supported values are: 2 (2.048 Mbit/sec), 4 (4.096 Mbit/sec),
+ 8 (8.192 Mbit/sec), 16 (16.384 Mbit/sec).
+ 8 if not defined.
+
+Adjusting the frame begin (time slot 0, bit 0) relative to SYPR/X or XMFS is
+possible in the range of 0 to 125 µs. The minimum shift of varying the
+time slot 0 begin can be programmed between 1 bit and 1/8 bit depending of the
+system clocking and data rate, e.g. with a clocking/data rate of 2.048 MHz
+shifting is done bit by bit, while running the FALC56 with 16.384 MHz and
+2.048 Mbit/s data rate it is done by 1/8 bit
+
+- channel-phase: First time slot transmission channel phase.
+ Supported values are: 0, 1, 2, 3, 4, 5, 6, 7.
+ 0 if not defined.
+
+All transmit or receive system interface data and marker are clocked or sampled
+with the following active edge :
+* Latched with the first falling edge of the selected PCM highway clock.
+* Latched with the first rising edge of the selected PCM highway clock.
+The behaviour of "transmit" and "receive" signals is inverse.
+
+- 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>;
+ clock-rate = <4>;
+ 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
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] WAN: Adding support for Infineon PEF2256 E1 chipset (FALC56)
2013-11-01 15:01 [PATCH v2] WAN: Adding support for Infineon PEF2256 E1 chipset (FALC56) Christophe Leroy
@ 2013-11-01 15:36 ` Govindarajulu Varadarajan
2013-11-02 22:26 ` Francois Romieu
2013-11-15 15:17 ` thomas.langer
2 siblings, 0 replies; 4+ messages in thread
From: Govindarajulu Varadarajan @ 2013-11-01 15:36 UTC (permalink / raw)
To: Christophe Leroy
Cc: Rob Herring, Pawel Moll, Mark Rutland, Stephen Warren,
Ian Campbell, Rob Landley, Grant Likely, Krzysztof Halasa,
devicetree, linux-doc, linux-kernel, netdev
On Fri, 1 Nov 2013, Christophe Leroy wrote:
> diff -urN a/drivers/net/wan/pef2256.c b/drivers/net/wan/pef2256.c
[..]
> +static int pef2256_remove(struct platform_device *pdev)
> +{
> + struct net_device *ndev = dev_get_drvdata(&pdev->dev);
> + struct pef2256_dev_priv *priv = dev_to_hdlc(ndev)->priv;
> +
> +
> + device_remove_file(priv->dev, &dev_attr_regs);
> + device_remove_file(priv->dev, &dev_attr_Tx_TS);
> + device_remove_file(priv->dev, &dev_attr_Rx_TS);
> + device_remove_file(priv->dev, &dev_attr_mode);
> +
> + unregister_hdlc_device(priv->netdev);
> +
> + free_netdev(priv->netdev);
> +
> + iounmap(priv->base_addr);
> +
> + kfree(priv);
> +
> + dev_set_drvdata(&pdev->dev, NULL);
dev_set_drvdata is not necessary. driver core clears the driver data to NULL
after device_release or on probe failure.
//govind
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] WAN: Adding support for Infineon PEF2256 E1 chipset (FALC56)
2013-11-01 15:01 [PATCH v2] WAN: Adding support for Infineon PEF2256 E1 chipset (FALC56) Christophe Leroy
2013-11-01 15:36 ` Govindarajulu Varadarajan
@ 2013-11-02 22:26 ` Francois Romieu
2013-11-15 15:17 ` thomas.langer
2 siblings, 0 replies; 4+ messages in thread
From: Francois Romieu @ 2013-11-02 22:26 UTC (permalink / raw)
To: Christophe Leroy
Cc: Rob Herring, Pawel Moll, Mark Rutland, Stephen Warren,
Ian Campbell, Rob Landley, Grant Likely, Krzysztof Halasa,
devicetree, linux-doc, linux-kernel, netdev,
jerome.chantelauze.ext
Christophe Leroy <christophe.leroy@c-s.fr> :
> The patch adds WAN support for Infineon FALC56 - PEF2256 E1 Chipset.
>
> Signed-off-by: Jerome Chantelauze <jerome.chantelauze.ext@c-s.fr>
> Acked-by: Christophe Leroy <christophe.leroy@c-s.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
[...]
> +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);
You should avoid mixed case function names.
You can reorder and remove the forward declarations: none of pef2256_irq,
Config_HDLC, init_FALC or pef2256_close exhibits any external dependency.
pef2256_open only needs the three former.
> +void print_regs(struct device *dev)
> +{
> + struct net_device *ndev = dev_get_drvdata(dev);
> + struct pef2256_dev_priv *priv = dev_to_hdlc(ndev)->priv;
> + unsigned char *base_addr = priv->base_addr;
> +
> + netdev_info(ndev, " MODE = 0x%02x\n", readb(base_addr + MODE));
[...]
> +static DEVICE_ATTR(regs, S_IRUGO, fs_attr_regs_show, NULL);
It duplicates an existing API. See ETHTOOL_GREGS in net/core/ethtool.c.
[...]
> +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;
> + long int value;
> + int ret = kstrtol(buf, 10, &value);
> + int reconfigure = (value != priv->mode);
> +
> + if (value != MASTER_MODE && value != SLAVE_MODE)
> + ret = -EINVAL;
> +
> + if (ret < 0)
> + netdev_info(ndev, "Invalid mode (0 or 1 expected\n");
> + else {
> + priv->mode = value;
> + if (reconfigure && priv->init_done) {
> + pef2256_close(ndev);
> + init_FALC(priv);
> + pef2256_open(ndev);
*ouch*
This code badly races with normal uses of ndev->{open / close}. You can't
do that.
You may split the pef2256_open function in several parts and share the
relevant one with the sysfs functions (assuming some extra mutex based
locking).
You want to update the hardware configuration. You don't need any software
data housekeeping and you don't want a complete close (free_irq, hdlc unreg,
etc.) / open cycle. It seems simple but most of time it's a pain to get the
error processing part right and once you get there one realizes that it
does a lot of useless work.
[...]
> +/* Setting up HDLC channel */
> +int Config_HDLC(struct pef2256_dev_priv *priv)
Missing 'static'.
> +{
> + int i;
Excess scope.
> + int TS_idx;
> + unsigned char *base_addr;
> + u8 dummy;
> +
> + /* Set framer E1 address */
> + base_addr = priv->base_addr;
Usually done in a single line:
unsigned char *base_addr = priv->base_addr;
> +
> + /* Read to remove pending IT */
> + dummy = readb(base_addr + ISR0);
> + dummy = readb(base_addr + ISR1);
> +
> + /* Mask HDLC 1 Transmit IT */
> + writeb(readb(base_addr + IMR1) | 1, base_addr + IMR1);
> + writeb(readb(base_addr + IMR1) | (1 << 4), base_addr + IMR1);
> + writeb(readb(base_addr + IMR1) | (1 << 5), base_addr + IMR1);
Two points:
1.
#define IMR1 ... (ok, you did it in the .h file)
#define IMR1_XDU ...
#define IMR1_ALLS ...
Please use more #define and remove the redundant part in the comments
(the "Receiver inactive", "CRC on", etc. is imho welcome though).
2.
You may consider adding a few functions / define
static u8 pef_r8(struct pef2256 *pp, u32 offset)
static void pef_w8(struct pef2256 *pp, u32 offset, u8 val)
static void pef_rwm8(struct pef2256 *pp, u32 offset, u8 val)
> +
> + /* Mask HDLC 1 Receive IT */
> + writeb(readb(base_addr + IMR0) | 1, base_addr + IMR0);
> + writeb(readb(base_addr + IMR0) | (1 << 7), base_addr + IMR0);
> + writeb(readb(base_addr + IMR1) | (1 << 6), base_addr + IMR1);
> +
> + /* The hardware requires a delay up to 2*32*125 usec to take commands
> + * into account
> + */
> + 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)
> + */
> + writeb(1 << 3, base_addr + MODE);
> + /* CCR1.EITS = 1 (Enable internal Time Slot 31:0 Signaling)
> + * CCR1.XMFA = 0 (No transmit multiframe alignment)
> + * CCR1.RFT1:0 = 00 (RFIFO is 32 bytes)
> + * setting up Interframe Time Fill
> + * CCR1.ITF = 1 (Interframe Time Fill Continuous flag)
> + */
> + writeb(0x10 | (1 << 3), base_addr + CCR1);
> + /* CCR2.XCRC = 0 (Transmit CRC ON)
> + * CCR2.RCRC = 0 (Receive CRC ON, no write in RFIFO)
> + * CCR2.RADD = 0 (No write address in RFIFO)
> + */
> + writeb(0x00, base_addr + CCR2);
> +
> + /* The hardware requires a delay up to 2*32*125 usec to take commands
> + * into account
> + */
> + 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)
> + */
> + writeb(1 << 3, base_addr + MODE);
> + /* CCR1.EITS = 1 (Enable internal Time Slot 31:0 Signaling)
> + * CCR1.XMFA = 0 (No transmit multiframe alignment)
> + * CCR1.RFT1:0 = 00 (RFIFO is 32 bytes)
> + * setting up Interframe Time Fill
> + * CCR1.ITF = 1 (Interframe Time Fill Continuous flag)
> + */
> + writeb(0x10 | (1 << 3), base_addr + CCR1);
> + /* CCR2.XCRC = 0 (Transmit CRC ON)
> + * CCR2.RCRC = 0 (Receive CRC ON, no write in RFIFO)
> + * CCR2.RADD = 0 (No write address in RFIFO)
> + */
> + writeb(0x00, base_addr + CCR2);
> +
> + /* The hardware requires a delay up to 2*32*125 usec to take commands
> + * into account
> + */
> + 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)
> + */
> + writeb(1 << 3, base_addr + MODE);
> + /* CCR1.EITS = 1 (Enable internal Time Slot 31:0 Signaling)
> + * CCR1.XMFA = 0 (No transmit multiframe alignment)
> + * CCR1.RFT1:0 = 00 (RFIFO is 32 bytes)
> + * setting up Interframe Time Fill
> + * CCR1.ITF = 1 (Interframe Time Fill Continuous flag)
> + */
> + writeb(0x10 | (1 << 3), base_addr + CCR1);
> + /* CCR2.XCRC = 0 (Transmit CRC ON)
> + * CCR2.RCRC = 0 (Receive CRC ON, no write in RFIFO)
> + * CCR2.RADD = 0 (No write address in RFIFO)
> + */
> + writeb(0x00, base_addr + CCR2);
> +
> + /* The hardware requires a delay up to 2*32*125 usec to take commands
> + * into account
> + */
> + udelay((2 * 32) * 125);
> +
> + /* Init Time Slot select */
> + writeb(0x00, base_addr + TTR1);
> + writeb(0x00, base_addr + TTR2);
> + writeb(0x00, base_addr + TTR3);
> + writeb(0x00, base_addr + TTR4);
> + writeb(0x00, base_addr + RTR1);
> + writeb(0x00, base_addr + RTR2);
> + writeb(0x00, base_addr + RTR3);
> + writeb(0x00, base_addr + RTR4);
> + /* 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)))
> + writeb(readb(base_addr + TTR1) | (1 << i),
> + base_addr + TTR1);
> + if (priv->Rx_TS & (1 << (31 - TS_idx)))
> + writeb(readb(base_addr + RTR1) | (1 << i),
> + base_addr + RTR1);
> + break;
> + case 1:
> + if (priv->Tx_TS & (1 << (31 - TS_idx)))
> + writeb(readb(base_addr + TTR2) | (1 << i),
> + base_addr + TTR2);
> + if (priv->Rx_TS & (1 << (31 - TS_idx)))
> + writeb(readb(base_addr + RTR2) | (1 << i),
> + base_addr + RTR2);
> + break;
> + case 2:
> + if (priv->Tx_TS & (1 << (31 - TS_idx)))
> + writeb(readb(base_addr + TTR3) | (1 << i),
> + base_addr + TTR3);
> + if (priv->Rx_TS & (1 << (31 - TS_idx)))
> + writeb(readb(base_addr + RTR3) | (1 << i),
> + base_addr + RTR3);
> + break;
> + case 3:
> + if (priv->Tx_TS & (1 << (31 - TS_idx)))
> + writeb(readb(base_addr + TTR4) | (1 << i),
> + base_addr + TTR4);
> + if (priv->Rx_TS & (1 << (31 - TS_idx)))
> + writeb(readb(base_addr + RTR4) | (1 << i),
> + base_addr + RTR4);
> + break;
May I suggest some slightly less yank pasted code ?
for (i = 1; i < 32; i++)
config_hdlc_timeslot(struct pef2256_dev_priv *priv, i);
static void config_hdlc_timeslot(struct pef2256_dev_priv *priv, int ts)
{
static struct {
u32 ttr;
u32 rtr;
} regs [] = {
{ TTR1, RTR1},
{ TTR2, RTR2},
{ TTR3, RTR3},
{ TTR4, RTR4}
};
int cfg_bit = 1 << (31 - ts);
int reg_bit = 1 << (7 - (ts % 8));
int j = ts / 8;
if (j >= 4)
return;
if (priv->Tx_TS & cfg_bit)
writeb(readb(base_addr + regs[j].ttr) | reg_bit,
base_addr + regs[j].ttr);
if (priv->Rx_TS & cfg_bit)
writeb(readb(base_addr + regs[j].rtr) | reg_bit,
base_addr + regs[j].rtr);
}
It should reduce to single line statements once you introduce the
relevant readb / writeb helpers.
> + }
> + }
> +
> + /* The hardware requires a delay up to 2*32*125 usec to take commands
> + * into account
> + */
> + udelay((2 * 32) * 125);
#define FALC_HW_CMD_DELAY_US ...
(it appears several times and you will save a comment)
> +
> + /* Unmask HDLC 1 Transmit IT */
> + writeb(readb(base_addr + IMR1) & ~1, base_addr + IMR1);
> + writeb(readb(base_addr + IMR1) & ~(1 << 4), base_addr + IMR1);
> + writeb(readb(base_addr + IMR1) & ~(1 << 5), base_addr + IMR1);
> +
> + /* Unmask HDLC 1 Receive IT */
> + writeb(readb(base_addr + IMR0) & ~1, base_addr + IMR0);
> + writeb(readb(base_addr + IMR0) & ~(1 << 7), base_addr + IMR0);
> + writeb(readb(base_addr + IMR1) & ~(1 << 6), base_addr + IMR1);
> +
> + /* The hardware requires a delay up to 2*32*125 usec to take commands
> + * into account
> + */
Bis repetita.
> + udelay((2 * 32) * 125);
(I assume the device won't ever be behind a write posting bus so there is
no point in flushing write before the udelay)
> +
> + return 0;
> +}
> +
> +
> +/* Init FALC56 */
Useless comment.
> +static int init_FALC(struct pef2256_dev_priv *priv)
Why does it return anything ? It always return 0.
> +{
> + unsigned char *base_addr;
unsigned char __iomem *base_addr = priv->base_addr;
> + int Version;
No caps.
[...]
> + /* channel phase for FALC56 */
> + if ((priv->channel_phase == CHANNEL_PHASE_1)
> + || (priv->channel_phase == CHANNEL_PHASE_3))
|| should stay at the end of the previous line
You don't all-tabs indent: you use the required tabs, then spaces, so
that the code lines up nicely. For instance:
if ((priv->channel_phase == CHANNEL_PHASE_1) ||
(priv->channel_phase == CHANNEL_PHASE_3))
(you can remove the excess parenthesis btw)
[...]
> +static int pef2256_open(struct net_device *netdev)
> +{
> + struct pef2256_dev_priv *priv = dev_to_hdlc(netdev)->priv;
> + unsigned char *base_addr = priv->base_addr;
> + int ret;
> +
> + if (hdlc_open(netdev))
> + return -EAGAIN;
hdlc_open status code should be propagated:
rc = hdlc_open(netdev);
if (rc < 0)
goto out;
> +
> + 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;
Leak.
goto err_hdlc_close;
> + }
> +
> + if (priv->component_id != VERSION_UNDEF) {
> + ret = init_FALC(priv);
Actually init_FALC never fails.
> + } else {
> + dev_err(priv->dev, "Composant ident (%X/%X) = %d\n",
> + readb(base_addr + VSTR), readb(base_addr + WID),
> + priv->component_id);
> + ret = -ENODEV;
Please unbalance and move the priv->component_id == VERSION_UNDEF test
to the start of the function.
> + }
> +
> + if (ret < 0)
> + return ret;
Leak.
> +
> + priv->tx_skb = NULL;
> + priv->rx_len = 0;
> +
> + Config_HDLC(priv);
> +
> + netif_carrier_on(netdev);
Nit: I am a bit surprized that the driver does not seem to detect signal
losses.
> + netif_start_queue(netdev);
> +
> + priv->init_done = 1;
Why don't you rely on the net_device up / down state ?
[...]
> +static int pef2256_rx(struct pef2256_dev_priv *priv)
The error status is never checked.
> +{
> + struct sk_buff *skb;
> + int idx, size;
Please reduce the scope of 'skb' and 'size'.
> + unsigned char *base_addr;
> +
> + base_addr = priv->base_addr;
(see above)
> +
> + /* RDO has been received -> wait for RME */
> + if (priv->rx_len == -1) {
> + /* Acknowledge the FIFO */
> + writeb(readb(base_addr + CMDR) | (1 << 7), base_addr + CMDR);
> +
> + if (priv->R_ISR0 & (1 << 7))
> + priv->rx_len = 0;
> +
> + return 0;
> + }
> +
> + /* RPF : a block is available in the receive FIFO */
> + if (priv->R_ISR0 & 1) {
More #define please.
> + for (idx = 0; idx < 32; idx++)
> + priv->rx_buff[priv->rx_len + idx] =
> + readb(base_addr + RFIFO + (idx & 1));
> +
> + /* Acknowledge the FIFO */
> + writeb(readb(base_addr + CMDR) | (1 << 7), base_addr + CMDR);
> +
> + priv->rx_len += 32;
> + }
> +
> + /* RME : Message end : Read the receive FIFO */
> + if (priv->R_ISR0 & (1 << 7)) {
More #define please.
> + /* Get size of last block */
> + size = readb(base_addr + RBCL) & 0x1F;
> +
> + /* Read last block */
> + for (idx = 0; idx < size; idx++)
> + priv->rx_buff[priv->rx_len + idx] =
> + readb(base_addr + RFIFO + (idx & 1));
> +
> + /* Acknowledge the FIFO */
> + writeb(readb(base_addr + CMDR) | (1 << 7), base_addr + CMDR);
static void pef2256_fifo_ack(...)
> +
> + priv->rx_len += size;
> +
> + /* Packet received */
> + if (priv->rx_len > 0) {
Please add a local priv->netdev->stats variable.
[...]
> +static int pef2256_tx(struct pef2256_dev_priv *priv)
> +{
> + int idx, size;
> + unsigned char *base_addr;
> + u8 *tx_buff = priv->tx_skb->data;
> +
> + base_addr = priv->base_addr;
> +
> + /* ALLS : transmit all done */
> + if (priv->R_ISR1 & (1 << 5)) {
> + priv->netdev->stats.tx_packets++;
> + priv->netdev->stats.tx_bytes += priv->tx_skb->len;
> + /* dev_kfree_skb(priv->tx_skb); */
Please remove.
> + 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) {
} else ...
> + size = priv->tx_skb->len - priv->tx_len;
> + if (size > 32)
> + size = 32;
> +
> + for (idx = 0; idx < size; idx++)
> + writeb(tx_buff[priv->tx_len + idx],
> + base_addr + XFIFO + (idx & 1));
> +
> + priv->tx_len += size;
> +
> + if (priv->tx_len == priv->tx_skb->len)
> + writeb(readb(base_addr + CMDR) | ((1 << 3) | (1 << 1)),
> + base_addr + CMDR);
> + else
> + writeb(readb(base_addr + CMDR) | (1 << 3),
> + base_addr + CMDR);
Please add more #define for the bits and use a single writeb(readb(...
statement with some "u8 mask" variable
> + }
> +
> + return 0;
> +}
> +
> +
> +irqreturn_t pef2256_irq(int irq, void *dev_priv)
static
> +{
> + struct pef2256_dev_priv *priv = (struct pef2256_dev_priv *)dev_priv;
> + unsigned char *base_addr;
> + u8 R_GIS;
No caps.
> +
> + base_addr = priv->base_addr;
> + R_GIS = readb(base_addr + GIS);
> +
> + priv->R_ISR0 = priv->R_ISR1 = 0;
> +
> + /* We only care about ISR0 and ISR1 */
> + /* ISR0 */
> + if (R_GIS & 1)
> + priv->R_ISR0 =
> + readb(base_addr + ISR0) & ~(readb(base_addr + IMR0));
> +
> + /* ISR1 */
> + if (R_GIS & (1 << 1))
> + priv->R_ISR1 =
> + readb(base_addr + ISR1) & ~(readb(base_addr + IMR1));
> +
> + /* Don't do anything else before init is done */
> + if (!priv->init_done)
> + return IRQ_HANDLED;
Gross (and probably SMP unsafe, etc.).
The driver doesn't request an IRQF_SHARED handler. This hack should not be
needed if the driver properly disables the device before registering the
irq handler.
> +
> + /* RDO : Receive data overflow -> RX error */
> + if (priv->R_ISR1 & (1 << 6)) {
> + /* Acknowledge the FIFO */
> + writeb(readb(base_addr + CMDR) | (1 << 7), base_addr + CMDR);
> + priv->netdev->stats.rx_errors++;
> + /* RME received ? */
> + if (priv->R_ISR0 & (1 << 7))
> + priv->rx_len = 0;
> + else
> + priv->rx_len = -1;
> + return IRQ_HANDLED;
> + }
> +
> + /* XDU : Transmit data underrun -> TX error */
> + if (priv->R_ISR1 & (1 << 4)) {
> + priv->netdev->stats.tx_errors++;
> + /* dev_kfree_skb(priv->tx_skb); */
Please remove.
> + priv->tx_skb = NULL;
> + netif_wake_queue(priv->netdev);
> + return IRQ_HANDLED;
> + }
Is it impossible to be notified of both RDO and XDU at the same time ?
[...]
> +/* Loading module */
> +static int pef2256_probe(struct platform_device *pdev)
Useless comment.
> +{
[...]
> + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return ret;
[...]
> + priv->irq = platform_get_irq(pdev, 0);
> + if (!priv->irq) {
> + dev_err(priv->dev, "no irq defined\n");
> + return -EINVAL;
Leak.
[...]
> + priv->init_done = 0;
priv comes from kzalloc. init_done is already 0.
[...]
> 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
[...]
> +struct pef2256_dev_priv {
> + struct sk_buff *tx_skb;
> + u16 tx_len;
> + struct device *dev;
> +
> + int init_done;
> +
> + unsigned char *base_addr;
It should be __iomem annotated.
It may be void *
Nit: I'd welcome a different name - 'ioaddr' or such - as base_addr is
already (ab)used in struct net_device.
--
Ueimor
^ permalink raw reply [flat|nested] 4+ messages in thread
* RE: [PATCH v2] WAN: Adding support for Infineon PEF2256 E1 chipset (FALC56)
2013-11-01 15:01 [PATCH v2] WAN: Adding support for Infineon PEF2256 E1 chipset (FALC56) Christophe Leroy
2013-11-01 15:36 ` Govindarajulu Varadarajan
2013-11-02 22:26 ` Francois Romieu
@ 2013-11-15 15:17 ` thomas.langer
2 siblings, 0 replies; 4+ messages in thread
From: thomas.langer @ 2013-11-15 15:17 UTC (permalink / raw)
To: christophe.leroy
Cc: devicetree, linux-doc, linux-kernel, netdev,
jerome.chantelauze.ext
Hello Christophe,
Christophe Leroy wrote on 2013-11-01:
> The patch adds WAN support for Infineon FALC56 - PEF2256 E1 Chipset.
can you please replace "Infineon" with "Lantiq"?
The former "wire-line" business-unit was transferred into an own company some years ago.
Maybe provide a comment in the description or binding document, to avoid more confusion about this.
>
> Signed-off-by: Jerome Chantelauze <jerome.chantelauze.ext@c-s.fr>
> Acked-by: Christophe Leroy <christophe.leroy@c-s.fr>
>
Thanks,
Thomas
---
There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.
---
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2013-11-15 15:17 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-11-01 15:01 [PATCH v2] WAN: Adding support for Infineon PEF2256 E1 chipset (FALC56) Christophe Leroy
2013-11-01 15:36 ` Govindarajulu Varadarajan
2013-11-02 22:26 ` Francois Romieu
2013-11-15 15:17 ` thomas.langer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).