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
  ...
This commit is contained in:
Linus Torvalds 2014-12-11 17:56:37 -08:00
commit c0222ac086
289 changed files with 9838 additions and 3446 deletions

View file

@ -0,0 +1,55 @@
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>;
...
};

View file

@ -0,0 +1,37 @@
* 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>;
};

View file

@ -0,0 +1,8 @@
* 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.

View file

@ -0,0 +1,11 @@
* Broadcom cable/DSL platforms
SoCs:
Required properties:
- compatible: "brcm,bcm3384", "brcm,bcm33843"
Boards:
Required properties:
- compatible: "brcm,bcm93384wvg"

View file

@ -0,0 +1,11 @@
* 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

View file

@ -1,6 +1,6 @@
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 },
{},
};

View file

@ -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.

View file

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

View file

@ -2,7 +2,9 @@
platforms += alchemy
platforms += ar7
platforms += ath25
platforms += ath79
platforms += bcm3384
platforms += bcm47xx
platforms += bcm63xx
platforms += cavium-octeon

View file

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

View file

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

View file

@ -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'

View file

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

View file

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

View file

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

16
arch/mips/ath25/Kconfig Normal file
View file

@ -0,0 +1,16 @@
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

16
arch/mips/ath25/Makefile Normal file
View file

@ -0,0 +1,16 @@
#
# 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

6
arch/mips/ath25/Platform Normal file
View file

@ -0,0 +1,6 @@
#
# Atheros AR531X/AR231X WiSoC
#
platform-$(CONFIG_ATH25) += ath25/
cflags-$(CONFIG_ATH25) += -I$(srctree)/arch/mips/include/asm/mach-ath25
load-$(CONFIG_ATH25) += 0xffffffff80041000

364
arch/mips/ath25/ar2315.c Normal file
View file

@ -0,0 +1,364 @@
/*
* 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
}

22
arch/mips/ath25/ar2315.h Normal file
View file

@ -0,0 +1,22 @@
#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 */

View file

@ -0,0 +1,410 @@
/*
* Register definitions for AR2315+
*
* 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-2008 Felix Fietkau <nbd@openwrt.org>
*/
#ifndef __ASM_MACH_ATH25_AR2315_REGS_H
#define __ASM_MACH_ATH25_AR2315_REGS_H
/*
* IRQs
*/
#define AR2315_IRQ_MISC (MIPS_CPU_IRQ_BASE + 2) /* C0_CAUSE: 0x0400 */
#define AR2315_IRQ_WLAN0 (MIPS_CPU_IRQ_BASE + 3) /* C0_CAUSE: 0x0800 */
#define AR2315_IRQ_ENET0 (MIPS_CPU_IRQ_BASE + 4) /* C0_CAUSE: 0x1000 */
#define AR2315_IRQ_LCBUS_PCI (MIPS_CPU_IRQ_BASE + 5) /* C0_CAUSE: 0x2000 */
#define AR2315_IRQ_WLAN0_POLL (MIPS_CPU_IRQ_BASE + 6) /* C0_CAUSE: 0x4000 */
/*
* Miscellaneous interrupts, which share IP2.
*/
#define AR2315_MISC_IRQ_UART0 0
#define AR2315_MISC_IRQ_I2C_RSVD 1
#define AR2315_MISC_IRQ_SPI 2
#define AR2315_MISC_IRQ_AHB 3
#define AR2315_MISC_IRQ_APB 4
#define AR2315_MISC_IRQ_TIMER 5
#define AR2315_MISC_IRQ_GPIO 6
#define AR2315_MISC_IRQ_WATCHDOG 7
#define AR2315_MISC_IRQ_IR_RSVD 8
#define AR2315_MISC_IRQ_COUNT 9
/*
* Address map
*/
#define AR2315_SPI_READ_BASE 0x08000000 /* SPI flash */
#define AR2315_SPI_READ_SIZE 0x01000000
#define AR2315_WLAN0_BASE 0x10000000 /* Wireless MMR */
#define AR2315_PCI_BASE 0x10100000 /* PCI MMR */
#define AR2315_PCI_SIZE 0x00001000
#define AR2315_SDRAMCTL_BASE 0x10300000 /* SDRAM MMR */
#define AR2315_SDRAMCTL_SIZE 0x00000020
#define AR2315_LOCAL_BASE 0x10400000 /* Local bus MMR */
#define AR2315_ENET0_BASE 0x10500000 /* Ethernet MMR */
#define AR2315_RST_BASE 0x11000000 /* Reset control MMR */
#define AR2315_RST_SIZE 0x00000100
#define AR2315_UART0_BASE 0x11100000 /* UART MMR */
#define AR2315_SPI_MMR_BASE 0x11300000 /* SPI flash MMR */
#define AR2315_SPI_MMR_SIZE 0x00000010
#define AR2315_PCI_EXT_BASE 0x80000000 /* PCI external */
#define AR2315_PCI_EXT_SIZE 0x40000000
/*
* Configuration registers
*/
/* Cold reset register */
#define AR2315_COLD_RESET 0x0000
#define AR2315_RESET_COLD_AHB 0x00000001
#define AR2315_RESET_COLD_APB 0x00000002
#define AR2315_RESET_COLD_CPU 0x00000004
#define AR2315_RESET_COLD_CPUWARM 0x00000008
#define AR2315_RESET_SYSTEM (RESET_COLD_CPU |\
RESET_COLD_APB |\
RESET_COLD_AHB) /* full system */
#define AR2317_RESET_SYSTEM 0x00000010
/* Reset register */
#define AR2315_RESET 0x0004
#define AR2315_RESET_WARM_WLAN0_MAC 0x00000001 /* warm reset WLAN0 MAC */
#define AR2315_RESET_WARM_WLAN0_BB 0x00000002 /* warm reset WLAN0 BB */
#define AR2315_RESET_MPEGTS_RSVD 0x00000004 /* warm reset MPEG-TS */
#define AR2315_RESET_PCIDMA 0x00000008 /* warm reset PCI ahb/dma */
#define AR2315_RESET_MEMCTL 0x00000010 /* warm reset mem control */
#define AR2315_RESET_LOCAL 0x00000020 /* warm reset local bus */
#define AR2315_RESET_I2C_RSVD 0x00000040 /* warm reset I2C bus */
#define AR2315_RESET_SPI 0x00000080 /* warm reset SPI iface */
#define AR2315_RESET_UART0 0x00000100 /* warm reset UART0 */
#define AR2315_RESET_IR_RSVD 0x00000200 /* warm reset IR iface */
#define AR2315_RESET_EPHY0 0x00000400 /* cold reset ENET0 phy */
#define AR2315_RESET_ENET0 0x00000800 /* cold reset ENET0 MAC */
/* AHB master arbitration control */
#define AR2315_AHB_ARB_CTL 0x0008
#define AR2315_ARB_CPU 0x00000001 /* CPU, default */
#define AR2315_ARB_WLAN 0x00000002 /* WLAN */
#define AR2315_ARB_MPEGTS_RSVD 0x00000004 /* MPEG-TS */
#define AR2315_ARB_LOCAL 0x00000008 /* Local bus */
#define AR2315_ARB_PCI 0x00000010 /* PCI bus */
#define AR2315_ARB_ETHERNET 0x00000020 /* Ethernet */
#define AR2315_ARB_RETRY 0x00000100 /* Retry policy (debug) */
/* Config Register */
#define AR2315_ENDIAN_CTL 0x000c
#define AR2315_CONFIG_AHB 0x00000001 /* EC-AHB bridge endian */
#define AR2315_CONFIG_WLAN 0x00000002 /* WLAN byteswap */
#define AR2315_CONFIG_MPEGTS_RSVD 0x00000004 /* MPEG-TS byteswap */
#define AR2315_CONFIG_PCI 0x00000008 /* PCI byteswap */
#define AR2315_CONFIG_MEMCTL 0x00000010 /* Mem controller endian */
#define AR2315_CONFIG_LOCAL 0x00000020 /* Local bus byteswap */
#define AR2315_CONFIG_ETHERNET 0x00000040 /* Ethernet byteswap */
#define AR2315_CONFIG_MERGE 0x00000200 /* CPU write buffer merge */
#define AR2315_CONFIG_CPU 0x00000400 /* CPU big endian */
#define AR2315_CONFIG_BIG 0x00000400
#define AR2315_CONFIG_PCIAHB 0x00000800
#define AR2315_CONFIG_PCIAHB_BRIDGE 0x00001000
#define AR2315_CONFIG_SPI 0x00008000 /* SPI byteswap */
#define AR2315_CONFIG_CPU_DRAM 0x00010000
#define AR2315_CONFIG_CPU_PCI 0x00020000
#define AR2315_CONFIG_CPU_MMR 0x00040000
/* NMI control */
#define AR2315_NMI_CTL 0x0010
#define AR2315_NMI_EN 1
/* Revision Register - Initial value is 0x3010 (WMAC 3.0, AR231X 1.0). */
#define AR2315_SREV 0x0014
#define AR2315_REV_MAJ 0x000000f0
#define AR2315_REV_MAJ_S 4
#define AR2315_REV_MIN 0x0000000f
#define AR2315_REV_MIN_S 0
#define AR2315_REV_CHIP (AR2315_REV_MAJ | AR2315_REV_MIN)
/* Interface Enable */
#define AR2315_IF_CTL 0x0018
#define AR2315_IF_MASK 0x00000007
#define AR2315_IF_DISABLED 0 /* Disable all */
#define AR2315_IF_PCI 1 /* PCI */
#define AR2315_IF_TS_LOCAL 2 /* Local bus */
#define AR2315_IF_ALL 3 /* Emulation only */
#define AR2315_IF_LOCAL_HOST 0x00000008
#define AR2315_IF_PCI_HOST 0x00000010
#define AR2315_IF_PCI_INTR 0x00000020
#define AR2315_IF_PCI_CLK_MASK 0x00030000
#define AR2315_IF_PCI_CLK_INPUT 0
#define AR2315_IF_PCI_CLK_OUTPUT_LOW 1
#define AR2315_IF_PCI_CLK_OUTPUT_CLK 2
#define AR2315_IF_PCI_CLK_OUTPUT_HIGH 3
#define AR2315_IF_PCI_CLK_SHIFT 16
/* APB Interrupt control */
#define AR2315_ISR 0x0020
#define AR2315_IMR 0x0024
#define AR2315_GISR 0x0028
#define AR2315_ISR_UART0 0x00000001 /* high speed UART */
#define AR2315_ISR_I2C_RSVD 0x00000002 /* I2C bus */
#define AR2315_ISR_SPI 0x00000004 /* SPI bus */
#define AR2315_ISR_AHB 0x00000008 /* AHB error */
#define AR2315_ISR_APB 0x00000010 /* APB error */
#define AR2315_ISR_TIMER 0x00000020 /* Timer */
#define AR2315_ISR_GPIO 0x00000040 /* GPIO */
#define AR2315_ISR_WD 0x00000080 /* Watchdog */
#define AR2315_ISR_IR_RSVD 0x00000100 /* IR */
#define AR2315_GISR_MISC 0x00000001 /* Misc */
#define AR2315_GISR_WLAN0 0x00000002 /* WLAN0 */
#define AR2315_GISR_MPEGTS_RSVD 0x00000004 /* MPEG-TS */
#define AR2315_GISR_LOCALPCI 0x00000008 /* Local/PCI bus */
#define AR2315_GISR_WMACPOLL 0x00000010
#define AR2315_GISR_TIMER 0x00000020
#define AR2315_GISR_ETHERNET 0x00000040 /* Ethernet */
/* Generic timer */
#define AR2315_TIMER 0x0030
#define AR2315_RELOAD 0x0034
/* Watchdog timer */
#define AR2315_WDT_TIMER 0x0038
#define AR2315_WDT_CTRL 0x003c
#define AR2315_WDT_CTRL_IGNORE 0x00000000 /* ignore expiration */
#define AR2315_WDT_CTRL_NMI 0x00000001 /* NMI on watchdog */
#define AR2315_WDT_CTRL_RESET 0x00000002 /* reset on watchdog */
/* CPU Performance Counters */
#define AR2315_PERFCNT0 0x0048
#define AR2315_PERFCNT1 0x004c
#define AR2315_PERF0_DATAHIT 0x00000001 /* Count Data Cache Hits */
#define AR2315_PERF0_DATAMISS 0x00000002 /* Count Data Cache Misses */
#define AR2315_PERF0_INSTHIT 0x00000004 /* Count Instruction Cache Hits */
#define AR2315_PERF0_INSTMISS 0x00000008 /* Count Instruction Cache Misses */
#define AR2315_PERF0_ACTIVE 0x00000010 /* Count Active Processor Cycles */
#define AR2315_PERF0_WBHIT 0x00000020 /* Count CPU Write Buffer Hits */
#define AR2315_PERF0_WBMISS 0x00000040 /* Count CPU Write Buffer Misses */
#define AR2315_PERF1_EB_ARDY 0x00000001 /* Count EB_ARdy signal */
#define AR2315_PERF1_EB_AVALID 0x00000002 /* Count EB_AValid signal */
#define AR2315_PERF1_EB_WDRDY 0x00000004 /* Count EB_WDRdy signal */
#define AR2315_PERF1_EB_RDVAL 0x00000008 /* Count EB_RdVal signal */
#define AR2315_PERF1_VRADDR 0x00000010 /* Count valid read address cycles*/
#define AR2315_PERF1_VWADDR 0x00000020 /* Count valid write address cycl.*/
#define AR2315_PERF1_VWDATA 0x00000040 /* Count valid write data cycles */
/* AHB Error Reporting */
#define AR2315_AHB_ERR0 0x0050 /* error */
#define AR2315_AHB_ERR1 0x0054 /* haddr */
#define AR2315_AHB_ERR2 0x0058 /* hwdata */
#define AR2315_AHB_ERR3 0x005c /* hrdata */
#define AR2315_AHB_ERR4 0x0060 /* status */
#define AR2315_AHB_ERROR_DET 1 /* AHB Error has been detected, */
/* write 1 to clear all bits in ERR0 */
#define AR2315_AHB_ERROR_OVR 2 /* AHB Error overflow has been detected */
#define AR2315_AHB_ERROR_WDT 4 /* AHB Error due to wdt instead of hresp */
#define AR2315_PROCERR_HMAST 0x0000000f
#define AR2315_PROCERR_HMAST_DFLT 0
#define AR2315_PROCERR_HMAST_WMAC 1
#define AR2315_PROCERR_HMAST_ENET 2
#define AR2315_PROCERR_HMAST_PCIENDPT 3
#define AR2315_PROCERR_HMAST_LOCAL 4
#define AR2315_PROCERR_HMAST_CPU 5
#define AR2315_PROCERR_HMAST_PCITGT 6
#define AR2315_PROCERR_HMAST_S 0
#define AR2315_PROCERR_HWRITE 0x00000010
#define AR2315_PROCERR_HSIZE 0x00000060
#define AR2315_PROCERR_HSIZE_S 5
#define AR2315_PROCERR_HTRANS 0x00000180
#define AR2315_PROCERR_HTRANS_S 7
#define AR2315_PROCERR_HBURST 0x00000e00
#define AR2315_PROCERR_HBURST_S 9
/* Clock Control */
#define AR2315_PLLC_CTL 0x0064
#define AR2315_PLLV_CTL 0x0068
#define AR2315_CPUCLK 0x006c
#define AR2315_AMBACLK 0x0070
#define AR2315_SYNCCLK 0x0074
#define AR2315_DSL_SLEEP_CTL 0x0080
#define AR2315_DSL_SLEEP_DUR 0x0084
/* PLLc Control fields */
#define AR2315_PLLC_REF_DIV_M 0x00000003
#define AR2315_PLLC_REF_DIV_S 0
#define AR2315_PLLC_FDBACK_DIV_M 0x0000007c
#define AR2315_PLLC_FDBACK_DIV_S 2
#define AR2315_PLLC_ADD_FDBACK_DIV_M 0x00000080
#define AR2315_PLLC_ADD_FDBACK_DIV_S 7
#define AR2315_PLLC_CLKC_DIV_M 0x0001c000
#define AR2315_PLLC_CLKC_DIV_S 14
#define AR2315_PLLC_CLKM_DIV_M 0x00700000
#define AR2315_PLLC_CLKM_DIV_S 20
/* CPU CLK Control fields */
#define AR2315_CPUCLK_CLK_SEL_M 0x00000003
#define AR2315_CPUCLK_CLK_SEL_S 0
#define AR2315_CPUCLK_CLK_DIV_M 0x0000000c
#define AR2315_CPUCLK_CLK_DIV_S 2
/* AMBA CLK Control fields */
#define AR2315_AMBACLK_CLK_SEL_M 0x00000003
#define AR2315_AMBACLK_CLK_SEL_S 0
#define AR2315_AMBACLK_CLK_DIV_M 0x0000000c
#define AR2315_AMBACLK_CLK_DIV_S 2
/* PCI Clock Control */
#define AR2315_PCICLK 0x00a4
#define AR2315_PCICLK_INPUT_M 0x00000003
#define AR2315_PCICLK_INPUT_S 0
#define AR2315_PCICLK_PLLC_CLKM 0
#define AR2315_PCICLK_PLLC_CLKM1 1
#define AR2315_PCICLK_PLLC_CLKC 2
#define AR2315_PCICLK_REF_CLK 3
#define AR2315_PCICLK_DIV_M 0x0000000c
#define AR2315_PCICLK_DIV_S 2
#define AR2315_PCICLK_IN_FREQ 0
#define AR2315_PCICLK_IN_FREQ_DIV_6 1
#define AR2315_PCICLK_IN_FREQ_DIV_8 2
#define AR2315_PCICLK_IN_FREQ_DIV_10 3
/* Observation Control Register */
#define AR2315_OCR 0x00b0
#define AR2315_OCR_GPIO0_IRIN 0x00000040
#define AR2315_OCR_GPIO1_IROUT 0x00000080
#define AR2315_OCR_GPIO3_RXCLR 0x00000200
/* General Clock Control */
#define AR2315_MISCCLK 0x00b4
#define AR2315_MISCCLK_PLLBYPASS_EN 0x00000001
#define AR2315_MISCCLK_PROCREFCLK 0x00000002
/*
* SDRAM Controller
* - No read or write buffers are included.
*/
#define AR2315_MEM_CFG 0x0000
#define AR2315_MEM_CTRL 0x000c
#define AR2315_MEM_REF 0x0010
#define AR2315_MEM_CFG_DATA_WIDTH_M 0x00006000
#define AR2315_MEM_CFG_DATA_WIDTH_S 13
#define AR2315_MEM_CFG_COL_WIDTH_M 0x00001e00
#define AR2315_MEM_CFG_COL_WIDTH_S 9
#define AR2315_MEM_CFG_ROW_WIDTH_M 0x000001e0
#define AR2315_MEM_CFG_ROW_WIDTH_S 5
#define AR2315_MEM_CFG_BANKADDR_BITS_M 0x00000018
#define AR2315_MEM_CFG_BANKADDR_BITS_S 3
/*
* Local Bus Interface Registers
*/
#define AR2315_LB_CONFIG 0x0000
#define AR2315_LBCONF_OE 0x00000001 /* =1 OE is low-true */
#define AR2315_LBCONF_CS0 0x00000002 /* =1 first CS is low-true */
#define AR2315_LBCONF_CS1 0x00000004 /* =1 2nd CS is low-true */
#define AR2315_LBCONF_RDY 0x00000008 /* =1 RDY is low-true */
#define AR2315_LBCONF_WE 0x00000010 /* =1 Write En is low-true */
#define AR2315_LBCONF_WAIT 0x00000020 /* =1 WAIT is low-true */
#define AR2315_LBCONF_ADS 0x00000040 /* =1 Adr Strobe is low-true */
#define AR2315_LBCONF_MOT 0x00000080 /* =0 Intel, =1 Motorola */
#define AR2315_LBCONF_8CS 0x00000100 /* =1 8 bits CS, 0= 16bits */
#define AR2315_LBCONF_8DS 0x00000200 /* =1 8 bits Data S, 0=16bits */
#define AR2315_LBCONF_ADS_EN 0x00000400 /* =1 Enable ADS */
#define AR2315_LBCONF_ADR_OE 0x00000800 /* =1 Adr cap on OE, WE or DS */
#define AR2315_LBCONF_ADDT_MUX 0x00001000 /* =1 Adr and Data share bus */
#define AR2315_LBCONF_DATA_OE 0x00002000 /* =1 Data cap on OE, WE, DS */
#define AR2315_LBCONF_16DATA 0x00004000 /* =1 Data is 16 bits wide */
#define AR2315_LBCONF_SWAPDT 0x00008000 /* =1 Byte swap data */
#define AR2315_LBCONF_SYNC 0x00010000 /* =1 Bus synchronous to clk */
#define AR2315_LBCONF_INT 0x00020000 /* =1 Intr is low true */
#define AR2315_LBCONF_INT_CTR0 0x00000000 /* GND high-Z, Vdd is high-Z */
#define AR2315_LBCONF_INT_CTR1 0x00040000 /* GND drive, Vdd is high-Z */
#define AR2315_LBCONF_INT_CTR2 0x00080000 /* GND high-Z, Vdd drive */
#define AR2315_LBCONF_INT_CTR3 0x000c0000 /* GND drive, Vdd drive */
#define AR2315_LBCONF_RDY_WAIT 0x00100000 /* =1 RDY is negative of WAIT */
#define AR2315_LBCONF_INT_PULSE 0x00200000 /* =1 Interrupt is a pulse */
#define AR2315_LBCONF_ENABLE 0x00400000 /* =1 Falcon respond to LB */
#define AR2315_LB_CLKSEL 0x0004
#define AR2315_LBCLK_EXT 0x00000001 /* use external clk for lb */
#define AR2315_LB_1MS 0x0008
#define AR2315_LB1MS_MASK 0x0003ffff /* # of AHB clk cycles in 1ms */
#define AR2315_LB_MISCCFG 0x000c
#define AR2315_LBM_TXD_EN 0x00000001 /* Enable TXD for fragments */
#define AR2315_LBM_RX_INTEN 0x00000002 /* Enable LB ints on RX ready */
#define AR2315_LBM_MBOXWR_INTEN 0x00000004 /* Enable LB ints on mbox wr */
#define AR2315_LBM_MBOXRD_INTEN 0x00000008 /* Enable LB ints on mbox rd */
#define AR2315_LMB_DESCSWAP_EN 0x00000010 /* Byte swap desc enable */
#define AR2315_LBM_TIMEOUT_M 0x00ffff80
#define AR2315_LBM_TIMEOUT_S 7
#define AR2315_LBM_PORTMUX 0x07000000
#define AR2315_LB_RXTSOFF 0x0010
#define AR2315_LB_TX_CHAIN_EN 0x0100
#define AR2315_LB_TXEN_0 0x00000001
#define AR2315_LB_TXEN_1 0x00000002
#define AR2315_LB_TXEN_2 0x00000004
#define AR2315_LB_TXEN_3 0x00000008
#define AR2315_LB_TX_CHAIN_DIS 0x0104
#define AR2315_LB_TX_DESC_PTR 0x0200
#define AR2315_LB_RX_CHAIN_EN 0x0400
#define AR2315_LB_RXEN 0x00000001
#define AR2315_LB_RX_CHAIN_DIS 0x0404
#define AR2315_LB_RX_DESC_PTR 0x0408
#define AR2315_LB_INT_STATUS 0x0500
#define AR2315_LB_INT_TX_DESC 0x00000001
#define AR2315_LB_INT_TX_OK 0x00000002
#define AR2315_LB_INT_TX_ERR 0x00000004
#define AR2315_LB_INT_TX_EOF 0x00000008
#define AR2315_LB_INT_RX_DESC 0x00000010
#define AR2315_LB_INT_RX_OK 0x00000020
#define AR2315_LB_INT_RX_ERR 0x00000040
#define AR2315_LB_INT_RX_EOF 0x00000080
#define AR2315_LB_INT_TX_TRUNC 0x00000100
#define AR2315_LB_INT_TX_STARVE 0x00000200
#define AR2315_LB_INT_LB_TIMEOUT 0x00000400
#define AR2315_LB_INT_LB_ERR 0x00000800
#define AR2315_LB_INT_MBOX_WR 0x00001000
#define AR2315_LB_INT_MBOX_RD 0x00002000
/* Bit definitions for INT MASK are the same as INT_STATUS */
#define AR2315_LB_INT_MASK 0x0504
#define AR2315_LB_INT_EN 0x0508
#define AR2315_LB_MBOX 0x0600
#endif /* __ASM_MACH_ATH25_AR2315_REGS_H */

393
arch/mips/ath25/ar5312.c Normal file
View file

@ -0,0 +1,393 @@
/*
* 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>
* Copyright (C) 2012 Alexandros C. Couloumbis <alex@ozo.com>
*/
/*
* Platform devices for Atheros AR5312 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/mtd/physmap.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 "ar5312.h"
#include "ar5312_regs.h"
static void __iomem *ar5312_rst_base;
static struct irq_domain *ar5312_misc_irq_domain;
static inline u32 ar5312_rst_reg_read(u32 reg)
{
return __raw_readl(ar5312_rst_base + reg);
}
static inline void ar5312_rst_reg_write(u32 reg, u32 val)
{
__raw_writel(val, ar5312_rst_base + reg);
}
static inline void ar5312_rst_reg_mask(u32 reg, u32 mask, u32 val)
{
u32 ret = ar5312_rst_reg_read(reg);
ret &= ~mask;
ret |= val;
ar5312_rst_reg_write(reg, ret);
}
static irqreturn_t ar5312_ahb_err_handler(int cpl, void *dev_id)
{
u32 proc1 = ar5312_rst_reg_read(AR5312_PROC1);
u32 proc_addr = ar5312_rst_reg_read(AR5312_PROCADDR); /* clears error */
u32 dma1 = ar5312_rst_reg_read(AR5312_DMA1);
u32 dma_addr = ar5312_rst_reg_read(AR5312_DMAADDR); /* clears error */
pr_emerg("AHB interrupt: PROCADDR=0x%8.8x PROC1=0x%8.8x DMAADDR=0x%8.8x DMA1=0x%8.8x\n",
proc_addr, proc1, dma_addr, dma1);
machine_restart("AHB error"); /* Catastrophic failure */
return IRQ_HANDLED;
}
static struct irqaction ar5312_ahb_err_interrupt = {
.handler = ar5312_ahb_err_handler,
.name = "ar5312-ahb-error",
};
static void ar5312_misc_irq_handler(unsigned irq, struct irq_desc *desc)
{
u32 pending = ar5312_rst_reg_read(AR5312_ISR) &
ar5312_rst_reg_read(AR5312_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) {
generic_handle_irq(misc_irq);
if (nr == AR5312_MISC_IRQ_TIMER)
ar5312_rst_reg_read(AR5312_TIMER);
} else {
spurious_interrupt();
}
}
/* Enable the specified AR5312_MISC_IRQ interrupt */
static void ar5312_misc_irq_unmask(struct irq_data *d)
{
ar5312_rst_reg_mask(AR5312_IMR, 0, BIT(d->hwirq));
}
/* Disable the specified AR5312_MISC_IRQ interrupt */
static void ar5312_misc_irq_mask(struct irq_data *d)
{
ar5312_rst_reg_mask(AR5312_IMR, BIT(d->hwirq), 0);
ar5312_rst_reg_read(AR5312_IMR); /* flush write buffer */
}
static struct irq_chip ar5312_misc_irq_chip = {
.name = "ar5312-misc",
.irq_unmask = ar5312_misc_irq_unmask,
.irq_mask = ar5312_misc_irq_mask,
};
static int ar5312_misc_irq_map(struct irq_domain *d, unsigned irq,
irq_hw_number_t hw)
{
irq_set_chip_and_handler(irq, &ar5312_misc_irq_chip, handle_level_irq);
return 0;
}
static struct irq_domain_ops ar5312_misc_irq_domain_ops = {
.map = ar5312_misc_irq_map,
};
static void ar5312_irq_dispatch(void)
{
u32 pending = read_c0_status() & read_c0_cause();
if (pending & CAUSEF_IP2)
do_IRQ(AR5312_IRQ_WLAN0);
else if (pending & CAUSEF_IP5)
do_IRQ(AR5312_IRQ_WLAN1);
else if (pending & CAUSEF_IP6)
do_IRQ(AR5312_IRQ_MISC);
else if (pending & CAUSEF_IP7)
do_IRQ(ATH25_IRQ_CPU_CLOCK);
else
spurious_interrupt();
}
void __init ar5312_arch_init_irq(void)
{
struct irq_domain *domain;
unsigned irq;
ath25_irq_dispatch = ar5312_irq_dispatch;
domain = irq_domain_add_linear(NULL, AR5312_MISC_IRQ_COUNT,
&ar5312_misc_irq_domain_ops, NULL);
if (!domain)
panic("Failed to add IRQ domain");
irq = irq_create_mapping(domain, AR5312_MISC_IRQ_AHB_PROC);
setup_irq(irq, &ar5312_ahb_err_interrupt);
irq_set_chained_handler(AR5312_IRQ_MISC, ar5312_misc_irq_handler);
irq_set_handler_data(AR5312_IRQ_MISC, domain);
ar5312_misc_irq_domain = domain;
}
static struct physmap_flash_data ar5312_flash_data = {
.width = 2,
};
static struct resource ar5312_flash_resource = {
.start = AR5312_FLASH_BASE,
.end = AR5312_FLASH_BASE + AR5312_FLASH_SIZE - 1,
.flags = IORESOURCE_MEM,
};
static struct platform_device ar5312_physmap_flash = {
.name = "physmap-flash",
.id = 0,
.dev.platform_data = &ar5312_flash_data,
.resource = &ar5312_flash_resource,
.num_resources = 1,
};
static void __init ar5312_flash_init(void)
{
void __iomem *flashctl_base;
u32 ctl;
flashctl_base = ioremap_nocache(AR5312_FLASHCTL_BASE,
AR5312_FLASHCTL_SIZE);
ctl = __raw_readl(flashctl_base + AR5312_FLASHCTL0);
ctl &= AR5312_FLASHCTL_MW;
/* fixup flash width */
switch (ctl) {
case AR5312_FLASHCTL_MW16:
ar5312_flash_data.width = 2;
break;
case AR5312_FLASHCTL_MW8:
default:
ar5312_flash_data.width = 1;
break;
}
/*
* Configure flash bank 0.
* Assume 8M window size. Flash will be aliased if it's smaller
*/
ctl |= AR5312_FLASHCTL_E | AR5312_FLASHCTL_AC_8M | AR5312_FLASHCTL_RBLE;
ctl |= 0x01 << AR5312_FLASHCTL_IDCY_S;
ctl |= 0x07 << AR5312_FLASHCTL_WST1_S;
ctl |= 0x07 << AR5312_FLASHCTL_WST2_S;
__raw_writel(ctl, flashctl_base + AR5312_FLASHCTL0);
/* Disable other flash banks */
ctl = __raw_readl(flashctl_base + AR5312_FLASHCTL1);
ctl &= ~(AR5312_FLASHCTL_E | AR5312_FLASHCTL_AC);
__raw_writel(ctl, flashctl_base + AR5312_FLASHCTL1);
ctl = __raw_readl(flashctl_base + AR5312_FLASHCTL2);
ctl &= ~(AR5312_FLASHCTL_E | AR5312_FLASHCTL_AC);
__raw_writel(ctl, flashctl_base + AR5312_FLASHCTL2);
iounmap(flashctl_base);
}
void __init ar5312_init_devices(void)
{
struct ath25_boarddata *config;
ar5312_flash_init();
/* Locate board/radio config data */
ath25_find_config(AR5312_FLASH_BASE, AR5312_FLASH_SIZE);
config = ath25_board.config;
/* AR2313 has CPU minor rev. 10 */
if ((current_cpu_data.processor_id & 0xff) == 0x0a)
ath25_soc = ATH25_SOC_AR2313;
/* AR2312 shares the same Silicon ID as AR5312 */
else if (config->flags & BD_ISCASPER)
ath25_soc = ATH25_SOC_AR2312;
/* Everything else is probably AR5312 or compatible */
else
ath25_soc = ATH25_SOC_AR5312;
platform_device_register(&ar5312_physmap_flash);
switch (ath25_soc) {
case ATH25_SOC_AR5312:
if (!ath25_board.radio)
return;
if (!(config->flags & BD_WLAN0))
break;
ath25_add_wmac(0, AR5312_WLAN0_BASE, AR5312_IRQ_WLAN0);
break;
case ATH25_SOC_AR2312:
case ATH25_SOC_AR2313:
if (!ath25_board.radio)
return;
break;
default:
break;
}
if (config->flags & BD_WLAN1)
ath25_add_wmac(1, AR5312_WLAN1_BASE, AR5312_IRQ_WLAN1);
}
static void ar5312_restart(char *command)
{
/* reset the system */
local_irq_disable();
while (1)
ar5312_rst_reg_write(AR5312_RESET, AR5312_RESET_SYSTEM);
}
/*
* This table is indexed by bits 5..4 of the CLOCKCTL1 register
* to determine the predevisor value.
*/
static unsigned clockctl1_predivide_table[4] __initdata = { 1, 2, 4, 5 };
static unsigned __init ar5312_cpu_frequency(void)
{
u32 scratch, devid, clock_ctl1;
u32 predivide_mask, multiplier_mask, doubler_mask;
unsigned predivide_shift, multiplier_shift;
unsigned predivide_select, predivisor, multiplier;
/* Trust the bootrom's idea of cpu frequency. */
scratch = ar5312_rst_reg_read(AR5312_SCRATCH);
if (scratch)
return scratch;
devid = ar5312_rst_reg_read(AR5312_REV);
devid = (devid & AR5312_REV_MAJ) >> AR5312_REV_MAJ_S;
if (devid == AR5312_REV_MAJ_AR2313) {
predivide_mask = AR2313_CLOCKCTL1_PREDIVIDE_MASK;
predivide_shift = AR2313_CLOCKCTL1_PREDIVIDE_SHIFT;
multiplier_mask = AR2313_CLOCKCTL1_MULTIPLIER_MASK;
multiplier_shift = AR2313_CLOCKCTL1_MULTIPLIER_SHIFT;
doubler_mask = AR2313_CLOCKCTL1_DOUBLER_MASK;
} else { /* AR5312 and AR2312 */
predivide_mask = AR5312_CLOCKCTL1_PREDIVIDE_MASK;
predivide_shift = AR5312_CLOCKCTL1_PREDIVIDE_SHIFT;
multiplier_mask = AR5312_CLOCKCTL1_MULTIPLIER_MASK;
multiplier_shift = AR5312_CLOCKCTL1_MULTIPLIER_SHIFT;
doubler_mask = AR5312_CLOCKCTL1_DOUBLER_MASK;
}
/*
* Clocking is derived from a fixed 40MHz input clock.
*
* cpu_freq = input_clock * MULT (where MULT is PLL multiplier)
* sys_freq = cpu_freq / 4 (used for APB clock, serial,
* flash, Timer, Watchdog Timer)
*
* cnt_freq = cpu_freq / 2 (use for CPU count/compare)
*
* So, for example, with a PLL multiplier of 5, we have
*
* cpu_freq = 200MHz
* sys_freq = 50MHz
* cnt_freq = 100MHz
*
* We compute the CPU frequency, based on PLL settings.
*/
clock_ctl1 = ar5312_rst_reg_read(AR5312_CLOCKCTL1);
predivide_select = (clock_ctl1 & predivide_mask) >> predivide_shift;
predivisor = clockctl1_predivide_table[predivide_select];
multiplier = (clock_ctl1 & multiplier_mask) >> multiplier_shift;
if (clock_ctl1 & doubler_mask)
multiplier <<= 1;
return (40000000 / predivisor) * multiplier;
}
static inline unsigned ar5312_sys_frequency(void)
{
return ar5312_cpu_frequency() / 4;
}
void __init ar5312_plat_time_init(void)
{
mips_hpt_frequency = ar5312_cpu_frequency() / 2;
}
void __init ar5312_plat_mem_setup(void)
{
void __iomem *sdram_base;
u32 memsize, memcfg, bank0_ac, bank1_ac;
u32 devid;
/* Detect memory size */
sdram_base = ioremap_nocache(AR5312_SDRAMCTL_BASE,
AR5312_SDRAMCTL_SIZE);
memcfg = __raw_readl(sdram_base + AR5312_MEM_CFG1);
bank0_ac = ATH25_REG_MS(memcfg, AR5312_MEM_CFG1_AC0);
bank1_ac = ATH25_REG_MS(memcfg, AR5312_MEM_CFG1_AC1);
memsize = (bank0_ac ? (1 << (bank0_ac + 1)) : 0) +
(bank1_ac ? (1 << (bank1_ac + 1)) : 0);
memsize <<= 20;
add_memory_region(0, memsize, BOOT_MEM_RAM);
iounmap(sdram_base);
ar5312_rst_base = ioremap_nocache(AR5312_RST_BASE, AR5312_RST_SIZE);
devid = ar5312_rst_reg_read(AR5312_REV);
devid >>= AR5312_REV_WMAC_MIN_S;
devid &= AR5312_REV_CHIP;
ath25_board.devid = (u16)devid;
/* Clear any lingering AHB errors */
ar5312_rst_reg_read(AR5312_PROCADDR);
ar5312_rst_reg_read(AR5312_DMAADDR);
ar5312_rst_reg_write(AR5312_WDT_CTRL, AR5312_WDT_CTRL_IGNORE);
_machine_restart = ar5312_restart;
}
void __init ar5312_arch_init(void)
{
unsigned irq = irq_create_mapping(ar5312_misc_irq_domain,
AR5312_MISC_IRQ_UART0);
ath25_serial_setup(AR5312_UART0_BASE, irq, ar5312_sys_frequency());
}

22
arch/mips/ath25/ar5312.h Normal file
View file

@ -0,0 +1,22 @@
#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 */

View file

@ -0,0 +1,224 @@
/*
* 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 */

234
arch/mips/ath25/board.c Normal file
View file

@ -0,0 +1,234 @@
/*
* 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();
}

125
arch/mips/ath25/devices.c Normal file
View file

@ -0,0 +1,125 @@
#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);

43
arch/mips/ath25/devices.h Normal file
View file

@ -0,0 +1,43 @@
#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

View file

@ -0,0 +1,44 @@
/*
* 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)
;
}

26
arch/mips/ath25/prom.c Normal file
View file

@ -0,0 +1,26 @@
/*
* 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)
{
}

View file

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

View file

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

View file

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

View file

@ -0,0 +1 @@
obj-y += setup.o irq.o dma.o

View file

@ -0,0 +1,7 @@
#
# Broadcom BCM3384 boards
#
platform-$(CONFIG_BCM3384) += bcm3384/
cflags-$(CONFIG_BCM3384) += \
-I$(srctree)/arch/mips/include/asm/mach-bcm3384/
load-$(CONFIG_BCM3384) := 0xffffffff80010000

81
arch/mips/bcm3384/dma.c Normal file
View file

@ -0,0 +1,81 @@
/*
* 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);

193
arch/mips/bcm3384/irq.c Normal file
View file

@ -0,0 +1,193 @@
/*
* 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);
}

97
arch/mips/bcm3384/setup.c Normal file
View file

@ -0,0 +1,97 @@
/*
* 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);

View file

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

View file

@ -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,

View file

@ -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 @@ found:
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;
void __iomem *iobase;
int err;
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;
}
iobase = ioremap_nocache(base, lim);
if (!iobase)
return -ENOMEM;
return nvram_find_and_copy(base, lim);
err = nvram_find_and_copy(iobase, lim);
iounmap(iobase);
return err;
}
#endif
#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;
}
return nvram_find_and_copy(base, lim);
}
#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;

View file

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

View file

@ -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
}

View file

@ -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()) {

View file

@ -1,3 +1,4 @@
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

View file

@ -0,0 +1,109 @@
/ {
#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";
};
};

View file

@ -0,0 +1,32 @@
/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";
};

View file

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

View file

@ -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
* Read a byte of fuse data
* @byte_addr: address to read
*
* @chip_id: Chip ID
*
* 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);
}

View file

@ -0,0 +1,78 @@
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

View file

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

View file

@ -17,6 +17,7 @@
#include <linux/irqflags.h>
#include <linux/types.h>
#include <asm/barrier.h>
#include <asm/compiler.h>
#include <asm/cpu-features.h>
#include <asm/cmpxchg.h>
#include <asm/war.h>
@ -40,95 +41,97 @@
*/
#define atomic_set(v, i) ((v)->counter = (i))
#define ATOMIC_OP(op, c_op, asm_op) \
static __inline__ void atomic_##op(int i, atomic_t * v) \
{ \
if (kernel_uses_llsc && R10000_LLSC_WAR) { \
int temp; \
\
__asm__ __volatile__( \
" .set arch=r4000 \n" \
"1: ll %0, %1 # atomic_" #op " \n" \
" " #asm_op " %0, %2 \n" \
" sc %0, %1 \n" \
" beqzl %0, 1b \n" \
" .set mips0 \n" \
: "=&r" (temp), "+m" (v->counter) \
: "Ir" (i)); \
} else if (kernel_uses_llsc) { \
int temp; \
\
do { \
__asm__ __volatile__( \
" .set arch=r4000 \n" \
" ll %0, %1 # atomic_" #op "\n" \
" " #asm_op " %0, %2 \n" \
" sc %0, %1 \n" \
" .set mips0 \n" \
: "=&r" (temp), "+m" (v->counter) \
: "Ir" (i)); \
} while (unlikely(!temp)); \
} else { \
unsigned long flags; \
\
raw_local_irq_save(flags); \
v->counter c_op i; \
raw_local_irq_restore(flags); \
} \
} \
#define ATOMIC_OP_RETURN(op, c_op, asm_op) \
static __inline__ int atomic_##op##_return(int i, atomic_t * v) \
{ \
int result; \
\
smp_mb__before_llsc(); \
\
if (kernel_uses_llsc && R10000_LLSC_WAR) { \
int temp; \
\
__asm__ __volatile__( \
" .set arch=r4000 \n" \
"1: ll %1, %2 # atomic_" #op "_return \n" \
" " #asm_op " %0, %1, %3 \n" \
" sc %0, %2 \n" \
" beqzl %0, 1b \n" \
" " #asm_op " %0, %1, %3 \n" \
" .set mips0 \n" \
: "=&r" (result), "=&r" (temp), "+m" (v->counter) \
: "Ir" (i)); \
} else if (kernel_uses_llsc) { \
int temp; \
\
do { \
__asm__ __volatile__( \
" .set arch=r4000 \n" \
" ll %1, %2 # atomic_" #op "_return \n" \
" " #asm_op " %0, %1, %3 \n" \
" sc %0, %2 \n" \
" .set mips0 \n" \
: "=&r" (result), "=&r" (temp), "+m" (v->counter) \
: "Ir" (i)); \
} while (unlikely(!result)); \
\
result = temp; result c_op i; \
} else { \
unsigned long flags; \
\
raw_local_irq_save(flags); \
result = v->counter; \
result c_op i; \
v->counter = result; \
raw_local_irq_restore(flags); \
} \
\
smp_llsc_mb(); \
\
return result; \
#define ATOMIC_OP(op, c_op, asm_op) \
static __inline__ void atomic_##op(int i, atomic_t * v) \
{ \
if (kernel_uses_llsc && R10000_LLSC_WAR) { \
int temp; \
\
__asm__ __volatile__( \
" .set arch=r4000 \n" \
"1: ll %0, %1 # atomic_" #op " \n" \
" " #asm_op " %0, %2 \n" \
" sc %0, %1 \n" \
" beqzl %0, 1b \n" \
" .set mips0 \n" \
: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter) \
: "Ir" (i)); \
} else if (kernel_uses_llsc) { \
int temp; \
\
do { \
__asm__ __volatile__( \
" .set arch=r4000 \n" \
" ll %0, %1 # atomic_" #op "\n" \
" " #asm_op " %0, %2 \n" \
" sc %0, %1 \n" \
" .set mips0 \n" \
: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter) \
: "Ir" (i)); \
} while (unlikely(!temp)); \
} else { \
unsigned long flags; \
\
raw_local_irq_save(flags); \
v->counter c_op i; \
raw_local_irq_restore(flags); \
} \
}
#define ATOMIC_OPS(op, c_op, asm_op) \
ATOMIC_OP(op, c_op, asm_op) \
#define ATOMIC_OP_RETURN(op, c_op, asm_op) \
static __inline__ int atomic_##op##_return(int i, atomic_t * v) \
{ \
int result; \
\
smp_mb__before_llsc(); \
\
if (kernel_uses_llsc && R10000_LLSC_WAR) { \
int temp; \
\
__asm__ __volatile__( \
" .set arch=r4000 \n" \
"1: ll %1, %2 # atomic_" #op "_return \n" \
" " #asm_op " %0, %1, %3 \n" \
" sc %0, %2 \n" \
" beqzl %0, 1b \n" \
" " #asm_op " %0, %1, %3 \n" \
" .set mips0 \n" \
: "=&r" (result), "=&r" (temp), \
"+" GCC_OFF12_ASM() (v->counter) \
: "Ir" (i)); \
} else if (kernel_uses_llsc) { \
int temp; \
\
do { \
__asm__ __volatile__( \
" .set arch=r4000 \n" \
" ll %1, %2 # atomic_" #op "_return \n" \
" " #asm_op " %0, %1, %3 \n" \
" sc %0, %2 \n" \
" .set mips0 \n" \
: "=&r" (result), "=&r" (temp), \
"+" GCC_OFF12_ASM() (v->counter) \
: "Ir" (i)); \
} while (unlikely(!result)); \
\
result = temp; result c_op i; \
} else { \
unsigned long flags; \
\
raw_local_irq_save(flags); \
result = v->counter; \
result c_op i; \
v->counter = result; \
raw_local_irq_restore(flags); \
} \
\
smp_llsc_mb(); \
\
return result; \
}
#define ATOMIC_OPS(op, c_op, asm_op) \
ATOMIC_OP(op, c_op, asm_op) \
ATOMIC_OP_RETURN(op, c_op, asm_op)
ATOMIC_OPS(add, +=, addu)
@ -167,8 +170,9 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
" .set reorder \n"
"1: \n"
" .set mips0 \n"
: "=&r" (result), "=&r" (temp), "+m" (v->counter)
: "Ir" (i), "m" (v->counter)
: "=&r" (result), "=&r" (temp),
"+" GCC_OFF12_ASM() (v->counter)
: "Ir" (i), GCC_OFF12_ASM() (v->counter)
: "memory");
} else if (kernel_uses_llsc) {
int temp;
@ -185,7 +189,8 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
" .set reorder \n"
"1: \n"
" .set mips0 \n"
: "=&r" (result), "=&r" (temp), "+m" (v->counter)
: "=&r" (result), "=&r" (temp),
"+" GCC_OFF12_ASM() (v->counter)
: "Ir" (i));
} else {
unsigned long flags;
@ -315,96 +320,98 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
*/
#define atomic64_set(v, i) ((v)->counter = (i))
#define ATOMIC64_OP(op, c_op, asm_op) \
static __inline__ void atomic64_##op(long i, atomic64_t * v) \
{ \
if (kernel_uses_llsc && R10000_LLSC_WAR) { \
long temp; \
\
__asm__ __volatile__( \
" .set arch=r4000 \n" \
"1: lld %0, %1 # atomic64_" #op " \n" \
" " #asm_op " %0, %2 \n" \
" scd %0, %1 \n" \
" beqzl %0, 1b \n" \
" .set mips0 \n" \
: "=&r" (temp), "+m" (v->counter) \
: "Ir" (i)); \
} else if (kernel_uses_llsc) { \
long temp; \
\
do { \
__asm__ __volatile__( \
" .set arch=r4000 \n" \
" lld %0, %1 # atomic64_" #op "\n" \
" " #asm_op " %0, %2 \n" \
" scd %0, %1 \n" \
" .set mips0 \n" \
: "=&r" (temp), "+m" (v->counter) \
: "Ir" (i)); \
} while (unlikely(!temp)); \
} else { \
unsigned long flags; \
\
raw_local_irq_save(flags); \
v->counter c_op i; \
raw_local_irq_restore(flags); \
} \
} \
#define ATOMIC64_OP_RETURN(op, c_op, asm_op) \
static __inline__ long atomic64_##op##_return(long i, atomic64_t * v) \
{ \
long result; \
\
smp_mb__before_llsc(); \
\
if (kernel_uses_llsc && R10000_LLSC_WAR) { \
long temp; \
\
__asm__ __volatile__( \
" .set arch=r4000 \n" \
"1: lld %1, %2 # atomic64_" #op "_return\n" \
" " #asm_op " %0, %1, %3 \n" \
" scd %0, %2 \n" \
" beqzl %0, 1b \n" \
" " #asm_op " %0, %1, %3 \n" \
" .set mips0 \n" \
: "=&r" (result), "=&r" (temp), "+m" (v->counter) \
: "Ir" (i)); \
} else if (kernel_uses_llsc) { \
long temp; \
\
do { \
__asm__ __volatile__( \
" .set arch=r4000 \n" \
" lld %1, %2 # atomic64_" #op "_return\n" \
" " #asm_op " %0, %1, %3 \n" \
" scd %0, %2 \n" \
" .set mips0 \n" \
: "=&r" (result), "=&r" (temp), "=m" (v->counter) \
: "Ir" (i), "m" (v->counter) \
: "memory"); \
} while (unlikely(!result)); \
\
result = temp; result c_op i; \
} else { \
unsigned long flags; \
\
raw_local_irq_save(flags); \
result = v->counter; \
result c_op i; \
v->counter = result; \
raw_local_irq_restore(flags); \
} \
\
smp_llsc_mb(); \
\
return result; \
#define ATOMIC64_OP(op, c_op, asm_op) \
static __inline__ void atomic64_##op(long i, atomic64_t * v) \
{ \
if (kernel_uses_llsc && R10000_LLSC_WAR) { \
long temp; \
\
__asm__ __volatile__( \
" .set arch=r4000 \n" \
"1: lld %0, %1 # atomic64_" #op " \n" \
" " #asm_op " %0, %2 \n" \
" scd %0, %1 \n" \
" beqzl %0, 1b \n" \
" .set mips0 \n" \
: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter) \
: "Ir" (i)); \
} else if (kernel_uses_llsc) { \
long temp; \
\
do { \
__asm__ __volatile__( \
" .set arch=r4000 \n" \
" lld %0, %1 # atomic64_" #op "\n" \
" " #asm_op " %0, %2 \n" \
" scd %0, %1 \n" \
" .set mips0 \n" \
: "=&r" (temp), "+" GCC_OFF12_ASM() (v->counter) \
: "Ir" (i)); \
} while (unlikely(!temp)); \
} else { \
unsigned long flags; \
\
raw_local_irq_save(flags); \
v->counter c_op i; \
raw_local_irq_restore(flags); \
} \
}
#define ATOMIC64_OPS(op, c_op, asm_op) \
ATOMIC64_OP(op, c_op, asm_op) \
#define ATOMIC64_OP_RETURN(op, c_op, asm_op) \
static __inline__ long atomic64_##op##_return(long i, atomic64_t * v) \
{ \
long result; \
\
smp_mb__before_llsc(); \
\
if (kernel_uses_llsc && R10000_LLSC_WAR) { \
long temp; \
\
__asm__ __volatile__( \
" .set arch=r4000 \n" \
"1: lld %1, %2 # atomic64_" #op "_return\n" \
" " #asm_op " %0, %1, %3 \n" \
" scd %0, %2 \n" \
" beqzl %0, 1b \n" \
" " #asm_op " %0, %1, %3 \n" \
" .set mips0 \n" \
: "=&r" (result), "=&r" (temp), \
"+" GCC_OFF12_ASM() (v->counter) \
: "Ir" (i)); \
} else if (kernel_uses_llsc) { \
long temp; \
\
do { \
__asm__ __volatile__( \
" .set arch=r4000 \n" \
" lld %1, %2 # atomic64_" #op "_return\n" \
" " #asm_op " %0, %1, %3 \n" \
" scd %0, %2 \n" \
" .set mips0 \n" \
: "=&r" (result), "=&r" (temp), \
"=" GCC_OFF12_ASM() (v->counter) \
: "Ir" (i), GCC_OFF12_ASM() (v->counter) \
: "memory"); \
} while (unlikely(!result)); \
\
result = temp; result c_op i; \
} else { \
unsigned long flags; \
\
raw_local_irq_save(flags); \
result = v->counter; \
result c_op i; \
v->counter = result; \
raw_local_irq_restore(flags); \
} \
\
smp_llsc_mb(); \
\
return result; \
}
#define ATOMIC64_OPS(op, c_op, asm_op) \
ATOMIC64_OP(op, c_op, asm_op) \
ATOMIC64_OP_RETURN(op, c_op, asm_op)
ATOMIC64_OPS(add, +=, daddu)
@ -415,7 +422,8 @@ ATOMIC64_OPS(sub, -=, dsubu)
#undef ATOMIC64_OP
/*
* atomic64_sub_if_positive - conditionally subtract integer from atomic variable
* atomic64_sub_if_positive - conditionally subtract integer from atomic
* variable
* @i: integer value to subtract
* @v: pointer of type atomic64_t
*
@ -443,8 +451,9 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
" .set reorder \n"
"1: \n"
" .set mips0 \n"
: "=&r" (result), "=&r" (temp), "=m" (v->counter)
: "Ir" (i), "m" (v->counter)
: "=&r" (result), "=&r" (temp),
"=" GCC_OFF12_ASM() (v->counter)
: "Ir" (i), GCC_OFF12_ASM() (v->counter)
: "memory");
} else if (kernel_uses_llsc) {
long temp;
@ -461,7 +470,8 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
" .set reorder \n"
"1: \n"
" .set mips0 \n"
: "=&r" (result), "=&r" (temp), "+m" (v->counter)
: "=&r" (result), "=&r" (temp),
"+" GCC_OFF12_ASM() (v->counter)
: "Ir" (i));
} else {
unsigned long flags;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,6 +1,8 @@
#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++;
}

View file

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

View file

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

View file

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

View file

@ -0,0 +1,73 @@
#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 */

View file

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

View file

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

View file

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

View file

@ -0,0 +1,73 @@
#ifndef __ASM_MACH_ATH25_PLATFORM_H
#define __ASM_MACH_ATH25_PLATFORM_H
#include <linux/etherdevice.h>
/*
* This is board-specific data that is stored in a "fixed" location in flash.
* It is shared across operating systems, so it should not be changed lightly.
* The main reason we need it is in order to extract the ethernet MAC
* address(es).
*/
struct ath25_boarddata {
u32 magic; /* board data is valid */
#define ATH25_BD_MAGIC 0x35333131 /* "5311", for all 531x/231x platforms */
u16 cksum; /* checksum (starting with BD_REV 2) */
u16 rev; /* revision of this struct */
#define BD_REV 4
char board_name[64]; /* Name of board */
u16 major; /* Board major number */
u16 minor; /* Board minor number */
u32 flags; /* Board configuration */
#define BD_ENET0 0x00000001 /* ENET0 is stuffed */
#define BD_ENET1 0x00000002 /* ENET1 is stuffed */
#define BD_UART1 0x00000004 /* UART1 is stuffed */
#define BD_UART0 0x00000008 /* UART0 is stuffed (dma) */
#define BD_RSTFACTORY 0x00000010 /* Reset factory defaults stuffed */
#define BD_SYSLED 0x00000020 /* System LED stuffed */
#define BD_EXTUARTCLK 0x00000040 /* External UART clock */
#define BD_CPUFREQ 0x00000080 /* cpu freq is valid in nvram */
#define BD_SYSFREQ 0x00000100 /* sys freq is set in nvram */
#define BD_WLAN0 0x00000200 /* Enable WLAN0 */
#define BD_MEMCAP 0x00000400 /* CAP SDRAM @ mem_cap for testing */
#define BD_DISWATCHDOG 0x00000800 /* disable system watchdog */
#define BD_WLAN1 0x00001000 /* Enable WLAN1 (ar5212) */
#define BD_ISCASPER 0x00002000 /* FLAG for AR2312 */
#define BD_WLAN0_2G_EN 0x00004000 /* FLAG for radio0_2G */
#define BD_WLAN0_5G_EN 0x00008000 /* FLAG for radio0_2G */
#define BD_WLAN1_2G_EN 0x00020000 /* FLAG for radio0_2G */
#define BD_WLAN1_5G_EN 0x00040000 /* FLAG for radio0_2G */
u16 reset_config_gpio; /* Reset factory GPIO pin */
u16 sys_led_gpio; /* System LED GPIO pin */
u32 cpu_freq; /* CPU core frequency in Hz */
u32 sys_freq; /* System frequency in Hz */
u32 cnt_freq; /* Calculated C0_COUNT frequency */
u8 wlan0_mac[ETH_ALEN];
u8 enet0_mac[ETH_ALEN];
u8 enet1_mac[ETH_ALEN];
u16 pci_id; /* Pseudo PCIID for common code */
u16 mem_cap; /* cap bank1 in MB */
/* version 3 */
u8 wlan1_mac[ETH_ALEN]; /* (ar5212) */
};
#define BOARD_CONFIG_BUFSZ 0x1000
/*
* Platform device information for the Wireless MAC
*/
struct ar231x_board_config {
u16 devid;
/* board config data */
struct ath25_boarddata *config;
/* radio calibration data */
const char *radio;
};
#endif /* __ASM_MACH_ATH25_PLATFORM_H */

View file

@ -0,0 +1,64 @@
/*
* Atheros AR231x/AR531x SoC specific CPU feature overrides
*
* Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org>
*
* This file was derived from: include/asm-mips/cpu-features.h
* Copyright (C) 2003, 2004 Ralf Baechle
* Copyright (C) 2004 Maciej W. Rozycki
*
* 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.
*
*/
#ifndef __ASM_MACH_ATH25_CPU_FEATURE_OVERRIDES_H
#define __ASM_MACH_ATH25_CPU_FEATURE_OVERRIDES_H
/*
* The Atheros AR531x/AR231x SoCs have MIPS 4Kc/4KEc core.
*/
#define cpu_has_tlb 1
#define cpu_has_4kex 1
#define cpu_has_3k_cache 0
#define cpu_has_4k_cache 1
#define cpu_has_tx39_cache 0
#define cpu_has_sb1_cache 0
#define cpu_has_fpu 0
#define cpu_has_32fpr 0
#define cpu_has_counter 1
#define cpu_has_ejtag 1
#if !defined(CONFIG_SOC_AR5312)
# define cpu_has_llsc 1
#else
/*
* The MIPS 4Kc V0.9 core in the AR5312/AR2312 have problems with the
* ll/sc instructions.
*/
# define cpu_has_llsc 0
#endif
#define cpu_has_mips16 0
#define cpu_has_mdmx 0
#define cpu_has_mips3d 0
#define cpu_has_smartmips 0
#define cpu_has_mips32r1 1
#if !defined(CONFIG_SOC_AR5312)
# define cpu_has_mips32r2 1
#endif
#define cpu_has_mips64r1 0
#define cpu_has_mips64r2 0
#define cpu_has_dsp 0
#define cpu_has_mipsmt 0
#define cpu_has_64bits 0
#define cpu_has_64bit_zero_reg 0
#define cpu_has_64bit_gp_regs 0
#define cpu_has_64bit_addresses 0
#endif /* __ASM_MACH_ATH25_CPU_FEATURE_OVERRIDES_H */

View file

@ -0,0 +1,82 @@
/*
* 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 Ralf Baechle <ralf@linux-mips.org>
* Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
*
*/
#ifndef __ASM_MACH_ATH25_DMA_COHERENCE_H
#define __ASM_MACH_ATH25_DMA_COHERENCE_H
#include <linux/device.h>
/*
* We need some arbitrary non-zero value to be programmed to the BAR1 register
* of PCI host controller to enable DMA. The same value should be used as the
* offset to calculate the physical address of DMA buffer for PCI devices.
*/
#define AR2315_PCI_HOST_SDRAM_BASEADDR 0x20000000
static inline dma_addr_t ath25_dev_offset(struct device *dev)
{
#ifdef CONFIG_PCI
extern struct bus_type pci_bus_type;
if (dev && dev->bus == &pci_bus_type)
return AR2315_PCI_HOST_SDRAM_BASEADDR;
#endif
return 0;
}
static inline dma_addr_t
plat_map_dma_mem(struct device *dev, void *addr, size_t size)
{
return virt_to_phys(addr) + ath25_dev_offset(dev);
}
static inline dma_addr_t
plat_map_dma_mem_page(struct device *dev, struct page *page)
{
return page_to_phys(page) + ath25_dev_offset(dev);
}
static inline unsigned long
plat_dma_addr_to_phys(struct device *dev, dma_addr_t dma_addr)
{
return dma_addr - ath25_dev_offset(dev);
}
static inline void
plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction direction)
{
}
static inline int plat_dma_supported(struct device *dev, u64 mask)
{
return 1;
}
static inline void plat_extra_sync_for_device(struct device *dev)
{
}
static inline int plat_dma_mapping_error(struct device *dev,
dma_addr_t dma_addr)
{
return 0;
}
static inline int plat_device_is_coherent(struct device *dev)
{
#ifdef CONFIG_DMA_COHERENT
return 1;
#endif
#ifdef CONFIG_DMA_NONCOHERENT
return 0;
#endif
}
#endif /* __ASM_MACH_ATH25_DMA_COHERENCE_H */

View file

@ -0,0 +1,16 @@
#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 */

View file

@ -0,0 +1,25 @@
/*
* 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 Felix Fietkau <nbd@openwrt.org>
*/
#ifndef __ASM_MACH_ATH25_WAR_H
#define __ASM_MACH_ATH25_WAR_H
#define R4600_V1_INDEX_ICACHEOP_WAR 0
#define R4600_V1_HIT_CACHEOP_WAR 0
#define R4600_V2_HIT_CACHEOP_WAR 0
#define R5432_CP0_INTERRUPT_WAR 0
#define BCM1250_M3_WAR 0
#define SIBYTE_1956_WAR 0
#define MIPS4K_ICACHE_REFILL_WAR 0
#define MIPS_CACHE_SYNC_WAR 0
#define TX49XX_ICACHE_INDEX_INV_WAR 0
#define RM9000_CDEX_SMP_WAR 0
#define ICACHE_REFILLS_WORKAROUND_WAR 0
#define R10000_LLSC_WAR 0
#define MIPS34K_MISSED_ITLB_WAR 0
#endif /* __ASM_MACH_ATH25_WAR_H */

View file

@ -11,10 +11,10 @@
#include <linux/types.h>
#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_PCI)
extern phys_t __fixup_bigphys_addr(phys_t, phys_t);
#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_PCI)
extern phys_addr_t __fixup_bigphys_addr(phys_addr_t, phys_addr_t);
#else
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;
}
@ -23,12 +23,12 @@ static inline phys_t __fixup_bigphys_addr(phys_t phys_addr, phys_t size)
/*
* Allow physical addresses to be fixed up to help 36-bit peripherals.
*/
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 __fixup_bigphys_addr(phys_addr, size);
}
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;

View file

@ -0,0 +1,48 @@
/*
* Copyright (C) 2006 Ralf Baechle <ralf@linux-mips.org>
* Copyright (C) 2009 Broadcom Corporation
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __ASM_MACH_BCM3384_DMA_COHERENCE_H
#define __ASM_MACH_BCM3384_DMA_COHERENCE_H
struct device;
extern dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size);
extern dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page);
extern unsigned long plat_dma_addr_to_phys(struct device *dev,
dma_addr_t dma_addr);
static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
size_t size, enum dma_data_direction direction)
{
}
static inline int plat_dma_supported(struct device *dev, u64 mask)
{
/*
* we fall back to GFP_DMA when the mask isn't all 1s,
* so we can't guarantee allocations that must be
* within a tighter range than GFP_DMA..
*/
if (mask < DMA_BIT_MASK(24))
return 0;
return 1;
}
static inline int plat_device_is_coherent(struct device *dev)
{
return 0;
}
#endif /* __ASM_MACH_BCM3384_DMA_COHERENCE_H */

View file

@ -0,0 +1,24 @@
/*
* 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) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
*/
#ifndef __ASM_MIPS_MACH_BCM3384_WAR_H
#define __ASM_MIPS_MACH_BCM3384_WAR_H
#define R4600_V1_INDEX_ICACHEOP_WAR 0
#define R4600_V1_HIT_CACHEOP_WAR 0
#define R4600_V2_HIT_CACHEOP_WAR 0
#define R5432_CP0_INTERRUPT_WAR 0
#define BCM1250_M3_WAR 0
#define SIBYTE_1956_WAR 0
#define MIPS4K_ICACHE_REFILL_WAR 0
#define MIPS_CACHE_SYNC_WAR 0
#define TX49XX_ICACHE_INDEX_INV_WAR 0
#define ICACHE_REFILLS_WORKAROUND_WAR 0
#define R10000_LLSC_WAR 0
#define MIPS34K_MISSED_ITLB_WAR 0
#endif /* __ASM_MIPS_MACH_BCM3384_WAR_H */

View file

@ -14,40 +14,8 @@
#include <linux/types.h>
#include <linux/kernel.h>
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 */
};
#define NVRAM_HEADER 0x48534C46 /* 'FLSH' */
#define NVRAM_VERSION 1
#define NVRAM_HEADER_SIZE 20
#define NVRAM_SPACE 0x8000
#define FLASH_MIN 0x00020000 /* Minimum flash size */
#define NVRAM_MAX_VALUE_LEN 255
#define NVRAM_MAX_PARAM_LEN 64
extern int bcm47xx_nvram_getenv(char *name, char *val, size_t val_len);
static inline 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
printk(KERN_WARNING "Can not parse mac address: %s\n", buf);
}
int bcm47xx_nvram_init_from_mem(u32 base, u32 lim);
int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len);
int bcm47xx_nvram_gpio_pin(const char *name);
#endif /* __BCM47XX_NVRAM_H */

View file

@ -3,12 +3,12 @@
#include <bcm63xx_cpu.h>
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 int is_bcm63xx_internal_registers(phys_t offset)
static inline int is_bcm63xx_internal_registers(phys_addr_t offset)
{
switch (bcm63xx_get_cpu_id()) {
case BCM3368_CPU_ID:
@ -32,7 +32,7 @@ static inline int is_bcm63xx_internal_registers(phys_t offset)
return 0;
}
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)
{
if (is_bcm63xx_internal_registers(offset))

View file

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

View file

@ -36,4 +36,10 @@
#endif /* CONFIG_IRQ_CPU */
#ifdef CONFIG_MIPS_GIC
#ifndef MIPS_GIC_IRQ_BASE
#define MIPS_GIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8)
#endif
#endif /* CONFIG_MIPS_GIC */
#endif /* __ASM_MACH_GENERIC_IRQ_H */

View file

@ -48,6 +48,8 @@ extern struct clk *clk_get_ppe(void);
extern unsigned char ltq_boot_select(void);
/* find out what caused the last cpu reset */
extern int ltq_reset_cause(void);
/* find out the soc type */
extern int ltq_soc_type(void);
#define IOPORT_RESOURCE_START 0x10000000
#define IOPORT_RESOURCE_END 0xffffffff

View file

@ -10,7 +10,8 @@
#define VIDEO_ROM 7
#define ADAPTER_ROM 8
#define ACPI_TABLE 9
#define MAX_MEMORY_TYPE 10
#define SMBIOS_TABLE 10
#define MAX_MEMORY_TYPE 11
#define LOONGSON3_BOOT_MEM_MAP_MAX 128
struct efi_memory_map_loongson {
@ -42,15 +43,49 @@ struct efi_cpuinfo_loongson {
u32 processor_id; /* PRID, e.g. 6305, 6306 */
u32 cputype; /* Loongson_3A/3B, etc. */
u32 total_node; /* num of total numa nodes */
u32 cpu_startup_core_id; /* Core id */
u16 cpu_startup_core_id; /* Boot core id */
u16 reserved_cores_mask;
u32 cpu_clock_freq; /* cpu_clock */
u32 nr_cpus;
} __packed;
#define MAX_UARTS 64
struct uart_device {
u32 iotype; /* see include/linux/serial_core.h */
u32 uartclk;
u32 int_offset;
u64 uart_base;
} __packed;
#define MAX_SENSORS 64
#define SENSOR_TEMPER 0x00000001
#define SENSOR_VOLTAGE 0x00000002
#define SENSOR_FAN 0x00000004
struct sensor_device {
char name[32]; /* a formal name */
char label[64]; /* a flexible description */
u32 type; /* SENSOR_* */
u32 id; /* instance id of a sensor-class */
u32 fan_policy; /* see loongson_hwmon.h */
u32 fan_percent;/* only for constant speed policy */
u64 base_addr; /* base address of device registers */
} __packed;
struct system_loongson {
u16 vers; /* version of system_loongson */
u32 ccnuma_smp; /* 0: no numa; 1: has numa */
u32 sing_double_channel; /* 1:single; 2:double */
u32 nr_uarts;
struct uart_device uarts[MAX_UARTS];
u32 nr_sensors;
struct sensor_device sensors[MAX_SENSORS];
char has_ec;
char ec_name[32];
u64 ec_base_addr;
char has_tcm;
char tcm_name[32];
u64 tcm_base_addr;
u64 workarounds; /* see workarounds.h */
} __packed;
struct irq_source_routing_table {
@ -149,6 +184,8 @@ struct loongson_system_configuration {
u32 nr_nodes;
int cores_per_node;
int cores_per_package;
u16 boot_cpu_id;
u16 reserved_cpus_mask;
enum loongson_cpu_type cputype;
u64 ht_control_base;
u64 pci_mem_start_addr;
@ -159,9 +196,15 @@ struct loongson_system_configuration {
u64 suspend_addr;
u64 vgabios_addr;
u32 dma_mask_bits;
char ecname[32];
u32 nr_uarts;
struct uart_device uarts[MAX_UARTS];
u32 nr_sensors;
struct sensor_device sensors[MAX_SENSORS];
u64 workarounds;
};
extern struct efi_memory_map_loongson *loongson_memmap;
extern struct loongson_system_configuration loongson_sysconf;
extern int cpuhotplug_workaround;
#endif

View file

@ -23,7 +23,7 @@ static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
size_t size)
{
#ifdef CONFIG_CPU_LOONGSON3
return virt_to_phys(addr);
return phys_to_dma(dev, virt_to_phys(addr));
#else
return virt_to_phys(addr) | 0x80000000;
#endif
@ -33,7 +33,7 @@ static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
struct page *page)
{
#ifdef CONFIG_CPU_LOONGSON3
return page_to_phys(page);
return phys_to_dma(dev, page_to_phys(page));
#else
return page_to_phys(page) | 0x80000000;
#endif
@ -43,7 +43,7 @@ static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
dma_addr_t dma_addr)
{
#if defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_64BIT)
return dma_addr;
return dma_to_phys(dev, dma_addr);
#elif defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr & 0x0fffffff);
#else

View file

@ -32,8 +32,7 @@
#define LOONGSON_INT_ROUTER_LPC LOONGSON_INT_ROUTER_ENTRY(0x0a)
#define LOONGSON_INT_ROUTER_HT1(n) LOONGSON_INT_ROUTER_ENTRY(n + 0x18)
#define LOONGSON_INT_CORE0_INT0 0x11 /* route to int 0 of core 0 */
#define LOONGSON_INT_CORE0_INT1 0x21 /* route to int 1 of core 0 */
#define LOONGSON_INT_COREx_INTy(x, y) (1<<(x) | 1<<(y+4)) /* route to int y of core x */
#endif

View file

@ -35,7 +35,7 @@ extern void __init prom_init_cmdline(void);
extern void __init prom_init_machtype(void);
extern void __init prom_init_env(void);
#ifdef CONFIG_LOONGSON_UART_BASE
extern unsigned long _loongson_uart_base, loongson_uart_base;
extern unsigned long _loongson_uart_base[], loongson_uart_base[];
extern void prom_init_loongson_uart_base(void);
#endif

View file

@ -0,0 +1,55 @@
#ifndef __LOONGSON_HWMON_H_
#define __LOONGSON_HWMON_H_
#include <linux/types.h>
#define MIN_TEMP 0
#define MAX_TEMP 255
#define NOT_VALID_TEMP 999
typedef int (*get_temp_fun)(int);
extern int loongson3_cpu_temp(int);
/* 0:Max speed, 1:Manual, 2:Auto */
enum fan_control_mode {
FAN_FULL_MODE = 0,
FAN_MANUAL_MODE = 1,
FAN_AUTO_MODE = 2,
FAN_MODE_END
};
struct temp_range {
u8 low;
u8 high;
u8 level;
};
#define CONSTANT_SPEED_POLICY 0 /* at constent speed */
#define STEP_SPEED_POLICY 1 /* use up/down arrays to describe policy */
#define KERNEL_HELPER_POLICY 2 /* kernel as a helper to fan control */
#define MAX_STEP_NUM 16
#define MAX_FAN_LEVEL 255
/* loongson_fan_policy works when fan work at FAN_AUTO_MODE */
struct loongson_fan_policy {
u8 type;
/* percent only used when type is CONSTANT_SPEED_POLICY */
u8 percent;
/* period between two check. (Unit: S) */
u8 adjust_period;
/* fan adjust usually depend on a temprature input */
get_temp_fun depend_temp;
/* up_step/down_step used when type is STEP_SPEED_POLICY */
u8 up_step_num;
u8 down_step_num;
struct temp_range up_step[MAX_STEP_NUM];
struct temp_range down_step[MAX_STEP_NUM];
struct delayed_work work;
};
#endif /* __LOONGSON_HWMON_H_*/

View file

@ -26,7 +26,7 @@
#ifdef CONFIG_LOONGSON_MACH3X
#define LOONGSON_MACHTYPE MACH_LEMOTE_A1101
#define LOONGSON_MACHTYPE MACH_LOONGSON_GENERIC
#endif /* CONFIG_LOONGSON_MACH3X */

View file

@ -3,7 +3,7 @@
#ifdef CONFIG_NUMA
#define cpu_to_node(cpu) ((cpu) >> 2)
#define cpu_to_node(cpu) (cpu_logical_map(cpu) >> 2)
#define parent_node(node) (node)
#define cpumask_of_node(node) (&__node_data[(node)]->cpumask)

View file

@ -0,0 +1,7 @@
#ifndef __ASM_MACH_LOONGSON_WORKAROUNDS_H_
#define __ASM_MACH_LOONGSON_WORKAROUNDS_H_
#define WORKAROUND_CPUFREQ 0x00000001
#define WORKAROUND_CPUHOTPLUG 0x00000002
#endif

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2014 Zhang, Keguang <keguang.zhang@gmail.com>
*
* Loongson 1 CPUFreq platform support.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef __ASM_MACH_LOONGSON1_CPUFREQ_H
#define __ASM_MACH_LOONGSON1_CPUFREQ_H
struct plat_ls1x_cpufreq {
const char *clk_name; /* CPU clk */
const char *osc_clk_name; /* OSC clk */
unsigned int max_freq; /* in kHz */
unsigned int min_freq; /* in kHz */
};
#endif /* __ASM_MACH_LOONGSON1_CPUFREQ_H */

View file

@ -16,6 +16,7 @@
#define DEFAULT_MEMSIZE 256 /* If no memsize provided */
/* Loongson 1 Register Bases */
#define LS1X_MUX_BASE 0x1fd00420
#define LS1X_INTC_BASE 0x1fd01040
#define LS1X_EHCI_BASE 0x1fe00000
#define LS1X_OHCI_BASE 0x1fe08000
@ -31,7 +32,10 @@
#define LS1X_I2C0_BASE 0x1fe58000
#define LS1X_I2C1_BASE 0x1fe68000
#define LS1X_I2C2_BASE 0x1fe70000
#define LS1X_PWM_BASE 0x1fe5c000
#define LS1X_PWM0_BASE 0x1fe5c000
#define LS1X_PWM1_BASE 0x1fe5c010
#define LS1X_PWM2_BASE 0x1fe5c020
#define LS1X_PWM3_BASE 0x1fe5c030
#define LS1X_WDT_BASE 0x1fe5c060
#define LS1X_RTC_BASE 0x1fe64000
#define LS1X_AC97_BASE 0x1fe74000
@ -39,6 +43,8 @@
#define LS1X_CLK_BASE 0x1fe78030
#include <regs-clk.h>
#include <regs-mux.h>
#include <regs-pwm.h>
#include <regs-wdt.h>
#endif /* __ASM_MACH_LOONGSON1_LOONGSON1_H */

View file

@ -13,10 +13,12 @@
#include <linux/platform_device.h>
extern struct platform_device ls1x_uart_device;
extern struct platform_device ls1x_eth0_device;
extern struct platform_device ls1x_ehci_device;
extern struct platform_device ls1x_rtc_device;
extern struct platform_device ls1x_uart_pdev;
extern struct platform_device ls1x_cpufreq_pdev;
extern struct platform_device ls1x_eth0_pdev;
extern struct platform_device ls1x_eth1_pdev;
extern struct platform_device ls1x_ehci_pdev;
extern struct platform_device ls1x_rtc_pdev;
extern void __init ls1x_clk_init(void);
extern void __init ls1x_serial_setup(struct platform_device *pdev);

View file

@ -20,15 +20,32 @@
/* Clock PLL Divisor Register Bits */
#define DIV_DC_EN (0x1 << 31)
#define DIV_DC_RST (0x1 << 30)
#define DIV_CPU_EN (0x1 << 25)
#define DIV_CPU_RST (0x1 << 24)
#define DIV_DDR_EN (0x1 << 19)
#define DIV_DDR_RST (0x1 << 18)
#define RST_DC_EN (0x1 << 5)
#define RST_DC (0x1 << 4)
#define RST_DDR_EN (0x1 << 3)
#define RST_DDR (0x1 << 2)
#define RST_CPU_EN (0x1 << 1)
#define RST_CPU 0x1
#define DIV_DC_SHIFT 26
#define DIV_CPU_SHIFT 20
#define DIV_DDR_SHIFT 14
#define DIV_DC_WIDTH 5
#define DIV_CPU_WIDTH 5
#define DIV_DDR_WIDTH 5
#define DIV_DC_WIDTH 4
#define DIV_CPU_WIDTH 4
#define DIV_DDR_WIDTH 4
#define BYPASS_DC_SHIFT 12
#define BYPASS_DDR_SHIFT 10
#define BYPASS_CPU_SHIFT 8
#define BYPASS_DC_WIDTH 1
#define BYPASS_DDR_WIDTH 1
#define BYPASS_CPU_WIDTH 1
#endif /* __ASM_MACH_LOONGSON1_REGS_CLK_H */

View file

@ -0,0 +1,67 @@
/*
* Copyright (c) 2014 Zhang, Keguang <keguang.zhang@gmail.com>
*
* Loongson 1 MUX Register Definitions.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef __ASM_MACH_LOONGSON1_REGS_MUX_H
#define __ASM_MACH_LOONGSON1_REGS_MUX_H
#define LS1X_MUX_REG(x) \
((void __iomem *)KSEG1ADDR(LS1X_MUX_BASE + (x)))
#define LS1X_MUX_CTRL0 LS1X_MUX_REG(0x0)
#define LS1X_MUX_CTRL1 LS1X_MUX_REG(0x4)
/* MUX CTRL0 Register Bits */
#define UART0_USE_PWM23 (0x1 << 28)
#define UART0_USE_PWM01 (0x1 << 27)
#define UART1_USE_LCD0_5_6_11 (0x1 << 26)
#define I2C2_USE_CAN1 (0x1 << 25)
#define I2C1_USE_CAN0 (0x1 << 24)
#define NAND3_USE_UART5 (0x1 << 23)
#define NAND3_USE_UART4 (0x1 << 22)
#define NAND3_USE_UART1_DAT (0x1 << 21)
#define NAND3_USE_UART1_CTS (0x1 << 20)
#define NAND3_USE_PWM23 (0x1 << 19)
#define NAND3_USE_PWM01 (0x1 << 18)
#define NAND2_USE_UART5 (0x1 << 17)
#define NAND2_USE_UART4 (0x1 << 16)
#define NAND2_USE_UART1_DAT (0x1 << 15)
#define NAND2_USE_UART1_CTS (0x1 << 14)
#define NAND2_USE_PWM23 (0x1 << 13)
#define NAND2_USE_PWM01 (0x1 << 12)
#define NAND1_USE_UART5 (0x1 << 11)
#define NAND1_USE_UART4 (0x1 << 10)
#define NAND1_USE_UART1_DAT (0x1 << 9)
#define NAND1_USE_UART1_CTS (0x1 << 8)
#define NAND1_USE_PWM23 (0x1 << 7)
#define NAND1_USE_PWM01 (0x1 << 6)
#define GMAC1_USE_UART1 (0x1 << 4)
#define GMAC1_USE_UART0 (0x1 << 3)
#define LCD_USE_UART0_DAT (0x1 << 2)
#define LCD_USE_UART15 (0x1 << 1)
#define LCD_USE_UART0 0x1
/* MUX CTRL1 Register Bits */
#define USB_RESET (0x1 << 31)
#define SPI1_CS_USE_PWM01 (0x1 << 24)
#define SPI1_USE_CAN (0x1 << 23)
#define DISABLE_DDR_CONFSPACE (0x1 << 20)
#define DDR32TO16EN (0x1 << 16)
#define GMAC1_SHUT (0x1 << 13)
#define GMAC0_SHUT (0x1 << 12)
#define USB_SHUT (0x1 << 11)
#define UART1_3_USE_CAN1 (0x1 << 5)
#define UART1_2_USE_CAN0 (0x1 << 4)
#define GMAC1_USE_TXCLK (0x1 << 3)
#define GMAC0_USE_TXCLK (0x1 << 2)
#define GMAC1_USE_PWM23 (0x1 << 1)
#define GMAC0_USE_PWM01 0x1
#endif /* __ASM_MACH_LOONGSON1_REGS_MUX_H */

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2014 Zhang, Keguang <keguang.zhang@gmail.com>
*
* Loongson 1 PWM Register Definitions.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef __ASM_MACH_LOONGSON1_REGS_PWM_H
#define __ASM_MACH_LOONGSON1_REGS_PWM_H
/* Loongson 1 PWM Timer Register Definitions */
#define PWM_CNT 0x0
#define PWM_HRC 0x4
#define PWM_LRC 0x8
#define PWM_CTRL 0xc
/* PWM Control Register Bits */
#define CNT_RST (0x1 << 7)
#define INT_SR (0x1 << 6)
#define INT_EN (0x1 << 5)
#define PWM_SINGLE (0x1 << 4)
#define PWM_OE (0x1 << 3)
#define CNT_EN 0x1
#endif /* __ASM_MACH_LOONGSON1_REGS_PWM_H */

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
*
* Loongson 1 watchdog register definitions.
* Loongson 1 Watchdog Register Definitions.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@ -12,11 +12,8 @@
#ifndef __ASM_MACH_LOONGSON1_REGS_WDT_H
#define __ASM_MACH_LOONGSON1_REGS_WDT_H
#define LS1X_WDT_REG(x) \
((void __iomem *)KSEG1ADDR(LS1X_WDT_BASE + (x)))
#define LS1X_WDT_EN LS1X_WDT_REG(0x0)
#define LS1X_WDT_SET LS1X_WDT_REG(0x4)
#define LS1X_WDT_TIMER LS1X_WDT_REG(0x8)
#define WDT_EN 0x0
#define WDT_TIMER 0x4
#define WDT_SET 0x8
#endif /* __ASM_MACH_LOONGSON1_REGS_WDT_H */

View file

@ -2,7 +2,6 @@
#define __ASM_MACH_MIPS_IRQ_H
#define GIC_NUM_INTRS (24 + NR_CPUS * 2)
#define NR_IRQS 256
#include_next <irq.h>

View file

@ -49,6 +49,7 @@
#include <linux/types.h>
#include <asm/compiler.h>
#include <asm/war.h>
#ifndef R10000_LLSC_WAR
@ -84,8 +85,8 @@ static inline void set_value_reg32(volatile u32 *const addr,
" "__beqz"%0, 1b \n"
" nop \n"
" .set pop \n"
: "=&r" (temp), "=m" (*addr)
: "ir" (~mask), "ir" (value), "m" (*addr));
: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
: "ir" (~mask), "ir" (value), GCC_OFF12_ASM() (*addr));
}
/*
@ -105,8 +106,8 @@ static inline void set_reg32(volatile u32 *const addr,
" "__beqz"%0, 1b \n"
" nop \n"
" .set pop \n"
: "=&r" (temp), "=m" (*addr)
: "ir" (mask), "m" (*addr));
: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
: "ir" (mask), GCC_OFF12_ASM() (*addr));
}
/*
@ -126,8 +127,8 @@ static inline void clear_reg32(volatile u32 *const addr,
" "__beqz"%0, 1b \n"
" nop \n"
" .set pop \n"
: "=&r" (temp), "=m" (*addr)
: "ir" (~mask), "m" (*addr));
: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
: "ir" (~mask), GCC_OFF12_ASM() (*addr));
}
/*
@ -147,8 +148,8 @@ static inline void toggle_reg32(volatile u32 *const addr,
" "__beqz"%0, 1b \n"
" nop \n"
" .set pop \n"
: "=&r" (temp), "=m" (*addr)
: "ir" (mask), "m" (*addr));
: "=&r" (temp), "=" GCC_OFF12_ASM() (*addr)
: "ir" (mask), GCC_OFF12_ASM() (*addr));
}
/*
@ -219,8 +220,8 @@ static inline u32 blocking_read_reg32(volatile u32 *const addr)
" .set arch=r4000 \n" \
"1: ll %0, %1 #custom_read_reg32 \n" \
" .set pop \n" \
: "=r" (tmp), "=m" (*address) \
: "m" (*address))
: "=r" (tmp), "=" GCC_OFF12_ASM() (*address) \
: GCC_OFF12_ASM() (*address))
#define custom_write_reg32(address, tmp) \
__asm__ __volatile__( \
@ -230,7 +231,7 @@ static inline u32 blocking_read_reg32(volatile u32 *const addr)
" "__beqz"%0, 1b \n" \
" nop \n" \
" .set pop \n" \
: "=&r" (tmp), "=m" (*address) \
: "0" (tmp), "m" (*address))
: "=&r" (tmp), "=" GCC_OFF12_ASM() (*address) \
: "0" (tmp), GCC_OFF12_ASM() (*address))
#endif /* __ASM_REGOPS_H__ */

View file

@ -13,6 +13,13 @@
#ifndef _MT7620_REGS_H_
#define _MT7620_REGS_H_
enum mt762x_soc_type {
MT762X_SOC_UNKNOWN = 0,
MT762X_SOC_MT7620A,
MT762X_SOC_MT7620N,
MT762X_SOC_MT7628AN,
};
#define MT7620_SYSC_BASE 0x10000000
#define SYSC_REG_CHIP_NAME0 0x00
@ -25,11 +32,9 @@
#define SYSC_REG_CPLL_CONFIG0 0x54
#define SYSC_REG_CPLL_CONFIG1 0x58
#define MT7620N_CHIP_NAME0 0x33365452
#define MT7620N_CHIP_NAME1 0x20203235
#define MT7620A_CHIP_NAME0 0x3637544d
#define MT7620A_CHIP_NAME1 0x20203032
#define MT7620_CHIP_NAME0 0x3637544d
#define MT7620_CHIP_NAME1 0x20203032
#define MT7628_CHIP_NAME1 0x20203832
#define SYSCFG0_XTAL_FREQ_SEL BIT(6)
@ -74,6 +79,9 @@
#define SYSCFG0_DRAM_TYPE_DDR1 1
#define SYSCFG0_DRAM_TYPE_DDR2 2
#define SYSCFG0_DRAM_TYPE_DDR2_MT7628 0
#define SYSCFG0_DRAM_TYPE_DDR1_MT7628 1
#define MT7620_DRAM_BASE 0x0
#define MT7620_SDRAM_SIZE_MIN 2
#define MT7620_SDRAM_SIZE_MAX 64
@ -82,7 +90,6 @@
#define MT7620_DDR2_SIZE_MIN 32
#define MT7620_DDR2_SIZE_MAX 256
#define MT7620_GPIO_MODE_I2C BIT(0)
#define MT7620_GPIO_MODE_UART0_SHIFT 2
#define MT7620_GPIO_MODE_UART0_MASK 0x7
#define MT7620_GPIO_MODE_UART0(x) ((x) << MT7620_GPIO_MODE_UART0_SHIFT)
@ -94,15 +101,40 @@
#define MT7620_GPIO_MODE_GPIO_UARTF 0x5
#define MT7620_GPIO_MODE_GPIO_I2S 0x6
#define MT7620_GPIO_MODE_GPIO 0x7
#define MT7620_GPIO_MODE_UART1 BIT(5)
#define MT7620_GPIO_MODE_MDIO BIT(8)
#define MT7620_GPIO_MODE_RGMII1 BIT(9)
#define MT7620_GPIO_MODE_RGMII2 BIT(10)
#define MT7620_GPIO_MODE_SPI BIT(11)
#define MT7620_GPIO_MODE_SPI_REF_CLK BIT(12)
#define MT7620_GPIO_MODE_WLED BIT(13)
#define MT7620_GPIO_MODE_JTAG BIT(15)
#define MT7620_GPIO_MODE_EPHY BIT(15)
#define MT7620_GPIO_MODE_WDT BIT(22)
#define MT7620_GPIO_MODE_NAND 0
#define MT7620_GPIO_MODE_SD 1
#define MT7620_GPIO_MODE_ND_SD_GPIO 2
#define MT7620_GPIO_MODE_ND_SD_MASK 0x3
#define MT7620_GPIO_MODE_ND_SD_SHIFT 18
#define MT7620_GPIO_MODE_PCIE_RST 0
#define MT7620_GPIO_MODE_PCIE_REF 1
#define MT7620_GPIO_MODE_PCIE_GPIO 2
#define MT7620_GPIO_MODE_PCIE_MASK 0x3
#define MT7620_GPIO_MODE_PCIE_SHIFT 16
#define MT7620_GPIO_MODE_WDT_RST 0
#define MT7620_GPIO_MODE_WDT_REF 1
#define MT7620_GPIO_MODE_WDT_GPIO 2
#define MT7620_GPIO_MODE_WDT_MASK 0x3
#define MT7620_GPIO_MODE_WDT_SHIFT 21
#define MT7620_GPIO_MODE_I2C 0
#define MT7620_GPIO_MODE_UART1 5
#define MT7620_GPIO_MODE_MDIO 8
#define MT7620_GPIO_MODE_RGMII1 9
#define MT7620_GPIO_MODE_RGMII2 10
#define MT7620_GPIO_MODE_SPI 11
#define MT7620_GPIO_MODE_SPI_REF_CLK 12
#define MT7620_GPIO_MODE_WLED 13
#define MT7620_GPIO_MODE_JTAG 15
#define MT7620_GPIO_MODE_EPHY 15
#define MT7620_GPIO_MODE_PA 20
static inline int mt7620_get_eco(void)
{
return rt_sysc_r32(SYSC_REG_CHIP_REV) & CHIP_REV_ECO_MASK;
}
#endif

View file

@ -0,0 +1,55 @@
/*
* 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
* publishhed by the Free Software Foundation.
*
* Copyright (C) 2012 John Crispin <blogic@openwrt.org>
*/
#ifndef _RT288X_PINMUX_H__
#define _RT288X_PINMUX_H__
#define FUNC(name, value, pin_first, pin_count) \
{ name, value, pin_first, pin_count }
#define GRP(_name, _func, _mask, _shift) \
{ .name = _name, .mask = _mask, .shift = _shift, \
.func = _func, .gpio = _mask, \
.func_count = ARRAY_SIZE(_func) }
#define GRP_G(_name, _func, _mask, _gpio, _shift) \
{ .name = _name, .mask = _mask, .shift = _shift, \
.func = _func, .gpio = _gpio, \
.func_count = ARRAY_SIZE(_func) }
struct rt2880_pmx_group;
struct rt2880_pmx_func {
const char *name;
const char value;
int pin_first;
int pin_count;
int *pins;
int *groups;
int group_count;
int enabled;
};
struct rt2880_pmx_group {
const char *name;
int enabled;
const u32 shift;
const char mask;
const char gpio;
struct rt2880_pmx_func *func;
int func_count;
};
extern struct rt2880_pmx_group *rt2880_pinmux_data;
#endif

View file

@ -26,6 +26,13 @@ static inline u32 rt_sysc_r32(unsigned reg)
return __raw_readl(rt_sysc_membase + reg);
}
static inline void rt_sysc_m32(u32 clr, u32 set, unsigned reg)
{
u32 val = rt_sysc_r32(reg) & ~clr;
__raw_writel(val | set, rt_sysc_membase + reg);
}
static inline void rt_memc_w32(u32 val, unsigned reg)
{
__raw_writel(val, rt_memc_membase + reg);

Some files were not shown because too many files have changed in this diff Show more