1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2025-01-26 13:21:07 +02:00

sync ssb with upstream

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@9302 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
nbd 2007-10-14 02:47:36 +00:00
parent d124ab28a8
commit 532249b507
37 changed files with 926 additions and 4665 deletions

View File

@ -1,250 +0,0 @@
CONFIG_32BIT=y
# CONFIG_64BIT is not set
# CONFIG_64BIT_PHYS_ADDR is not set
# CONFIG_8139TOO is not set
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
# CONFIG_ARPD is not set
# CONFIG_ATMEL is not set
# CONFIG_ATM_DRIVERS is not set
CONFIG_B44=y
CONFIG_BASE_SMALL=0
# CONFIG_BCM43XX is not set
CONFIG_BCM947XX=y
CONFIG_BITREVERSE=y
# CONFIG_BONDING is not set
# CONFIG_BSD_DISKLABEL is not set
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_BT_HCIBCM203X is not set
# CONFIG_BT_HCIBFUSB is not set
# CONFIG_BT_HCIBPA10X is not set
# CONFIG_BT_HCIVHCI is not set
CONFIG_CFE=y
# CONFIG_CIFS_STATS is not set
# CONFIG_CLS_U32_MARK is not set
# CONFIG_CLS_U32_PERF is not set
CONFIG_CMDLINE="root=/dev/mtdblock2 rootfstype=squashfs,jffs2 init=/etc/preinit noinitrd console=ttyS0,115200"
# CONFIG_CONFIGFS_FS is not set
CONFIG_CONNECTOR=m
# CONFIG_CPU_BIG_ENDIAN is not set
CONFIG_CPU_HAS_LLSC=y
CONFIG_CPU_HAS_PREFETCH=y
CONFIG_CPU_HAS_SYNC=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_CPU_MIPS32=y
CONFIG_CPU_MIPS32_R1=y
# CONFIG_CPU_MIPS32_R2 is not set
# CONFIG_CPU_MIPS64_R1 is not set
# CONFIG_CPU_MIPS64_R2 is not set
CONFIG_CPU_MIPSR1=y
# CONFIG_CPU_NEVADA is not set
# CONFIG_CPU_R10000 is not set
# CONFIG_CPU_R3000 is not set
# CONFIG_CPU_R4300 is not set
# CONFIG_CPU_R4X00 is not set
# CONFIG_CPU_R5000 is not set
# CONFIG_CPU_R5432 is not set
# CONFIG_CPU_R6000 is not set
# CONFIG_CPU_R8000 is not set
# CONFIG_CPU_RM7000 is not set
# CONFIG_CPU_RM9000 is not set
# CONFIG_CPU_SB1 is not set
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
CONFIG_CPU_SUPPORTS_HIGHMEM=y
# CONFIG_CPU_TX39XX is not set
# CONFIG_CPU_TX49XX is not set
# CONFIG_CPU_VR41XX is not set
# CONFIG_DDB5477 is not set
CONFIG_DEVPORT=y
# CONFIG_DM9000 is not set
CONFIG_DMA_NEED_PCI_MAP_STATE=y
CONFIG_DMA_NONCOHERENT=y
# CONFIG_E100 is not set
CONFIG_FS_POSIX_ACL=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_GPIO=y
# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
# CONFIG_GEN_RTC is not set
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HID=m
CONFIG_HW_HAS_PCI=y
CONFIG_HW_RANDOM=y
CONFIG_HZ=250
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_I2C is not set
# CONFIG_IDE is not set
# CONFIG_IKCONFIG is not set
CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m
CONFIG_INITRAMFS_SOURCE=""
CONFIG_INPUT=m
# CONFIG_IP6_NF_MATCH_FRAG is not set
# CONFIG_IP6_NF_MATCH_HL is not set
# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set
# CONFIG_IP6_NF_MATCH_OPTS is not set
# CONFIG_IP6_NF_MATCH_RT is not set
# CONFIG_IP6_NF_TARGET_HL is not set
CONFIG_IPW2200_QOS=y
# CONFIG_IP_DCCP is not set
# CONFIG_IP_ROUTE_VERBOSE is not set
CONFIG_IRQ_CPU=y
# CONFIG_LIBCRC32C is not set
# CONFIG_LLC2 is not set
# CONFIG_MACH_ALCHEMY is not set
# CONFIG_MACH_DECSTATION is not set
# CONFIG_MACH_JAZZ is not set
# CONFIG_MACH_VR41XX is not set
CONFIG_MIPS=y
# CONFIG_MIPS_ATLAS is not set
# CONFIG_MIPS_COBALT is not set
# CONFIG_MIPS_EV64120 is not set
CONFIG_MIPS_L1_CACHE_SHIFT=5
# CONFIG_MIPS_MALTA is not set
CONFIG_MIPS_MT_DISABLED=y
# CONFIG_MIPS_MT_SMP is not set
# CONFIG_MIPS_MT_SMTC is not set
# CONFIG_MIPS_SEAD is not set
# CONFIG_MIPS_SIM is not set
# CONFIG_MIPS_VPE_LOADER is not set
# CONFIG_MOMENCO_OCELOT is not set
# CONFIG_MOMENCO_OCELOT_3 is not set
# CONFIG_MOMENCO_OCELOT_C is not set
CONFIG_MTD=y
# CONFIG_MTD_ABSENT is not set
CONFIG_MTD_BCM47XX=y
CONFIG_MTD_BLKDEVS=y
CONFIG_MTD_BLOCK=y
# CONFIG_MTD_BLOCK2MTD is not set
CONFIG_MTD_CFI=y
# CONFIG_MTD_CFI_ADV_OPTIONS is not set
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_CFI_I1=y
CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_I4 is not set
# CONFIG_MTD_CFI_I8 is not set
CONFIG_MTD_CFI_INTELEXT=y
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
CONFIG_MTD_CHAR=y
# CONFIG_MTD_CMDLINE_PARTS is not set
CONFIG_MTD_COMPLEX_MAPPINGS=y
# CONFIG_MTD_CONCAT is not set
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
CONFIG_MTD_GEN_PROBE=y
# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_MAP_BANK_WIDTH_1=y
# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
CONFIG_MTD_MAP_BANK_WIDTH_2=y
# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
CONFIG_MTD_MAP_BANK_WIDTH_4=y
# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
# CONFIG_MTD_MTDRAM is not set
# CONFIG_MTD_ONENAND is not set
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_PCI is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_PHYSMAP is not set
# CONFIG_MTD_PLATRAM is not set
# CONFIG_MTD_PMC551 is not set
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_SLRAM is not set
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
CONFIG_NETDEV_1000=y
# CONFIG_NET_EMATCH is not set
# CONFIG_NET_IPGRE_BROADCAST is not set
# CONFIG_NET_PKTGEN is not set
CONFIG_NET_SCH_FIFO=y
# CONFIG_NET_SCH_NETEM is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NTFS_FS is not set
# CONFIG_PAGE_SIZE_16KB is not set
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_PAGE_SIZE_8KB is not set
# CONFIG_PMC_YOSEMITE is not set
# CONFIG_PNPACPI is not set
# CONFIG_PNX8550_JBS is not set
# CONFIG_PNX8550_STB810 is not set
# CONFIG_PPP_MULTILINK is not set
# CONFIG_PPP_SYNC_TTY is not set
# CONFIG_PROC_KCORE is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_RTC is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
# CONFIG_SCSI_MULTI_LUN is not set
CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SERIAL_8250_DETECT_IRQ is not set
CONFIG_SERIAL_8250_EXTENDED=y
# CONFIG_SERIAL_8250_MANY_PORTS is not set
# CONFIG_SERIAL_8250_RSA is not set
CONFIG_SERIAL_8250_SHARE_IRQ=y
# CONFIG_SGI_IP22 is not set
# CONFIG_SGI_IP27 is not set
# CONFIG_SGI_IP32 is not set
# CONFIG_SIBYTE_BIGSUR is not set
# CONFIG_SIBYTE_CARMEL is not set
# CONFIG_SIBYTE_CRHINE is not set
# CONFIG_SIBYTE_CRHONE is not set
# CONFIG_SIBYTE_LITTLESUR is not set
# CONFIG_SIBYTE_PTSWARM is not set
# CONFIG_SIBYTE_RHONE is not set
# CONFIG_SIBYTE_SENTOSA is not set
# CONFIG_SIBYTE_SWARM is not set
# CONFIG_SPARSEMEM_STATIC is not set
CONFIG_SSB=y
CONFIG_SSB_DEBUG=y
CONFIG_SSB_DRIVER_EXTIF=y
CONFIG_SSB_DRIVER_MIPS=y
CONFIG_SSB_DRIVER_PCICORE=y
CONFIG_SSB_PCICORE_HOSTMODE=y
CONFIG_SSB_PCIHOST=y
CONFIG_SSB_SERIAL=y
# CONFIG_SSB_SILENT is not set
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_SYS_HAS_CPU_MIPS32_R1=y
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
# CONFIG_TC35815 is not set
# CONFIG_TOSHIBA_JMR3927 is not set
# CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_TRAD_SIGNALS=y
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_USB_CATC is not set
# CONFIG_USB_EHCI_BIG_ENDIAN_MMIO is not set
CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
CONFIG_USB_EHCI_SPLIT_ISO=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
CONFIG_USB_OHCI_HCD=m
# CONFIG_USB_OHCI_HCD_SSB is not set
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
# CONFIG_USB_STORAGE_ALAUDA is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_DPCM is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
# CONFIG_USB_STORAGE_KARMA is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
# CONFIG_USB_STORAGE_USBAT is not set
CONFIG_USB_UHCI_HCD=m
# CONFIG_VGASTATE is not set
# CONFIG_VIA_RHINE is not set
# CONFIG_WATCHDOG is not set
CONFIG_ZONE_DMA_FLAG=0

View File

@ -171,7 +171,6 @@ CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PPP_SYNC_TTY is not set # CONFIG_PPP_SYNC_TTY is not set
# CONFIG_PROC_KCORE is not set # CONFIG_PROC_KCORE is not set
# CONFIG_RTC is not set # CONFIG_RTC is not set
# CONFIG_RTL8187 is not set
CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
# CONFIG_SCSI_MULTI_LUN is not set # CONFIG_SCSI_MULTI_LUN is not set
@ -199,8 +198,11 @@ CONFIG_SSB_DEBUG=y
CONFIG_SSB_DRIVER_EXTIF=y CONFIG_SSB_DRIVER_EXTIF=y
CONFIG_SSB_DRIVER_MIPS=y CONFIG_SSB_DRIVER_MIPS=y
CONFIG_SSB_DRIVER_PCICORE=y CONFIG_SSB_DRIVER_PCICORE=y
CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
CONFIG_SSB_PCICORE_HOSTMODE=y CONFIG_SSB_PCICORE_HOSTMODE=y
CONFIG_SSB_PCIHOST=y CONFIG_SSB_PCIHOST=y
CONFIG_SSB_PCIHOST_POSSIBLE=y
CONFIG_SSB_POSSIBLE=y
CONFIG_SSB_SERIAL=y CONFIG_SSB_SERIAL=y
# CONFIG_SSB_SILENT is not set # CONFIG_SSB_SILENT is not set
CONFIG_SYSVIPC_SYSCTL=y CONFIG_SYSVIPC_SYSCTL=y
@ -213,7 +215,6 @@ CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
# CONFIG_TOSHIBA_RBTX4927 is not set # CONFIG_TOSHIBA_RBTX4927 is not set
# CONFIG_TOSHIBA_RBTX4938 is not set # CONFIG_TOSHIBA_RBTX4938 is not set
CONFIG_TRAD_SIGNALS=y CONFIG_TRAD_SIGNALS=y
# CONFIG_UNUSED_SYMBOLS is not set
# CONFIG_USB_CATC is not set # CONFIG_USB_CATC is not set
CONFIG_USB_EHCI_HCD=m CONFIG_USB_EHCI_HCD=m
CONFIG_USB_EHCI_SPLIT_ISO=y CONFIG_USB_EHCI_SPLIT_ISO=y
@ -221,7 +222,6 @@ CONFIG_USB_EHCI_SPLIT_ISO=y
# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
CONFIG_USB_OHCI_HCD=m CONFIG_USB_OHCI_HCD=m
# CONFIG_USB_OHCI_HCD_SSB is not set
# CONFIG_USB_PEGASUS is not set # CONFIG_USB_PEGASUS is not set
# CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_R8A66597_HCD is not set
# CONFIG_USB_SERIAL_OTI6858 is not set # CONFIG_USB_SERIAL_OTI6858 is not set

View File

@ -55,7 +55,7 @@ static void bcm47xx_machine_restart(char *command)
*/ */
/* Set the watchdog timer to reset immediately */ /* Set the watchdog timer to reset immediately */
ssb_chipco_watchdog(&ssb.chipco, 1); ssb_chipco_watchdog_timer_set(&ssb.chipco, 1);
while (1) while (1)
cpu_relax(); cpu_relax();
} }
@ -64,7 +64,7 @@ static void bcm47xx_machine_halt(void)
{ {
/* Disable interrupts and watchdog and spin forever */ /* Disable interrupts and watchdog and spin forever */
local_irq_disable(); local_irq_disable();
ssb_chipco_watchdog(&ssb.chipco, 0); ssb_chipco_watchdog_timer_set(&ssb.chipco, 0);
while (1) while (1)
cpu_relax(); cpu_relax();
} }

View File

@ -1,211 +0,0 @@
Index: linux-2.6.22-rc4/arch/mips/Kconfig
===================================================================
--- linux-2.6.22-rc4.orig/arch/mips/Kconfig 2007-06-10 21:32:36.000000000 +0100
+++ linux-2.6.22-rc4/arch/mips/Kconfig 2007-06-10 21:33:12.000000000 +0100
@@ -4,6 +4,10 @@
# Horrible source of confusion. Die, die, die ...
select EMBEDDED
+config CFE
+ bool
+ # Common Firmware Environment
+
mainmenu "Linux/MIPS Kernel Configuration"
menu "Machine selection"
@@ -126,6 +130,23 @@
Members include the Acer PICA, MIPS Magnum 4000, MIPS Millenium and
Olivetti M700-10 workstations.
+config BCM947XX
+ bool "Support for BCM947xx based boards"
+ select DMA_NONCOHERENT
+ select HW_HAS_PCI
+ select IRQ_CPU
+ select SYS_HAS_CPU_MIPS32_R1
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+ select SSB
+ select SSB_SERIAL
+ select SSB_DRIVER_PCICORE
+ select SSB_PCICORE_HOSTMODE
+ select CFE
+ select GENERIC_GPIO
+ help
+ Support for BCM947xx based boards
+
config LASAT
bool "LASAT Networks platforms"
select DMA_NONCOHERENT
Index: linux-2.6.22-rc4/arch/mips/kernel/cpu-probe.c
===================================================================
--- linux-2.6.22-rc4.orig/arch/mips/kernel/cpu-probe.c 2007-06-10 21:32:13.000000000 +0100
+++ linux-2.6.22-rc4/arch/mips/kernel/cpu-probe.c 2007-06-10 21:33:12.000000000 +0100
@@ -711,6 +711,28 @@
}
+static inline void cpu_probe_broadcom(struct cpuinfo_mips *c)
+{
+ decode_config1(c);
+ switch (c->processor_id & 0xff00) {
+ case PRID_IMP_BCM3302:
+ c->cputype = CPU_BCM3302;
+ c->isa_level = MIPS_CPU_ISA_M32R1;
+ c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+ MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER;
+ break;
+ case PRID_IMP_BCM4710:
+ c->cputype = CPU_BCM4710;
+ c->isa_level = MIPS_CPU_ISA_M32R1;
+ c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+ MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER;
+ break;
+ default:
+ c->cputype = CPU_UNKNOWN;
+ break;
+ }
+}
+
__init void cpu_probe(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
@@ -733,6 +755,9 @@
case PRID_COMP_SIBYTE:
cpu_probe_sibyte(c);
break;
+ case PRID_COMP_BROADCOM:
+ cpu_probe_broadcom(c);
+ break;
case PRID_COMP_SANDCRAFT:
cpu_probe_sandcraft(c);
break;
Index: linux-2.6.22-rc4/arch/mips/kernel/proc.c
===================================================================
--- linux-2.6.22-rc4.orig/arch/mips/kernel/proc.c 2007-06-10 21:32:13.000000000 +0100
+++ linux-2.6.22-rc4/arch/mips/kernel/proc.c 2007-06-10 21:33:12.000000000 +0100
@@ -83,6 +83,8 @@
[CPU_VR4181] = "NEC VR4181",
[CPU_VR4181A] = "NEC VR4181A",
[CPU_SR71000] = "Sandcraft SR71000",
+ [CPU_BCM3302] = "Broadcom BCM3302",
+ [CPU_BCM4710] = "Broadcom BCM4710",
[CPU_PR4450] = "Philips PR4450",
};
Index: linux-2.6.22-rc4/arch/mips/Makefile
===================================================================
--- linux-2.6.22-rc4.orig/arch/mips/Makefile 2007-06-10 21:32:56.000000000 +0100
+++ linux-2.6.22-rc4/arch/mips/Makefile 2007-06-10 21:33:12.000000000 +0100
@@ -560,6 +560,18 @@
load-$(CONFIG_SIBYTE_BIGSUR) := 0xffffffff80100000
#
+# Broadcom BCM47XX boards
+#
+core-$(CONFIG_BCM947XX) += arch/mips/bcm947xx/
+cflags-$(CONFIG_BCM947XX) += -Iarch/mips/bcm947xx/include -Iinclude/asm-mips/mach-bcm947xx
+load-$(CONFIG_BCM947XX) := 0xffffffff80001000
+
+#
+# Common Firmware Environment
+#
+core-$(CONFIG_CFE) += arch/mips/cfe/
+
+#
# SNI RM
#
core-$(CONFIG_SNI_RM) += arch/mips/sni/
Index: linux-2.6.22-rc4/arch/mips/mm/tlbex.c
===================================================================
--- linux-2.6.22-rc4.orig/arch/mips/mm/tlbex.c 2007-06-10 21:32:35.000000000 +0100
+++ linux-2.6.22-rc4/arch/mips/mm/tlbex.c 2007-06-10 21:33:12.000000000 +0100
@@ -892,6 +892,8 @@
case CPU_4KSC:
case CPU_20KC:
case CPU_25KF:
+ case CPU_BCM3302:
+ case CPU_BCM4710:
tlbw(p);
break;
Index: linux-2.6.22-rc4/drivers/Kconfig
===================================================================
--- linux-2.6.22-rc4.orig/drivers/Kconfig 2007-06-10 21:32:13.000000000 +0100
+++ linux-2.6.22-rc4/drivers/Kconfig 2007-06-10 21:33:12.000000000 +0100
@@ -56,6 +56,8 @@
source "drivers/hwmon/Kconfig"
+source "drivers/ssb/Kconfig"
+
source "drivers/mfd/Kconfig"
source "drivers/media/Kconfig"
Index: linux-2.6.22-rc4/drivers/Makefile
===================================================================
--- linux-2.6.22-rc4.orig/drivers/Makefile 2007-06-10 21:32:14.000000000 +0100
+++ linux-2.6.22-rc4/drivers/Makefile 2007-06-10 21:33:12.000000000 +0100
@@ -81,3 +81,4 @@
obj-$(CONFIG_DMA_ENGINE) += dma/
obj-$(CONFIG_HID) += hid/
obj-$(CONFIG_PPC_PS3) += ps3/
+obj-$(CONFIG_SSB) += ssb/
Index: linux-2.6.22-rc4/include/asm-mips/bootinfo.h
===================================================================
--- linux-2.6.22-rc4.orig/include/asm-mips/bootinfo.h 2007-06-10 21:32:14.000000000 +0100
+++ linux-2.6.22-rc4/include/asm-mips/bootinfo.h 2007-06-10 21:33:12.000000000 +0100
@@ -213,6 +213,12 @@
#define MACH_GROUP_NEC_EMMA2RH 25 /* NEC EMMA2RH (was 23) */
#define MACH_NEC_MARKEINS 0 /* NEC EMMA2RH Mark-eins */
+/*
+ * Valid machtype for group Broadcom
+ */
+#define MACH_GROUP_BRCM 23 /* Broadcom */
+#define MACH_BCM47XX 1 /* Broadcom BCM47xx */
+
#define CL_SIZE COMMAND_LINE_SIZE
const char *get_system_type(void);
Index: linux-2.6.22-rc4/include/asm-mips/cpu.h
===================================================================
--- linux-2.6.22-rc4.orig/include/asm-mips/cpu.h 2007-06-10 21:32:14.000000000 +0100
+++ linux-2.6.22-rc4/include/asm-mips/cpu.h 2007-06-10 21:33:12.000000000 +0100
@@ -104,6 +104,13 @@
#define PRID_IMP_SR71000 0x0400
/*
+ * These are the PRID's for when 23:16 == PRID_COMP_BROADCOM
+ */
+
+#define PRID_IMP_BCM4710 0x4000
+#define PRID_IMP_BCM3302 0x9000
+
+/*
* Definitions for 7:0 on legacy processors
*/
@@ -200,7 +207,9 @@
#define CPU_SB1A 62
#define CPU_74K 63
#define CPU_R14000 64
-#define CPU_LAST 64
+#define CPU_BCM3302 65
+#define CPU_BCM4710 66
+#define CPU_LAST 66
/*
* ISA Level encodings
Index: linux-2.6.22-rc4/include/linux/pci_ids.h
===================================================================
--- linux-2.6.22-rc4.orig/include/linux/pci_ids.h 2007-06-10 21:32:14.000000000 +0100
+++ linux-2.6.22-rc4/include/linux/pci_ids.h 2007-06-10 21:33:12.000000000 +0100
@@ -1991,6 +1991,7 @@
#define PCI_DEVICE_ID_TIGON3_5906M 0x1713
#define PCI_DEVICE_ID_BCM4401 0x4401
#define PCI_DEVICE_ID_BCM4401B0 0x4402
+#define PCI_DEVICE_ID_BCM4713 0x4713
#define PCI_VENDOR_ID_TOPIC 0x151f
#define PCI_DEVICE_ID_TOPIC_TP560 0x0000

View File

@ -1,29 +0,0 @@
Index: linux-2.6.22-rc4/drivers/mtd/maps/Kconfig
===================================================================
--- linux-2.6.22-rc4.orig/drivers/mtd/maps/Kconfig 2007-06-10 21:32:13.000000000 +0100
+++ linux-2.6.22-rc4/drivers/mtd/maps/Kconfig 2007-06-10 21:33:14.000000000 +0100
@@ -358,6 +358,12 @@
Mapping for the Flaga digital module. If you don't have one, ignore
this setting.
+config MTD_BCM47XX
+ tristate "BCM47xx flash device"
+ depends on MIPS && MTD_CFI && BCM947XX
+ help
+ Support for the flash chips on the BCM947xx board.
+
config MTD_WALNUT
tristate "Flash device mapped on IBM 405GP Walnut"
depends on MTD_JEDECPROBE && WALNUT
Index: linux-2.6.22-rc4/drivers/mtd/maps/Makefile
===================================================================
--- linux-2.6.22-rc4.orig/drivers/mtd/maps/Makefile 2007-06-10 21:32:13.000000000 +0100
+++ linux-2.6.22-rc4/drivers/mtd/maps/Makefile 2007-06-10 21:33:14.000000000 +0100
@@ -33,6 +33,7 @@
obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o
obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o
+obj-$(CONFIG_MTD_BCM47XX) += bcm47xx-flash.o
obj-$(CONFIG_MTD_SA1100) += sa1100-flash.o
obj-$(CONFIG_MTD_IPAQ) += ipaq-flash.o
obj-$(CONFIG_MTD_SBC_GXX) += sbc_gxx.o

File diff suppressed because it is too large Load Diff

View File

@ -1,95 +0,0 @@
Index: linux-2.6.22-rc4/arch/mips/Kconfig
===================================================================
--- linux-2.6.22-rc4.orig/arch/mips/Kconfig 2007-06-10 21:33:12.000000000 +0100
+++ linux-2.6.22-rc4/arch/mips/Kconfig 2007-06-10 21:33:17.000000000 +0100
@@ -202,7 +202,6 @@
select I8259
select MIPS_BOARDS_GEN
select MIPS_BONITO64
- select MIPS_CPU_SCACHE
select PCI_GT64XXX_PCI0
select MIPS_MSC
select SWAP_IO_SPACE
@@ -1345,13 +1344,6 @@
bool
select BOARD_SCACHE
-#
-# Support for a MIPS32 / MIPS64 style S-caches
-#
-config MIPS_CPU_SCACHE
- bool
- select BOARD_SCACHE
-
config R5000_CPU_SCACHE
bool
select BOARD_SCACHE
Index: linux-2.6.22-rc4/arch/mips/kernel/cpu-probe.c
===================================================================
--- linux-2.6.22-rc4.orig/arch/mips/kernel/cpu-probe.c 2007-06-10 21:33:12.000000000 +0100
+++ linux-2.6.22-rc4/arch/mips/kernel/cpu-probe.c 2007-06-10 21:33:17.000000000 +0100
@@ -619,6 +619,8 @@
break;
case PRID_IMP_25KF:
c->cputype = CPU_25KF;
+ /* Probe for L2 cache */
+ c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
break;
case PRID_IMP_34K:
c->cputype = CPU_34K;
Index: linux-2.6.22-rc4/arch/mips/mm/c-r4k.c
===================================================================
--- linux-2.6.22-rc4.orig/arch/mips/mm/c-r4k.c 2007-06-10 21:32:13.000000000 +0100
+++ linux-2.6.22-rc4/arch/mips/mm/c-r4k.c 2007-06-10 21:33:17.000000000 +0100
@@ -1038,7 +1038,6 @@
extern int r5k_sc_init(void);
extern int rm7k_sc_init(void);
-extern int mips_sc_init(void);
static void __init setup_scache(void)
{
@@ -1086,29 +1085,17 @@
return;
default:
- if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
- c->isa_level == MIPS_CPU_ISA_M32R2 ||
- c->isa_level == MIPS_CPU_ISA_M64R1 ||
- c->isa_level == MIPS_CPU_ISA_M64R2) {
-#ifdef CONFIG_MIPS_CPU_SCACHE
- if (mips_sc_init ()) {
- scache_size = c->scache.ways * c->scache.sets * c->scache.linesz;
- printk("MIPS secondary cache %ldkB, %s, linesize %d bytes.\n",
- scache_size >> 10,
- way_string[c->scache.ways], c->scache.linesz);
- }
-#else
- if (!(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
- panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
-#endif
- return;
- }
sc_present = 0;
}
if (!sc_present)
return;
+ if ((c->isa_level == MIPS_CPU_ISA_M32R1 ||
+ c->isa_level == MIPS_CPU_ISA_M64R1) &&
+ !(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
+ panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
+
/* compute a couple of other cache variables */
c->scache.waysize = scache_size / c->scache.ways;
Index: linux-2.6.22-rc4/arch/mips/mm/Makefile
===================================================================
--- linux-2.6.22-rc4.orig/arch/mips/mm/Makefile 2007-06-10 21:32:13.000000000 +0100
+++ linux-2.6.22-rc4/arch/mips/mm/Makefile 2007-06-10 21:33:17.000000000 +0100
@@ -30,4 +30,3 @@
obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o
obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o
obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o
-obj-$(CONFIG_MIPS_CPU_SCACHE) += sc-mips.o

View File

@ -1,643 +0,0 @@
Index: linux-2.6.22/arch/mips/kernel/genex.S
===================================================================
--- linux-2.6.22.orig/arch/mips/kernel/genex.S 2007-07-26 06:29:25.057170943 +0200
+++ linux-2.6.22/arch/mips/kernel/genex.S 2007-07-26 06:29:40.890073208 +0200
@@ -51,6 +51,10 @@
NESTED(except_vec3_generic, 0, sp)
.set push
.set noat
+#ifdef CONFIG_BCM947XX
+ nop
+ nop
+#endif
#if R5432_CP0_INTERRUPT_WAR
mfc0 k0, CP0_INDEX
#endif
Index: linux-2.6.22/arch/mips/mm/c-r4k.c
===================================================================
--- linux-2.6.22.orig/arch/mips/mm/c-r4k.c 2007-07-26 06:29:40.826069560 +0200
+++ linux-2.6.22/arch/mips/mm/c-r4k.c 2007-07-26 06:32:45.956619550 +0200
@@ -29,6 +29,9 @@
#include <asm/cacheflush.h> /* for run_uncached() */
+/* For enabling BCM4710 cache workarounds */
+int bcm4710 = 0;
+
/*
* Special Variant of smp_call_function for use by cache functions:
*
@@ -85,14 +88,21 @@
static inline void r4k_blast_dcache_page_dc32(unsigned long addr)
{
+ unsigned long flags;
+
+ local_irq_save(flags);
R4600_HIT_CACHEOP_WAR_IMPL;
blast_dcache32_page(addr);
+ local_irq_restore(flags);
}
static void __init r4k_blast_dcache_page_setup(void)
{
unsigned long dc_lsize = cpu_dcache_line_size();
+ if (bcm4710)
+ r4k_blast_dcache_page = blast_dcache_page;
+ else
if (dc_lsize == 0)
r4k_blast_dcache_page = (void *)cache_noop;
else if (dc_lsize == 16)
@@ -107,6 +117,9 @@
{
unsigned long dc_lsize = cpu_dcache_line_size();
+ if (bcm4710)
+ r4k_blast_dcache_page_indexed = blast_dcache_page_indexed;
+ else
if (dc_lsize == 0)
r4k_blast_dcache_page_indexed = (void *)cache_noop;
else if (dc_lsize == 16)
@@ -121,6 +134,9 @@
{
unsigned long dc_lsize = cpu_dcache_line_size();
+ if (bcm4710)
+ r4k_blast_dcache = blast_dcache;
+ else
if (dc_lsize == 0)
r4k_blast_dcache = (void *)cache_noop;
else if (dc_lsize == 16)
@@ -202,8 +218,12 @@
static void (* r4k_blast_icache_page)(unsigned long addr);
+static void r4k_flush_cache_all(void);
static void __init r4k_blast_icache_page_setup(void)
{
+#ifdef CONFIG_BCM947XX
+ r4k_blast_icache_page = (void *)r4k_flush_cache_all;
+#else
unsigned long ic_lsize = cpu_icache_line_size();
if (ic_lsize == 0)
@@ -214,6 +234,7 @@
r4k_blast_icache_page = blast_icache32_page;
else if (ic_lsize == 64)
r4k_blast_icache_page = blast_icache64_page;
+#endif
}
@@ -221,6 +242,9 @@
static void __init r4k_blast_icache_page_indexed_setup(void)
{
+#ifdef CONFIG_BCM947XX
+ r4k_blast_icache_page_indexed = (void *)r4k_flush_cache_all;
+#else
unsigned long ic_lsize = cpu_icache_line_size();
if (ic_lsize == 0)
@@ -239,6 +263,7 @@
blast_icache32_page_indexed;
} else if (ic_lsize == 64)
r4k_blast_icache_page_indexed = blast_icache64_page_indexed;
+#endif
}
static void (* r4k_blast_icache)(void);
@@ -322,12 +347,17 @@
*/
static inline void local_r4k_flush_cache_all(void * args)
{
+ unsigned long flags;
+
+ local_irq_save(flags);
r4k_blast_dcache();
+ r4k_blast_icache();
+ local_irq_restore(flags);
}
static void r4k_flush_cache_all(void)
{
- if (!cpu_has_dc_aliases)
+ if (!cpu_has_dc_aliases && cpu_use_kmap_coherent)
return;
r4k_on_each_cpu(local_r4k_flush_cache_all, NULL, 1, 1);
@@ -335,6 +365,9 @@
static inline void local_r4k___flush_cache_all(void * args)
{
+ unsigned long flags;
+
+ local_irq_save(flags);
r4k_blast_dcache();
r4k_blast_icache();
@@ -348,6 +381,7 @@
case CPU_R14000:
r4k_blast_scache();
}
+ local_irq_restore(flags);
}
static void r4k___flush_cache_all(void)
@@ -358,17 +392,21 @@
static inline void local_r4k_flush_cache_range(void * args)
{
struct vm_area_struct *vma = args;
+ unsigned long flags;
if (!(cpu_context(smp_processor_id(), vma->vm_mm)))
return;
+ local_irq_save(flags);
r4k_blast_dcache();
+ r4k_blast_icache();
+ local_irq_restore(flags);
}
static void r4k_flush_cache_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
{
- if (!cpu_has_dc_aliases)
+ if (!cpu_has_dc_aliases && cpu_use_kmap_coherent)
return;
r4k_on_each_cpu(local_r4k_flush_cache_range, vma, 1, 1);
@@ -377,6 +415,7 @@
static inline void local_r4k_flush_cache_mm(void * args)
{
struct mm_struct *mm = args;
+ unsigned long flags;
if (!cpu_context(smp_processor_id(), mm))
return;
@@ -395,12 +434,15 @@
return;
}
+ local_irq_save(flags);
r4k_blast_dcache();
+ r4k_blast_icache();
+ local_irq_restore(flags);
}
static void r4k_flush_cache_mm(struct mm_struct *mm)
{
- if (!cpu_has_dc_aliases)
+ if (!cpu_has_dc_aliases && cpu_use_kmap_coherent)
return;
r4k_on_each_cpu(local_r4k_flush_cache_mm, mm, 1, 1);
@@ -420,6 +462,7 @@
unsigned long paddr = fcp_args->pfn << PAGE_SHIFT;
int exec = vma->vm_flags & VM_EXEC;
struct mm_struct *mm = vma->vm_mm;
+ unsigned long flags;
pgd_t *pgdp;
pud_t *pudp;
pmd_t *pmdp;
@@ -451,8 +494,9 @@
* for every cache flush operation. So we do indexed flushes
* in that case, which doesn't overly flush the cache too much.
*/
+ local_irq_save(flags);
if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) {
- if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
+ if (!cpu_use_kmap_coherent || cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
r4k_blast_dcache_page(addr);
if (exec && !cpu_icache_snoops_remote_store)
r4k_blast_scache_page(addr);
@@ -460,14 +504,14 @@
if (exec)
r4k_blast_icache_page(addr);
- return;
+ goto done;
}
/*
* Do indexed flush, too much work to get the (possible) TLB refills
* to work correctly.
*/
- if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
+ if (!cpu_use_kmap_coherent || cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
r4k_blast_dcache_page_indexed(cpu_has_pindexed_dcache ?
paddr : addr);
if (exec && !cpu_icache_snoops_remote_store) {
@@ -483,6 +527,8 @@
} else
r4k_blast_icache_page_indexed(addr);
}
+done:
+ local_irq_restore(flags);
}
static void r4k_flush_cache_page(struct vm_area_struct *vma,
@@ -499,7 +545,11 @@
static inline void local_r4k_flush_data_cache_page(void * addr)
{
+ unsigned long flags;
+
+ local_irq_save(flags);
r4k_blast_dcache_page((unsigned long) addr);
+ local_irq_restore(flags);
}
static void r4k_flush_data_cache_page(unsigned long addr)
@@ -542,6 +592,9 @@
static void r4k_flush_icache_range(unsigned long start, unsigned long end)
{
+#ifdef CONFIG_BCM947XX
+ r4k_flush_cache_all();
+#else
struct flush_icache_range_args args;
args.start = start;
@@ -549,12 +602,15 @@
r4k_on_each_cpu(local_r4k_flush_icache_range, &args, 1, 1);
instruction_hazard();
+#endif
}
#ifdef CONFIG_DMA_NONCOHERENT
static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
{
+ unsigned long flags;
+
/* Catch bad driver code */
BUG_ON(size == 0);
@@ -571,18 +627,21 @@
* subset property so we have to flush the primary caches
* explicitly
*/
+ local_irq_save(flags);
if (size >= dcache_size) {
r4k_blast_dcache();
} else {
R4600_HIT_CACHEOP_WAR_IMPL;
blast_dcache_range(addr, addr + size);
}
-
bc_wback_inv(addr, size);
+ local_irq_restore(flags);
}
static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
{
+ unsigned long flags;
+
/* Catch bad driver code */
BUG_ON(size == 0);
@@ -594,6 +653,7 @@
return;
}
+ local_irq_save(flags);
if (size >= dcache_size) {
r4k_blast_dcache();
} else {
@@ -602,6 +662,7 @@
}
bc_inv(addr, size);
+ local_irq_restore(flags);
}
#endif /* CONFIG_DMA_NONCOHERENT */
@@ -616,8 +677,12 @@
unsigned long dc_lsize = cpu_dcache_line_size();
unsigned long sc_lsize = cpu_scache_line_size();
unsigned long addr = (unsigned long) arg;
+ unsigned long flags;
+ local_irq_save(flags);
R4600_HIT_CACHEOP_WAR_IMPL;
+ BCM4710_PROTECTED_FILL_TLB(addr);
+ BCM4710_PROTECTED_FILL_TLB(addr + 4);
if (dc_lsize)
protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
if (!cpu_icache_snoops_remote_store && scache_size)
@@ -644,6 +709,7 @@
}
if (MIPS_CACHE_SYNC_WAR)
__asm__ __volatile__ ("sync");
+ local_irq_restore(flags);
}
static void r4k_flush_cache_sigtramp(unsigned long addr)
@@ -1144,6 +1210,17 @@
* silly idea of putting something else there ...
*/
switch (current_cpu_data.cputype) {
+ case CPU_BCM3302:
+ {
+ u32 cm;
+ cm = read_c0_diag();
+ /* Enable icache */
+ cm |= (1 << 31);
+ /* Enable dcache */
+ cm |= (1 << 30);
+ write_c0_diag(cm);
+ }
+ break;
case CPU_R4000PC:
case CPU_R4000SC:
case CPU_R4000MC:
@@ -1174,6 +1251,15 @@
/* Default cache error handler for R4000 and R5000 family */
set_uncached_handler (0x100, &except_vec2_generic, 0x80);
+ /* Check if special workarounds are required */
+#ifdef CONFIG_BCM947XX
+ if (current_cpu_data.cputype == CPU_BCM4710 && (current_cpu_data.processor_id & 0xff) == 0) {
+ printk("Enabling BCM4710A0 cache workarounds.\n");
+ bcm4710 = 1;
+ } else
+#endif
+ bcm4710 = 0;
+
probe_pcache();
setup_scache();
@@ -1219,5 +1305,13 @@
build_clear_page();
build_copy_page();
local_r4k___flush_cache_all(NULL);
+#ifdef CONFIG_BCM947XX
+ {
+ static void (*_coherency_setup)(void);
+ _coherency_setup = (void (*)(void)) KSEG1ADDR(coherency_setup);
+ _coherency_setup();
+ }
+#else
coherency_setup();
+#endif
}
Index: linux-2.6.22/arch/mips/mm/tlbex.c
===================================================================
--- linux-2.6.22.orig/arch/mips/mm/tlbex.c 2007-07-26 06:29:40.582055658 +0200
+++ linux-2.6.22/arch/mips/mm/tlbex.c 2007-07-26 06:32:45.964620005 +0200
@@ -1229,6 +1229,10 @@
#endif
}
+#ifdef CONFIG_BCM947XX
+extern int bcm4710;
+#endif
+
static void __init build_r4000_tlb_refill_handler(void)
{
u32 *p = tlb_handler;
@@ -1243,6 +1247,10 @@
memset(relocs, 0, sizeof(relocs));
memset(final_handler, 0, sizeof(final_handler));
+#ifdef CONFIG_BCM947XX
+ i_nop(&p);
+#endif
+
/*
* create the plain linear handler
*/
@@ -1736,6 +1744,9 @@
memset(labels, 0, sizeof(labels));
memset(relocs, 0, sizeof(relocs));
+#ifdef CONFIG_BCM947XX
+ i_nop(&p);
+#endif
if (bcm1250_m3_war()) {
i_MFC0(&p, K0, C0_BADVADDR);
i_MFC0(&p, K1, C0_ENTRYHI);
Index: linux-2.6.22/include/asm-mips/r4kcache.h
===================================================================
--- linux-2.6.22.orig/include/asm-mips/r4kcache.h 2007-07-26 06:29:25.085172538 +0200
+++ linux-2.6.22/include/asm-mips/r4kcache.h 2007-07-26 06:29:40.938075943 +0200
@@ -17,6 +17,20 @@
#include <asm/cpu-features.h>
#include <asm/mipsmtregs.h>
+#ifdef CONFIG_BCM947XX
+#include <asm/paccess.h>
+#include <linux/ssb/ssb.h>
+#define BCM4710_DUMMY_RREG() ((void) *((u8 *) KSEG1ADDR(SSB_ENUM_BASE + SSB_IMSTATE)))
+
+#define BCM4710_FILL_TLB(addr) (*(volatile unsigned long *)(addr))
+#define BCM4710_PROTECTED_FILL_TLB(addr) ({ unsigned long x; get_dbe(x, (volatile unsigned long *)(addr)); })
+#else
+#define BCM4710_DUMMY_RREG()
+
+#define BCM4710_FILL_TLB(addr)
+#define BCM4710_PROTECTED_FILL_TLB(addr)
+#endif
+
/*
* This macro return a properly sign-extended address suitable as base address
* for indexed cache operations. Two issues here:
@@ -150,6 +164,7 @@
static inline void flush_dcache_line_indexed(unsigned long addr)
{
__dflush_prologue
+ BCM4710_DUMMY_RREG();
cache_op(Index_Writeback_Inv_D, addr);
__dflush_epilogue
}
@@ -169,6 +184,7 @@
static inline void flush_dcache_line(unsigned long addr)
{
__dflush_prologue
+ BCM4710_DUMMY_RREG();
cache_op(Hit_Writeback_Inv_D, addr);
__dflush_epilogue
}
@@ -176,6 +192,7 @@
static inline void invalidate_dcache_line(unsigned long addr)
{
__dflush_prologue
+ BCM4710_DUMMY_RREG();
cache_op(Hit_Invalidate_D, addr);
__dflush_epilogue
}
@@ -208,6 +225,7 @@
*/
static inline void protected_flush_icache_line(unsigned long addr)
{
+ BCM4710_DUMMY_RREG();
protected_cache_op(Hit_Invalidate_I, addr);
}
@@ -219,6 +237,7 @@
*/
static inline void protected_writeback_dcache_line(unsigned long addr)
{
+ BCM4710_DUMMY_RREG();
protected_cache_op(Hit_Writeback_Inv_D, addr);
}
@@ -339,8 +358,52 @@
: "r" (base), \
"i" (op));
+static inline void blast_dcache(void)
+{
+ unsigned long start = KSEG0;
+ unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways;
+ unsigned long end = (start + dcache_size);
+
+ do {
+ BCM4710_DUMMY_RREG();
+ cache_op(Index_Writeback_Inv_D, start);
+ start += current_cpu_data.dcache.linesz;
+ } while(start < end);
+}
+
+static inline void blast_dcache_page(unsigned long page)
+{
+ unsigned long start = page;
+ unsigned long end = start + PAGE_SIZE;
+
+ BCM4710_FILL_TLB(start);
+ do {
+ BCM4710_DUMMY_RREG();
+ cache_op(Hit_Writeback_Inv_D, start);
+ start += current_cpu_data.dcache.linesz;
+ } while(start < end);
+}
+
+static inline void blast_dcache_page_indexed(unsigned long page)
+{
+ unsigned long start = page;
+ unsigned long end = start + PAGE_SIZE;
+ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
+ unsigned long ws_end = current_cpu_data.dcache.ways <<
+ current_cpu_data.dcache.waybit;
+ unsigned long ws, addr;
+ for (ws = 0; ws < ws_end; ws += ws_inc) {
+ start = page + ws;
+ for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) {
+ BCM4710_DUMMY_RREG();
+ cache_op(Index_Writeback_Inv_D, addr);
+ }
+ }
+}
+
+
/* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
-#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \
+#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, war) \
static inline void blast_##pfx##cache##lsize(void) \
{ \
unsigned long start = INDEX_BASE; \
@@ -352,6 +415,7 @@
\
__##pfx##flush_prologue \
\
+ war \
for (ws = 0; ws < ws_end; ws += ws_inc) \
for (addr = start; addr < end; addr += lsize * 32) \
cache##lsize##_unroll32(addr|ws,indexop); \
@@ -366,6 +430,7 @@
\
__##pfx##flush_prologue \
\
+ war \
do { \
cache##lsize##_unroll32(start,hitop); \
start += lsize * 32; \
@@ -384,6 +449,8 @@
current_cpu_data.desc.waybit; \
unsigned long ws, addr; \
\
+ war \
+ \
__##pfx##flush_prologue \
\
for (ws = 0; ws < ws_end; ws += ws_inc) \
@@ -393,28 +460,30 @@
__##pfx##flush_epilogue \
}
-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, BCM4710_FILL_TLB(start);)
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, )
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, BCM4710_FILL_TLB(start);)
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, )
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, BCM4710_FILL_TLB(start);)
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
/* build blast_xxx_range, protected_blast_xxx_range */
-#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \
+#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, war, war2) \
static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
unsigned long end) \
{ \
unsigned long lsize = cpu_##desc##_line_size(); \
unsigned long addr = start & ~(lsize - 1); \
unsigned long aend = (end - 1) & ~(lsize - 1); \
+ war \
\
__##pfx##flush_prologue \
\
while (1) { \
+ war2 \
prot##cache_op(hitop, addr); \
if (addr == aend) \
break; \
@@ -424,13 +493,13 @@
__##pfx##flush_epilogue \
}
-__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
-__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_)
-__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_)
-__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, )
-__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, )
+__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, BCM4710_PROTECTED_FILL_TLB(addr); BCM4710_PROTECTED_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
+__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_,, )
+__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_,, )
+__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D,, BCM4710_FILL_TLB(addr); BCM4710_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
+__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD,,, )
/* blast_inv_dcache_range */
-__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, )
-__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, )
+__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D,,,BCM4710_DUMMY_RREG();)
+__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD,,, )
#endif /* _ASM_R4KCACHE_H */
Index: linux-2.6.22/include/asm-mips/stackframe.h
===================================================================
--- linux-2.6.22.orig/include/asm-mips/stackframe.h 2007-07-26 06:29:25.093172994 +0200
+++ linux-2.6.22/include/asm-mips/stackframe.h 2007-07-26 06:29:40.962077312 +0200
@@ -350,6 +350,10 @@
.macro RESTORE_SP_AND_RET
LONG_L sp, PT_R29(sp)
.set mips3
+#ifdef CONFIG_BCM947XX
+ nop
+ nop
+#endif
eret
.set mips0
.endm

View File

@ -1,63 +0,0 @@
Index: linux-2.6.22-rc6/arch/mips/mm/init.c
===================================================================
--- linux-2.6.22-rc6.orig/arch/mips/mm/init.c 2007-07-04 02:17:11.423962000 +0200
+++ linux-2.6.22-rc6/arch/mips/mm/init.c 2007-07-04 02:17:31.269202250 +0200
@@ -207,7 +207,7 @@
void *vfrom, *vto;
vto = kmap_atomic(to, KM_USER1);
- if (cpu_has_dc_aliases) {
+ if (cpu_has_dc_aliases && cpu_use_kmap_coherent) {
vfrom = kmap_coherent(from, vaddr);
copy_page(vto, vfrom);
kunmap_coherent();
@@ -230,7 +230,7 @@
struct page *page, unsigned long vaddr, void *dst, const void *src,
unsigned long len)
{
- if (cpu_has_dc_aliases) {
+ if (cpu_has_dc_aliases && cpu_use_kmap_coherent) {
void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
memcpy(vto, src, len);
kunmap_coherent();
@@ -246,7 +246,7 @@
struct page *page, unsigned long vaddr, void *dst, const void *src,
unsigned long len)
{
- if (cpu_has_dc_aliases) {
+ if (cpu_has_dc_aliases && cpu_use_kmap_coherent) {
void *vfrom =
kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
memcpy(dst, vfrom, len);
Index: linux-2.6.22-rc6/include/asm-mips/mach-bcm947xx/cpu-feature-overrides.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.22-rc6/include/asm-mips/mach-bcm947xx/cpu-feature-overrides.h 2007-07-04 02:17:31.273202500 +0200
@@ -0,0 +1,13 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
+ */
+#ifndef __ASM_MACH_BCM947XX_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_BCM947XX_CPU_FEATURE_OVERRIDES_H
+
+#define cpu_use_kmap_coherent 0
+
+#endif /* __ASM_MACH_BCM947XX_CPU_FEATURE_OVERRIDES_H */
Index: linux-2.6.22-rc6/include/asm-mips/cpu-features.h
===================================================================
--- linux-2.6.22-rc6.orig/include/asm-mips/cpu-features.h 2007-07-04 02:17:11.455964000 +0200
+++ linux-2.6.22-rc6/include/asm-mips/cpu-features.h 2007-07-04 02:17:31.305204500 +0200
@@ -101,6 +101,9 @@
#ifndef cpu_has_pindexed_dcache
#define cpu_has_pindexed_dcache (cpu_data[0].dcache.flags & MIPS_CACHE_PINDEX)
#endif
+#ifndef cpu_use_kmap_coherent
+#define cpu_use_kmap_coherent 1
+#endif
/*
* I-Cache snoops remote store. This only matters on SMP. Some multiprocessors

View File

@ -1,12 +0,0 @@
Index: linux-2.6.22-rc4/arch/mips/kernel/cpu-probe.c
===================================================================
--- linux-2.6.22-rc4.orig/arch/mips/kernel/cpu-probe.c 2007-06-10 21:33:17.000000000 +0100
+++ linux-2.6.22-rc4/arch/mips/kernel/cpu-probe.c 2007-06-10 21:33:22.000000000 +0100
@@ -139,6 +139,7 @@
case CPU_5KC:
case CPU_25KF:
case CPU_PR4450:
+ case CPU_BCM3302:
cpu_wait = r4k_wait;
break;

View File

@ -1,256 +0,0 @@
Index: linux-2.6.22-rc4/drivers/net/b44.c
===================================================================
--- linux-2.6.22-rc4.orig/drivers/net/b44.c 2007-06-10 21:33:15.000000000 +0100
+++ linux-2.6.22-rc4/drivers/net/b44.c 2007-06-10 21:33:23.000000000 +0100
@@ -128,7 +128,7 @@
unsigned long offset,
enum dma_data_direction dir)
{
- dma_sync_single_range_for_device(&sdev->dev, dma_base,
+ dma_sync_single_range_for_device(sdev->dev, dma_base,
offset & dma_desc_align_mask,
dma_desc_sync_size, dir);
}
@@ -138,7 +138,7 @@
unsigned long offset,
enum dma_data_direction dir)
{
- dma_sync_single_range_for_cpu(&sdev->dev, dma_base,
+ dma_sync_single_range_for_cpu(sdev->dev, dma_base,
offset & dma_desc_align_mask,
dma_desc_sync_size, dir);
}
@@ -563,7 +563,7 @@
BUG_ON(skb == NULL);
- dma_unmap_single(&bp->sdev->dev,
+ dma_unmap_single(bp->sdev->dev,
pci_unmap_addr(rp, mapping),
skb->len,
DMA_TO_DEVICE);
@@ -603,7 +603,7 @@
if (skb == NULL)
return -ENOMEM;
- mapping = dma_map_single(&bp->sdev->dev, skb->data,
+ mapping = dma_map_single(bp->sdev->dev, skb->data,
RX_PKT_BUF_SZ,
DMA_FROM_DEVICE);
@@ -613,18 +613,18 @@
mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) {
/* Sigh... */
if (!dma_mapping_error(mapping))
- dma_unmap_single(&bp->sdev->dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
+ dma_unmap_single(bp->sdev->dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
skb = __dev_alloc_skb(RX_PKT_BUF_SZ,GFP_DMA);
if (skb == NULL)
return -ENOMEM;
- mapping = dma_map_single(&bp->sdev->dev, skb->data,
+ mapping = dma_map_single(bp->sdev->dev, skb->data,
RX_PKT_BUF_SZ,
DMA_FROM_DEVICE);
if (dma_mapping_error(mapping) ||
mapping + RX_PKT_BUF_SZ > DMA_30BIT_MASK) {
if (!dma_mapping_error(mapping))
- dma_unmap_single(&bp->sdev->dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
+ dma_unmap_single(bp->sdev->dev, mapping, RX_PKT_BUF_SZ,DMA_FROM_DEVICE);
dev_kfree_skb_any(skb);
return -ENOMEM;
}
@@ -702,7 +702,7 @@
dest_idx * sizeof(dest_desc),
DMA_BIDIRECTIONAL);
- dma_sync_single_for_device(&bp->sdev->dev, le32_to_cpu(src_desc->addr),
+ dma_sync_single_for_device(bp->sdev->dev, le32_to_cpu(src_desc->addr),
RX_PKT_BUF_SZ,
DMA_FROM_DEVICE);
}
@@ -724,7 +724,7 @@
struct rx_header *rh;
u16 len;
- dma_sync_single_for_cpu(&bp->sdev->dev, map,
+ dma_sync_single_for_cpu(bp->sdev->dev, map,
RX_PKT_BUF_SZ,
DMA_FROM_DEVICE);
rh = (struct rx_header *) skb->data;
@@ -758,7 +758,7 @@
skb_size = b44_alloc_rx_skb(bp, cons, bp->rx_prod);
if (skb_size < 0)
goto drop_it;
- dma_unmap_single(&bp->sdev->dev, map,
+ dma_unmap_single(bp->sdev->dev, map,
skb_size, DMA_FROM_DEVICE);
/* Leave out rx_header */
skb_put(skb, len+bp->rx_offset);
@@ -931,22 +931,22 @@
goto err_out;
}
- mapping = dma_map_single(&bp->sdev->dev, skb->data, len, DMA_TO_DEVICE);
+ mapping = dma_map_single(bp->sdev->dev, skb->data, len, DMA_TO_DEVICE);
if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
/* Chip can't handle DMA to/from >1GB, use bounce buffer */
if (!dma_mapping_error(mapping))
- dma_unmap_single(&bp->sdev->dev, mapping, len, DMA_TO_DEVICE);
+ dma_unmap_single(bp->sdev->dev, mapping, len, DMA_TO_DEVICE);
bounce_skb = __dev_alloc_skb(TX_PKT_BUF_SZ,
GFP_ATOMIC|GFP_DMA);
if (!bounce_skb)
goto err_out;
- mapping = dma_map_single(&bp->sdev->dev, bounce_skb->data,
+ mapping = dma_map_single(bp->sdev->dev, bounce_skb->data,
len, DMA_TO_DEVICE);
if (dma_mapping_error(mapping) || mapping + len > DMA_30BIT_MASK) {
if (!dma_mapping_error(mapping))
- dma_unmap_single(&bp->sdev->dev, mapping,
+ dma_unmap_single(bp->sdev->dev, mapping,
len, DMA_TO_DEVICE);
dev_kfree_skb_any(bounce_skb);
goto err_out;
@@ -1046,7 +1046,7 @@
if (rp->skb == NULL)
continue;
- dma_unmap_single(&bp->sdev->dev,
+ dma_unmap_single(bp->sdev->dev,
pci_unmap_addr(rp, mapping),
RX_PKT_BUF_SZ,
DMA_FROM_DEVICE);
@@ -1060,7 +1060,7 @@
if (rp->skb == NULL)
continue;
- dma_unmap_single(&bp->sdev->dev,
+ dma_unmap_single(bp->sdev->dev,
pci_unmap_addr(rp, mapping),
rp->skb->len,
DMA_TO_DEVICE);
@@ -1085,12 +1085,12 @@
memset(bp->tx_ring, 0, B44_TX_RING_BYTES);
if (bp->flags & B44_FLAG_RX_RING_HACK)
- dma_sync_single_for_device(&bp->sdev->dev, bp->rx_ring_dma,
+ dma_sync_single_for_device(bp->sdev->dev, bp->rx_ring_dma,
DMA_TABLE_BYTES,
DMA_BIDIRECTIONAL);
if (bp->flags & B44_FLAG_TX_RING_HACK)
- dma_sync_single_for_device(&bp->sdev->dev, bp->tx_ring_dma,
+ dma_sync_single_for_device(bp->sdev->dev, bp->tx_ring_dma,
DMA_TABLE_BYTES,
DMA_TO_DEVICE);
@@ -1112,24 +1112,24 @@
bp->tx_buffers = NULL;
if (bp->rx_ring) {
if (bp->flags & B44_FLAG_RX_RING_HACK) {
- dma_unmap_single(&bp->sdev->dev, bp->rx_ring_dma,
+ dma_unmap_single(bp->sdev->dev, bp->rx_ring_dma,
DMA_TABLE_BYTES,
DMA_BIDIRECTIONAL);
kfree(bp->rx_ring);
} else
- dma_free_coherent(&bp->sdev->dev, DMA_TABLE_BYTES,
+ dma_free_coherent(bp->sdev->dev, DMA_TABLE_BYTES,
bp->rx_ring, bp->rx_ring_dma);
bp->rx_ring = NULL;
bp->flags &= ~B44_FLAG_RX_RING_HACK;
}
if (bp->tx_ring) {
if (bp->flags & B44_FLAG_TX_RING_HACK) {
- dma_unmap_single(&bp->sdev->dev, bp->tx_ring_dma,
+ dma_unmap_single(bp->sdev->dev, bp->tx_ring_dma,
DMA_TABLE_BYTES,
DMA_TO_DEVICE);
kfree(bp->tx_ring);
} else
- dma_free_coherent(&bp->sdev->dev, DMA_TABLE_BYTES,
+ dma_free_coherent(bp->sdev->dev, DMA_TABLE_BYTES,
bp->tx_ring, bp->tx_ring_dma);
bp->tx_ring = NULL;
bp->flags &= ~B44_FLAG_TX_RING_HACK;
@@ -1155,7 +1155,7 @@
goto out_err;
size = DMA_TABLE_BYTES;
- bp->rx_ring = dma_alloc_coherent(&bp->sdev->dev, size, &bp->rx_ring_dma, GFP_ATOMIC);
+ bp->rx_ring = dma_alloc_coherent(bp->sdev->dev, size, &bp->rx_ring_dma, GFP_ATOMIC);
if (!bp->rx_ring) {
/* Allocation may have failed due to pci_alloc_consistent
insisting on use of GFP_DMA, which is more restrictive
@@ -1167,7 +1167,7 @@
if (!rx_ring)
goto out_err;
- rx_ring_dma = dma_map_single(&bp->sdev->dev, rx_ring,
+ rx_ring_dma = dma_map_single(bp->sdev->dev, rx_ring,
DMA_TABLE_BYTES,
DMA_BIDIRECTIONAL);
@@ -1182,7 +1182,7 @@
bp->flags |= B44_FLAG_RX_RING_HACK;
}
- bp->tx_ring = dma_alloc_coherent(&bp->sdev->dev, size, &bp->tx_ring_dma, GFP_ATOMIC);
+ bp->tx_ring = dma_alloc_coherent(bp->sdev->dev, size, &bp->tx_ring_dma, GFP_ATOMIC);
if (!bp->tx_ring) {
/* Allocation may have failed due to dma_alloc_coherent
insisting on use of GFP_DMA, which is more restrictive
@@ -1194,7 +1194,7 @@
if (!tx_ring)
goto out_err;
- tx_ring_dma = dma_map_single(&bp->sdev->dev, tx_ring,
+ tx_ring_dma = dma_map_single(bp->sdev->dev, tx_ring,
DMA_TABLE_BYTES,
DMA_TO_DEVICE);
@@ -2314,13 +2314,13 @@
dev = alloc_etherdev(sizeof(*bp));
if (!dev) {
- dev_err(&sdev->dev, "Etherdev alloc failed, aborting.\n");
+ dev_err(sdev->dev, "Etherdev alloc failed, aborting.\n");
err = -ENOMEM;
goto out;
}
SET_MODULE_OWNER(dev);
- SET_NETDEV_DEV(dev,&sdev->dev);
+ SET_NETDEV_DEV(dev,sdev->dev);
/* No interesting netdevice features in this card... */
dev->features |= 0;
@@ -2358,7 +2358,7 @@
err = b44_get_invariants(bp);
if (err) {
- dev_err(&sdev->dev,
+ dev_err(sdev->dev,
"Problem fetching invariants of chip, aborting.\n");
goto err_out_free_dev;
}
@@ -2379,7 +2379,7 @@
err = register_netdev(dev);
if (err) {
- dev_err(&sdev->dev, "Cannot register net device, aborting.\n");
+ dev_err(sdev->dev, "Cannot register net device, aborting.\n");
goto out;
}
@@ -2458,7 +2458,6 @@
rc = request_irq(dev->irq, b44_interrupt, IRQF_SHARED, dev->name, dev);
if (rc) {
printk(KERN_ERR PFX "%s: request_irq failed\n", dev->name);
- pci_disable_device(pdev);
return rc;
}

View File

@ -1,372 +0,0 @@
Index: linux-2.6.22-rc5/drivers/ssb/driver_chipcommon.c
===================================================================
--- linux-2.6.22-rc5.orig/drivers/ssb/driver_chipcommon.c 2007-06-21 23:04:38.000000000 +0100
+++ linux-2.6.22-rc5/drivers/ssb/driver_chipcommon.c 2007-06-24 20:07:15.000000000 +0100
@@ -264,6 +264,31 @@
ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
}
+/* TODO: These two functions are a clear candidate for merging, but one gets
+ * the processor clock, and the other gets the bus clock.
+ */
+void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,
+ u32 *plltype, u32 *n, u32 *m)
+{
+ *n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N);
+ *plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
+ switch (*plltype) {
+ case SSB_PLLTYPE_2:
+ case SSB_PLLTYPE_4:
+ case SSB_PLLTYPE_6:
+ case SSB_PLLTYPE_7:
+ *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_MIPS);
+ break;
+ case SSB_PLLTYPE_3:
+ /* 5350 uses m2 to control mips */
+ *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_M2);
+ break;
+ default:
+ *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_SB);
+ break;
+ }
+}
+
void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc,
u32 *plltype, u32 *n, u32 *m)
{
@@ -400,3 +425,13 @@
return nr_ports;
}
#endif /* CONFIG_SSB_SERIAL */
+
+/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
+int
+ssb_chipco_watchdog(struct ssb_chipcommon *cc, uint ticks)
+{
+ /* instant NMI */
+ chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks);
+ return 0;
+}
+EXPORT_SYMBOL(ssb_chipco_watchdog);
Index: linux-2.6.22-rc5/drivers/ssb/driver_mipscore.c
===================================================================
--- linux-2.6.22-rc5.orig/drivers/ssb/driver_mipscore.c 2007-06-10 16:44:31.000000000 +0100
+++ linux-2.6.22-rc5/drivers/ssb/driver_mipscore.c 2007-06-24 20:48:52.000000000 +0100
@@ -4,6 +4,7 @@
*
* Copyright 2005, Broadcom Corporation
* Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Felix Fietkau <nbd@openwrt.org>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
@@ -31,6 +32,16 @@
ssb_write32(mcore->dev, offset, value);
}
+static inline u32 extif_read32(struct ssb_extif *extif, u16 offset)
+{
+ return ssb_read32(extif->dev, offset);
+}
+
+static inline void extif_write32(struct ssb_extif *extif, u16 offset, u32 value)
+{
+ ssb_write32(extif->dev, offset, value);
+}
+
static const u32 ipsflag_irq_mask[] = {
0,
SSB_IPSFLAG_IRQ1,
@@ -118,9 +129,9 @@
}
/* XXX: leave here or move into separate extif driver? */
-static int ssb_extif_serial_init(struct ssb_device *dev, struct ssb_serial_ports *ports)
+static int ssb_extif_serial_init(struct ssb_extif *dev, struct ssb_serial_port *ports)
{
-
+ return 0;
}
@@ -174,23 +185,76 @@
{
struct ssb_bus *bus = mcore->dev->bus;
+ mcore->flash_buswidth = 2;
if (bus->chipco.dev) {
mcore->flash_window = 0x1c000000;
- mcore->flash_window_size = 0x800000;
+ mcore->flash_window_size = 0x02000000;
+ if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG)
+ & SSB_CHIPCO_CFG_DS16) == 0)
+ mcore->flash_buswidth = 1;
} else {
mcore->flash_window = 0x1fc00000;
- mcore->flash_window_size = 0x400000;
+ mcore->flash_window_size = 0x00400000;
}
}
+static void ssb_extif_timing_init(struct ssb_extif *extif, u32 ns)
+{
+ u32 tmp;
+
+ /* Initialize extif so we can get to the LEDs and external UART */
+ extif_write32(extif, SSB_EXTIF_PROG_CFG, SSB_EXTCFG_EN);
+
+ /* Set timing for the flash */
+ tmp = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT;
+ tmp |= DIV_ROUND_UP(40, ns) << SSB_PROG_WCNT_1_SHIFT;
+ tmp |= DIV_ROUND_UP(120, ns);
+ extif_write32(extif, SSB_EXTIF_PROG_WAITCNT, tmp);
+
+ /* Set programmable interface timing for external uart */
+ tmp = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT;
+ tmp |= DIV_ROUND_UP(20, ns) << SSB_PROG_WCNT_2_SHIFT;
+ tmp |= DIV_ROUND_UP(100, ns) << SSB_PROG_WCNT_1_SHIFT;
+ tmp |= DIV_ROUND_UP(120, ns);
+ extif_write32(extif, SSB_EXTIF_PROG_WAITCNT, tmp);
+}
-static void ssb_cpu_clock(struct ssb_mipscore *mcore)
+static inline void ssb_extif_get_clockcontrol(struct ssb_extif *extif,
+ u32 *pll_type, u32 *n, u32 *m)
{
+ *pll_type = SSB_PLLTYPE_1;
+ *n = extif_read32(extif, SSB_EXTIF_CLOCK_N);
+ *m = extif_read32(extif, SSB_EXTIF_CLOCK_SB);
}
-void ssb_mipscore_init(struct ssb_mipscore *mcore)
+u32 ssb_cpu_clock(struct ssb_mipscore *mcore)
{
struct ssb_bus *bus = mcore->dev->bus;
+ u32 pll_type, n, m, rate = 0;
+
+ if (bus->extif.dev) {
+ ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m);
+ } else if (bus->chipco.dev) {
+ ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m);
+ } else
+ return 0;
+
+ if ((pll_type == SSB_PLLTYPE_5) || (bus->chip_id == 0x5365)) {
+ rate = 200000000;
+ } else {
+ rate = ssb_calc_clock_rate(pll_type, n, m);
+ }
+
+ if (pll_type == SSB_PLLTYPE_6) {
+ rate *= 2;
+ }
+
+ return rate;
+}
+
+void ssb_mipscore_init(struct ssb_mipscore *mcore)
+{
+ struct ssb_bus *bus;
struct ssb_device *dev;
unsigned long hz, ns;
unsigned int irq, i;
@@ -198,6 +262,8 @@
if (!mcore->dev)
return; /* We don't have a MIPS core */
+ bus = mcore->dev->bus;
+
ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n");
hz = ssb_clockspeed(bus);
@@ -205,28 +271,9 @@
hz = 100000000;
ns = 1000000000 / hz;
-//TODO
-#if 0
- if (have EXTIF) {
- /* Initialize extif so we can get to the LEDs and external UART */
- W_REG(&eir->prog_config, CF_EN);
-
- /* Set timing for the flash */
- tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
- tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */
- tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
- W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
-
- /* Set programmable interface timing for external uart */
- tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
- tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */
- tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */
- tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
- W_REG(&eir->prog_waitcount, tmp);
- }
- else... chipcommon
-#endif
- if (bus->chipco.dev)
+ if (bus->extif.dev)
+ ssb_extif_timing_init(&bus->extif, ns);
+ else if (bus->chipco.dev)
ssb_chipco_timing_init(&bus->chipco, ns);
/* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */
@@ -256,3 +303,5 @@
ssb_mips_serial_init(mcore);
ssb_mips_flash_detect(mcore);
}
+
+EXPORT_SYMBOL(ssb_mips_irq);
Index: linux-2.6.22-rc5/include/linux/ssb/ssb_driver_chipcommon.h
===================================================================
--- linux-2.6.22-rc5.orig/include/linux/ssb/ssb_driver_chipcommon.h 2007-06-10 16:44:47.000000000 +0100
+++ linux-2.6.22-rc5/include/linux/ssb/ssb_driver_chipcommon.h 2007-06-24 20:07:15.000000000 +0100
@@ -364,6 +364,8 @@
extern void ssb_chipco_suspend(struct ssb_chipcommon *cc, pm_message_t state);
extern void ssb_chipco_resume(struct ssb_chipcommon *cc);
+extern void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,
+ u32 *plltype, u32 *n, u32 *m);
extern void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc,
u32 *plltype, u32 *n, u32 *m);
extern void ssb_chipco_timing_init(struct ssb_chipcommon *cc,
@@ -378,6 +380,46 @@
extern void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,
enum ssb_clkmode mode);
+/* GPIO functions */
+static inline u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc,
+ u32 mask)
+{
+ return ssb_read32(cc->dev, SSB_CHIPCO_GPIOIN) & mask;
+}
+
+static inline u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc,
+ u32 mask, u32 value)
+{
+ return ssb_write32_masked(cc->dev, SSB_CHIPCO_GPIOOUT, mask, value);
+}
+
+static inline u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc,
+ u32 mask, u32 value)
+{
+ return ssb_write32_masked(cc->dev, SSB_CHIPCO_GPIOOUTEN, mask, value);
+}
+
+static inline u32 ssb_chipco_gpio_control(struct ssb_chipcommon *cc,
+ u32 mask, u32 value)
+{
+ return ssb_write32_masked(cc->dev, SSB_CHIPCO_GPIOCTL, mask, value);
+}
+
+static inline u32 ssb_chipco_gpio_intmask(struct ssb_chipcommon *cc,
+ u32 mask, u32 value)
+{
+ return ssb_write32_masked(cc->dev, SSB_CHIPCO_GPIOIRQ, mask, value);
+}
+
+static inline u32 ssb_chipco_gpio_polarity(struct ssb_chipcommon *cc,
+ u32 mask, u32 value)
+{
+ return ssb_write32_masked(cc->dev, SSB_CHIPCO_GPIOPOL, mask, value);
+}
+/* TODO: GPIO reservation */
+
+extern int ssb_chipco_watchdog(struct ssb_chipcommon *cc, uint ticks);
+
#ifdef CONFIG_SSB_SERIAL
extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
struct ssb_serial_port *ports);
Index: linux-2.6.22-rc5/include/linux/ssb/ssb_driver_extif.h
===================================================================
--- linux-2.6.22-rc5.orig/include/linux/ssb/ssb_driver_extif.h 2007-06-10 16:44:47.000000000 +0100
+++ linux-2.6.22-rc5/include/linux/ssb/ssb_driver_extif.h 2007-06-24 20:07:15.000000000 +0100
@@ -158,6 +158,36 @@
/* watchdog */
#define SSB_EXTIF_WATCHDOG_CLK 48000000 /* Hz */
+/* GPIO functions */
+static inline u32 ssb_extif_gpio_in(struct ssb_extif *extif,
+ u32 mask)
+{
+ return ssb_read32(extif->dev, SSB_EXTIF_GPIO_IN) & mask;
+}
+
+static inline u32 ssb_extif_gpio_out(struct ssb_extif *extif,
+ u32 mask, u32 value)
+{
+ return ssb_write32_masked(extif->dev, SSB_EXTIF_GPIO_OUT(0), mask, value);
+}
+
+static inline u32 ssb_extif_gpio_outen(struct ssb_extif *extif,
+ u32 mask, u32 value)
+{
+ return ssb_write32_masked(extif->dev, SSB_EXTIF_GPIO_OUTEN(0), mask, value);
+}
+
+static inline u32 ssb_extif_gpio_polarity(struct ssb_extif *extif,
+ u32 mask, u32 value)
+{
+ return ssb_write32_masked(extif->dev, SSB_EXTIF_GPIO_INTPOL, mask, value);
+}
+
+static inline u32 ssb_extif_gpio_intmask(struct ssb_extif *extif,
+ u32 mask, u32 value)
+{
+ return ssb_write32_masked(extif->dev, SSB_EXTIF_GPIO_INTMASK, mask, value);
+}
#endif /* __KERNEL__ */
#endif /* LINUX_SSB_EXTIFCORE_H_ */
Index: linux-2.6.22-rc5/include/linux/ssb/ssb_driver_mips.h
===================================================================
--- linux-2.6.22-rc5.orig/include/linux/ssb/ssb_driver_mips.h 2007-06-10 16:44:47.000000000 +0100
+++ linux-2.6.22-rc5/include/linux/ssb/ssb_driver_mips.h 2007-06-24 20:07:15.000000000 +0100
@@ -22,11 +22,13 @@
int nr_serial_ports;
struct ssb_serial_port serial_ports[4];
+ int flash_buswidth;
u32 flash_window;
u32 flash_window_size;
};
extern void ssb_mipscore_init(struct ssb_mipscore *mcore);
+extern u32 ssb_cpu_clock(struct ssb_mipscore *mcore);
extern unsigned int ssb_mips_irq(struct ssb_device *dev);
Index: linux-2.6.22-rc5/include/linux/ssb/ssb.h
===================================================================
--- linux-2.6.22-rc5.orig/include/linux/ssb/ssb.h 2007-06-24 19:49:56.000000000 +0100
+++ linux-2.6.22-rc5/include/linux/ssb/ssb.h 2007-06-24 20:07:15.000000000 +0100
@@ -270,6 +270,12 @@
#define SSB_CHIPPACK_BCM4712M 2 /* Medium 225pin 4712 */
#define SSB_CHIPPACK_BCM4712L 0 /* Large 340pin 4712 */
+static inline u16 ssb_read16(struct ssb_device *dev, u16 offset);
+static inline u32 ssb_read32(struct ssb_device *dev, u16 offset);
+static inline void ssb_write16(struct ssb_device *dev, u16 offset, u16 value);
+static inline void ssb_write32(struct ssb_device *dev, u16 offset, u32 value);
+static inline u32 ssb_write32_masked(struct ssb_device *dev, u16 offset, u32 mask, u32 value);
+
#include <linux/ssb/ssb_driver_chipcommon.h>
#include <linux/ssb/ssb_driver_mips.h>
#include <linux/ssb/ssb_driver_extif.h>
@@ -388,6 +394,16 @@
dev->ops->write32(dev, offset, value);
}
+static inline u32 ssb_write32_masked(struct ssb_device *dev,
+ u16 offset,
+ u32 mask,
+ u32 value)
+{
+ value &= mask;
+ value |= ssb_read32(dev, offset) & ~mask;
+ ssb_write32(dev, offset, value);
+ return value;
+}
/* Translation (routing) bits that need to be ORed to DMA
* addresses before they are given to a device. */

View File

@ -1,152 +0,0 @@
Index: linux-2.6.22-rc6/drivers/ssb/driver_mipscore.c
===================================================================
--- linux-2.6.22-rc6.orig/drivers/ssb/driver_mipscore.c 2007-06-28 11:35:29.077307472 +0200
+++ linux-2.6.22-rc6/drivers/ssb/driver_mipscore.c 2007-06-28 12:11:01.433140112 +0200
@@ -128,10 +128,46 @@
ssb_write32(mdev, SSB_IPSFLAG, irqflag);
}
-/* XXX: leave here or move into separate extif driver? */
+static inline bool serial_exists(u8 *regs)
+{
+ u8 save_mcr, status1 = 0;
+
+ if (regs) {
+ save_mcr = regs[UART_MCR];
+ regs[UART_MCR] = (UART_MCR_LOOP | 0x0a);
+ // Fixme UART_MSR_DSR appears in status1
+ status1 = regs[UART_MSR] & 0xd0;
+ regs[UART_MCR] = save_mcr;
+ }
+ return (status1 == (UART_MSR_DCD | UART_MSR_CTS));
+}
+
static int ssb_extif_serial_init(struct ssb_extif *dev, struct ssb_serial_port *ports)
{
- return 0;
+ u32 i, nr_ports = 0;
+
+ /* Disable GPIO interrupt initially */
+ extif_write32(dev, SSB_EXTIF_GPIO_INTPOL, 0);
+ extif_write32(dev, SSB_EXTIF_GPIO_INTMASK, 0);
+
+ for (i = 0; i < 2; i++) {
+ void __iomem *uart_regs;
+
+ uart_regs = ioremap_nocache(SSB_EUART, 16);
+ uart_regs += (i * 8);
+
+ if (serial_exists(uart_regs) && ports) {
+ extif_write32(dev, SSB_EXTIF_GPIO_INTMASK, 2);
+
+ nr_ports++;
+ ports[i].regs = uart_regs;
+ ports[i].irq = 2;
+ ports[i].baud_base = 13500000;
+ ports[i].reg_shift = 0;
+ }
+ iounmap(uart_regs);
+ }
+ return nr_ports;
}
@@ -139,40 +175,6 @@
{
struct ssb_bus *bus = mcore->dev->bus;
- //TODO if (EXTIF available
-#if 0
- extifregs_t *eir = (extifregs_t *) regs;
- sbconfig_t *sb;
-
- /* Determine external UART register base */
- sb = (sbconfig_t *)((ulong) eir + SBCONFIGOFF);
- base = EXTIF_CFGIF_BASE(sb_base(R_REG(&sb->sbadmatch1)));
-
- /* Determine IRQ */
- irq = sb_irq(sbh);
-
- /* Disable GPIO interrupt initially */
- W_REG(&eir->gpiointpolarity, 0);
- W_REG(&eir->gpiointmask, 0);
-
- /* Search for external UARTs */
- n = 2;
- for (i = 0; i < 2; i++) {
- regs = (void *) REG_MAP(base + (i * 8), 8);
- if (BCMINIT(serial_exists)(regs)) {
- /* Set GPIO 1 to be the external UART IRQ */
- W_REG(&eir->gpiointmask, 2);
- if (add)
- add(regs, irq, 13500000, 0);
- }
- }
-
- /* Add internal UART if enabled */
- if (R_REG(&eir->corecontrol) & CC_UE)
- if (add)
- add((void *) &eir->uartdata, irq, sb_clock(sbh), 2);
-
-#endif
if (bus->extif.dev)
mcore->nr_serial_ports = ssb_extif_serial_init(&bus->extif, mcore->serial_ports);
else if (bus->chipco.dev)
@@ -219,7 +221,7 @@
extif_write32(extif, SSB_EXTIF_PROG_WAITCNT, tmp);
}
-static inline void ssb_extif_get_clockcontrol(struct ssb_extif *extif,
+void ssb_extif_get_clockcontrol(struct ssb_extif *extif,
u32 *pll_type, u32 *n, u32 *m)
{
*pll_type = SSB_PLLTYPE_1;
Index: linux-2.6.22-rc6/drivers/ssb/main.c
===================================================================
--- linux-2.6.22-rc6.orig/drivers/ssb/main.c 2007-06-28 11:23:38.418344056 +0200
+++ linux-2.6.22-rc6/drivers/ssb/main.c 2007-06-28 12:07:50.346189744 +0200
@@ -774,12 +774,12 @@
u32 plltype;
u32 clkctl_n, clkctl_m;
- //TODO if EXTIF: PLLTYPE == 1, read n from clockcontrol_n, m from clockcontrol_sb
-
- if (bus->chipco.dev) {
+ if (bus->extif.dev)
+ ssb_extif_get_clockcontrol(&bus->extif, &plltype, &clkctl_n, &clkctl_m);
+ else if (bus->chipco.dev)
ssb_chipco_get_clockcontrol(&bus->chipco, &plltype,
&clkctl_n, &clkctl_m);
- } else
+ else
return 0;
if (bus->chip_id == 0x5365) {
Index: linux-2.6.22-rc6/include/linux/ssb/ssb_driver_extif.h
===================================================================
--- linux-2.6.22-rc6.orig/include/linux/ssb/ssb_driver_extif.h 2007-06-28 11:27:47.099538768 +0200
+++ linux-2.6.22-rc6/include/linux/ssb/ssb_driver_extif.h 2007-06-28 11:28:03.482048248 +0200
@@ -158,6 +158,8 @@
/* watchdog */
#define SSB_EXTIF_WATCHDOG_CLK 48000000 /* Hz */
+extern void ssb_extif_get_clockcontrol(struct ssb_extif *, u32 *, u32 *, u32 *);
+
/* GPIO functions */
static inline u32 ssb_extif_gpio_in(struct ssb_extif *extif,
u32 mask)
Index: linux-2.6.22-rc6/include/linux/ssb/ssb_regs.h
===================================================================
--- linux-2.6.22-rc6.orig/include/linux/ssb/ssb_regs.h 2007-06-28 12:09:24.943808720 +0200
+++ linux-2.6.22-rc6/include/linux/ssb/ssb_regs.h 2007-06-28 12:09:34.606339792 +0200
@@ -24,8 +24,8 @@
#define SSB_PCI_DMA_SZ 0x40000000 /* Client Mode sb2pcitranslation2 size in bytes */
#define SSB_PCIE_DMA_L32 0x00000000 /* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), low 32 bits */
#define SSB_PCIE_DMA_H32 0x80000000 /* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), high 32 bits */
-#define SSB_EUART (SB_EXTIF_BASE + 0x00800000)
-#define SSB_LED (SB_EXTIF_BASE + 0x00900000)
+#define SSB_EUART (SSB_EXTIF_BASE + 0x00800000)
+#define SSB_LED (SSB_EXTIF_BASE + 0x00900000)
/* Enumeration space constants */

View File

@ -1,252 +1,37 @@
Index: linux-2.6.22-rc5/drivers/ssb/driver_chipcommon.c Index: linux-2.6.23/drivers/ssb/driver_mipscore.c
=================================================================== ===================================================================
--- linux-2.6.22-rc5.orig/drivers/ssb/driver_chipcommon.c 2007-06-21 23:04:38.000000000 +0100 --- linux-2.6.23.orig/drivers/ssb/driver_mipscore.c 2007-10-14 04:32:45.793470742 +0200
+++ linux-2.6.22-rc5/drivers/ssb/driver_chipcommon.c 2007-06-24 20:07:15.000000000 +0100 +++ linux-2.6.23/drivers/ssb/driver_mipscore.c 2007-10-14 04:33:25.155713862 +0200
@@ -264,6 +264,31 @@ @@ -222,3 +222,5 @@
ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
}
+/* TODO: These two functions are a clear candidate for merging, but one gets
+ * the processor clock, and the other gets the bus clock.
+ */
+void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,
+ u32 *plltype, u32 *n, u32 *m)
+{
+ *n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N);
+ *plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
+ switch (*plltype) {
+ case SSB_PLLTYPE_2:
+ case SSB_PLLTYPE_4:
+ case SSB_PLLTYPE_6:
+ case SSB_PLLTYPE_7:
+ *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_MIPS);
+ break;
+ case SSB_PLLTYPE_3:
+ /* 5350 uses m2 to control mips */
+ *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_M2);
+ break;
+ default:
+ *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_SB);
+ break;
+ }
+}
+
void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc,
u32 *plltype, u32 *n, u32 *m)
{
@@ -400,3 +425,13 @@
return nr_ports;
}
#endif /* CONFIG_SSB_SERIAL */
+
+/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
+int
+ssb_chipco_watchdog(struct ssb_chipcommon *cc, uint ticks)
+{
+ /* instant NMI */
+ chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks);
+ return 0;
+}
+EXPORT_SYMBOL(ssb_chipco_watchdog);
Index: linux-2.6.22-rc5/drivers/ssb/driver_mipscore.c
===================================================================
--- linux-2.6.22-rc5.orig/drivers/ssb/driver_mipscore.c 2007-06-10 16:44:31.000000000 +0100
+++ linux-2.6.22-rc5/drivers/ssb/driver_mipscore.c 2007-06-24 20:48:52.000000000 +0100
@@ -4,6 +4,7 @@
*
* Copyright 2005, Broadcom Corporation
* Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
+ * Copyright 2006, 2007, Felix Fietkau <nbd@openwrt.org>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
@@ -31,6 +32,16 @@
ssb_write32(mcore->dev, offset, value);
}
+static inline u32 extif_read32(struct ssb_extif *extif, u16 offset)
+{
+ return ssb_read32(extif->dev, offset);
+}
+
+static inline void extif_write32(struct ssb_extif *extif, u16 offset, u32 value)
+{
+ ssb_write32(extif->dev, offset, value);
+}
+
static const u32 ipsflag_irq_mask[] = {
0,
SSB_IPSFLAG_IRQ1,
@@ -118,9 +129,9 @@
}
/* XXX: leave here or move into separate extif driver? */
-static int ssb_extif_serial_init(struct ssb_device *dev, struct ssb_serial_ports *ports)
+static int ssb_extif_serial_init(struct ssb_extif *dev, struct ssb_serial_port *ports)
{
-
+ return 0;
}
@@ -174,23 +185,76 @@
{
struct ssb_bus *bus = mcore->dev->bus;
+ mcore->flash_buswidth = 2;
if (bus->chipco.dev) {
mcore->flash_window = 0x1c000000;
- mcore->flash_window_size = 0x800000;
+ mcore->flash_window_size = 0x02000000;
+ if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG)
+ & SSB_CHIPCO_CFG_DS16) == 0)
+ mcore->flash_buswidth = 1;
} else {
mcore->flash_window = 0x1fc00000;
- mcore->flash_window_size = 0x400000;
+ mcore->flash_window_size = 0x00400000;
}
}
+static void ssb_extif_timing_init(struct ssb_extif *extif, u32 ns)
+{
+ u32 tmp;
+
+ /* Initialize extif so we can get to the LEDs and external UART */
+ extif_write32(extif, SSB_EXTIF_PROG_CFG, SSB_EXTCFG_EN);
+
+ /* Set timing for the flash */
+ tmp = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT;
+ tmp |= DIV_ROUND_UP(40, ns) << SSB_PROG_WCNT_1_SHIFT;
+ tmp |= DIV_ROUND_UP(120, ns);
+ extif_write32(extif, SSB_EXTIF_PROG_WAITCNT, tmp);
+
+ /* Set programmable interface timing for external uart */
+ tmp = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT;
+ tmp |= DIV_ROUND_UP(20, ns) << SSB_PROG_WCNT_2_SHIFT;
+ tmp |= DIV_ROUND_UP(100, ns) << SSB_PROG_WCNT_1_SHIFT;
+ tmp |= DIV_ROUND_UP(120, ns);
+ extif_write32(extif, SSB_EXTIF_PROG_WAITCNT, tmp);
+}
-static void ssb_cpu_clock(struct ssb_mipscore *mcore)
+static inline void ssb_extif_get_clockcontrol(struct ssb_extif *extif,
+ u32 *pll_type, u32 *n, u32 *m)
{
+ *pll_type = SSB_PLLTYPE_1;
+ *n = extif_read32(extif, SSB_EXTIF_CLOCK_N);
+ *m = extif_read32(extif, SSB_EXTIF_CLOCK_SB);
}
-void ssb_mipscore_init(struct ssb_mipscore *mcore)
+u32 ssb_cpu_clock(struct ssb_mipscore *mcore)
{
struct ssb_bus *bus = mcore->dev->bus;
+ u32 pll_type, n, m, rate = 0;
+
+ if (bus->extif.dev) {
+ ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m);
+ } else if (bus->chipco.dev) {
+ ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m);
+ } else
+ return 0;
+
+ if ((pll_type == SSB_PLLTYPE_5) || (bus->chip_id == 0x5365)) {
+ rate = 200000000;
+ } else {
+ rate = ssb_calc_clock_rate(pll_type, n, m);
+ }
+
+ if (pll_type == SSB_PLLTYPE_6) {
+ rate *= 2;
+ }
+
+ return rate;
+}
+
+void ssb_mipscore_init(struct ssb_mipscore *mcore)
+{
+ struct ssb_bus *bus;
struct ssb_device *dev;
unsigned long hz, ns;
unsigned int irq, i;
@@ -198,6 +262,8 @@
if (!mcore->dev)
return; /* We don't have a MIPS core */
+ bus = mcore->dev->bus;
+
ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n");
hz = ssb_clockspeed(bus);
@@ -205,28 +271,9 @@
hz = 100000000;
ns = 1000000000 / hz;
-//TODO
-#if 0
- if (have EXTIF) {
- /* Initialize extif so we can get to the LEDs and external UART */
- W_REG(&eir->prog_config, CF_EN);
-
- /* Set timing for the flash */
- tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
- tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */
- tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
- W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
-
- /* Set programmable interface timing for external uart */
- tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
- tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */
- tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */
- tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
- W_REG(&eir->prog_waitcount, tmp);
- }
- else... chipcommon
-#endif
- if (bus->chipco.dev)
+ if (bus->extif.dev)
+ ssb_extif_timing_init(&bus->extif, ns);
+ else if (bus->chipco.dev)
ssb_chipco_timing_init(&bus->chipco, ns);
/* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */
@@ -256,3 +303,5 @@
ssb_mips_serial_init(mcore); ssb_mips_serial_init(mcore);
ssb_mips_flash_detect(mcore); ssb_mips_flash_detect(mcore);
} }
+ +
+EXPORT_SYMBOL(ssb_mips_irq); +EXPORT_SYMBOL(ssb_mips_irq);
Index: linux-2.6.22-rc5/include/linux/ssb/ssb_driver_chipcommon.h Index: linux-2.6.23/include/linux/ssb/ssb_driver_chipcommon.h
=================================================================== ===================================================================
--- linux-2.6.22-rc5.orig/include/linux/ssb/ssb_driver_chipcommon.h 2007-06-10 16:44:47.000000000 +0100 --- linux-2.6.23.orig/include/linux/ssb/ssb_driver_chipcommon.h 2007-10-14 04:32:45.817472111 +0200
+++ linux-2.6.22-rc5/include/linux/ssb/ssb_driver_chipcommon.h 2007-06-24 20:07:15.000000000 +0100 +++ linux-2.6.23/include/linux/ssb/ssb_driver_chipcommon.h 2007-10-14 04:33:25.159714091 +0200
@@ -364,6 +364,8 @@ @@ -382,11 +382,45 @@
extern void ssb_chipco_suspend(struct ssb_chipcommon *cc, pm_message_t state); extern void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc,
extern void ssb_chipco_resume(struct ssb_chipcommon *cc); u32 ticks);
+extern void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,
+ u32 *plltype, u32 *n, u32 *m);
extern void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc,
u32 *plltype, u32 *n, u32 *m);
extern void ssb_chipco_timing_init(struct ssb_chipcommon *cc,
@@ -378,6 +380,46 @@
extern void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,
enum ssb_clkmode mode);
-u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask);
+/* GPIO functions */ +/* GPIO functions */
+static inline u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, +static inline u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc,
+ u32 mask) + u32 mask)
+{ +{
+ return ssb_read32(cc->dev, SSB_CHIPCO_GPIOIN) & mask; + return ssb_read32(cc->dev, SSB_CHIPCO_GPIOIN) & mask;
+} +}
+
-void ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value);
+static inline u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc, +static inline u32 ssb_chipco_gpio_out(struct ssb_chipcommon *cc,
+ u32 mask, u32 value) + u32 mask, u32 value)
+{ +{
+ return ssb_write32_masked(cc->dev, SSB_CHIPCO_GPIOOUT, mask, value); + return ssb_write32_masked(cc->dev, SSB_CHIPCO_GPIOOUT, mask, value);
+} +}
+
-void ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value);
+static inline u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, +static inline u32 ssb_chipco_gpio_outen(struct ssb_chipcommon *cc,
+ u32 mask, u32 value) + u32 mask, u32 value)
+{ +{
@ -273,18 +58,36 @@ Index: linux-2.6.22-rc5/include/linux/ssb/ssb_driver_chipcommon.h
+/* TODO: GPIO reservation */ +/* TODO: GPIO reservation */
+ +
+extern int ssb_chipco_watchdog(struct ssb_chipcommon *cc, uint ticks); +extern int ssb_chipco_watchdog(struct ssb_chipcommon *cc, uint ticks);
+
#ifdef CONFIG_SSB_SERIAL #ifdef CONFIG_SSB_SERIAL
extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc, extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
struct ssb_serial_port *ports); Index: linux-2.6.23/include/linux/ssb/ssb_driver_extif.h
Index: linux-2.6.22-rc5/include/linux/ssb/ssb_driver_extif.h
=================================================================== ===================================================================
--- linux-2.6.22-rc5.orig/include/linux/ssb/ssb_driver_extif.h 2007-06-10 16:44:47.000000000 +0100 --- linux-2.6.23.orig/include/linux/ssb/ssb_driver_extif.h 2007-10-14 04:32:45.821472339 +0200
+++ linux-2.6.22-rc5/include/linux/ssb/ssb_driver_extif.h 2007-06-24 20:07:15.000000000 +0100 +++ linux-2.6.23/include/linux/ssb/ssb_driver_extif.h 2007-10-14 04:33:25.167714544 +0200
@@ -158,6 +158,36 @@ @@ -153,7 +153,6 @@
/* watchdog */
#define SSB_EXTIF_WATCHDOG_CLK 48000000 /* Hz */ #define SSB_EXTIF_WATCHDOG_CLK 48000000 /* Hz */
-
#ifdef CONFIG_SSB_DRIVER_EXTIF
struct ssb_extif {
@@ -171,17 +170,42 @@
extern void ssb_extif_timing_init(struct ssb_extif *extif,
unsigned long ns);
-u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask);
-
-void ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value);
-
-void ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value);
-
#ifdef CONFIG_SSB_SERIAL
extern int ssb_extif_serial_init(struct ssb_extif *extif,
struct ssb_serial_port *ports);
#endif /* CONFIG_SSB_SERIAL */
+/* GPIO functions */ +/* GPIO functions */
+static inline u32 ssb_extif_gpio_in(struct ssb_extif *extif, +static inline u32 ssb_extif_gpio_in(struct ssb_extif *extif,
+ u32 mask) + u32 mask)
@ -315,32 +118,15 @@ Index: linux-2.6.22-rc5/include/linux/ssb/ssb_driver_extif.h
+{ +{
+ return ssb_write32_masked(extif->dev, SSB_EXTIF_GPIO_INTMASK, mask, value); + return ssb_write32_masked(extif->dev, SSB_EXTIF_GPIO_INTMASK, mask, value);
+} +}
+
#endif /* __KERNEL__ */ #else /* CONFIG_SSB_DRIVER_EXTIF */
#endif /* LINUX_SSB_EXTIFCORE_H_ */ /* extif disabled */
Index: linux-2.6.22-rc5/include/linux/ssb/ssb_driver_mips.h Index: linux-2.6.23/include/linux/ssb/ssb.h
=================================================================== ===================================================================
--- linux-2.6.22-rc5.orig/include/linux/ssb/ssb_driver_mips.h 2007-06-10 16:44:47.000000000 +0100 --- linux-2.6.23.orig/include/linux/ssb/ssb.h 2007-10-14 04:32:45.833473010 +0200
+++ linux-2.6.22-rc5/include/linux/ssb/ssb_driver_mips.h 2007-06-24 20:07:15.000000000 +0100 +++ linux-2.6.23/include/linux/ssb/ssb.h 2007-10-14 04:33:25.171714773 +0200
@@ -22,11 +22,13 @@ @@ -255,6 +255,12 @@
int nr_serial_ports;
struct ssb_serial_port serial_ports[4];
+ int flash_buswidth;
u32 flash_window;
u32 flash_window_size;
};
extern void ssb_mipscore_init(struct ssb_mipscore *mcore);
+extern u32 ssb_cpu_clock(struct ssb_mipscore *mcore);
extern unsigned int ssb_mips_irq(struct ssb_device *dev);
Index: linux-2.6.22-rc5/include/linux/ssb/ssb.h
===================================================================
--- linux-2.6.22-rc5.orig/include/linux/ssb/ssb.h 2007-06-24 19:49:56.000000000 +0100
+++ linux-2.6.22-rc5/include/linux/ssb/ssb.h 2007-06-24 20:07:15.000000000 +0100
@@ -270,6 +270,12 @@
#define SSB_CHIPPACK_BCM4712M 2 /* Medium 225pin 4712 */ #define SSB_CHIPPACK_BCM4712M 2 /* Medium 225pin 4712 */
#define SSB_CHIPPACK_BCM4712L 0 /* Large 340pin 4712 */ #define SSB_CHIPPACK_BCM4712L 0 /* Large 340pin 4712 */
@ -353,7 +139,7 @@ Index: linux-2.6.22-rc5/include/linux/ssb/ssb.h
#include <linux/ssb/ssb_driver_chipcommon.h> #include <linux/ssb/ssb_driver_chipcommon.h>
#include <linux/ssb/ssb_driver_mips.h> #include <linux/ssb/ssb_driver_mips.h>
#include <linux/ssb/ssb_driver_extif.h> #include <linux/ssb/ssb_driver_extif.h>
@@ -388,6 +394,16 @@ @@ -385,6 +391,16 @@
dev->ops->write32(dev, offset, value); dev->ops->write32(dev, offset, value);
} }
@ -370,3 +156,78 @@ Index: linux-2.6.22-rc5/include/linux/ssb/ssb.h
/* Translation (routing) bits that need to be ORed to DMA /* Translation (routing) bits that need to be ORed to DMA
* addresses before they are given to a device. */ * addresses before they are given to a device. */
Index: linux-2.6.23/drivers/ssb/driver_chipcommon.c
===================================================================
--- linux-2.6.23.orig/drivers/ssb/driver_chipcommon.c 2007-10-14 04:32:45.797470966 +0200
+++ linux-2.6.23/drivers/ssb/driver_chipcommon.c 2007-10-14 04:33:25.175715001 +0200
@@ -351,21 +351,6 @@
chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks);
}
-u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask)
-{
- return chipco_read32(cc, SSB_CHIPCO_GPIOIN) & mask;
-}
-
-void ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value)
-{
- chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value);
-}
-
-void ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value)
-{
- chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value);
-}
-
#ifdef CONFIG_SSB_SERIAL
int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
struct ssb_serial_port *ports)
Index: linux-2.6.23/drivers/ssb/driver_extif.c
===================================================================
--- linux-2.6.23.orig/drivers/ssb/driver_extif.c 2007-10-14 04:32:45.809471640 +0200
+++ linux-2.6.23/drivers/ssb/driver_extif.c 2007-10-14 04:33:25.179715231 +0200
@@ -110,20 +110,4 @@
*m = extif_read32(extif, SSB_EXTIF_CLOCK_SB);
}
-u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask)
-{
- return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask;
-}
-
-void ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value)
-{
- return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0),
- mask, value);
-}
-
-void ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value)
-{
- return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0),
- mask, value);
-}
Index: linux-2.6.23/include/linux/mod_devicetable.h
===================================================================
--- linux-2.6.23.orig/include/linux/mod_devicetable.h 2007-10-14 04:35:22.102378272 +0200
+++ linux-2.6.23/include/linux/mod_devicetable.h 2007-10-14 04:34:41.172045787 +0200
@@ -340,4 +340,19 @@
#define PA_HVERSION_ANY_ID 0xffff
#define PA_SVERSION_ANY_ID 0xffffffff
+/* SSB core, see drivers/ssb/ */
+struct ssb_device_id {
+ __u16 vendor;
+ __u16 coreid;
+ __u8 revision;
+};
+#define SSB_DEVICE(_vendor, _coreid, _revision) \
+ { .vendor = _vendor, .coreid = _coreid, .revision = _revision, }
+#define SSB_DEVTABLE_END \
+ { 0, },
+
+#define SSB_ANY_VENDOR 0xFFFF
+#define SSB_ANY_ID 0xFFFF
+#define SSB_ANY_REV 0xFF
+
#endif /* LINUX_MOD_DEVICETABLE_H */

View File

@ -1,152 +0,0 @@
Index: linux-2.6.23/drivers/ssb/driver_mipscore.c
===================================================================
--- linux-2.6.23.orig/drivers/ssb/driver_mipscore.c 2007-10-13 03:01:19.829188047 +0200
+++ linux-2.6.23/drivers/ssb/driver_mipscore.c 2007-10-13 03:01:21.777299062 +0200
@@ -128,10 +128,46 @@
ssb_write32(mdev, SSB_IPSFLAG, irqflag);
}
-/* XXX: leave here or move into separate extif driver? */
+static inline bool serial_exists(u8 *regs)
+{
+ u8 save_mcr, status1 = 0;
+
+ if (regs) {
+ save_mcr = regs[UART_MCR];
+ regs[UART_MCR] = (UART_MCR_LOOP | 0x0a);
+ // Fixme UART_MSR_DSR appears in status1
+ status1 = regs[UART_MSR] & 0xd0;
+ regs[UART_MCR] = save_mcr;
+ }
+ return (status1 == (UART_MSR_DCD | UART_MSR_CTS));
+}
+
static int ssb_extif_serial_init(struct ssb_extif *dev, struct ssb_serial_port *ports)
{
- return 0;
+ u32 i, nr_ports = 0;
+
+ /* Disable GPIO interrupt initially */
+ extif_write32(dev, SSB_EXTIF_GPIO_INTPOL, 0);
+ extif_write32(dev, SSB_EXTIF_GPIO_INTMASK, 0);
+
+ for (i = 0; i < 2; i++) {
+ void __iomem *uart_regs;
+
+ uart_regs = ioremap_nocache(SSB_EUART, 16);
+ uart_regs += (i * 8);
+
+ if (serial_exists(uart_regs) && ports) {
+ extif_write32(dev, SSB_EXTIF_GPIO_INTMASK, 2);
+
+ nr_ports++;
+ ports[i].regs = uart_regs;
+ ports[i].irq = 2;
+ ports[i].baud_base = 13500000;
+ ports[i].reg_shift = 0;
+ }
+ iounmap(uart_regs);
+ }
+ return nr_ports;
}
@@ -139,40 +175,6 @@
{
struct ssb_bus *bus = mcore->dev->bus;
- //TODO if (EXTIF available
-#if 0
- extifregs_t *eir = (extifregs_t *) regs;
- sbconfig_t *sb;
-
- /* Determine external UART register base */
- sb = (sbconfig_t *)((ulong) eir + SBCONFIGOFF);
- base = EXTIF_CFGIF_BASE(sb_base(R_REG(&sb->sbadmatch1)));
-
- /* Determine IRQ */
- irq = sb_irq(sbh);
-
- /* Disable GPIO interrupt initially */
- W_REG(&eir->gpiointpolarity, 0);
- W_REG(&eir->gpiointmask, 0);
-
- /* Search for external UARTs */
- n = 2;
- for (i = 0; i < 2; i++) {
- regs = (void *) REG_MAP(base + (i * 8), 8);
- if (BCMINIT(serial_exists)(regs)) {
- /* Set GPIO 1 to be the external UART IRQ */
- W_REG(&eir->gpiointmask, 2);
- if (add)
- add(regs, irq, 13500000, 0);
- }
- }
-
- /* Add internal UART if enabled */
- if (R_REG(&eir->corecontrol) & CC_UE)
- if (add)
- add((void *) &eir->uartdata, irq, sb_clock(sbh), 2);
-
-#endif
if (bus->extif.dev)
mcore->nr_serial_ports = ssb_extif_serial_init(&bus->extif, mcore->serial_ports);
else if (bus->chipco.dev)
@@ -219,7 +221,7 @@
extif_write32(extif, SSB_EXTIF_PROG_WAITCNT, tmp);
}
-static inline void ssb_extif_get_clockcontrol(struct ssb_extif *extif,
+void ssb_extif_get_clockcontrol(struct ssb_extif *extif,
u32 *pll_type, u32 *n, u32 *m)
{
*pll_type = SSB_PLLTYPE_1;
Index: linux-2.6.23/drivers/ssb/main.c
===================================================================
--- linux-2.6.23.orig/drivers/ssb/main.c 2007-10-11 19:38:13.198446000 +0200
+++ linux-2.6.23/drivers/ssb/main.c 2007-10-13 03:01:21.785299518 +0200
@@ -774,12 +774,12 @@
u32 plltype;
u32 clkctl_n, clkctl_m;
- //TODO if EXTIF: PLLTYPE == 1, read n from clockcontrol_n, m from clockcontrol_sb
-
- if (bus->chipco.dev) {
+ if (bus->extif.dev)
+ ssb_extif_get_clockcontrol(&bus->extif, &plltype, &clkctl_n, &clkctl_m);
+ else if (bus->chipco.dev)
ssb_chipco_get_clockcontrol(&bus->chipco, &plltype,
&clkctl_n, &clkctl_m);
- } else
+ else
return 0;
if (bus->chip_id == 0x5365) {
Index: linux-2.6.23/include/linux/ssb/ssb_driver_extif.h
===================================================================
--- linux-2.6.23.orig/include/linux/ssb/ssb_driver_extif.h 2007-10-13 03:01:19.841188731 +0200
+++ linux-2.6.23/include/linux/ssb/ssb_driver_extif.h 2007-10-13 03:01:21.789299747 +0200
@@ -158,6 +158,8 @@
/* watchdog */
#define SSB_EXTIF_WATCHDOG_CLK 48000000 /* Hz */
+extern void ssb_extif_get_clockcontrol(struct ssb_extif *, u32 *, u32 *, u32 *);
+
/* GPIO functions */
static inline u32 ssb_extif_gpio_in(struct ssb_extif *extif,
u32 mask)
Index: linux-2.6.23/include/linux/ssb/ssb_regs.h
===================================================================
--- linux-2.6.23.orig/include/linux/ssb/ssb_regs.h 2007-10-11 19:38:13.206447000 +0200
+++ linux-2.6.23/include/linux/ssb/ssb_regs.h 2007-10-13 03:01:21.793299976 +0200
@@ -24,8 +24,8 @@
#define SSB_PCI_DMA_SZ 0x40000000 /* Client Mode sb2pcitranslation2 size in bytes */
#define SSB_PCIE_DMA_L32 0x00000000 /* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), low 32 bits */
#define SSB_PCIE_DMA_H32 0x80000000 /* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), high 32 bits */
-#define SSB_EUART (SB_EXTIF_BASE + 0x00800000)
-#define SSB_LED (SB_EXTIF_BASE + 0x00900000)
+#define SSB_EUART (SSB_EXTIF_BASE + 0x00800000)
+#define SSB_LED (SSB_EXTIF_BASE + 0x00900000)
/* Enumeration space constants */

View File

@ -1,18 +1,33 @@
menu "Sonics Silicon Backplane" menu "Sonics Silicon Backplane"
config SSB_POSSIBLE
bool
depends on HAS_IOMEM
default y
config SSB config SSB
tristate "Sonics Silicon Backplane support" tristate "Sonics Silicon Backplane support"
depends on EXPERIMENTAL depends on SSB_POSSIBLE
help help
Support for the Sonics Silicon Backplane bus Support for the Sonics Silicon Backplane bus.
You only need to enable this option, if you are
configuring a kernel for an embedded system with
this bus.
It will be auto-selected if needed in other
environments.
The module will be called ssb The module will be called ssb.
If unsure, say M If unsure, say N.
config SSB_PCIHOST_POSSIBLE
bool
depends on SSB && PCI
default y
config SSB_PCIHOST config SSB_PCIHOST
bool "Support for SSB on PCI-bus host" bool "Support for SSB on PCI-bus host"
depends on SSB && PCI depends on SSB_PCIHOST_POSSIBLE
default y default y
help help
Support for a Sonics Silicon Backplane on top Support for a Sonics Silicon Backplane on top
@ -20,9 +35,14 @@ config SSB_PCIHOST
If unsure, say Y If unsure, say Y
config SSB_PCMCIAHOST_POSSIBLE
bool
depends on SSB && PCMCIA && EXPERIMENTAL
default y
config SSB_PCMCIAHOST config SSB_PCMCIAHOST
bool "Support for SSB on PCMCIA-bus host" bool "Support for SSB on PCMCIA-bus host (EXPERIMENTAL)"
depends on SSB && PCMCIA depends on SSB_PCMCIAHOST_POSSIBLE
help help
Support for a Sonics Silicon Backplane on top Support for a Sonics Silicon Backplane on top
of a PCMCIA device. of a PCMCIA device.
@ -31,7 +51,7 @@ config SSB_PCMCIAHOST
config SSB_SILENT config SSB_SILENT
bool "No SSB kernel messages" bool "No SSB kernel messages"
depends on SSB depends on SSB && EMBEDDED
help help
This option turns off all Sonics Silicon Backplane printks. This option turns off all Sonics Silicon Backplane printks.
Note that you won't be able to identify problems, once Note that you won't be able to identify problems, once
@ -55,10 +75,14 @@ config SSB_SERIAL
depends on SSB depends on SSB
# ChipCommon and ExtIf serial support routines. # ChipCommon and ExtIf serial support routines.
config SSB_DRIVER_PCICORE_POSSIBLE
bool
depends on SSB_PCIHOST
default y
config SSB_DRIVER_PCICORE config SSB_DRIVER_PCICORE
bool "SSB PCI core driver" bool "SSB PCI core driver"
depends on SSB && SSB_PCIHOST depends on SSB_DRIVER_PCICORE_POSSIBLE
default y
help help
Driver for the Sonics Silicon Backplane attached Driver for the Sonics Silicon Backplane attached
Broadcom PCI core. Broadcom PCI core.
@ -66,14 +90,14 @@ config SSB_DRIVER_PCICORE
If unsure, say Y If unsure, say Y
config SSB_PCICORE_HOSTMODE config SSB_PCICORE_HOSTMODE
bool "Hostmode support for SSB PCI core" bool "Hostmode support for SSB PCI core (EXPERIMENTAL)"
depends on SSB_DRIVER_PCICORE && SSB_DRIVER_MIPS depends on SSB_DRIVER_PCICORE && SSB_DRIVER_MIPS && EXPERIMENTAL
help help
PCIcore hostmode operation (external PCI bus). PCIcore hostmode operation (external PCI bus).
config SSB_DRIVER_MIPS config SSB_DRIVER_MIPS
bool "SSB Broadcom MIPS core driver" bool "SSB Broadcom MIPS core driver (EXPERIMENTAL)"
depends on SSB && MIPS depends on SSB && MIPS && EXPERIMENTAL
select SSB_SERIAL select SSB_SERIAL
help help
Driver for the Sonics Silicon Backplane attached Driver for the Sonics Silicon Backplane attached
@ -82,8 +106,8 @@ config SSB_DRIVER_MIPS
If unsure, say N If unsure, say N
config SSB_DRIVER_EXTIF config SSB_DRIVER_EXTIF
bool "SSB Broadcom EXTIF core driver" bool "SSB Broadcom EXTIF core driver (EXPERIMENTAL)"
depends on SSB_DRIVER_MIPS depends on SSB_DRIVER_MIPS && EXPERIMENTAL
help help
Driver for the Sonics Silicon Backplane attached Driver for the Sonics Silicon Backplane attached
Broadcom EXTIF core. Broadcom EXTIF core.

View File

@ -1,11 +1,18 @@
ssb-builtin-drivers-y += driver_chipcommon.o # core
ssb-builtin-drivers-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o ssb-y += main.o scan.o
ssb-builtin-drivers-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o
ssb-hostsupport-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o # host support
ssb-hostsupport-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o
ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o
obj-$(CONFIG_SSB) += ssb.o # built-in drivers
ssb-y += driver_chipcommon.o
ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o
ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o
ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o
ssb-objs := main.o scan.o \ # b43 pci-ssb-bridge driver
$(ssb-hostsupport-y) $(ssb-builtin-drivers-y) # Not strictly a part of SSB, but kept here for convenience
ssb-$(CONFIG_SSB_PCIHOST) += b43_pci_bridge.o
obj-$(CONFIG_SSB) += ssb.o

View File

@ -0,0 +1,48 @@
/*
* Broadcom 43xx PCI-SSB bridge module
*
* This technically is a seperate PCI driver module, but
* because of its small size we include it in the SSB core
* instead of creating a standalone module.
*
* Copyright 2007 Michael Buesch <mb@bu3sch.de>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
#include <linux/pci.h>
#include <linux/ssb/ssb.h>
#include "ssb_private.h"
static const struct pci_device_id b43_pci_bridge_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4301) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4307) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4311) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4312) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4318) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl);
static struct pci_driver b43_pci_bridge_driver = {
.name = "b43-pci-bridge",
.id_table = b43_pci_bridge_tbl,
};
int __init b43_pci_ssb_bridge_init(void)
{
return ssb_pcihost_register(&b43_pci_bridge_driver);
}
void __exit b43_pci_ssb_bridge_exit(void)
{
ssb_pcihost_unregister(&b43_pci_bridge_driver);
}

View File

@ -16,7 +16,7 @@
/* Clock sources */ /* Clock sources */
enum { enum ssb_clksrc {
/* PCI clock */ /* PCI clock */
SSB_CHIPCO_CLKSRC_PCI, SSB_CHIPCO_CLKSRC_PCI,
/* Crystal slow clock oscillator */ /* Crystal slow clock oscillator */
@ -39,6 +39,14 @@ static inline void chipco_write32(struct ssb_chipcommon *cc,
ssb_write32(cc->dev, offset, value); ssb_write32(cc->dev, offset, value);
} }
static inline void chipco_write32_masked(struct ssb_chipcommon *cc, u16 offset,
u32 mask, u32 value)
{
value &= mask;
value |= chipco_read32(cc, offset) & ~mask;
chipco_write32(cc, offset, value);
}
void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc, void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,
enum ssb_clkmode mode) enum ssb_clkmode mode)
{ {
@ -85,15 +93,15 @@ void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,
ssb_pci_xtal(bus, SSB_GPIO_XTAL, 0); ssb_pci_xtal(bus, SSB_GPIO_XTAL, 0);
break; break;
default: default:
assert(0); SSB_WARN_ON(1);
} }
} }
/* Get the Slow Clock Source */ /* Get the Slow Clock Source */
static int chipco_pctl_get_slowclksrc(struct ssb_chipcommon *cc) static enum ssb_clksrc chipco_pctl_get_slowclksrc(struct ssb_chipcommon *cc)
{ {
struct ssb_bus *bus = cc->dev->bus; struct ssb_bus *bus = cc->dev->bus;
u32 tmp = 0; u32 uninitialized_var(tmp);
if (cc->dev->id.revision < 6) { if (cc->dev->id.revision < 6) {
if (bus->bustype == SSB_BUSTYPE_SSB || if (bus->bustype == SSB_BUSTYPE_SSB ||
@ -123,9 +131,9 @@ static int chipco_pctl_get_slowclksrc(struct ssb_chipcommon *cc)
/* Get maximum or minimum (depending on get_max flag) slowclock frequency. */ /* Get maximum or minimum (depending on get_max flag) slowclock frequency. */
static int chipco_pctl_clockfreqlimit(struct ssb_chipcommon *cc, int get_max) static int chipco_pctl_clockfreqlimit(struct ssb_chipcommon *cc, int get_max)
{ {
int limit; int uninitialized_var(limit);
int clocksrc; enum ssb_clksrc clocksrc;
int divisor; int divisor = 1;
u32 tmp; u32 tmp;
clocksrc = chipco_pctl_get_slowclksrc(cc); clocksrc = chipco_pctl_get_slowclksrc(cc);
@ -138,13 +146,11 @@ static int chipco_pctl_clockfreqlimit(struct ssb_chipcommon *cc, int get_max)
divisor = 32; divisor = 32;
break; break;
default: default:
assert(0); SSB_WARN_ON(1);
divisor = 1;
} }
} else if (cc->dev->id.revision < 10) { } else if (cc->dev->id.revision < 10) {
switch (clocksrc) { switch (clocksrc) {
case SSB_CHIPCO_CLKSRC_LOPWROS: case SSB_CHIPCO_CLKSRC_LOPWROS:
divisor = 1;
break; break;
case SSB_CHIPCO_CLKSRC_XTALOS: case SSB_CHIPCO_CLKSRC_XTALOS:
case SSB_CHIPCO_CLKSRC_PCI: case SSB_CHIPCO_CLKSRC_PCI:
@ -152,9 +158,6 @@ static int chipco_pctl_clockfreqlimit(struct ssb_chipcommon *cc, int get_max)
divisor = (tmp >> 16) + 1; divisor = (tmp >> 16) + 1;
divisor *= 4; divisor *= 4;
break; break;
default:
assert(0);
divisor = 1;
} }
} else { } else {
tmp = chipco_read32(cc, SSB_CHIPCO_SYSCLKCTL); tmp = chipco_read32(cc, SSB_CHIPCO_SYSCLKCTL);
@ -181,9 +184,6 @@ static int chipco_pctl_clockfreqlimit(struct ssb_chipcommon *cc, int get_max)
else else
limit = 25000000; limit = 25000000;
break; break;
default:
assert(0);
limit = 0;
} }
limit /= divisor; limit /= divisor;
@ -235,7 +235,7 @@ static void calc_fast_powerup_delay(struct ssb_chipcommon *cc)
minfreq = chipco_pctl_clockfreqlimit(cc, 0); minfreq = chipco_pctl_clockfreqlimit(cc, 0);
pll_on_delay = chipco_read32(cc, SSB_CHIPCO_PLLONDELAY); pll_on_delay = chipco_read32(cc, SSB_CHIPCO_PLLONDELAY);
tmp = (((pll_on_delay + 2) * 1000000) + (minfreq - 1)) / minfreq; tmp = (((pll_on_delay + 2) * 1000000) + (minfreq - 1)) / minfreq;
assert((tmp & ~0xFFFF) == 0); SSB_WARN_ON(tmp & ~0xFFFF);
cc->fast_pwrup_delay = tmp; cc->fast_pwrup_delay = tmp;
} }
@ -264,6 +264,30 @@ void ssb_chipco_resume(struct ssb_chipcommon *cc)
ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST); ssb_chipco_set_clockmode(cc, SSB_CLKMODE_FAST);
} }
/* Get the processor clock */
void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,
u32 *plltype, u32 *n, u32 *m)
{
*n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N);
*plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
switch (*plltype) {
case SSB_PLLTYPE_2:
case SSB_PLLTYPE_4:
case SSB_PLLTYPE_6:
case SSB_PLLTYPE_7:
*m = chipco_read32(cc, SSB_CHIPCO_CLOCK_MIPS);
break;
case SSB_PLLTYPE_3:
/* 5350 uses m2 to control mips */
*m = chipco_read32(cc, SSB_CHIPCO_CLOCK_M2);
break;
default:
*m = chipco_read32(cc, SSB_CHIPCO_CLOCK_SB);
break;
}
}
/* Get the bus clock */
void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc, void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc,
u32 *plltype, u32 *n, u32 *m) u32 *plltype, u32 *n, u32 *m)
{ {
@ -320,6 +344,27 @@ void ssb_chipco_timing_init(struct ssb_chipcommon *cc,
} }
} }
/* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */
void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc, u32 ticks)
{
/* instant NMI */
chipco_write32(cc, SSB_CHIPCO_WATCHDOG, ticks);
}
u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask)
{
return chipco_read32(cc, SSB_CHIPCO_GPIOIN) & mask;
}
void ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value)
{
chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUT, mask, value);
}
void ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value)
{
chipco_write32_masked(cc, SSB_CHIPCO_GPIOOUTEN, mask, value);
}
#ifdef CONFIG_SSB_SERIAL #ifdef CONFIG_SSB_SERIAL
int ssb_chipco_serial_init(struct ssb_chipcommon *cc, int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
@ -352,10 +397,8 @@ int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
} else if (cc->dev->id.revision >= 3) { } else if (cc->dev->id.revision >= 3) {
/* Internal backplane clock */ /* Internal backplane clock */
baud_base = ssb_clockspeed(bus); baud_base = ssb_clockspeed(bus);
div = 2; /* Minimum divisor */ div = chipco_read32(cc, SSB_CHIPCO_CLKDIV)
chipco_write32(cc, SSB_CHIPCO_CLKDIV, & SSB_CHIPCO_CLKDIV_UART;
(chipco_read32(cc, SSB_CHIPCO_CLKDIV)
& ~SSB_CHIPCO_CLKDIV_UART) | div);
} else { } else {
/* Fixed internal backplane clock */ /* Fixed internal backplane clock */
baud_base = 88000000; baud_base = 88000000;

View File

@ -0,0 +1,129 @@
/*
* Sonics Silicon Backplane
* Broadcom EXTIF core driver
*
* Copyright 2005, Broadcom Corporation
* Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
* Copyright 2006, 2007, Felix Fietkau <nbd@openwrt.org>
* Copyright 2007, Aurelien Jarno <aurelien@aurel32.net>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
#include "ssb_private.h"
static inline u32 extif_read32(struct ssb_extif *extif, u16 offset)
{
return ssb_read32(extif->dev, offset);
}
static inline void extif_write32(struct ssb_extif *extif, u16 offset, u32 value)
{
ssb_write32(extif->dev, offset, value);
}
static inline void extif_write32_masked(struct ssb_extif *extif, u16 offset,
u32 mask, u32 value)
{
value &= mask;
value |= extif_read32(extif, offset) & ~mask;
extif_write32(extif, offset, value);
}
#ifdef CONFIG_SSB_SERIAL
static bool serial_exists(u8 *regs)
{
u8 save_mcr, msr = 0;
if (regs) {
save_mcr = regs[UART_MCR];
regs[UART_MCR] = (UART_MCR_LOOP | UART_MCR_OUT2 | UART_MCR_RTS);
msr = regs[UART_MSR] & (UART_MSR_DCD | UART_MSR_RI
| UART_MSR_CTS | UART_MSR_DSR);
regs[UART_MCR] = save_mcr;
}
return (msr == (UART_MSR_DCD | UART_MSR_CTS));
}
int ssb_extif_serial_init(struct ssb_extif *extif, struct ssb_serial_port *ports)
{
u32 i, nr_ports = 0;
/* Disable GPIO interrupt initially */
extif_write32(extif, SSB_EXTIF_GPIO_INTPOL, 0);
extif_write32(extif, SSB_EXTIF_GPIO_INTMASK, 0);
for (i = 0; i < 2; i++) {
void __iomem *uart_regs;
uart_regs = ioremap_nocache(SSB_EUART, 16);
if (uart_regs) {
uart_regs += (i * 8);
if (serial_exists(uart_regs) && ports) {
extif_write32(extif, SSB_EXTIF_GPIO_INTMASK, 2);
nr_ports++;
ports[i].regs = uart_regs;
ports[i].irq = 2;
ports[i].baud_base = 13500000;
ports[i].reg_shift = 0;
}
iounmap(uart_regs);
}
}
return nr_ports;
}
#endif /* CONFIG_SSB_SERIAL */
void ssb_extif_timing_init(struct ssb_extif *extif, unsigned long ns)
{
u32 tmp;
/* Initialize extif so we can get to the LEDs and external UART */
extif_write32(extif, SSB_EXTIF_PROG_CFG, SSB_EXTCFG_EN);
/* Set timing for the flash */
tmp = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT;
tmp |= DIV_ROUND_UP(40, ns) << SSB_PROG_WCNT_1_SHIFT;
tmp |= DIV_ROUND_UP(120, ns);
extif_write32(extif, SSB_EXTIF_PROG_WAITCNT, tmp);
/* Set programmable interface timing for external uart */
tmp = DIV_ROUND_UP(10, ns) << SSB_PROG_WCNT_3_SHIFT;
tmp |= DIV_ROUND_UP(20, ns) << SSB_PROG_WCNT_2_SHIFT;
tmp |= DIV_ROUND_UP(100, ns) << SSB_PROG_WCNT_1_SHIFT;
tmp |= DIV_ROUND_UP(120, ns);
extif_write32(extif, SSB_EXTIF_PROG_WAITCNT, tmp);
}
void ssb_extif_get_clockcontrol(struct ssb_extif *extif,
u32 *pll_type, u32 *n, u32 *m)
{
*pll_type = SSB_PLLTYPE_1;
*n = extif_read32(extif, SSB_EXTIF_CLOCK_N);
*m = extif_read32(extif, SSB_EXTIF_CLOCK_SB);
}
u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask)
{
return extif_read32(extif, SSB_EXTIF_GPIO_IN) & mask;
}
void ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value)
{
return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUT(0),
mask, value);
}
void ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value)
{
return extif_write32_masked(extif, SSB_EXTIF_GPIO_OUTEN(0),
mask, value);
}

View File

@ -13,7 +13,7 @@
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/serial_reg.h> #include <linux/serial_reg.h>
#include <asm/time.h> #include <linux/time.h>
#include "ssb_private.h" #include "ssb_private.h"
@ -117,51 +117,10 @@ static void set_irq(struct ssb_device *dev, unsigned int irq)
ssb_write32(mdev, SSB_IPSFLAG, irqflag); ssb_write32(mdev, SSB_IPSFLAG, irqflag);
} }
/* XXX: leave here or move into separate extif driver? */
static int ssb_extif_serial_init(struct ssb_device *dev, struct ssb_serial_ports *ports)
{
}
static void ssb_mips_serial_init(struct ssb_mipscore *mcore) static void ssb_mips_serial_init(struct ssb_mipscore *mcore)
{ {
struct ssb_bus *bus = mcore->dev->bus; struct ssb_bus *bus = mcore->dev->bus;
//TODO if (EXTIF available
#if 0
extifregs_t *eir = (extifregs_t *) regs;
sbconfig_t *sb;
/* Determine external UART register base */
sb = (sbconfig_t *)((ulong) eir + SBCONFIGOFF);
base = EXTIF_CFGIF_BASE(sb_base(R_REG(&sb->sbadmatch1)));
/* Determine IRQ */
irq = sb_irq(sbh);
/* Disable GPIO interrupt initially */
W_REG(&eir->gpiointpolarity, 0);
W_REG(&eir->gpiointmask, 0);
/* Search for external UARTs */
n = 2;
for (i = 0; i < 2; i++) {
regs = (void *) REG_MAP(base + (i * 8), 8);
if (BCMINIT(serial_exists)(regs)) {
/* Set GPIO 1 to be the external UART IRQ */
W_REG(&eir->gpiointmask, 2);
if (add)
add(regs, irq, 13500000, 0);
}
}
/* Add internal UART if enabled */
if (R_REG(&eir->corecontrol) & CC_UE)
if (add)
add((void *) &eir->uartdata, irq, sb_clock(sbh), 2);
#endif
if (bus->extif.dev) if (bus->extif.dev)
mcore->nr_serial_ports = ssb_extif_serial_init(&bus->extif, mcore->serial_ports); mcore->nr_serial_ports = ssb_extif_serial_init(&bus->extif, mcore->serial_ports);
else if (bus->chipco.dev) else if (bus->chipco.dev)
@ -174,23 +133,47 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore)
{ {
struct ssb_bus *bus = mcore->dev->bus; struct ssb_bus *bus = mcore->dev->bus;
mcore->flash_buswidth = 2;
if (bus->chipco.dev) { if (bus->chipco.dev) {
mcore->flash_window = 0x1c000000; mcore->flash_window = 0x1c000000;
mcore->flash_window_size = 0x800000; mcore->flash_window_size = 0x02000000;
if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG)
& SSB_CHIPCO_CFG_DS16) == 0)
mcore->flash_buswidth = 1;
} else { } else {
mcore->flash_window = 0x1fc00000; mcore->flash_window = 0x1fc00000;
mcore->flash_window_size = 0x400000; mcore->flash_window_size = 0x00400000;
} }
} }
u32 ssb_cpu_clock(struct ssb_mipscore *mcore)
static void ssb_cpu_clock(struct ssb_mipscore *mcore)
{ {
struct ssb_bus *bus = mcore->dev->bus;
u32 pll_type, n, m, rate = 0;
if (bus->extif.dev) {
ssb_extif_get_clockcontrol(&bus->extif, &pll_type, &n, &m);
} else if (bus->chipco.dev) {
ssb_chipco_get_clockcpu(&bus->chipco, &pll_type, &n, &m);
} else
return 0;
if ((pll_type == SSB_PLLTYPE_5) || (bus->chip_id == 0x5365)) {
rate = 200000000;
} else {
rate = ssb_calc_clock_rate(pll_type, n, m);
}
if (pll_type == SSB_PLLTYPE_6) {
rate *= 2;
}
return rate;
} }
void ssb_mipscore_init(struct ssb_mipscore *mcore) void ssb_mipscore_init(struct ssb_mipscore *mcore)
{ {
struct ssb_bus *bus = mcore->dev->bus; struct ssb_bus *bus;
struct ssb_device *dev; struct ssb_device *dev;
unsigned long hz, ns; unsigned long hz, ns;
unsigned int irq, i; unsigned int irq, i;
@ -200,56 +183,39 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n"); ssb_dprintk(KERN_INFO PFX "Initializing MIPS core...\n");
bus = mcore->dev->bus;
hz = ssb_clockspeed(bus); hz = ssb_clockspeed(bus);
if (!hz) if (!hz)
hz = 100000000; hz = 100000000;
ns = 1000000000 / hz; ns = 1000000000 / hz;
//TODO if (bus->extif.dev)
#if 0 ssb_extif_timing_init(&bus->extif, ns);
if (have EXTIF) { else if (bus->chipco.dev)
/* Initialize extif so we can get to the LEDs and external UART */
W_REG(&eir->prog_config, CF_EN);
/* Set timing for the flash */
tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
tmp = tmp | (CEIL(40, ns) << FW_W1_SHIFT); /* W1 = 40nS */
tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
W_REG(&eir->prog_waitcount, tmp); /* 0x01020a0c for a 100Mhz clock */
/* Set programmable interface timing for external uart */
tmp = CEIL(10, ns) << FW_W3_SHIFT; /* W3 = 10nS */
tmp = tmp | (CEIL(20, ns) << FW_W2_SHIFT); /* W2 = 20nS */
tmp = tmp | (CEIL(100, ns) << FW_W1_SHIFT); /* W1 = 100nS */
tmp = tmp | CEIL(120, ns); /* W0 = 120nS */
W_REG(&eir->prog_waitcount, tmp);
}
else... chipcommon
#endif
if (bus->chipco.dev)
ssb_chipco_timing_init(&bus->chipco, ns); ssb_chipco_timing_init(&bus->chipco, ns);
/* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */ /* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */
for (irq = 2, i = 0; i < bus->nr_devices; i++) { for (irq = 2, i = 0; i < bus->nr_devices; i++) {
dev = &(bus->devices[i]); dev = &(bus->devices[i]);
dev->irq = ssb_mips_irq(dev) + 2; dev->irq = ssb_mips_irq(dev) + 2;
switch(dev->id.coreid) { switch (dev->id.coreid) {
case SSB_DEV_USB11_HOST: case SSB_DEV_USB11_HOST:
/* shouldn't need a separate irq line for non-4710, most of them have a proper /* shouldn't need a separate irq line for non-4710, most of them have a proper
* external usb controller on the pci */ * external usb controller on the pci */
if ((bus->chip_id == 0x4710) && (irq <= 4)) { if ((bus->chip_id == 0x4710) && (irq <= 4)) {
set_irq(dev, irq++); set_irq(dev, irq++);
break; break;
} }
case SSB_DEV_PCI: /* fallthrough */
case SSB_DEV_ETHERNET: case SSB_DEV_PCI:
case SSB_DEV_80211: case SSB_DEV_ETHERNET:
case SSB_DEV_USB20_HOST: case SSB_DEV_80211:
/* These devices get their own IRQ line if available, the rest goes on IRQ0 */ case SSB_DEV_USB20_HOST:
if (irq <= 4) { /* These devices get their own IRQ line if available, the rest goes on IRQ0 */
set_irq(dev, irq++); if (irq <= 4) {
break; set_irq(dev, irq++);
} break;
}
} }
} }

View File

@ -34,8 +34,10 @@ void pcicore_write32(struct ssb_pcicore *pc, u16 offset, u32 value)
#ifdef CONFIG_SSB_PCICORE_HOSTMODE #ifdef CONFIG_SSB_PCICORE_HOSTMODE
#include <asm/paccess.h> #include <asm/paccess.h>
/* Read the bus and catch bus exceptions. This is MIPS specific. */ /* Probe a 32bit value on the bus and catch bus exceptions.
#define mips_busprobe(val, addr) get_dbe((val), (addr)) * Returns nonzero on a bus exception.
* This is MIPS specific */
#define mips_busprobe32(val, addr) get_dbe((val), ((u32 *)(addr)))
/* Assume one-hot slot wiring */ /* Assume one-hot slot wiring */
#define SSB_PCI_SLOT_MAX 16 #define SSB_PCI_SLOT_MAX 16
@ -45,8 +47,8 @@ static DEFINE_SPINLOCK(cfgspace_lock);
/* Core to access the external PCI config space. Can only have one. */ /* Core to access the external PCI config space. Can only have one. */
static struct ssb_pcicore *extpci_core; static struct ssb_pcicore *extpci_core;
u32 pci_iobase = 0x100; static u32 ssb_pcicore_pcibus_iobase = 0x100;
u32 pci_membase = SSB_PCI_DMA; static u32 ssb_pcicore_pcibus_membase = SSB_PCI_DMA;
int pcibios_plat_dev_init(struct pci_dev *d) int pcibios_plat_dev_init(struct pci_dev *d)
{ {
@ -54,12 +56,16 @@ int pcibios_plat_dev_init(struct pci_dev *d)
int pos, size; int pos, size;
u32 *base; u32 *base;
printk("PCI: Fixing up device %s\n", pci_name(d)); ssb_printk(KERN_INFO "PCI: Fixing up device %s\n",
pci_name(d));
/* Fix up resource bases */ /* Fix up resource bases */
for (pos = 0; pos < 6; pos++) { for (pos = 0; pos < 6; pos++) {
res = &d->resource[pos]; res = &d->resource[pos];
base = ((res->flags & IORESOURCE_IO) ? &pci_iobase : &pci_membase); if (res->flags & IORESOURCE_IO)
base = &ssb_pcicore_pcibus_iobase;
else
base = &ssb_pcicore_pcibus_membase;
if (res->end) { if (res->end) {
size = res->end - res->start + 1; size = res->end - res->start + 1;
if (*base & (size - 1)) if (*base & (size - 1))
@ -85,7 +91,7 @@ static void __init ssb_fixup_pcibridge(struct pci_dev *dev)
if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0) if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0)
return; return;
printk("PCI: fixing up bridge\n"); ssb_printk(KERN_INFO "PCI: fixing up bridge\n");
/* Enable PCI bridge bus mastering and memory space */ /* Enable PCI bridge bus mastering and memory space */
pci_set_master(dev); pci_set_master(dev);
@ -93,10 +99,13 @@ static void __init ssb_fixup_pcibridge(struct pci_dev *dev)
/* Enable PCI bridge BAR1 prefetch and burst */ /* Enable PCI bridge BAR1 prefetch and burst */
pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3); pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3);
/* Make sure our latency is high enough to handle the devices behind us */
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xa8);
} }
DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_fixup_pcibridge); DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_fixup_pcibridge);
int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{ {
return ssb_mips_irq(extpci_core->dev) + 2; return ssb_mips_irq(extpci_core->dev) + 2;
} }
@ -147,7 +156,7 @@ static int ssb_extpci_read_config(struct ssb_pcicore *pc,
u32 addr, val; u32 addr, val;
void __iomem *mmio; void __iomem *mmio;
assert(pc->hostmode); SSB_WARN_ON(!pc->hostmode);
if (unlikely(len != 1 && len != 2 && len != 4)) if (unlikely(len != 1 && len != 2 && len != 4))
goto out; goto out;
addr = get_cfgspace_addr(pc, bus, dev, func, off); addr = get_cfgspace_addr(pc, bus, dev, func, off);
@ -158,7 +167,7 @@ static int ssb_extpci_read_config(struct ssb_pcicore *pc,
if (!mmio) if (!mmio)
goto out; goto out;
if (mips_busprobe(val, (u32 *) mmio)) { if (mips_busprobe32(val, mmio)) {
val = 0xffffffff; val = 0xffffffff;
goto unmap; goto unmap;
} }
@ -193,7 +202,7 @@ static int ssb_extpci_write_config(struct ssb_pcicore *pc,
u32 addr, val = 0; u32 addr, val = 0;
void __iomem *mmio; void __iomem *mmio;
assert(pc->hostmode); SSB_WARN_ON(!pc->hostmode);
if (unlikely(len != 1 && len != 2 && len != 4)) if (unlikely(len != 1 && len != 2 && len != 4))
goto out; goto out;
addr = get_cfgspace_addr(pc, bus, dev, func, off); addr = get_cfgspace_addr(pc, bus, dev, func, off);
@ -204,7 +213,7 @@ static int ssb_extpci_write_config(struct ssb_pcicore *pc,
if (!mmio) if (!mmio)
goto out; goto out;
if (mips_busprobe(val, (u32 *) mmio)) { if (mips_busprobe32(val, mmio)) {
val = 0xffffffff; val = 0xffffffff;
goto unmap; goto unmap;
} }
@ -224,7 +233,7 @@ static int ssb_extpci_write_config(struct ssb_pcicore *pc,
val = *((const u32 *)buf); val = *((const u32 *)buf);
break; break;
} }
writel(*((const u32 *)buf), mmio); writel(val, mmio);
err = 0; err = 0;
unmap: unmap:
@ -269,7 +278,7 @@ static struct pci_ops ssb_pcicore_pciops = {
static struct resource ssb_pcicore_mem_resource = { static struct resource ssb_pcicore_mem_resource = {
.name = "SSB PCIcore external memory", .name = "SSB PCIcore external memory",
.start = SSB_PCI_DMA, .start = SSB_PCI_DMA,
.end = (u32)SSB_PCI_DMA + (u32)SSB_PCI_DMA_SZ - 1, .end = SSB_PCI_DMA + SSB_PCI_DMA_SZ - 1,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}; };
@ -291,10 +300,8 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
{ {
u32 val; u32 val;
if (extpci_core) { if (WARN_ON(extpci_core))
WARN_ON(1);
return; return;
}
extpci_core = pc; extpci_core = pc;
ssb_dprintk(KERN_INFO PFX "PCIcore in host mode found\n"); ssb_dprintk(KERN_INFO PFX "PCIcore in host mode found\n");
@ -304,12 +311,14 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
pcicore_write32(pc, SSB_PCICORE_CTL, val); pcicore_write32(pc, SSB_PCICORE_CTL, val);
val |= SSB_PCICORE_CTL_CLK; /* Clock on */ val |= SSB_PCICORE_CTL_CLK; /* Clock on */
pcicore_write32(pc, SSB_PCICORE_CTL, val); pcicore_write32(pc, SSB_PCICORE_CTL, val);
udelay(150); udelay(150); /* Assertion time demanded by the PCI standard */
val |= SSB_PCICORE_CTL_RST; /* Deassert RST# */ val |= SSB_PCICORE_CTL_RST; /* Deassert RST# */
pcicore_write32(pc, SSB_PCICORE_CTL, val); pcicore_write32(pc, SSB_PCICORE_CTL, val);
udelay(1); val = SSB_PCICORE_ARBCTL_INTERN;
pcicore_write32(pc, SSB_PCICORE_ARBCTL, val);
udelay(1); /* Assertion time demanded by the PCI standard */
//TODO cardbus mode /*TODO cardbus mode */
/* 64MB I/O window */ /* 64MB I/O window */
pcicore_write32(pc, SSB_PCICORE_SBTOPCI0, pcicore_write32(pc, SSB_PCICORE_SBTOPCI0,
@ -336,6 +345,9 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
* The following needs change, if we want to port hostmode * The following needs change, if we want to port hostmode
* to non-MIPS platform. */ * to non-MIPS platform. */
set_io_port_base((unsigned long)ioremap_nocache(SSB_PCI_MEM, 0x04000000)); set_io_port_base((unsigned long)ioremap_nocache(SSB_PCI_MEM, 0x04000000));
/* Give some time to the PCI controller to configure itself with the new
* values. Not waiting at this point causes crashes of the machine. */
mdelay(10);
register_pci_controller(&ssb_pcicore_controller); register_pci_controller(&ssb_pcicore_controller);
} }
@ -364,7 +376,7 @@ static int pcicore_is_in_hostmode(struct ssb_pcicore *pc)
if (bus->chip_id == 0x5350) if (bus->chip_id == 0x5350)
return 0; return 0;
return !mips_busprobe(tmp, (u32 *) (bus->mmio + (pc->dev->core_index * SSB_CORE_SIZE))); return !mips_busprobe32(tmp, (bus->mmio + (pc->dev->core_index * SSB_CORE_SIZE)));
} }
#endif /* CONFIG_SSB_PCICORE_HOSTMODE */ #endif /* CONFIG_SSB_PCICORE_HOSTMODE */
@ -430,6 +442,7 @@ static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device,
v |= (u32)address << 18; v |= (u32)address << 18;
v |= data; v |= data;
pcicore_write32(pc, mdio_data, v); pcicore_write32(pc, mdio_data, v);
/* Wait for the device to complete the transaction */
udelay(10); udelay(10);
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
v = pcicore_read32(pc, mdio_control); v = pcicore_read32(pc, mdio_control);
@ -458,7 +471,8 @@ static void ssb_commit_settings(struct ssb_bus *bus)
struct ssb_device *dev; struct ssb_device *dev;
dev = bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev; dev = bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev;
assert(dev); if (WARN_ON(!dev))
return;
/* This forces an update of the cached registers. */ /* This forces an update of the cached registers. */
ssb_broadcast_value(dev, 0xFD8, 0); ssb_broadcast_value(dev, 0xFD8, 0);
} }
@ -496,9 +510,15 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
u32 intvec; u32 intvec;
intvec = ssb_read32(pdev, SSB_INTVEC); intvec = ssb_read32(pdev, SSB_INTVEC);
tmp = ssb_read32(dev, SSB_TPSFLAG); if ((bus->chip_id & 0xFF00) == 0x4400) {
tmp &= SSB_TPSFLAG_BPFLAG; /* Workaround: On the BCM44XX the BPFLAG routing
intvec |= tmp; * bit is wrong. Use a hardcoded constant. */
intvec |= 0x00000002;
} else {
tmp = ssb_read32(dev, SSB_TPSFLAG);
tmp &= SSB_TPSFLAG_BPFLAG;
intvec |= tmp;
}
ssb_write32(pdev, SSB_INTVEC, intvec); ssb_write32(pdev, SSB_INTVEC, intvec);
} }
@ -525,7 +545,7 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp); pcicore_write32(pc, SSB_PCICORE_SBTOPCI2, tmp);
} }
} else { } else {
assert(pdev->id.coreid == SSB_DEV_PCIE); WARN_ON(pdev->id.coreid != SSB_DEV_PCIE);
//TODO: Better make defines for all these magic PCIE values. //TODO: Better make defines for all these magic PCIE values.
if ((pdev->id.revision == 0) || (pdev->id.revision == 1)) { if ((pdev->id.revision == 0) || (pdev->id.revision == 1)) {
/* TLP Workaround register. */ /* TLP Workaround register. */

View File

@ -13,34 +13,43 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/ssb/ssb.h> #include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_regs.h> #include <linux/ssb/ssb_regs.h>
#include <linux/dma-mapping.h>
#include <linux/pci.h>
#ifdef CONFIG_SSB_PCIHOST #include <pcmcia/cs_types.h>
# include <linux/pci.h> #include <pcmcia/cs.h>
#endif #include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#ifdef CONFIG_SSB_PCMCIAHOST
# include <pcmcia/cs_types.h>
# include <pcmcia/cs.h>
# include <pcmcia/cistpl.h>
# include <pcmcia/ds.h>
#endif
MODULE_DESCRIPTION("Sonics Silicon Backplane driver"); MODULE_DESCRIPTION("Sonics Silicon Backplane driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* Temporary list of yet-to-be-attached buses */
static LIST_HEAD(attach_queue); static LIST_HEAD(attach_queue);
/* List if running buses */
static LIST_HEAD(buses); static LIST_HEAD(buses);
/* Software ID counter */
static unsigned int next_busnumber; static unsigned int next_busnumber;
/* buses_mutes locks the two buslists and the next_busnumber.
* Don't lock this directly, but use ssb_buses_[un]lock() below. */
static DEFINE_MUTEX(buses_mutex); static DEFINE_MUTEX(buses_mutex);
/* There are differences in the codeflow, if the bus is
* initialized from early boot, as various needed services
* are not available early. This is a mechanism to delay
* these initializations to after early boot has finished.
* It's also used to avoid mutex locking, as that's not
* available and needed early. */
static bool ssb_is_early_boot = 1;
static void ssb_buses_lock(void); static void ssb_buses_lock(void);
static void ssb_buses_unlock(void); static void ssb_buses_unlock(void);
#ifdef CONFIG_SSB_PCIHOST #ifdef CONFIG_SSB_PCIHOST
struct ssb_bus * ssb_pci_dev_to_bus(struct pci_dev *pdev) struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev)
{ {
struct ssb_bus *bus; struct ssb_bus *bus;
@ -58,7 +67,7 @@ found:
} }
#endif /* CONFIG_SSB_PCIHOST */ #endif /* CONFIG_SSB_PCIHOST */
static struct ssb_device * ssb_device_get(struct ssb_device *dev) static struct ssb_device *ssb_device_get(struct ssb_device *dev)
{ {
if (dev) if (dev)
get_device(dev->dev); get_device(dev->dev);
@ -122,6 +131,9 @@ static void ssb_bus_suspend(struct ssb_bus *bus, pm_message_t state)
#ifdef CONFIG_SSB_DRIVER_PCICORE #ifdef CONFIG_SSB_DRIVER_PCICORE
bus->pcicore.setup_done = 0; bus->pcicore.setup_done = 0;
#endif #endif
#ifdef CONFIG_SSB_DEBUG
bus->powered_up = 0;
#endif
} }
static int ssb_device_suspend(struct device *dev, pm_message_t state) static int ssb_device_suspend(struct device *dev, pm_message_t state)
@ -159,20 +171,53 @@ int ssb_devices_freeze(struct ssb_bus *bus)
int i; int i;
pm_message_t state = PMSG_FREEZE; pm_message_t state = PMSG_FREEZE;
/* First check that we are capable to freeze all devices. */
for (i = 0; i < bus->nr_devices; i++) { for (i = 0; i < bus->nr_devices; i++) {
dev = &(bus->devices[i]); dev = &(bus->devices[i]);
if (!dev->dev->driver) if (!dev->dev ||
continue; !dev->dev->driver ||
if (!device_is_registered(dev->dev)) !device_is_registered(dev->dev))
continue; continue;
drv = drv_to_ssb_drv(dev->dev->driver); drv = drv_to_ssb_drv(dev->dev->driver);
if (drv && drv->suspend) { if (!drv)
err = drv->suspend(dev, state); continue;
if (err) if (!drv->suspend) {
goto out; /* Nope, can't suspend this one. */
return -EOPNOTSUPP;
} }
} }
out: /* Now suspend all devices */
for (i = 0; i < bus->nr_devices; i++) {
dev = &(bus->devices[i]);
if (!dev->dev ||
!dev->dev->driver ||
!device_is_registered(dev->dev))
continue;
drv = drv_to_ssb_drv(dev->dev->driver);
if (!drv)
continue;
err = drv->suspend(dev, state);
if (err) {
ssb_printk(KERN_ERR PFX "Failed to freeze device %s\n",
dev->dev->bus_id);
goto err_unwind;
}
}
return 0;
err_unwind:
for (i--; i >= 0; i--) {
dev = &(bus->devices[i]);
if (!dev->dev ||
!dev->dev->driver ||
!device_is_registered(dev->dev))
continue;
drv = drv_to_ssb_drv(dev->dev->driver);
if (!drv)
continue;
if (drv->resume)
drv->resume(dev);
}
return err; return err;
} }
@ -180,24 +225,28 @@ int ssb_devices_thaw(struct ssb_bus *bus)
{ {
struct ssb_device *dev; struct ssb_device *dev;
struct ssb_driver *drv; struct ssb_driver *drv;
int err = 0; int err;
int i; int i;
for (i = 0; i < bus->nr_devices; i++) { for (i = 0; i < bus->nr_devices; i++) {
dev = &(bus->devices[i]); dev = &(bus->devices[i]);
if (!dev->dev->driver) if (!dev->dev ||
continue; !dev->dev->driver ||
if (!device_is_registered(dev->dev)) !device_is_registered(dev->dev))
continue; continue;
drv = drv_to_ssb_drv(dev->dev->driver); drv = drv_to_ssb_drv(dev->dev->driver);
if (drv && drv->resume) { if (!drv)
err = drv->resume(dev); continue;
if (err) if (SSB_WARN_ON(!drv->resume))
goto out; continue;
err = drv->resume(dev);
if (err) {
ssb_printk(KERN_ERR PFX "Failed to thaw device %s\n",
dev->dev->bus_id);
} }
} }
out:
return err; return 0;
} }
#endif /* CONFIG_SSB_PCIHOST */ #endif /* CONFIG_SSB_PCIHOST */
@ -271,27 +320,47 @@ static int ssb_bus_match(struct device *dev, struct device_driver *drv)
return 0; return 0;
} }
static int ssb_device_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
int ret, i = 0, length = 0;
if (!dev)
return -ENODEV;
ret = add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"MODALIAS=ssb:v%04Xid%04Xrev%02X",
ssb_dev->id.vendor, ssb_dev->id.coreid,
ssb_dev->id.revision);
envp[i] = NULL;
return ret;
}
static struct bus_type ssb_bustype = { static struct bus_type ssb_bustype = {
.name = NULL, /* Intentionally NULL to indicate early boot */ .name = "ssb",
.match = ssb_bus_match, .match = ssb_bus_match,
.probe = ssb_device_probe, .probe = ssb_device_probe,
.remove = ssb_device_remove, .remove = ssb_device_remove,
.shutdown = ssb_device_shutdown, .shutdown = ssb_device_shutdown,
.suspend = ssb_device_suspend, .suspend = ssb_device_suspend,
.resume = ssb_device_resume, .resume = ssb_device_resume,
.uevent = ssb_device_uevent,
}; };
#define is_early_boot() (ssb_bustype.name == NULL)
static void ssb_buses_lock(void) static void ssb_buses_lock(void)
{ {
if (!is_early_boot()) /* See the comment at the ssb_is_early_boot definition */
if (!ssb_is_early_boot)
mutex_lock(&buses_mutex); mutex_lock(&buses_mutex);
} }
static void ssb_buses_unlock(void) static void ssb_buses_unlock(void)
{ {
if (!is_early_boot()) /* See the comment at the ssb_is_early_boot definition */
if (!ssb_is_early_boot)
mutex_unlock(&buses_mutex); mutex_unlock(&buses_mutex);
} }
@ -421,9 +490,14 @@ static int ssb_attach_queued_buses(void)
* is too early in boot for embedded systems * is too early in boot for embedded systems
* (no udelay() available). So do it here in attach stage. * (no udelay() available). So do it here in attach stage.
*/ */
err = ssb_bus_powerup(bus, 0);
if (err)
goto error;
ssb_pcicore_init(&bus->pcicore); ssb_pcicore_init(&bus->pcicore);
ssb_bus_may_powerdown(bus);
err = ssb_devices_register(bus); err = ssb_devices_register(bus);
error:
if (err) { if (err) {
drop_them_all = 1; drop_them_all = 1;
list_del(&bus->list); list_del(&bus->list);
@ -467,6 +541,7 @@ static void ssb_ssb_write32(struct ssb_device *dev, u16 offset, u32 value)
writel(value, bus->mmio + offset); writel(value, bus->mmio + offset);
} }
/* Ops for the plain SSB bus without a host-device (no PCI or PCMCIA). */
static const struct ssb_bus_ops ssb_ssb_ops = { static const struct ssb_bus_ops ssb_ssb_ops = {
.read16 = ssb_ssb_read16, .read16 = ssb_ssb_read16,
.read32 = ssb_ssb_read32, .read32 = ssb_ssb_read32,
@ -475,8 +550,7 @@ static const struct ssb_bus_ops ssb_ssb_ops = {
}; };
static int ssb_fetch_invariants(struct ssb_bus *bus, static int ssb_fetch_invariants(struct ssb_bus *bus,
int (*get_invariants)(struct ssb_bus *bus, ssb_invariants_func_t get_invariants)
struct ssb_init_invariants *iv))
{ {
struct ssb_init_invariants iv; struct ssb_init_invariants iv;
int err; int err;
@ -492,8 +566,7 @@ out:
} }
static int ssb_bus_register(struct ssb_bus *bus, static int ssb_bus_register(struct ssb_bus *bus,
int (*get_invariants)(struct ssb_bus *bus, ssb_invariants_func_t get_invariants,
struct ssb_init_invariants *iv),
unsigned long baseaddr) unsigned long baseaddr)
{ {
int err; int err;
@ -522,15 +595,22 @@ static int ssb_bus_register(struct ssb_bus *bus,
goto err_pci_exit; goto err_pci_exit;
/* Initialize basic system devices (if available) */ /* Initialize basic system devices (if available) */
err = ssb_bus_powerup(bus, 0);
if (err)
goto err_pcmcia_exit;
ssb_chipcommon_init(&bus->chipco); ssb_chipcommon_init(&bus->chipco);
ssb_mipscore_init(&bus->mipscore); ssb_mipscore_init(&bus->mipscore);
err = ssb_fetch_invariants(bus, get_invariants); err = ssb_fetch_invariants(bus, get_invariants);
if (err) if (err) {
ssb_bus_may_powerdown(bus);
goto err_pcmcia_exit; goto err_pcmcia_exit;
}
ssb_bus_may_powerdown(bus);
/* Queue it for attach */ /* Queue it for attach.
* See the comment at the ssb_is_early_boot definition. */
list_add_tail(&bus->list, &attach_queue); list_add_tail(&bus->list, &attach_queue);
if (!is_early_boot()) { if (!ssb_is_early_boot) {
/* This is not early boot, so we must attach the bus now */ /* This is not early boot, so we must attach the bus now */
err = ssb_attach_queued_buses(); err = ssb_attach_queued_buses();
if (err) if (err)
@ -601,8 +681,7 @@ EXPORT_SYMBOL(ssb_bus_pcmciabus_register);
int ssb_bus_ssbbus_register(struct ssb_bus *bus, int ssb_bus_ssbbus_register(struct ssb_bus *bus,
unsigned long baseaddr, unsigned long baseaddr,
int (*get_invariants)(struct ssb_bus *bus, ssb_invariants_func_t get_invariants)
struct ssb_init_invariants *iv))
{ {
int err; int err;
@ -695,13 +774,13 @@ u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m)
case SSB_PLLTYPE_2: /* 48Mhz, 4 dividers */ case SSB_PLLTYPE_2: /* 48Mhz, 4 dividers */
n1 += SSB_CHIPCO_CLK_T2_BIAS; n1 += SSB_CHIPCO_CLK_T2_BIAS;
n2 += SSB_CHIPCO_CLK_T2_BIAS; n2 += SSB_CHIPCO_CLK_T2_BIAS;
assert((n1 >= 2) && (n1 <= 7)); SSB_WARN_ON(!((n1 >= 2) && (n1 <= 7)));
assert((n2 >= 5) && (n2 <= 23)); SSB_WARN_ON(!((n2 >= 5) && (n2 <= 23)));
break; break;
case SSB_PLLTYPE_5: /* 25Mhz, 4 dividers */ case SSB_PLLTYPE_5: /* 25Mhz, 4 dividers */
return 100000000; return 100000000;
default: default:
assert(0); SSB_WARN_ON(1);
} }
switch (plltype) { switch (plltype) {
@ -750,9 +829,9 @@ u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m)
m1 += SSB_CHIPCO_CLK_T2_BIAS; m1 += SSB_CHIPCO_CLK_T2_BIAS;
m2 += SSB_CHIPCO_CLK_T2M2_BIAS; m2 += SSB_CHIPCO_CLK_T2M2_BIAS;
m3 += SSB_CHIPCO_CLK_T2_BIAS; m3 += SSB_CHIPCO_CLK_T2_BIAS;
assert((m1 >= 2) && (m1 <= 7)); SSB_WARN_ON(!((m1 >= 2) && (m1 <= 7)));
assert((m2 >= 3) && (m2 <= 10)); SSB_WARN_ON(!((m2 >= 3) && (m2 <= 10)));
assert((m3 >= 2) && (m3 <= 7)); SSB_WARN_ON(!((m3 >= 2) && (m3 <= 7)));
if (!(mc & SSB_CHIPCO_CLK_T2MC_M1BYP)) if (!(mc & SSB_CHIPCO_CLK_T2MC_M1BYP))
clock /= m1; clock /= m1;
@ -762,7 +841,7 @@ u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m)
clock /= m3; clock /= m3;
return clock; return clock;
default: default:
assert(0); SSB_WARN_ON(1);
} }
return 0; return 0;
} }
@ -774,12 +853,13 @@ u32 ssb_clockspeed(struct ssb_bus *bus)
u32 plltype; u32 plltype;
u32 clkctl_n, clkctl_m; u32 clkctl_n, clkctl_m;
//TODO if EXTIF: PLLTYPE == 1, read n from clockcontrol_n, m from clockcontrol_sb if (ssb_extif_available(&bus->extif))
ssb_extif_get_clockcontrol(&bus->extif, &plltype,
if (bus->chipco.dev) { &clkctl_n, &clkctl_m);
else if (bus->chipco.dev)
ssb_chipco_get_clockcontrol(&bus->chipco, &plltype, ssb_chipco_get_clockcontrol(&bus->chipco, &plltype,
&clkctl_n, &clkctl_m); &clkctl_n, &clkctl_m);
} else else
return 0; return 0;
if (bus->chip_id == 0x5365) { if (bus->chip_id == 0x5365) {
@ -804,7 +884,7 @@ static u32 ssb_tmslow_reject_bitmask(struct ssb_device *dev)
case SSB_IDLOW_SSBREV_23: case SSB_IDLOW_SSBREV_23:
return SSB_TMSLOW_REJECT_23; return SSB_TMSLOW_REJECT_23;
default: default:
assert(0); WARN_ON(1);
} }
return (SSB_TMSLOW_REJECT_22 | SSB_TMSLOW_REJECT_23); return (SSB_TMSLOW_REJECT_22 | SSB_TMSLOW_REJECT_23);
} }
@ -822,6 +902,18 @@ int ssb_device_is_enabled(struct ssb_device *dev)
} }
EXPORT_SYMBOL(ssb_device_is_enabled); EXPORT_SYMBOL(ssb_device_is_enabled);
static void ssb_flush_tmslow(struct ssb_device *dev)
{
/* Make _really_ sure the device has finished the TMSLOW
* register write transaction, as we risk running into
* a machine check exception otherwise.
* Do this by reading the register back to commit the
* PCI write and delay an additional usec for the device
* to react to the change. */
ssb_read32(dev, SSB_TMSLOW);
udelay(1);
}
void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags) void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags)
{ {
u32 val; u32 val;
@ -830,9 +922,7 @@ void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags)
ssb_write32(dev, SSB_TMSLOW, ssb_write32(dev, SSB_TMSLOW,
SSB_TMSLOW_RESET | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET | SSB_TMSLOW_CLOCK |
SSB_TMSLOW_FGC | core_specific_flags); SSB_TMSLOW_FGC | core_specific_flags);
/* flush */ ssb_flush_tmslow(dev);
ssb_read32(dev, SSB_TMSLOW);
udelay(1);
/* Clear SERR if set. This is a hw bug workaround. */ /* Clear SERR if set. This is a hw bug workaround. */
if (ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_SERR) if (ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_SERR)
@ -847,18 +937,16 @@ void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags)
ssb_write32(dev, SSB_TMSLOW, ssb_write32(dev, SSB_TMSLOW,
SSB_TMSLOW_CLOCK | SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_FGC |
core_specific_flags); core_specific_flags);
/* flush */ ssb_flush_tmslow(dev);
ssb_read32(dev, SSB_TMSLOW);
udelay(1);
ssb_write32(dev, SSB_TMSLOW, SSB_TMSLOW_CLOCK | ssb_write32(dev, SSB_TMSLOW, SSB_TMSLOW_CLOCK |
core_specific_flags); core_specific_flags);
/* flush */ ssb_flush_tmslow(dev);
ssb_read32(dev, SSB_TMSLOW);
udelay(1);
} }
EXPORT_SYMBOL(ssb_device_enable); EXPORT_SYMBOL(ssb_device_enable);
/* Wait for a bit in a register to get set or unset.
* timeout is in units of ten-microseconds */
static int ssb_wait_bit(struct ssb_device *dev, u16 reg, u32 bitmask, static int ssb_wait_bit(struct ssb_device *dev, u16 reg, u32 bitmask,
int timeout, int set) int timeout, int set)
{ {
@ -898,22 +986,18 @@ void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags)
SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
reject | SSB_TMSLOW_RESET | reject | SSB_TMSLOW_RESET |
core_specific_flags); core_specific_flags);
/* flush */ ssb_flush_tmslow(dev);
ssb_read32(dev, SSB_TMSLOW);
udelay(1);
ssb_write32(dev, SSB_TMSLOW, ssb_write32(dev, SSB_TMSLOW,
reject | SSB_TMSLOW_RESET | reject | SSB_TMSLOW_RESET |
core_specific_flags); core_specific_flags);
/* flush */ ssb_flush_tmslow(dev);
ssb_read32(dev, SSB_TMSLOW);
udelay(1);
} }
EXPORT_SYMBOL(ssb_device_disable); EXPORT_SYMBOL(ssb_device_disable);
u32 ssb_dma_translation(struct ssb_device *dev) u32 ssb_dma_translation(struct ssb_device *dev)
{ {
switch(dev->bus->bustype) { switch (dev->bus->bustype) {
case SSB_BUSTYPE_SSB: case SSB_BUSTYPE_SSB:
return 0; return 0;
case SSB_BUSTYPE_PCI: case SSB_BUSTYPE_PCI:
@ -943,28 +1027,31 @@ EXPORT_SYMBOL(ssb_dma_set_mask);
int ssb_bus_may_powerdown(struct ssb_bus *bus) int ssb_bus_may_powerdown(struct ssb_bus *bus)
{ {
struct ssb_chipcommon *cc; struct ssb_chipcommon *cc;
int err; int err = 0;
/* On buses where more than one core may be working /* On buses where more than one core may be working
* at a time, we must not powerdown stuff if there are * at a time, we must not powerdown stuff if there are
* still cores that may want to run. */ * still cores that may want to run. */
if (bus->bustype == SSB_BUSTYPE_SSB) if (bus->bustype == SSB_BUSTYPE_SSB)
return 0; goto out;
cc = &bus->chipco; cc = &bus->chipco;
ssb_chipco_set_clockmode(cc, SSB_CLKMODE_SLOW); ssb_chipco_set_clockmode(cc, SSB_CLKMODE_SLOW);
err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0); err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0);
if (err) if (err)
goto error; goto error;
out:
return 0; #ifdef CONFIG_SSB_DEBUG
bus->powered_up = 0;
#endif
return err;
error: error:
ssb_printk(KERN_ERR PFX "Bus powerdown failed\n"); ssb_printk(KERN_ERR PFX "Bus powerdown failed\n");
return err; goto out;
} }
EXPORT_SYMBOL(ssb_bus_may_powerdown); EXPORT_SYMBOL(ssb_bus_may_powerdown);
int ssb_bus_powerup(struct ssb_bus *bus, int dynamic_pctl) int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl)
{ {
struct ssb_chipcommon *cc; struct ssb_chipcommon *cc;
int err; int err;
@ -977,6 +1064,9 @@ int ssb_bus_powerup(struct ssb_bus *bus, int dynamic_pctl)
mode = dynamic_pctl ? SSB_CLKMODE_DYNAMIC : SSB_CLKMODE_FAST; mode = dynamic_pctl ? SSB_CLKMODE_DYNAMIC : SSB_CLKMODE_FAST;
ssb_chipco_set_clockmode(cc, mode); ssb_chipco_set_clockmode(cc, mode);
#ifdef CONFIG_SSB_DEBUG
bus->powered_up = 1;
#endif
return 0; return 0;
error: error:
ssb_printk(KERN_ERR PFX "Bus powerup failed\n"); ssb_printk(KERN_ERR PFX "Bus powerup failed\n");
@ -993,15 +1083,15 @@ u32 ssb_admatch_base(u32 adm)
base = (adm & SSB_ADM_BASE0); base = (adm & SSB_ADM_BASE0);
break; break;
case SSB_ADM_TYPE1: case SSB_ADM_TYPE1:
assert(!(adm & SSB_ADM_NEG)); /* unsupported */ SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */
base = (adm & SSB_ADM_BASE1); base = (adm & SSB_ADM_BASE1);
break; break;
case SSB_ADM_TYPE2: case SSB_ADM_TYPE2:
assert(!(adm & SSB_ADM_NEG)); /* unsupported */ SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */
base = (adm & SSB_ADM_BASE2); base = (adm & SSB_ADM_BASE2);
break; break;
default: default:
assert(0); SSB_WARN_ON(1);
} }
return base; return base;
@ -1017,15 +1107,15 @@ u32 ssb_admatch_size(u32 adm)
size = ((adm & SSB_ADM_SZ0) >> SSB_ADM_SZ0_SHIFT); size = ((adm & SSB_ADM_SZ0) >> SSB_ADM_SZ0_SHIFT);
break; break;
case SSB_ADM_TYPE1: case SSB_ADM_TYPE1:
assert(!(adm & SSB_ADM_NEG)); /* unsupported */ SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */
size = ((adm & SSB_ADM_SZ1) >> SSB_ADM_SZ1_SHIFT); size = ((adm & SSB_ADM_SZ1) >> SSB_ADM_SZ1_SHIFT);
break; break;
case SSB_ADM_TYPE2: case SSB_ADM_TYPE2:
assert(!(adm & SSB_ADM_NEG)); /* unsupported */ SSB_WARN_ON(adm & SSB_ADM_NEG); /* unsupported */
size = ((adm & SSB_ADM_SZ2) >> SSB_ADM_SZ2_SHIFT); size = ((adm & SSB_ADM_SZ2) >> SSB_ADM_SZ2_SHIFT);
break; break;
default: default:
assert(0); SSB_WARN_ON(1);
} }
size = (1 << (size + 1)); size = (1 << (size + 1));
@ -1037,7 +1127,8 @@ static int __init ssb_modinit(void)
{ {
int err; int err;
ssb_bustype.name = "ssb"; /* See the comment at the ssb_is_early_boot definition */
ssb_is_early_boot = 0;
err = bus_register(&ssb_bustype); err = bus_register(&ssb_bustype);
if (err) if (err)
return err; return err;
@ -1051,12 +1142,21 @@ static int __init ssb_modinit(void)
if (err) if (err)
bus_unregister(&ssb_bustype); bus_unregister(&ssb_bustype);
err = b43_pci_ssb_bridge_init();
if (err) {
ssb_printk(KERN_ERR "Broadcom 43xx PCI-SSB-bridge "
"initialization failed");
/* don't fail SSB init because of this */
err = 0;
}
return err; return err;
} }
subsys_initcall(ssb_modinit); subsys_initcall(ssb_modinit);
static void __exit ssb_modexit(void) static void __exit ssb_modexit(void)
{ {
b43_pci_ssb_bridge_exit();
bus_unregister(&ssb_bustype); bus_unregister(&ssb_bustype);
} }
module_exit(ssb_modexit) module_exit(ssb_modexit)

View File

@ -23,6 +23,11 @@
#include "ssb_private.h" #include "ssb_private.h"
/* Define the following to 1 to enable a printk on each coreswitch. */
#define SSB_VERBOSE_PCICORESWITCH_DEBUG 0
/* Lowlevel coreswitching */
int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx) int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
{ {
int err; int err;
@ -60,10 +65,12 @@ int ssb_pci_switch_core(struct ssb_bus *bus,
int err; int err;
unsigned long flags; unsigned long flags;
ssb_dprintk(KERN_INFO PFX #if SSB_VERBOSE_PCICORESWITCH_DEBUG
"Switching to %s core, index %d\n", ssb_printk(KERN_INFO PFX
ssb_core_name(dev->id.coreid), "Switching to %s core, index %d\n",
dev->core_index); ssb_core_name(dev->id.coreid),
dev->core_index);
#endif
spin_lock_irqsave(&bus->bar_lock, flags); spin_lock_irqsave(&bus->bar_lock, flags);
err = ssb_pci_switch_coreidx(bus, dev->core_index); err = ssb_pci_switch_coreidx(bus, dev->core_index);
@ -74,6 +81,7 @@ int ssb_pci_switch_core(struct ssb_bus *bus,
return err; return err;
} }
/* Enable/disable the on board crystal oscillator and/or PLL. */
int ssb_pci_xtal(struct ssb_bus *bus, u32 what, int turn_on) int ssb_pci_xtal(struct ssb_bus *bus, u32 what, int turn_on)
{ {
int err; int err;
@ -158,7 +166,9 @@ err_pci:
goto out; goto out;
} }
/* Get the word-offset for a SSB_SPROM_XXX define. */
#define SPOFF(offset) (((offset) - SSB_SPROM_BASE) / sizeof(u16)) #define SPOFF(offset) (((offset) - SSB_SPROM_BASE) / sizeof(u16))
/* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
#define SPEX(_outvar, _offset, _mask, _shift) \ #define SPEX(_outvar, _offset, _mask, _shift) \
out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift)) out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
@ -296,15 +306,15 @@ static void sprom_extract_r1(struct ssb_sprom_r1 *out, const u16 *in)
SPEX(pci_pid, SSB_SPROM1_PID, 0xFFFF, 0); SPEX(pci_pid, SSB_SPROM1_PID, 0xFFFF, 0);
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
v = in[SPOFF(SSB_SPROM1_IL0MAC) + i]; v = in[SPOFF(SSB_SPROM1_IL0MAC) + i];
*(((u16 *)out->il0mac) + i) = cpu_to_be16(v); *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v);
} }
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
v = in[SPOFF(SSB_SPROM1_ET0MAC) + i]; v = in[SPOFF(SSB_SPROM1_ET0MAC) + i];
*(((u16 *)out->et0mac) + i) = cpu_to_be16(v); *(((__be16 *)out->et0mac) + i) = cpu_to_be16(v);
} }
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
v = in[SPOFF(SSB_SPROM1_ET1MAC) + i]; v = in[SPOFF(SSB_SPROM1_ET1MAC) + i];
*(((u16 *)out->et1mac) + i) = cpu_to_be16(v); *(((__be16 *)out->et1mac) + i) = cpu_to_be16(v);
} }
SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0); SPEX(et0phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0A, 0);
SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A, SPEX(et1phyaddr, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1A,
@ -342,7 +352,7 @@ static void sprom_extract_r1(struct ssb_sprom_r1 *out, const u16 *in)
SSB_SPROM1_AGAIN_BG_SHIFT); SSB_SPROM1_AGAIN_BG_SHIFT);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
v = in[SPOFF(SSB_SPROM1_OEM) + i]; v = in[SPOFF(SSB_SPROM1_OEM) + i];
*(((u16 *)out->oem) + i) = cpu_to_le16(v); *(((__le16 *)out->oem) + i) = cpu_to_le16(v);
} }
} }
@ -364,7 +374,7 @@ static void sprom_extract_r2(struct ssb_sprom_r2 *out, const u16 *in)
SPEX(ofdm_pwr_off, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0); SPEX(ofdm_pwr_off, SSB_SPROM2_OPO, SSB_SPROM2_OPO_VALUE, 0);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
v = in[SPOFF(SSB_SPROM2_CCODE) + i]; v = in[SPOFF(SSB_SPROM2_CCODE) + i];
*(((u16 *)out->country_str) + i) = cpu_to_le16(v); *(((__le16 *)out->country_str) + i) = cpu_to_le16(v);
} }
} }
@ -489,50 +499,81 @@ out:
return err; return err;
} }
#ifdef CONFIG_SSB_DEBUG
static int ssb_pci_assert_buspower(struct ssb_bus *bus)
{
if (likely(bus->powered_up))
return 0;
printk(KERN_ERR PFX "FATAL ERROR: Bus powered down "
"while accessing PCI MMIO space\n");
if (bus->power_warn_count <= 10) {
bus->power_warn_count++;
dump_stack();
}
return -ENODEV;
}
#else /* DEBUG */
static inline int ssb_pci_assert_buspower(struct ssb_bus *bus)
{
return 0;
}
#endif /* DEBUG */
static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset) static u16 ssb_pci_read16(struct ssb_device *dev, u16 offset)
{ {
struct ssb_bus *bus = dev->bus; struct ssb_bus *bus = dev->bus;
if (unlikely(ssb_pci_assert_buspower(bus)))
return 0xFFFF;
if (unlikely(bus->mapped_device != dev)) { if (unlikely(bus->mapped_device != dev)) {
if (unlikely(ssb_pci_switch_core(bus, dev))) if (unlikely(ssb_pci_switch_core(bus, dev)))
return 0xFFFF; return 0xFFFF;
} }
return readw(bus->mmio + offset); return ioread16(bus->mmio + offset);
} }
static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset) static u32 ssb_pci_read32(struct ssb_device *dev, u16 offset)
{ {
struct ssb_bus *bus = dev->bus; struct ssb_bus *bus = dev->bus;
if (unlikely(ssb_pci_assert_buspower(bus)))
return 0xFFFFFFFF;
if (unlikely(bus->mapped_device != dev)) { if (unlikely(bus->mapped_device != dev)) {
if (unlikely(ssb_pci_switch_core(bus, dev))) if (unlikely(ssb_pci_switch_core(bus, dev)))
return 0xFFFFFFFF; return 0xFFFFFFFF;
} }
return readl(bus->mmio + offset); return ioread32(bus->mmio + offset);
} }
static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value) static void ssb_pci_write16(struct ssb_device *dev, u16 offset, u16 value)
{ {
struct ssb_bus *bus = dev->bus; struct ssb_bus *bus = dev->bus;
if (unlikely(ssb_pci_assert_buspower(bus)))
return;
if (unlikely(bus->mapped_device != dev)) { if (unlikely(bus->mapped_device != dev)) {
if (unlikely(ssb_pci_switch_core(bus, dev))) if (unlikely(ssb_pci_switch_core(bus, dev)))
return; return;
} }
writew(value, bus->mmio + offset); iowrite16(value, bus->mmio + offset);
} }
static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value) static void ssb_pci_write32(struct ssb_device *dev, u16 offset, u32 value)
{ {
struct ssb_bus *bus = dev->bus; struct ssb_bus *bus = dev->bus;
if (unlikely(ssb_pci_assert_buspower(bus)))
return;
if (unlikely(bus->mapped_device != dev)) { if (unlikely(bus->mapped_device != dev)) {
if (unlikely(ssb_pci_switch_core(bus, dev))) if (unlikely(ssb_pci_switch_core(bus, dev)))
return; return;
} }
writel(value, bus->mmio + offset); iowrite32(value, bus->mmio + offset);
} }
/* Not "static", as it's used in main.c */
const struct ssb_bus_ops ssb_pci_ops = { const struct ssb_bus_ops ssb_pci_ops = {
.read16 = ssb_pci_read16, .read16 = ssb_pci_read16,
.read32 = ssb_pci_read32, .read32 = ssb_pci_read32,
@ -590,6 +631,9 @@ static ssize_t ssb_pci_attr_sprom_show(struct device *pcidev,
if (!sprom) if (!sprom)
goto out; goto out;
/* Use interruptible locking, as the SPROM write might
* be holding the lock for several seconds. So allow userspace
* to cancel operation. */
err = -ERESTARTSYS; err = -ERESTARTSYS;
if (mutex_lock_interruptible(&bus->pci_sprom_mutex)) if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
goto out_kfree; goto out_kfree;
@ -632,10 +676,18 @@ static ssize_t ssb_pci_attr_sprom_store(struct device *pcidev,
goto out_kfree; goto out_kfree;
} }
/* Use interruptible locking, as the SPROM write might
* be holding the lock for several seconds. So allow userspace
* to cancel operation. */
err = -ERESTARTSYS; err = -ERESTARTSYS;
if (mutex_lock_interruptible(&bus->pci_sprom_mutex)) if (mutex_lock_interruptible(&bus->pci_sprom_mutex))
goto out_kfree; goto out_kfree;
err = ssb_devices_freeze(bus); err = ssb_devices_freeze(bus);
if (err == -EOPNOTSUPP) {
ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze devices. "
"No suspend support. Is CONFIG_PM enabled?\n");
goto out_unlock;
}
if (err) { if (err) {
ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n"); ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
goto out_unlock; goto out_unlock;

View File

@ -21,6 +21,10 @@
#include "ssb_private.h" #include "ssb_private.h"
/* Define the following to 1 to enable a printk on each coreswitch. */
#define SSB_VERBOSE_PCMCIACORESWITCH_DEBUG 0
int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus, int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus,
u8 coreidx) u8 coreidx)
{ {
@ -91,10 +95,12 @@ int ssb_pcmcia_switch_core(struct ssb_bus *bus,
int err; int err;
unsigned long flags; unsigned long flags;
ssb_dprintk(KERN_INFO PFX #if SSB_VERBOSE_PCMCIACORESWITCH_DEBUG
"Switching to %s core, index %d\n", ssb_printk(KERN_INFO PFX
ssb_core_name(dev->id.coreid), "Switching to %s core, index %d\n",
dev->core_index); ssb_core_name(dev->id.coreid),
dev->core_index);
#endif
spin_lock_irqsave(&bus->bar_lock, flags); spin_lock_irqsave(&bus->bar_lock, flags);
err = ssb_pcmcia_switch_coreidx(bus, dev->core_index); err = ssb_pcmcia_switch_coreidx(bus, dev->core_index);
@ -112,7 +118,7 @@ int ssb_pcmcia_switch_segment(struct ssb_bus *bus, u8 seg)
conf_reg_t reg; conf_reg_t reg;
int res, err = 0; int res, err = 0;
assert(seg == 0 || seg == 1); SSB_WARN_ON((seg != 0) && (seg != 1));
reg.Offset = 0x34; reg.Offset = 0x34;
reg.Function = 0; reg.Function = 0;
spin_lock_irqsave(&bus->bar_lock, flags); spin_lock_irqsave(&bus->bar_lock, flags);
@ -145,6 +151,9 @@ error:
goto out_unlock; goto out_unlock;
} }
/* These are the main device register access functions.
* do_select_core is inline to have the likely hotpath inline.
* All unlikely codepaths are out-of-line. */
static inline int do_select_core(struct ssb_bus *bus, static inline int do_select_core(struct ssb_bus *bus,
struct ssb_device *dev, struct ssb_device *dev,
u16 *offset) u16 *offset)
@ -176,7 +185,7 @@ static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset)
if (unlikely(do_select_core(bus, dev, &offset))) if (unlikely(do_select_core(bus, dev, &offset)))
return 0xFFFF; return 0xFFFF;
x = readw(bus->mmio + offset); x = readw(bus->mmio + offset);
//printk("R16 0x%04X, 0x%04X\n", offset, x);
return x; return x;
} }
@ -188,7 +197,7 @@ static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset)
if (unlikely(do_select_core(bus, dev, &offset))) if (unlikely(do_select_core(bus, dev, &offset)))
return 0xFFFFFFFF; return 0xFFFFFFFF;
x = readl(bus->mmio + offset); x = readl(bus->mmio + offset);
//printk("R32 0x%04X, 0x%08X\n", offset, x);
return x; return x;
} }
@ -198,7 +207,6 @@ static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value)
if (unlikely(do_select_core(bus, dev, &offset))) if (unlikely(do_select_core(bus, dev, &offset)))
return; return;
//printk("W16 0x%04X, 0x%04X\n", offset, value);
writew(value, bus->mmio + offset); writew(value, bus->mmio + offset);
} }
@ -208,13 +216,13 @@ static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value)
if (unlikely(do_select_core(bus, dev, &offset))) if (unlikely(do_select_core(bus, dev, &offset)))
return; return;
//printk("W32 0x%04X, 0x%08X\n", offset, value);
readw(bus->mmio + offset); readw(bus->mmio + offset);
writew(value >> 16, bus->mmio + offset + 2); writew(value >> 16, bus->mmio + offset + 2);
readw(bus->mmio + offset); readw(bus->mmio + offset);
writew(value, bus->mmio + offset); writew(value, bus->mmio + offset);
} }
/* Not "static", as it's used in main.c */
const struct ssb_bus_ops ssb_pcmcia_ops = { const struct ssb_bus_ops ssb_pcmcia_ops = {
.read16 = ssb_pcmcia_read16, .read16 = ssb_pcmcia_read16,
.read32 = ssb_pcmcia_read32, .read32 = ssb_pcmcia_read32,

View File

@ -15,19 +15,17 @@
#include <linux/ssb/ssb.h> #include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_regs.h> #include <linux/ssb/ssb_regs.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <asm/io.h> #include <linux/io.h>
#ifdef CONFIG_SSB_PCMCIAHOST #include <pcmcia/cs_types.h>
# include <pcmcia/cs_types.h> #include <pcmcia/cs.h>
# include <pcmcia/cs.h> #include <pcmcia/cistpl.h>
# include <pcmcia/cistpl.h> #include <pcmcia/ds.h>
# include <pcmcia/ds.h>
#endif
#include "ssb_private.h" #include "ssb_private.h"
const char * ssb_core_name(u16 coreid) const char *ssb_core_name(u16 coreid)
{ {
switch (coreid) { switch (coreid) {
case SSB_DEV_CHIPCOMMON: case SSB_DEV_CHIPCOMMON:
@ -205,7 +203,7 @@ void ssb_iounmap(struct ssb_bus *bus)
#ifdef CONFIG_SSB_PCIHOST #ifdef CONFIG_SSB_PCIHOST
pci_iounmap(bus->host_pci, bus->mmio); pci_iounmap(bus->host_pci, bus->mmio);
#else #else
assert(0); /* Can't reach this code. */ SSB_BUG_ON(1); /* Can't reach this code. */
#endif #endif
break; break;
} }
@ -213,8 +211,8 @@ void ssb_iounmap(struct ssb_bus *bus)
bus->mapped_device = NULL; bus->mapped_device = NULL;
} }
static void __iomem * ssb_ioremap(struct ssb_bus *bus, static void __iomem *ssb_ioremap(struct ssb_bus *bus,
unsigned long baseaddr) unsigned long baseaddr)
{ {
void __iomem *mmio = NULL; void __iomem *mmio = NULL;
@ -229,7 +227,7 @@ static void __iomem * ssb_ioremap(struct ssb_bus *bus,
#ifdef CONFIG_SSB_PCIHOST #ifdef CONFIG_SSB_PCIHOST
mmio = pci_iomap(bus->host_pci, 0, ~0UL); mmio = pci_iomap(bus->host_pci, 0, ~0UL);
#else #else
assert(0); /* Can't reach this code. */ SSB_BUG_ON(1); /* Can't reach this code. */
#endif #endif
break; break;
} }

View File

@ -3,7 +3,6 @@
#include <linux/ssb/ssb.h> #include <linux/ssb/ssb.h>
#include <linux/types.h> #include <linux/types.h>
#include <asm/io.h>
#define PFX "ssb: " #define PFX "ssb: "
@ -16,32 +15,20 @@
/* dprintk: Debugging printk; vanishes for non-debug compilation */ /* dprintk: Debugging printk; vanishes for non-debug compilation */
#ifdef CONFIG_SSB_DEBUG #ifdef CONFIG_SSB_DEBUG
# define ssb_dprintk(fmt, x...) ssb_printk(fmt ,##x) # define ssb_dprintk(fmt, x...) ssb_printk(fmt , ##x)
#else #else
# define ssb_dprintk(fmt, x...) do { /* nothing */ } while (0) # define ssb_dprintk(fmt, x...) do { /* nothing */ } while (0)
#endif #endif
/* printkl: Rate limited printk */
#define ssb_printkl(fmt, x...) do { \
if (printk_ratelimit()) \
ssb_printk(fmt ,##x); \
} while (0)
/* dprintkl: Rate limited debugging printk */
#ifdef CONFIG_SSB_DEBUG #ifdef CONFIG_SSB_DEBUG
# define ssb_dprintkl ssb_printkl # define SSB_WARN_ON(x) WARN_ON(x)
# define SSB_BUG_ON(x) BUG_ON(x)
#else #else
# define ssb_dprintkl(fmt, x...) do { /* nothing */ } while (0) static inline int __ssb_do_nothing(int x) { return x; }
# define SSB_WARN_ON(x) __ssb_do_nothing(unlikely(!!(x)))
# define SSB_BUG_ON(x) __ssb_do_nothing(unlikely(!!(x)))
#endif #endif
#define assert(cond) do { \
if (unlikely(!(cond))) { \
ssb_dprintk(KERN_ERR PFX "BUG: Assertion failed (%s) " \
"at: %s:%d:%s()\n", \
#cond, __FILE__, __LINE__, __func__); \
} \
} while (0)
/* pci.c */ /* pci.c */
#ifdef CONFIG_SSB_PCIHOST #ifdef CONFIG_SSB_PCIHOST
@ -120,7 +107,7 @@ static inline int ssb_pcmcia_init(struct ssb_bus *bus)
/* scan.c */ /* scan.c */
extern const char * ssb_core_name(u16 coreid); extern const char *ssb_core_name(u16 coreid);
extern int ssb_bus_scan(struct ssb_bus *bus, extern int ssb_bus_scan(struct ssb_bus *bus,
unsigned long baseaddr); unsigned long baseaddr);
extern void ssb_iounmap(struct ssb_bus *ssb); extern void ssb_iounmap(struct ssb_bus *ssb);
@ -128,10 +115,22 @@ extern void ssb_iounmap(struct ssb_bus *ssb);
/* core.c */ /* core.c */
extern u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m); extern u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m);
#ifdef CONFIG_SSB_PCIHOST
extern int ssb_devices_freeze(struct ssb_bus *bus); extern int ssb_devices_freeze(struct ssb_bus *bus);
extern int ssb_devices_thaw(struct ssb_bus *bus); extern int ssb_devices_thaw(struct ssb_bus *bus);
extern struct ssb_bus * ssb_pci_dev_to_bus(struct pci_dev *pdev); extern struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev);
/* b43_pci_bridge.c */
#ifdef CONFIG_SSB_PCIHOST
extern int __init b43_pci_ssb_bridge_init(void);
extern void __exit b43_pci_ssb_bridge_exit(void);
#else /* CONFIG_SSB_PCIHOST */
static inline int b43_pci_ssb_bridge_init(void)
{
return 0;
}
static inline void b43_pci_ssb_bridge_exit(void)
{
}
#endif /* CONFIG_SSB_PCIHOST */ #endif /* CONFIG_SSB_PCIHOST */
#endif /* LINUX_SSB_PRIVATE_H_ */ #endif /* LINUX_SSB_PRIVATE_H_ */

View File

@ -1,14 +1,12 @@
#ifndef LINUX_SSB_H_ #ifndef LINUX_SSB_H_
#define LINUX_SSB_H_ #define LINUX_SSB_H_
#ifdef __KERNEL__
#include <linux/device.h> #include <linux/device.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#ifdef CONFIG_SSB_PCIHOST #include <linux/pci.h>
# include <linux/pci.h> #include <linux/mod_devicetable.h>
#endif
#include <linux/ssb/ssb_regs.h> #include <linux/ssb/ssb_regs.h>
@ -156,20 +154,6 @@ struct ssb_bus_ops {
/* Vendor-ID values */ /* Vendor-ID values */
#define SSB_VENDOR_BROADCOM 0x4243 #define SSB_VENDOR_BROADCOM 0x4243
struct ssb_device_id {
u16 vendor;
u16 coreid;
u8 revision;
};
#define SSB_DEVICE(_vendor, _coreid, _revision) \
{ .vendor = _vendor, .coreid = _coreid, .revision = _revision, }
#define SSB_DEVTABLE_END \
{ 0, },
#define SSB_ANY_VENDOR 0xFFFF
#define SSB_ANY_ID 0xFFFF
#define SSB_ANY_REV 0xFF
/* Some kernel subsystems poke with dev->drvdata, so we must use the /* Some kernel subsystems poke with dev->drvdata, so we must use the
* following ugly workaround to get from struct device to struct ssb_device */ * following ugly workaround to get from struct device to struct ssb_device */
struct __ssb_dev_wrapper { struct __ssb_dev_wrapper {
@ -198,7 +182,8 @@ struct ssb_device {
static inline static inline
struct ssb_device * dev_to_ssb_dev(struct device *dev) struct ssb_device * dev_to_ssb_dev(struct device *dev)
{ {
struct __ssb_dev_wrapper *wrap = container_of(dev, struct __ssb_dev_wrapper, dev); struct __ssb_dev_wrapper *wrap;
wrap = container_of(dev, struct __ssb_dev_wrapper, dev);
return wrap->sdev; return wrap->sdev;
} }
@ -296,6 +281,7 @@ struct ssb_bus {
struct pcmcia_device *host_pcmcia; struct pcmcia_device *host_pcmcia;
#ifdef CONFIG_SSB_PCIHOST #ifdef CONFIG_SSB_PCIHOST
/* Mutex to protect the SPROM writing. */
struct mutex pci_sprom_mutex; struct mutex pci_sprom_mutex;
#endif #endif
@ -333,8 +319,13 @@ struct ssb_bus {
/* Contents of the SPROM. */ /* Contents of the SPROM. */
struct ssb_sprom sprom; struct ssb_sprom sprom;
/* Internal. */ /* Internal-only stuff follows. Do not touch. */
struct list_head list; struct list_head list;
#ifdef CONFIG_SSB_DEBUG
/* Is the bus already powered up? */
bool powered_up;
int power_warn_count;
#endif /* DEBUG */
}; };
/* The initialization-invariants. */ /* The initialization-invariants. */
@ -342,6 +333,9 @@ struct ssb_init_invariants {
struct ssb_boardinfo boardinfo; struct ssb_boardinfo boardinfo;
struct ssb_sprom sprom; struct ssb_sprom sprom;
}; };
/* Type of function to fetch the invariants. */
typedef int (*ssb_invariants_func_t)(struct ssb_bus *bus,
struct ssb_init_invariants *iv);
/* Register a SSB system bus. get_invariants() is called after the /* Register a SSB system bus. get_invariants() is called after the
* basic system devices are initialized. * basic system devices are initialized.
@ -349,8 +343,7 @@ struct ssb_init_invariants {
* Put the invariants into the struct pointed to by iv. */ * Put the invariants into the struct pointed to by iv. */
extern int ssb_bus_ssbbus_register(struct ssb_bus *bus, extern int ssb_bus_ssbbus_register(struct ssb_bus *bus,
unsigned long baseaddr, unsigned long baseaddr,
int (*get_invariants)(struct ssb_bus *bus, ssb_invariants_func_t get_invariants);
struct ssb_init_invariants *iv));
#ifdef CONFIG_SSB_PCIHOST #ifdef CONFIG_SSB_PCIHOST
extern int ssb_bus_pcibus_register(struct ssb_bus *bus, extern int ssb_bus_pcibus_register(struct ssb_bus *bus,
struct pci_dev *host_pci); struct pci_dev *host_pci);
@ -365,8 +358,12 @@ extern void ssb_bus_unregister(struct ssb_bus *bus);
extern u32 ssb_clockspeed(struct ssb_bus *bus); extern u32 ssb_clockspeed(struct ssb_bus *bus);
/* Is the device enabled in hardware? */
int ssb_device_is_enabled(struct ssb_device *dev); int ssb_device_is_enabled(struct ssb_device *dev);
/* Enable a device and pass device-specific SSB_TMSLOW flags.
* If no device-specific flags are available, use 0. */
void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags); void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags);
/* Disable a device in hardware and pass SSB_TMSLOW flags (if any). */
void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags); void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags);
@ -408,9 +405,15 @@ static inline void ssb_pcihost_unregister(struct pci_driver *driver)
#endif /* CONFIG_SSB_PCIHOST */ #endif /* CONFIG_SSB_PCIHOST */
/* Bus-Power handling functions. */ /* If a driver is shutdown or suspended, call this to signal
* that the bus may be completely powered down. SSB will decide,
* if it's really time to power down the bus, based on if there
* are other devices that want to run. */
extern int ssb_bus_may_powerdown(struct ssb_bus *bus); extern int ssb_bus_may_powerdown(struct ssb_bus *bus);
extern int ssb_bus_powerup(struct ssb_bus *bus, int dynamic_pctl); /* Before initializing and enabling a device, call this to power-up the bus.
* If you want to allow use of dynamic-power-control, pass the flag.
* Otherwise static always-on powercontrol will be used. */
extern int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl);
/* Various helper functions */ /* Various helper functions */
@ -418,5 +421,4 @@ extern u32 ssb_admatch_base(u32 adm);
extern u32 ssb_admatch_size(u32 adm); extern u32 ssb_admatch_size(u32 adm);
#endif /* __KERNEL__ */
#endif /* LINUX_SSB_H_ */ #endif /* LINUX_SSB_H_ */

View File

@ -12,7 +12,6 @@
* *
* Licensed under the GPL version 2. See COPYING for details. * Licensed under the GPL version 2. See COPYING for details.
*/ */
#ifdef __KERNEL__
/** ChipCommon core registers. **/ /** ChipCommon core registers. **/
@ -364,6 +363,8 @@ extern void ssb_chipcommon_init(struct ssb_chipcommon *cc);
extern void ssb_chipco_suspend(struct ssb_chipcommon *cc, pm_message_t state); extern void ssb_chipco_suspend(struct ssb_chipcommon *cc, pm_message_t state);
extern void ssb_chipco_resume(struct ssb_chipcommon *cc); extern void ssb_chipco_resume(struct ssb_chipcommon *cc);
extern void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,
u32 *plltype, u32 *n, u32 *m);
extern void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc, extern void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc,
u32 *plltype, u32 *n, u32 *m); u32 *plltype, u32 *n, u32 *m);
extern void ssb_chipco_timing_init(struct ssb_chipcommon *cc, extern void ssb_chipco_timing_init(struct ssb_chipcommon *cc,
@ -378,10 +379,18 @@ enum ssb_clkmode {
extern void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc, extern void ssb_chipco_set_clockmode(struct ssb_chipcommon *cc,
enum ssb_clkmode mode); enum ssb_clkmode mode);
extern void ssb_chipco_watchdog_timer_set(struct ssb_chipcommon *cc,
u32 ticks);
u32 ssb_chipco_gpio_in(struct ssb_chipcommon *cc, u32 mask);
void ssb_chipco_gpio_out(struct ssb_chipcommon *cc, u32 mask, u32 value);
void ssb_chipco_gpio_outen(struct ssb_chipcommon *cc, u32 mask, u32 value);
#ifdef CONFIG_SSB_SERIAL #ifdef CONFIG_SSB_SERIAL
extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc, extern int ssb_chipco_serial_init(struct ssb_chipcommon *cc,
struct ssb_serial_port *ports); struct ssb_serial_port *ports);
#endif /* CONFIG_SSB_SERIAL */ #endif /* CONFIG_SSB_SERIAL */
#endif /* __KERNEL__ */
#endif /* LINUX_SSB_CHIPCO_H_ */ #endif /* LINUX_SSB_CHIPCO_H_ */

View File

@ -20,12 +20,6 @@
#ifndef LINUX_SSB_EXTIFCORE_H_ #ifndef LINUX_SSB_EXTIFCORE_H_
#define LINUX_SSB_EXTIFCORE_H_ #define LINUX_SSB_EXTIFCORE_H_
#ifdef __KERNEL__
struct ssb_extif {
struct ssb_device *dev;
};
/* external interface address space */ /* external interface address space */
#define SSB_EXTIF_PCMCIA_MEMBASE(x) (x) #define SSB_EXTIF_PCMCIA_MEMBASE(x) (x)
#define SSB_EXTIF_PCMCIA_IOBASE(x) ((x) + 0x100000) #define SSB_EXTIF_PCMCIA_IOBASE(x) ((x) + 0x100000)
@ -159,5 +153,52 @@ struct ssb_extif {
#define SSB_EXTIF_WATCHDOG_CLK 48000000 /* Hz */ #define SSB_EXTIF_WATCHDOG_CLK 48000000 /* Hz */
#endif /* __KERNEL__ */
#ifdef CONFIG_SSB_DRIVER_EXTIF
struct ssb_extif {
struct ssb_device *dev;
};
static inline bool ssb_extif_available(struct ssb_extif *extif)
{
return (extif->dev != NULL);
}
extern void ssb_extif_get_clockcontrol(struct ssb_extif *extif,
u32 *plltype, u32 *n, u32 *m);
extern void ssb_extif_timing_init(struct ssb_extif *extif,
unsigned long ns);
u32 ssb_extif_gpio_in(struct ssb_extif *extif, u32 mask);
void ssb_extif_gpio_out(struct ssb_extif *extif, u32 mask, u32 value);
void ssb_extif_gpio_outen(struct ssb_extif *extif, u32 mask, u32 value);
#ifdef CONFIG_SSB_SERIAL
extern int ssb_extif_serial_init(struct ssb_extif *extif,
struct ssb_serial_port *ports);
#endif /* CONFIG_SSB_SERIAL */
#else /* CONFIG_SSB_DRIVER_EXTIF */
/* extif disabled */
struct ssb_extif {
};
static inline bool ssb_extif_available(struct ssb_extif *extif)
{
return 0;
}
static inline
void ssb_extif_get_clockcontrol(struct ssb_extif *extif,
u32 *plltype, u32 *n, u32 *m)
{
}
#endif /* CONFIG_SSB_DRIVER_EXTIF */
#endif /* LINUX_SSB_EXTIFCORE_H_ */ #endif /* LINUX_SSB_EXTIFCORE_H_ */

View File

@ -1,8 +1,6 @@
#ifndef LINUX_SSB_MIPSCORE_H_ #ifndef LINUX_SSB_MIPSCORE_H_
#define LINUX_SSB_MIPSCORE_H_ #define LINUX_SSB_MIPSCORE_H_
#ifdef __KERNEL__
#ifdef CONFIG_SSB_DRIVER_MIPS #ifdef CONFIG_SSB_DRIVER_MIPS
struct ssb_device; struct ssb_device;
@ -22,11 +20,13 @@ struct ssb_mipscore {
int nr_serial_ports; int nr_serial_ports;
struct ssb_serial_port serial_ports[4]; struct ssb_serial_port serial_ports[4];
u8 flash_buswidth;
u32 flash_window; u32 flash_window;
u32 flash_window_size; u32 flash_window_size;
}; };
extern void ssb_mipscore_init(struct ssb_mipscore *mcore); extern void ssb_mipscore_init(struct ssb_mipscore *mcore);
extern u32 ssb_cpu_clock(struct ssb_mipscore *mcore);
extern unsigned int ssb_mips_irq(struct ssb_device *dev); extern unsigned int ssb_mips_irq(struct ssb_device *dev);
@ -43,5 +43,4 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore)
#endif /* CONFIG_SSB_DRIVER_MIPS */ #endif /* CONFIG_SSB_DRIVER_MIPS */
#endif /* __KERNEL__ */
#endif /* LINUX_SSB_MIPSCORE_H_ */ #endif /* LINUX_SSB_MIPSCORE_H_ */

View File

@ -1,6 +1,5 @@
#ifndef LINUX_SSB_PCICORE_H_ #ifndef LINUX_SSB_PCICORE_H_
#define LINUX_SSB_PCICORE_H_ #define LINUX_SSB_PCICORE_H_
#ifdef __KERNEL__
#ifdef CONFIG_SSB_DRIVER_PCICORE #ifdef CONFIG_SSB_DRIVER_PCICORE
@ -104,5 +103,4 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc,
} }
#endif /* CONFIG_SSB_DRIVER_PCICORE */ #endif /* CONFIG_SSB_DRIVER_PCICORE */
#endif /* __KERNEL__ */
#endif /* LINUX_SSB_PCICORE_H_ */ #endif /* LINUX_SSB_PCICORE_H_ */

View File

@ -1,31 +1,30 @@
#ifndef LINUX_SSB_REGS_H_ #ifndef LINUX_SSB_REGS_H_
#define LINUX_SSB_REGS_H_ #define LINUX_SSB_REGS_H_
#ifdef __KERNEL__
/* SiliconBackplane Address Map. /* SiliconBackplane Address Map.
* All regions may not exist on all chips. * All regions may not exist on all chips.
*/ */
#define SSB_SDRAM_BASE 0x00000000 /* Physical SDRAM */ #define SSB_SDRAM_BASE 0x00000000U /* Physical SDRAM */
#define SSB_PCI_MEM 0x08000000 /* Host Mode sb2pcitranslation0 (64 MB) */ #define SSB_PCI_MEM 0x08000000U /* Host Mode sb2pcitranslation0 (64 MB) */
#define SSB_PCI_CFG 0x0c000000 /* Host Mode sb2pcitranslation1 (64 MB) */ #define SSB_PCI_CFG 0x0c000000U /* Host Mode sb2pcitranslation1 (64 MB) */
#define SSB_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */ #define SSB_SDRAM_SWAPPED 0x10000000U /* Byteswapped Physical SDRAM */
#define SSB_ENUM_BASE 0x18000000 /* Enumeration space base */ #define SSB_ENUM_BASE 0x18000000U /* Enumeration space base */
#define SSB_ENUM_LIMIT 0x18010000 /* Enumeration space limit */ #define SSB_ENUM_LIMIT 0x18010000U /* Enumeration space limit */
#define SSB_FLASH2 0x1c000000 /* Flash Region 2 (region 1 shadowed here) */ #define SSB_FLASH2 0x1c000000U /* Flash Region 2 (region 1 shadowed here) */
#define SSB_FLASH2_SZ 0x02000000 /* Size of Flash Region 2 */ #define SSB_FLASH2_SZ 0x02000000U /* Size of Flash Region 2 */
#define SSB_EXTIF_BASE 0x1f000000 /* External Interface region base address */ #define SSB_EXTIF_BASE 0x1f000000U /* External Interface region base address */
#define SSB_FLASH1 0x1fc00000 /* Flash Region 1 */ #define SSB_FLASH1 0x1fc00000U /* Flash Region 1 */
#define SSB_FLASH1_SZ 0x00400000 /* Size of Flash Region 1 */ #define SSB_FLASH1_SZ 0x00400000U /* Size of Flash Region 1 */
#define SSB_PCI_DMA 0x40000000 /* Client Mode sb2pcitranslation2 (1 GB) */ #define SSB_PCI_DMA 0x40000000U /* Client Mode sb2pcitranslation2 (1 GB) */
#define SSB_PCI_DMA_SZ 0x40000000 /* Client Mode sb2pcitranslation2 size in bytes */ #define SSB_PCI_DMA_SZ 0x40000000U /* Client Mode sb2pcitranslation2 size in bytes */
#define SSB_PCIE_DMA_L32 0x00000000 /* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), low 32 bits */ #define SSB_PCIE_DMA_L32 0x00000000U /* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), low 32 bits */
#define SSB_PCIE_DMA_H32 0x80000000 /* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), high 32 bits */ #define SSB_PCIE_DMA_H32 0x80000000U /* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), high 32 bits */
#define SSB_EUART (SB_EXTIF_BASE + 0x00800000) #define SSB_EUART (SSB_EXTIF_BASE + 0x00800000)
#define SSB_LED (SB_EXTIF_BASE + 0x00900000) #define SSB_LED (SSB_EXTIF_BASE + 0x00900000)
/* Enumeration space constants */ /* Enumeration space constants */
@ -268,7 +267,7 @@ enum {
SSB_SPROM1CCODE_NONE, SSB_SPROM1CCODE_NONE,
}; };
/* Address-Match values and masks (SSB_ADMATCH?) */ /* Address-Match values and masks (SSB_ADMATCHxxx) */
#define SSB_ADM_TYPE 0x00000003 /* Address type */ #define SSB_ADM_TYPE 0x00000003 /* Address type */
#define SSB_ADM_TYPE0 0 #define SSB_ADM_TYPE0 0
#define SSB_ADM_TYPE1 1 #define SSB_ADM_TYPE1 1
@ -290,5 +289,4 @@ enum {
#define SSB_ADM_BASE2_SHIFT 16 #define SSB_ADM_BASE2_SHIFT 16
#endif /* __KERNEL__ */
#endif /* LINUX_SSB_REGS_H_ */ #endif /* LINUX_SSB_REGS_H_ */

View File

@ -1,78 +0,0 @@
Index: linux-2.6.22-rc4/drivers/usb/host/Kconfig
===================================================================
--- linux-2.6.22-rc4.orig/drivers/usb/host/Kconfig 2007-06-10 21:32:11.000000000 +0100
+++ linux-2.6.22-rc4/drivers/usb/host/Kconfig 2007-06-10 21:33:24.000000000 +0100
@@ -142,6 +142,19 @@
Enables support for PCI-bus plug-in USB controller cards.
If unsure, say Y.
+config USB_OHCI_HCD_SSB
+ bool "OHCI support for the Broadcom SSB OHCI core (embedded systems only)"
+ depends on USB_OHCI_HCD && ((USB_OHCI_HCD=m && SSB) || (USB_OHCI_HCD=y && SSB=y)) && EXPERIMENTAL
+ default n
+ ---help---
+ Support for the Sonics Silicon Backplane (SSB) attached
+ Broadcom USB OHCI core.
+
+ This device is only present in some embedded devices with
+ Broadcom based SSB bus.
+
+ If unsure, say N.
+
config USB_OHCI_BIG_ENDIAN_DESC
bool
depends on USB_OHCI_HCD
Index: linux-2.6.22-rc4/drivers/usb/host/ohci-hcd.c
===================================================================
--- linux-2.6.22-rc4.orig/drivers/usb/host/ohci-hcd.c 2007-06-10 21:32:11.000000000 +0100
+++ linux-2.6.22-rc4/drivers/usb/host/ohci-hcd.c 2007-06-10 21:33:24.000000000 +0100
@@ -920,11 +920,17 @@
#define PS3_SYSTEM_BUS_DRIVER ps3_ohci_sb_driver
#endif
+#ifdef CONFIG_USB_OHCI_HCD_SSB
+#include "ohci-ssb.c"
+#define SSB_OHCI_DRIVER ssb_ohci_driver
+#endif
+
#if !defined(PCI_DRIVER) && \
!defined(PLATFORM_DRIVER) && \
!defined(OF_PLATFORM_DRIVER) && \
!defined(SA1111_DRIVER) && \
- !defined(PS3_SYSTEM_BUS_DRIVER)
+ !defined(PS3_SYSTEM_BUS_DRIVER) && \
+ !defined(SSB_OHCI_DRIVER)
#error "missing bus glue for ohci-hcd"
#endif
@@ -972,10 +978,20 @@
goto error_pci;
#endif
+#ifdef SSB_OHCI_DRIVER
+ retval = ssb_driver_register(&SSB_OHCI_DRIVER);
+ if (retval)
+ goto error_ssb;
+#endif
+
return retval;
/* Error path */
+#ifdef SSB_OHCI_DRIVER
+ error_ssb:
+#endif
#ifdef PCI_DRIVER
+ pci_unregister_driver(&PCI_DRIVER);
error_pci:
#endif
#ifdef SA1111_DRIVER
@@ -1001,6 +1017,9 @@
static void __exit ohci_hcd_mod_exit(void)
{
+#ifdef SSB_OHCI_DRIVER
+ ssb_driver_unregister(&SSB_OHCI_DRIVER);
+#endif
#ifdef PCI_DRIVER
pci_unregister_driver(&PCI_DRIVER);
#endif

View File

@ -1,49 +0,0 @@
Index: linux-2.6.22-rc5/drivers/ssb/driver_pcicore.c
===================================================================
--- linux-2.6.22-rc5.orig/drivers/ssb/driver_pcicore.c 2007-06-10 16:44:31.000000000 +0100
+++ linux-2.6.22-rc5/drivers/ssb/driver_pcicore.c 2007-06-24 20:07:15.000000000 +0100
@@ -93,6 +93,9 @@
/* Enable PCI bridge BAR1 prefetch and burst */
pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3);
+
+ /* Make sure our latency is high enough to handle the devices behind us */
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xa8);
}
DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_fixup_pcibridge);
@@ -110,7 +113,7 @@
if (unlikely(pc->cardbusmode && dev > 1))
goto out;
- if (bus == 0) {
+ if (bus == 0) {//FIXME busnumber ok?
/* Type 0 transaction */
if (unlikely(dev >= SSB_PCI_SLOT_MAX))
goto out;
@@ -224,7 +227,7 @@
val = *((const u32 *)buf);
break;
}
- writel(*((const u32 *)buf), mmio);
+ writel(val, mmio);
err = 0;
unmap:
@@ -307,6 +310,8 @@
udelay(150);
val |= SSB_PCICORE_CTL_RST; /* Deassert RST# */
pcicore_write32(pc, SSB_PCICORE_CTL, val);
+ val = SSB_PCICORE_ARBCTL_INTERN;
+ pcicore_write32(pc, SSB_PCICORE_ARBCTL, val);
udelay(1);
//TODO cardbus mode
@@ -336,6 +341,7 @@
* The following needs change, if we want to port hostmode
* to non-MIPS platform. */
set_io_port_base((unsigned long)ioremap_nocache(SSB_PCI_MEM, 0x04000000));
+ mdelay(300);
register_pci_controller(&ssb_pcicore_controller);
}

View File

@ -1,78 +0,0 @@
Index: linux-2.6.23-rc6/drivers/usb/host/Kconfig
===================================================================
--- linux-2.6.23-rc6.orig/drivers/usb/host/Kconfig 2007-09-21 16:23:52.000000000 +0800
+++ linux-2.6.23-rc6/drivers/usb/host/Kconfig 2007-09-21 16:24:07.000000000 +0800
@@ -154,6 +154,19 @@
Enables support for PCI-bus plug-in USB controller cards.
If unsure, say Y.
+config USB_OHCI_HCD_SSB
+ bool "OHCI support for the Broadcom SSB OHCI core (embedded systems only)"
+ depends on USB_OHCI_HCD && ((USB_OHCI_HCD=m && SSB) || (USB_OHCI_HCD=y && SSB=y)) && EXPERIMENTAL
+ default n
+ ---help---
+ Support for the Sonics Silicon Backplane (SSB) attached
+ Broadcom USB OHCI core.
+
+ This device is only present in some embedded devices with
+ Broadcom based SSB bus.
+
+ If unsure, say N.
+
config USB_OHCI_BIG_ENDIAN_DESC
bool
depends on USB_OHCI_HCD
Index: linux-2.6.23-rc6/drivers/usb/host/ohci-hcd.c
===================================================================
--- linux-2.6.23-rc6.orig/drivers/usb/host/ohci-hcd.c 2007-09-21 16:23:52.000000000 +0800
+++ linux-2.6.23-rc6/drivers/usb/host/ohci-hcd.c 2007-09-21 16:24:07.000000000 +0800
@@ -926,11 +926,17 @@
#define PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver
#endif
+#ifdef CONFIG_USB_OHCI_HCD_SSB
+#include "ohci-ssb.c"
+#define SSB_OHCI_DRIVER ssb_ohci_driver
+#endif
+
#if !defined(PCI_DRIVER) && \
!defined(PLATFORM_DRIVER) && \
!defined(OF_PLATFORM_DRIVER) && \
!defined(SA1111_DRIVER) && \
- !defined(PS3_SYSTEM_BUS_DRIVER)
+ !defined(PS3_SYSTEM_BUS_DRIVER) && \
+ !defined(SSB_OHCI_DRIVER)
#error "missing bus glue for ohci-hcd"
#endif
@@ -975,10 +981,20 @@
goto error_pci;
#endif
+#ifdef SSB_OHCI_DRIVER
+ retval = ssb_driver_register(&SSB_OHCI_DRIVER);
+ if (retval)
+ goto error_ssb;
+#endif
+
return retval;
/* Error path */
+#ifdef SSB_OHCI_DRIVER
+ error_ssb:
+#endif
#ifdef PCI_DRIVER
+ pci_unregister_driver(&PCI_DRIVER);
error_pci:
#endif
#ifdef SA1111_DRIVER
@@ -1003,6 +1019,9 @@
static void __exit ohci_hcd_mod_exit(void)
{
+#ifdef SSB_OHCI_DRIVER
+ ssb_driver_unregister(&SSB_OHCI_DRIVER);
+#endif
#ifdef PCI_DRIVER
pci_unregister_driver(&PCI_DRIVER);
#endif

View File

@ -1,54 +0,0 @@
Index: linux-2.6.23/drivers/ssb/driver_pcicore.c
===================================================================
--- linux-2.6.23.orig/drivers/ssb/driver_pcicore.c 2007-10-13 04:20:23.235499369 +0200
+++ linux-2.6.23/drivers/ssb/driver_pcicore.c 2007-10-13 04:21:28.895241103 +0200
@@ -93,10 +93,13 @@
/* Enable PCI bridge BAR1 prefetch and burst */
pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3);
+
+ /* Make sure our latency is high enough to handle the devices behind us */
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xa8);
}
DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ssb_fixup_pcibridge);
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return ssb_mips_irq(extpci_core->dev) + 2;
}
@@ -110,7 +113,7 @@
if (unlikely(pc->cardbusmode && dev > 1))
goto out;
- if (bus == 0) {
+ if (bus == 0) {//FIXME busnumber ok?
/* Type 0 transaction */
if (unlikely(dev >= SSB_PCI_SLOT_MAX))
goto out;
@@ -224,7 +227,7 @@
val = *((const u32 *)buf);
break;
}
- writel(*((const u32 *)buf), mmio);
+ writel(val, mmio);
err = 0;
unmap:
@@ -307,6 +310,8 @@
udelay(150);
val |= SSB_PCICORE_CTL_RST; /* Deassert RST# */
pcicore_write32(pc, SSB_PCICORE_CTL, val);
+ val = SSB_PCICORE_ARBCTL_INTERN;
+ pcicore_write32(pc, SSB_PCICORE_ARBCTL, val);
udelay(1);
//TODO cardbus mode
@@ -336,6 +341,7 @@
* The following needs change, if we want to port hostmode
* to non-MIPS platform. */
set_io_port_base((unsigned long)ioremap_nocache(SSB_PCI_MEM, 0x04000000));
+ mdelay(300);
register_pci_controller(&ssb_pcicore_controller);
}