MN10300: ASB2364: Add support for SMSC911X and SMC911X
authorAkira Takeuchi <takeuchi.akr@jp.panasonic.com>
Wed, 27 Oct 2010 16:28:58 +0000 (17:28 +0100)
committerDavid Howells <dhowells@redhat.com>
Wed, 27 Oct 2010 16:28:58 +0000 (17:28 +0100)
Add support for SMSC911X and SMC911X for the ASB2364 unit.

Signed-off-by: Akira Takeuchi <takeuchi.akr@jp.panasonic.com>
Signed-off-by: Kiyoshi Owada <owada.kiyoshi@jp.panasonic.com>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: steve.glendinning@smsc.com
cc: netdev@vger.kernel.org

arch/mn10300/Kconfig
arch/mn10300/include/asm/smsc911x.h [new file with mode: 0644]
arch/mn10300/unit-asb2364/Makefile
arch/mn10300/unit-asb2364/include/unit/smsc911x.h [new file with mode: 0644]
arch/mn10300/unit-asb2364/smsc911x.c [new file with mode: 0644]
drivers/net/Kconfig
drivers/net/smsc911x.c
drivers/net/smsc911x.h

index 42ca55a..129ca49 100644 (file)
@@ -117,6 +117,7 @@ config MN10300_UNIT_ASB2305
 
 config MN10300_UNIT_ASB2364
        bool "ASB2364"
+       select SMSC911X_ARCH_HOOKS if SMSC911X
 
 endchoice
 
diff --git a/arch/mn10300/include/asm/smsc911x.h b/arch/mn10300/include/asm/smsc911x.h
new file mode 100644 (file)
index 0000000..2fcd108
--- /dev/null
@@ -0,0 +1 @@
+#include <unit/smsc911x.h>
index e9d9b90..b3263ec 100644 (file)
@@ -8,3 +8,5 @@
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
 obj-y   := unit-init.o leds.o irq-fpga.o
+
+obj-$(CONFIG_SMSC911X) += smsc911x.o
diff --git a/arch/mn10300/unit-asb2364/include/unit/smsc911x.h b/arch/mn10300/unit-asb2364/include/unit/smsc911x.h
new file mode 100644 (file)
index 0000000..4c1ede5
--- /dev/null
@@ -0,0 +1,171 @@
+/* Support for the SMSC911x NIC
+ *
+ * Copyright (C) 2006 Matsushita Electric Industrial Co., Ltd.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _ASM_UNIT_SMSC911X_H
+#define _ASM_UNIT_SMSC911X_H
+
+#include <linux/netdevice.h>
+#include <proc/irq.h>
+#include <unit/fpga-regs.h>
+
+#define MN10300_USE_EXT_EEPROM
+
+
+#define SMSC911X_BASE          0xA8000000UL
+#define SMSC911X_BASE_END      0xA8000100UL
+#define SMSC911X_IRQ           FPGA_LAN_IRQ
+
+/*
+ * Allow the FPGA to be initialised by the SMSC911x driver
+ */
+#undef SMSC_INITIALIZE
+#define SMSC_INITIALIZE()                                      \
+do {                                                           \
+       /* release reset */                                     \
+       ASB2364_FPGA_REG_RESET_LAN = 0x0001;                    \
+       SyncExBus();                                            \
+} while (0)
+
+#ifdef MN10300_USE_EXT_EEPROM
+#include <linux/delay.h>
+#include <unit/clock.h>
+
+#define EEPROM_ADDRESS 0xA0
+#define MAC_OFFSET     0x0008
+#define USE_IIC_CH     0       /* 0 or 1 */
+#define IIC_OFFSET     (0x80000 * USE_IIC_CH)
+#define IIC_DTRM       __SYSREG(0xd8400000 + IIC_OFFSET, u32)
+#define IIC_DREC       __SYSREG(0xd8400004 + IIC_OFFSET, u32)
+#define IIC_MYADD      __SYSREG(0xd8400008 + IIC_OFFSET, u32)
+#define IIC_CLK                __SYSREG(0xd840000c + IIC_OFFSET, u32)
+#define IIC_BRST       __SYSREG(0xd8400010 + IIC_OFFSET, u32)
+#define IIC_HOLD       __SYSREG(0xd8400014 + IIC_OFFSET, u32)
+#define IIC_BSTS       __SYSREG(0xd8400018 + IIC_OFFSET, u32)
+#define IIC_ICR                __SYSREG(0xd4000080 + 4 * USE_IIC_CH, u16)
+
+#define IIC_CLK_PLS    ((unsigned short)(MN10300_IOCLK / 100000 - 1))
+#define IIC_CLK_LOW    ((unsigned short)(IIC_CLK_PLS / 2))
+
+#define SYS_IIC_DTRM_Bit_STA   ((unsigned short)0x0400)
+#define SYS_IIC_DTRM_Bit_STO   ((unsigned short)0x0200)
+#define SYS_IIC_DTRM_Bit_ACK   ((unsigned short)0x0100)
+#define SYS_IIC_DTRM_Bit_DATA  ((unsigned short)0x00FF)
+
+static inline void POLL_INT_REQ(volatile u16 *icr)
+{
+       unsigned long flags;
+       u16 tmp;
+
+       while (!(*icr & GxICR_REQUEST))
+               ;
+       flags = arch_local_cli_save();
+       tmp = *icr;
+       *icr = (tmp & GxICR_LEVEL) | GxICR_DETECT;
+       tmp = *icr;
+       arch_local_irq_restore(flags);
+}
+
+/*
+ * Implement the SMSC911x hook for MAC address retrieval
+ */
+#undef smsc_get_mac
+static inline int smsc_get_mac(struct net_device *dev)
+{
+       unsigned char *mac_buf = dev->dev_addr;
+       int i;
+       unsigned short value;
+       unsigned int data;
+       int mac_length = 6;
+       int check;
+       u16 orig_gicr, tmp;
+       unsigned long flags;
+
+       /* save original GnICR and clear GnICR.IE */
+       flags = arch_local_cli_save();
+       orig_gicr = IIC_ICR;
+       IIC_ICR = orig_gicr & GxICR_LEVEL;
+       tmp = IIC_ICR;
+       arch_local_irq_restore(flags);
+
+       IIC_MYADD = 0x00000008;
+       IIC_CLK = (IIC_CLK_LOW << 16) + (IIC_CLK_PLS);
+       /* bus hung recovery */
+
+       while (1) {
+               check = 0;
+               for (i = 0; i < 3; i++) {
+                       if ((IIC_BSTS & 0x00000003) == 0x00000003)
+                               check++;
+                       udelay(3);
+               }
+
+               if (check == 3) {
+                       IIC_BRST = 0x00000003;
+                       break;
+               } else {
+                       for (i = 0; i < 3; i++) {
+                               IIC_BRST = 0x00000002;
+                               udelay(8);
+                               IIC_BRST = 0x00000003;
+                               udelay(8);
+                       }
+               }
+       }
+
+       IIC_BRST = 0x00000002;
+       IIC_BRST = 0x00000003;
+
+       value   =  SYS_IIC_DTRM_Bit_STA | SYS_IIC_DTRM_Bit_ACK;
+       value   |= (((unsigned short)EEPROM_ADDRESS & SYS_IIC_DTRM_Bit_DATA) |
+                   (unsigned short)0x0000);
+       IIC_DTRM = value;
+       POLL_INT_REQ(&IIC_ICR);
+
+       /** send offset of MAC address in EEPROM **/
+       IIC_DTRM = (unsigned char)((MAC_OFFSET & 0xFF00) >> 8);
+       POLL_INT_REQ(&IIC_ICR);
+
+       IIC_DTRM = (unsigned char)(MAC_OFFSET & 0x00FF);
+       POLL_INT_REQ(&IIC_ICR);
+
+       udelay(1000);
+
+       value   =  SYS_IIC_DTRM_Bit_STA;
+       value   |= (((unsigned short)EEPROM_ADDRESS & SYS_IIC_DTRM_Bit_DATA) |
+                   (unsigned short)0x0001);
+       IIC_DTRM = value;
+       POLL_INT_REQ(&IIC_ICR);
+
+       IIC_DTRM = 0x00000000;
+       while (mac_length > 0) {
+               POLL_INT_REQ(&IIC_ICR);
+
+               data = IIC_DREC;
+               mac_length--;
+               if (mac_length == 0)
+                       value = 0x00000300;     /* stop IIC bus */
+               else if (mac_length == 1)
+                       value = 0x00000100;     /* no ack */
+               else
+                       value = 0x00000000;     /* ack */
+               IIC_DTRM = value;
+               *mac_buf++ = (unsigned char)(data & 0xff);
+       }
+
+       /* restore GnICR.LV and GnICR.IE */
+       flags = arch_local_cli_save();
+       IIC_ICR = (orig_gicr & (GxICR_LEVEL | GxICR_ENABLE));
+       tmp = IIC_ICR;
+       arch_local_irq_restore(flags);
+
+       return 0;
+}
+#endif /* MN10300_USE_EXT_EEPROM */
+#endif /* _ASM_UNIT_SMSC911X_H */
diff --git a/arch/mn10300/unit-asb2364/smsc911x.c b/arch/mn10300/unit-asb2364/smsc911x.c
new file mode 100644 (file)
index 0000000..544a73e
--- /dev/null
@@ -0,0 +1,58 @@
+/* Specification for the SMSC911x NIC
+ *
+ * Copyright (C) 2006 Matsushita Electric Industrial Co., Ltd.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/smsc911x.h>
+#include <unit/smsc911x.h>
+
+static struct smsc911x_platform_config smsc911x_config = {
+       .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+       .irq_type       = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+       .flags          = SMSC911X_USE_32BIT,
+};
+
+static struct resource smsc911x_resources[] = {
+       [0] = {
+               .start  = SMSC911X_BASE,
+               .end    = SMSC911X_BASE_END,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = SMSC911X_IRQ,
+               .end    = SMSC911X_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device smsc911x_device = {
+       .name           = "smsc911x",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(smsc911x_resources),
+       .resource       = smsc911x_resources,
+       .dev            = {
+               .platform_data = &smsc911x_config,
+       }
+};
+
+/*
+ * add platform devices
+ */
+static int __init unit_device_init(void)
+{
+       platform_device_register(&smsc911x_device);
+       return 0;
+}
+
+device_initcall(unit_device_init);
index 86fe67f..9334539 100644 (file)
@@ -1041,7 +1041,7 @@ config SMC911X
        tristate "SMSC LAN911[5678] support"
        select CRC32
        select MII
-       depends on ARM || SUPERH
+       depends on ARM || SUPERH || MN10300
        help
          This is a driver for SMSC's LAN911x series of Ethernet chipsets
          including the new LAN9115, LAN9116, LAN9117, and LAN9118.
@@ -1055,7 +1055,7 @@ config SMC911X
 
 config SMSC911X
        tristate "SMSC LAN911x/LAN921x families embedded ethernet support"
-       depends on ARM || SUPERH || BLACKFIN || MIPS
+       depends on ARM || SUPERH || BLACKFIN || MIPS || MN10300
        select CRC32
        select MII
        select PHYLIB
@@ -1067,6 +1067,14 @@ config SMSC911X
          <file:Documentation/networking/net-modules.txt>. The module
          will be called smsc911x.
 
+config SMSC911X_ARCH_HOOKS
+       def_bool n
+       depends on SMSC911X
+       help
+         If the arch enables this, it allows the arch to implement various
+         hooks for more comprehensive interrupt control and also to override
+         the source of the MAC address.
+
 config NET_VENDOR_RACAL
        bool "Racal-Interlan (Micom) NI cards"
        depends on ISA
index a8e5856..64bfdae 100644 (file)
@@ -2075,7 +2075,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
        } else {
                /* Try reading mac address from device. if EEPROM is present
                 * it will already have been set */
-               smsc911x_read_mac_address(dev);
+               smsc_get_mac(dev);
 
                if (is_valid_ether_addr(dev->dev_addr)) {
                        /* eeprom values are valid  so use them */
@@ -2176,6 +2176,7 @@ static struct platform_driver smsc911x_driver = {
 /* Entry point for loading the module */
 static int __init smsc911x_init_module(void)
 {
+       SMSC_INITIALIZE();
        return platform_driver_register(&smsc911x_driver);
 }
 
index 016360c..52f38e1 100644 (file)
 #define LPA_PAUSE_ALL                  (LPA_PAUSE_CAP | \
                                         LPA_PAUSE_ASYM)
 
+/*
+ * Provide hooks to let the arch add to the initialisation procedure
+ * and to override the source of the MAC address.
+ */
+#define SMSC_INITIALIZE()              do {} while (0)
+#define smsc_get_mac(dev)              smsc911x_read_mac_address((dev))
+
+#ifdef CONFIG_SMSC911X_ARCH_HOOKS
+#include <asm/smsc911x.h>
+#endif
+
 #endif                         /* __SMSC911X_H__ */