Commit c0222ac0 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus

Pull MIPS updates from Ralf Baechle:
 "This is an unusually large pull request for MIPS - in parts because
  lots of patches missed the 3.18 deadline but primarily because some
  folks opened the flood gates.

   - Retire the MIPS-specific phys_t with the generic phys_addr_t.
   - Improvments for the backtrace code used by oprofile.
   - Better backtraces on SMP systems.
   - Cleanups for the Octeon platform code.
   - Cleanups and fixes for the Loongson platform code.
   - Cleanups and fixes to the firmware library.
   - Switch ATH79 platform to use the firmware library.
   - Grand overhault to the SEAD3 and Malta interrupt code.
   - Move the GIC interrupt code to drivers/irqchip
   - Lots of GIC cleanups and updates to the GIC code to use modern IRQ
     infrastructures and features of the kernel.
   - OF documentation updates for the GIC bindings
   - Move GIC clocksource driver to drivers/clocksource
   - Merge GIC clocksource driver with clockevent driver.
   - Further updates to bring the GIC clocksource driver up to date.
   - R3000 TLB code cleanups
   - Improvments to the Loongson 3 platform code.
   - Convert pr_warning to pr_warn.
   - Merge a bunch of small lantiq and ralink fixes that have been
     staged/lingering inside the openwrt tree for a while.
   - Update archhelp for IP22/IP32
   - Fix a number of issues for Loongson 1B.
   - New clocksource and clockevent driver for Loongson 1B.
   - Further work on clk handling for Loongson 1B.
   - Platform work for Broadcom BMIPS.
   - Error handling cleanups for TurboChannel.
   - Fixes and optimization to the microMIPS support.
   - Option to disable the FTLB.
   - Dump more relevant information on machine check exception
   - Change binfmt to allow arch to examine PT_*PROC headers
   - Support for new style FPU register model in O32
   - VDSO randomization.
   - BCM47xx cleanups
   - BCM47xx reimplement the way the kernel accesses NVRAM information.
   - Random cleanups
   - Add support for ATH25 platforms
   - Remove pointless locking code in some PCI platforms.
   - Some improvments to EVA support
   - Minor Alchemy cleanup"

* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (185 commits)
  MIPS: Add MFHC0 and MTHC0 instructions to uasm.
  MIPS: Cosmetic cleanups of page table headers.
  MIPS: Add CP0 macros for extended EntryLo registers
  MIPS: Remove now unused definition of phys_t.
  MIPS: Replace use of phys_t with phys_addr_t.
  MIPS: Replace MIPS-specific 64BIT_PHYS_ADDR with generic PHYS_ADDR_T_64BIT
  PCMCIA: Alchemy Don't select 64BIT_PHYS_ADDR in Kconfig.
  MIPS: lib: memset: Clean up some MIPS{EL,EB} ifdefery
  MIPS: iomap: Use __mem_{read,write}{b,w,l} for MMIO
  MIPS: <asm/types.h> fix indentation.
  MAINTAINERS: Add entry for BMIPS multiplatform kernel
  MIPS: Enable VDSO randomization
  MIPS: Remove a temporary hack for debugging cache flushes in SMTC configuration
  MIPS: Remove declaration of obsolete arch_init_clk_ops()
  MIPS: atomic.h: Reformat to fit in 79 columns
  MIPS: Apply `.insn' to fixup labels throughout
  MIPS: Fix microMIPS LL/SC immediate offsets
  MIPS: Kconfig: Only allow 32-bit microMIPS builds
  MIPS: signal.c: Fix an invalid cast in ISA mode bit handling
  MIPS: mm: Only build one microassembler that is suitable
  ...
parents 140cd7fb e2965cd0
MIPS Global Interrupt Controller (GIC)
The MIPS GIC routes external interrupts to individual VPEs and IRQ pins.
It also supports local (per-processor) interrupts and software-generated
interrupts which can be used as IPIs. The GIC also includes a free-running
global timer, per-CPU count/compare timers, and a watchdog.
Required properties:
- compatible : Should be "mti,gic".
- interrupt-controller : Identifies the node as an interrupt controller
- #interrupt-cells : Specifies the number of cells needed to encode an
interrupt specifier. Should be 3.
- The first cell is the type of interrupt, local or shared.
See <include/dt-bindings/interrupt-controller/mips-gic.h>.
- The second cell is the GIC interrupt number.
- The third cell encodes the interrupt flags.
See <include/dt-bindings/interrupt-controller/irq.h> for a list of valid
flags.
Optional properties:
- reg : Base address and length of the GIC registers. If not present,
the base address reported by the hardware GCR_GIC_BASE will be used.
- mti,reserved-cpu-vectors : Specifies the list of CPU interrupt vectors
to which the GIC may not route interrupts. Valid values are 2 - 7.
This property is ignored if the CPU is started in EIC mode.
Required properties for timer sub-node:
- compatible : Should be "mti,gic-timer".
- interrupts : Interrupt for the GIC local timer.
- clock-frequency : Clock frequency at which the GIC timers operate.
Example:
gic: interrupt-controller@1bdc0000 {
compatible = "mti,gic";
reg = <0x1bdc0000 0x20000>;
interrupt-controller;
#interrupt-cells = <3>;
mti,reserved-cpu-vectors = <7>;
timer {
compatible = "mti,gic-timer";
interrupts = <GIC_LOCAL 1 IRQ_TYPE_NONE>;
clock-frequency = <50000000>;
};
};
uart@18101400 {
...
interrupt-parent = <&gic>;
interrupts = <GIC_SHARED 24 IRQ_TYPE_LEVEL_HIGH>;
...
};
* Interrupt Controller
Properties:
- compatible: "brcm,bcm3384-intc"
Compatibility with BCM3384 and possibly other BCM33xx/BCM63xx SoCs.
- reg: Address/length pairs for each mask/status register set. Length must
be 8. If multiple register sets are specified, the first set will
handle IRQ offsets 0..31, the second set 32..63, and so on.
- interrupt-controller: This is an interrupt controller.
- #interrupt-cells: Must be <1>. Just a simple IRQ offset; no level/edge
or polarity configuration is possible with this controller.
- interrupt-parent: This controller is cascaded from a MIPS CPU HW IRQ, or
from another INTC.
- interrupts: The IRQ on the parent controller.
Example:
periph_intc: periph_intc@14e00038 {
compatible = "brcm,bcm3384-intc";
/*
* IRQs 0..31: mask reg 0x14e00038, status reg 0x14e0003c
* IRQs 32..63: mask reg 0x14e00340, status reg 0x14e00344
*/
reg = <0x14e00038 0x8 0x14e00340 0x8>;
interrupt-controller;
#interrupt-cells = <1>;
interrupt-parent = <&cpu_intc>;
interrupts = <4>;
};
* Broadcom MIPS (BMIPS) CPUs
Required properties:
- compatible: "brcm,bmips3300", "brcm,bmips4350", "brcm,bmips4380",
"brcm,bmips5000"
- mips-hpt-frequency: This is common to all CPUs in the system so it lives
under the "cpus" node.
* Broadcom cable/DSL platforms
SoCs:
Required properties:
- compatible: "brcm,bcm3384", "brcm,bcm33843"
Boards:
Required properties:
- compatible: "brcm,bcm93384wvg"
* Broadcom USB controllers
Required properties:
- compatible: "brcm,bcm3384-ohci", "brcm,bcm3384-ehci"
These currently use the generic-ohci and generic-ehci drivers. On some
systems, special handling may be needed in the following cases:
- Restoring state after systemwide power save modes
- Sharing PHYs with the USBD (UDC) hardware
- Figuring out which controllers are disabled on ASIC bondout variants
MIPS CPU interrupt controller
On MIPS the mips_cpu_intc_init() helper can be used to initialize the 8 CPU
On MIPS the mips_cpu_irq_of_init() helper can be used to initialize the 8 CPU
IRQs from a devicetree file and create a irq_domain for IRQ controller.
With the irq_domain in place we can describe how the 8 IRQs are wired to the
......@@ -36,7 +36,7 @@ Example devicetree:
Example platform irq.c:
static struct of_device_id __initdata of_irq_ids[] = {
{ .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_intc_init },
{ .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_irq_of_init },
{ .compatible = "ralink,rt2880-intc", .data = intc_of_init },
{},
};
......
......@@ -101,6 +101,7 @@ mitsubishi Mitsubishi Electric Corporation
mosaixtech Mosaix Technologies, Inc.
moxa Moxa
mpl MPL AG
mti Imagination Technologies Ltd. (formerly MIPS Technologies Inc.)
mundoreader Mundo Reader S.L.
murata Murata Manufacturing Co., Ltd.
mxicy Macronix International Co., Ltd.
......
......@@ -2085,6 +2085,14 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/rpi/linux-rpi.git
S: Maintained
N: bcm2835
BROADCOM BCM33XX MIPS ARCHITECTURE
M: Kevin Cernekee <cernekee@gmail.com>
L: linux-mips@linux-mips.org
S: Maintained
F: arch/mips/bcm3384/*
F: arch/mips/include/asm/mach-bcm3384/*
F: arch/mips/kernel/*bmips*
BROADCOM BCM5301X ARM ARCHITECTURE
M: Hauke Mehrtens <hauke@hauke-m.de>
L: linux-arm-kernel@lists.infradead.org
......@@ -2101,6 +2109,12 @@ S: Maintained
F: arch/arm/mach-bcm/bcm63xx.c
F: arch/arm/include/debug/bcm63xx.S
BROADCOM BCM63XX/BCM33XX UDC DRIVER
M: Kevin Cernekee <cernekee@gmail.com>
L: linux-usb@vger.kernel.org
S: Maintained
F: drivers/usb/gadget/udc/bcm63xx_udc.*
BROADCOM BCM7XXX ARM ARCHITECTURE
M: Marc Carino <marc.ceeeee@gmail.com>
M: Brian Norris <computersforpeace@gmail.com>
......@@ -2112,6 +2126,18 @@ F: arch/arm/mach-bcm/*brcmstb*
F: arch/arm/boot/dts/bcm7*.dts*
F: drivers/bus/brcmstb_gisb.c
BROADCOM BMIPS MIPS ARCHITECTURE
M: Kevin Cernekee <cernekee@gmail.com>
M: Florian Fainelli <f.fainelli@gmail.com>
L: linux-mips@linux-mips.org
S: Maintained
F: arch/mips/bmips/*
F: arch/mips/include/asm/mach-bmips/*
F: arch/mips/kernel/*bmips*
F: arch/mips/boot/dts/bcm*.dts*
F: drivers/irqchip/irq-bcm7*
F: drivers/irqchip/irq-brcmstb*
BROADCOM TG3 GIGABIT ETHERNET DRIVER
M: Prashant Sreedharan <prashant@broadcom.com>
M: Michael Chan <mchan@broadcom.com>
......
......@@ -2,7 +2,9 @@
platforms += alchemy
platforms += ar7
platforms += ath25
platforms += ath79
platforms += bcm3384
platforms += bcm47xx
platforms += bcm63xx
platforms += cavium-octeon
......
......@@ -53,6 +53,7 @@ config MIPS
select HAVE_CC_STACKPROTECTOR
select CPU_PM if CPU_IDLE
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_BINFMT_ELF_STATE
menu "Machine selection"
......@@ -62,7 +63,7 @@ choice
config MIPS_ALCHEMY
bool "Alchemy processor based machines"
select 64BIT_PHYS_ADDR
select ARCH_PHYS_ADDR_T_64BIT
select CEVT_R4K
select CSRC_R4K
select IRQ_CPU
......@@ -96,6 +97,20 @@ config AR7
Support for the Texas Instruments AR7 System-on-a-Chip
family: TNETD7100, 7200 and 7300.
config ATH25
bool "Atheros AR231x/AR531x SoC support"
select CEVT_R4K
select CSRC_R4K
select DMA_NONCOHERENT
select IRQ_CPU
select IRQ_DOMAIN
select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_HAS_EARLY_PRINTK
help
Support for Atheros AR231x and Atheros AR531x based boards
config ATH79
bool "Atheros AR71XX/AR724X/AR913X based boards"
select ARCH_REQUIRE_GPIOLIB
......@@ -115,6 +130,32 @@ config ATH79
help
Support for the Atheros AR71XX/AR724X/AR913X SoCs.
config BCM3384
bool "Broadcom BCM3384 based boards"
select BOOT_RAW
select NO_EXCEPT_FILL
select USE_OF
select CEVT_R4K
select CSRC_R4K
select SYNC_R4K
select COMMON_CLK
select DMA_NONCOHERENT
select IRQ_CPU
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_HIGHMEM
select SYS_HAS_CPU_BMIPS5000
select SWAP_IO_SPACE
select USB_EHCI_BIG_ENDIAN_DESC
select USB_EHCI_BIG_ENDIAN_MMIO
select USB_OHCI_BIG_ENDIAN_DESC
select USB_OHCI_BIG_ENDIAN_MMIO
help
Support for BCM3384 based boards. BCM3384/BCM33843 is a cable modem
chipset with a Linux application processor that is often used to
provide Samba services, a CUPS print server, and/or advanced routing
features.
config BCM47XX
bool "Broadcom BCM47XX based boards"
select ARCH_WANT_OPTIONAL_GPIOLIB
......@@ -269,6 +310,8 @@ config LANTIQ
select USE_OF
select PINCTRL
select PINCTRL_LANTIQ
select ARCH_HAS_RESET_CONTROLLER
select RESET_CONTROLLER
config LASAT
bool "LASAT Networks platforms"
......@@ -315,17 +358,18 @@ config MIPS_MALTA
select BOOT_RAW
select CEVT_R4K
select CSRC_R4K
select CSRC_GIC
select CLKSRC_MIPS_GIC
select DMA_MAYBE_COHERENT
select GENERIC_ISA_DMA
select HAVE_PCSPKR_PLATFORM
select IRQ_CPU
select IRQ_GIC
select MIPS_GIC
select HW_HAS_PCI
select I8253
select I8259
select MIPS_BONITO64
select MIPS_CPU_SCACHE
select MIPS_L1_CACHE_SHIFT_6
select PCI_GT64XXX_PCI0
select MIPS_MSC
select SWAP_IO_SPACE
......@@ -340,6 +384,7 @@ config MIPS_MALTA
select SYS_SUPPORTS_64BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_MICROMIPS
select SYS_SUPPORTS_MIPS_CMP
select SYS_SUPPORTS_MIPS_CPS
select SYS_SUPPORTS_MIPS16
......@@ -357,12 +402,12 @@ config MIPS_SEAD3
select BUILTIN_DTB
select CEVT_R4K
select CSRC_R4K
select CSRC_GIC
select CLKSRC_MIPS_GIC
select CPU_MIPSR2_IRQ_VI
select CPU_MIPSR2_IRQ_EI
select DMA_NONCOHERENT
select IRQ_CPU
select IRQ_GIC
select MIPS_GIC
select LIBFDT
select MIPS_MSC
select SYS_HAS_CPU_MIPS32_R1
......@@ -726,7 +771,7 @@ config MIKROTIK_RB532
config CAVIUM_OCTEON_SOC
bool "Cavium Networks Octeon SoC based boards"
select CEVT_R4K
select 64BIT_PHYS_ADDR
select ARCH_PHYS_ADDR_T_64BIT
select DMA_COHERENT
select SYS_SUPPORTS_64BIT_KERNEL
select SYS_SUPPORTS_BIG_ENDIAN
......@@ -768,7 +813,7 @@ config NLM_XLR_BOARD
select SWAP_IO_SPACE
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL
select 64BIT_PHYS_ADDR
select ARCH_PHYS_ADDR_T_64BIT
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_HIGHMEM
select DMA_COHERENT
......@@ -794,7 +839,7 @@ config NLM_XLP_BOARD
select HW_HAS_PCI
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL
select 64BIT_PHYS_ADDR
select ARCH_PHYS_ADDR_T_64BIT
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_HIGHMEM
......@@ -835,6 +880,7 @@ config MIPS_PARAVIRT
endchoice
source "arch/mips/alchemy/Kconfig"
source "arch/mips/ath25/Kconfig"
source "arch/mips/ath79/Kconfig"
source "arch/mips/bcm47xx/Kconfig"
source "arch/mips/bcm63xx/Kconfig"
......@@ -907,10 +953,6 @@ config CEVT_GT641XX
config CEVT_R4K
bool
config CEVT_GIC
select MIPS_CM
bool
config CEVT_SB1250
bool
......@@ -926,10 +968,6 @@ config CSRC_IOASIC
config CSRC_R4K
bool
config CSRC_GIC
select MIPS_CM
bool
config CSRC_SB1250
bool
......@@ -941,7 +979,7 @@ config FW_CFE
bool
config ARCH_DMA_ADDR_T_64BIT
def_bool (HIGHMEM && 64BIT_PHYS_ADDR) || 64BIT
def_bool (HIGHMEM && ARCH_PHYS_ADDR_T_64BIT) || 64BIT
config DMA_MAYBE_COHERENT
select DMA_NONCOHERENT
......@@ -975,6 +1013,7 @@ config SYS_SUPPORTS_HOTPLUG_CPU
config I8259
bool
select IRQ_DOMAIN
config MIPS_BONITO64
bool
......@@ -1055,6 +1094,7 @@ config MIPS_HUGE_TLB_SUPPORT
config IRQ_CPU
bool
select IRQ_DOMAIN
config IRQ_CPU_RM7K
bool
......@@ -1071,10 +1111,6 @@ config IRQ_TXX9
config IRQ_GT641XX
bool
config IRQ_GIC
select MIPS_CM
bool
config PCI_GT64XXX_PCI0
bool
......@@ -1574,6 +1610,7 @@ config CPU_LOONGSON1
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM
select CPU_SUPPORTS_CPUFREQ
config CPU_BMIPS32_3300
select SMP_UP if SMP
......@@ -1586,12 +1623,14 @@ config CPU_BMIPS4350
config CPU_BMIPS4380
bool
select MIPS_L1_CACHE_SHIFT_6
select SYS_SUPPORTS_SMP
select SYS_SUPPORTS_HOTPLUG_CPU
config CPU_BMIPS5000
bool
select MIPS_CPU_SCACHE
select MIPS_L1_CACHE_SHIFT_7
select SYS_SUPPORTS_SMP
select SYS_SUPPORTS_HOTPLUG_CPU
......@@ -1886,15 +1925,6 @@ config FORCE_MAX_ZONEORDER
The page size is not necessarily 4KB. Keep this in mind
when choosing a value for this option.
config CEVT_GIC
bool "Use GIC global counter for clock events"
depends on IRQ_GIC && !MIPS_SEAD3
help
Use the GIC global counter for the clock events. The R4K clock
event driver is always present, so if the platform ends up not
detecting a GIC, it will fall back to the R4K timer for the
generation of clock events.
config BOARD_SCACHE
bool
......@@ -1908,7 +1938,6 @@ config IP22_CPU_SCACHE
config MIPS_CPU_SCACHE
bool
select BOARD_SCACHE
select MIPS_L1_CACHE_SHIFT_6
config R5000_CPU_SCACHE
bool
......@@ -2095,11 +2124,8 @@ config SB1_PASS_2_1_WORKAROUNDS
default y
config 64BIT_PHYS_ADDR
bool
config ARCH_PHYS_ADDR_T_64BIT
def_bool 64BIT_PHYS_ADDR
bool
choice
prompt "SmartMIPS or microMIPS ASE support"
......@@ -2122,7 +2148,7 @@ config CPU_HAS_SMARTMIPS
here.
config CPU_MICROMIPS
depends on SYS_SUPPORTS_MICROMIPS
depends on 32BIT && SYS_SUPPORTS_MICROMIPS
bool "microMIPS"
help
When this option is enabled the kernel will be built using the
......
......@@ -122,4 +122,17 @@ config SPINLOCK_TEST
help
Add several files to the debugfs to test spinlock speed.
config FP32XX_HYBRID_FPRS
bool "Run FP32 & FPXX code with hybrid FPRs"
depends on MIPS_O32_FP64_SUPPORT
help
The hybrid FPR scheme is normally used only when a program needs to
execute a mix of FP32 & FP64A code, since the trapping & emulation
that it entails is expensive. When enabled, this option will lead
to the kernel running programs which use the FP32 & FPXX FP ABIs
using the hybrid FPR scheme, which can be useful for debugging
purposes.
If unsure, say N.
endmenu
......@@ -380,6 +380,7 @@ define archhelp
echo ' vmlinux.ecoff - ECOFF boot image'
echo ' vmlinux.bin - Raw binary boot image'
echo ' vmlinux.srec - SREC boot image'
echo ' vmlinux.32 - 64-bit boot image wrapped in 32bits (IP22/IP32)'
echo ' vmlinuz - Compressed boot(zboot) image'
echo ' vmlinuz.ecoff - ECOFF zboot image'
echo ' vmlinuz.bin - Raw binary zboot image'
......
......@@ -37,7 +37,6 @@
#include <linux/io.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/clk-private.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/types.h>
......@@ -397,10 +396,10 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
break;
/* if this parent is currently unused, remember it.
* XXX: I know it's a layering violation, but it works
* so well.. (if (!clk_has_active_children(pc)) )
* XXX: we would actually want clk_has_active_children()
* but this is a good-enough approximation for now.
*/
if (pc->prepare_count == 0) {
if (!__clk_is_prepared(pc)) {
if (!free)
free = pc;
}
......
......@@ -70,9 +70,9 @@ void __init plat_mem_setup(void)
iomem_resource.end = IOMEM_RESOURCE_END;
}
#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_PCI)
#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_PCI)
/* This routine should be valid for all Au1x based boards */
phys_t __fixup_bigphys_addr(phys_t phys_addr, phys_t size)
phys_addr_t __fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size)
{
unsigned long start = ALCHEMY_PCI_MEMWIN_START;
unsigned long end = ALCHEMY_PCI_MEMWIN_END;
......@@ -83,7 +83,7 @@ phys_t __fixup_bigphys_addr(phys_t phys_addr, phys_t size)
/* Check for PCI memory window */
if (phys_addr >= start && (phys_addr + size - 1) <= end)
return (phys_t)(AU1500_PCI_MEM_PHYS_ADDR + phys_addr);
return (phys_addr_t)(AU1500_PCI_MEM_PHYS_ADDR + phys_addr);
/* default nop */
return phys_addr;
......
......@@ -311,8 +311,7 @@ static void __init cpmac_get_mac(int instance, unsigned char *dev_addr)
&dev_addr[0], &dev_addr[1],
&dev_addr[2], &dev_addr[3],
&dev_addr[4], &dev_addr[5]) != 6) {
pr_warning("cannot parse mac address, "
"using random address\n");
pr_warn("cannot parse mac address, using random address\n");
eth_random_addr(dev_addr);
}
} else
......@@ -665,7 +664,7 @@ static int __init ar7_register_devices(void)
res = platform_device_register(&physmap_flash);
if (res)
pr_warning("unable to register physmap-flash: %d\n", res);
pr_warn("unable to register physmap-flash: %d\n", res);
if (ar7_is_titan())
titan_fixup_devices();
......@@ -673,13 +672,13 @@ static int __init ar7_register_devices(void)
ar7_device_disable(vlynq_low_data.reset_bit);
res = platform_device_register(&vlynq_low);
if (res)
pr_warning("unable to register vlynq-low: %d\n", res);
pr_warn("unable to register vlynq-low: %d\n", res);
if (ar7_has_high_vlynq()) {
ar7_device_disable(vlynq_high_data.reset_bit);
res = platform_device_register(&vlynq_high);
if (res)
pr_warning("unable to register vlynq-high: %d\n", res);
pr_warn("unable to register vlynq-high: %d\n", res);
}
if (ar7_has_high_cpmac()) {
......@@ -689,9 +688,10 @@ static int __init ar7_register_devices(void)
res = platform_device_register(&cpmac_high);
if (res)
pr_warning("unable to register cpmac-high: %d\n", res);
pr_warn("unable to register cpmac-high: %d\n",
res);
} else
pr_warning("unable to add cpmac-high phy: %d\n", res);
pr_warn("unable to add cpmac-high phy: %d\n", res);
} else
cpmac_low_data.phy_mask = 0xffffffff;
......@@ -700,18 +700,18 @@ static int __init ar7_register_devices(void)
cpmac_get_mac(0, cpmac_low_data.dev_addr);
res = platform_device_register(&cpmac_low);
if (res)
pr_warning("unable to register cpmac-low: %d\n", res);
pr_warn("unable to register cpmac-low: %d\n", res);
} else
pr_warning("unable to add cpmac-low phy: %d\n", res);
pr_warn("unable to add cpmac-low phy: %d\n", res);
detect_leds();
res = platform_device_register(&ar7_gpio_leds);
if (res)
pr_warning("unable to register leds: %d\n", res);
pr_warn("unable to register leds: %d\n", res);
res = platform_device_register(&ar7_udc);
if (res)
pr_warning("unable to register usb slave: %d\n", res);
pr_warn("unable to register usb slave: %d\n", res);
/* Register watchdog only if enabled in hardware */
bootcr = ioremap_nocache(AR7_REGS_DCL, 4);
......@@ -726,7 +726,7 @@ static int __init ar7_register_devices(void)
ar7_wdt_res.end = ar7_wdt_res.start + 0x20;
res = platform_device_register(&ar7_wdt);
if (res)
pr_warning("unable to register watchdog: %d\n", res);
pr_warn("unable to register watchdog: %d\n", res);
}
return 0;
......
config SOC_AR5312
bool "Atheros AR5312/AR2312+ SoC support"
depends on ATH25
default y
config SOC_AR2315
bool "Atheros AR2315+ SoC support"
depends on ATH25
default y
config PCI_AR2315
bool "Atheros AR2315 PCI controller support"
depends on SOC_AR2315
select HW_HAS_PCI
select PCI
default y
#
# 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) 2006 FON Technology, SL.
# Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
# Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org>
#
obj-y += board.o prom.o devices.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_SOC_AR5312) += ar5312.o
obj-$(CONFIG_SOC_AR2315) += ar2315.o
#
# Atheros AR531X/AR231X WiSoC
#
platform-$(CONFIG_ATH25) += ath25/
cflags-$(CONFIG_ATH25) += -I$(srctree)/arch/mips/include/asm/mach-ath25
load-$(CONFIG_ATH25) += 0xffffffff80041000
/*
* 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) 2003 Atheros Communications, Inc., All Rights Reserved.
* Copyright (C) 2006 FON Technology, SL.
* Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
* Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2012 Alexandros C. Couloumbis <alex@ozo.com>
*/
/*
* Platform devices for Atheros AR2315 SoCs
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/bitops.h>
#include <linux/irqdomain.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <asm/bootinfo.h>
#include <asm/reboot.h>
#include <asm/time.h>
#include <ath25_platform.h>
#include "devices.h"
#include "ar2315.h"
#include "ar2315_regs.h"
static void __iomem *ar2315_rst_base;
static struct irq_domain *ar2315_misc_irq_domain;
static inline u32 ar2315_rst_reg_read(u32 reg)
{
return __raw_readl(ar2315_rst_base + reg);
}
static inline void ar2315_rst_reg_write(u32 reg, u32 val)
{
__raw_writel(val, ar2315_rst_base + reg);
}
static inline void ar2315_rst_reg_mask(u32 reg, u32 mask, u32 val)
{
u32 ret = ar2315_rst_reg_read(reg);
ret &= ~mask;
ret |= val;
ar2315_rst_reg_write(reg, ret);
}
static irqreturn_t ar2315_ahb_err_handler(int cpl, void *dev_id)
{
ar2315_rst_reg_write(AR2315_AHB_ERR0, AR2315_AHB_ERROR_DET);
ar2315_rst_reg_read(AR2315_AHB_ERR1);
pr_emerg("AHB fatal error\n");
machine_restart("AHB error"); /* Catastrophic failure */
return IRQ_HANDLED;
}
static struct irqaction ar2315_ahb_err_interrupt = {
.handler = ar2315_ahb_err_handler,
.name = "ar2315-ahb-error",
};
static void ar2315_misc_irq_handler(unsigned irq, struct irq_desc *desc)
{
u32 pending = ar2315_rst_reg_read(AR2315_ISR) &
ar2315_rst_reg_read(AR2315_IMR);
unsigned nr, misc_irq = 0;
if (pending) {
struct irq_domain *domain = irq_get_handler_data(irq);
nr = __ffs(pending);
misc_irq = irq_find_mapping(domain, nr);
}
if (misc_irq) {
if (nr == AR2315_MISC_IRQ_GPIO)
ar2315_rst_reg_write(AR2315_ISR, AR2315_ISR_GPIO);
else if (nr == AR2315_MISC_IRQ_WATCHDOG)
ar2315_rst_reg_write(AR2315_ISR, AR2315_ISR_WD);
generic_handle_irq(misc_irq);
} else {
spurious_interrupt();
}
}
static void ar2315_misc_irq_unmask(struct irq_data *d)
{
ar2315_rst_reg_mask(AR2315_IMR, 0, BIT(d->hwirq));
}
static void ar2315_misc_irq_mask(struct irq_data *d)
{
ar2315_rst_reg_mask(AR2315_IMR, BIT(d->hwirq), 0);
}
static struct irq_chip ar2315_misc_irq_chip = {
.name = "ar2315-misc",
.irq_unmask = ar2315_misc_irq_unmask,
.irq_mask = ar2315_misc_irq_mask,
};
static int ar2315_misc_irq_map(struct irq_domain *d, unsigned irq,
irq_hw_number_t hw)
{
irq_set_chip_and_handler(irq, &ar2315_misc_irq_chip, handle_level_irq);
return 0;
}
static struct irq_domain_ops ar2315_misc_irq_domain_ops = {
.map = ar2315_misc_irq_map,
};
/*
* Called when an interrupt is received, this function
* determines exactly which interrupt it was, and it
* invokes the appropriate handler.
*
* Implicitly, we also define interrupt priority by
* choosing which to dispatch first.
*/
static void ar2315_irq_dispatch(void)
{
u32 pending = read_c0_status() & read_c0_cause();
if (pending & CAUSEF_IP3)
do_IRQ(AR2315_IRQ_WLAN0);
#ifdef CONFIG_PCI_AR2315
else if (pending & CAUSEF_IP5)
do_IRQ(AR2315_IRQ_LCBUS_PCI);
#endif
else if (pending & CAUSEF_IP2)
do_IRQ(AR2315_IRQ_MISC);
else if (pending & CAUSEF_IP7)
do_IRQ(ATH25_IRQ_CPU_CLOCK);
else
spurious_interrupt();
}
void __init ar2315_arch_init_irq(void)
{
struct irq_domain *domain;
unsigned irq;
ath25_irq_dispatch = ar2315_irq_dispatch;
domain = irq_domain_add_linear(NULL, AR2315_MISC_IRQ_COUNT,
&ar2315_misc_irq_domain_ops, NULL);
if (!domain)
panic("Failed to add IRQ domain");
irq = irq_create_mapping(domain, AR2315_MISC_IRQ_AHB);
setup_irq(irq, &ar2315_ahb_err_interrupt);
irq_set_chained_handler(AR2315_IRQ_MISC, ar2315_misc_irq_handler);
irq_set_handler_data(AR2315_IRQ_MISC, domain);
ar2315_misc_irq_domain = domain;
}
void __init ar2315_init_devices(void)
{
/* Find board configuration */
ath25_find_config(AR2315_SPI_READ_BASE, AR2315_SPI_READ_SIZE);
ath25_add_wmac(0, AR2315_WLAN0_BASE, AR2315_IRQ_WLAN0);
}
static void ar2315_restart(char *command)
{
void (*mips_reset_vec)(void) = (void *)0xbfc00000;
local_irq_disable();
/* try reset the system via reset control */
ar2315_rst_reg_write(AR2315_COLD_RESET, AR2317_RESET_SYSTEM);
/* Cold reset does not work on the AR2315/6, use the GPIO reset bits
* a workaround. Give it some time to attempt a gpio based hardware
* reset (atheros reference design workaround) */
/* TODO: implement the GPIO reset workaround */
/* Some boards (e.g. Senao EOC-2610) don't implement the reset logic
* workaround. Attempt to jump to the mips reset location -
* the boot loader itself might be able to recover the system */
mips_reset_vec();
}
/*
* This table is indexed by bits 5..4 of the CLOCKCTL1 register
* to determine the predevisor value.
*/
static int clockctl1_predivide_table[4] __initdata = { 1, 2, 4, 5 };
static int pllc_divide_table[5] __initdata = { 2, 3, 4, 6, 3 };
static unsigned __init ar2315_sys_clk(u32 clock_ctl)
{
unsigned int pllc_ctrl, cpu_div;
unsigned int pllc_out, refdiv, fdiv, divby2;
unsigned int clk_div;
pllc_ctrl = ar2315_rst_reg_read(AR2315_PLLC_CTL);
refdiv = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_REF_DIV);
refdiv = clockctl1_predivide_table[refdiv];
fdiv = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_FDBACK_DIV);
divby2 = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_ADD_FDBACK_DIV) + 1;
pllc_out = (40000000 / refdiv) * (2 * divby2) * fdiv;
/* clkm input selected */
switch (clock_ctl & AR2315_CPUCLK_CLK_SEL_M) {
case 0:
case 1:
clk_div = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_CLKM_DIV);
clk_div = pllc_divide_table[clk_div];
break;
case 2:
clk_div = ATH25_REG_MS(pllc_ctrl, AR2315_PLLC_CLKC_DIV);
clk_div = pllc_divide_table[clk_div];
break;
default:
pllc_out = 40000000;
clk_div = 1;
break;
}
cpu_div = ATH25_REG_MS(clock_ctl, AR2315_CPUCLK_CLK_DIV);
cpu_div = cpu_div * 2 ?: 1;
return pllc_out / (clk_div * cpu_div);
}
static inline unsigned ar2315_cpu_frequency(void)
{
return ar2315_sys_clk(ar2315_rst_reg_read(AR2315_CPUCLK));
}
static inline unsigned ar2315_apb_frequency(void)
{
return ar2315_sys_clk(ar2315_rst_reg_read(AR2315_AMBACLK));
}
void __init ar2315_plat_time_init(void)
{
mips_hpt_frequency = ar2315_cpu_frequency() / 2;
}
void __init ar2315_plat_mem_setup(void)
{
void __iomem *sdram_base;
u32 memsize, memcfg;
u32 devid;
u32 config;
/* Detect memory size */
sdram_base = ioremap_nocache(AR2315_SDRAMCTL_BASE,
AR2315_SDRAMCTL_SIZE);
memcfg = __raw_readl(sdram_base + AR2315_MEM_CFG);
memsize = 1 + ATH25_REG_MS(memcfg, AR2315_MEM_CFG_DATA_WIDTH);
memsize <<= 1 + ATH25_REG_MS(memcfg, AR2315_MEM_CFG_COL_WIDTH);
memsize <<= 1 + ATH25_REG_MS(memcfg, AR2315_MEM_CFG_ROW_WIDTH);
memsize <<= 3;
add_memory_region(0, memsize, BOOT_MEM_RAM);
iounmap(sdram_base);
ar2315_rst_base = ioremap_nocache(AR2315_RST_BASE, AR2315_RST_SIZE);
/* Detect the hardware based on the device ID */
devid = ar2315_rst_reg_read(AR2315_SREV) & AR2315_REV_CHIP;
switch (devid) {
case 0x91: /* Need to check */
ath25_soc = ATH25_SOC_AR2318;
break;
case 0x90:
ath25_soc = ATH25_SOC_AR2317;
break;
case 0x87:
ath25_soc = ATH25_SOC_AR2316;
break;
case 0x86:
default:
ath25_soc = ATH25_SOC_AR2315;
break;
}
ath25_board.devid = devid;
/* Clear any lingering AHB errors */
config = read_c0_config();
write_c0_config(config & ~0x3);
ar2315_rst_reg_write(AR2315_AHB_ERR0, AR2315_AHB_ERROR_DET);
ar2315_rst_reg_read(AR2315_AHB_ERR1);
ar2315_rst_reg_write(AR2315_WDT_CTRL, AR2315_WDT_CTRL_IGNORE);
_machine_restart = ar2315_restart;
}
#ifdef CONFIG_PCI_AR2315
static struct resource ar2315_pci_res[] = {
{
.name = "ar2315-pci-ctrl",
.flags = IORESOURCE_MEM,
.start = AR2315_PCI_BASE,
.end = AR2315_PCI_BASE + AR2315_PCI_SIZE - 1,
},
{
.name = "ar2315-pci-ext",
.flags = IORESOURCE_MEM,
.start = AR2315_PCI_EXT_BASE,
.end = AR2315_PCI_EXT_BASE + AR2315_PCI_EXT_SIZE - 1,
},
{
.name = "ar2315-pci",
.flags = IORESOURCE_IRQ,
.start = AR2315_IRQ_LCBUS_PCI,
.end = AR2315_IRQ_LCBUS_PCI,
},
};
#endif
void __init ar2315_arch_init(void)
{
unsigned irq = irq_create_mapping(ar2315_misc_irq_domain,
AR2315_MISC_IRQ_UART0);
ath25_serial_setup(AR2315_UART0_BASE, irq, ar2315_apb_frequency());
#ifdef CONFIG_PCI_AR2315
if (ath25_soc == ATH25_SOC_AR2315) {
/* Reset PCI DMA logic */
ar2315_rst_reg_mask(AR2315_RESET, 0, AR2315_RESET_PCIDMA);
msleep(20);
ar2315_rst_reg_mask(AR2315_RESET, AR2315_RESET_PCIDMA, 0);
msleep(20);
/* Configure endians */
ar2315_rst_reg_mask(AR2315_ENDIAN_CTL, 0, AR2315_CONFIG_PCIAHB |
AR2315_CONFIG_PCIAHB_BRIDGE);
/* Configure as PCI host with DMA */
ar2315_rst_reg_write(AR2315_PCICLK, AR2315_PCICLK_PLLC_CLKM |
(AR2315_PCICLK_IN_FREQ_DIV_6 <<
AR2315_PCICLK_DIV_S));
ar2315_rst_reg_mask(AR2315_AHB_ARB_CTL, 0, AR2315_ARB_PCI);
ar2315_rst_reg_mask(AR2315_IF_CTL, AR2315_IF_PCI_CLK_MASK |
AR2315_IF_MASK, AR2315_IF_PCI |
AR2315_IF_PCI_HOST | AR2315_IF_PCI_INTR |
(AR2315_IF_PCI_CLK_OUTPUT_CLK <<
AR2315_IF_PCI_CLK_SHIFT));
platform_device_register_simple("ar2315-pci", -1,
ar2315_pci_res,
ARRAY_SIZE(ar2315_pci_res));
}
#endif
}
#ifndef __AR2315_H
#define __AR2315_H
#ifdef CONFIG_SOC_AR2315
void ar2315_arch_init_irq(void);
void ar2315_init_devices(void);
void ar2315_plat_time_init(void);
void ar2315_plat_mem_setup(void);
void ar2315_arch_init(void);
#else
static inline void ar2315_arch_init_irq(void) {}
static inline void ar2315_init_devices(void) {}
static inline void ar2315_plat_time_init(void) {}
static inline void ar2315_plat_mem_setup(void) {}
static inline void ar2315_arch_init(void) {}
#endif
#endif /* __AR2315_H */
This diff is collapsed.
This diff is collapsed.
#ifndef __AR5312_H
#define __AR5312_H
#ifdef CONFIG_SOC_AR5312
void ar5312_arch_init_irq(void);
void ar5312_init_devices(void);
void ar5312_plat_time_init(void);
void ar5312_plat_mem_setup(void);
void ar5312_arch_init(void);
#else
static inline void ar5312_arch_init_irq(void) {}
static inline void ar5312_init_devices(void) {}
static inline void ar5312_plat_time_init(void) {}
static inline void ar5312_plat_mem_setup(void) {}
static inline void ar5312_arch_init(void) {}
#endif
#endif /* __AR5312_H */
/*
* 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) 2003 Atheros Communications, Inc., All Rights Reserved.
* Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
* Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
*/
#ifndef __ASM_MACH_ATH25_AR5312_REGS_H
#define __ASM_MACH_ATH25_AR5312_REGS_H
/*
* IRQs
*/
#define AR5312_IRQ_WLAN0 (MIPS_CPU_IRQ_BASE + 2) /* C0_CAUSE: 0x0400 */
#define AR5312_IRQ_ENET0 (MIPS_CPU_IRQ_BASE + 3) /* C0_CAUSE: 0x0800 */
#define AR5312_IRQ_ENET1 (MIPS_CPU_IRQ_BASE + 4) /* C0_CAUSE: 0x1000 */
#define AR5312_IRQ_WLAN1 (MIPS_CPU_IRQ_BASE + 5) /* C0_CAUSE: 0x2000 */
#define AR5312_IRQ_MISC (MIPS_CPU_IRQ_BASE + 6) /* C0_CAUSE: 0x4000 */
/*
* Miscellaneous interrupts, which share IP6.
*/
#define AR5312_MISC_IRQ_TIMER 0
#define AR5312_MISC_IRQ_AHB_PROC 1
#define AR5312_MISC_IRQ_AHB_DMA 2
#define AR5312_MISC_IRQ_GPIO 3
#define AR5312_MISC_IRQ_UART0 4
#define AR5312_MISC_IRQ_UART0_DMA 5
#define AR5312_MISC_IRQ_WATCHDOG 6
#define AR5312_MISC_IRQ_LOCAL 7
#define AR5312_MISC_IRQ_SPI 8
#define AR5312_MISC_IRQ_COUNT 9
/*
* Address Map
*
* The AR5312 supports 2 enet MACS, even though many reference boards only
* actually use 1 of them (i.e. Only MAC 0 is actually connected to an enet
* PHY or PHY switch. The AR2312 supports 1 enet MAC.
*/
#define AR5312_WLAN0_BASE 0x18000000
#define AR5312_ENET0_BASE 0x18100000
#define AR5312_ENET1_BASE 0x18200000
#define AR5312_SDRAMCTL_BASE 0x18300000
#define AR5312_SDRAMCTL_SIZE 0x00000010
#define AR5312_FLASHCTL_BASE 0x18400000
#define AR5312_FLASHCTL_SIZE 0x00000010
#define AR5312_WLAN1_BASE 0x18500000
#define AR5312_UART0_BASE 0x1c000000 /* UART MMR */
#define AR5312_GPIO_BASE 0x1c002000
#define AR5312_GPIO_SIZE 0x00000010
#define AR5312_RST_BASE 0x1c003000
#define AR5312_RST_SIZE 0x00000100
#define AR5312_FLASH_BASE 0x1e000000
#define AR5312_FLASH_SIZE 0x00800000
/*
* Need these defines to determine true number of ethernet MACs
*/
#define AR5312_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */
#define AR5312_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */
#define AR5312_AR2313_REV8 0x0058 /* AR2313 WMAC (AP43-030) */
/* Reset/Timer Block Address Map */
#define AR5312_TIMER 0x0000 /* countdown timer */
#define AR5312_RELOAD 0x0004 /* timer reload value */
#define AR5312_WDT_CTRL 0x0008 /* watchdog cntrl */
#define AR5312_WDT_TIMER 0x000c /* watchdog timer */
#define AR5312_ISR 0x0010 /* Intr Status Reg */
#define AR5312_IMR 0x0014 /* Intr Mask Reg */
#define AR5312_RESET 0x0020
#define AR5312_CLOCKCTL1 0x0064
#define AR5312_SCRATCH 0x006c
#define AR5312_PROCADDR 0x0070
#define AR5312_PROC1 0x0074
#define AR5312_DMAADDR 0x0078
#define AR5312_DMA1 0x007c
#define AR5312_ENABLE 0x0080 /* interface enb */
#define AR5312_REV 0x0090 /* revision */
/* AR5312_WDT_CTRL register bit field definitions */
#define AR5312_WDT_CTRL_IGNORE 0x00000000 /* ignore expiration */
#define AR5312_WDT_CTRL_NMI 0x00000001
#define AR5312_WDT_CTRL_RESET 0x00000002
/* AR5312_ISR register bit field definitions */
#define AR5312_ISR_TIMER 0x00000001
#define AR5312_ISR_AHBPROC 0x00000002
#define AR5312_ISR_AHBDMA 0x00000004
#define AR5312_ISR_GPIO 0x00000008
#define AR5312_ISR_UART0 0x00000010
#define AR5312_ISR_UART0DMA 0x00000020
#define AR5312_ISR_WD 0x00000040
#define AR5312_ISR_LOCAL 0x00000080
/* AR5312_RESET register bit field definitions */
#define AR5312_RESET_SYSTEM 0x00000001 /* cold reset full system */
#define AR5312_RESET_PROC 0x00000002 /* cold reset MIPS core */
#define AR5312_RESET_WLAN0 0x00000004 /* cold reset WLAN MAC/BB */
#define AR5312_RESET_EPHY0 0x00000008 /* cold reset ENET0 phy */
#define AR5312_RESET_EPHY1 0x00000010 /* cold reset ENET1 phy */
#define AR5312_RESET_ENET0 0x00000020 /* cold reset ENET0 MAC */
#define AR5312_RESET_ENET1 0x00000040 /* cold reset ENET1 MAC */
#define AR5312_RESET_UART0 0x00000100 /* cold reset UART0 */
#define AR5312_RESET_WLAN1 0x00000200 /* cold reset WLAN MAC/BB */
#define AR5312_RESET_APB 0x00000400 /* cold reset APB ar5312 */
#define AR5312_RESET_WARM_PROC 0x00001000 /* warm reset MIPS core */
#define AR5312_RESET_WARM_WLAN0_MAC 0x00002000 /* warm reset WLAN0 MAC */
#define AR5312_RESET_WARM_WLAN0_BB 0x00004000 /* warm reset WLAN0 BB */
#define AR5312_RESET_NMI 0x00010000 /* send an NMI to the CPU */
#define AR5312_RESET_WARM_WLAN1_MAC 0x00020000 /* warm reset WLAN1 MAC */
#define AR5312_RESET_WARM_WLAN1_BB 0x00040000 /* warm reset WLAN1 BB */
#define AR5312_RESET_LOCAL_BUS 0x00080000 /* reset local bus */
#define AR5312_RESET_WDOG 0x00100000 /* last reset was a wdt */
#define AR5312_RESET_WMAC0_BITS (AR5312_RESET_WLAN0 |\
AR5312_RESET_WARM_WLAN0_MAC |\
AR5312_RESET_WARM_WLAN0_BB)
#define AR5312_RESET_WMAC1_BITS (AR5312_RESET_WLAN1 |\
AR5312_RESET_WARM_WLAN1_MAC |\
AR5312_RESET_WARM_WLAN1_BB)
/* AR5312_CLOCKCTL1 register bit field definitions */
#define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030
#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4
#define AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00
#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8
#define AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000
/* Valid for AR5312 and AR2312 */
#define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030
#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4
#define AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00
#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8
#define AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000
/* Valid for AR2313 */
#define AR2313_CLOCKCTL1_PREDIVIDE_MASK 0x00003000
#define AR2313_CLOCKCTL1_PREDIVIDE_SHIFT 12
#define AR2313_CLOCKCTL1_MULTIPLIER_MASK 0x001f0000
#define AR2313_CLOCKCTL1_MULTIPLIER_SHIFT 16
#define AR2313_CLOCKCTL1_DOUBLER_MASK 0x00000000
/* AR5312_ENABLE register bit field definitions */
#define AR5312_ENABLE_WLAN0 0x00000001
#define AR5312_ENABLE_ENET0 0x00000002
#define AR5312_ENABLE_ENET1 0x00000004
#define AR5312_ENABLE_UART_AND_WLAN1_PIO 0x00000008/* UART & WLAN1 PIO */
#define AR5312_ENABLE_WLAN1_DMA 0x00000010/* WLAN1 DMAs */
#define AR5312_ENABLE_WLAN1 (AR5312_ENABLE_UART_AND_WLAN1_PIO |\
AR5312_ENABLE_WLAN1_DMA)
/* AR5312_REV register bit field definitions */
#define AR5312_REV_WMAC_MAJ 0x0000f000
#define AR5312_REV_WMAC_MAJ_S 12
#define AR5312_REV_WMAC_MIN 0x00000f00
#define AR5312_REV_WMAC_MIN_S 8
#define AR5312_REV_MAJ 0x000000f0
#define AR5312_REV_MAJ_S 4
#define AR5312_REV_MIN 0x0000000f
#define AR5312_REV_MIN_S 0
#define AR5312_REV_CHIP (AR5312_REV_MAJ|AR5312_REV_MIN)
/* Major revision numbers, bits 7..4 of Revision ID register */
#define AR5312_REV_MAJ_AR5312 0x4
#define AR5312_REV_MAJ_AR2313 0x5
/* Minor revision numbers, bits 3..0 of Revision ID register */
#define AR5312_REV_MIN_DUAL 0x0 /* Dual WLAN version */
#define AR5312_REV_MIN_SINGLE 0x1 /* Single WLAN version */
/*
* ARM Flash Controller -- 3 flash banks with either x8 or x16 devices
*/
#define AR5312_FLASHCTL0 0x0000
#define AR5312_FLASHCTL1 0x0004
#define AR5312_FLASHCTL2 0x0008
/* AR5312_FLASHCTL register bit field definitions */
#define AR5312_FLASHCTL_IDCY 0x0000000f /* Idle cycle turnaround time */
#define AR5312_FLASHCTL_IDCY_S 0
#define AR5312_FLASHCTL_WST1 0x000003e0 /* Wait state 1 */
#define AR5312_FLASHCTL_WST1_S 5
#define AR5312_FLASHCTL_RBLE 0x00000400 /* Read byte lane enable */
#define AR5312_FLASHCTL_WST2 0x0000f800 /* Wait state 2 */
#define AR5312_FLASHCTL_WST2_S 11
#define AR5312_FLASHCTL_AC 0x00070000 /* Flash addr check (added) */
#define AR5312_FLASHCTL_AC_S 16
#define AR5312_FLASHCTL_AC_128K 0x00000000
#define AR5312_FLASHCTL_AC_256K 0x00010000
#define AR5312_FLASHCTL_AC_512K 0x00020000
#define AR5312_FLASHCTL_AC_1M 0x00030000
#define AR5312_FLASHCTL_AC_2M 0x00040000
#define AR5312_FLASHCTL_AC_4M 0x00050000
#define AR5312_FLASHCTL_AC_8M 0x00060000
#define AR5312_FLASHCTL_AC_RES 0x00070000 /* 16MB is not supported */
#define AR5312_FLASHCTL_E 0x00080000 /* Flash bank enable (added) */
#define AR5312_FLASHCTL_BUSERR 0x01000000 /* Bus transfer error flag */
#define AR5312_FLASHCTL_WPERR 0x02000000 /* Write protect error flag */
#define AR5312_FLASHCTL_WP 0x04000000 /* Write protect */
#define AR5312_FLASHCTL_BM 0x08000000 /* Burst mode */
#define AR5312_FLASHCTL_MW 0x30000000 /* Mem width */
#define AR5312_FLASHCTL_MW8 0x00000000 /* Mem width x8 */
#define AR5312_FLASHCTL_MW16 0x10000000 /* Mem width x16 */
#define AR5312_FLASHCTL_MW32 0x20000000 /* Mem width x32 (not supp) */
#define AR5312_FLASHCTL_ATNR 0x00000000 /* Access == no retry */
#define AR5312_FLASHCTL_ATR 0x80000000 /* Access == retry every */
#define AR5312_FLASHCTL_ATR4 0xc0000000 /* Access == retry every 4 */
/*
* ARM SDRAM Controller -- just enough to determine memory size
*/
#define AR5312_MEM_CFG1 0x0004
#define AR5312_MEM_CFG1_AC0_M 0x00000700 /* bank 0: SDRAM addr check */
#define AR5312_MEM_CFG1_AC0_S 8
#define AR5312_MEM_CFG1_AC1_M 0x00007000 /* bank 1: SDRAM addr check */
#define AR5312_MEM_CFG1_AC1_S 12
#endif /* __ASM_MACH_ATH25_AR5312_REGS_H */
/*
* 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) 2003 Atheros Communications, Inc., All Rights Reserved.
* Copyright (C) 2006 FON Technology, SL.
* Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
* Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org>
*/
#include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/irq_cpu.h>
#include <asm/reboot.h>
#include <asm/bootinfo.h>
#include <asm/time.h>
#include <ath25_platform.h>
#include "devices.h"
#include "ar5312.h"
#include "ar2315.h"
void (*ath25_irq_dispatch)(void);
static inline bool check_radio_magic(const void __iomem *addr)
{
addr += 0x7a; /* offset for flash magic */
return (__raw_readb(addr) == 0x5a) && (__raw_readb(addr + 1) == 0xa5);
}
static inline bool check_notempty(const void __iomem *addr)
{
return __raw_readl(addr) != 0xffffffff;
}
static inline bool check_board_data(const void __iomem *addr, bool broken)
{
/* config magic found */
if (__raw_readl(addr) == ATH25_BD_MAGIC)
return true;
if (!broken)
return false;
/* broken board data detected, use radio data to find the
* offset, user will fix this */
if (check_radio_magic(addr + 0x1000))
return true;
if (check_radio_magic(addr + 0xf8))
return true;
return false;
}
static const void __iomem * __init find_board_config(const void __iomem *limit,
const bool broken)
{
const void __iomem *addr;
const void __iomem *begin = limit - 0x1000;
const void __iomem *end = limit - 0x30000;
for (addr = begin; addr >= end; addr -= 0x1000)
if (check_board_data(addr, broken))
return addr;
return NULL;
}
static const void __iomem * __init find_radio_config(const void __iomem *limit,
const void __iomem *bcfg)
{
const void __iomem *rcfg, *begin, *end;
/*
* Now find the start of Radio Configuration data, using heuristics:
* Search forward from Board Configuration data by 0x1000 bytes
* at a time until we find non-0xffffffff.
*/
begin = bcfg + 0x1000;
end = limit;
for (rcfg = begin; rcfg < end; rcfg += 0x1000)
if (check_notempty(rcfg) && check_radio_magic(rcfg))
return rcfg;
/* AR2316 relocates radio config to new location */
begin = bcfg + 0xf8;
end = limit - 0x1000 + 0xf8;
for (rcfg = begin; rcfg < end; rcfg += 0x1000)
if (check_notempty(rcfg) && check_radio_magic(rcfg))
return rcfg;
return NULL;
}
/*
* NB: Search region size could be larger than the actual flash size,
* but this shouldn't be a problem here, because the flash
* will simply be mapped multiple times.
*/
int __init ath25_find_config(phys_addr_t base, unsigned long size)
{
const void __iomem *flash_base, *flash_limit;
struct ath25_boarddata *config;
unsigned int rcfg_size;
int broken_boarddata = 0;
const void __iomem *bcfg, *rcfg;
u8 *board_data;
u8 *radio_data;
u8 *mac_addr;
u32 offset;
flash_base = ioremap_nocache(base, size);
flash_limit = flash_base + size;
ath25_board.config = NULL;
ath25_board.radio = NULL;
/* Copy the board and radio data to RAM, because accessing the mapped
* memory of the flash directly after booting is not safe */
/* Try to find valid board and radio data */
bcfg = find_board_config(flash_limit, false);
/* If that fails, try to at least find valid radio data */
if (!bcfg) {
bcfg = find_board_config(flash_limit, true);
broken_boarddata = 1;
}
if (!bcfg) {
pr_warn("WARNING: No board configuration data found!\n");
goto error;
}
board_data = kzalloc(BOARD_CONFIG_BUFSZ, GFP_KERNEL);
ath25_board.config = (struct ath25_boarddata *)board_data;
memcpy_fromio(board_data, bcfg, 0x100);
if (broken_boarddata) {
pr_warn("WARNING: broken board data detected\n");
config = ath25_board.config;
if (is_zero_ether_addr(config->enet0_mac)) {
pr_info("Fixing up empty mac addresses\n");
config->reset_config_gpio = 0xffff;
config->sys_led_gpio = 0xffff;
random_ether_addr(config->wlan0_mac);
config->wlan0_mac[0] &= ~0x06;
random_ether_addr(config->enet0_mac);
random_ether_addr(config->enet1_mac);
}
}
/* Radio config starts 0x100 bytes after board config, regardless
* of what the physical layout on the flash chip looks like */
rcfg = find_radio_config(flash_limit, bcfg);
if (!rcfg) {
pr_warn("WARNING: Could not find Radio Configuration data\n");
goto error;
}
radio_data = board_data + 0x100 + ((rcfg - bcfg) & 0xfff);
ath25_board.radio = radio_data;
offset = radio_data - board_data;
pr_info("Radio config found at offset 0x%x (0x%x)\n", rcfg - bcfg,
offset);
rcfg_size = BOARD_CONFIG_BUFSZ - offset;
memcpy_fromio(radio_data, rcfg, rcfg_size);
mac_addr = &radio_data[0x1d * 2];
if (is_broadcast_ether_addr(mac_addr)) {
pr_info("Radio MAC is blank; using board-data\n");
ether_addr_copy(mac_addr, ath25_board.config->wlan0_mac);
}
iounmap(flash_base);
return 0;
error:
iounmap(flash_base);
return -ENODEV;
}
static void ath25_halt(void)
{
local_irq_disable();
unreachable();
}
void __init plat_mem_setup(void)
{
_machine_halt = ath25_halt;
pm_power_off = ath25_halt;
if (is_ar5312())
ar5312_plat_mem_setup();
else
ar2315_plat_mem_setup();
/* Disable data watchpoints */
write_c0_watchlo0(0);
}
asmlinkage void plat_irq_dispatch(void)
{
ath25_irq_dispatch();
}
void __init plat_time_init(void)
{
if (is_ar5312())
ar5312_plat_time_init();
else
ar2315_plat_time_init();
}
unsigned int __cpuinit get_c0_compare_int(void)
{
return CP0_LEGACY_COMPARE_IRQ;
}
void __init arch_init_irq(void)
{
clear_c0_status(ST0_IM);
mips_cpu_irq_init();
/* Initialize interrupt controllers */
if (is_ar5312())
ar5312_arch_init_irq();
else
ar2315_arch_init_irq();
}
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/serial_8250.h>
#include <linux/platform_device.h>
#include <asm/bootinfo.h>
#include <ath25_platform.h>
#include "devices.h"
#include "ar5312.h"
#include "ar2315.h"
struct ar231x_board_config ath25_board;
enum ath25_soc_type ath25_soc = ATH25_SOC_UNKNOWN;
static struct resource ath25_wmac0_res[] = {
{
.name = "wmac0_membase",
.flags = IORESOURCE_MEM,
},
{
.name = "wmac0_irq",
.flags = IORESOURCE_IRQ,
}
};
static struct resource ath25_wmac1_res[] = {
{
.name = "wmac1_membase",
.flags = IORESOURCE_MEM,
},
{
.name = "wmac1_irq",
.flags = IORESOURCE_IRQ,
}
};
static struct platform_device ath25_wmac[] = {
{
.id = 0,
.name = "ar231x-wmac",
.resource = ath25_wmac0_res,
.num_resources = ARRAY_SIZE(ath25_wmac0_res),
.dev.platform_data = &ath25_board,
},
{
.id = 1,
.name = "ar231x-wmac",
.resource = ath25_wmac1_res,
.num_resources = ARRAY_SIZE(ath25_wmac1_res),
.dev.platform_data = &ath25_board,
},
};
static const char * const soc_type_strings[] = {
[ATH25_SOC_AR5312] = "Atheros AR5312",
[ATH25_SOC_AR2312] = "Atheros AR2312",
[ATH25_SOC_AR2313] = "Atheros AR2313",
[ATH25_SOC_AR2315] = "Atheros AR2315",
[ATH25_SOC_AR2316] = "Atheros AR2316",
[ATH25_SOC_AR2317] = "Atheros AR2317",
[ATH25_SOC_AR2318] = "Atheros AR2318",
[ATH25_SOC_UNKNOWN] = "Atheros (unknown)",
};
const char *get_system_type(void)
{
if ((ath25_soc >= ARRAY_SIZE(soc_type_strings)) ||
!soc_type_strings[ath25_soc])
return soc_type_strings[ATH25_SOC_UNKNOWN];
return soc_type_strings[ath25_soc];
}
void __init ath25_serial_setup(u32 mapbase, int irq, unsigned int uartclk)
{
struct uart_port s;
memset(&s, 0, sizeof(s));
s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP;
s.iotype = UPIO_MEM32;
s.irq = irq;
s.regshift = 2;
s.mapbase = mapbase;
s.uartclk = uartclk;
early_serial_setup(&s);
}
int __init ath25_add_wmac(int nr, u32 base, int irq)
{
struct resource *res;
ath25_wmac[nr].dev.platform_data = &ath25_board;
res = &ath25_wmac[nr].resource[0];
res->start = base;
res->end = base + 0x10000 - 1;
res++;
res->start = irq;
res->end = irq;
return platform_device_register(&ath25_wmac[nr]);
}
static int __init ath25_register_devices(void)
{
if (is_ar5312())
ar5312_init_devices();
else
ar2315_init_devices();
return 0;
}
device_initcall(ath25_register_devices);
static int __init ath25_arch_init(void)
{
if (is_ar5312())
ar5312_arch_init();
else
ar2315_arch_init();
return 0;
}
arch_initcall(ath25_arch_init);
#ifndef __ATH25_DEVICES_H
#define __ATH25_DEVICES_H
#include <linux/cpu.h>
#define ATH25_REG_MS(_val, _field) (((_val) & _field##_M) >> _field##_S)
#define ATH25_IRQ_CPU_CLOCK (MIPS_CPU_IRQ_BASE + 7) /* C0_CAUSE: 0x8000 */
enum ath25_soc_type {
/* handled by ar5312.c */
ATH25_SOC_AR2312,
ATH25_SOC_AR2313,
ATH25_SOC_AR5312,
/* handled by ar2315.c */
ATH25_SOC_AR2315,
ATH25_SOC_AR2316,
ATH25_SOC_AR2317,
ATH25_SOC_AR2318,
ATH25_SOC_UNKNOWN
};
extern enum ath25_soc_type ath25_soc;
extern struct ar231x_board_config ath25_board;
extern void (*ath25_irq_dispatch)(void);
int ath25_find_config(phys_addr_t offset, unsigned long size);
void ath25_serial_setup(u32 mapbase, int irq, unsigned int uartclk);
int ath25_add_wmac(int nr, u32 base, int irq);
static inline bool is_ar2315(void)
{
return (current_cpu_data.cputype == CPU_4KEC);
}
static inline bool is_ar5312(void)
{
return !is_ar2315();
}
#endif
/*
* 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) 2010 Gabor Juhos <juhosg@openwrt.org>
*/
#include <linux/mm.h>
#include <linux/io.h>
#include <linux/serial_reg.h>
#include "devices.h"
#include "ar2315_regs.h"
#include "ar5312_regs.h"
static inline void prom_uart_wr(void __iomem *base, unsigned reg,
unsigned char ch)
{
__raw_writel(ch, base + 4 * reg);
}
static inline unsigned char prom_uart_rr(void __iomem *base, unsigned reg)
{
return __raw_readl(base + 4 * reg);
}
void prom_putchar(unsigned char ch)
{
static void __iomem *base;
if (unlikely(base == NULL)) {
if (is_ar2315())
base = (void __iomem *)(KSEG1ADDR(AR2315_UART0_BASE));
else
base = (void __iomem *)(KSEG1ADDR(AR5312_UART0_BASE));
}
while ((prom_uart_rr(base, UART_LSR) & UART_LSR_THRE) == 0)
;
prom_uart_wr(base, UART_TX, ch);
while ((prom_uart_rr(base, UART_LSR) & UART_LSR_THRE) == 0)
;
}
/*
* 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 MontaVista Software Inc
* Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved.
* Copyright (C) 2006 FON Technology, SL.
* Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
* Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
*/
/*
* Prom setup file for AR5312/AR231x SoCs
*/
#include <linux/init.h>
#include <asm/bootinfo.h>
void __init prom_init(void)
{
}
void __init prom_free_prom_memory(void)
{
}
......@@ -359,7 +359,6 @@ void __init arch_init_irq(void)
BUG();
}
cp0_perfcount_irq = ATH79_MISC_IRQ(5);
mips_cpu_irq_init();
ath79_misc_irq_init();
......
......@@ -13,42 +13,24 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/string.h>
#include <linux/initrd.h>
#include <asm/bootinfo.h>
#include <asm/addrspace.h>
#include <asm/fw/fw.h>
#include "common.h"
static inline int is_valid_ram_addr(void *addr)
{
if (((u32) addr > KSEG0) &&
((u32) addr < (KSEG0 + ATH79_MEM_SIZE_MAX)))
return 1;
if (((u32) addr > KSEG1) &&
((u32) addr < (KSEG1 + ATH79_MEM_SIZE_MAX)))
return 1;
return 0;
}
static __init void ath79_prom_init_cmdline(int argc, char **argv)
{
int i;
if (!is_valid_ram_addr(argv))
return;
for (i = 0; i < argc; i++)
if (is_valid_ram_addr(argv[i])) {
strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
strlcat(arcs_cmdline, argv[i], sizeof(arcs_cmdline));
}
}
void __init prom_init(void)
{
ath79_prom_init_cmdline(fw_arg0, (char **)fw_arg1);
fw_init_cmdline();
/* Read the initrd address from the firmware environment */
initrd_start = fw_getenvl("initrd_start");
if (initrd_start) {
initrd_start = KSEG0ADDR(initrd_start);
initrd_end = initrd_start + fw_getenvl("initrd_size");
}
}
void __init prom_free_prom_memory(void)
......
......@@ -182,6 +182,11 @@ const char *get_system_type(void)
return ath79_sys_type;
}
int get_c0_perfcount_int(void)
{
return ATH79_MISC_IRQ(5);
}
unsigned int get_c0_compare_int(void)
{
return CP0_LEGACY_COMPARE_IRQ;
......
obj-y += setup.o irq.o dma.o
#
# Broadcom BCM3384 boards
#
platform-$(CONFIG_BCM3384) += bcm3384/
cflags-$(CONFIG_BCM3384) += \
-I$(srctree)/arch/mips/include/asm/mach-bcm3384/
load-$(CONFIG_BCM3384) := 0xffffffff80010000
/*
* 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) 2014 Kevin Cernekee <cernekee@gmail.com>
*/
#include <linux/device.h>
#include <linux/dma-direction.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/of.h>
#include <linux/pci.h>
#include <linux/types.h>
#include <dma-coherence.h>
/*
* BCM3384 has configurable address translation windows which allow the
* peripherals' DMA addresses to be different from the Zephyr-visible
* physical addresses. e.g. usb_dma_addr = zephyr_pa ^ 0x08000000
*
* If our DT "memory" node has a "dma-xor-mask" property we will enable this
* translation using the provided offset.
*/
static u32 bcm3384_dma_xor_mask;
static u32 bcm3384_dma_xor_limit = 0xffffffff;
/*
* PCI collapses the memory hole at 0x10000000 - 0x1fffffff.
* On systems with a dma-xor-mask, this range is guaranteed to live above
* the dma-xor-limit.
*/
#define BCM3384_MEM_HOLE_PA 0x10000000
#define BCM3384_MEM_HOLE_SIZE 0x10000000
static dma_addr_t bcm3384_phys_to_dma(struct device *dev, phys_addr_t pa)
{
if (dev && dev_is_pci(dev) &&
pa >= (BCM3384_MEM_HOLE_PA + BCM3384_MEM_HOLE_SIZE))
return pa - BCM3384_MEM_HOLE_SIZE;
if (pa <= bcm3384_dma_xor_limit)
return pa ^ bcm3384_dma_xor_mask;
return pa;
}
dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size)
{
return bcm3384_phys_to_dma(dev, virt_to_phys(addr));
}
dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page)
{
return bcm3384_phys_to_dma(dev, page_to_phys(page));
}
unsigned long plat_dma_addr_to_phys(struct device *dev, dma_addr_t dma_addr)
{
if (dev && dev_is_pci(dev) &&
dma_addr >= BCM3384_MEM_HOLE_PA)
return dma_addr + BCM3384_MEM_HOLE_SIZE;
if ((dma_addr ^ bcm3384_dma_xor_mask) <= bcm3384_dma_xor_limit)
return dma_addr ^ bcm3384_dma_xor_mask;
return dma_addr;
}
static int __init bcm3384_init_dma_xor(void)
{
struct device_node *np = of_find_node_by_type(NULL, "memory");
if (!np)
return 0;
of_property_read_u32(np, "dma-xor-mask", &bcm3384_dma_xor_mask);
of_property_read_u32(np, "dma-xor-limit", &bcm3384_dma_xor_limit);
of_node_put(np);
return 0;
}
arch_initcall(bcm3384_init_dma_xor);
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* Partially based on arch/mips/ralink/irq.c
*
* Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2013 John Crispin <blogic@openwrt.org>
* Copyright (C) 2014 Kevin Cernekee <cernekee@gmail.com>
*/
#include <linux/io.h>
#include <linux/bitops.h>
#include <linux/of_platform.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/irqdomain.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <asm/bmips.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
/* INTC register offsets */
#define INTC_REG_ENABLE 0x00
#define INTC_REG_STATUS 0x04
#define MAX_WORDS 2
#define IRQS_PER_WORD 32
struct bcm3384_intc {
int n_words;
void __iomem *reg[MAX_WORDS];
u32 enable[MAX_WORDS];
spinlock_t lock;
};
static void bcm3384_intc_irq_unmask(struct irq_data *d)
{
struct bcm3384_intc *priv = d->domain->host_data;
unsigned long flags;
int idx = d->hwirq / IRQS_PER_WORD;
int bit = d->hwirq % IRQS_PER_WORD;
spin_lock_irqsave(&priv->lock, flags);
priv->enable[idx] |= BIT(bit);
__raw_writel(priv->enable[idx], priv->reg[idx] + INTC_REG_ENABLE);
spin_unlock_irqrestore(&priv->lock, flags);
}
static void bcm3384_intc_irq_mask(struct irq_data *d)
{
struct bcm3384_intc *priv = d->domain->host_data;
unsigned long flags;
int idx = d->hwirq / IRQS_PER_WORD;
int bit = d->hwirq % IRQS_PER_WORD;
spin_lock_irqsave(&priv->lock, flags);
priv->enable[idx] &= ~BIT(bit);
__raw_writel(priv->enable[idx], priv->reg[idx] + INTC_REG_ENABLE);
spin_unlock_irqrestore(&priv->lock, flags);
}
static struct irq_chip bcm3384_intc_irq_chip = {
.name = "INTC",
.irq_unmask = bcm3384_intc_irq_unmask,
.irq_mask = bcm3384_intc_irq_mask,
.irq_mask_ack = bcm3384_intc_irq_mask,
};
unsigned int get_c0_compare_int(void)
{
return CP0_LEGACY_COMPARE_IRQ;
}
static void bcm3384_intc_irq_handler(unsigned int irq, struct irq_desc *desc)
{
struct irq_domain *domain = irq_get_handler_data(irq);
struct bcm3384_intc *priv = domain->host_data;
unsigned long flags;
unsigned int idx;
for (idx = 0; idx < priv->n_words; idx++) {
unsigned long pending;
int hwirq;
spin_lock_irqsave(&priv->lock, flags);
pending = __raw_readl(priv->reg[idx] + INTC_REG_STATUS) &
priv->enable[idx];
spin_unlock_irqrestore(&priv->lock, flags);
for_each_set_bit(hwirq, &pending, IRQS_PER_WORD) {
generic_handle_irq(irq_find_mapping(domain,
hwirq + idx * IRQS_PER_WORD));
}
}
}
asmlinkage void plat_irq_dispatch(void)
{
unsigned long pending =
(read_c0_status() & read_c0_cause() & ST0_IM) >> STATUSB_IP0;
int bit;
for_each_set_bit(bit, &pending, 8)
do_IRQ(MIPS_CPU_IRQ_BASE + bit);
}
static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
{
irq_set_chip_and_handler(irq, &bcm3384_intc_irq_chip, handle_level_irq);
return 0;
}
static const struct irq_domain_ops irq_domain_ops = {
.xlate = irq_domain_xlate_onecell,
.map = intc_map,
};
static int __init ioremap_one_pair(struct bcm3384_intc *priv,
struct device_node *node,
int idx)
{
struct resource res;
if (of_address_to_resource(node, idx, &res))
return 0;
if (request_mem_region(res.start, resource_size(&res),
res.name) < 0)
pr_err("Failed to request INTC register region\n");
priv->reg[idx] = ioremap_nocache(res.start, resource_size(&res));
if (!priv->reg[idx])
panic("Failed to ioremap INTC register range");
/* start up with everything masked before we hook the parent IRQ */
__raw_writel(0, priv->reg[idx] + INTC_REG_ENABLE);
priv->enable[idx] = 0;
return IRQS_PER_WORD;
}
static int __init intc_of_init(struct device_node *node,
struct device_node *parent)
{
struct irq_domain *domain;
unsigned int parent_irq, n_irqs = 0;
struct bcm3384_intc *priv;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
panic("Failed to allocate bcm3384_intc struct");
spin_lock_init(&priv->lock);
parent_irq = irq_of_parse_and_map(node, 0);
if (!parent_irq)
panic("Failed to get INTC IRQ");
n_irqs += ioremap_one_pair(priv, node, 0);
n_irqs += ioremap_one_pair(priv, node, 1);
if (!n_irqs)
panic("Failed to map INTC registers");
priv->n_words = n_irqs / IRQS_PER_WORD;
domain = irq_domain_add_linear(node, n_irqs, &irq_domain_ops, priv);
if (!domain)
panic("Failed to add irqdomain");
irq_set_chained_handler(parent_irq, bcm3384_intc_irq_handler);
irq_set_handler_data(parent_irq, domain);
return 0;
}
static struct of_device_id of_irq_ids[] __initdata = {
{ .compatible = "mti,cpu-interrupt-controller",
.data = mips_cpu_intc_init },
{ .compatible = "brcm,bcm3384-intc",
.data = intc_of_init },
{},
};
void __init arch_init_irq(void)
{
bmips_tp1_irqs = 0;
of_irq_init(of_irq_ids);
}
/*
* 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) 2008 Maxime Bizon <mbizon@freebox.fr>
* Copyright (C) 2014 Kevin Cernekee <cernekee@gmail.com>
*/
#include <linux/init.h>
#include <linux/bootmem.h>
#include <linux/clk-provider.h>
#include <linux/ioport.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/of_platform.h>
#include <linux/smp.h>
#include <asm/addrspace.h>
#include <asm/bmips.h>
#include <asm/bootinfo.h>
#include <asm/prom.h>
#include <asm/smp-ops.h>
#include <asm/time.h>
void __init prom_init(void)
{
register_bmips_smp_ops();
}
void __init prom_free_prom_memory(void)
{
}
const char *get_system_type(void)
{
return "BCM3384";
}
void __init plat_time_init(void)
{
struct device_node *np;
u32 freq;
np = of_find_node_by_name(NULL, "cpus");
if (!np)
panic("missing 'cpus' DT node");
if (of_property_read_u32(np, "mips-hpt-frequency", &freq) < 0)
panic("missing 'mips-hpt-frequency' property");
of_node_put(np);
mips_hpt_frequency = freq;
}
void __init plat_mem_setup(void)
{
void *dtb = __dtb_start;
set_io_port_base(0);
ioport_resource.start = 0;
ioport_resource.end = ~0;
/* intended to somewhat resemble ARM; see Documentation/arm/Booting */
if (fw_arg0 == 0 && fw_arg1 == 0xffffffff)
dtb = phys_to_virt(fw_arg2);
__dt_setup_arch(dtb);
strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
}
void __init device_tree_init(void)
{
struct device_node *np;
unflatten_and_copy_device_tree();
/* Disable SMP boot unless both CPUs are listed in DT and !disabled */
np = of_find_node_by_name(NULL, "cpus");
if (np && of_get_available_child_count(np) <= 1)
bmips_smp_enabled = 0;
of_node_put(np);
}
int __init plat_of_setup(void)
{
return __dt_register_buses("brcm,bcm3384", "simple-bus");
}
arch_initcall(plat_of_setup);
static int __init plat_dev_init(void)
{
of_clk_init(NULL);
return 0;
}
device_initcall(plat_dev_init);
......@@ -6,12 +6,18 @@
/* prom.c */
void __init bcm47xx_prom_highmem_init(void);
/* sprom.c */
void bcm47xx_sprom_register_fallbacks(void);
/* buttons.c */
int __init bcm47xx_buttons_register(void);
/* leds.c */
void __init bcm47xx_leds_register(void);
/* setup.c */
void __init bcm47xx_bus_setup(void);
/* workarounds.c */
void __init bcm47xx_workarounds(void);
......
......@@ -22,6 +22,8 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "bcm47xx_private.h"
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
......@@ -65,6 +67,12 @@ DEFINE_HWx_IRQDISPATCH(7)
void __init arch_init_irq(void)
{
/*
* This is the first arch callback after mm_init (we can use kmalloc),
* so let's finish bus initialization now.
*/
bcm47xx_bus_setup();
#ifdef CONFIG_BCM47XX_BCMA
if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) {
bcma_write32(bcm47xx_bus.bcma.bus.drv_mips.core,
......
......@@ -13,24 +13,35 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/ssb/ssb.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <asm/addrspace.h>
#include <linux/mtd/mtd.h>
#include <bcm47xx_nvram.h>
#include <asm/mach-bcm47xx/bcm47xx.h>
#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */
#define NVRAM_SPACE 0x8000
#define FLASH_MIN 0x00020000 /* Minimum flash size */
struct nvram_header {
u32 magic;
u32 len;
u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */
u32 config_ncdl; /* ncdl values for memc */
};
static char nvram_buf[NVRAM_SPACE];
static const u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000};
static u32 find_nvram_size(u32 end)
static u32 find_nvram_size(void __iomem *end)
{
struct nvram_header *header;
struct nvram_header __iomem *header;
int i;
for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) {
header = (struct nvram_header *)KSEG1ADDR(end - nvram_sizes[i]);
if (header->magic == NVRAM_HEADER)
header = (struct nvram_header *)(end - nvram_sizes[i]);
if (header->magic == NVRAM_MAGIC)
return nvram_sizes[i];
}
......@@ -38,36 +49,40 @@ static u32 find_nvram_size(u32 end)
}
/* Probe for NVRAM header */
static int nvram_find_and_copy(u32 base, u32 lim)
static int nvram_find_and_copy(void __iomem *iobase, u32 lim)
{
struct nvram_header *header;
struct nvram_header __iomem *header;
int i;
u32 off;
u32 *src, *dst;
u32 size;
if (nvram_buf[0]) {
pr_warn("nvram already initialized\n");
return -EEXIST;
}
/* TODO: when nvram is on nand flash check for bad blocks first. */
off = FLASH_MIN;
while (off <= lim) {
/* Windowed flash access */
size = find_nvram_size(base + off);
size = find_nvram_size(iobase + off);
if (size) {
header = (struct nvram_header *)KSEG1ADDR(base + off -
size);
header = (struct nvram_header *)(iobase + off - size);
goto found;
}
off <<= 1;
}
/* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
header = (struct nvram_header *) KSEG1ADDR(base + 4096);
if (header->magic == NVRAM_HEADER) {
header = (struct nvram_header *)(iobase + 4096);
if (header->magic == NVRAM_MAGIC) {
size = NVRAM_SPACE;
goto found;
}
header = (struct nvram_header *) KSEG1ADDR(base + 1024);
if (header->magic == NVRAM_HEADER) {
header = (struct nvram_header *)(iobase + 1024);
if (header->magic == NVRAM_MAGIC) {
size = NVRAM_SPACE;
goto found;
}
......@@ -94,71 +109,73 @@ static int nvram_find_and_copy(u32 base, u32 lim)
return 0;
}
#ifdef CONFIG_BCM47XX_SSB
static int nvram_init_ssb(void)
/*
* On bcm47xx we need access to the NVRAM very early, so we can't use mtd
* subsystem to access flash. We can't even use platform device / driver to
* store memory offset.
* To handle this we provide following symbol. It's supposed to be called as
* soon as we get info about flash device, before any NVRAM entry is needed.
*/
int bcm47xx_nvram_init_from_mem(u32 base, u32 lim)
{
struct ssb_mipscore *mcore = &bcm47xx_bus.ssb.mipscore;
u32 base;
u32 lim;
if (mcore->pflash.present) {
base = mcore->pflash.window;
lim = mcore->pflash.window_size;
} else {
pr_err("Couldn't find supported flash memory\n");
return -ENXIO;
}
void __iomem *iobase;
int err;
return nvram_find_and_copy(base, lim);
}
#endif
iobase = ioremap_nocache(base, lim);
if (!iobase)
return -ENOMEM;
#ifdef CONFIG_BCM47XX_BCMA
static int nvram_init_bcma(void)
{
struct bcma_drv_cc *cc = &bcm47xx_bus.bcma.bus.drv_cc;
u32 base;
u32 lim;
#ifdef CONFIG_BCMA_NFLASH
if (cc->nflash.boot) {
base = BCMA_SOC_FLASH1;
lim = BCMA_SOC_FLASH1_SZ;
} else
#endif
if (cc->pflash.present) {
base = cc->pflash.window;
lim = cc->pflash.window_size;
#ifdef CONFIG_BCMA_SFLASH
} else if (cc->sflash.present) {
base = cc->sflash.window;
lim = cc->sflash.size;
#endif
} else {
pr_err("Couldn't find supported flash memory\n");
return -ENXIO;
}
err = nvram_find_and_copy(iobase, lim);
iounmap(iobase);
return nvram_find_and_copy(base, lim);
return err;
}
#endif
static int nvram_init(void)
{
switch (bcm47xx_bus_type) {
#ifdef CONFIG_BCM47XX_SSB
case BCM47XX_BUS_TYPE_SSB:
return nvram_init_ssb();
#endif
#ifdef CONFIG_BCM47XX_BCMA
case BCM47XX_BUS_TYPE_BCMA:
return nvram_init_bcma();
#endif
#ifdef CONFIG_MTD
struct mtd_info *mtd;
struct nvram_header header;
size_t bytes_read;
int err, i;
mtd = get_mtd_device_nm("nvram");
if (IS_ERR(mtd))
return -ENODEV;
for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) {
loff_t from = mtd->size - nvram_sizes[i];
if (from < 0)
continue;
err = mtd_read(mtd, from, sizeof(header), &bytes_read,
(uint8_t *)&header);
if (!err && header.magic == NVRAM_MAGIC) {
u8 *dst = (uint8_t *)nvram_buf;
size_t len = header.len;
if (header.len > NVRAM_SPACE) {
pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n",
header.len, NVRAM_SPACE);
len = NVRAM_SPACE;
}
err = mtd_read(mtd, from, len, &bytes_read, dst);
if (err)
return err;
memset(dst + bytes_read, 0x0, NVRAM_SPACE - bytes_read);
return 0;
}
}
#endif
return -ENXIO;
}
int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len)
int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len)
{
char *var, *value, *end, *eq;
int err;
......
......@@ -102,23 +102,6 @@ static void bcm47xx_machine_halt(void)
}
#ifdef CONFIG_BCM47XX_SSB
static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
{
char prefix[10];
if (bus->bustype == SSB_BUSTYPE_PCI) {
memset(out, 0, sizeof(struct ssb_sprom));
snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
bus->host_pci->bus->number + 1,
PCI_SLOT(bus->host_pci->devfn));
bcm47xx_fill_sprom(out, prefix, false);
return 0;
} else {
printk(KERN_WARNING "bcm47xx: unable to fill SPROM for given bustype.\n");
return -EINVAL;
}
}
static int bcm47xx_get_invariants(struct ssb_bus *bus,
struct ssb_init_invariants *iv)
{
......@@ -144,11 +127,6 @@ static void __init bcm47xx_register_ssb(void)
char buf[100];
struct ssb_mipscore *mcore;
err = ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom_ssb);
if (err)
printk(KERN_WARNING "bcm47xx: someone else already registered"
" a ssb SPROM callback handler (err %d)\n", err);
err = ssb_bus_ssbbus_register(&(bcm47xx_bus.ssb), SSB_ENUM_BASE,
bcm47xx_get_invariants);
if (err)
......@@ -171,56 +149,21 @@ static void __init bcm47xx_register_ssb(void)
#endif
#ifdef CONFIG_BCM47XX_BCMA
static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out)
{
char prefix[10];
struct bcma_device *core;
switch (bus->hosttype) {
case BCMA_HOSTTYPE_PCI:
memset(out, 0, sizeof(struct ssb_sprom));
snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
bus->host_pci->bus->number + 1,
PCI_SLOT(bus->host_pci->devfn));
bcm47xx_fill_sprom(out, prefix, false);
return 0;
case BCMA_HOSTTYPE_SOC:
memset(out, 0, sizeof(struct ssb_sprom));
core = bcma_find_core(bus, BCMA_CORE_80211);
if (core) {
snprintf(prefix, sizeof(prefix), "sb/%u/",
core->core_index);
bcm47xx_fill_sprom(out, prefix, true);
} else {
bcm47xx_fill_sprom(out, NULL, false);
}
return 0;
default:
pr_warn("bcm47xx: unable to fill SPROM for given bustype.\n");
return -EINVAL;
}
}
static void __init bcm47xx_register_bcma(void)
{
int err;
err = bcma_arch_register_fallback_sprom(&bcm47xx_get_sprom_bcma);
if (err)
pr_warn("bcm47xx: someone else already registered a bcma SPROM callback handler (err %d)\n", err);
err = bcma_host_soc_register(&bcm47xx_bus.bcma);
if (err)
panic("Failed to register BCMA bus (err %d)", err);
err = bcma_host_soc_init(&bcm47xx_bus.bcma);
if (err)
panic("Failed to initialize BCMA bus (err %d)", err);
bcm47xx_fill_bcma_boardinfo(&bcm47xx_bus.bcma.bus.boardinfo, NULL);
}
#endif
/*
* Memory setup is done in the early part of MIPS's arch_mem_init. It's supposed
* to detect memory and record it with add_memory_region.
* Any extra initializaion performed here must not use kmalloc or bootmem.
*/
void __init plat_mem_setup(void)
{
struct cpuinfo_mips *c = &current_cpu_data;
......@@ -229,6 +172,7 @@ void __init plat_mem_setup(void)
printk(KERN_INFO "bcm47xx: using bcma bus\n");
#ifdef CONFIG_BCM47XX_BCMA
bcm47xx_bus_type = BCM47XX_BUS_TYPE_BCMA;
bcm47xx_sprom_register_fallbacks();
bcm47xx_register_bcma();
bcm47xx_set_system_type(bcm47xx_bus.bcma.bus.chipinfo.id);
#ifdef CONFIG_HIGHMEM
......@@ -239,6 +183,7 @@ void __init plat_mem_setup(void)
printk(KERN_INFO "bcm47xx: using ssb bus\n");
#ifdef CONFIG_BCM47XX_SSB
bcm47xx_bus_type = BCM47XX_BUS_TYPE_SSB;
bcm47xx_sprom_register_fallbacks();
bcm47xx_register_ssb();
bcm47xx_set_system_type(bcm47xx_bus.ssb.chip_id);
#endif
......@@ -247,6 +192,28 @@ void __init plat_mem_setup(void)
_machine_restart = bcm47xx_machine_restart;
_machine_halt = bcm47xx_machine_halt;
pm_power_off = bcm47xx_machine_halt;
}
/*
* This finishes bus initialization doing things that were not possible without
* kmalloc. Make sure to call it late enough (after mm_init).
*/
void __init bcm47xx_bus_setup(void)
{
#ifdef CONFIG_BCM47XX_BCMA
if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) {
int err;
err = bcma_host_soc_init(&bcm47xx_bus.bcma);
if (err)
panic("Failed to initialize BCMA bus (err %d)", err);
bcm47xx_fill_bcma_boardinfo(&bcm47xx_bus.bcma.bus.boardinfo,
NULL);
}
#endif
/* With bus initialized we can access NVRAM and detect the board */
bcm47xx_board_detect();
mips_set_machine_name(bcm47xx_board_get_name());
}
......
......@@ -136,6 +136,20 @@ static void nvram_read_leddc(const char *prefix, const char *name,
*leddc_off_time = (val >> 16) & 0xff;
}
static void bcm47xx_nvram_parse_macaddr(char *buf, u8 macaddr[6])
{
if (strchr(buf, ':'))
sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],
&macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
&macaddr[5]);
else if (strchr(buf, '-'))
sscanf(buf, "%hhx-%hhx-%hhx-%hhx-%hhx-%hhx", &macaddr[0],
&macaddr[1], &macaddr[2], &macaddr[3], &macaddr[4],
&macaddr[5]);
else
pr_warn("Can not parse mac address: %s\n", buf);
}
static void nvram_read_macaddr(const char *prefix, const char *name,
u8 val[6], bool fallback)
{
......@@ -801,3 +815,71 @@ void bcm47xx_fill_bcma_boardinfo(struct bcma_boardinfo *boardinfo,
nvram_read_u16(prefix, NULL, "boardtype", &boardinfo->type, 0, true);
}
#endif
#if defined(CONFIG_BCM47XX_SSB)
static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
{
char prefix[10];
if (bus->bustype == SSB_BUSTYPE_PCI) {
memset(out, 0, sizeof(struct ssb_sprom));
snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
bus->host_pci->bus->number + 1,
PCI_SLOT(bus->host_pci->devfn));
bcm47xx_fill_sprom(out, prefix, false);
return 0;
} else {
pr_warn("bcm47xx: unable to fill SPROM for given bustype.\n");
return -EINVAL;
}
}
#endif
#if defined(CONFIG_BCM47XX_BCMA)
static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out)
{
char prefix[10];
struct bcma_device *core;
switch (bus->hosttype) {
case BCMA_HOSTTYPE_PCI:
memset(out, 0, sizeof(struct ssb_sprom));
snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
bus->host_pci->bus->number + 1,
PCI_SLOT(bus->host_pci->devfn));
bcm47xx_fill_sprom(out, prefix, false);
return 0;
case BCMA_HOSTTYPE_SOC:
memset(out, 0, sizeof(struct ssb_sprom));
core = bcma_find_core(bus, BCMA_CORE_80211);
if (core) {
snprintf(prefix, sizeof(prefix), "sb/%u/",
core->core_index);
bcm47xx_fill_sprom(out, prefix, true);
} else {
bcm47xx_fill_sprom(out, NULL, false);
}
return 0;
default:
pr_warn("bcm47xx: unable to fill SPROM for given bustype.\n");
return -EINVAL;
}
}
#endif
/*
* On bcm47xx we need to register SPROM fallback handler very early, so we can't
* use anything like platform device / driver for this.
*/
void bcm47xx_sprom_register_fallbacks(void)
{
#if defined(CONFIG_BCM47XX_SSB)
if (ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom_ssb))
pr_warn("Failed to registered ssb SPROM handler\n");
#endif
#if defined(CONFIG_BCM47XX_BCMA)
if (bcma_arch_register_fallback_sprom(&bcm47xx_get_sprom_bcma))
pr_warn("Failed to registered bcma SPROM handler\n");
#endif
}
......@@ -263,7 +263,7 @@ static unsigned int detect_memory_size(void)
if (BCMCPU_IS_6345()) {
val = bcm_sdram_readl(SDRAM_MBASE_REG);
return (val * 8 * 1024 * 1024);
return val * 8 * 1024 * 1024;
}
if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) {
......
dtb-$(CONFIG_BCM3384) += bcm93384wvg.dtb
dtb-$(CONFIG_CAVIUM_OCTEON_SOC) += octeon_3xxx.dtb octeon_68xx.dtb
dtb-$(CONFIG_DT_EASY50712) += easy50712.dtb
dtb-$(CONFIG_DT_XLP_EVP) += xlp_evp.dtb
......
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "brcm,bcm3384", "brcm,bcm33843";
cpus {
#address-cells = <1>;
#size-cells = <0>;
/* On BMIPS5000 this is 1/8th of the CPU core clock */
mips-hpt-frequency = <100000000>;
cpu@0 {
compatible = "brcm,bmips5000";
device_type = "cpu";
reg = <0>;
};
cpu@1 {
compatible = "brcm,bmips5000";
device_type = "cpu";
reg = <1>;
};
};
clocks {
#address-cells = <1>;
#size-cells = <0>;
periph_clk: periph_clk@0 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <54000000>;
};
};
aliases {
uart0 = &uart0;
};
cpu_intc: cpu_intc@0 {
#address-cells = <0>;
compatible = "mti,cpu-interrupt-controller";
interrupt-controller;
#interrupt-cells = <1>;
};
periph_intc: periph_intc@14e00038 {
compatible = "brcm,bcm3384-intc";
reg = <0x14e00038 0x8 0x14e00340 0x8>;
interrupt-controller;
#interrupt-cells = <1>;
interrupt-parent = <&cpu_intc>;
interrupts = <4>;
};
zmips_intc: zmips_intc@104b0060 {
compatible = "brcm,bcm3384-intc";
reg = <0x104b0060 0x8>;
interrupt-controller;
#interrupt-cells = <1>;
interrupt-parent = <&periph_intc>;
interrupts = <29>;
};
iop_intc: iop_intc@14e00058 {
compatible = "brcm,bcm3384-intc";
reg = <0x14e00058 0x8>;
interrupt-controller;
#interrupt-cells = <1>;
interrupt-parent = <&cpu_intc>;
interrupts = <6>;
};
uart0: serial@14e00520 {
compatible = "brcm,bcm6345-uart";
reg = <0x14e00520 0x18>;
interrupt-parent = <&periph_intc>;
interrupts = <2>;
clocks = <&periph_clk>;
status = "disabled";
};
ehci0: usb@15400300 {
compatible = "brcm,bcm3384-ehci", "generic-ehci";
reg = <0x15400300 0x100>;
big-endian;
interrupt-parent = <&periph_intc>;
interrupts = <41>;
status = "disabled";
};
ohci0: usb@15400400 {
compatible = "brcm,bcm3384-ohci", "generic-ohci";
reg = <0x15400400 0x100>;
big-endian;
no-big-frame-no;
interrupt-parent = <&periph_intc>;
interrupts = <40>;
status = "disabled";
};
};
/dts-v1/;
/include/ "bcm3384.dtsi"
/ {
compatible = "brcm,bcm93384wvg", "brcm,bcm3384";
model = "Broadcom BCM93384WVG";
chosen {
bootargs = "console=ttyS0,115200";
stdout-path = &uart0;
};
memory@0 {
device_type = "memory";
reg = <0x0 0x04000000>;
dma-xor-mask = <0x08000000>;
dma-xor-limit = <0x0fffffff>;
};
};
&uart0 {
status = "okay";
};
&ehci0 {
status = "okay";
};
&ohci0 {
status = "okay";
};
......@@ -262,8 +262,8 @@ char *octeon_swiotlb;
void __init plat_swiotlb_setup(void)
{
int i;
phys_t max_addr;
phys_t addr_size;
phys_addr_t max_addr;
phys_addr_t addr_size;
size_t swiotlbsize;
unsigned long swiotlb_nslabs;
......
......@@ -28,22 +28,23 @@
#include <asm/octeon/octeon.h>
/**
* Given the chip processor ID from COP0, this function returns a
* string representing the chip model number. The string is of the
* form CNXXXXpX.X-FREQ-SUFFIX.
* - XXXX = The chip model number
* - X.X = Chip pass number
* - FREQ = Current frequency in Mhz
* - SUFFIX = NSP, EXP, SCP, SSP, or CP
*
* @chip_id: Chip ID
* Read a byte of fuse data
* @byte_addr: address to read
*
* Returns Model string
* Returns fuse value: 0 or 1
*/
const char *octeon_model_get_string(uint32_t chip_id)
static uint8_t __init cvmx_fuse_read_byte(int byte_addr)
{
static char buffer[32];
return octeon_model_get_string_buffer(chip_id, buffer);
union cvmx_mio_fus_rcmd read_cmd;
read_cmd.u64 = 0;
read_cmd.s.addr = byte_addr;
read_cmd.s.pend = 1;
cvmx_write_csr(CVMX_MIO_FUS_RCMD, read_cmd.u64);
while ((read_cmd.u64 = cvmx_read_csr(CVMX_MIO_FUS_RCMD))
&& read_cmd.s.pend)
;
return read_cmd.s.dat;
}
/*
......@@ -51,7 +52,8 @@ const char *octeon_model_get_string(uint32_t chip_id)
* as running early in u-boot static/global variables don't work when
* running from flash.
*/
const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer)
static const char *__init octeon_model_get_string_buffer(uint32_t chip_id,
char *buffer)
{
const char *family;
const char *core_model;
......@@ -407,3 +409,22 @@ const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer)
sprintf(buffer, "CN%s%sp%s-%d-%s", family, core_model, pass, clock_mhz, suffix);
return buffer;
}
/**
* Given the chip processor ID from COP0, this function returns a
* string representing the chip model number. The string is of the
* form CNXXXXpX.X-FREQ-SUFFIX.
* - XXXX = The chip model number
* - X.X = Chip pass number
* - FREQ = Current frequency in Mhz
* - SUFFIX = NSP, EXP, SCP, SSP, or CP
*
* @chip_id: Chip ID
*
* Returns Model string
*/
const char *__init octeon_model_get_string(uint32_t chip_id)
{
static char buffer[32];
return octeon_model_get_string_buffer(chip_id, buffer);
}
CONFIG_BCM3384=y
CONFIG_HIGHMEM=y
CONFIG_SMP=y
CONFIG_NR_CPUS=4
# CONFIG_SECCOMP is not set
CONFIG_MIPS_O32_FP64_SUPPORT=y
# CONFIG_LOCALVERSION_AUTO is not set
# CONFIG_SWAP is not set
CONFIG_NO_HZ=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_RD_GZIP is not set
CONFIG_EXPERT=y
# CONFIG_VM_EVENT_COUNTERS is not set
# CONFIG_SLUB_DEBUG is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_PACKET_DIAG=y
CONFIG_UNIX=y
CONFIG_INET=y
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
# CONFIG_INET_DIAG is not set
CONFIG_CFG80211=y
CONFIG_NL80211_TESTMODE=y
CONFIG_MAC80211=y
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_STANDALONE is not set
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
CONFIG_MTD=y
CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_PHYSMAP=y
# CONFIG_BLK_DEV is not set
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
# CONFIG_SCSI_LOWLEVEL is not set
CONFIG_NETDEVICES=y
CONFIG_USB_USBNET=y
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_EARLYCON_FORCE=y
CONFIG_SERIAL_BCM63XX=y
CONFIG_SERIAL_BCM63XX_CONSOLE=y
# CONFIG_HW_RANDOM is not set
# CONFIG_HWMON is not set
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_EHCI_HCD_PLATFORM=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PLATFORM=y
CONFIG_USB_STORAGE=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
# CONFIG_DNOTIFY is not set
CONFIG_FUSE_FS=y
CONFIG_VFAT_FS=y
CONFIG_PROC_KCORE=y
CONFIG_TMPFS=y
CONFIG_NFS_FS=y
CONFIG_CIFS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
CONFIG_DEBUG_FS=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_CRYPTO_HW is not set
......@@ -68,7 +68,7 @@ char *fw_getenv(char *envname)
result = fw_envp(index + 1);
break;
} else if (fw_envp(index)[i] == '=') {
result = (fw_envp(index + 1) + i);
result = fw_envp(index) + i + 1;
break;
}
}
......@@ -88,13 +88,13 @@ unsigned long fw_getenvl(char *envname)
{
unsigned long envl = 0UL;
char *str;
long val;
int tmp;
str = fw_getenv(envname);
if (str) {
tmp = kstrtol(str, 0, &val);
envl = (unsigned long)val;
tmp = kstrtoul(str, 0, &envl);
if (tmp)
envl = 0;
}
return envl;
......
This diff is collapsed.
......@@ -17,6 +17,7 @@
#include <linux/types.h>
#include <asm/barrier.h>
#include <asm/byteorder.h> /* sigh ... */
#include <asm/compiler.h>
#include <asm/cpu-features.h>
#include <asm/sgidefs.h>
#include <asm/war.h>
......@@ -78,8 +79,8 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
" " __SC "%0, %1 \n"
" beqzl %0, 1b \n"
" .set mips0 \n"
: "=&r" (temp), "=m" (*m)
: "ir" (1UL << bit), "m" (*m));
: "=&r" (temp), "=" GCC_OFF12_ASM() (*m)
: "ir" (1UL << bit), GCC_OFF12_ASM() (*m));
#ifdef CONFIG_CPU_MIPSR2
} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
do {
......@@ -87,7 +88,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
" " __LL "%0, %1 # set_bit \n"
" " __INS "%0, %3, %2, 1 \n"
" " __SC "%0, %1 \n"
: "=&r" (temp), "+m" (*m)
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
: "ir" (bit), "r" (~0));
} while (unlikely(!temp));
#endif /* CONFIG_CPU_MIPSR2 */
......@@ -99,7 +100,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
" or %0, %2 \n"
" " __SC "%0, %1 \n"
" .set mips0 \n"
: "=&r" (temp), "+m" (*m)
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
: "ir" (1UL << bit));
} while (unlikely(!temp));
} else
......@@ -130,7 +131,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
" " __SC "%0, %1 \n"
" beqzl %0, 1b \n"
" .set mips0 \n"
: "=&r" (temp), "+m" (*m)
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
: "ir" (~(1UL << bit)));
#ifdef CONFIG_CPU_MIPSR2
} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
......@@ -139,7 +140,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
" " __LL "%0, %1 # clear_bit \n"
" " __INS "%0, $0, %2, 1 \n"
" " __SC "%0, %1 \n"
: "=&r" (temp), "+m" (*m)
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
: "ir" (bit));
} while (unlikely(!temp));
#endif /* CONFIG_CPU_MIPSR2 */
......@@ -151,7 +152,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
" and %0, %2 \n"
" " __SC "%0, %1 \n"
" .set mips0 \n"
: "=&r" (temp), "+m" (*m)
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
: "ir" (~(1UL << bit)));
} while (unlikely(!temp));
} else
......@@ -196,7 +197,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
" " __SC "%0, %1 \n"
" beqzl %0, 1b \n"
" .set mips0 \n"
: "=&r" (temp), "+m" (*m)
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
: "ir" (1UL << bit));
} else if (kernel_uses_llsc) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
......@@ -209,7 +210,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
" xor %0, %2 \n"
" " __SC "%0, %1 \n"
" .set mips0 \n"
: "=&r" (temp), "+m" (*m)
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m)
: "ir" (1UL << bit));
} while (unlikely(!temp));
} else
......@@ -244,7 +245,7 @@ static inline int test_and_set_bit(unsigned long nr,
" beqzl %2, 1b \n"
" and %2, %0, %3 \n"
" .set mips0 \n"
: "=&r" (temp), "+m" (*m), "=&r" (res)
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
: "r" (1UL << bit)
: "memory");
} else if (kernel_uses_llsc) {
......@@ -258,7 +259,7 @@ static inline int test_and_set_bit(unsigned long nr,
" or %2, %0, %3 \n"
" " __SC "%2, %1 \n"
" .set mips0 \n"
: "=&r" (temp), "+m" (*m), "=&r" (res)
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
: "r" (1UL << bit)
: "memory");
} while (unlikely(!res));
......@@ -312,7 +313,7 @@ static inline int test_and_set_bit_lock(unsigned long nr,
" or %2, %0, %3 \n"
" " __SC "%2, %1 \n"
" .set mips0 \n"
: "=&r" (temp), "+m" (*m), "=&r" (res)
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
: "r" (1UL << bit)
: "memory");
} while (unlikely(!res));
......@@ -354,7 +355,7 @@ static inline int test_and_clear_bit(unsigned long nr,
" beqzl %2, 1b \n"
" and %2, %0, %3 \n"
" .set mips0 \n"
: "=&r" (temp), "+m" (*m), "=&r" (res)
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
: "r" (1UL << bit)
: "memory");
#ifdef CONFIG_CPU_MIPSR2
......@@ -368,7 +369,7 @@ static inline int test_and_clear_bit(unsigned long nr,
" " __EXT "%2, %0, %3, 1 \n"
" " __INS "%0, $0, %3, 1 \n"
" " __SC "%0, %1 \n"
: "=&r" (temp), "+m" (*m), "=&r" (res)
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
: "ir" (bit)
: "memory");
} while (unlikely(!temp));
......@@ -385,7 +386,7 @@ static inline int test_and_clear_bit(unsigned long nr,
" xor %2, %3 \n"
" " __SC "%2, %1 \n"
" .set mips0 \n"
: "=&r" (temp), "+m" (*m), "=&r" (res)
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
: "r" (1UL << bit)
: "memory");
} while (unlikely(!res));
......@@ -427,7 +428,7 @@ static inline int test_and_change_bit(unsigned long nr,
" beqzl %2, 1b \n"
" and %2, %0, %3 \n"
" .set mips0 \n"
: "=&r" (temp), "+m" (*m), "=&r" (res)
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
: "r" (1UL << bit)
: "memory");
} else if (kernel_uses_llsc) {
......@@ -441,7 +442,7 @@ static inline int test_and_change_bit(unsigned long nr,
" xor %2, %0, %3 \n"
" " __SC "\t%2, %1 \n"
" .set mips0 \n"
: "=&r" (temp), "+m" (*m), "=&r" (res)
: "=&r" (temp), "+" GCC_OFF12_ASM() (*m), "=&r" (res)
: "r" (1UL << bit)
: "memory");
} while (unlikely(!res));
......
......@@ -84,6 +84,7 @@ extern char bmips_smp_int_vec_end;
extern int bmips_smp_enabled;
extern int bmips_cpu_offset;
extern cpumask_t bmips_booted_mask;
extern unsigned long bmips_tp1_irqs;
extern void bmips_ebase_setup(void);
extern asmlinkage void plat_wired_tlb_setup(void);
......
......@@ -70,10 +70,7 @@ enum loongson_machine_type {
MACH_DEXXON_GDIUM2F10,
MACH_LEMOTE_NAS,
MACH_LEMOTE_LL2F,
MACH_LEMOTE_A1004,
MACH_LEMOTE_A1101,
MACH_LEMOTE_A1201,
MACH_LEMOTE_A1205,
MACH_LOONGSON_GENERIC,
MACH_LOONGSON_END
};
......@@ -101,16 +98,16 @@ extern unsigned long mips_machtype;
struct boot_mem_map {
int nr_map;
struct boot_mem_map_entry {
phys_t addr; /* start of memory segment */
phys_t size; /* size of memory segment */
phys_addr_t addr; /* start of memory segment */
phys_addr_t size; /* size of memory segment */
long type; /* type of memory segment */
} map[BOOT_MEM_MAP_MAX];
};
extern struct boot_mem_map boot_mem_map;
extern void add_memory_region(phys_t start, phys_t size, long type);
extern void detect_memory_region(phys_t start, phys_t sz_min, phys_t sz_max);
extern void add_memory_region(phys_addr_t start, phys_addr_t size, long type);
extern void detect_memory_region(phys_addr_t start, phys_addr_t sz_min, phys_addr_t sz_max);
extern void prom_init(void);
extern void prom_free_prom_memory(void);
......
......@@ -35,9 +35,6 @@ struct clk {
#define CLK_ALWAYS_ENABLED (1 << 0)
#define CLK_RATE_PROPAGATES (1 << 1)
/* Should be defined by processor-specific code */
void arch_init_clk_ops(struct clk_ops **, int type);
int clk_init(void);
int __clk_enable(struct clk *);
......
......@@ -10,6 +10,7 @@
#include <linux/bug.h>
#include <linux/irqflags.h>
#include <asm/compiler.h>
#include <asm/war.h>
static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
......@@ -30,8 +31,8 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
" sc %2, %1 \n"
" beqzl %2, 1b \n"
" .set mips0 \n"
: "=&r" (retval), "=m" (*m), "=&r" (dummy)
: "R" (*m), "Jr" (val)
: "=&r" (retval), "=" GCC_OFF12_ASM() (*m), "=&r" (dummy)
: GCC_OFF12_ASM() (*m), "Jr" (val)
: "memory");
} else if (kernel_uses_llsc) {
unsigned long dummy;
......@@ -45,8 +46,9 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val)
" .set arch=r4000 \n"
" sc %2, %1 \n"
" .set mips0 \n"
: "=&r" (retval), "=m" (*m), "=&r" (dummy)
: "R" (*m), "Jr" (val)
: "=&r" (retval), "=" GCC_OFF12_ASM() (*m),
"=&r" (dummy)
: GCC_OFF12_ASM() (*m), "Jr" (val)
: "memory");
} while (unlikely(!dummy));
} else {
......@@ -80,8 +82,8 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
" scd %2, %1 \n"
" beqzl %2, 1b \n"
" .set mips0 \n"
: "=&r" (retval), "=m" (*m), "=&r" (dummy)
: "R" (*m), "Jr" (val)
: "=&r" (retval), "=" GCC_OFF12_ASM() (*m), "=&r" (dummy)
: GCC_OFF12_ASM() (*m), "Jr" (val)
: "memory");
} else if (kernel_uses_llsc) {
unsigned long dummy;
......@@ -93,8 +95,9 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val)
" move %2, %z4 \n"
" scd %2, %1 \n"
" .set mips0 \n"
: "=&r" (retval), "=m" (*m), "=&r" (dummy)
: "R" (*m), "Jr" (val)
: "=&r" (retval), "=" GCC_OFF12_ASM() (*m),
"=&r" (dummy)
: GCC_OFF12_ASM() (*m), "Jr" (val)
: "memory");
} while (unlikely(!dummy));
} else {
......@@ -155,8 +158,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
" beqzl $1, 1b \n" \
"2: \n" \
" .set pop \n" \
: "=&r" (__ret), "=R" (*m) \
: "R" (*m), "Jr" (old), "Jr" (new) \
: "=&r" (__ret), "=" GCC_OFF12_ASM() (*m) \
: GCC_OFF12_ASM() (*m), "Jr" (old), "Jr" (new) \
: "memory"); \
} else if (kernel_uses_llsc) { \
__asm__ __volatile__( \
......@@ -172,8 +175,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
" beqz $1, 1b \n" \
" .set pop \n" \
"2: \n" \
: "=&r" (__ret), "=R" (*m) \
: "R" (*m), "Jr" (old), "Jr" (new) \
: "=&r" (__ret), "=" GCC_OFF12_ASM() (*m) \
: GCC_OFF12_ASM() (*m), "Jr" (old), "Jr" (new) \
: "memory"); \
} else { \
unsigned long __flags; \
......
......@@ -16,4 +16,12 @@
#define GCC_REG_ACCUM "accum"
#endif
#ifndef CONFIG_CPU_MICROMIPS
#define GCC_OFF12_ASM() "R"
#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
#define GCC_OFF12_ASM() "ZC"
#else
#error "microMIPS compilation unsupported with GCC older than 4.9"
#endif
#endif /* _ASM_COMPILER_H */
......@@ -344,4 +344,8 @@
# define cpu_has_msa 0
#endif
#ifndef cpu_has_fre
# define cpu_has_fre (cpu_data[0].options & MIPS_CPU_FRE)
#endif
#endif /* __ASM_CPU_FEATURES_H */
......@@ -142,6 +142,7 @@
#define PRID_IMP_BMIPS3300_BUG 0x0000
#define PRID_IMP_BMIPS43XX 0xa000
#define PRID_IMP_BMIPS5000 0x5a00
#define PRID_IMP_BMIPS5200 0x5b00
#define PRID_REV_BMIPS4380_LO 0x0040
#define PRID_REV_BMIPS4380_HI 0x006f
......@@ -368,6 +369,7 @@ enum cpu_type_enum {
#define MIPS_CPU_HTW 0x100000000ull /* CPU support Hardware Page Table Walker */
#define MIPS_CPU_RIXIEX 0x200000000ull /* CPU has unique exception codes for {Read, Execute}-Inhibit exceptions */
#define MIPS_CPU_MAAR 0x400000000ull /* MAAR(I) registers are present */
#define MIPS_CPU_FRE 0x800000000ull /* FRE & UFE bits implemented */
/*
* CPU ASE encodings
......
#ifndef ASM_EDAC_H
#define ASM_EDAC_H
#include <asm/compiler.h>
/* ECC atomic, DMA, SMP and interrupt safe scrub function */
static inline void atomic_scrub(void *va, u32 size)
......@@ -24,8 +26,8 @@ static inline void atomic_scrub(void *va, u32 size)
" sc %0, %1 \n"
" beqz %0, 1b \n"
" .set mips0 \n"
: "=&r" (temp), "=m" (*virt_addr)
: "m" (*virt_addr));
: "=&r" (temp), "=" GCC_OFF12_ASM() (*virt_addr)
: GCC_OFF12_ASM() (*virt_addr));
virt_addr++;
}
......
......@@ -8,6 +8,8 @@
#ifndef _ASM_ELF_H
#define _ASM_ELF_H
#include <linux/fs.h>
#include <uapi/linux/elf.h>
/* ELF header e_flags defines. */
/* MIPS architecture level. */
......@@ -28,6 +30,7 @@
#define PT_MIPS_REGINFO 0x70000000
#define PT_MIPS_RTPROC 0x70000001
#define PT_MIPS_OPTIONS 0x70000002
#define PT_MIPS_ABIFLAGS 0x70000003
/* Flags in the e_flags field of the header */
#define EF_MIPS_NOREORDER 0x00000001
......@@ -174,6 +177,30 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG];
typedef double elf_fpreg_t;
typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
struct mips_elf_abiflags_v0 {
uint16_t version; /* Version of flags structure */
uint8_t isa_level; /* The level of the ISA: 1-5, 32, 64 */
uint8_t isa_rev; /* The revision of ISA: 0 for MIPS V and below,
1-n otherwise */
uint8_t gpr_size; /* The size of general purpose registers */
uint8_t cpr1_size; /* The size of co-processor 1 registers */
uint8_t cpr2_size; /* The size of co-processor 2 registers */
uint8_t fp_abi; /* The floating-point ABI */
uint32_t isa_ext; /* Mask of processor-specific extensions */
uint32_t ases; /* Mask of ASEs used */
uint32_t flags1; /* Mask of general flags */
uint32_t flags2;
};
#define MIPS_ABI_FP_ANY 0 /* FP ABI doesn't matter */
#define MIPS_ABI_FP_DOUBLE 1 /* -mdouble-float */
#define MIPS_ABI_FP_SINGLE 2 /* -msingle-float */
#define MIPS_ABI_FP_SOFT 3 /* -msoft-float */
#define MIPS_ABI_FP_OLD_64 4 /* -mips32r2 -mfp64 */
#define MIPS_ABI_FP_XX 5 /* -mfpxx */
#define MIPS_ABI_FP_64 6 /* -mips32r2 -mfp64 */
#define MIPS_ABI_FP_64A 7 /* -mips32r2 -mfp64 -mno-odd-spreg */
#ifdef CONFIG_32BIT
/*
......@@ -262,16 +289,13 @@ extern struct mips_abi mips_abi_n32;
#ifdef CONFIG_32BIT
#define SET_PERSONALITY(ex) \
#define SET_PERSONALITY2(ex, state) \
do { \
if ((ex).e_flags & EF_MIPS_FP64) \
clear_thread_flag(TIF_32BIT_FPREGS); \
else \
set_thread_flag(TIF_32BIT_FPREGS); \
\
if (personality(current->personality) != PER_LINUX) \
set_personality(PER_LINUX); \
\
mips_set_personality_fp(state); \
\
current->thread.abi = &mips_abi; \
} while (0)
......@@ -291,44 +315,44 @@ do { \
#endif
#ifdef CONFIG_MIPS32_O32
#define __SET_PERSONALITY32_O32(ex) \
#define __SET_PERSONALITY32_O32(ex, state) \
do { \
set_thread_flag(TIF_32BIT_REGS); \
set_thread_flag(TIF_32BIT_ADDR); \
\
if (!((ex).e_flags & EF_MIPS_FP64)) \
set_thread_flag(TIF_32BIT_FPREGS); \
mips_set_personality_fp(state); \
\
current->thread.abi = &mips_abi_32; \
} while (0)
#else
#define __SET_PERSONALITY32_O32(ex) \
#define __SET_PERSONALITY32_O32(ex, state) \
do { } while (0)
#endif
#ifdef CONFIG_MIPS32_COMPAT
#define __SET_PERSONALITY32(ex) \
#define __SET_PERSONALITY32(ex, state) \
do { \
if ((((ex).e_flags & EF_MIPS_ABI2) != 0) && \
((ex).e_flags & EF_MIPS_ABI) == 0) \
__SET_PERSONALITY32_N32(); \
else \
__SET_PERSONALITY32_O32(ex); \
__SET_PERSONALITY32_O32(ex, state); \
} while (0)
#else
#define __SET_PERSONALITY32(ex) do { } while (0)
#define __SET_PERSONALITY32(ex, state) do { } while (0)
#endif
#define SET_PERSONALITY(ex) \
#define SET_PERSONALITY2(ex, state) \
do { \
unsigned int p; \
\
clear_thread_flag(TIF_32BIT_REGS); \
clear_thread_flag(TIF_32BIT_FPREGS); \
clear_thread_flag(TIF_HYBRID_FPREGS); \
clear_thread_flag(TIF_32BIT_ADDR); \
\
if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
__SET_PERSONALITY32(ex); \
__SET_PERSONALITY32(ex, state); \
else \
current->thread.abi = &mips_abi; \
\
......@@ -390,4 +414,24 @@ struct mm_struct;
extern unsigned long arch_randomize_brk(struct mm_struct *mm);
#define arch_randomize_brk arch_randomize_brk
struct arch_elf_state {
int fp_abi;
int interp_fp_abi;
int overall_abi;
};
#define INIT_ARCH_ELF_STATE { \
.fp_abi = -1, \
.interp_fp_abi = -1, \
.overall_abi = -1, \
}
extern int arch_elf_pt_proc(void *ehdr, void *phdr, struct file *elf,
bool is_interp, struct arch_elf_state *state);
extern int arch_check_elf(void *ehdr, bool has_interpreter,
struct arch_elf_state *state);
extern void mips_set_personality_fp(struct arch_elf_state *state);
#endif /* _ASM_ELF_H */
......@@ -36,14 +36,16 @@ extern void _restore_fp(struct task_struct *);
/*
* This enum specifies a mode in which we want the FPU to operate, for cores
* which implement the Status.FR bit. Note that FPU_32BIT & FPU_64BIT
* purposefully have the values 0 & 1 respectively, so that an integer value
* of Status.FR can be trivially casted to the corresponding enum fpu_mode.
* which implement the Status.FR bit. Note that the bottom bit of the value
* purposefully matches the desired value of the Status.FR bit.
*/
enum fpu_mode {
FPU_32BIT = 0, /* FR = 0 */
FPU_64BIT, /* FR = 1 */
FPU_64BIT, /* FR = 1, FRE = 0 */
FPU_AS_IS,
FPU_HYBRID, /* FR = 1, FRE = 1 */
#define FPU_FR_MASK 0x1
};
static inline int __enable_fpu(enum fpu_mode mode)
......@@ -57,6 +59,14 @@ static inline int __enable_fpu(enum fpu_mode mode)
enable_fpu_hazard();
return 0;
case FPU_HYBRID:
if (!cpu_has_fre)
return SIGFPE;
/* set FRE */
write_c0_config5(read_c0_config5() | MIPS_CONF5_FRE);
goto fr_common;
case FPU_64BIT:
#if !(defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_64BIT))
/* we only have a 32-bit FPU */
......@@ -64,8 +74,11 @@ static inline int __enable_fpu(enum fpu_mode mode)
#endif
/* fall through */
case FPU_32BIT:
/* clear FRE */
write_c0_config5(read_c0_config5() & ~MIPS_CONF5_FRE);
fr_common:
/* set CU1 & change FR appropriately */
fr = (int)mode;
fr = (int)mode & FPU_FR_MASK;
change_c0_status(ST0_CU1 | ST0_FR, ST0_CU1 | (fr ? ST0_FR : 0));
enable_fpu_hazard();
......@@ -102,13 +115,17 @@ static inline int __own_fpu(void)
enum fpu_mode mode;
int ret;
mode = !test_thread_flag(TIF_32BIT_FPREGS);
if (test_thread_flag(TIF_HYBRID_FPREGS))
mode = FPU_HYBRID;
else
mode = !test_thread_flag(TIF_32BIT_FPREGS);
ret = __enable_fpu(mode);
if (ret)
return ret;
KSTK_STATUS(current) |= ST0_CU1;
if (mode == FPU_64BIT)
if (mode == FPU_64BIT || mode == FPU_HYBRID)
KSTK_STATUS(current) |= ST0_FR;
else /* mode == FPU_32BIT */
KSTK_STATUS(current) &= ~ST0_FR;
......@@ -166,8 +183,24 @@ static inline int init_fpu(void)
if (cpu_has_fpu) {
ret = __own_fpu();
if (!ret)
if (!ret) {
unsigned int config5 = read_c0_config5();
/*
* Ensure FRE is clear whilst running _init_fpu, since
* single precision FP instructions are used. If FRE
* was set then we'll just end up initialising all 32
* 64b registers.
*/
write_c0_config5(config5 & ~MIPS_CONF5_FRE);
enable_fpu_hazard();
_init_fpu();
/* Restore FRE */
write_c0_config5(config5);
enable_fpu_hazard();
}
} else
fpu_emulator_init_fpu();
......
......@@ -14,6 +14,7 @@
#include <linux/uaccess.h>
#include <asm/asm-eva.h>
#include <asm/barrier.h>
#include <asm/compiler.h>
#include <asm/errno.h>
#include <asm/war.h>
......@@ -32,6 +33,7 @@
" beqzl $1, 1b \n" \
__WEAK_LLSC_MB \
"3: \n" \
" .insn \n" \
" .set pop \n" \
" .set mips0 \n" \
" .section .fixup,\"ax\" \n" \
......@@ -42,8 +44,10 @@
" "__UA_ADDR "\t1b, 4b \n" \
" "__UA_ADDR "\t2b, 4b \n" \
" .previous \n" \
: "=r" (ret), "=&r" (oldval), "=R" (*uaddr) \
: "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT) \
: "=r" (ret), "=&r" (oldval), \
"=" GCC_OFF12_ASM() (*uaddr) \
: "0" (0), GCC_OFF12_ASM() (*uaddr), "Jr" (oparg), \
"i" (-EFAULT) \
: "memory"); \
} else if (cpu_has_llsc) { \
__asm__ __volatile__( \
......@@ -58,6 +62,7 @@
" beqz $1, 1b \n" \
__WEAK_LLSC_MB \
"3: \n" \
" .insn \n" \
" .set pop \n" \
" .set mips0 \n" \
" .section .fixup,\"ax\" \n" \
......@@ -68,8 +73,10 @@
" "__UA_ADDR "\t1b, 4b \n" \
" "__UA_ADDR "\t2b, 4b \n" \
" .previous \n" \
: "=r" (ret), "=&r" (oldval), "=R" (*uaddr) \
: "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT) \
: "=r" (ret), "=&r" (oldval), \
"=" GCC_OFF12_ASM() (*uaddr) \
: "0" (0), GCC_OFF12_ASM() (*uaddr), "Jr" (oparg), \
"i" (-EFAULT) \
: "memory"); \
} else \
ret = -ENOSYS; \
......@@ -157,6 +164,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
" beqzl $1, 1b \n"
__WEAK_LLSC_MB
"3: \n"
" .insn \n"
" .set pop \n"
" .section .fixup,\"ax\" \n"
"4: li %0, %6 \n"
......@@ -166,8 +174,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
" "__UA_ADDR "\t1b, 4b \n"
" "__UA_ADDR "\t2b, 4b \n"
" .previous \n"
: "+r" (ret), "=&r" (val), "=R" (*uaddr)
: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
: "+r" (ret), "=&r" (val), "=" GCC_OFF12_ASM() (*uaddr)
: GCC_OFF12_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
"i" (-EFAULT)
: "memory");
} else if (cpu_has_llsc) {
__asm__ __volatile__(
......@@ -184,6 +193,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
" beqz $1, 1b \n"
__WEAK_LLSC_MB
"3: \n"
" .insn \n"
" .set pop \n"
" .section .fixup,\"ax\" \n"
"4: li %0, %6 \n"
......@@ -193,8 +203,9 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
" "__UA_ADDR "\t1b, 4b \n"
" "__UA_ADDR "\t2b, 4b \n"
" .previous \n"
: "+r" (ret), "=&r" (val), "=R" (*uaddr)
: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
: "+r" (ret), "=&r" (val), "=" GCC_OFF12_ASM() (*uaddr)
: GCC_OFF12_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
"i" (-EFAULT)
: "memory");
} else
return -ENOSYS;
......
#ifndef _ASM_HPET_H
#define _ASM_HPET_H
#ifdef CONFIG_RS780_HPET
#define HPET_MMAP_SIZE 1024
#define HPET_ID 0x000
#define HPET_PERIOD 0x004
#define HPET_CFG 0x010
#define HPET_STATUS 0x020
#define HPET_COUNTER 0x0f0
#define HPET_Tn_CFG(n) (0x100 + 0x20 * n)
#define HPET_Tn_CMP(n) (0x108 + 0x20 * n)
#define HPET_Tn_ROUTE(n) (0x110 + 0x20 * n)
#define HPET_T0_IRS 0x001
#define HPET_T1_IRS 0x002
#define HPET_T3_IRS 0x004
#define HPET_T0_CFG 0x100
#define HPET_T0_CMP 0x108
#define HPET_T0_ROUTE 0x110
#define HPET_T1_CFG 0x120
#define HPET_T1_CMP 0x128
#define HPET_T1_ROUTE 0x130
#define HPET_T2_CFG 0x140
#define HPET_T2_CMP 0x148
#define HPET_T2_ROUTE 0x150
#define HPET_ID_REV 0x000000ff
#define HPET_ID_NUMBER 0x00001f00
#define HPET_ID_64BIT 0x00002000
#define HPET_ID_LEGSUP 0x00008000
#define HPET_ID_VENDOR 0xffff0000
#define HPET_ID_NUMBER_SHIFT 8
#define HPET_ID_VENDOR_SHIFT 16
#define HPET_CFG_ENABLE 0x001
#define HPET_CFG_LEGACY 0x002
#define HPET_LEGACY_8254 2
#define HPET_LEGACY_RTC 8
#define HPET_TN_LEVEL 0x0002
#define HPET_TN_ENABLE 0x0004
#define HPET_TN_PERIODIC 0x0008
#define HPET_TN_PERIODIC_CAP 0x0010
#define HPET_TN_64BIT_CAP 0x0020
#define HPET_TN_SETVAL 0x0040
#define HPET_TN_32BIT 0x0100
#define HPET_TN_ROUTE 0x3e00
#define HPET_TN_FSB 0x4000
#define HPET_TN_FSB_CAP 0x8000
#define HPET_TN_ROUTE_SHIFT 9
/* Max HPET Period is 10^8 femto sec as in HPET spec */
#define HPET_MAX_PERIOD 100000000UL
/*
* Min HPET period is 10^5 femto sec just for safety. If it is less than this,
* then 32 bit HPET counter wrapsaround in less than 0.5 sec.
*/
#define HPET_MIN_PERIOD 100000UL
#define HPET_ADDR 0x20000
#define HPET_MMIO_ADDR 0x90000e0000020000
#define HPET_FREQ 14318780
#define HPET_COMPARE_VAL ((HPET_FREQ + HZ / 2) / HZ)
#define HPET_T0_IRQ 0
extern void __init setup_hpet_timer(void);
#endif /* CONFIG_RS780_HPET */
#endif /* _ASM_HPET_H */
......@@ -167,7 +167,7 @@ static inline void * isa_bus_to_virt(unsigned long address)
*/
#define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
extern void __iomem * __ioremap(phys_t offset, phys_t size, unsigned long flags);
extern void __iomem * __ioremap(phys_addr_t offset, phys_addr_t size, unsigned long flags);
extern void __iounmap(const volatile void __iomem *addr);
#ifndef CONFIG_PCI
......@@ -175,7 +175,7 @@ struct pci_dev;
static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {}
#endif
static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size,
static inline void __iomem * __ioremap_mode(phys_addr_t offset, unsigned long size,
unsigned long flags)
{
void __iomem *addr = plat_ioremap(offset, size, flags);
......@@ -183,7 +183,7 @@ static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size,
if (addr)
return addr;
#define __IS_LOW512(addr) (!((phys_t)(addr) & (phys_t) ~0x1fffffffULL))
#define __IS_LOW512(addr) (!((phys_addr_t)(addr) & (phys_addr_t) ~0x1fffffffULL))
if (cpu_has_64bit_addresses) {
u64 base = UNCAC_BASE;
......@@ -197,7 +197,7 @@ static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size,
return (void __iomem *) (unsigned long) (base + offset);
} else if (__builtin_constant_p(offset) &&
__builtin_constant_p(size) && __builtin_constant_p(flags)) {
phys_t phys_addr, last_addr;
phys_addr_t phys_addr, last_addr;
phys_addr = fixup_bigphys_addr(offset, size);
......
......@@ -48,4 +48,7 @@ extern int cp0_compare_irq;
extern int cp0_compare_irq_shift;
extern int cp0_perfcount_irq;
void arch_trigger_all_cpu_backtrace(bool);
#define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace
#endif /* _ASM_IRQ_H */
......@@ -19,8 +19,8 @@ extern void rm9k_cpu_irq_init(void);
#ifdef CONFIG_IRQ_DOMAIN
struct device_node;
extern int mips_cpu_intc_init(struct device_node *of_node,
struct device_node *parent);
extern int mips_cpu_irq_of_init(struct device_node *of_node,
struct device_node *parent);
#endif
#endif /* _ASM_IRQ_CPU_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#ifndef __ASM_MACH_ATH25_GPIO_H
#define __ASM_MACH_ATH25_GPIO_H
#include <asm-generic/gpio.h>
#define gpio_get_value __gpio_get_value
#define gpio_set_value __gpio_set_value
#define gpio_cansleep __gpio_cansleep
#define gpio_to_irq __gpio_to_irq
static inline int irq_to_gpio(unsigned irq)
{
return -EINVAL;
}
#endif /* __ASM_MACH_ATH25_GPIO_H */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -15,12 +15,12 @@
* Allow physical addresses to be fixed up to help peripherals located
* outside the low 32-bit range -- generic pass-through version.
*/
static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
static inline phys_addr_t fixup_bigphys_addr(phys_addr_t phys_addr, phys_addr_t size)
{
return phys_addr;
}
static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
static inline void __iomem *plat_ioremap(phys_addr_t offset, unsigned long size,
unsigned long flags)
{
return NULL;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment