summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkira Takeuchi <takeuchi.akr@jp.panasonic.com>2010-10-27 17:28:58 +0100
committerDavid Howells <dhowells@redhat.com>2010-10-27 17:28:58 +0100
commit62747cd27ee241ffa32d501e45980cdc441d4a09 (patch)
tree6ad1e1d530c5761dc39e1fb21fca56a2751c63e7
parent6044cf1d9426dfd5cdc1e7b9cf8eaed6418e1ff6 (diff)
downloadlinux-next-62747cd27ee241ffa32d501e45980cdc441d4a09.tar.gz
MN10300: ASB2364: Add support for SMSC911X and SMC911X
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
-rw-r--r--arch/mn10300/Kconfig1
-rw-r--r--arch/mn10300/include/asm/smsc911x.h1
-rw-r--r--arch/mn10300/unit-asb2364/Makefile2
-rw-r--r--arch/mn10300/unit-asb2364/include/unit/smsc911x.h171
-rw-r--r--arch/mn10300/unit-asb2364/smsc911x.c58
-rw-r--r--drivers/net/Kconfig12
-rw-r--r--drivers/net/smsc911x.c3
-rw-r--r--drivers/net/smsc911x.h11
8 files changed, 256 insertions, 3 deletions
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig
index 42ca55a47377..129ca492e917 100644
--- a/arch/mn10300/Kconfig
+++ b/arch/mn10300/Kconfig
@@ -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
index 000000000000..2fcd1080322b
--- /dev/null
+++ b/arch/mn10300/include/asm/smsc911x.h
@@ -0,0 +1 @@
+#include <unit/smsc911x.h>
diff --git a/arch/mn10300/unit-asb2364/Makefile b/arch/mn10300/unit-asb2364/Makefile
index e9d9b90ef6da..b3263ecfc4ff 100644
--- a/arch/mn10300/unit-asb2364/Makefile
+++ b/arch/mn10300/unit-asb2364/Makefile
@@ -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
index 000000000000..4c1ede535fa9
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/include/unit/smsc911x.h
@@ -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
index 000000000000..544a73e94c81
--- /dev/null
+++ b/arch/mn10300/unit-asb2364/smsc911x.c
@@ -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);
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 86fe67fd49ba..9334539ebf75 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -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
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
index a8e5856ce882..64bfdae5956f 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/smsc911x.c
@@ -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);
}
diff --git a/drivers/net/smsc911x.h b/drivers/net/smsc911x.h
index 016360c65ce2..52f38e12a879 100644
--- a/drivers/net/smsc911x.h
+++ b/drivers/net/smsc911x.h
@@ -394,4 +394,15 @@
#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__ */