LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH/2.6.17-rc4 7/10]  Powerpc: workaround for tsi108 pci confi g read exception
From: Zang Roy-r61911 @ 2006-05-17 10:14 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list, Alexandre.Bounine, Yang Xin-Xin-r48390

Workaround for Tundra Semiconductor tsi108 host bridge pci config read
exception

Signed-off-by: Alexandre Bounine <alexandreb@tundra.com>
Signed-off-by: Roy Zang	<tie-fei.zang@freescale.com>

---

 arch/powerpc/kernel/traps.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

0575fbe21e4f1045528bb91ec4b34bb7955c4a92
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 064a525..7468d76 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -262,6 +262,19 @@ #if defined(CONFIG_PPC_PMAC) && defined(
 		}
 	}
 #endif /* CONFIG_PPC_PMAC && CONFIG_PPC32 */
+
+#ifdef CONFIG_TSI108_BRIDGE
+	extern void tsi108_clear_pci_cfg_error(void);
+	const struct exception_table_entry *entry;
+
+	/* Are we prepared to handle this fault?  */
+	if ((entry = search_exception_tables(regs->nip)) != NULL) {
+		tsi108_clear_pci_cfg_error();
+		regs->msr |= MSR_RI;
+		regs->nip = entry->fixup;
+		return 1;
+	}
+#endif /* CONFIG_TSI108_BRIDGE */
 	return 0;
 }
 
-- 
1.3.0

^ permalink raw reply related

* [PATCH/2.6.17-rc4 6/10]  Add  Tundra pci vendor and device ID
From: Zang Roy-r61911 @ 2006-05-17 10:14 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list, Alexandre.Bounine, Yang Xin-Xin-r48390

Add Tundra Semiconductor pci host bridge vendor ID and device ID

Signed-off-by: Alexandre Bounine <alexandreb@tundra.com>
Signed-off-by: Roy Zang	<tie-fei.zang@freescale.com>

---

 include/linux/pci_ids.h |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

14bddf6670ca982d5cee57afa472d2199e2170fc
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index d6fe048..c39fcfc 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2276,3 +2276,7 @@ #define PCI_DEVICE_ID_RME_DIGI32	0x9896
 #define PCI_DEVICE_ID_RME_DIGI32_PRO	0x9897
 #define PCI_DEVICE_ID_RME_DIGI32_8	0x9898
 
+#define PCI_VENDOR_ID_TUNDRA		0x10e3
+#define PCI_DEVICE_ID_TUNDRA_CA91C042	0x0000
+#define PCI_DEVICE_ID_TUNDRA_TSI108	0x0108
+#define PCI_DEVICE_ID_TUNDRA_TSI109	0xA108
-- 
1.3.0

^ permalink raw reply related

* [PATCH/2.6.17-rc4 8/10]  Add  tsi108 8250 serial support
From: Zang Roy-r61911 @ 2006-05-17 10:14 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list, Alexandre.Bounine, Yang Xin-Xin-r48390

This patch contains changes to the serial device driver specific for integrated
serial port in Tsi108 Host Bridge.

Signed-off-by: Alexandre Bounine <alexandreb@tundra.com>
Signed-off-by: Roy Zang	<tie-fei.zang@freescale.com>

>From nobody Mon Sep 17 00:00:00 2001
From: roy zang <tie-fei.zang@freescale.com>
Date: Tue May 16 15:26:02 2006 +0800
Subject: [PATCH] Add tsi108 serial support

---

 drivers/serial/8250.c |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)

6cb950357e9970afa671d59f172dbc4b03f11560
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index bbf78aa..c12f516 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -723,7 +723,9 @@ static int broken_efr(struct uart_8250_p
 static void autoconfig_16550a(struct uart_8250_port *up)
 {
 	unsigned char status1, status2;
+#ifndef CONFIG_TSI108_BRIDGE
 	unsigned int iersave;
+#endif
 
 	up->port.type = PORT_16550A;
 	up->capabilities |= UART_CAP_FIFO;
@@ -833,6 +835,7 @@ static void autoconfig_16550a(struct uar
 	 * trying to write and read a 1 just to make sure it's not
 	 * already a 1 and maybe locked there before we even start start.
 	 */
+#ifndef CONFIG_TSI108_BRIDGE
 	iersave = serial_in(up, UART_IER);
 	serial_outp(up, UART_IER, iersave & ~UART_IER_UUE);
 	if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
@@ -859,6 +862,7 @@ static void autoconfig_16550a(struct uar
 		DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
 	}
 	serial_outp(up, UART_IER, iersave);
+#endif
 }
 
 /*
@@ -1348,7 +1352,12 @@ static irqreturn_t serial8250_interrupt(
 
 		up = list_entry(l, struct uart_8250_port, list);
 
+#ifdef CONFIG_TSI108_BRIDGE /* for TSI108_REV_Z1 errata U2 */
+		/* read IIR as part of 32-bit word */
+		iir = (in_be32((u32 *)(up->port.membase + UART_RX)) >> 8) & 0xff;
+#else
 		iir = serial_in(up, UART_IIR);
+#endif
 		if (!(iir & UART_IIR_NO_INT)) {
 			serial8250_handle_port(up, regs);
 
@@ -1529,7 +1538,9 @@ static int serial8250_startup(struct uar
 {
 	struct uart_8250_port *up = (struct uart_8250_port *)port;
 	unsigned long flags;
+#ifndef CONFIG_TSI108_BRIDGE
 	unsigned char lsr, iir;
+#endif
 	int retval;
 
 	up->capabilities = uart_config[up->port.type].flags;
@@ -1567,7 +1578,9 @@ #endif
 	 */
 	(void) serial_inp(up, UART_LSR);
 	(void) serial_inp(up, UART_RX);
+#ifndef CONFIG_TSI108_BRIDGE /* for TSI108_REV_Z1 errata U2 */
 	(void) serial_inp(up, UART_IIR);
+#endif
 	(void) serial_inp(up, UART_MSR);
 
 	/*
@@ -1634,6 +1647,7 @@ #endif
 
 	serial8250_set_mctrl(&up->port, up->port.mctrl);
 
+#ifndef CONFIG_TSI108_BRIDGE
 	/*
 	 * Do a quick test to see if we receive an
 	 * interrupt when we enable the TX irq.
@@ -1652,6 +1666,7 @@ #endif
 	} else {
 		up->bugs &= ~UART_BUG_TXEN;
 	}
+#endif
 
 	spin_unlock_irqrestore(&up->port.lock, flags);
 
@@ -1678,7 +1693,9 @@ #endif
 	 */
 	(void) serial_inp(up, UART_LSR);
 	(void) serial_inp(up, UART_RX);
+#ifndef CONFIG_TSI108_BRIDGE /* for TSI108_REV_Z1 errata U2 */
 	(void) serial_inp(up, UART_IIR);
+#endif
 	(void) serial_inp(up, UART_MSR);
 
 	return 0;
-- 
1.3.0

^ permalink raw reply related

* [PATCH/2.6.17-rc4 10/10]  bugs fix for marvell SATA on powerpc pl atform
From: Zang Roy-r61911 @ 2006-05-17 10:14 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list, Alexandre.Bounine, Yang Xin-Xin-r48390

Fix Marvell SATA driver bugs on PowerPC platform: 
SATA device can't work for the problem on little-endian mode.
U-Boot can't find SATA device after kernel reboots.

Signed-off-by: Hongjun cheng	<hong-jun.chen@reescale.com>
Signed-off-by: Roy Zang		<tie-fei.zang@freescale.com>

>From nobody Mon Sep 17 00:00:00 2001
From: roy zang <tie-fei.zang@freescale.com>
Date: Tue May 16 15:25:23 2006 +0800
Subject: [PATCH] Fix bugs on powerpc platform for mv sata driver

---

 drivers/scsi/sata_mv.c |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

d82ac19d259f8487a31105eaf844a93cbd9008e8
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index d5fdcb9..4166422 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -1032,6 +1032,9 @@ static inline void mv_crqb_pack_cmd(u16 
 {
 	*cmdw = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
 		(last ? CRQB_CMD_LAST : 0);
+#ifdef CONFIG_PPC
+	*cmdw = cpu_to_le16(*cmdw);
+#endif
 }
 
 /**
@@ -1567,13 +1570,18 @@ static void mv5_read_preamp(struct mv_ho
 static void mv5_enable_leds(struct mv_host_priv *hpriv, void __iomem *mmio)
 {
 	u32 tmp;
-
+#ifndef CONFIG_PPC
 	writel(0, mmio + MV_GPIO_PORT_CTL);
+#endif
 
 	/* FIXME: handle MV_HP_ERRATA_50XXB2 errata */
 
 	tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
+#ifdef CONFIG_PPC
+	tmp &= ~(1 << 0);
+#else	
 	tmp |= ~(1 << 0);
+#endif
 	writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
 }
 
-- 
1.3.0

^ permalink raw reply related

* [PATCH/2.6.17-rc4 9/10] Powerpc: mpc7448hpc2 (taiga) board config file
From: Zang Roy-r61911 @ 2006-05-17 10:14 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list, Alexandre.Bounine, Yang Xin-Xin-r48390

mpc7448 hpc2 (taiga) board config file

Signed-off-by: Roy Zang	<tie-fei.zang@freescale.com>

---

 arch/powerpc/configs/mpc7448_hpc2_defconfig |  897 +++++++++++++++++++++++++++
 1 files changed, 897 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/configs/mpc7448_hpc2_defconfig

077c8fa32614ef54c05ad815f55498f117c8e166
diff --git a/arch/powerpc/configs/mpc7448_hpc2_defconfig b/arch/powerpc/configs/mpc7448_hpc2_defconfig
new file mode 100644
index 0000000..ea4b69d
--- /dev/null
+++ b/arch/powerpc/configs/mpc7448_hpc2_defconfig
@@ -0,0 +1,897 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc3
+# Fri May 12 10:51:01 2006
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+CONFIG_DEFAULT_UIMAGE=y
+
+#
+# Processor support
+#
+CONFIG_CLASSIC32=y
+# CONFIG_PPC_52xx is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_85xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+CONFIG_6xx=y
+CONFIG_PPC_FPU=y
+# CONFIG_ALTIVEC is not set
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+# CONFIG_SMP is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Platform support
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_PPC_ISERIES is not set
+# CONFIG_EMBEDDED6xx is not set
+# CONFIG_APUS is not set
+CONFIG_MPC7448HPC2=y
+CONFIG_74xx=y
+CONFIG_TSI108_BRIDGE=y
+# CONFIG_PPC_RTAS is not set
+# CONFIG_MMIO_NVRAM is not set
+# CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
+# CONFIG_CPU_FREQ is not set
+# CONFIG_TAU is not set
+# CONFIG_WANT_EARLY_SERIAL is not set
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+# CONFIG_SOFTWARE_SUSPEND is not set
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_PPC_I8259 is not set
+# CONFIG_PPC_INDIRECT_PCI is not set
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+CONFIG_SCSI_SATA=y
+# CONFIG_SCSI_SATA_AHCI is not set
+# CONFIG_SCSI_SATA_SVW is not set
+# CONFIG_SCSI_ATA_PIIX is not set
+CONFIG_SCSI_SATA_MV=y
+# CONFIG_SCSI_SATA_NV is not set
+# CONFIG_SCSI_PDC_ADMA is not set
+# CONFIG_SCSI_SATA_QSTOR is not set
+# CONFIG_SCSI_SATA_PROMISE is not set
+# CONFIG_SCSI_SATA_SX4 is not set
+# CONFIG_SCSI_SATA_SIL is not set
+# CONFIG_SCSI_SATA_SIL24 is not set
+# CONFIG_SCSI_SATA_SIS is not set
+# CONFIG_SCSI_SATA_ULI is not set
+# CONFIG_SCSI_SATA_VIA is not set
+# CONFIG_SCSI_SATA_VITESSE is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_TSI108_ETH=y
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
+# CONFIG_PPC_EARLY_DEBUG_G5 is not set
+# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
+# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
+# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
-- 
1.3.0

^ permalink raw reply related

* Re: [RFC PATCH 01/09] robust VM per_cpu core
From: Andi Kleen @ 2006-05-17  9:17 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Andrew Morton, linux-mips, David Mosberger-Tang, linux-ia64,
	Martin Mares, spyro, Joe Taylor, linuxppc-dev, Paul Mackerras,
	benedict.gaster, sam, bjornw, kenneth.w.chen, Ingo Molnar, kiran,
	clameter, Nick Piggin, grundler, arnd, Rusty Russell, starvik,
	Linus Torvalds, Thomas Gleixner, rth, Chris Zankel, tony.luck,
	LKML, ralf, Marc Gauthier, lethal, schwidefsky, linux390, davem,
	parisc-linux
In-Reply-To: <Pine.LNX.4.58.0605170555190.8408@gandalf.stny.rr.com>


> As well as the following three functions:
>
> pud_t *pud_boot_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long addr,
>                      int cpu);
> pmd_t *pmd_boot_alloc(struct mm_struct *mm, pud_t *pud, unsigned long addr,
>                      int cpu);
> pte_t *pte_boot_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long addr,
>                      int cpu);

I'm not sure you can just put them like this into generic code. Some 
architectures are doing strange things with them.

And we already have boot_ioremap on some architectures. Why is that not 
enough? 

-Andi

^ permalink raw reply

* Re: [RFC PATCH 01/09] robust VM per_cpu core
From: Steven Rostedt @ 2006-05-17 10:46 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Andrew Morton, linux-mips, linux-ia64, Martin Mares, spyro,
	Joe Taylor, linuxppc-dev, Paul Mackerras, sam, bjornw,
	kenneth.w.chen, Ingo Molnar, kiran, clameter, Nick Piggin,
	grundler, arnd, Rusty Russell, starvik, Linus Torvalds,
	Thomas Gleixner, rth, Chris Zankel, tony.luck, LKML, ralf,
	Marc Gauthier, lethal, schwidefsky, linux390, davem, parisc-linux
In-Reply-To: <200605171117.06060.ak@suse.de>


On Wed, 17 May 2006, Andi Kleen wrote:

>
> > As well as the following three functions:
> >
> > pud_t *pud_boot_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long addr,
> >                      int cpu);
> > pmd_t *pmd_boot_alloc(struct mm_struct *mm, pud_t *pud, unsigned long addr,
> >                      int cpu);
> > pte_t *pte_boot_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long addr,
> >                      int cpu);
>
> I'm not sure you can just put them like this into generic code. Some
> architectures are doing strange things with them.

Hmm, like what?

>
> And we already have boot_ioremap on some architectures. Why is that not
> enough?

I thought about using boot_ioremap, but it seems to be an abuse.  Since
I'm not mapping io, but actual memory pages.  So the solution to that
seemed more of a hack.  I then would need to worry about grabbing pages
that were node specific and getting the physical addresses.  It just
looked like a cleaner solution to have an API that was for exactly what it
was meant for.

-- Steve

^ permalink raw reply

* Re: [RFC PATCH 01/09] robust VM per_cpu core
From: Andi Kleen @ 2006-05-17 11:08 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Andrew Morton, linux-mips, linux-ia64, Martin Mares, spyro,
	Joe Taylor, linuxppc-dev, Paul Mackerras, sam, bjornw,
	kenneth.w.chen, Ingo Molnar, kiran, clameter, Nick Piggin,
	grundler, arnd, Rusty Russell, starvik, Linus Torvalds,
	Thomas Gleixner, rth, Chris Zankel, tony.luck, LKML, ralf,
	Marc Gauthier, lethal, schwidefsky, linux390, davem, parisc-linux
In-Reply-To: <Pine.LNX.4.58.0605170640280.8408@gandalf.stny.rr.com>

On Wednesday 17 May 2006 12:46, Steven Rostedt wrote:
> 
> On Wed, 17 May 2006, Andi Kleen wrote:
> 
> >
> > > As well as the following three functions:
> > >
> > > pud_t *pud_boot_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long addr,
> > >                      int cpu);
> > > pmd_t *pmd_boot_alloc(struct mm_struct *mm, pud_t *pud, unsigned long addr,
> > >                      int cpu);
> > > pte_t *pte_boot_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long addr,
> > >                      int cpu);
> >
> > I'm not sure you can just put them like this into generic code. Some
> > architectures are doing strange things with them.
> 
> Hmm, like what?

Mostly managing their software TLBs I think.
 
> >
> > And we already have boot_ioremap on some architectures. Why is that not
> > enough?
> 
> I thought about using boot_ioremap, but it seems to be an abuse.  Since
> I'm not mapping io, but actual memory pages. 

We already use it for memory, e.g. for mapping some BIOS tables.

> So the solution to that 
> seemed more of a hack.  I then would need to worry about grabbing pages
> that were node specific 

alloc_bootmem_node

> and getting the physical addresses.  

virt_to_phys() 

[ + hacks to handle 32bit NUMA unfortunately ]

-Andi

^ permalink raw reply

* Re: Unable to boot a kernel on a MPC8560
From: CORVELLER Mickael @ 2006-05-17 11:13 UTC (permalink / raw)
  To: wd; +Cc: linuxppc-embedded
In-Reply-To: <20060516202600.9181D35363E@atlas.denx.de>

> >
> > first of all, I am a newbie in embedded linux systems.
>
>Seems you are also a newbie when it comes to posting to mailing lists
>in general. Posting  the  same  question  several  times  to  several
>mailing    lists    is    not    a    good    idea.    Please    read
>http://www.catb.org/%7eesr/faqs/smart-questions.html

Indeed, I'm not used to write in mailing lists.

>
>
> > The boot loader is U-Boot.
>...
> > Here is the result of one of my tests :
> > -> niot 0
>...
> > -> nbo 0
>
>These are definitely no U-Boot commands.
>

OK, now I know that my boot loader is not U-Boot, now the question is :
what is the boot loader used by my board ?
I have supposed (certainly wrongly) that the firmware provides on the card 
was based on U-Boot...mea-culpa.

According to you, is it the boot loader the cause of my problem ?

>Best regards,
>
>Wolfgang Denk
>
>--
>Software Engineering:  Embedded and Realtime Systems,  Embedded Linux
>Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
>He's dead, Jim
>	-- McCoy, "The Devil in the Dark", stardate 3196.1

^ permalink raw reply

* Re: [RFC PATCH 01/09] robust VM per_cpu core
From: Steven Rostedt @ 2006-05-17 11:31 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Andrew Morton, linux-mips, linux-ia64, Martin Mares, spyro,
	Joe Taylor, linuxppc-dev, Paul Mackerras, sam, bjornw,
	kenneth.w.chen, Ingo Molnar, kiran, clameter, Nick Piggin,
	grundler, arnd, Rusty Russell, starvik, Linus Torvalds,
	Thomas Gleixner, rth, Chris Zankel, tony.luck, LKML, ralf,
	Marc Gauthier, lethal, schwidefsky, linux390, davem, parisc-linux
In-Reply-To: <200605171308.56203.ak@suse.de>


On Wed, 17 May 2006, Andi Kleen wrote:

> On Wednesday 17 May 2006 12:46, Steven Rostedt wrote:
> >
> > On Wed, 17 May 2006, Andi Kleen wrote:
> >
> > >
> > > > As well as the following three functions:
> > > >
> > > > pud_t *pud_boot_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long addr,
> > > >                      int cpu);
> > > > pmd_t *pmd_boot_alloc(struct mm_struct *mm, pud_t *pud, unsigned long addr,
> > > >                      int cpu);
> > > > pte_t *pte_boot_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long addr,
> > > >                      int cpu);
> > >
> > > I'm not sure you can just put them like this into generic code. Some
> > > architectures are doing strange things with them.
> >
> > Hmm, like what?
>
> Mostly managing their software TLBs I think.

Wait. "into generic code"?  Do you mean that we can't use them in generic
code.  The are not defined there, but are defined in the arch. They are
just used like the p*_alloc (without boot) equivalents (from vmalloc.c).

>
> > >
> > > And we already have boot_ioremap on some architectures. Why is that not
> > > enough?
> >
> > I thought about using boot_ioremap, but it seems to be an abuse.  Since
> > I'm not mapping io, but actual memory pages.
>
> We already use it for memory, e.g. for mapping some BIOS tables.
>
> > So the solution to that
> > seemed more of a hack.  I then would need to worry about grabbing pages
> > that were node specific
>
> alloc_bootmem_node
>
> > and getting the physical addresses.
>
> virt_to_phys()
>
> [ + hacks to handle 32bit NUMA unfortunately ]

With the archs defining their own p*_boot_alloc functions, there shouldn't
be any hacks.  The arch can figure out what to do. I didn't want any hacks
in the generic code.

-- Steve

^ permalink raw reply

* Re: "Need help to configure DNS on the Embedded system"
From: Markus Klotzbücher @ 2006-05-17 11:28 UTC (permalink / raw)
  To: Eberhard Stoll; +Cc: linuxppc-embedded
In-Reply-To: <4469D55E.50105@berghof.com>


Eberhard Stoll <eberhard.stoll@berghof.com> writes:

> Which C library do you use?
> Did you setup /etc/hosts.conf correctly?
                         ^

I guess you meant to write: "/etc/host.conf", right?

Regards

Markus Klotzbücher

^ permalink raw reply

* snd-aoa status update / automatic driver loading
From: Johannes Berg @ 2006-05-17 10:09 UTC (permalink / raw)
  To: debian-powerpc; +Cc: linuxppc-dev list

[-- Attachment #1: Type: text/plain, Size: 2227 bytes --]

Hey,

Currently snd-aoa is known to work on the following machines:
* PowerBook5,8
* PowerBook5,7
* PowerMac8,1
* PowerMac8,2
* 17" October 2005 PowerBook (don't know the number)
* PowerMac11,2
* PowerBook6,8
and my
* PowerBook5,6

People with those machines are encouraged to use and stress-test it, it
also provides much better hardware support than snd-powermac, for
example it can actually reprogram the hardware if you have a 48KHz file
instead of having to digitally downsample it to 44.1KHz like required
with snd-powermac in most cases.

Note that the big missing feature is headphone/line-in/line-out
autodetection at the moment, so if you rely on that don't use snd-aoa
for the moment.

There are apparently some cases where it loses interrupts and then the
sound is garbled, my brother's investigating that at the moment, it
doesn't happen with my powerbook nor with my powermac.

Note that Topaz chips (optical input usually, though I think there's a
version where it does optical output too, probably the tas/topaz
combinations I heard about) are not supported yet as I don't have any
optical hardware except for my PowerMac11,2 and haven't written any code
for the required clock recovering and switching. If you want to see it
supported (and don't want to write the code yourself) your best bet is
probably to send me some hardware that has a controllable optical
output ;) If you want to write the code yourself talk to me first
please.

But the other reason for writing this mail is that I finally found the
last remaining bug that prevented sound module autoloading! :)

Now, when you boot, mac-io is already built-in so provides the i2s
device, which my i2sbus module binds to. Since udev synthesizes events,
i2sbus gets loaded automatically. Now, i2sbus creates uevents on its
own, with the layout number given as the MODALIAS. Hence, the layout
fabric module is loaded because it has an alias for all the layouts it
handles, and it in turn requests all the codec modules that it requires.
Also, this means that 'modprobe i2sbus' will suffice to get the driver
up and running without a reboot, provided that all modules are
installed.

Have fun,
johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* PowerMac7,3 sound (was: PowerBook5,4 -- no sound?)
From: Johannes Berg @ 2006-05-17 10:34 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1145307118.3912.11.camel@localhost.localdomain>

[-- Attachment #1: Type: text/plain, Size: 1961 bytes --]


> > request_mem_region(80000000 - 80000fff, i2sbus control)
> > 
> >       80000000-8007ffff : 0.80000000:mac-io
> >         8000002c-8000002f : 0.0000004c:fans
> >         80000030-80000033 : 0.0000004c:fans
> >         80000034-80000037 : 0.0000004c:fans
> >         8000004c-8000004f : 0.0000004c:fans
> >         80000050-8000008a : 0.00000050:gpio

> Look like the bugs in the device-tree I told you about ...

Ben, is it safe to just hardcode 0x80010000-0x80010fff? Or hardcode
0x10000-0x10fff and have it do the translation depending on the
device-tree node, iow assume that the 'reg' property is bogus and
essentially replace it with one that contains the values
  0x00010000 0x00001000 (buggy one seems to be 0x00000000 0x00001000)
  0x00008000 0x00000100
  0x00008100 0x00000100
and then go from there? Even then though, I have no idea how to do the
ranges translation for the node. Maybe we should just fix up the reg
property in the device-tree for the affected machine(s)?

Btw, it doesn't look like snd-powermac handles this correctly, it only
ever handles the rx/tx specially and also takes the control io area
straight from the device tree.

Andreas, you'll probably be able to get a bit further by inserting the
following code in front of the loop in i2sbus-core.c line 162, and
removing the of_address_to_resource call inside the loop.

  dev->resources[0].start = 0x80010000;
  dev->resources[0].end   = 0x80010fff;
  dev->resources[1].start = 0x80008000;
  dev->resources[1].end   = 0x800080ff;
  dev->resources[2].start = 0x80008100;
  dev->resources[2].end   = 0x800081ff;

But I'm not sure that is correct on all machines (in fact, I'm not
perfectly sure it is correct on your machine).

After that, you'll probably still not have usable sound though because I
know nothing about the layout-id of your machine. If I have support for
your codec already, that should be easy though.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* Re: [Alsa-devel] [RFC] alsa integer control ranges
From: Johannes Berg @ 2006-05-17 12:16 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: ALSA development, Benjamin Berg, linuxppc-dev list
In-Reply-To: <s5hy7x10y5t.wl%tiwai@suse.de>

[-- Attachment #1: Type: text/plain, Size: 379 bytes --]

On Wed, 2006-05-17 at 11:59 +0200, Takashi Iwai wrote:

> We have several issuess regarding the conversion of dB <-> raw volume
> values:
> 
> - some codecs use linear volume
> - some codecs have non-linear dB slopes

And I made a huge table so that the slope is linear! Otherwise it'd have
been logarithmic. Anything else is pretty user-unfriendly though.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* Re: [Alsa-devel] [RFC] alsa integer control ranges
From: Johannes Berg @ 2006-05-17 12:17 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: linuxppc-dev list, ALSA development, Benjamin Berg
In-Reply-To: <s5h7j4m40kf.wl%tiwai@suse.de>

[-- Attachment #1: Type: text/plain, Size: 446 bytes --]

On Tue, 2006-05-16 at 14:27 +0200, Takashi Iwai wrote:

> I don't think it's alsa-lib that prevents the negative or non-zero
> integer range.  The fact amixer works implies that it's an
> app-specific bug.  But I'm not 100% sure and need more
> inside-looking. 

Basically, I think what I'm saying is: "why doesn't alsa-lib shift the
range to start at zero?"
It already does so many manipulations, that one wouldn't hurt...

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* Re: [Alsa-devel] [RFC] alsa integer control ranges
From: Johannes Berg @ 2006-05-17 12:21 UTC (permalink / raw)
  To: Jaroslav Kysela; +Cc: ALSA development, Benjamin Berg, linuxppc-dev list
In-Reply-To: <Pine.LNX.4.61.0605170836470.10248@tm8103.perex-int.cz>

[-- Attachment #1: Type: text/plain, Size: 827 bytes --]

On Wed, 2006-05-17 at 08:41 +0200, Jaroslav Kysela wrote:

> It's better to have problematic values by default and define a module 
> (driver) option to enable the "compatible" behaviour. 

I just committed the patch to be always compatible. I'm not going to
clutter the code even more.

> Otherwise the apps 
> will be never fixed. 

True.

> Also, ideally, you can fix apps and send patches to 
> authors and/or create problematic controls in the dummy driver 
> (drivers/dummy.c) and send a notice to app developers that they have 
> broken apps and ask to fix them refering to the dummy driver test case. 

The dummy driver isn't a bad idea, all the rest is. There are *dozens*
of broken apps, and most of their code is horrid. I couldn't even fix
alsamixer for the 3..28 range brokenness.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* Re: [Alsa-devel] [RFC] alsa integer control ranges
From: Johannes Berg @ 2006-05-17 12:24 UTC (permalink / raw)
  To: Takashi Iwai
  Cc: ALSA development, Benjamin Berg, Jaroslav Kysela,
	linuxppc-dev list
In-Reply-To: <s5hzmhh0yq4.wl%tiwai@suse.de>

[-- Attachment #1: Type: text/plain, Size: 918 bytes --]

On Wed, 2006-05-17 at 11:47 +0200, Takashi Iwai wrote:
> 
> The mixer stuff is the weakest point in the current ALSA
> implementation, and it has to be sorted out better. 

Here's another item for the wishlist:

Give applications an option to tell the library they can handle
ENUMERATED controls, and then don't mess with them. And then, if the
application *doesn't* tell the lib it can handle ENUMERATED controls,
split up *all* the enumerated controls instead of just the "Capture
Source" one. The current behaviour:
 - it splits up the Capture Source one but no others
 - it doesn't allow apps to get the real intention

is bogus for the following reasons:
 - most GUI programs get *checkboxes* that are mutually exclusive
 - a lot of GUI programs that cannot handle ENUMERATED items
   totally screw up when they still get an enumerated one just
   because it had a different name.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* Re: [Alsa-devel] [RFC] alsa integer control ranges
From: Takashi Iwai @ 2006-05-17 12:35 UTC (permalink / raw)
  To: Johannes Berg; +Cc: ALSA development, Benjamin Berg, linuxppc-dev list
In-Reply-To: <1147868218.15507.4.camel@johannes>

At Wed, 17 May 2006 14:16:58 +0200,
Johannes Berg wrote:
> 
> On Wed, 2006-05-17 at 11:59 +0200, Takashi Iwai wrote:
> 
> > We have several issuess regarding the conversion of dB <-> raw volume
> > values:
> > 
> > - some codecs use linear volume
> > - some codecs have non-linear dB slopes
> 
> And I made a huge table so that the slope is linear! Otherwise it'd have
> been logarithmic. Anything else is pretty user-unfriendly though.

It's not the question of user-friendliness.  As the end result, the dB
expression would be the best for users.  No doubt.

The question is where to implement a huge table or a complex
conversion function -- whether in the driver or in alsa-lib.


Takashi

^ permalink raw reply

* Re: [Alsa-devel] [RFC] alsa integer control ranges
From: Takashi Iwai @ 2006-05-17 12:37 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev list, ALSA development, Benjamin Berg
In-Reply-To: <1147868274.15507.6.camel@johannes>

At Wed, 17 May 2006 14:17:54 +0200,
Johannes Berg wrote:
> 
> On Tue, 2006-05-16 at 14:27 +0200, Takashi Iwai wrote:
> 
> > I don't think it's alsa-lib that prevents the negative or non-zero
> > integer range.  The fact amixer works implies that it's an
> > app-specific bug.  But I'm not 100% sure and need more
> > inside-looking. 
> 
> Basically, I think what I'm saying is: "why doesn't alsa-lib shift the
> range to start at zero?"
> It already does so many manipulations, that one wouldn't hurt...

True, but then it's a workaround only for your driver right now :)

The API clearly defines the non-zero minimum value, so manipulating it
in alsa-lib sounds self-inconsistent.


Takashi

^ permalink raw reply

* Re: [Alsa-devel] [RFC] alsa integer control ranges
From: Johannes Berg @ 2006-05-17 12:39 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: ALSA development, Benjamin Berg, linuxppc-dev list
In-Reply-To: <s5hd5ec4yn7.wl%tiwai@suse.de>

[-- Attachment #1: Type: text/plain, Size: 431 bytes --]

On Wed, 2006-05-17 at 14:35 +0200, Takashi Iwai wrote:

> The question is where to implement a huge table or a complex
> conversion function -- whether in the driver or in alsa-lib.

Well if it was in the alsa-lib I could just give it a formula that
contains an exponential and some constants, and that's all it needs. But
in the kernel it has to be a lookup table since I can't do floating
point math easily.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* Re: [PATCH/2.6.17-rc4 5/10]  Add tsi108 Ethernet support
From: Kumar Gala @ 2006-05-17 13:24 UTC (permalink / raw)
  To: Zang Roy-r61911
  Cc: linuxppc-dev list, Yang Xin-Xin-r48390, Paul Mackerras,
	Alexandre.Bounine
In-Reply-To: <9FCDBA58F226D911B202000BDBAD46730626D622@zch01exm40.ap.freescale.net>


On May 17, 2006, at 5:14 AM, Zang Roy-r61911 wrote:

> This patch adds a device driver and configuration options for
> Tundra Semiconductor Tsi108 integrated dual port Gigabit Ethernet  
> controller
>
> Signed-off-by: Alexandre Bounine <alexandreb@tundra.com>
> Signed-off-by: Roy Zang	<tie-fei.zang@freescale.com>

This patch needs to go to the netdev list and Jeff Garzik as  
maintainer for review.

- kumar

>  drivers/net/Kconfig      |    8
>  drivers/net/Makefile     |    1
>  drivers/net/tsi108_eth.c | 1740 +++++++++++++++++++++++++++++++++++ 
> +++++++++++
>  drivers/net/tsi108_eth.h |  404 +++++++++++
>  4 files changed, 2153 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/net/tsi108_eth.c
>  create mode 100644 drivers/net/tsi108_eth.h
>
> 23ed1c55ab6bc7a4c1c76f646579a1bc195bc7d2
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index bdaaad8..8a4ef29 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -2177,6 +2177,14 @@ config SPIDER_NET
>  	  This driver supports the Gigabit Ethernet chips present on the
>  	  Cell Processor-Based Blades from IBM.
>
> +config TSI108_ETH
> +	   tristate "Tundra TSI108 gigabit Ethernet support"
> +	   depends on TSI108_BRIDGE
> +	   help
> +	     This driver supports Tundra TSI108 gigabit Ethernet ports.
> +	     To compile this driver as a module, choose M here: the module
> +	     will be called tsi108_eth.
> +
>  config GIANFAR
>  	tristate "Gianfar Ethernet"
>  	depends on 85xx || 83xx
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index b90468a..5f90b30 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -109,6 +109,7 @@ obj-$(CONFIG_B44) += b44.o
>  obj-$(CONFIG_FORCEDETH) += forcedeth.o
>  obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
>
> +obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
>  obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
>
>  obj-$(CONFIG_PPP) += ppp_generic.o slhc.o
> diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c
> new file mode 100644
> index 0000000..cb67dbe
> --- /dev/null
> +++ b/drivers/net/tsi108_eth.c
> @@ -0,0 +1,1740 @@
> +/ 
> ********************************************************************** 
> *********
> +
> +  Copyright(c) 2005 Tundra Semiconductor Corporation.
> +
> +  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.
> +
> +  This program is distributed in the hope that it will be useful,  
> but WITHOUT
> +  ANY WARRANTY; without even the implied warranty of  
> MERCHANTABILITY or
> +  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public  
> License for
> +  more details.
> +
> +  You should have received a copy of the GNU General Public  
> License along with
> +  this program; if not, write to the Free Software Foundation,  
> Inc., 59
> +  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
> +
> +********************************************************************* 
> **********/
> +
> +/* This driver is based on the driver code originally developed	
> + * for the Intel IOC80314 (ForestLake) Gigabit Ethernet by
> + * scott.wood@timesys.com  * Copyright (C) 2003 TimeSys Corporation
> + *
> + * Currently changes from original version are:
> + * - portig to Tsi108-based platform and kernel 2.6  
> (kong.lai@tundra.com)
> + * - modifications to handle two ports independently and support for
> + *   additional PHY devices (alexandre.bounine@tundra.com)
> + *
> + */
> +
> +#include <linux/config.h>
> +#include <linux/module.h>
> +#include <linux/types.h>
> +#include <linux/init.h>
> +#include <linux/net.h>
> +#include <linux/netdevice.h>
> +#include <linux/etherdevice.h>
> +#include <linux/skbuff.h>
> +#include <linux/slab.h>
> +#include <linux/sched.h>
> +#include <linux/spinlock.h>
> +#include <linux/delay.h>
> +#include <linux/crc32.h>
> +#include <linux/mii.h>
> +#include <linux/device.h>
> +#include <asm/system.h>
> +#include <asm/io.h>
> +#include <linux/pci.h>
> +#include <linux/rtnetlink.h>
> +#include <linux/timer.h>
> +
> +#include <asm/tsi108_irq.h>
> +#include <asm/tsi108.h>
> +#include "tsi108_eth.h"
> +
> +typedef struct net_device net_device;
> +typedef struct sk_buff sk_buff;
> +
> +#define MII_READ_DELAY 10000	/* max link wait time in msec */
> +
> +#define TSI108_RXRING_LEN     256
> +
> +/* NOTE: The driver currently does not support receiving packets
> + * larger than the buffer size, so don't decrease this (unless you
> + * want to add such support).
> + */
> +#define TSI108_RXBUF_SIZE     1536
> +
> +#define TSI108_TXRING_LEN     256
> +
> +#define TSI108_TX_INT_FREQ    64
> +
> +/* Check the phy status every half a second. */
> +#define CHECK_PHY_INTERVAL (HZ/2)
> +
> +extern hw_info hw_info_table[];
> +
> +typedef struct {
> +	volatile u32 regs;	/* Base of normal regs */
> +	volatile u32 phyregs;	/* Base of register bank used for PHY  
> access */
> +	int phy;		/* Index of PHY for this interface */
> +	int irq_num;
> +
> +	struct timer_list timer;/* Timer that triggers the check phy  
> function */
> +	int rxtail;		/* Next entry in rxring to read */
> +	int rxhead;		/* Next entry in rxring to give a new buffer */
> +	int rxfree;		/* Number of free, allocated RX buffers */
> +
> +	int rxpending;		/* Non-zero if there are still descriptors
> +				 * to be processed from a previous descriptor
> +				 * interrupt condition that has been cleared */
> +
> +	int txtail;		/* Next TX descriptor to check status on */
> +	int txhead;		/* Next TX descriptor to use */
> +
> +	/* Number of free TX descriptors.  This could be calculated from
> +	 * rxhead and rxtail if one descriptor were left unused to  
> disambiguate
> +	 * full and empty conditions, but it's simpler to just keep track
> +	 * explicitly. */
> +
> +	int txfree;
> +
> +	int phy_ok;		/* The PHY is currently powered on. */
> +
> +	/* PHY status (duplex is 1 for half, 2 for full,
> +	 * so that the default 0 indicates that neither has
> +	 * yet been configured). */
> +
> +	int link_up;
> +	int speed;
> +	int duplex;
> +
> +	tx_desc *txring;
> +	rx_desc *rxring;
> +	sk_buff *txskbs[TSI108_TXRING_LEN];
> +	sk_buff *rxskbs[TSI108_RXRING_LEN];
> +
> +	dma_addr_t txdma, rxdma;
> +
> +	/* txlock nests in misclock and phy_lock */
> +
> +	spinlock_t txlock, misclock;
> +
> +	/* stats is used to hold the upper bits of each hardware counter,
> +	 * and tmpstats is used to hold the full values for returning
> +	 * to the caller of get_stats().  They must be separate in case
> +	 * an overflow interrupt occurs before the stats are consumed.
> +	 */
> +
> +	struct net_device_stats stats;
> +	struct net_device_stats tmpstats;
> +
> +	/* These stats are kept separate in hardware, thus require  
> individual
> +	 * fields for handling carry.  They are combined in get_stats.
> +	 */
> +
> +	unsigned long rx_fcs;	/* Add to rx_frame_errors */
> +	unsigned long rx_short_fcs;	/* Add to rx_frame_errors */
> +	unsigned long rx_long_fcs;	/* Add to rx_frame_errors */
> +	unsigned long rx_underruns;	/* Add to rx_length_errors */
> +	unsigned long rx_overruns;	/* Add to rx_length_errors */
> +
> +	unsigned long tx_coll_abort;	/* Add to tx_aborted_errors/ 
> collisions */
> +	unsigned long tx_pause_drop;	/* Add to tx_aborted_errors */
> +
> +	unsigned long mc_hash[16];
> +} tsi108_prv_data;
> +static void tsi108_timed_checker(unsigned long dev_ptr);
> +
> +static net_device *tsi108_devs[TSI108_ETH_PORT_NUM];
> +
> +static void dump_eth_one(net_device * dev)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +
> +	printk("Dumping %s...\n", dev->name);
> +	printk("intstat %x intmask %x phy_ok %d"
> +	       " link %d speed %d duplex %d\n",
> +	       TSI108_ETH_READ_REG(TSI108_EC_INTSTAT),
> +	       TSI108_ETH_READ_REG(TSI108_EC_INTMASK), data->phy_ok,
> +	       data->link_up, data->speed, data->duplex);
> +
> +	printk("TX: head %d, tail %d, free %d, stat %x, estat %x, err %x\n",
> +	       data->txhead, data->txtail, data->txfree,
> +	       TSI108_ETH_READ_REG(TSI108_EC_TXSTAT),
> +	       TSI108_ETH_READ_REG(TSI108_EC_TXESTAT),
> +	       TSI108_ETH_READ_REG(TSI108_EC_TXERR));
> +
> +	printk("RX: head %d, tail %d, free %d, stat %x,"
> +	       " estat %x, err %x, pending %d\n\n",
> +	       data->rxhead, data->rxtail, data->rxfree,
> +	       TSI108_ETH_READ_REG(TSI108_EC_RXSTAT),
> +	       TSI108_ETH_READ_REG(TSI108_EC_RXESTAT),
> +	       TSI108_ETH_READ_REG(TSI108_EC_RXERR), data->rxpending);
> +}
> +
> +void tsi108_dump_eth(void)
> +{
> +	dump_eth_one(tsi108_devs[0]);
> +	dump_eth_one(tsi108_devs[1]);
> +}
> +
> +/* Synchronization is needed between the thread and up/down events.
> + * Note that the PHY is accessed through the same registers for both
> + * interfaces, so this can't be made interface-specific.
> + */
> +
> +static spinlock_t phy_lock = SPIN_LOCK_UNLOCKED;
> +
> +static inline u16 tsi108_read_mii(tsi108_prv_data * data, int reg,  
> int *status)
> +{
> +	int i;
> +	u16 ret;
> +
> +	TSI108_ETH_WRITE_PHYREG(TSI108_MAC_MII_ADDR,
> +				(data->phy << TSI108_MAC_MII_ADDR_PHY) |
> +				(reg << TSI108_MAC_MII_ADDR_REG));
> +	mb();
> +	TSI108_ETH_WRITE_PHYREG(TSI108_MAC_MII_CMD, 0);
> +	mb();
> +	TSI108_ETH_WRITE_PHYREG(TSI108_MAC_MII_CMD,  
> TSI108_MAC_MII_CMD_READ);
> +	mb();
> +	for (i = 0; i < 100; i++) {
> +		if (!(TSI108_ETH_READ_PHYREG(TSI108_MAC_MII_IND) &
> +		      (TSI108_MAC_MII_IND_NOTVALID | TSI108_MAC_MII_IND_BUSY)))
> +			break;
> +		udelay(10);
> +	}
> +
> +	if (i == 100) {
> +		if (status)
> +			*status = -EBUSY;
> +
> +		ret = 0xffff;
> +	} else {
> +		if (status)
> +			*status = 0;
> +
> +		ret = TSI108_ETH_READ_PHYREG(TSI108_MAC_MII_DATAIN);
> +	}
> +
> +	return ret;
> +}
> +
> +static inline void tsi108_write_mii(tsi108_prv_data * data, int  
> reg, u16 val)
> +{
> +	TSI108_ETH_WRITE_PHYREG(TSI108_MAC_MII_ADDR,
> +				(data->phy << TSI108_MAC_MII_ADDR_PHY) |
> +				(reg << TSI108_MAC_MII_ADDR_REG));
> +	mb();
> +	TSI108_ETH_WRITE_PHYREG(TSI108_MAC_MII_DATAOUT, val);
> +	mb();
> +	while (TSI108_ETH_READ_PHYREG(TSI108_MAC_MII_IND) &
> +	       TSI108_MAC_MII_IND_BUSY) ;
> +}
> +
> +static inline void tsi108_write_tbi(tsi108_prv_data * data, int  
> reg, u16 val)
> +{
> +
> +	TSI108_ETH_WRITE_REG(TSI108_MAC_MII_ADDR,
> +			     (0x1e << TSI108_MAC_MII_ADDR_PHY)
> +			     | (reg << TSI108_MAC_MII_ADDR_REG));
> +	mb();
> +
> +	TSI108_ETH_WRITE_REG(TSI108_MAC_MII_DATAOUT, val);
> +	mb();
> +	while (TSI108_ETH_READ_REG(TSI108_MAC_MII_IND) &
> +	       TSI108_MAC_MII_IND_BUSY) ;
> +}
> +
> +static void tsi108_check_phy(net_device * dev)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +	u16 sumstat;
> +	u32 mac_cfg2_reg, portctrl_reg;
> +	u32 fdx_flag = 0, reg_update = 0;
> +
> +	/* Do a dummy read, as for some reason the first read
> +	 * after a link becomes up returns link down, even if
> +	 * it's been a while since the link came up.
> +	 */
> +
> +	spin_lock(&phy_lock);
> +
> +	if (!data->phy_ok)
> +		goto out;
> +
> +	tsi108_read_mii(data, PHY_STAT, NULL);
> +
> +	if (!(tsi108_read_mii(data, PHY_STAT, NULL) & PHY_STAT_LINKUP)) {
> +		if (data->link_up == 1) {
> +			netif_stop_queue(dev);
> +			data->link_up = 0;
> +			printk(KERN_NOTICE "%s : link is down\n", dev->name);
> +			netif_carrier_off(dev);
> +		}
> +
> +		goto out;
> +	}
> +
> +	{
> +		mac_cfg2_reg = TSI108_ETH_READ_REG(TSI108_MAC_CFG2);
> +		portctrl_reg = TSI108_ETH_READ_REG(TSI108_EC_PORTCTRL);
> +
> +		sumstat = tsi108_read_mii(data, PHY_SUM_STAT, NULL);
> +
> +		switch (sumstat & PHY_SUM_STAT_SPEED_MASK) {
> +		case PHY_SUM_STAT_1000T_FD:
> +			fdx_flag++;
> +		case PHY_SUM_STAT_1000T_HD:
> +			if (data->speed != 1000) {
> +				mac_cfg2_reg &= ~TSI108_MAC_CFG2_IFACE_MASK;
> +				mac_cfg2_reg |= TSI108_MAC_CFG2_GIG;
> +				portctrl_reg &= ~TSI108_EC_PORTCTRL_NOGIG;
> +				data->speed = 1000;
> +				reg_update++;
> +			}
> +			break;
> +		case PHY_SUM_STAT_100TX_FD:
> +			fdx_flag++;
> +		case PHY_SUM_STAT_100TX_HD:
> +			if (data->speed != 100) {
> +				mac_cfg2_reg &= ~TSI108_MAC_CFG2_IFACE_MASK;
> +				mac_cfg2_reg |= TSI108_MAC_CFG2_NOGIG;
> +				portctrl_reg |= TSI108_EC_PORTCTRL_NOGIG;
> +				data->speed = 100;
> +				reg_update++;
> +			}
> +			break;
> +
> +		case PHY_SUM_STAT_10T_FD:
> +			fdx_flag++;
> +		case PHY_SUM_STAT_10T_HD:
> +			if (data->speed != 10) {
> +				mac_cfg2_reg &= ~TSI108_MAC_CFG2_IFACE_MASK;
> +				mac_cfg2_reg |= TSI108_MAC_CFG2_NOGIG;
> +				portctrl_reg |= TSI108_EC_PORTCTRL_NOGIG;
> +				data->speed = 10;
> +				reg_update++;
> +			}
> +			break;
> +
> +		default:
> +			if (net_ratelimit())
> +				printk(KERN_ERR "PHY reported invalid speed,"
> +				       KERN_ERR " summary status %x\n",
> +				       sumstat);
> +			goto out;
> +		}
> +
> +		if (fdx_flag || (sumstat & PHY_SUM_STAT_FULLDUPLEX)) {
> +			if (data->duplex != 2) {
> +				mac_cfg2_reg |= TSI108_MAC_CFG2_FULLDUPLEX;
> +				portctrl_reg &= ~TSI108_EC_PORTCTRL_HALFDUPLEX;
> +				data->duplex = 2;
> +				reg_update++;
> +			}
> +		} else {
> +			if (data->duplex != 1) {
> +				mac_cfg2_reg &= ~TSI108_MAC_CFG2_FULLDUPLEX;
> +				portctrl_reg |= TSI108_EC_PORTCTRL_HALFDUPLEX;
> +				data->duplex = 1;
> +				reg_update++;
> +			}
> +		}
> +
> +		if (reg_update) {
> +			TSI108_ETH_WRITE_REG(TSI108_MAC_CFG2, mac_cfg2_reg);
> +			mb();
> +			TSI108_ETH_WRITE_REG(TSI108_EC_PORTCTRL, portctrl_reg);
> +			mb();
> +		}
> +
> +	}
> +
> +	if (data->link_up == 0) {
> +		/* The manual says it can take 3-4 usecs for the speed change
> +		 * to take effect.
> +		 */
> +		udelay(5);
> +
> +		spin_lock(&data->txlock);
> +		if (netif_queue_stopped(dev)
> +		    && is_valid_ether_addr(dev->dev_addr) && data->txfree)
> +			netif_wake_queue(dev);
> +
> +		data->link_up = 1;
> +		spin_unlock(&data->txlock);
> +		printk("%s : link is up: %dMb %s-duplex\n",
> +		       dev->name, data->speed,
> +		       (data->duplex == 2) ? "full" : "half");
> +		netif_carrier_on(dev);
> +	}
> +
> +      out:
> +	spin_unlock(&phy_lock);
> +}
> +
> +static inline void
> +tsi108_stat_carry_one(int carry, int carry_bit, int carry_shift,
> +		      unsigned long *upper)
> +{
> +	if (carry & carry_bit)
> +		*upper += carry_shift;
> +}
> +
> +static void tsi108_stat_carry(net_device * dev)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +	u32 carry1, carry2;
> +
> +	spin_lock_irq(&data->misclock);
> +
> +	carry1 = TSI108_ETH_READ_REG(TSI108_STAT_CARRY1);
> +	carry2 = TSI108_ETH_READ_REG(TSI108_STAT_CARRY2);
> +
> +	TSI108_ETH_WRITE_REG(TSI108_STAT_CARRY1, carry1);
> +	TSI108_ETH_WRITE_REG(TSI108_STAT_CARRY2, carry2);
> +
> +	tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXBYTES,
> +			      TSI108_STAT_RXBYTES_CARRY, &data->stats.rx_bytes);
> +
> +	tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXPKTS,
> +			      TSI108_STAT_RXPKTS_CARRY,
> +			      &data->stats.rx_packets);
> +
> +	tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXFCS,
> +			      TSI108_STAT_RXFCS_CARRY, &data->rx_fcs);
> +
> +	tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXMCAST,
> +			      TSI108_STAT_RXMCAST_CARRY,
> +			      &data->stats.multicast);
> +
> +	tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXALIGN,
> +			      TSI108_STAT_RXALIGN_CARRY,
> +			      &data->stats.rx_frame_errors);
> +
> +	tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXLENGTH,
> +			      TSI108_STAT_RXLENGTH_CARRY,
> +			      &data->stats.rx_length_errors);
> +
> +	tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXRUNT,
> +			      TSI108_STAT_RXRUNT_CARRY, &data->rx_underruns);
> +
> +	tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXJUMBO,
> +			      TSI108_STAT_RXJUMBO_CARRY, &data->rx_overruns);
> +
> +	tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXFRAG,
> +			      TSI108_STAT_RXFRAG_CARRY, &data->rx_short_fcs);
> +
> +	tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXJABBER,
> +			      TSI108_STAT_RXJABBER_CARRY, &data->rx_long_fcs);
> +
> +	tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXDROP,
> +			      TSI108_STAT_RXDROP_CARRY,
> +			      &data->stats.rx_missed_errors);
> +
> +	tsi108_stat_carry_one(carry2, TSI108_STAT_CARRY2_TXBYTES,
> +			      TSI108_STAT_TXBYTES_CARRY, &data->stats.tx_bytes);
> +
> +	tsi108_stat_carry_one(carry2, TSI108_STAT_CARRY2_TXPKTS,
> +			      TSI108_STAT_TXPKTS_CARRY,
> +			      &data->stats.tx_packets);
> +
> +	tsi108_stat_carry_one(carry2, TSI108_STAT_CARRY2_TXEXDEF,
> +			      TSI108_STAT_TXEXDEF_CARRY,
> +			      &data->stats.tx_aborted_errors);
> +
> +	tsi108_stat_carry_one(carry2, TSI108_STAT_CARRY2_TXEXCOL,
> +			      TSI108_STAT_TXEXCOL_CARRY, &data->tx_coll_abort);
> +
> +	tsi108_stat_carry_one(carry2, TSI108_STAT_CARRY2_TXTCOL,
> +			      TSI108_STAT_TXTCOL_CARRY,
> +			      &data->stats.collisions);
> +
> +	tsi108_stat_carry_one(carry2, TSI108_STAT_CARRY2_TXPAUSE,
> +			      TSI108_STAT_TXPAUSEDROP_CARRY,
> +			      &data->tx_pause_drop);
> +
> +	spin_unlock_irq(&data->misclock);
> +}
> +
> +/* Read a stat counter atomically with respect to carries.
> + * data->misclock must be held.
> + */
> +static inline unsigned long
> +tsi108_read_stat(tsi108_prv_data * data, int reg, int carry_bit,
> +		 int carry_shift, unsigned long *upper)
> +{
> +	int carryreg;
> +	unsigned long val;
> +
> +	if (reg < 0xb0)
> +		carryreg = TSI108_STAT_CARRY1;
> +	else
> +		carryreg = TSI108_STAT_CARRY2;
> +
> +      again:
> +	val = TSI108_ETH_READ_REG(reg) | *upper;
> +
> +	rmb();
> +
> +	/* Check to see if it overflowed, but the interrupt hasn't
> +	 * been serviced yet.  If so, handle the carry here, and
> +	 * try again.
> +	 */
> +
> +	if (unlikely(TSI108_ETH_READ_REG(carryreg) & carry_bit)) {
> +		*upper += carry_shift;
> +		TSI108_ETH_WRITE_REG(carryreg, carry_bit);
> +		mb();
> +
> +		goto again;
> +	}
> +
> +	return val;
> +}
> +
> +static struct net_device_stats *tsi108_get_stats(net_device * dev)
> +{
> +	unsigned long excol;
> +
> +	tsi108_prv_data *data = netdev_priv(dev);
> +	spin_lock_irq(&data->misclock);
> +
> +	data->tmpstats.rx_packets =
> +	    tsi108_read_stat(data, TSI108_STAT_RXPKTS,
> +			     TSI108_STAT_CARRY1_RXPKTS,
> +			     TSI108_STAT_RXPKTS_CARRY, &data->stats.rx_packets);
> +
> +	data->tmpstats.tx_packets =
> +	    tsi108_read_stat(data, TSI108_STAT_TXPKTS,
> +			     TSI108_STAT_CARRY2_TXPKTS,
> +			     TSI108_STAT_TXPKTS_CARRY, &data->stats.tx_packets);
> +
> +	data->tmpstats.rx_bytes =
> +	    tsi108_read_stat(data, TSI108_STAT_RXBYTES,
> +			     TSI108_STAT_CARRY1_RXBYTES,
> +			     TSI108_STAT_RXBYTES_CARRY, &data->stats.rx_bytes);
> +
> +	data->tmpstats.tx_bytes =
> +	    tsi108_read_stat(data, TSI108_STAT_TXBYTES,
> +			     TSI108_STAT_CARRY2_TXBYTES,
> +			     TSI108_STAT_TXBYTES_CARRY, &data->stats.tx_bytes);
> +
> +	data->tmpstats.multicast =
> +	    tsi108_read_stat(data, TSI108_STAT_RXMCAST,
> +			     TSI108_STAT_CARRY1_RXMCAST,
> +			     TSI108_STAT_RXMCAST_CARRY, &data->stats.multicast);
> +
> +	excol = tsi108_read_stat(data, TSI108_STAT_TXEXCOL,
> +				 TSI108_STAT_CARRY2_TXEXCOL,
> +				 TSI108_STAT_TXEXCOL_CARRY,
> +				 &data->tx_coll_abort);
> +
> +	data->tmpstats.collisions =
> +	    tsi108_read_stat(data, TSI108_STAT_TXTCOL,
> +			     TSI108_STAT_CARRY2_TXTCOL,
> +			     TSI108_STAT_TXTCOL_CARRY, &data->stats.collisions);
> +
> +	data->tmpstats.collisions += excol;
> +
> +	data->tmpstats.rx_length_errors =
> +	    tsi108_read_stat(data, TSI108_STAT_RXLENGTH,
> +			     TSI108_STAT_CARRY1_RXLENGTH,
> +			     TSI108_STAT_RXLENGTH_CARRY,
> +			     &data->stats.rx_length_errors);
> +
> +	data->tmpstats.rx_length_errors +=
> +	    tsi108_read_stat(data, TSI108_STAT_RXRUNT,
> +			     TSI108_STAT_CARRY1_RXRUNT,
> +			     TSI108_STAT_RXRUNT_CARRY, &data->rx_underruns);
> +
> +	data->tmpstats.rx_length_errors +=
> +	    tsi108_read_stat(data, TSI108_STAT_RXJUMBO,
> +			     TSI108_STAT_CARRY1_RXJUMBO,
> +			     TSI108_STAT_RXJUMBO_CARRY, &data->rx_overruns);
> +
> +	data->tmpstats.rx_frame_errors =
> +	    tsi108_read_stat(data, TSI108_STAT_RXALIGN,
> +			     TSI108_STAT_CARRY1_RXALIGN,
> +			     TSI108_STAT_RXALIGN_CARRY,
> +			     &data->stats.rx_frame_errors);
> +
> +	data->tmpstats.rx_frame_errors +=
> +	    tsi108_read_stat(data, TSI108_STAT_RXFCS,
> +			     TSI108_STAT_CARRY1_RXFCS, TSI108_STAT_RXFCS_CARRY,
> +			     &data->rx_fcs);
> +
> +	data->tmpstats.rx_frame_errors +=
> +	    tsi108_read_stat(data, TSI108_STAT_RXFRAG,
> +			     TSI108_STAT_CARRY1_RXFRAG,
> +			     TSI108_STAT_RXFRAG_CARRY, &data->rx_short_fcs);
> +
> +	data->tmpstats.rx_missed_errors =
> +	    tsi108_read_stat(data, TSI108_STAT_RXDROP,
> +			     TSI108_STAT_CARRY1_RXDROP,
> +			     TSI108_STAT_RXDROP_CARRY,
> +			     &data->stats.rx_missed_errors);
> +
> +	/* These three are maintained by software. */
> +	data->tmpstats.rx_fifo_errors = data->stats.rx_fifo_errors;
> +	data->tmpstats.rx_crc_errors = data->stats.rx_crc_errors;
> +
> +	data->tmpstats.tx_aborted_errors =
> +	    tsi108_read_stat(data, TSI108_STAT_TXEXDEF,
> +			     TSI108_STAT_CARRY2_TXEXDEF,
> +			     TSI108_STAT_TXEXDEF_CARRY,
> +			     &data->stats.tx_aborted_errors);
> +
> +	data->tmpstats.tx_aborted_errors +=
> +	    tsi108_read_stat(data, TSI108_STAT_TXPAUSEDROP,
> +			     TSI108_STAT_CARRY2_TXPAUSE,
> +			     TSI108_STAT_TXPAUSEDROP_CARRY,
> +			     &data->tx_pause_drop);
> +
> +	data->tmpstats.tx_aborted_errors += excol;
> +
> +	data->tmpstats.tx_errors = data->tmpstats.tx_aborted_errors;
> +	data->tmpstats.rx_errors = data->tmpstats.rx_length_errors +
> +	    data->tmpstats.rx_crc_errors +
> +	    data->tmpstats.rx_frame_errors +
> +	    data->tmpstats.rx_fifo_errors + data->tmpstats.rx_missed_errors;
> +
> +	spin_unlock_irq(&data->misclock);
> +	return &data->tmpstats;
> +}
> +
> +static void tsi108_restart_rx(tsi108_prv_data * data, net_device *  
> dev)
> +{
> +	TSI108_ETH_WRITE_REG(TSI108_EC_RXQ_PTRHIGH,
> +			     TSI108_EC_RXQ_PTRHIGH_VALID);
> +
> +	wmb();
> +	TSI108_ETH_WRITE_REG(TSI108_EC_RXCTRL, TSI108_EC_RXCTRL_GO
> +			     | TSI108_EC_RXCTRL_QUEUE0);
> +}
> +
> +static void tsi108_restart_tx(tsi108_prv_data * data)
> +{
> +	TSI108_ETH_WRITE_REG(TSI108_EC_TXQ_PTRHIGH,
> +			     TSI108_EC_TXQ_PTRHIGH_VALID);
> +
> +	wmb();
> +	TSI108_ETH_WRITE_REG(TSI108_EC_TXCTRL, TSI108_EC_TXCTRL_IDLEINT |
> +			     TSI108_EC_TXCTRL_GO | TSI108_EC_TXCTRL_QUEUE0);
> +}
> +
> +/* txlock must be held by caller, with IRQs disabled, and
> + * with permission to re-enable them when the lock is dropped.
> + */
> +static void tsi108_check_for_completed_tx(net_device * dev)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +	int tx;
> +	struct sk_buff *skb;
> +	int release = 0;
> +
> +	while (!data->txfree || data->txhead != data->txtail) {
> +		tx = data->txtail;
> +
> +		if (data->txring[tx].misc & TSI108_TX_OWN)
> +			break;
> +
> +		skb = data->txskbs[tx];
> +
> +		if (!(data->txring[tx].misc & TSI108_TX_OK))
> +			printk("%s: bad tx packet, misc %x\n",
> +			       dev->name, data->txring[tx].misc);
> +
> +		data->txtail = (data->txtail + 1) % TSI108_TXRING_LEN;
> +		data->txfree++;
> +
> +		if (data->txring[tx].misc & TSI108_TX_EOF) {
> +			dev_kfree_skb_any(skb);
> +			release++;
> +		}
> +	}
> +
> +	if (release) {
> +
> +		if (netif_queue_stopped(dev)
> +		    && is_valid_ether_addr(dev->dev_addr) && data->link_up)
> +			netif_wake_queue(dev);
> +	}
> +}
> +
> +static int tsi108_send_packet(sk_buff * skb, net_device * dev)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +	int frags = skb_shinfo(skb)->nr_frags + 1;
> +	int i;
> +#ifdef FIXME_SG_CSUM_NOT_TESTED	/* FIXME: Not supported now. */
> +	long csstart;
> +	long csum;
> +
> +	csstart = skb->len - skb->data_len;
> +	if (csstart > skb->len - skb->data_len)
> +		BUG();
> +	csum = 0;
> +	if (csstart != skb->len)
> +		csum = skb_checksum(skb, csstart, skb->len - csstart, 0);
> +#endif
> +
> +	if (!data->phy_ok && net_ratelimit())
> +		printk(KERN_ERR "%s: Transmit while PHY is down!\n", dev->name);
> +
> +	if (!data->link_up) {
> +		printk(KERN_ERR "%s: Transmit while link is down!\n",
> +		       dev->name);
> +		netif_stop_queue(dev);
> +		return 1;
> +	}
> +
> +	if (data->txfree < MAX_SKB_FRAGS + 1) {
> +		netif_stop_queue(dev);
> +
> +		if (net_ratelimit())
> +			printk(KERN_ERR "%s: Transmit with full tx ring!\n",
> +			       dev->name);
> +		return 1;
> +	}
> +
> +	if (data->txfree - frags < MAX_SKB_FRAGS + 1) {
> +		netif_stop_queue(dev);
> +	}
> +
> +	spin_lock_irq(&data->txlock);
> +
> +	for (i = 0; i < frags; i++) {
> +		int misc = 0;
> +		int tx = data->txhead;
> +
> +		/* This is done to mark every TSI108_TX_INT_FREQ tx buffers with
> +		 * the interrupt bit.  TX descriptor-complete interrupts are
> +		 * enabled when the queue fills up, and masked when there is
> +		 * still free space.  This way, when saturating the outbound
> +		 * link, the tx interrupts are kept to a reasonable level.
> +		 * When the queue is not full, reclamation of skbs still occurs
> +		 * as new packets are transmitted, or on a queue-empty
> +		 * interrupt.
> +		 */
> +
> +		if ((tx % TSI108_TX_INT_FREQ == 0) &&
> +		    ((TSI108_TXRING_LEN - data->txfree) >= TSI108_TX_INT_FREQ)
> +		    )
> +			misc = TSI108_TX_INT;
> +
> +		data->txskbs[tx] = skb;
> +
> +		if (i == 0) {
> +			data->txring[tx].buf0 = virt_to_phys(skb->data);
> +			data->txring[tx].len = skb->len - skb->data_len;
> +			misc |= TSI108_TX_SOF;
> +		} else {
> +			skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
> +
> +			data->txring[tx].buf0 =
> +			    page_to_phys(frag->page) + frag->page_offset;
> +			data->txring[tx].len = frag->size;
> +		}
> +
> +		if (i == frags - 1)
> +			misc |= TSI108_TX_EOF;
> +
> +#ifdef TSI108_PRINT_TX_FRAME
> +		{
> +			int i;
> +			printk("%s: Tx Frame contents (%d)\n", dev->name,
> +			       skb->len);
> +			for (i = 0; i < skb->len; i++)
> +				printk(" %2.2x", skb->data[i]);
> +			printk(".\n");
> +		}
> +#endif				/* TSI108_PRINT_TX_FRAME */
> +
> +		mb();
> +		data->txring[tx].misc = misc | TSI108_TX_OWN;
> +
> +		data->txhead = (data->txhead + 1) % TSI108_TXRING_LEN;
> +		data->txfree--;
> +	}
> +
> +	tsi108_check_for_completed_tx(dev);
> +
> +	/* This must be done after the check for completed tx descriptors,
> +	 * so that the tail pointer is correct.
> +	 */
> +
> +	if (!(TSI108_ETH_READ_REG(TSI108_EC_TXSTAT) &  
> TSI108_EC_TXSTAT_QUEUE0))
> +		tsi108_restart_tx(data);
> +
> +	spin_unlock_irq(&data->txlock);
> +	return 0;
> +}
> +
> +static int tsi108_check_for_completed_rx(net_device * dev, int  
> budget)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +	int done = 0;
> +
> +	while (data->rxfree && done != budget) {
> +		int rx = data->rxtail;
> +		struct sk_buff *skb;
> +
> +		if (data->rxring[rx].misc & TSI108_RX_OWN)
> +			break;
> +
> +		skb = data->rxskbs[rx];
> +		data->rxtail = (data->rxtail + 1) % TSI108_RXRING_LEN;
> +		data->rxfree--;
> +		done++;
> +
> +		if (data->rxring[rx].misc & TSI108_RX_BAD) {
> +			spin_lock_irq(&data->misclock);
> +
> +			if (data->rxring[rx].misc & TSI108_RX_CRC)
> +				data->stats.rx_crc_errors++;
> +			if (data->rxring[rx].misc & TSI108_RX_OVER)
> +				data->stats.rx_fifo_errors++;
> +
> +			spin_unlock_irq(&data->misclock);
> +
> +			dev_kfree_skb_any(skb);
> +			continue;
> +		}
> +#ifdef TSI108_PRINT_RX_FRAME
> +		{
> +			int i;
> +			printk("%s: Rx Frame contents (%d)\n",
> +			       dev->name, data->rxring[rx].len);
> +			for (i = 0; i < data->rxring[rx].len; i++)
> +				printk(" %2.2x", skb->data[i]);
> +			printk(".\n");
> +		}
> +#endif				/* TSI108_PRINT_RX_FRAME */
> +
> +		skb->dev = dev;
> +		skb_put(skb, data->rxring[rx].len);
> +		skb->protocol = eth_type_trans(skb, dev);
> +		netif_receive_skb(skb);
> +		dev->last_rx = jiffies;
> +	}
> +
> +	return done;
> +}
> +
> +static int tsi108_refill_rx(net_device * dev, int budget)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +	int done = 0;
> +
> +	while (data->rxfree != TSI108_RXRING_LEN && done != budget) {
> +		int rx = data->rxhead;
> +		sk_buff *skb;
> +
> +		data->rxskbs[rx] = skb = dev_alloc_skb(TSI108_RXBUF_SIZE + 2);
> +		if (!skb)
> +			break;
> +
> +		skb_reserve(skb, 2);	/* Align the data on a 4-byte boundary. */
> +
> +		data->rxring[rx].buf0 = virt_to_phys(skb->data);
> +
> +		/* Sometimes the hardware sets blen to zero after packet
> +		 * reception, even though the manual says that it's only ever
> +		 * modified by the driver.
> +		 */
> +
> +		data->rxring[rx].blen = 1536;
> +		mb();
> +		data->rxring[rx].misc = TSI108_RX_OWN | TSI108_RX_INT;
> +
> +		data->rxhead = (data->rxhead + 1) % TSI108_RXRING_LEN;
> +		data->rxfree++;
> +		done++;
> +	}
> +
> +	mb();
> +
> +	if (done != 0 && !(TSI108_ETH_READ_REG(TSI108_EC_RXSTAT) &
> +			   TSI108_EC_RXSTAT_QUEUE0))
> +		tsi108_restart_rx(data, dev);
> +
> +	return done;
> +}
> +
> +static int tsi108_poll(net_device * dev, int *budget)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +	u32 estat = TSI108_ETH_READ_REG(TSI108_EC_RXESTAT);
> +	u32 intstat = TSI108_ETH_READ_REG(TSI108_EC_INTSTAT);
> +	int total_budget = min(*budget, dev->quota);
> +	int num_received = 0, num_filled = 0, budget_used;
> +
> +	intstat &= TSI108_INT_RXQUEUE0 | TSI108_INT_RXTHRESH |
> +	    TSI108_INT_RXOVERRUN | TSI108_INT_RXERROR | TSI108_INT_RXWAIT;
> +
> +	TSI108_ETH_WRITE_REG(TSI108_EC_RXESTAT, estat);
> +	TSI108_ETH_WRITE_REG(TSI108_EC_INTSTAT, intstat);
> +
> +	if (data->rxpending || (estat & TSI108_EC_RXESTAT_Q0_DESCINT))
> +		num_received = tsi108_check_for_completed_rx(dev, total_budget);
> +
> +	/* This should normally fill no more slots than the number of
> +	 * packets received in tsi108_check_for_completed_rx().  The  
> exception
> +	 * is when we previously ran out of memory for RX SKBs.  In that
> +	 * case, it's helpful to obey the budget, not only so that the
> +	 * CPU isn't hogged, but so that memory (which may still be low)
> +	 * is not hogged by one device.
> +	 *
> +	 * A work unit is considered to be two SKBs to allow us to catch
> +	 * up when the ring has shrunk due to out-of-memory but we're
> +	 * still removing the full budget's worth of packets each time.
> +	 */
> +
> +	if (data->rxfree < TSI108_RXRING_LEN)
> +		num_filled = tsi108_refill_rx(dev, total_budget * 2);
> +
> +	if (intstat & TSI108_INT_RXERROR) {
> +		u32 err = TSI108_ETH_READ_REG(TSI108_EC_RXERR);
> +		TSI108_ETH_WRITE_REG(TSI108_EC_RXERR, err);
> +
> +		if (err) {
> +			if (net_ratelimit())
> +				printk(KERN_DEBUG "%s: RX error %x\n",
> +				       dev->name, err);
> +
> +			if (!(TSI108_ETH_READ_REG(TSI108_EC_RXSTAT) &
> +			      TSI108_EC_RXSTAT_QUEUE0))
> +				tsi108_restart_rx(data, dev);
> +		}
> +	}
> +
> +	if (intstat & TSI108_INT_RXOVERRUN) {
> +		spin_lock_irq(&data->misclock);
> +		data->stats.rx_fifo_errors++;
> +		spin_unlock_irq(&data->misclock);
> +	}
> +
> +	budget_used = max(num_received, num_filled / 2);
> +
> +	*budget -= budget_used;
> +	dev->quota -= budget_used;
> +
> +	if (budget_used != total_budget) {
> +		data->rxpending = 0;
> +		netif_rx_complete(dev);
> +
> +		TSI108_ETH_WRITE_REG(TSI108_EC_INTMASK,
> +				     TSI108_ETH_READ_REG(TSI108_EC_INTMASK)
> +				     & ~(TSI108_INT_RXQUEUE0
> +					 | TSI108_INT_RXTHRESH |
> +					 TSI108_INT_RXOVERRUN |
> +					 TSI108_INT_RXERROR |
> +					 TSI108_INT_RXWAIT));
> +
> +		mb();
> +
> +		/* IRQs are level-triggered, so no need to re-check */
> +		return 0;
> +	} else {
> +		data->rxpending = 1;
> +	}
> +
> +	return 1;
> +}
> +
> +static void tsi108_rx_int(net_device * dev)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +
> +	/* A race could cause dev to already be scheduled, so it's not an
> +	 * error if that happens (and interrupts shouldn't be re-masked,
> +	 * because that can cause harmful races, if poll has already
> +	 * unmasked them but not cleared LINK_STATE_SCHED).
> +	 *
> +	 * This can happen if this code races with tsi108_poll(), which  
> masks
> +	 * the interrupts after tsi108_irq_one() read the mask, but before
> +	 * netif_rx_schedule is called.  It could also happen due to calls
> +	 * from tsi108_check_rxring().
> +	 */
> +
> +	if (netif_rx_schedule_prep(dev)) {
> +		/* Mask, rather than ack, the receive interrupts.  The ack
> +		 * will happen in tsi108_poll().
> +		 */
> +
> +		TSI108_ETH_WRITE_REG(TSI108_EC_INTMASK,
> +				     TSI108_ETH_READ_REG(TSI108_EC_INTMASK) |
> +				     TSI108_INT_RXQUEUE0
> +				     | TSI108_INT_RXTHRESH |
> +				     TSI108_INT_RXOVERRUN | TSI108_INT_RXERROR |
> +				     TSI108_INT_RXWAIT);
> +		mb();
> +		__netif_rx_schedule(dev);
> +	} else {
> +		if (!netif_running(dev)) {
> +			/* This can happen if an interrupt occurs while the
> +			 * interface is being brought down, as the START
> +			 * bit is cleared before the stop function is called.
> +			 *
> +			 * In this case, the interrupts must be masked, or
> +			 * they will continue indefinitely.
> +			 *
> +			 * There's a race here if the interface is brought down
> +			 * and then up in rapid succession, as the device could
> +			 * be made running after the above check and before
> +			 * the masking below.  This will only happen if the IRQ
> +			 * thread has a lower priority than the task brining
> +			 * up the interface.  Fixing this race would likely
> +			 * require changes in generic code.
> +			 */
> +
> +			TSI108_ETH_WRITE_REG(TSI108_EC_INTMASK,
> +					     TSI108_ETH_READ_REG
> +					     (TSI108_EC_INTMASK) |
> +					     TSI108_INT_RXQUEUE0 |
> +					     TSI108_INT_RXTHRESH |
> +					     TSI108_INT_RXOVERRUN |
> +					     TSI108_INT_RXERROR |
> +					     TSI108_INT_RXWAIT);
> +			mb();
> +		}
> +	}
> +}
> +
> +/* If the RX ring has run out of memory, try periodically
> + * to allocate some more, as otherwise poll would never
> + * get called (apart from the initial end-of-queue condition).
> + *
> + * This is called once per second (by default) from the thread.
> + */
> +
> +static void tsi108_check_rxring(net_device * dev)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +
> +	/* A poll is scheduled, as opposed to caling tsi108_refill_rx
> +	 * directly, so as to keep the receive path single-threaded
> +	 * (and thus not needing a lock).
> +	 */
> +
> +	if (netif_running(dev) && data->rxfree < TSI108_RXRING_LEN / 4)
> +		tsi108_rx_int(dev);
> +}
> +
> +static void tsi108_tx_int(net_device * dev)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +	u32 estat = TSI108_ETH_READ_REG(TSI108_EC_TXESTAT);
> +
> +	mb();
> +	TSI108_ETH_WRITE_REG(TSI108_EC_TXESTAT, estat);
> +	mb();
> +	TSI108_ETH_WRITE_REG(TSI108_EC_INTSTAT, TSI108_INT_TXQUEUE0 |
> +			     TSI108_INT_TXIDLE | TSI108_INT_TXERROR);
> +	mb();
> +	if (estat & TSI108_EC_TXESTAT_Q0_ERR) {
> +		u32 err = TSI108_ETH_READ_REG(TSI108_EC_TXERR);
> +		TSI108_ETH_WRITE_REG(TSI108_EC_TXERR, err);
> +
> +		if (err && net_ratelimit())
> +			printk(KERN_ERR "%s: TX error %x\n", dev->name, err);
> +	}
> +
> +	if (estat & (TSI108_EC_TXESTAT_Q0_DESCINT |  
> TSI108_EC_TXESTAT_Q0_EOQ)) {
> +		spin_lock(&data->txlock);
> +		tsi108_check_for_completed_tx(dev);
> +		spin_unlock(&data->txlock);
> +	}
> +}
> +
> +static irqreturn_t tsi108_irq_one(net_device * dev)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +	u32 stat = TSI108_ETH_READ_REG(TSI108_EC_INTSTAT);
> +
> +	if (!(stat & TSI108_INT_ANY))
> +		return IRQ_NONE;	/* Not our interrupt */
> +
> +	stat &= ~TSI108_ETH_READ_REG(TSI108_EC_INTMASK);
> +
> +	if (stat & (TSI108_INT_TXQUEUE0 | TSI108_INT_TXIDLE |
> +		    TSI108_INT_TXERROR))
> +		tsi108_tx_int(dev);
> +	if (stat & (TSI108_INT_RXQUEUE0 | TSI108_INT_RXTHRESH |
> +		    TSI108_INT_RXWAIT | TSI108_INT_RXOVERRUN |
> +		    TSI108_INT_RXERROR))
> +		tsi108_rx_int(dev);
> +
> +	if (stat & TSI108_INT_SFN) {
> +		if (net_ratelimit())
> +			printk(KERN_DEBUG "%s: SFN error\n", dev->name);
> +		TSI108_ETH_WRITE_REG(TSI108_EC_INTSTAT, TSI108_INT_SFN);
> +	}
> +
> +	if (stat & TSI108_INT_STATCARRY) {
> +		tsi108_stat_carry(dev);
> +		TSI108_ETH_WRITE_REG(TSI108_EC_INTSTAT, TSI108_INT_STATCARRY);
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t tsi108_irq(int irq, void *dev_id, struct  
> pt_regs *regs)
> +{
> +	if ((IRQ_TSI108_GIGE0 != irq) && (IRQ_TSI108_GIGE1 != irq))
> +		return IRQ_NONE;	/* Not our interrupt */
> +
> +	return tsi108_irq_one((struct net_device *)dev_id);
> +}
> +
> +static void tsi108_stop_ethernet(net_device * dev)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +
> +	/* Disable all TX and RX queues ... */
> +	TSI108_ETH_WRITE_REG(TSI108_EC_TXCTRL, 0);
> +	TSI108_ETH_WRITE_REG(TSI108_EC_RXCTRL, 0);
> +
> +	/* ...and wait for them to become idle */
> +	mb();
> +	while (TSI108_ETH_READ_REG(TSI108_EC_TXSTAT) &
> +	       TSI108_EC_TXSTAT_ACTIVE) ;
> +	while (TSI108_ETH_READ_REG(TSI108_EC_RXSTAT) &
> +	       TSI108_EC_RXSTAT_ACTIVE) ;
> +}
> +
> +static void tsi108_reset_ether(tsi108_prv_data * data)
> +{
> +	TSI108_ETH_WRITE_REG(TSI108_MAC_CFG1, TSI108_MAC_CFG1_SOFTRST);
> +	udelay(100);
> +	TSI108_ETH_WRITE_REG(TSI108_MAC_CFG1, 0);
> +
> +	TSI108_ETH_WRITE_REG(TSI108_EC_PORTCTRL,  
> TSI108_EC_PORTCTRL_STATRST);
> +	udelay(100);
> +	TSI108_ETH_WRITE_REG(TSI108_EC_PORTCTRL,
> +			     TSI108_ETH_READ_REG(TSI108_EC_PORTCTRL) &
> +			     ~TSI108_EC_PORTCTRL_STATRST);
> +
> +	TSI108_ETH_WRITE_REG(TSI108_EC_TXCFG, TSI108_EC_TXCFG_RST);
> +	udelay(100);
> +	TSI108_ETH_WRITE_REG(TSI108_EC_TXCFG,
> +			     TSI108_ETH_READ_REG(TSI108_EC_TXCFG) &
> +			     ~TSI108_EC_TXCFG_RST);
> +
> +	TSI108_ETH_WRITE_REG(TSI108_EC_RXCFG, TSI108_EC_RXCFG_RST);
> +	udelay(100);
> +	TSI108_ETH_WRITE_REG(TSI108_EC_RXCFG,
> +			     TSI108_ETH_READ_REG(TSI108_EC_RXCFG) &
> +			     ~TSI108_EC_RXCFG_RST);
> +
> +	TSI108_ETH_WRITE_REG(TSI108_MAC_MII_MGMT_CFG,
> +			     TSI108_ETH_READ_REG(TSI108_MAC_MII_MGMT_CFG) |
> +			     TSI108_MAC_MII_MGMT_RST);
> +	udelay(100);
> +	TSI108_ETH_WRITE_REG(TSI108_MAC_MII_MGMT_CFG,
> +			     TSI108_ETH_READ_REG(TSI108_MAC_MII_MGMT_CFG) &
> +			     ~(TSI108_MAC_MII_MGMT_RST |
> +			       TSI108_MAC_MII_MGMT_CLK));
> +
> +	TSI108_ETH_WRITE_REG(TSI108_MAC_MII_MGMT_CFG,
> +			     TSI108_ETH_READ_REG(TSI108_MAC_MII_MGMT_CFG) |
> +			     TSI108_MAC_MII_MGMT_CLK);
> +}
> +
> +static int tsi108_get_mac(net_device * dev)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +
> +	u32 word1 = TSI108_ETH_READ_REG(TSI108_MAC_ADDR1);
> +	u32 word2 = TSI108_ETH_READ_REG(TSI108_MAC_ADDR2);
> +
> +	/* Note that the octets are reversed from what the manual says,
> +	 * producing an even weirder ordering...
> +	 */
> +	if (word2 == 0 && word1 == 0) {
> +		dev->dev_addr[0] = 0x00;
> +		dev->dev_addr[1] = 0x06;
> +		dev->dev_addr[2] = 0xd2;
> +		dev->dev_addr[3] = 0x00;
> +		dev->dev_addr[4] = 0x00;
> +		if (0x8 == data->phy)
> +			dev->dev_addr[5] = 0x01;
> +		else
> +			dev->dev_addr[5] = 0x02;
> +
> +		word2 = (dev->dev_addr[0] << 16) | (dev->dev_addr[1] << 24);
> +
> +		word1 = (dev->dev_addr[2] << 0) | (dev->dev_addr[3] << 8) |
> +		    (dev->dev_addr[4] << 16) | (dev->dev_addr[5] << 24);
> +
> +		TSI108_ETH_WRITE_REG(TSI108_MAC_ADDR1, word1);
> +		TSI108_ETH_WRITE_REG(TSI108_MAC_ADDR2, word2);
> +	} else {
> +		dev->dev_addr[0] = (word2 >> 16) & 0xff;
> +		dev->dev_addr[1] = (word2 >> 24) & 0xff;
> +		dev->dev_addr[2] = (word1 >> 0) & 0xff;
> +		dev->dev_addr[3] = (word1 >> 8) & 0xff;
> +		dev->dev_addr[4] = (word1 >> 16) & 0xff;
> +		dev->dev_addr[5] = (word1 >> 24) & 0xff;
> +	}
> +
> +	if (!is_valid_ether_addr(dev->dev_addr)) {
> +		printk("KERN_ERR: word1: %08x, word2: %08x\n", word1, word2);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int tsi108_set_mac(net_device * dev, void *addr)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +	u32 word1, word2;
> +	int i;
> +
> +	if (!is_valid_ether_addr(addr))
> +		return -EINVAL;
> +
> +	for (i = 0; i < 6; i++)
> +		/* +2 is for the offset of the HW addr type */
> +		dev->dev_addr[i] = ((unsigned char *)addr)[i + 2];
> +
> +	word2 = (dev->dev_addr[0] << 16) | (dev->dev_addr[1] << 24);
> +
> +	word1 = (dev->dev_addr[2] << 0) | (dev->dev_addr[3] << 8) |
> +	    (dev->dev_addr[4] << 16) | (dev->dev_addr[5] << 24);
> +
> +	spin_lock_irq(&data->misclock);
> +	TSI108_ETH_WRITE_REG(TSI108_MAC_ADDR1, word1);
> +	TSI108_ETH_WRITE_REG(TSI108_MAC_ADDR2, word2);
> +	spin_lock(&data->txlock);
> +
> +	if (netif_queue_stopped(dev) && data->txfree && data->link_up)
> +		netif_wake_queue(dev);
> +
> +	spin_unlock(&data->txlock);
> +	spin_unlock_irq(&data->misclock);
> +	return 0;
> +}
> +
> +/* Protected by dev->xmit_lock. */
> +static void tsi108_set_rx_mode(net_device * dev)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +	u32 rxcfg = TSI108_ETH_READ_REG(TSI108_EC_RXCFG);
> +
> +	if (dev->flags & IFF_PROMISC) {
> +		rxcfg &= ~(TSI108_EC_RXCFG_UC_HASH | TSI108_EC_RXCFG_MC_HASH);
> +		rxcfg |= TSI108_EC_RXCFG_UFE | TSI108_EC_RXCFG_MFE;
> +		goto out;
> +	}
> +
> +	rxcfg &= ~(TSI108_EC_RXCFG_UFE | TSI108_EC_RXCFG_MFE);
> +
> +	if (dev->mc_count) {
> +		int i;
> +		struct dev_mc_list *mc = dev->mc_list;
> +		rxcfg |= TSI108_EC_RXCFG_MFE | TSI108_EC_RXCFG_MC_HASH;
> +
> +		memset(data->mc_hash, 0, sizeof(data->mc_hash));
> +
> +		while (mc) {
> +			u32 hash, crc;
> +
> +			if (mc->dmi_addrlen == 6) {
> +				crc = ether_crc(6, mc->dmi_addr);
> +				hash = crc >> 23;
> +
> +				__set_bit(hash, &data->mc_hash[0]);
> +			} else {
> +				printk(KERN_ERR
> +				       "%s: got multicast address of length %d "
> +				       "instead of 6.\n", dev->name,
> +				       mc->dmi_addrlen);
> +			}
> +
> +			mc = mc->next;
> +		}
> +
> +		TSI108_ETH_WRITE_REG(TSI108_EC_HASHADDR,
> +				     TSI108_EC_HASHADDR_AUTOINC |
> +				     TSI108_EC_HASHADDR_MCAST);
> +
> +		for (i = 0; i < 16; i++) {
> +			/* The manual says that the hardware may drop
> +			 * back-to-back writes to the data register.
> +			 */
> +			udelay(1);
> +			mb();
> +			TSI108_ETH_WRITE_REG(TSI108_EC_HASHDATA,
> +					     data->mc_hash[i]);
> +			mb();
> +		}
> +	}
> +
> +      out:
> +	mb();
> +	TSI108_ETH_WRITE_REG(TSI108_EC_RXCFG, rxcfg);
> +}
> +
> +static void tsi108_init_phy(net_device * dev)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +	u32 i = 0;
> +	u16 phyVal = 0;
> +
> +	spin_lock_irq(&phy_lock);
> +
> +	tsi108_write_mii(data, PHY_CTRL, PHY_CTRL_RESET);
> +	mb();
> +	while (tsi108_read_mii(data, PHY_CTRL, NULL) & PHY_CTRL_RESET) ;
> +
> +#if (TSI108_PHY_TYPE == PHY_BCM54XX)	/* Broadcom BCM54xx PHY */
> +	tsi108_write_mii(data, 0x09, 0x0300);
> +	tsi108_write_mii(data, 0x10, 0x1020);
> +	tsi108_write_mii(data, 0x1c, 0x8c00);
> +	mb();
> +#endif
> +
> +	tsi108_write_mii(data,
> +			 PHY_CTRL,
> +			 PHY_CTRL_AUTONEG_EN | PHY_CTRL_AUTONEG_START);
> +	mb();
> +	while (tsi108_read_mii(data, PHY_CTRL, NULL) &  
> PHY_CTRL_AUTONEG_START) ;
> +
> +	/* Set G/MII mode and receive clock select in TBI control #2.  The
> +	 * second port won't work if this isn't done, even though we don't
> +	 * use TBI mode.
> +	 */
> +
> +	tsi108_write_tbi(data, 0x11, 0x30);
> +
> +	/* FIXME: It seems to take more than 2 back-to-back reads to the
> +	 * PHY_STAT register before the link up status bit is set.
> +	 */
> +
> +	data->link_up = 1;
> +
> +	while (!((phyVal = tsi108_read_mii(data, PHY_STAT, NULL)) &
> +		 PHY_STAT_LINKUP)) {
> +		if (i++ > (MII_READ_DELAY / 10)) {
> +			data->link_up = 0;
> +			break;
> +		}
> +		mdelay(10);
> +	}
> +
> +	printk(KERN_DEBUG "PHY_STAT reg contains %08x\n", phyVal);
> +	data->phy_ok = 1;
> +	spin_unlock_irq(&phy_lock);
> +}
> +
> +static void tsi108_kill_phy(struct net_device *dev)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +
> +	spin_lock_irq(&phy_lock);
> +	tsi108_write_mii(data, PHY_CTRL, PHY_CTRL_POWERDOWN);
> +	data->phy_ok = 0;
> +	spin_unlock_irq(&phy_lock);
> +}
> +
> +static int tsi108_open(struct net_device *dev)
> +{
> +	int i;
> +	tsi108_prv_data *data = netdev_priv(dev);
> +	unsigned int rxring_size = TSI108_RXRING_LEN * sizeof(rx_desc);
> +	unsigned int txring_size = TSI108_TXRING_LEN * sizeof(tx_desc);
> +
> +	printk(KERN_DEBUG "Inside tsi108_open()!\n");
> +
> +	i = request_irq(data->irq_num, tsi108_irq, 0, dev->name, dev);
> +	if (i != 0) {
> +		printk(KERN_ERR "tsi108_eth%d: Could not allocate IRQ%d.\n",
> +		       data->irq_num % IRQ_TSI108_GIGE0, data->irq_num);
> +		return i;
> +	} else {
> +		dev->irq = data->irq_num;
> +		printk(KERN_NOTICE
> +		       "tsi108_open : Port %d Assigned IRQ %d to %s\n",
> +		       data->irq_num % IRQ_TSI108_GIGE0, dev->irq, dev->name);
> +	}
> +
> +	data->rxring = pci_alloc_consistent(NULL, rxring_size, &data- 
> >rxdma);
> +
> +	if (!data->rxring) {
> +		printk(KERN_DEBUG
> +		       "TSI108_ETH: failed to allocate memory for rxring!\n");
> +		return -ENOMEM;
> +	} else {
> +		memset(data->rxring, 0, rxring_size);
> +	}
> +
> +	data->txring = pci_alloc_consistent(NULL, txring_size, &data- 
> >txdma);
> +
> +	if (!data->txring) {
> +		printk(KERN_DEBUG
> +		       "TSI108_ETH: failed to allocate memory for txring!\n");
> +		pci_free_consistent(0, rxring_size, data->rxring, data->rxdma);
> +		return -ENOMEM;
> +	} else {
> +		memset(data->txring, 0, txring_size);
> +	}
> +
> +	for (i = 0; i < TSI108_RXRING_LEN; i++) {
> +		data->rxring[i].next0 = data->rxdma + (i + 1) * sizeof(rx_desc);
> +		data->rxring[i].blen = TSI108_RXBUF_SIZE;
> +		data->rxring[i].vlan = 0;
> +	}
> +
> +	data->rxring[TSI108_RXRING_LEN - 1].next0 = data->rxdma;
> +
> +	data->rxtail = 0;
> +	data->rxhead = 0;
> +
> +	for (i = 0; i < TSI108_RXRING_LEN; i++) {
> +		sk_buff *skb = dev_alloc_skb(TSI108_RXBUF_SIZE + NET_IP_ALIGN);
> +
> +		if (!skb) {
> +			/* Bah.  No memory for now, but maybe we'll get
> +			 * some more later.
> +			 * For now, we'll live with the smaller ring.
> +			 */
> +			printk(KERN_WARNING
> +			       "%s: Could only allocate %d receive skb(s).\n",
> +			       dev->name, i);
> +			data->rxhead = i;
> +			break;
> +		}
> +
> +		data->rxskbs[i] = skb;
> +		/* Align the payload on a 4-byte boundary */
> +		skb_reserve(skb, 2);
> +		data->rxskbs[i] = skb;
> +		data->rxring[i].buf0 = virt_to_phys(data->rxskbs[i]->data);
> +		data->rxring[i].misc = TSI108_RX_OWN | TSI108_RX_INT;
> +	}
> +
> +	data->rxfree = i;
> +	TSI108_ETH_WRITE_REG(TSI108_EC_RXQ_PTRLOW, data->rxdma);
> +
> +	for (i = 0; i < TSI108_TXRING_LEN; i++) {
> +		data->txring[i].next0 = data->txdma + (i + 1) * sizeof(tx_desc);
> +		data->txring[i].misc = 0;
> +	}
> +
> +	data->txring[TSI108_TXRING_LEN - 1].next0 = data->txdma;
> +	data->txtail = 0;
> +	data->txhead = 0;
> +	data->txfree = TSI108_TXRING_LEN;
> +	TSI108_ETH_WRITE_REG(TSI108_EC_TXQ_PTRLOW, data->txdma);
> +	tsi108_init_phy(dev);
> +
> +	init_timer(&data->timer);
> +	data->timer.expires = jiffies + 1;
> +	data->timer.data = (unsigned long)dev;
> +	data->timer.function = &tsi108_timed_checker;	/* timer handler */
> +	add_timer(&data->timer);
> +
> +	tsi108_restart_rx(data, dev);
> +
> +	TSI108_ETH_WRITE_REG(TSI108_EC_INTSTAT, ~0);
> +	mb();
> +
> +	TSI108_ETH_WRITE_REG(TSI108_EC_INTMASK,
> +			     ~(TSI108_INT_TXQUEUE0 | TSI108_INT_RXERROR |
> +			       TSI108_INT_RXTHRESH | TSI108_INT_RXQUEUE0 |
> +			       TSI108_INT_RXOVERRUN | TSI108_INT_RXWAIT |
> +			       TSI108_INT_SFN | TSI108_INT_STATCARRY));
> +
> +	TSI108_ETH_WRITE_REG(TSI108_MAC_CFG1,
> +			     TSI108_MAC_CFG1_RXEN | TSI108_MAC_CFG1_TXEN);
> +	netif_start_queue(dev);
> +	return 0;
> +}
> +
> +static int tsi108_close(net_device * dev)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +
> +	netif_stop_queue(dev);
> +
> +	del_timer_sync(&data->timer);
> +
> +	printk(KERN_DEBUG "Inside tsi108_ifdown!\n");
> +
> +	tsi108_stop_ethernet(dev);
> +	tsi108_kill_phy(dev);
> +	TSI108_ETH_WRITE_REG(TSI108_EC_INTMASK, ~0);
> +	TSI108_ETH_WRITE_REG(TSI108_MAC_CFG1, 0);
> +
> +	/* Check for any pending TX packets, and drop them. */
> +
> +	while (!data->txfree || data->txhead != data->txtail) {
> +		int tx = data->txtail;
> +		struct sk_buff *skb;
> +		skb = data->txskbs[tx];
> +		data->txtail = (data->txtail + 1) % TSI108_TXRING_LEN;
> +		data->txfree++;
> +		dev_kfree_skb(skb);
> +	}
> +
> +	synchronize_irq(data->irq_num);
> +	free_irq(data->irq_num, dev);
> +
> +	/* Discard the RX ring. */
> +
> +	while (data->rxfree) {
> +		int rx = data->rxtail;
> +		struct sk_buff *skb;
> +
> +		skb = data->rxskbs[rx];
> +		data->rxtail = (data->rxtail + 1) % TSI108_RXRING_LEN;
> +		data->rxfree--;
> +		dev_kfree_skb(skb);
> +	}
> +
> +	pci_free_consistent(0,
> +			    TSI108_RXRING_LEN * sizeof(rx_desc),
> +			    data->rxring, data->rxdma);
> +	pci_free_consistent(0,
> +			    TSI108_TXRING_LEN * sizeof(tx_desc),
> +			    data->txring, data->txdma);
> +
> +	return 0;
> +}
> +
> +static void tsi108_init_mac(net_device * dev)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +
> +	TSI108_ETH_WRITE_REG(TSI108_MAC_CFG2,  
> TSI108_MAC_CFG2_DFLT_PREAMBLE |
> +			     TSI108_MAC_CFG2_PADCRC);
> +
> +	TSI108_ETH_WRITE_REG(TSI108_EC_TXTHRESH,
> +			     (192 << TSI108_EC_TXTHRESH_STARTFILL) |
> +			     (192 << TSI108_EC_TXTHRESH_STOPFILL));
> +
> +	TSI108_ETH_WRITE_REG(TSI108_STAT_CARRYMASK1,
> +			     ~(TSI108_STAT_CARRY1_RXBYTES |
> +			       TSI108_STAT_CARRY1_RXPKTS |
> +			       TSI108_STAT_CARRY1_RXFCS |
> +			       TSI108_STAT_CARRY1_RXMCAST |
> +			       TSI108_STAT_CARRY1_RXALIGN |
> +			       TSI108_STAT_CARRY1_RXLENGTH |
> +			       TSI108_STAT_CARRY1_RXRUNT |
> +			       TSI108_STAT_CARRY1_RXJUMBO |
> +			       TSI108_STAT_CARRY1_RXFRAG |
> +			       TSI108_STAT_CARRY1_RXJABBER |
> +			       TSI108_STAT_CARRY1_RXDROP));
> +
> +	TSI108_ETH_WRITE_REG(TSI108_STAT_CARRYMASK2,
> +			     ~(TSI108_STAT_CARRY2_TXBYTES |
> +			       TSI108_STAT_CARRY2_TXPKTS |
> +			       TSI108_STAT_CARRY2_TXEXDEF |
> +			       TSI108_STAT_CARRY2_TXEXCOL |
> +			       TSI108_STAT_CARRY2_TXTCOL |
> +			       TSI108_STAT_CARRY2_TXPAUSE));
> +
> +	TSI108_ETH_WRITE_REG(TSI108_EC_PORTCTRL, TSI108_EC_PORTCTRL_STATEN);
> +	TSI108_ETH_WRITE_REG(TSI108_MAC_CFG1, 0);
> +
> +	TSI108_ETH_WRITE_REG(TSI108_EC_RXCFG,
> +			     TSI108_EC_RXCFG_SE | TSI108_EC_RXCFG_BFE);
> +
> +	TSI108_ETH_WRITE_REG(TSI108_EC_TXQ_CFG, TSI108_EC_TXQ_CFG_DESC_INT |
> +			     TSI108_EC_TXQ_CFG_EOQ_OWN_INT |
> +			     TSI108_EC_TXQ_CFG_WSWP | (TSI108_PBM_PORT <<
> +						       TSI108_EC_TXQ_CFG_SFNPORT));
> +
> +	TSI108_ETH_WRITE_REG(TSI108_EC_RXQ_CFG, TSI108_EC_RXQ_CFG_DESC_INT |
> +			     TSI108_EC_RXQ_CFG_EOQ_OWN_INT |
> +			     TSI108_EC_RXQ_CFG_WSWP | (TSI108_PBM_PORT <<
> +						       TSI108_EC_RXQ_CFG_SFNPORT));
> +
> +	TSI108_ETH_WRITE_REG(TSI108_EC_TXQ_BUFCFG,
> +			     TSI108_EC_TXQ_BUFCFG_BURST256 |
> +			     TSI108_EC_TXQ_BUFCFG_BSWP | (TSI108_PBM_PORT <<
> +							  TSI108_EC_TXQ_BUFCFG_SFNPORT));
> +
> +	TSI108_ETH_WRITE_REG(TSI108_EC_RXQ_BUFCFG,
> +			     TSI108_EC_RXQ_BUFCFG_BURST256 |
> +			     TSI108_EC_RXQ_BUFCFG_BSWP | (TSI108_PBM_PORT <<
> +							  TSI108_EC_RXQ_BUFCFG_SFNPORT));
> +
> +	TSI108_ETH_WRITE_REG(TSI108_EC_INTMASK, ~0);
> +}
> +
> +static int tsi108_ioctl(net_device * dev, struct ifreq *rq, int cmd)
> +{
> +	tsi108_prv_data *data = netdev_priv(dev);
> +	struct mii_ioctl_data *mii_data =
> +	    (struct mii_ioctl_data *)&rq->ifr_data;
> +	int ret;
> +
> +	switch (cmd) {
> +	case SIOCGMIIPHY:
> +		mii_data->phy_id = data->phy;
> +		ret = 0;
> +		break;
> +
> +	case SIOCGMIIREG:
> +		spin_lock_irq(&phy_lock);
> +		mii_data->val_out =
> +		    tsi108_read_mii(data, mii_data->reg_num, &ret);
> +		spin_unlock_irq(&phy_lock);
> +		break;
> +
> +	default:
> +		ret = -EOPNOTSUPP;
> +	}
> +
> +	return ret;
> +}
> +
> +static int
> +tsi108_init_one(unsigned long regs, unsigned long phyregs, u16  
> phy, u16 irq_num)
> +{
> +	net_device *dev = alloc_etherdev(sizeof(tsi108_prv_data));
> +	tsi108_prv_data *data;
> +	int ret;
> +
> +	if (!dev) {
> +		printk("tsi108_eth: Could not allocate a device structure\n");
> +		return -ENOMEM;
> +	}
> +
> +	data = netdev_priv(dev);
> +	memset(data, 0, sizeof(tsi108_prv_data));
> +
> +	data->regs = (volatile u32)regs;
> +	data->phyregs = (volatile u32)phyregs;
> +	data->phy = phy;
> +	data->irq_num = irq_num;
> +
> +	dev->open = tsi108_open;
> +	dev->stop = tsi108_close;
> +	dev->hard_start_xmit = tsi108_send_packet;
> +	dev->set_mac_address = tsi108_set_mac;
> +	dev->set_multicast_list = tsi108_set_rx_mode;
> +	dev->get_stats = tsi108_get_stats;
> +	dev->poll = tsi108_poll;
> +	dev->do_ioctl = tsi108_ioctl;
> +	dev->weight = 64;	/* 64 is more suitable for GigE interface -  
> klai */
> +
> +	/* Apparently, the Linux networking code won't use scatter-gather
> +	 * if the hardware doesn't do checksums.  However, it's faster
> +	 * to checksum in place and use SG, as (among other reasons)
> +	 * the cache won't be dirtied (which then has to be flushed
> +	 * before DMA).  The checksumming is done by the driver (via
> +	 * a new function skb_csum_dev() in net/core/skbuff.c).
> +	 */
> +
> +#ifdef FIXME_SG_CSUM_NOT_TESTED	/* FIXME: Not supported now. */
> +	dev->features = NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_HW_CSUM;
> +#else
> +	dev->features = NETIF_F_HIGHDMA;
> +#endif
> +	SET_MODULE_OWNER(dev);
> +
> +	spin_lock_init(&data->txlock);
> +	spin_lock_init(&data->misclock);
> +
> +	tsi108_reset_ether(data);
> +	tsi108_kill_phy(dev);
> +
> +	if (tsi108_get_mac(dev) != 0)
> +		printk(KERN_ERR "%s: Invalid MAC address.  Please correct.\n",
> +		       dev->name);
> +
> +	tsi108_init_mac(dev);
> +
> +	tsi108_devs[irq_num % IRQ_TSI108_GIGE0] = dev;
> +
> +	ret = register_netdev(dev);
> +	if (ret < 0) {
> +		kfree(dev);
> +		return ret;
> +	}
> +
> +	printk(KERN_INFO "%s: Tsi108 Gigabit Ethernet, MAC: "
> +	       "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
> +	       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
> +	       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
> +
> +	return 0;
> +}
> +
> +/* There's no way to either get interrupts from the PHY when
> + * something changes, or to have the Tsi108 automatically communicate
> + * with the PHY to reconfigure itself.
> + *
> + * Thus, we have to do it using a timer.
> + */
> +
> +static void tsi108_timed_checker(unsigned long dev_ptr)
> +{
> +	struct net_device *dev = (struct net_device *)dev_ptr;
> +	tsi108_prv_data *data = netdev_priv(dev);
> +
> +	tsi108_check_phy(dev);
> +	tsi108_check_rxring(dev);
> +	data->timer.expires = jiffies + CHECK_PHY_INTERVAL;
> +	add_timer(&data->timer);
> +}
> +
> +static int tsi108_ether_init(void)
> +{
> +	int ret;
> +	int dev_count = 0;
> +	int i;
> +
> +	hw_info_table[0].regs = (u32) ioremap(hw_info_table[0].regs, 0x400);
> +	hw_info_table[0].phyregs = hw_info_table[0].regs;
> +
> +	hw_info_table[1].regs = (u32) ioremap(hw_info_table[1].regs, 0x400);
> +	hw_info_table[1].phyregs = hw_info_table[0].regs;
> +
> +	for (i = 0; hw_info_table[i].regs != TBL_END; i++) {
> +		ret = tsi108_init_one(hw_info_table[i].regs,
> +				      hw_info_table[i].phyregs,
> +				      hw_info_table[i].phy,
> +				      hw_info_table[i].irq_num);
> +		if (ret < 0)
> +			printk("tsi108_ether_init: error initializing ethernet "
> +			       "device%d\n", i);
> +		else
> +			dev_count++;
> +	}
> +
> +	printk("tsi108_ether_init: found %d device(s)\n", dev_count);
> +
> +	return 0;
> +}
> +
> +static void tsi108_ether_exit(void)
> +{
> +	int i;
> +	net_device *dev;
> +
> +	for (i = 0; hw_info_table[i].regs != TBL_END; i++) {
> +		if ((dev = tsi108_devs[i]) != NULL) {
> +			unregister_netdev(dev);
> +			tsi108_stop_ethernet(dev);
> +			kfree(dev);
> +			tsi108_devs[i] = NULL;
> +		}
> +	}
> +}
> +
> +module_init(tsi108_ether_init);
> +module_exit(tsi108_ether_exit);
> +
> +MODULE_AUTHOR("Tundra Semiconductor Corporation");
> +MODULE_DESCRIPTION("Tsi108 Gigabit Ethernet driver");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/net/tsi108_eth.h b/drivers/net/tsi108_eth.h
> new file mode 100644
> index 0000000..cb54f92
> --- /dev/null
> +++ b/drivers/net/tsi108_eth.h
> @@ -0,0 +1,404 @@
> +/*
> + * (C) Copyright 2005 Tundra Semiconductor Corp.
> + * Kong Lai, <kong.lai@tundra.com).
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +/*
> + * net/tsi108_eth.h - definitions for Tsi108 GIGE network controller.
> + */
> +
> +#ifndef __TSI108_ETH_H
> +#define __TSI108_ETH_H
> +
> +#include <linux/config.h>
> +#include <linux/types.h>
> +
> +#define TSI108_ETH_WRITE_REG(offset, val) \
> +	out_be32((volatile u32 *)(data->regs + offset), val)
> +
> +#define TSI108_ETH_READ_REG(offset) \
> +	in_be32((volatile u32 *)(data->regs + offset))
> +
> +#define TSI108_ETH_WRITE_PHYREG(offset, val) \
> +	out_be32((volatile u32 *)(data->phyregs + offset), val)
> +
> +#define TSI108_ETH_READ_PHYREG(offset) \
> +	in_be32((volatile u32 *)(data->phyregs + offset))
> +
> +/*
> + * PHY Configuration Options
> + *
> + * NOTE: Enable set of definitions corresponding to your board type
> + */
> +#define PHY_MV88E	1	/* Marvel 88Exxxx PHY */
> +#define PHY_BCM54XX	2	/* Broardcom BCM54xx PHY */
> +#define TSI108_PHY_TYPE	PHY_MV88E
> +
> +/*
> + * TSI108 GIGE port registers
> + */
> +
> +#define TSI108_ETH_PORT_NUM		2
> +#define TSI108_PBM_PORT			2
> +#define TSI108_SDRAM_PORT		4
> +
> +#define TSI108_MAC_CFG1			(0x000)
> +#define TSI108_MAC_CFG1_SOFTRST		(1 << 31)
> +#define TSI108_MAC_CFG1_LOOPBACK	(1 << 8)
> +#define TSI108_MAC_CFG1_RXEN		(1 << 2)
> +#define TSI108_MAC_CFG1_TXEN		(1 << 0)
> +
> +#define TSI108_MAC_CFG2			(0x004)
> +#define TSI108_MAC_CFG2_DFLT_PREAMBLE	(7 << 12)
> +#define TSI108_MAC_CFG2_IFACE_MASK	(3 << 8)
> +#define TSI108_MAC_CFG2_NOGIG		(1 << 8)
> +#define TSI108_MAC_CFG2_GIG		(2 << 8)
> +#define TSI108_MAC_CFG2_PADCRC		(1 << 2)
> +#define TSI108_MAC_CFG2_FULLDUPLEX	(1 << 0)
> +
> +#define TSI108_MAC_MII_MGMT_CFG		(0x020)
> +#define TSI108_MAC_MII_MGMT_CLK		(7 << 0)
> +#define TSI108_MAC_MII_MGMT_RST		(1 << 31)
> +
> +#define TSI108_MAC_MII_CMD		(0x024)
> +#define TSI108_MAC_MII_CMD_READ		(1 << 0)
> +
> +#define TSI108_MAC_MII_ADDR		(0x028)
> +#define TSI108_MAC_MII_ADDR_REG		0
> +#define TSI108_MAC_MII_ADDR_PHY		8
> +
> +#define TSI108_MAC_MII_DATAOUT		(0x02c)
> +#define TSI108_MAC_MII_DATAIN		(0x030)
> +
> +#define TSI108_MAC_MII_IND		(0x034)
> +#define TSI108_MAC_MII_IND_NOTVALID	(1 << 2)
> +#define TSI108_MAC_MII_IND_SCANNING	(1 << 1)
> +#define TSI108_MAC_MII_IND_BUSY		(1 << 0)
> +
> +#define TSI108_MAC_IFCTRL		(0x038)
> +#define TSI108_MAC_IFCTRL_PHYMODE	(1 << 24)
> +
> +#define TSI108_MAC_ADDR1		(0x040)
> +#define TSI108_MAC_ADDR2		(0x044)
> +
> +#define TSI108_STAT_RXBYTES		(0x06c)
> +#define TSI108_STAT_RXBYTES_CARRY	(1 << 24)
> +
> +#define TSI108_STAT_RXPKTS		(0x070)
> +#define TSI108_STAT_RXPKTS_CARRY	(1 << 18)
> +
> +#define TSI108_STAT_RXFCS		(0x074)
> +#define TSI108_STAT_RXFCS_CARRY		(1 << 12)
> +
> +#define TSI108_STAT_RXMCAST		(0x078)
> +#define TSI108_STAT_RXMCAST_CARRY	(1 << 18)
> +
> +#define TSI108_STAT_RXALIGN		(0x08c)
> +#define TSI108_STAT_RXALIGN_CARRY	(1 << 12)
> +
> +#define TSI108_STAT_RXLENGTH		(0x090)
> +#define TSI108_STAT_RXLENGTH_CARRY	(1 << 12)
> +
> +#define TSI108_STAT_RXRUNT		(0x09c)
> +#define TSI108_STAT_RXRUNT_CARRY	(1 << 12)
> +
> +#define TSI108_STAT_RXJUMBO		(0x0a0)
> +#define TSI108_STAT_RXJUMBO_CARRY	(1 << 12)
> +
> +#define TSI108_STAT_RXFRAG		(0x0a4)
> +#define TSI108_STAT_RXFRAG_CARRY	(1 << 12)
> +
> +#define TSI108_STAT_RXJABBER		(0x0a8)
> +#define TSI108_STAT_RXJABBER_CARRY	(1 << 12)
> +
> +#define TSI108_STAT_RXDROP		(0x0ac)
> +#define TSI108_STAT_RXDROP_CARRY	(1 << 12)
> +
> +#define TSI108_STAT_TXBYTES		(0x0b0)
> +#define TSI108_STAT_TXBYTES_CARRY	(1 << 24)
> +
> +#define TSI108_STAT_TXPKTS		(0x0b4)
> +#define TSI108_STAT_TXPKTS_CARRY	(1 << 18)
> +
> +#define TSI108_STAT_TXEXDEF		(0x0c8)
> +#define TSI108_STAT_TXEXDEF_CARRY	(1 << 12)
> +
> +#define TSI108_STAT_TXEXCOL		(0x0d8)
> +#define TSI108_STAT_TXEXCOL_CARRY	(1 << 12)
> +
> +#define TSI108_STAT_TXTCOL		(0x0dc)
> +#define TSI108_STAT_TXTCOL_CARRY	(1 << 13)
> +
> +#define TSI108_STAT_TXPAUSEDROP		(0x0e4)
> +#define TSI108_STAT_TXPAUSEDROP_CARRY	(1 << 12)
> +
> +#define TSI108_STAT_CARRY1		(0x100)
> +#define TSI108_STAT_CARRY1_RXBYTES	(1 << 16)
> +#define TSI108_STAT_CARRY1_RXPKTS	(1 << 15)
> +#define TSI108_STAT_CARRY1_RXFCS	(1 << 14)
> +#define TSI108_STAT_CARRY1_RXMCAST	(1 << 13)
> +#define TSI108_STAT_CARRY1_RXALIGN	(1 << 8)
> +#define TSI108_STAT_CARRY1_RXLENGTH	(1 << 7)
> +#define TSI108_STAT_CARRY1_RXRUNT	(1 << 4)
> +#define TSI108_STAT_CARRY1_RXJUMBO	(1 << 3)
> +#define TSI108_STAT_CARRY1_RXFRAG	(1 << 2)
> +#define TSI108_STAT_CARRY1_RXJABBER	(1 << 1)
> +#define TSI108_STAT_CARRY1_RXDROP	(1 << 0)
> +
> +#define TSI108_STAT_CARRY2		(0x104)
> +#define TSI108_STAT_CARRY2_TXBYTES	(1 << 13)
> +#define TSI108_STAT_CARRY2_TXPKTS	(1 << 12)
> +#define TSI108_STAT_CARRY2_TXEXDEF	(1 << 7)
> +#define TSI108_STAT_CARRY2_TXEXCOL	(1 << 3)
> +#define TSI108_STAT_CARRY2_TXTCOL	(1 << 2)
> +#define TSI108_STAT_CARRY2_TXPAUSE	(1 << 0)
> +
> +#define TSI108_STAT_CARRYMASK1		(0x108)
> +#define TSI108_STAT_CARRYMASK2		(0x10c)
> +
> +#define TSI108_EC_PORTCTRL		(0x200)
> +#define TSI108_EC_PORTCTRL_STATRST	(1 << 31)
> +#define TSI108_EC_PORTCTRL_STATEN	(1 << 28)
> +#define TSI108_EC_PORTCTRL_NOGIG	(1 << 18)
> +#define TSI108_EC_PORTCTRL_HALFDUPLEX	(1 << 16)
> +
> +#define TSI108_EC_INTSTAT		(0x204)
> +#define TSI108_EC_INTMASK		(0x208)
> +
> +#define TSI108_INT_ANY			(1 << 31)
> +#define TSI108_INT_SFN			(1 << 30)
> +#define TSI108_INT_RXIDLE		(1 << 29)
> +#define TSI108_INT_RXABORT		(1 << 28)
> +#define TSI108_INT_RXERROR		(1 << 27)
> +#define TSI108_INT_RXOVERRUN		(1 << 26)
> +#define TSI108_INT_RXTHRESH		(1 << 25)
> +#define TSI108_INT_RXWAIT		(1 << 24)
> +#define TSI108_INT_RXQUEUE0		(1 << 16)
> +#define TSI108_INT_STATCARRY		(1 << 15)
> +#define TSI108_INT_TXIDLE		(1 << 13)
> +#define TSI108_INT_TXABORT		(1 << 12)
> +#define TSI108_INT_TXERROR		(1 << 11)
> +#define TSI108_INT_TXUNDERRUN		(1 << 10)
> +#define TSI108_INT_TXTHRESH		(1 <<  9)
> +#define TSI108_INT_TXWAIT		(1 <<  8)
> +#define TSI108_INT_TXQUEUE0		(1 <<  0)
> +
> +#define TSI108_EC_TXCFG			(0x220)
> +#define TSI108_EC_TXCFG_RST		(1 << 31)
> +
> +#define TSI108_EC_TXCTRL		(0x224)
> +#define TSI108_EC_TXCTRL_IDLEINT	(1 << 31)
> +#define TSI108_EC_TXCTRL_ABORT		(1 << 30)
> +#define TSI108_EC_TXCTRL_GO		(1 << 15)
> +#define TSI108_EC_TXCTRL_QUEUE0		(1 <<  0)
> +
> +#define TSI108_EC_TXSTAT		(0x228)
> +#define TSI108_EC_TXSTAT_ACTIVE		(1 << 15)
> +#define TSI108_EC_TXSTAT_QUEUE0		(1 << 0)
> +
> +#define TSI108_EC_TXESTAT		(0x22c)
> +#define TSI108_EC_TXESTAT_Q0_ERR	(1 << 24)
> +#define TSI108_EC_TXESTAT_Q0_DESCINT	(1 << 16)
> +#define TSI108_EC_TXESTAT_Q0_EOF	(1 <<  8)
> +#define TSI108_EC_TXESTAT_Q0_EOQ	(1 <<  0)
> +
> +#define TSI108_EC_TXERR			(0x278)
> +
> +#define TSI108_EC_TXQ_CFG		(0x280)
> +#define TSI108_EC_TXQ_CFG_DESC_INT	(1 << 20)
> +#define TSI108_EC_TXQ_CFG_EOQ_OWN_INT	(1 << 19)
> +#define TSI108_EC_TXQ_CFG_WSWP		(1 << 11)
> +#define TSI108_EC_TXQ_CFG_BSWP		(1 << 10)
> +#define TSI108_EC_TXQ_CFG_SFNPORT	0
> +
> +#define TSI108_EC_TXQ_BUFCFG		(0x284)
> +#define TSI108_EC_TXQ_BUFCFG_BURST8	(0 << 8)
> +#define TSI108_EC_TXQ_BUFCFG_BURST32	(1 << 8)
> +#define TSI108_EC_TXQ_BUFCFG_BURST128	(2 << 8)
> +#define TSI108_EC_TXQ_BUFCFG_BURST256	(3 << 8)
> +#define TSI108_EC_TXQ_BUFCFG_WSWP	(1 << 11)
> +#define TSI108_EC_TXQ_BUFCFG_BSWP	(1 << 10)
> +#define TSI108_EC_TXQ_BUFCFG_SFNPORT	0
> +
> +#define TSI108_EC_TXQ_PTRLOW		(0x288)
> +
> +#define TSI108_EC_TXQ_PTRHIGH		(0x28c)
> +#define TSI108_EC_TXQ_PTRHIGH_VALID	(1 << 31)
> +
> +#define TSI108_EC_TXTHRESH		(0x230)
> +#define TSI108_EC_TXTHRESH_STARTFILL	0
> +#define TSI108_EC_TXTHRESH_STOPFILL	16
> +
> +#define TSI108_EC_RXCFG			(0x320)
> +#define TSI108_EC_RXCFG_RST		(1 << 31)
> +
> +#define TSI108_EC_RXSTAT		(0x328)
> +#define TSI108_EC_RXSTAT_ACTIVE		(1 << 15)
> +#define TSI108_EC_RXSTAT_QUEUE0		(1 << 0)
> +
> +#define TSI108_EC_RXESTAT		(0x32c)
> +#define TSI108_EC_RXESTAT_Q0_ERR	(1 << 24)
> +#define TSI108_EC_RXESTAT_Q0_DESCINT	(1 << 16)
> +#define TSI108_EC_RXESTAT_Q0_EOF	(1 <<  8)
> +#define TSI108_EC_RXESTAT_Q0_EOQ	(1 <<  0)
> +
> +#define TSI108_EC_HASHADDR		(0x360)
> +#define TSI108_EC_HASHADDR_AUTOINC	(1 << 31)
> +#define TSI108_EC_HASHADDR_DO1STREAD	(1 << 30)
> +#define TSI108_EC_HASHADDR_UNICAST	(0 <<  4)
> +#define TSI108_EC_HASHADDR_MCAST	(1 <<  4)
> +
> +#define TSI108_EC_HASHDATA		(0x364)
> +
> +#define TSI108_EC_RXQ_PTRLOW		(0x388)
> +
> +#define TSI108_EC_RXQ_PTRHIGH		(0x38c)
> +#define TSI108_EC_RXQ_PTRHIGH_VALID	(1 << 31)
> +
> +/* Station Enable -- accept packets destined for us */
> +#define TSI108_EC_RXCFG_SE		(1 << 13)
> +/* Unicast Frame Enable -- for packets not destined for us */
> +#define TSI108_EC_RXCFG_UFE		(1 << 12)
> +/* Multicast Frame Enable */
> +#define TSI108_EC_RXCFG_MFE		(1 << 11)
> +/* Broadcast Frame Enable */
> +#define TSI108_EC_RXCFG_BFE		(1 << 10)
> +#define TSI108_EC_RXCFG_UC_HASH		(1 <<  9)
> +#define TSI108_EC_RXCFG_MC_HASH		(1 <<  8)
> +
> +#define TSI108_EC_RXQ_CFG		(0x380)
> +#define TSI108_EC_RXQ_CFG_DESC_INT	(1 << 20)
> +#define TSI108_EC_RXQ_CFG_EOQ_OWN_INT	(1 << 19)
> +#define TSI108_EC_RXQ_CFG_WSWP		(1 << 11)
> +#define TSI108_EC_RXQ_CFG_BSWP		(1 << 10)
> +#define TSI108_EC_RXQ_CFG_SFNPORT	0
> +
> +#define TSI108_EC_RXQ_BUFCFG		(0x384)
> +#define TSI108_EC_RXQ_BUFCFG_BURST8	(0 << 8)
> +#define TSI108_EC_RXQ_BUFCFG_BURST32	(1 << 8)
> +#define TSI108_EC_RXQ_BUFCFG_BURST128	(2 << 8)
> +#define TSI108_EC_RXQ_BUFCFG_BURST256	(3 << 8)
> +#define TSI108_EC_RXQ_BUFCFG_WSWP	(1 << 11)
> +#define TSI108_EC_RXQ_BUFCFG_BSWP	(1 << 10)
> +#define TSI108_EC_RXQ_BUFCFG_SFNPORT	0
> +
> +#define TSI108_EC_RXCTRL		(0x324)
> +#define TSI108_EC_RXCTRL_ABORT		(1 << 30)
> +#define TSI108_EC_RXCTRL_GO		(1 << 15)
> +#define TSI108_EC_RXCTRL_QUEUE0		(1 << 0)
> +
> +#define TSI108_EC_RXERR			(0x378)
> +
> +#define PHY_CTRL			0
> +#define PHY_CTRL_RESET			(1 << 15)
> +#define PHY_CTRL_AUTONEG_EN		(1 << 12)
> +#define PHY_CTRL_POWERDOWN		(1 << 11)
> +#define PHY_CTRL_AUTONEG_START		(1 << 9)
> +
> +#define PHY_STAT			1
> +#define PHY_STAT_LINKUP			(1 << 2)
> +
> +#if (TSI108_PHY_TYPE == PHY_MV88E)
> +/* Marvel 88E1xxx-specific */
> +#define PHY_SUM_STAT			0x11
> +#define PHY_SUM_STAT_SPEED_MASK		(3 << 14)
> +#define PHY_SUM_STAT_SPEED_10		(0 << 14)
> +#define PHY_SUM_STAT_SPEED_100		(1 << 14)
> +#define PHY_SUM_STAT_SPEED_1000		(2 << 14)
> +#define PHY_SUM_STAT_FULLDUPLEX		(1 << 13)
> +
> +#define PHY_SUM_STAT_1000T_FD    (PHY_SUM_STAT_SPEED_1000 |  
> PHY_SUM_STAT_FULLDUPLEX)
> +#define PHY_SUM_STAT_1000T_HD    (PHY_SUM_STAT_SPEED_1000)
> +#define PHY_SUM_STAT_100TX_FD    (PHY_SUM_STAT_SPEED_100 |  
> PHY_SUM_STAT_FULLDUPLEX)
> +#define PHY_SUM_STAT_100TX_HD    (PHY_SUM_STAT_SPEED_100)
> +#define PHY_SUM_STAT_10T_FD	    (PHY_SUM_STAT_SPEED_10 |  
> PHY_SUM_STAT_FULLDUPLEX)
> +#define PHY_SUM_STAT_10T_HD	    (PHY_SUM_STAT_SPEED_10)
> +#elif (TSI108_PHY_TYPE == PHY_BCM54XX)
> +/*Broadcom BCM54xx */
> +#define PHY_SUM_STAT			0x19
> +#define PHY_SUM_STAT_SPEED_MASK		(7 << 8)	/* Auto Negotiation HCD */
> +#define PHY_SUM_STAT_1000T_FD		(7 << 8)	/* 1000BASE-T Full-Duplex */
> +#define PHY_SUM_STAT_1000T_HD		(6 << 8)	/* 1000BASE-T Half-Duplex */
> +#define PHY_SUM_STAT_100TX_FD		(5 << 8)	/* 100BASE-TX Full-Duplex */
> +#define PHY_SUM_STAT_100T4		(4 << 8)	/* 100BASE-T4 */
> +#define PHY_SUM_STAT_100TX_HD		(3 << 8)	/* 100BASE-TX Half-Duplex */
> +#define PHY_SUM_STAT_10T_FD		(2 << 8)	/* 10BASE-T Full-Duplex */
> +#define PHY_SUM_STAT_10T_HD		(1 << 8)	/* 10BASE-T Half-Duplex */
> +#define PHY_SUM_STAT_AN_FAIL		(0 << 8)	/* 1000BASE-T Half-Duplex */
> +#else
> +#error "PHY Device not specified"
> +#endif				/* MV88_PHY */
> +
> +#define TSI108_TX_EOF	(1 << 0)	/* End of frame; last fragment of  
> packet */
> +#define TSI108_TX_SOF	(1 << 1)	/* Start of frame; first frag. of  
> packet */
> +#define TSI108_TX_VLAN	(1 << 2)	/* Per-frame VLAN: enables VLAN  
> override */
> +#define TSI108_TX_HUGE	(1 << 3)	/* Huge frame enable */
> +#define TSI108_TX_PAD	(1 << 4)	/* Pad the packet if too short */
> +#define TSI108_TX_CRC	(1 << 5)	/* Generate CRC for this packet */
> +#define TSI108_TX_INT	(1 << 14)	/* Generate an IRQ after frag.  
> processed */
> +#define TSI108_TX_RETRY	16	/* 4 bit field indicating num. of  
> retries */
> +#define TSI108_TX_COL	(1 << 20)	/* Set if a collision occured */
> +#define TSI108_TX_LCOL	(1 << 24)	/* Set if a late collision  
> occured */
> +#define TSI108_TX_UNDER	(1 << 25)	/* Set if a FIFO underrun  
> occured */
> +#define TSI108_TX_RLIM	(1 << 26)	/* Set if the retry limit was  
> reached */
> +#define TSI108_TX_OK	(1 << 30)	/* Set if the frame TX was  
> successful */
> +#define TSI108_TX_OWN	(1 << 31)	/* Set if the device owns the  
> descriptor */
> +
> +/* Note: the descriptor layouts assume big-endian byte order. */
> +typedef struct {
> +	u32 buf0;
> +	u32 buf1;		/* Base address of buffer */
> +	u32 next0;		/* Address of next descriptor, if any */
> +	u32 next1;
> +	u16 vlan;		/* VLAN, if override enabled for this packet */
> +	u16 len;		/* Length of buffer in bytes */
> +	u32 misc;		/* See TSI108_TX_* above */
> +	u32 reserved0;		/*reserved0 and reserved1 are added to make the  
> desc */
> +	u32 reserved1;		/* 32-byte aligned */
> +} __attribute__ ((aligned(32))) tx_desc;
> +
> +#define TSI108_RX_EOF	(1 << 0)	/* End of frame; last fragment of  
> packet */
> +#define TSI108_RX_SOF	(1 << 1)	/* Start of frame; first frag. of  
> packet */
> +#define TSI108_RX_VLAN	(1 << 2)	/* Set on SOF if packet has a VLAN */
> +#define TSI108_RX_FTYPE	(1 << 3)	/* Length/Type field is type, not  
> length */
> +#define TSI108_RX_RUNT	(1 << 4)/* Packet is less than minimum size */
> +#define TSI108_RX_HASH	(1 << 7)/* Hash table match */
> +#define TSI108_RX_BAD	(1 << 8)	/* Bad frame */
> +#define TSI108_RX_OVER	(1 << 9)	/* FIFO overrun occured */
> +#define TSI108_RX_TRUNC	(1 << 11)	/* Packet truncated due to  
> excess length */
> +#define TSI108_RX_CRC	(1 << 12)	/* Packet had a CRC error */
> +#define TSI108_RX_INT	(1 << 13)	/* Generate an IRQ after frag.  
> processed */
> +#define TSI108_RX_OWN	(1 << 15)	/* Set if the device owns the  
> descriptor */
> +
> +typedef struct {
> +	u32 buf0;		/* Base address of buffer */
> +	u32 buf1;		/* Base address of buffer */
> +	u32 next0;		/* Address of next descriptor, if any */
> +	u32 next1;		/* Address of next descriptor, if any */
> +	u16 vlan;		/* VLAN of received packet, first frag only */
> +	u16 len;		/* Length of received fragment in bytes */
> +	u16 blen;		/* Length of buffer in bytes */
> +	u16 misc;		/* See TSI108_RX_* above */
> +	u32 reserved0;		/* reserved0 and reserved1 are added to make the  
> desc */
> +	u32 reserved1;		/* 32-byte aligned */
> +} __attribute__ ((aligned(32))) rx_desc;
> +
> +#endif				/* __TSI108_ETH_H */
> -- 
> 1.3.0
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [PATCH/2.6.17-rc4 8/10]  Add  tsi108 8250 serial support
From: Kumar Gala @ 2006-05-17 13:26 UTC (permalink / raw)
  To: Zang Roy-r61911
  Cc: linuxppc-dev list, Yang Xin-Xin-r48390, Paul Mackerras,
	Alexandre.Bounine
In-Reply-To: <9FCDBA58F226D911B202000BDBAD46730626D625@zch01exm40.ap.freescale.net>


On May 17, 2006, at 5:14 AM, Zang Roy-r61911 wrote:

> This patch contains changes to the serial device driver specific  
> for integrated
> serial port in Tsi108 Host Bridge.
>
> Signed-off-by: Alexandre Bounine <alexandreb@tundra.com>
> Signed-off-by: Roy Zang	<tie-fei.zang@freescale.com>
>
>> From nobody Mon Sep 17 00:00:00 2001
> From: roy zang <tie-fei.zang@freescale.com>
> Date: Tue May 16 15:26:02 2006 +0800
> Subject: [PATCH] Add tsi108 serial support

This patch needs to go to Russell King as uart/8250 driver maintainer.

- kumar

>
> ---
>
>  drivers/serial/8250.c |   17 +++++++++++++++++
>  1 files changed, 17 insertions(+), 0 deletions(-)
>
> 6cb950357e9970afa671d59f172dbc4b03f11560
> diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
> index bbf78aa..c12f516 100644
> --- a/drivers/serial/8250.c
> +++ b/drivers/serial/8250.c
> @@ -723,7 +723,9 @@ static int broken_efr(struct uart_8250_p
>  static void autoconfig_16550a(struct uart_8250_port *up)
>  {
>  	unsigned char status1, status2;
> +#ifndef CONFIG_TSI108_BRIDGE
>  	unsigned int iersave;
> +#endif
>
>  	up->port.type = PORT_16550A;
>  	up->capabilities |= UART_CAP_FIFO;
> @@ -833,6 +835,7 @@ static void autoconfig_16550a(struct uar
>  	 * trying to write and read a 1 just to make sure it's not
>  	 * already a 1 and maybe locked there before we even start start.
>  	 */
> +#ifndef CONFIG_TSI108_BRIDGE
>  	iersave = serial_in(up, UART_IER);
>  	serial_outp(up, UART_IER, iersave & ~UART_IER_UUE);
>  	if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
> @@ -859,6 +862,7 @@ static void autoconfig_16550a(struct uar
>  		DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
>  	}
>  	serial_outp(up, UART_IER, iersave);
> +#endif
>  }
>
>  /*
> @@ -1348,7 +1352,12 @@ static irqreturn_t serial8250_interrupt(
>
>  		up = list_entry(l, struct uart_8250_port, list);
>
> +#ifdef CONFIG_TSI108_BRIDGE /* for TSI108_REV_Z1 errata U2 */
> +		/* read IIR as part of 32-bit word */
> +		iir = (in_be32((u32 *)(up->port.membase + UART_RX)) >> 8) & 0xff;
> +#else
>  		iir = serial_in(up, UART_IIR);
> +#endif
>  		if (!(iir & UART_IIR_NO_INT)) {
>  			serial8250_handle_port(up, regs);
>
> @@ -1529,7 +1538,9 @@ static int serial8250_startup(struct uar
>  {
>  	struct uart_8250_port *up = (struct uart_8250_port *)port;
>  	unsigned long flags;
> +#ifndef CONFIG_TSI108_BRIDGE
>  	unsigned char lsr, iir;
> +#endif
>  	int retval;
>
>  	up->capabilities = uart_config[up->port.type].flags;
> @@ -1567,7 +1578,9 @@ #endif
>  	 */
>  	(void) serial_inp(up, UART_LSR);
>  	(void) serial_inp(up, UART_RX);
> +#ifndef CONFIG_TSI108_BRIDGE /* for TSI108_REV_Z1 errata U2 */
>  	(void) serial_inp(up, UART_IIR);
> +#endif
>  	(void) serial_inp(up, UART_MSR);
>
>  	/*
> @@ -1634,6 +1647,7 @@ #endif
>
>  	serial8250_set_mctrl(&up->port, up->port.mctrl);
>
> +#ifndef CONFIG_TSI108_BRIDGE
>  	/*
>  	 * Do a quick test to see if we receive an
>  	 * interrupt when we enable the TX irq.
> @@ -1652,6 +1666,7 @@ #endif
>  	} else {
>  		up->bugs &= ~UART_BUG_TXEN;
>  	}
> +#endif
>
>  	spin_unlock_irqrestore(&up->port.lock, flags);
>
> @@ -1678,7 +1693,9 @@ #endif
>  	 */
>  	(void) serial_inp(up, UART_LSR);
>  	(void) serial_inp(up, UART_RX);
> +#ifndef CONFIG_TSI108_BRIDGE /* for TSI108_REV_Z1 errata U2 */
>  	(void) serial_inp(up, UART_IIR);
> +#endif
>  	(void) serial_inp(up, UART_MSR);
>
>  	return 0;
> -- 
> 1.3.0
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [PATCH/2.6.17-rc4 10/10] bugs fix for marvell SATA on powerpc pl atform
From: Kumar Gala @ 2006-05-17 13:27 UTC (permalink / raw)
  To: Zang Roy-r61911
  Cc: linuxppc-dev list, Yang Xin-Xin-r48390, Paul Mackerras,
	Alexandre.Bounine
In-Reply-To: <9FCDBA58F226D911B202000BDBAD46730626D628@zch01exm40.ap.freescale.net>


On May 17, 2006, at 5:14 AM, Zang Roy-r61911 wrote:

> Fix Marvell SATA driver bugs on PowerPC platform:
> SATA device can't work for the problem on little-endian mode.
> U-Boot can't find SATA device after kernel reboots.
>
> Signed-off-by: Hongjun cheng	<hong-jun.chen@reescale.com>
> Signed-off-by: Roy Zang		<tie-fei.zang@freescale.com>
>
>> From nobody Mon Sep 17 00:00:00 2001
> From: roy zang <tie-fei.zang@freescale.com>
> Date: Tue May 16 15:25:23 2006 +0800
> Subject: [PATCH] Fix bugs on powerpc platform for mv sata driver

This needs to go to Jeff Garzik as SATA driver maintainer.

- kumar

>
>  drivers/scsi/sata_mv.c |   10 +++++++++-
>  1 files changed, 9 insertions(+), 1 deletions(-)
>
> d82ac19d259f8487a31105eaf844a93cbd9008e8
> diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
> index d5fdcb9..4166422 100644
> --- a/drivers/scsi/sata_mv.c
> +++ b/drivers/scsi/sata_mv.c
> @@ -1032,6 +1032,9 @@ static inline void mv_crqb_pack_cmd(u16
>  {
>  	*cmdw = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
>  		(last ? CRQB_CMD_LAST : 0);
> +#ifdef CONFIG_PPC
> +	*cmdw = cpu_to_le16(*cmdw);
> +#endif
>  }
>
>  /**
> @@ -1567,13 +1570,18 @@ static void mv5_read_preamp(struct mv_ho
>  static void mv5_enable_leds(struct mv_host_priv *hpriv, void  
> __iomem *mmio)
>  {
>  	u32 tmp;
> -
> +#ifndef CONFIG_PPC
>  	writel(0, mmio + MV_GPIO_PORT_CTL);
> +#endif
>
>  	/* FIXME: handle MV_HP_ERRATA_50XXB2 errata */
>
>  	tmp = readl(mmio + MV_PCI_EXP_ROM_BAR_CTL);
> +#ifdef CONFIG_PPC
> +	tmp &= ~(1 << 0);
> +#else	
>  	tmp |= ~(1 << 0);
> +#endif
>  	writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
>  }
>
> -- 
> 1.3.0
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [PATCH/2.6.17-rc4 1/10] Powerpc: Add general support for mpc7448h pc2 (Taiga) platform
From: Kumar Gala @ 2006-05-17 13:45 UTC (permalink / raw)
  To: Zang Roy-r61911
  Cc: linuxppc-dev list, Yang Xin-Xin-r48390, Paul Mackerras,
	Alexandre.Bounine
In-Reply-To: <9FCDBA58F226D911B202000BDBAD46730626D619@zch01exm40.ap.freescale.net>


On May 17, 2006, at 5:13 AM, Zang Roy-r61911 wrote:

> Add support for Freescale mpcc7448 (Taiga) board support
>
> Signed-off-by: Roy Zang  <tie-fei.zang@freescale.com>
>
> ---
>
>  arch/powerpc/Kconfig                       |   24 +++
>  arch/powerpc/kernel/legacy_serial.c        |   39 ++++

These board port should live in platforms/embedded6xx.

>  arch/powerpc/platforms/74xx/Makefile       |    4
>  arch/powerpc/platforms/74xx/misc.c         |   38 ++++
>  arch/powerpc/platforms/74xx/mpc7448_hpc2.c |  257 +++++++++++++++++ 
> +++++++++++
>  arch/powerpc/platforms/74xx/mpc7448_hpc2.h |   80 +++++++++
>  arch/powerpc/platforms/74xx/pci.c          |  103 +++++++++++
>  arch/powerpc/platforms/Makefile            |    1
>  8 files changed, 545 insertions(+), 1 deletions(-)
>  create mode 100644 arch/powerpc/platforms/74xx/Makefile
>  create mode 100644 arch/powerpc/platforms/74xx/misc.c
>  create mode 100644 arch/powerpc/platforms/74xx/mpc7448_hpc2.c
>  create mode 100644 arch/powerpc/platforms/74xx/mpc7448_hpc2.h
>  create mode 100644 arch/powerpc/platforms/74xx/pci.c
>
> 13c16416da4fa51ec771bd4863d94344d139b2f5
> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> index 6729c98..abeac1f 100644
> --- a/arch/powerpc/Kconfig
> +++ b/arch/powerpc/Kconfig
> @@ -332,6 +332,27 @@ config APUS
>  	  Select APUS if configuring for a PowerUP Amiga.
>  	  More information is available at:
>  	  <http://linux-apus.sourceforge.net/>.
> +
> +config MPC7448HPC2
> +	bool "Freescale MPC7448HPC2(Taiga)"
> +	select DEFAULT_UIMAGE
> +	select PPC_UDBG_16550
> +	help
> +	  Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2  
> (Taiga)
> +	  platform
> +
> +config 74xx
> +	bool
> +	depends on MPC7448HPC2
> +	default y
> +	help
> +	  Select 74xx support
> +

What is the config option used for?  We should get ride of.

> +config TSI108_BRIDGE
> +	bool
> +	depends on MPC7448HPC2
> +	default y
> +	
>  endchoice
>
>  config PPC_PSERIES
> @@ -798,7 +819,8 @@ config MCA
>  	bool
>
>  config PCI
> -	bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx ||  
> PPC_MPC52xx || (EMBEDDED && PPC_ISERIES)
> +	bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx ||  
> PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) \
> +				  || MPC7448HPC2
>  	default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx && ! 
> PPC_85xx
>  	default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
>  	default PCI_QSPAN if !4xx && !CPM2 && 8xx
> diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/ 
> kernel/legacy_serial.c
> index 6e67b5b..f99238d 100644
> --- a/arch/powerpc/kernel/legacy_serial.c
> +++ b/arch/powerpc/kernel/legacy_serial.c
> @@ -134,6 +134,34 @@ static int __init add_legacy_soc_port(st
>  	return add_legacy_port(np, -1, UPIO_MEM, addr, addr, NO_IRQ, flags);
>  }
>
> +static int __init add_legacy_tsi_port(struct device_node *np,
> +				      struct device_node *tsi_dev)
> +{
> +	phys_addr_t addr;
> +	u32 *addrp;
> +	upf_t flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;
> +
> +	/* We only support ports that have a clock frequency properly
> +	 * encoded in the device-tree.
> +	 */
> +	if (get_property(np, "clock-frequency", NULL) == NULL)
> +		return -1;
> +
> +	/* Get the address */
> +	addrp = of_get_address(tsi_dev, 0, NULL, NULL);
> +	if (addrp == NULL)
> +		return -1;
> +
> +	addr = of_translate_address(tsi_dev, addrp);
> +
> +	/* Add port, irq will be dealt with later. We passed a translated
> +	 * IO port value. It will be fixed up later along with the irq
> +	 */
> +	return add_legacy_port(np, -1, UPIO_MEM, addr, addr, NO_IRQ, flags);
> +}
> +

This looks like its duplicating add_legacy_soc_port, why not use that  
instead?

> +
> +
>  static int __init add_legacy_isa_port(struct device_node *np,
>  				      struct device_node *isa_brg)
>  {
> @@ -302,6 +330,17 @@ void __init find_legacy_serial_ports(voi
>  		of_node_put(isa);
>  	}
>
> +	/* First fill our array with tsi-bridge ports */
> +	for (np = NULL; (np = of_find_compatible_node(np, "serial",  
> "ns16550")) != NULL;) {
> +		struct device_node *tsi = of_get_parent(np);
> +		if (tsi && !strcmp(tsi->type, "tsi-bridge")) {
> +			index = add_legacy_tsi_port(np, np);
> +			if (index >= 0 && np == stdout)
> +				legacy_serial_console = index;
> +		}
> +		of_node_put(tsi);
> +	}
> +	
>  #ifdef CONFIG_PCI
>  	/* Next, try to locate PCI ports */
>  	for (np = NULL; (np = of_find_all_nodes(np));) {
> diff --git a/arch/powerpc/platforms/74xx/Makefile b/arch/powerpc/ 
> platforms/74xx/Makefile
> new file mode 100644
> index 0000000..ed5648c
> --- /dev/null
> +++ b/arch/powerpc/platforms/74xx/Makefile
> @@ -0,0 +1,4 @@
> +#
> +# Makefile for the PowerPC 74xx linux kernel.
> +#
> +obj-$(CONFIG_MPC7448HPC2)	+= mpc7448_hpc2.o pci.o misc.o
> diff --git a/arch/powerpc/platforms/74xx/misc.c b/arch/powerpc/ 
> platforms/74xx/misc.c
> new file mode 100644
> index 0000000..6228875
> --- /dev/null
> +++ b/arch/powerpc/platforms/74xx/misc.c
> @@ -0,0 +1,38 @@
> +
> +/*
> + * MPC74xx generic code.
> + *
> + * Maintained by Roy Zang
> + *
> + * Copyright 2006 Freescale Semiconductor Inc.
> + *
> + * 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/irq.h>
> +#include <linux/module.h>
> +#include <asm/irq.h>
> +extern void _nmask_and_or_msr(unsigned long nmask, unsigned long  
> or_val);
> +
> +void mpc7448_hpc2_restart(char *cmd)
> +{
> +	local_irq_disable();
> +
> +	/* Set exception prefix high - to the firmware */
> +	_nmask_and_or_msr(0, MSR_IP);
> +
> +	for (;;) ;		/* Spin until reset happens */
> +}
> +
> +void mpc7448_hpc2_power_off(void)
> +{
> +	local_irq_disable();
> +	for (;;) ;		/* No way to shut power off with software */
> +}
> +
> +void mpc7448_hpc2_halt(void)
> +{
> +	mpc7448_hpc2_power_off();
> +}

Move these back into mpc7448_hpc2.c.  They are to specific to hpc2.

> diff --git a/arch/powerpc/platforms/74xx/mpc7448_hpc2.c b/arch/ 
> powerpc/platforms/74xx/mpc7448_hpc2.c
> new file mode 100644
> index 0000000..b060ae1
> --- /dev/null
> +++ b/arch/powerpc/platforms/74xx/mpc7448_hpc2.c
> @@ -0,0 +1,257 @@
> +/*
> + * mpc7448_hpc2.c
> + *
> + * Board setup routines for the Freescale Taiga platform
> + *
> + * Author: Jacob Pan
> + *	 jacob.pan@freescale.com
> + * Author: Xianghua Xiao
> + *       updated for taiga board from emulation platform 2005.5
> + *       x.xiao@freescale.com
> + * Maintainer: Roy Zang <tie-fei.zang@freescale.com>
> + *
> + * Copyright 2004-2006 Freescale Semiconductor, Inc.
> + *
> + * This file is licensed under
> + * the terms of the GNU General Public License version 2.  This  
> program
> + * is licensed "as is" without any warranty of any kind, whether  
> express
> + * or implied.
> + */
> +
> +#include <linux/config.h>
> +#include <linux/stddef.h>
> +#include <linux/kernel.h>
> +#include <linux/pci.h>
> +#include <linux/kdev_t.h>
> +#include <linux/console.h>
> +#include <linux/delay.h>
> +#include <linux/irq.h>
> +#include <linux/ide.h>
> +#include <linux/seq_file.h>
> +#include <linux/root_dev.h>
> +#include <linux/serial.h>
> +#include <linux/tty.h>
> +#include <linux/serial_core.h>
> +
> +#include <asm/system.h>
> +#include <asm/time.h>
> +#include <asm/machdep.h>
> +#include <asm/prom.h>
> +#include <asm/udbg.h>
> +#include <asm/tsi108.h>
> +#include <asm/pci-bridge.h>
> +#include <asm/reg.h>
> +#include <mm/mmu_decl.h>
> +#include "mpc7448_hpc2.h"
> +#include <asm/tsi108_pic.h>
> +
> +#ifndef CONFIG_PCI
> +isa_io_base = MPC7448_HPC2_ISA_IO_BASE;
> +isa_mem_base = MPC7448_HPC2_ISA_MEM_BASE;
> +pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET;
> +#endif
> +
> +extern int add_bridge(struct device_node *dev);
> +extern void mpc7448_hpc2_restart(char *cmd);
> +extern void mpc7448_hpc2_power_off(void);
> +extern void mpc7448_hpc2_halt(void);
> +
> +#ifdef TSI108_ETH
> +hw_info hw_info_table[TSI108_ETH_MAX_PORTS + 1] = {
> +	{TSI108_CSR_ADDR_PHYS + TSI108_ETH_OFFSET,
> +	 TSI108_CSR_ADDR_PHYS + TSI108_ETH_OFFSET,
> +	 TSI108_PHY0_ADDR, IRQ_TSI108_GIGE0},
> +
> +	{TSI108_CSR_ADDR_PHYS + TSI108_ETH_OFFSET + 0x400,
> +	 TSI108_CSR_ADDR_PHYS + TSI108_ETH_OFFSET,
> +	 TSI108_PHY1_ADDR, IRQ_TSI108_GIGE1},
> +
> +	{TBL_END, TBL_END, TBL_END, TBL_END}
> +};
> +#endif

This table looks problematic.  Look at using something like a  
platform device.

> +
> +/*
> + * Define all of the IRQ senses and polarities.  Taken from the
> + * mpc7448hpc  manual.
> + * Note:  Likely, this table and the following function should be
> + *        obtained and derived from the OF Device Tree.
> + */
> +
> +static u_char mpc7448_hpc2_pic_initsenses[] __initdata = {
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* INT[0] XINT0 from  
> FPGA */
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* INT[1] XINT1 from  
> FPGA */
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* INT[2] PHY_INT from  
> both GIGE */
> +	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* INT[3] RESERVED */
> +};
> +
> +/*
> + * mpc7448hpc2 PCI interrupt routing. all PCI interrupt comes from
> + * external PCI source at 23. need to program pci interrupt  
> control registers
> + * to route per slot IRQs.
> + */
> +
> +static inline int
> +mpc7448_hpc2_map_irq(struct pci_dev *dev, unsigned char idsel,
> +		     unsigned char pin)
> +{
> +	static char pci_irq_table[][4] =
> +	    /*
> +	     *      PCI IDSEL/INTPIN->INTLINE
> +	     *         A     B     C     D
> +	     */
> +	{
> +		{IRQ_PCI_INTA, IRQ_PCI_INTB, IRQ_PCI_INTC, IRQ_PCI_INTD},	/* A  
> SLOT 1 IDSEL 17 */
> +		{IRQ_PCI_INTB, IRQ_PCI_INTC, IRQ_PCI_INTD, IRQ_PCI_INTA},	/* B  
> SLOT 2 IDSEL 18 */
> +		{IRQ_PCI_INTC, IRQ_PCI_INTD, IRQ_PCI_INTA, IRQ_PCI_INTB},	/* C  
> SATA IDSEL 19 */
> +		{IRQ_PCI_INTD, IRQ_PCI_INTA, IRQ_PCI_INTB, IRQ_PCI_INTC},	/* D  
> USB IDSEL 20 */
> +	};
> +
> +	const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4;
> +	return PCI_IRQ_TABLE_LOOKUP;
> +}
> +
> +int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn)
> +{
> +	if (bus == 0 && PCI_SLOT(devfn) == 0)
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +	else
> +		return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static __inline__ void mpc7448_hpc2_l2cr_prefetch_enable(void)
> +{
> +	unsigned long msscr0;
> +	__asm__ __volatile__("mfspr %0, 0x3f6\n \
> +		ori %0,%0,0x3\n	         \
> +		sync \n                  \
> +		mtspr 0x3f6,%0\n   \
> +		sync\n			 \
> +		isync ":"=r"(msscr0));
> +}
> +
> +static void __init mpc7448_hpc2_setup_arch(void)
> +{
> +	struct device_node *cpu;
> +	struct device_node *np;
> +	if (ppc_md.progress)
> +		ppc_md.progress("mpc7448_hpc2_setup_arch():set_bridge", 0);
> +
> +	cpu = of_find_node_by_type(NULL, "cpu");
> +	if (cpu != 0) {
> +		unsigned int *fp;
> +
> +		fp = (int *)get_property(cpu, "clock-frequency", NULL);
> +		if (fp != 0)
> +			loops_per_jiffy = *fp / HZ;
> +		else
> +			loops_per_jiffy = 50000000 / HZ;
> +		of_node_put(cpu);
> +	}
> +
> +#ifdef	CONFIG_ROOT_NFS
> +	ROOT_DEV = Root_NFS;
> +#else
> +	ROOT_DEV = Root_HDA1;
> +#endif
> +
> +#ifdef CONFIG_BLK_DEV_INITRD
> +	ROOT_DEV = Root_RAM0;
> +#endif
> +
> +	/* setup PCI host bridge */
> +
> +#ifdef CONFIG_PCI
> +
> +	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
> +		add_bridge(np);
> +
> +	ppc_md.pci_swizzle = common_swizzle;
> +	ppc_md.pci_map_irq = mpc7448_hpc2_map_irq;
> +	ppc_md.pci_exclude_device = mpc7448_hpc2_exclude_device;
> +	if (ppc_md.progress)
> +		ppc_md.progress("tsi108: resources set", 0x100);
> +#endif
> +
> +#ifdef CONFIG_DUMMY_CONSOLE
> +	conswitchp = &dummy_con;
> +#endif
> +
> +	printk(KERN_INFO "MPC7448HPC2 (TAIGA) Platform\n");
> +	printk(KERN_INFO
> +	       "Jointly ported by Freescale and Tundra Semiconductor\n");
> +	printk(KERN_INFO
> +	       "Enabling L2 cache then enabling the HID0 prefetch engine. 
> \n");
> +	_set_L2CR(L2CR_L2E);
> +	mpc7448_hpc2_l2cr_prefetch_enable();

Hmm, can't remember what happens with the L2 setup on 74xx.

> +}
> +
> +/*
> + * Interrupt setup and service.  Interrrupts on the mpc7448_hpc2 come
> + * from the four external INT pins, PCI interrupts are routed via
> + * PCI interrupt control registers, it generates internal IRQ23
> + *
> + * Interrupt routing on the Taiga Board:
> + * TSI108:PB_INT[0] -> CPU0:INT#
> + * TSI108:PB_INT[1] -> CPU0:MCP#
> + * TSI108:PB_INT[2] -> N/C
> + * TSI108:PB_INT[3] -> N/C
> + */
> +static void __init mpc7448_hpc2_init_IRQ(void)
> +{
> +
> +	tsi108_pic_init(mpc7448_hpc2_pic_initsenses);
> +
> +	/* Configure MPIC outputs to CPU0 */
> +	tsi108_pic_set_output(0, IRQ_SENSE_EDGE, IRQ_POLARITY_NEGATIVE);
> +}
> +
> +static void __init mpc7448_hpc2_map_io(void)
> +{
> +	/* PCI IO  mapping */
> +	io_block_mapping(MPC7448_HPC2_PCI_IO_BASE_VIRT,
> +			 MPC7448_HPC2_PCI_IO_BASE_PHYS, 0x00800000, _PAGE_IO);
> +	/* Tsi108 CSR mapping */
> +	io_block_mapping(TSI108_CSR_ADDR_VIRT, TSI108_CSR_ADDR_PHYS,
> +			 0x100000, _PAGE_IO);
> +
> +	/* PCI Config mapping */
> +	io_block_mapping(MPC7448_HPC2_PCI_CFG_BASE_VIRT,
> +			 MPC7448_HPC2_PCI_CFG_BASE_PHYS,
> +			 MPC7448_HPC2_PCI_CFG_SIZE, _PAGE_IO);
> +
> +	tsi108_pci_cfg_base = MPC7448_HPC2_PCI_CFG_BASE_VIRT;
> +	/* NVRAM mapping */
> +	io_block_mapping(MPC7448_HPC2_NVRAM_BASE_ADDR,
> +			 MPC7448_HPC2_NVRAM_BASE_ADDR, MPC7448_HPC2_NVRAM_SIZE,
> +			 _PAGE_IO);
> +}

You need to do this another way, we are trying to avoid using  
io_block_mapping()

> +
> +void mpc7448_hpc2_show_cpuinfo(struct seq_file *m)
> +{
> +	seq_printf(m, "vendor\t\t: Freescale Semiconductor\n");
> +	seq_printf(m, "machine\t\t: MPC7448hpc2\n");
> +}
> +
> +/*
> + * Called very early, device-tree isn't unflattened
> + */
> +static int __init mpc7448_hpc2_probe(void)
> +{
> +	/* We always match for now, eventually we should look at the flat
> +	   dev tree to ensure this is the board we are suppose to run on
> +	 */
> +	return 1;
> +}
> +
> +define_machine(mpc7448_hpc2){
> +	.name 			= "MPC7448 HPC2",
> +	.probe 			= mpc7448_hpc2_probe,
> +	.setup_arch 		= mpc7448_hpc2_setup_arch,
> +	.init_IRQ 		= mpc7448_hpc2_init_IRQ,
> +	.show_cpuinfo 		= mpc7448_hpc2_show_cpuinfo,
> +	.get_irq 		= tsi108_pic_get_irq,
> +	.restart 		= mpc7448_hpc2_restart,
> +	.calibrate_decr 	= generic_calibrate_decr,
> +	.setup_io_mappings 	= mpc7448_hpc2_map_io,
> +	.progress 		= udbg_progress,
> +};
> diff --git a/arch/powerpc/platforms/74xx/mpc7448_hpc2.h b/arch/ 
> powerpc/platforms/74xx/mpc7448_hpc2.h
> new file mode 100644
> index 0000000..8833520
> --- /dev/null
> +++ b/arch/powerpc/platforms/74xx/mpc7448_hpc2.h
> @@ -0,0 +1,80 @@
> +/*
> + * mpc7448_hpc2.h
> + *
> + * Definitions for Freescale MPC7448_HPC2 platform
> + *
> + * Author: Jacob Pan
> + *         jacob.pan@freescale.com
> + * Maintainer: Roy Zang <roy.zang@freescale.com>
> + *
> + * 2006 (c) Freescale Semiconductor, Inc.  This file is licensed  
> under
> + * the terms of the GNU General Public License version 2.  This  
> program
> + * is licensed "as is" without any warranty of any kind, whether  
> express
> + * or implied.
> + */
> +
> +#ifndef __PPC_PLATFORMS_MPC7448_HPC2_H
> +#define __PPC_PLATFORMS_MPC7448_HPC2_H
> +
> +#include <asm/ppcboot.h>
> +
> +/* Ethernet defines
> + */
> +#define TSI108_ETH
> +#define TSI108_ETH_MAX_PORTS	(2)	/* TSI108 Ethernet block has 2  
> ports */
> +#define TSI108_PHY0_ADDR	(8)	/* PHY address for GIGE port 0 */
> +#define TSI108_PHY1_ADDR	(9)	/* PHY address for GIGE port 1 */
> +
> +/* Base Addresses for the PCI bus
> + * HOST_PCI initiator (outbound) window to PCI bus
> + */
> +#define MPC7448_HPC2_PCI_MEM_OFFSET	(0x00000000)
> +#define MPC7448_HPC2_PCI_IO_BASE_PHYS	(0xfa000000)
> +#define MPC7448_HPC2_PCI_IO_BASE_VIRT	(MPC7448_HPC2_PCI_IO_BASE_PHYS)
> +#define MPC7448_HPC2_PCI_MEM_BASE	(0xe0000000)
> +#define MPC7448_HPC2_ISA_IO_BASE	(0x00000000)
> +#define MPC7448_HPC2_ISA_MEM_BASE	(0x00000000)
> +
> +#define MPC7448_HPC2_PCI_CFG_BASE_PHYS	(0xfb000000)
> +#define MPC7448_HPC2_PCI_CFG_BASE_VIRT	 
> (MPC7448_HPC2_PCI_CFG_BASE_PHYS)
> +#define MPC7448_HPC2_PCI_CFG_SIZE	(0x01000000)
> +
> +#define MPC7448_HPC2_PCI_MEM_START	(0xE0000000)
> +#define MPC7448_HPC2_PCI_MEM_END	(0xF9FFFFFF)
> +
> +#define MPC7448_HPC2_PCI_IO_START	(0xFA000000)
> +#define MPC7448_HPC2_PCI_IO_END	(0xFA00FFFF)
> +
> +#define MPC7448_HPC2_PCI_CFG_OFFSET	(0xFB000000)
> +#define MPC7448_HPC2_PCI_IO_OFFSET	(0xFA000000)
> +
> +#define MPC7448_HPC2_PCI_MEM32_OFFSET	0x00000000	/* PCI MEM32  
> space offset within
> +							   the PCI window */
> +#define MPC7448_HPC2_PCI_PFM_OFFSET	0x10000000	/* PCI PFM1 space  
> offset within
> +							   the PCI window */

Can you not determine these from your flat device tree?

> +
> +/* Memory-mapped CIU resources (CPU view)
> + * The memory map is set by initialization code in monitor
> + */
> +
> +#define TSI108_CSR_ADDR_PHYS	(0xC0000000)	/* Physical Tsi108 CSR  
> Base Address */
> +#define TSI108_CSR_ADDR_VIRT	(0xF0000000)	/* Virtual Tsi108 CSR  
> Base Address */

Don't use hard coded VIRT addresses.

> +
> +#define FLASH_BASE_ADDR		(0xFF000000)	/* Boot FLASH Base Address */
> +
> +#define SDRAM_BASE_ADDR		0x00000000	/* SDRAM base address */
> +#define BOARD_SDRAM_SIZE	0x20000000	/* Default value: 512MB */
> +
> +/* Size of SDRAM space reserved for user space. This limits space  
> available
> + * for dynamic allocation.
> + */
> +#define USER_RESERVED_MEM	(BOARD_SDRAM_SIZE - 0x02000000)
> +
> +#define USER_RESERVED_BASE  \
> +  (SDRAM_BASE_ADDR + (BOARD_SDRAM_SIZE - USER_RESERVED_MEM)
> +
> +/* Memory mapped NVRAM/RTC */
> +#define MPC7448_HPC2_NVRAM_BASE_ADDR	(0xFC000000)
> +#define MPC7448_HPC2_NVRAM_SIZE	(0x8000)
> +
> +#endif				/* __PPC_PLATFORMS_MPC7448_HPC2_H */
> diff --git a/arch/powerpc/platforms/74xx/pci.c b/arch/powerpc/ 
> platforms/74xx/pci.c
> new file mode 100644
> index 0000000..fd822ed
> --- /dev/null
> +++ b/arch/powerpc/platforms/74xx/pci.c

If this is generic to the tsi108 rename to something like  
tsi108_pci.c as its not generic to 74xx or embedded6xx.

> @@ -0,0 +1,103 @@
> +/*
> + * TSI 108 PCI hose setup up code
> + *
> + * Maintained by Roy Zang
> + *
> + * 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/config.h>
> +#include <linux/stddef.h>
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/errno.h>
> +#include <linux/pci.h>
> +#include <linux/delay.h>
> +#include <linux/irq.h>
> +#include <linux/module.h>
> +
> +#include <asm/system.h>
> +#include <asm/atomic.h>
> +#include <asm/io.h>
> +#include <asm/pci-bridge.h>
> +#include <asm/prom.h>
> +#include <asm/tsi108.h>
> +#include "mpc7448_hpc2.h"

What's this included needed for?

> +
> +#undef DEBUG
> +
> +#ifdef DEBUG
> +#define DBG(x...) printk(x)
> +#else
> +#define DBG(x...)
> +#endif
> +
> +extern int tsi108_direct_write_config(struct pci_bus *bus,  
> unsigned int devfn,
> +				      int offset, int len, u32 val);
> +extern int tsi108_direct_read_config(struct pci_bus *bus, unsigned  
> int devfn,
> +				     int offset, int len, u32 * val);
> +

Can you not use indirect pci support that already exists?

> +void tsi108_clear_pci_error(u32 pci_cfg_base);
> +
> +extern int
> +tsi108_read_config(int bus, unsigned int devfn, int offset, int  
> len, u32 * val);
> +#ifdef CONFIG_PCI
> +static struct pci_ops direct_pci_ops = {
> +	tsi108_direct_read_config,
> +	tsi108_direct_write_config
> +};
> +
> +void tsi108_clear_pci_cfg_error(void)
> +{
> +	tsi108_clear_pci_error(MPC7448_HPC2_PCI_CFG_BASE_PHYS);
> +}
> +
> +int __init add_bridge(struct device_node *dev)
> +{
> +	int len;
> +	struct pci_controller *hose;
> +	struct resource rsrc;
> +	int *bus_range;
> +	int primary = 0, has_address = 0;
> +
> +	DBG("TSI_PCI: %s tsi108_pci_cfg_base=0x%x\n", __FUNCTION__,
> +	    tsi108_pci_cfg_base);
> +
> +	/* Fetch host bridge registers address */
> +	has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
> +
> +	/* Get bus range if any */
> +	bus_range = (int *)get_property(dev, "bus-range", &len);
> +	if (bus_range == NULL || len < 2 * sizeof(int)) {
> +		printk(KERN_WARNING "Can't get bus-range for %s, assume"
> +		       " bus 0\n", dev->full_name);
> +	}
> +
> +	hose = pcibios_alloc_controller();
> +
> +	if (!hose) {
> +		printk("PCI Host bridge init failed\n");
> +		return -ENOMEM;
> +	}
> +	hose->arch_data = dev;
> +	hose->set_cfg_type = 1;
> +
> +	hose->first_busno = bus_range ? bus_range[0] : 0;
> +	hose->last_busno = bus_range ? bus_range[1] : 0xff;
> +
> +	(hose)->ops = &direct_pci_ops;
> +
> +	printk(KERN_INFO "Found tsi108 PCI host bridge at 0x%08lx. "
> +	       "Firmware bus number: %d->%d\n",
> +	       rsrc.start, hose->first_busno, hose->last_busno);
> +
> +	/* Interpret the "ranges" property */
> +	/* This also maps the I/O region and sets isa_io/mem_base */
> +	pci_process_bridge_OF_ranges(hose, dev, primary);
> +	return 0;
> +
> +}
> +#endif
> diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/ 
> platforms/Makefile
> index c4f6b0d..71ca0e0 100644
> --- a/arch/powerpc/platforms/Makefile
> +++ b/arch/powerpc/platforms/Makefile
> @@ -9,6 +9,7 @@ obj-$(CONFIG_PPC_CHRP)		+= chrp/
>  obj-$(CONFIG_4xx)		+= 4xx/
>  obj-$(CONFIG_PPC_83xx)		+= 83xx/
>  obj-$(CONFIG_PPC_85xx)		+= 85xx/
> +obj-$(CONFIG_74xx)		+= 74xx/
>  obj-$(CONFIG_PPC_PSERIES)	+= pseries/
>  obj-$(CONFIG_PPC_ISERIES)	+= iseries/
>  obj-$(CONFIG_PPC_MAPLE)		+= maple/
> -- 
> 1.3.0
>
>
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [PATCH/2.6.17-rc4 3/10] Powerpc: Add tsi108 common function
From: Kumar Gala @ 2006-05-17 13:47 UTC (permalink / raw)
  To: Zang Roy-r61911
  Cc: linuxppc-dev list, Yang Xin-Xin-r48390, Paul Mackerras,
	Alexandre.Bounine
In-Reply-To: <9FCDBA58F226D911B202000BDBAD46730626D61D@zch01exm40.ap.freescale.net>


On May 17, 2006, at 5:14 AM, Zang Roy-r61911 wrote:

> Add Tundra Semiconductor tsi108 host bridge common function support.
>
> Signed-off-by: Alexandre Bounine <alexandreb@tundra.com>
> Signed-off-by: Roy Zang	<tie-fei.zang@freescale.com>
>
> ---
>
>  arch/powerpc/sysdev/Makefile        |    1
>  arch/powerpc/sysdev/tsi108_common.c |  224 ++++++++++++++++++++++++ 
> +++++++++++
>  2 files changed, 225 insertions(+), 0 deletions(-)
>  create mode 100644 arch/powerpc/sysdev/tsi108_common.c
>
> ab3b477b5924d2c9cbf6ba3ae4d95fe333c9bad9
> diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/ 
> Makefile
> index 4c2b356..8c0afb7 100644
> --- a/arch/powerpc/sysdev/Makefile
> +++ b/arch/powerpc/sysdev/Makefile
> @@ -8,3 +8,4 @@ obj-$(CONFIG_U3_DART)		+= dart_iommu.o
>  obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
>  obj-$(CONFIG_PPC_83xx)		+= ipic.o
>  obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
> +obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_common.o tsi108_pic.o
> diff --git a/arch/powerpc/sysdev/tsi108_common.c b/arch/powerpc/ 
> sysdev/tsi108_common.c
> new file mode 100644
> index 0000000..3c55f99
> --- /dev/null
> +++ b/arch/powerpc/sysdev/tsi108_common.c
> @@ -0,0 +1,224 @@
> +/*
> + * arch/ppc/syslib/tsi108_common.c
> + *
> + * Common routines for Tundra Semiconductor TSI108 host bridge.
> + *
> + * 2004-2005 (c) Tundra Semiconductor Corp.
> + * Author: Alex Bounine (alexandreb@tundra.com)
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,  
> but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of  
> MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public  
> License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public  
> License along with
> + * this program; if not, write to the Free Software Foundation,  
> Inc., 59
> + * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/pci.h>
> +#include <linux/slab.h>
> +
> +#include <asm/byteorder.h>
> +#include <asm/io.h>
> +#include <asm/irq.h>
> +#include <asm/uaccess.h>
> +#include <asm/machdep.h>
> +#include <asm/pci-bridge.h>
> +#include <asm/tsi108.h>
> +#include <asm/prom.h>
> +
> +u32 tsi108_pci_cfg_base;
> +
> +#undef TSI108_PCI_DEBUG
> +
> +#define tsi_mk_config_addr(bus, devfunc, offset) \
> +	(((bus)<<16) | ((devfunc)<<8) | (offset & 0xfc)|  
> tsi108_pci_cfg_base)
> +
> +static phys_addr_t tsi108_csr_base = -1;
> +
> +phys_addr_t get_csrbase(void)
> +{
> +	struct device_node *tsi;
> +
> +	if (tsi108_csr_base != -1)
> +		return tsi108_csr_base;
> +
> +	tsi = of_find_node_by_type(NULL, "tsi-bridge");
> +	if (tsi) {
> +		unsigned int size;
> +		void *prop = get_property(tsi, "reg", &size);
> +		tsi108_csr_base = of_translate_address(tsi, prop);
> +		of_node_put(tsi);
> +	};
> +	return tsi108_csr_base;
> +}
> +
> +u32 get_vir_csrbase(void)
> +{
> +	return (u32) (ioremap(get_csrbase(), 0x10000));
> +}
> +
> +EXPORT_SYMBOL(get_csrbase);
> +EXPORT_SYMBOL(get_vir_csrbase);
> +
> +/*
> + * Prosessor Bus Clock (in MHz) defined by CG_PB_SELECT
> + * (based on recommended Tsi108 reference clock 33MHz)
> + */
> +static int pb_clk_sel[8] = { 0, 0, 183, 100, 133, 167, 200, 233 };
> +
> +/*
> + * SDRAM Clock (in MHz) defined by CG_SD_SELECT
> + * (based on recommended Tsi108 reference clock 33MHz)
> + */
> +static int sd_clk_sel[2][8] = {
> +	{0, 0, 183, 100, 133, 167, 200, 233},	/* SYNC */
> +	{0, 0, 0, 0, 133, 160, 200, 0}	/* ASYNC */
> +};
> +

Can the PCI use indirect like used on most other PPC platforms.

> +int
> +tsi108_direct_write_config(struct pci_bus *bus, unsigned int devfunc,
> +			   int offset, int len, u32 val)
> +{
> +	volatile unsigned char *cfg_addr;
> +
> +	cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
> +							devfunc, offset) |
> +				     (offset & 0x03));
> +
> +#ifdef TSI108_PCI_DEBUG
> +	printk("PCI CFG write : ");
> +	printk("%d:0x%x:0x%x ", bus->number, devfunc, offset);
> +	printk("%d ADDR=0x%08x ", len, (uint) cfg_addr);
> +	printk("data = 0x%08x\n", val);
> +#endif
> +
> +	switch (len) {
> +	case 1:
> +		out_8((u8 *) cfg_addr, val);
> +		break;
> +	case 2:
> +		out_le16((u16 *) cfg_addr, val);
> +		break;
> +	default:
> +		out_le32((u32 *) cfg_addr, val);
> +		break;
> +	}
> +
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +void tsi108_clear_pci_error(u32 pci_cfg_base)
> +{
> +	u32 err_stat, err_addr, pci_stat;
> +
> +	/*
> +	 * Quietly clear PB and PCI error flags set as result
> +	 * of PCI/X configuration read requests.
> +	 */
> +
> +	/* Read PB Error Log Registers */
> +
> +	err_stat = tsi108_read_reg(TSI108_PB_OFFSET + TSI108_PB_ERRCS);
> +	err_addr = tsi108_read_reg(TSI108_PB_OFFSET + TSI108_PB_AERR);
> +
> +	if (err_stat & TSI108_PB_ERRCS_ES) {
> +		/* Clear error flag */
> +		tsi108_write_reg(TSI108_PB_OFFSET + TSI108_PB_ERRCS,
> +				 TSI108_PB_ERRCS_ES);
> +
> +		/* Clear read error reported in PB_ISR */
> +		tsi108_write_reg(TSI108_PB_OFFSET + TSI108_PB_ISR,
> +				 TSI108_PB_ISR_PBS_RD_ERR);
> +
> +		/* Clear PCI/X bus cfg errors if applicable */
> +		if ((err_addr & 0xFF000000) == pci_cfg_base) {
> +			pci_stat =
> +			    tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_CSR);
> +			tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_CSR,
> +					 pci_stat);
> +		}
> +	}
> +
> +	return;
> +}
> +
> +#define __tsi108_read_pci_config(x, addr, op)		\
> +	__asm__ __volatile__(				\
> +		"	"op" %0,0,%1\n"		\
> +		"1:	eieio\n"			\
> +		"2:\n"					\
> +		".section .fixup,\"ax\"\n"		\
> +		"3:	li %0,-1\n"			\
> +		"	b 2b\n"				\
> +		".section __ex_table,\"a\"\n"		\
> +		"	.align 2\n"			\
> +		"	.long 1b,3b\n"			\
> +		".text"					\
> +		: "=r"(x) : "r"(addr))
> +
> +int
> +tsi108_direct_read_config(struct pci_bus *bus, unsigned int devfn,  
> int offset,
> +			  int len, u32 * val)
> +{
> +	volatile unsigned char *cfg_addr;
> +	u32 temp;
> +
> +	cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number,
> +							devfn,
> +							offset) | (offset &
> +								   0x03));
> +
> +	switch (len) {
> +	case 1:
> +		__tsi108_read_pci_config(temp, cfg_addr, "lbzx");
> +		break;
> +	case 2:
> +		__tsi108_read_pci_config(temp, cfg_addr, "lhbrx");
> +		break;
> +	default:
> +		__tsi108_read_pci_config(temp, cfg_addr, "lwbrx");
> +		break;
> +	}
> +
> +	*val = temp;
> +
> +#ifdef TSI108_PCI_DEBUG
> +	if ((0xFFFFFFFF != temp) && (0xFFFF != temp) && (0xFF != temp)) {
> +		printk("PCI CFG read : ");
> +		printk("%d:0x%x:0x%x ", bus->number, devfn, offset);
> +		printk("%d ADDR=0x%08x ", len, (uint) cfg_addr);
> +		printk("data = 0x%x\n", *val);
> +	}
> +#endif
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +unsigned long tsi108_get_cpu_clk(void)
> +{
> +	/* Detect PB clock freq. */
> +	u32 i = tsi108_read_reg(TSI108_CLK_OFFSET + TSI108_CG_PWRUP_STATUS);
> +
> +	i = (i >> 16) & 0x07;	/* Get PB PLL multiplier */
> +	return (pb_clk_sel[i] * 1000000);
> +}
> +
> +unsigned long tsi108_get_sdc_clk(void)
> +{
> +	u32 i, k;
> +
> +	/* Get SDC/PB clock freq. from CG settings */
> +	i = tsi108_read_reg(TSI108_CLK_OFFSET + TSI108_CG_PWRUP_STATUS);
> +	k = (i >> 16) & 0x07;	/* Get PB PLL multiplier */
> +	i = (i >> 20) & 0x07;	/* Get SDC PLL multiplier */
> +	k = (k == i) ? 0 : 1;	/* sync/async configuration */
> +	return (sd_clk_sel[k][i] * 1000000);
> +}
> -- 
> 1.3.0
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox