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
This commit is contained in:
Akira Takeuchi 2010-10-27 17:28:58 +01:00 committed by David Howells
parent 6044cf1d94
commit 62747cd27e
8 changed files with 256 additions and 3 deletions

View File

@ -117,6 +117,7 @@ config MN10300_UNIT_ASB2305
config MN10300_UNIT_ASB2364
bool "ASB2364"
select SMSC911X_ARCH_HOOKS if SMSC911X
endchoice

View File

@ -0,0 +1 @@
#include <unit/smsc911x.h>

View 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

View File

@ -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 */

View File

@ -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);

View 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

View 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);
}

View File

@ -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__ */