Commit e2464688 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull MIPS updates from Ralf Baechle:
 "This is the main pull request for MIPS for 4.5 plus some 4.4 fixes.

  The executive summary:

   - ATH79 platform improvments, use DT bindings for the ATH79 USB PHY.
   - Avoid useless rebuilds for zboot.
   - jz4780: Add NEMC, BCH and NAND device tree nodes
   - Initial support for the MicroChip's DT platform.  As all the device
     drivers are missing this is still of limited use.
   - Some Loongson3 cleanups.
   - The unavoidable whitespace polishing.
   - Reduce clock skew when synchronizing the CPU cycle counters on CPU
     startup.
   - Add MIPS R6 fixes.
   - Lots of cleanups across arch/mips as fallout from KVM.
   - Lots of minor fixes and changes for IEEE 754-2008 support to the
     FPU emulator / fp-assist software.
   - Minor Ralink, BCM47xx and bcm963xx platform support improvments.
   - Support SMP on BCM63168"

* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (84 commits)
  MIPS: zboot: Add support for serial debug using the PROM
  MIPS: zboot: Avoid useless rebuilds
  MIPS: BMIPS: Enable ARCH_WANT_OPTIONAL_GPIOLIB
  MIPS: bcm63xx: nvram: Remove unused bcm63xx_nvram_get_psi_size() function
  MIPS: bcm963xx: Update bcm_tag field image_sequence
  MIPS: bcm963xx: Move extended flash address to bcm_tag header file
  MIPS: bcm963xx: Move Broadcom BCM963xx image tag data structure
  MIPS: bcm63xx: nvram: Use nvram structure definition from header file
  MIPS: bcm963xx: Add Broadcom BCM963xx board nvram data structure
  MAINTAINERS: Add KVM for MIPS entry
  MIPS: KVM: Add missing newline to kvm_err()
  MIPS: Move KVM specific opcodes into asm/inst.h
  MIPS: KVM: Use cacheops.h definitions
  MIPS: Break down cacheops.h definitions
  MIPS: Use EXCCODE_ constants with set_except_vector()
  MIPS: Update trap codes
  MIPS: Move Cause.ExcCode trap codes to mipsregs.h
  MIPS: KVM: Make kvm_mips_{init,exit}() static
  MIPS: KVM: Refactor added offsetof()s
  MIPS: KVM: Convert EXPORT_SYMBOL to _GPL
  ...
parents e1c10879 07d17f09
Microchip PIC32 Interrupt Controller
====================================
The Microchip PIC32 contains an Enhanced Vectored Interrupt Controller (EVIC).
It handles all internal and external interrupts. This controller exists outside
of the CPU and is the arbitrator of all interrupts (including interrupts from
the CPU itself) before they are presented to the CPU.
External interrupts have a software configurable edge polarity. Non external
interrupts have a type and polarity that is determined by the source of the
interrupt.
Required properties
-------------------
- compatible: Should be "microchip,pic32mzda-evic"
- reg: Specifies physical base address and size of register range.
- interrupt-controller: Identifies the node as an interrupt controller.
- #interrupt cells: Specifies the number of cells used to encode an interrupt
source connected to this controller. The value shall be 2 and interrupt
descriptor shall have the following format:
<hw_irq irq_type>
hw_irq - represents the hardware interrupt number as in the data sheet.
irq_type - is used to describe the type and polarity of an interrupt. For
internal interrupts use IRQ_TYPE_EDGE_RISING for non persistent interrupts and
IRQ_TYPE_LEVEL_HIGH for persistent interrupts. For external interrupts use
IRQ_TYPE_EDGE_RISING or IRQ_TYPE_EDGE_FALLING to select the desired polarity.
Optional properties
-------------------
- microchip,external-irqs: u32 array of external interrupts with software
polarity configuration. This array corresponds to the bits in the INTCON
SFR.
Example
-------
evic: interrupt-controller@1f810000 {
compatible = "microchip,pic32mzda-evic";
interrupt-controller;
#interrupt-cells = <2>;
reg = <0x1f810000 0x1000>;
microchip,external-irqs = <3 8 13 18 23>;
};
Each device/peripheral must request its interrupt line with the associated type
and polarity.
Internal interrupt DTS snippet
------------------------------
device@1f800000 {
...
interrupts = <113 IRQ_TYPE_LEVEL_HIGH>;
...
};
External interrupt DTS snippet
------------------------------
device@1f800000 {
...
interrupts = <3 IRQ_TYPE_EDGE_RISING>;
...
};
* Microchip PIC32MZDA Platforms
PIC32MZDA Starter Kit
Required root node properties:
- compatible = "microchip,pic32mzda-sk", "microchip,pic32mzda"
CPU nodes:
----------
A "cpus" node is required. Required properties:
- #address-cells: Must be 1.
- #size-cells: Must be 0.
A CPU sub-node is also required. Required properties:
- device_type: Must be "cpu".
- compatible: Must be "mti,mips14KEc".
Example:
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu0: cpu@0 {
device_type = "cpu";
compatible = "mti,mips14KEc";
};
};
Boot protocol
--------------
In accordance with Unified Hosting Interface Reference Manual (MD01069), the
bootloader must pass the following arguments to the kernel:
- $a0: -2.
- $a1: KSEG0 address of the flattened device-tree blob.
Mediatek Gigabit Switch
=======================
The mediatek gigabit switch can be found on Mediatek SoCs (mt7620, mt7621).
Required properties:
- compatible: Should be "mediatek,mt7620-gsw" or "mediatek,mt7621-gsw"
- reg: Address and length of the register set for the device
- interrupt-parent: Should be the phandle for the interrupt controller
that services interrupts for this device
- interrupts: Should contain the gigabit switches interrupt
- resets: Should contain the gigabit switches resets
- reset-names: Should contain the reset names "gsw"
Example:
gsw@10110000 {
compatible = "ralink,mt7620-gsw";
reg = <0x10110000 8000>;
resets = <&rstctrl 23>;
reset-names = "gsw";
interrupt-parent = <&intc>;
interrupts = <17>;
};
Ralink Frame Engine Ethernet controller
=======================================
The Ralink frame engine ethernet controller can be found on Ralink and
Mediatek SoCs (RT288x, RT3x5x, RT366x, RT388x, rt5350, mt7620, mt7621, mt76x8).
Depending on the SoC, there is a number of ports connected to the CPU port
directly and/or via a (gigabit-)switch.
* Ethernet controller node
Required properties:
- compatible: Should be one of "ralink,rt2880-eth", "ralink,rt3050-eth",
"ralink,rt3050-eth", "ralink,rt3883-eth", "ralink,rt5350-eth",
"mediatek,mt7620-eth", "mediatek,mt7621-eth"
- reg: Address and length of the register set for the device
- interrupt-parent: Should be the phandle for the interrupt controller
that services interrupts for this device
- interrupts: Should contain the frame engines interrupt
- resets: Should contain the frame engines resets
- reset-names: Should contain the reset names "fe". If a switch is present
"esw" is also required.
* Ethernet port node
Required properties:
- compatible: Should be "ralink,eth-port"
- reg: The number of the physical port
- phy-handle: reference to the node describing the phy
Example:
mdio-bus {
...
phy0: ethernet-phy@0 {
phy-mode = "mii";
reg = <0>;
};
};
ethernet@400000 {
compatible = "ralink,rt2880-eth";
reg = <0x00400000 10000>;
#address-cells = <1>;
#size-cells = <0>;
resets = <&rstctrl 18>;
reset-names = "fe";
interrupt-parent = <&cpuintc>;
interrupts = <5>;
port@0 {
compatible = "ralink,eth-port";
reg = <0>;
phy-handle = <&phy0>;
};
};
Ralink Fast Ethernet Embedded Switch
====================================
The ralink fast ethernet embedded switch can be found on Ralink and Mediatek
SoCs (RT3x5x, RT5350, MT76x8).
Required properties:
- compatible: Should be "ralink,rt3050-esw"
- reg: Address and length of the register set for the device
- interrupt-parent: Should be the phandle for the interrupt controller
that services interrupts for this device
- interrupts: Should contain the embedded switches interrupt
- resets: Should contain the embedded switches resets
- reset-names: Should contain the reset names "esw"
Optional properties:
- ralink,portmap: can be used to choose if the default switch setup is
llllw or wllll
- ralink,led_polarity: override the active high/low settings of the leds
Example:
esw@10110000 {
compatible = "ralink,rt3050-esw";
reg = <0x10110000 8000>;
resets = <&rstctrl 23>;
reset-names = "esw";
interrupt-parent = <&intc>;
interrupts = <17>;
};
* Atheros AR71XX/9XXX USB PHY
Required properties:
- compatible: "qca,ar7100-usb-phy"
- #phys-cells: should be 0
- reset-names: "usb-phy"[, "usb-suspend-override"]
- resets: references to the reset controllers
Example:
usb-phy {
compatible = "qca,ar7100-usb-phy";
reset-names = "usb-phy", "usb-suspend-override";
resets = <&rst 4>, <&rst 3>;
#phy-cells = <0>;
};
......@@ -1454,6 +1454,41 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
In such case C2/C3 won't be used again.
idle=nomwait: Disable mwait for CPU C-states
ieee754= [MIPS] Select IEEE Std 754 conformance mode
Format: { strict | legacy | 2008 | relaxed }
Default: strict
Choose which programs will be accepted for execution
based on the IEEE 754 NaN encoding(s) supported by
the FPU and the NaN encoding requested with the value
of an ELF file header flag individually set by each
binary. Hardware implementations are permitted to
support either or both of the legacy and the 2008 NaN
encoding mode.
Available settings are as follows:
strict accept binaries that request a NaN encoding
supported by the FPU
legacy only accept legacy-NaN binaries, if supported
by the FPU
2008 only accept 2008-NaN binaries, if supported
by the FPU
relaxed accept any binaries regardless of whether
supported by the FPU
The FPU emulator is always able to support both NaN
encodings, so if no FPU hardware is present or it has
been disabled with 'nofpu', then the settings of
'legacy' and '2008' strap the emulator accordingly,
'relaxed' straps the emulator for both legacy-NaN and
2008-NaN, whereas 'strict' enables legacy-NaN only on
legacy processors and both NaN encodings on MIPS32 or
MIPS64 CPUs.
The setting for ABS.fmt/NEG.fmt instruction execution
mode generally follows that for the NaN encoding,
except where unsupported by hardware.
ignore_loglevel [KNL]
Ignore loglevel setting - this will print /all/
kernel messages to the console. Useful for debugging.
......
......@@ -2420,6 +2420,8 @@ F: arch/mips/kernel/*bmips*
F: arch/mips/boot/dts/brcm/bcm*.dts*
F: drivers/irqchip/irq-bcm7*
F: drivers/irqchip/irq-brcmstb*
F: include/linux/bcm963xx_nvram.h
F: include/linux/bcm963xx_tag.h
BROADCOM TG3 GIGABIT ETHERNET DRIVER
M: Prashant Sreedharan <prashant@broadcom.com>
......@@ -6216,6 +6218,14 @@ F: arch/arm64/include/uapi/asm/kvm*
F: arch/arm64/include/asm/kvm*
F: arch/arm64/kvm/
KERNEL VIRTUAL MACHINE FOR MIPS (KVM/mips)
M: James Hogan <james.hogan@imgtec.com>
L: linux-mips@linux-mips.org
S: Supported
F: arch/mips/include/uapi/asm/kvm*
F: arch/mips/include/asm/kvm*
F: arch/mips/kvm/
KEXEC
M: Eric Biederman <ebiederm@xmission.com>
W: http://kernel.org/pub/linux/utils/kernel/kexec/
......@@ -6313,6 +6323,12 @@ S: Maintained
F: net/l3mdev
F: include/net/l3mdev.h
LANTIQ MIPS ARCHITECTURE
M: John Crispin <blogic@openwrt.org>
L: linux-mips@linux-mips.org
S: Maintained
F: arch/mips/lantiq
LAPB module
L: linux-x25@vger.kernel.org
S: Orphan
......@@ -8997,6 +9013,12 @@ L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/fbdev/aty/aty128fb.c
RALINK MIPS ARCHITECTURE
M: John Crispin <blogic@openwrt.org>
L: linux-mips@linux-mips.org
S: Maintained
F: arch/mips/ralink
RALINK RT2X00 WIRELESS LAN DRIVER
P: rt2x00 project
M: Stanislaw Gruszka <sgruszka@redhat.com>
......
......@@ -21,6 +21,7 @@ platforms += mti-malta
platforms += mti-sead3
platforms += netlogic
platforms += paravirt
platforms += pic32
platforms += pistachio
platforms += pmcs-msp71xx
platforms += pnx833x
......
......@@ -169,6 +169,7 @@ config BMIPS_GENERIC
select USB_EHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN
select USB_OHCI_BIG_ENDIAN_DESC if CPU_BIG_ENDIAN
select USB_OHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN
select ARCH_WANT_OPTIONAL_GPIOLIB
help
Build a generic DT-based kernel image that boots on select
BCM33xx cable modem chips, BCM63xx DSL chips, and BCM7xxx set-top
......@@ -480,6 +481,14 @@ config MIPS_MALTA
This enables support for the MIPS Technologies Malta evaluation
board.
config MACH_PIC32
bool "Microchip PIC32 Family"
help
This enables support for the Microchip PIC32 family of platforms.
Microchip PIC32 is a family of general-purpose 32 bit MIPS core
microcontrollers.
config MIPS_SEAD3
bool "MIPS SEAD3 board"
select BOOT_ELF32
......@@ -979,6 +988,7 @@ source "arch/mips/jazz/Kconfig"
source "arch/mips/jz4740/Kconfig"
source "arch/mips/lantiq/Kconfig"
source "arch/mips/lasat/Kconfig"
source "arch/mips/pic32/Kconfig"
source "arch/mips/pistachio/Kconfig"
source "arch/mips/pmcs-msp71xx/Kconfig"
source "arch/mips/ralink/Kconfig"
......@@ -1755,6 +1765,10 @@ config SYS_SUPPORTS_ZBOOT_UART16550
bool
select SYS_SUPPORTS_ZBOOT
config SYS_SUPPORTS_ZBOOT_UART_PROM
bool
select SYS_SUPPORTS_ZBOOT
config CPU_LOONGSON2
bool
select CPU_SUPPORTS_32BIT_KERNEL
......@@ -2017,7 +2031,8 @@ config KVM_GUEST
bool "KVM Guest Kernel"
depends on BROKEN_ON_SMP
help
Select this option if building a guest kernel for KVM (Trap & Emulate) mode
Select this option if building a guest kernel for KVM (Trap & Emulate)
mode.
config KVM_GUEST_TIMER_FREQ
int "Count/Compare Timer Frequency (MHz)"
......
......@@ -166,16 +166,6 @@ cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += -Wa,-march=octeon
endif
cflags-$(CONFIG_CAVIUM_CN63XXP1) += -Wa,-mfix-cn63xxp1
cflags-$(CONFIG_CPU_BMIPS) += -march=mips32 -Wa,-mips32 -Wa,--trap
#
# binutils from v2.25 on and gcc starting from v4.9.0 treat -march=loongson3a
# as MIPS64 R1; older versions as just R1. This leaves the possibility open
# that GCC might generate R2 code for -march=loongson3a which then is rejected
# by GAS. The cc-option can't probe for this behaviour so -march=loongson3a
# can't easily be used safely within the kbuild framework.
#
cflags-$(CONFIG_CPU_LOONGSON3) += \
$(call cc-option,-march=mips64r2,-mips64r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
-Wa,-mips64r2 -Wa,--trap
cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,)
cflags-$(CONFIG_CPU_R4400_WORKAROUNDS) += $(call cc-option,-mfix-r4400,)
......
......@@ -40,7 +40,7 @@
static int gpio2_get(struct gpio_chip *chip, unsigned offset)
{
return alchemy_gpio2_get_value(offset + ALCHEMY_GPIO2_BASE);
return !!alchemy_gpio2_get_value(offset + ALCHEMY_GPIO2_BASE);
}
static void gpio2_set(struct gpio_chip *chip, unsigned offset, int value)
......@@ -68,7 +68,7 @@ static int gpio2_to_irq(struct gpio_chip *chip, unsigned offset)
static int gpio1_get(struct gpio_chip *chip, unsigned offset)
{
return alchemy_gpio1_get_value(offset + ALCHEMY_GPIO1_BASE);
return !!alchemy_gpio1_get_value(offset + ALCHEMY_GPIO1_BASE);
}
static void gpio1_set(struct gpio_chip *chip,
......@@ -119,7 +119,7 @@ struct gpio_chip alchemy_gpio_chip[] = {
static int alchemy_gpic_get(struct gpio_chip *chip, unsigned int off)
{
return au1300_gpio_get_value(off + AU1300_GPIO_BASE);
return !!au1300_gpio_get_value(off + AU1300_GPIO_BASE);
}
static void alchemy_gpic_set(struct gpio_chip *chip, unsigned int off, int v)
......
......@@ -37,7 +37,7 @@ static int ar7_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
container_of(chip, struct ar7_gpio_chip, chip);
void __iomem *gpio_in = gpch->regs + AR7_GPIO_INPUT;
return readl(gpio_in) & (1 << gpio);
return !!(readl(gpio_in) & (1 << gpio));
}
static int titan_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
......
......@@ -23,7 +23,6 @@ void ath79_clocks_init(void);
unsigned long ath79_get_sys_clk_rate(const char *id);
void ath79_ddr_ctrl_init(void);
void ath79_ddr_wb_flush(unsigned int reg);
void ath79_gpio_init(void);
......
......@@ -26,9 +26,13 @@
#include "common.h"
#include "machtypes.h"
static void __init ath79_misc_intc_domain_init(
struct device_node *node, int irq);
static void ath79_misc_irq_handler(struct irq_desc *desc)
{
void __iomem *base = ath79_reset_base;
struct irq_domain *domain = irq_desc_get_handler_data(desc);
void __iomem *base = domain->host_data;
u32 pending;
pending = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS) &
......@@ -42,15 +46,15 @@ static void ath79_misc_irq_handler(struct irq_desc *desc)
while (pending) {
int bit = __ffs(pending);
generic_handle_irq(ATH79_MISC_IRQ(bit));
generic_handle_irq(irq_linear_revmap(domain, bit));
pending &= ~BIT(bit);
}
}
static void ar71xx_misc_irq_unmask(struct irq_data *d)
{
unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE;
void __iomem *base = ath79_reset_base;
void __iomem *base = irq_data_get_irq_chip_data(d);
unsigned int irq = d->hwirq;
u32 t;
t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
......@@ -62,8 +66,8 @@ static void ar71xx_misc_irq_unmask(struct irq_data *d)
static void ar71xx_misc_irq_mask(struct irq_data *d)
{
unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE;
void __iomem *base = ath79_reset_base;
void __iomem *base = irq_data_get_irq_chip_data(d);
unsigned int irq = d->hwirq;
u32 t;
t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
......@@ -75,8 +79,8 @@ static void ar71xx_misc_irq_mask(struct irq_data *d)
static void ar724x_misc_irq_ack(struct irq_data *d)
{
unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE;
void __iomem *base = ath79_reset_base;
void __iomem *base = irq_data_get_irq_chip_data(d);
unsigned int irq = d->hwirq;
u32 t;
t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
......@@ -94,12 +98,6 @@ static struct irq_chip ath79_misc_irq_chip = {
static void __init ath79_misc_irq_init(void)
{
void __iomem *base = ath79_reset_base;
int i;
__raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
__raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
if (soc_is_ar71xx() || soc_is_ar913x())
ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask;
else if (soc_is_ar724x() ||
......@@ -110,13 +108,7 @@ static void __init ath79_misc_irq_init(void)
else
BUG();
for (i = ATH79_MISC_IRQ_BASE;
i < ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT; i++) {
irq_set_chip_and_handler(i, &ath79_misc_irq_chip,
handle_level_irq);
}
irq_set_chained_handler(ATH79_CPU_IRQ(6), ath79_misc_irq_handler);
ath79_misc_intc_domain_init(NULL, ATH79_CPU_IRQ(6));
}
static void ar934x_ip2_irq_dispatch(struct irq_desc *desc)
......@@ -256,10 +248,10 @@ asmlinkage void plat_irq_dispatch(void)
}
}
#ifdef CONFIG_IRQCHIP
static int misc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
{
irq_set_chip_and_handler(irq, &ath79_misc_irq_chip, handle_level_irq);
irq_set_chip_data(irq, d->host_data);
return 0;
}
......@@ -268,19 +260,14 @@ static const struct irq_domain_ops misc_irq_domain_ops = {
.map = misc_map,
};
static int __init ath79_misc_intc_of_init(
struct device_node *node, struct device_node *parent)
static void __init ath79_misc_intc_domain_init(
struct device_node *node, int irq)
{
void __iomem *base = ath79_reset_base;
struct irq_domain *domain;
int irq;
irq = irq_of_parse_and_map(node, 0);
if (!irq)
panic("Failed to get MISC IRQ");
domain = irq_domain_add_legacy(node, ATH79_MISC_IRQ_COUNT,
ATH79_MISC_IRQ_BASE, 0, &misc_irq_domain_ops, NULL);
ATH79_MISC_IRQ_BASE, 0, &misc_irq_domain_ops, base);
if (!domain)
panic("Failed to add MISC irqdomain");
......@@ -288,9 +275,19 @@ static int __init ath79_misc_intc_of_init(
__raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
__raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
irq_set_chained_handler_and_data(irq, ath79_misc_irq_handler, domain);
}
irq_set_chained_handler(irq, ath79_misc_irq_handler);
static int __init ath79_misc_intc_of_init(
struct device_node *node, struct device_node *parent)
{
int irq;
irq = irq_of_parse_and_map(node, 0);
if (!irq)
panic("Failed to get MISC IRQ");
ath79_misc_intc_domain_init(node, irq);
return 0;
}
......@@ -349,8 +346,6 @@ static int __init ar79_cpu_intc_of_init(
IRQCHIP_DECLARE(ar79_cpu_intc, "qca,ar7100-cpu-intc",
ar79_cpu_intc_of_init);
#endif
void __init arch_init_irq(void)
{
if (mips_machtype == ATH79_MACH_GENERIC_OF) {
......
......@@ -36,10 +36,6 @@
#define ATH79_SYS_TYPE_LEN 64
#define AR71XX_BASE_FREQ 40000000
#define AR724X_BASE_FREQ 5000000
#define AR913X_BASE_FREQ 5000000
static char ath79_sys_type[ATH79_SYS_TYPE_LEN];
static void ath79_restart(char *command)
......@@ -272,15 +268,10 @@ void __init device_tree_init(void)
unflatten_and_copy_device_tree();
}
static void __init ath79_generic_init(void)
{
/* Nothing to do */
}
MIPS_MACHINE(ATH79_MACH_GENERIC,
"Generic",
"Generic AR71XX/AR724X/AR913X based board",
ath79_generic_init);
NULL);
MIPS_MACHINE(ATH79_MACH_GENERIC_OF,
"DTB",
......
......@@ -666,9 +666,15 @@ static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out)
switch (bus->hosttype) {
case BCMA_HOSTTYPE_PCI:
memset(out, 0, sizeof(struct ssb_sprom));
/* On BCM47XX all PCI buses share the same domain */
if (config_enabled(CONFIG_BCM47XX))
snprintf(buf, sizeof(buf), "pci/%u/%u/",
bus->host_pci->bus->number + 1,
PCI_SLOT(bus->host_pci->devfn));
else
snprintf(buf, sizeof(buf), "pci/%u/%u/",
pci_domain_nr(bus->host_pci->bus) + 1,
bus->host_pci->bus->number);
bcm47xx_sprom_apply_prefix_alias(buf, sizeof(buf));
prefix = buf;
break;
......
......@@ -10,6 +10,7 @@
#define pr_fmt(fmt) "bcm63xx_nvram: " fmt
#include <linux/bcm963xx_nvram.h>
#include <linux/init.h>
#include <linux/crc32.h>
#include <linux/export.h>
......@@ -18,51 +19,19 @@
#include <bcm63xx_nvram.h>
/*
* nvram structure
*/
struct bcm963xx_nvram {
u32 version;
u8 reserved1[256];
u8 name[16];
u32 main_tp_number;
u32 psi_size;
u32 mac_addr_count;
u8 mac_addr_base[ETH_ALEN];
u8 reserved2[2];
u32 checksum_old;
u8 reserved3[720];
u32 checksum_high;
};
#define BCM63XX_DEFAULT_PSI_SIZE 64
static struct bcm963xx_nvram nvram;
static int mac_addr_used;
void __init bcm63xx_nvram_init(void *addr)
{
unsigned int check_len;
u32 crc, expected_crc;
u8 hcs_mac_addr[ETH_ALEN] = { 0x00, 0x10, 0x18, 0xff, 0xff, 0xff };
/* extract nvram data */
memcpy(&nvram, addr, sizeof(nvram));
memcpy(&nvram, addr, BCM963XX_NVRAM_V5_SIZE);
/* check checksum before using data */
if (nvram.version <= 4) {
check_len = offsetof(struct bcm963xx_nvram, reserved3);
expected_crc = nvram.checksum_old;
nvram.checksum_old = 0;
} else {
check_len = sizeof(nvram);
expected_crc = nvram.checksum_high;
nvram.checksum_high = 0;
}
crc = crc32_le(~0, (u8 *)&nvram, check_len);
if (crc != expected_crc)
if (bcm963xx_nvram_checksum(&nvram, &expected_crc, &crc))
pr_warn("nvram checksum failed, contents may be invalid (expected %08x, got %08x)\n",
expected_crc, crc);
......@@ -116,12 +85,3 @@ int bcm63xx_nvram_get_mac_address(u8 *mac)
return 0;
}
EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address);
int bcm63xx_nvram_get_psi_size(void)
{
if (nvram.psi_size > 0)
return nvram.psi_size;
return BCM63XX_DEFAULT_PSI_SIZE;
}
EXPORT_SYMBOL(bcm63xx_nvram_get_psi_size);
......@@ -105,6 +105,7 @@ static const struct bmips_quirk bmips_quirk_list[] = {
{ "brcm,bcm33843-viper", &bcm3384_viper_quirks },
{ "brcm,bcm6328", &bcm6328_quirks },
{ "brcm,bcm6368", &bcm6368_quirks },
{ "brcm,bcm63168", &bcm6368_quirks },
{ },
};
......
......@@ -29,20 +29,23 @@ KBUILD_AFLAGS := $(LINUXINCLUDE) $(KBUILD_AFLAGS) -D__ASSEMBLY__ \
-DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) \
-DKERNEL_ENTRY=$(VMLINUX_ENTRY_ADDRESS)
targets := head.o decompress.o string.o dbg.o uart-16550.o uart-alchemy.o
# decompressor objects (linked with vmlinuz)
vmlinuzobjs-y := $(obj)/head.o $(obj)/decompress.o $(obj)/string.o
ifdef CONFIG_DEBUG_ZBOOT
vmlinuzobjs-$(CONFIG_DEBUG_ZBOOT) += $(obj)/dbg.o
vmlinuzobjs-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART16550) += $(obj)/uart-16550.o
vmlinuzobjs-$(CONFIG_SYS_SUPPORTS_ZBOOT_UART_PROM) += $(obj)/uart-prom.o
vmlinuzobjs-$(CONFIG_MIPS_ALCHEMY) += $(obj)/uart-alchemy.o
endif
ifdef CONFIG_KERNEL_XZ
vmlinuzobjs-y += $(obj)/../../lib/ashldi3.o
endif
vmlinuzobjs-$(CONFIG_KERNEL_XZ) += $(obj)/ashldi3.o
$(obj)/ashldi3.o: KBUILD_CFLAGS += -I$(srctree)/arch/mips/lib
$(obj)/ashldi3.c: $(srctree)/arch/mips/lib/ashldi3.c
$(call cmd,shipped)
targets := $(notdir $(vmlinuzobjs-y))
targets += vmlinux.bin
OBJCOPYFLAGS_vmlinux.bin := $(OBJCOPYFLAGS) -O binary -R .comment -S
......@@ -60,7 +63,7 @@ targets += vmlinux.bin.z
$(obj)/vmlinux.bin.z: $(obj)/vmlinux.bin FORCE
$(call if_changed,$(tool_y))
targets += piggy.o
targets += piggy.o dummy.o
OBJCOPYFLAGS_piggy.o := --add-section=.image=$(obj)/vmlinux.bin.z \
--set-section-flags=.image=contents,alloc,load,readonly,data
$(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.bin.z FORCE
......
extern void prom_putchar(unsigned char ch);
void putc(char c)
{
prom_putchar(c);
}
......@@ -4,6 +4,7 @@ dts-dirs += ingenic
dts-dirs += lantiq
dts-dirs += mti
dts-dirs += netlogic
dts-dirs += pic32
dts-dirs += qca
dts-dirs += ralink
dts-dirs += xilfpga
......
......@@ -31,6 +31,7 @@ periph_clk: periph_clk {
};
aliases {
leds0 = &leds0;
uart0 = &uart0;
};
......@@ -81,5 +82,13 @@ reboot {
offset = <0x28>;
mask = <0x1>;
};
leds0: led-controller@10000800 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "brcm,bcm6328-leds";
reg = <0x10000800 0x24>;
status = "disabled";
};
};
};
......@@ -32,6 +32,7 @@ periph_clk: periph_clk {
};
aliases {
leds0 = &leds0;
uart0 = &uart0;
};
......@@ -50,6 +51,19 @@ ubus {
compatible = "simple-bus";
ranges;
periph_cntl: syscon@10000000 {
compatible = "syscon";
reg = <0x10000000 0x14>;
little-endian;
};
reboot: syscon-reboot@10000008 {
compatible = "syscon-reboot";
regmap = <&periph_cntl>;
offset = <0x8>;
mask = <0x1>;
};
periph_intc: periph_intc@10000020 {
compatible = "brcm,bcm3380-l2-intc";
reg = <0x10000024 0x4 0x1000002c 0x4>,
......@@ -62,6 +76,14 @@ periph_intc: periph_intc@10000020 {
interrupts = <2>;
};
leds0: led-controller@100000d0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "brcm,bcm6358-leds";
reg = <0x100000d0 0x8>;
status = "disabled";
};
uart0: serial@10000100 {
compatible = "brcm,bcm6345-uart";
reg = <0x10000100 0x18>;
......
......@@ -42,3 +42,67 @@ &uart3 {
&uart4 {
status = "okay";
};
&nemc {
status = "okay";
nandc: nand-controller@1 {
compatible = "ingenic,jz4780-nand";
reg = <1 0 0x1000000>;
#address-cells = <1>;
#size-cells = <0>;
ingenic,bch-controller = <&bch>;
ingenic,nemc-tAS = <10>;
ingenic,nemc-tAH = <5>;
ingenic,nemc-tBP = <10>;
ingenic,nemc-tAW = <15>;
ingenic,nemc-tSTRV = <100>;
nand@1 {
reg = <1>;
nand-ecc-step-size = <1024>;
nand-ecc-strength = <24>;
nand-ecc-mode = "hw";
nand-on-flash-bbt;
partitions {
compatible = "fixed-partitions";
#address-cells = <2>;
#size-cells = <2>;
partition@0 {
label = "u-boot-spl";
reg = <0x0 0x0 0x0 0x800000>;
};
partition@0x800000 {
label = "u-boot";
reg = <0x0 0x800000 0x0 0x200000>;
};
partition@0xa00000 {
label = "u-boot-env";
reg = <0x0 0xa00000 0x0 0x200000>;
};
partition@0xc00000 {
label = "boot";
reg = <0x0 0xc00000 0x0 0x4000000>;
};
partition@0x8c00000 {
label = "system";
reg = <0x0 0x4c00000 0x1 0xfb400000>;
};
};
};
};
};
&bch {
status = "okay";
};
......@@ -108,4 +108,30 @@ uart4: serial@10034000 {
status = "disabled";
};
nemc: nemc@13410000 {
compatible = "ingenic,jz4780-nemc";
reg = <0x13410000 0x10000>;
#address-cells = <2>;
#size-cells = <1>;
ranges = <1 0 0x1b000000 0x1000000
2 0 0x1a000000 0x1000000
3 0 0x19000000 0x1000000
4 0 0x18000000 0x1000000
5 0 0x17000000 0x1000000
6 0 0x16000000 0x1000000>;
clocks = <&cgu JZ4780_CLK_NEMC>;
status = "disabled";
};
bch: bch@134d0000 {
compatible = "ingenic,jz4780-bch";
reg = <0x134d0000 0x10000>;
clocks = <&cgu JZ4780_CLK_BCH>;
status = "disabled";
};
};
dtb-$(CONFIG_DTB_PIC32_MZDA_SK) += pic32mzda_sk.dtb
dtb-$(CONFIG_DTB_PIC32_NONE) += \
pic32mzda_sk.dtb
obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
# Force kbuild to make empty built-in.o if necessary
obj- += dummy.o
always := $(dtb-y)
clean-files := *.dtb *.dtb.S
/*
* Device Tree Source for PIC32MZDA clock data
*
* Purna Chandra Mandal <purna.mandal@microchip.com>
* Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
*
* Licensed under GPLv2 or later.
*/
/* all fixed rate clocks */
/ {
POSC:posc_clk { /* On-chip primary oscillator */
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
};
FRC:frc_clk { /* internal FRC oscillator */
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <8000000>;
};
BFRC:bfrc_clk { /* internal backup FRC oscillator */
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <8000000>;
};
LPRC:lprc_clk { /* internal low-power FRC oscillator */
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <32000>;
};
/* UPLL provides clock to USBCORE */
UPLL:usb_phy_clk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
clock-output-names = "usbphy_clk";
};
TxCKI:txcki_clk { /* external clock input on TxCLKI pin */
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <4000000>;
status = "disabled";
};
/* external clock input on REFCLKIx pin */
REFIx:refix_clk {
#clock-cells = <0>;
compatible = "fixed-clock";
clock-frequency = <24000000>;
status = "disabled";
};
/* PIC32 specific clks */
pic32_clktree {
#address-cells = <1>;
#size-cells = <1>;
reg = <0x1f801200 0x200>;
compatible = "microchip,pic32mzda-clk";
ranges = <0 0x1f801200 0x200>;
/* secondary oscillator; external input on SOSCI pin */
SOSC:sosc_clk@0 {
#clock-cells = <0>;
compatible = "microchip,pic32mzda-sosc";
clock-frequency = <32768>;
reg = <0x000 0x10>, /* enable reg */
<0x1d0 0x10>; /* status reg */
microchip,bit-mask = <0x02>; /* enable mask */
microchip,status-bit-mask = <0x10>; /* status-mask*/
};
FRCDIV:frcdiv_clk {
#clock-cells = <0>;
compatible = "microchip,pic32mzda-frcdivclk";
clocks = <&FRC>;
clock-output-names = "frcdiv_clk";
};
/* System PLL clock */
SYSPLL:spll_clk@020 {
#clock-cells = <0>;
compatible = "microchip,pic32mzda-syspll";
reg = <0x020 0x10>, /* SPLL register */
<0x1d0 0x10>; /* CLKSTAT register */
clocks = <&POSC>, <&FRC>;
clock-output-names = "sys_pll";
microchip,status-bit-mask = <0x80>; /* SPLLRDY */
};
/* system clock; mux with postdiv & slew */
SYSCLK:sys_clk@1c0 {
#clock-cells = <0>;
compatible = "microchip,pic32mzda-sysclk-v2";
reg = <0x1c0 0x04>; /* SLEWCON */
clocks = <&FRCDIV>, <&SYSPLL>, <&POSC>, <&SOSC>,
<&LPRC>, <&FRCDIV>;
microchip,clock-indices = <0>, <1>, <2>, <4>,
<5>, <7>;
clock-output-names = "sys_clk";
};
/* Peripheral bus1 clock */
PBCLK1:pb1_clk@140 {
reg = <0x140 0x10>;
#clock-cells = <0>;
compatible = "microchip,pic32mzda-pbclk";
clocks = <&SYSCLK>;
clock-output-names = "pb1_clk";
/* used by system modules, not gateable */
microchip,ignore-unused;
};
/* Peripheral bus2 clock */
PBCLK2:pb2_clk@150 {
reg = <0x150 0x10>;
#clock-cells = <0>;
compatible = "microchip,pic32mzda-pbclk";
clocks = <&SYSCLK>;
clock-output-names = "pb2_clk";
/* avoid gating even if unused */
microchip,ignore-unused;
};
/* Peripheral bus3 clock */
PBCLK3:pb3_clk@160 {
reg = <0x160 0x10>;
#clock-cells = <0>;
compatible = "microchip,pic32mzda-pbclk";
clocks = <&SYSCLK>;
clock-output-names = "pb3_clk";
};
/* Peripheral bus4 clock(I/O ports, GPIO) */
PBCLK4:pb4_clk@170 {
reg = <0x170 0x10>;
#clock-cells = <0>;
compatible = "microchip,pic32mzda-pbclk";
clocks = <&SYSCLK>;
clock-output-names = "pb4_clk";
};
/* Peripheral bus clock */
PBCLK5:pb5_clk@180 {
reg = <0x180 0x10>;
#clock-cells = <0>;
compatible = "microchip,pic32mzda-pbclk";
clocks = <&SYSCLK>;
clock-output-names = "pb5_clk";
};
/* Peripheral Bus6 clock; */
PBCLK6:pb6_clk@190 {
reg = <0x190 0x10>;
compatible = "microchip,pic32mzda-pbclk";
clocks = <&SYSCLK>;
#clock-cells = <0>;
};
/* Peripheral bus7 clock */
PBCLK7:pb7_clk@1a0 {
reg = <0x1a0 0x10>;
#clock-cells = <0>;
compatible = "microchip,pic32mzda-pbclk";
/* CPU is driven by this clock; so named */
clock-output-names = "cpu_clk";
clocks = <&SYSCLK>;
};
/* Reference Oscillator clock for SPI/I2S */
REFCLKO1:refo1_clk@80 {
reg = <0x080 0x20>;
#clock-cells = <0>;
compatible = "microchip,pic32mzda-refoclk";
clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
<5>, <7>, <8>, <9>;
clock-output-names = "refo1_clk";
};
/* Reference Oscillator clock for SQI */
REFCLKO2:refo2_clk@a0 {
reg = <0x0a0 0x20>;
#clock-cells = <0>;
compatible = "microchip,pic32mzda-refoclk";
clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
<5>, <7>, <8>, <9>;
clock-output-names = "refo2_clk";
};
/* Reference Oscillator clock, ADC */
REFCLKO3:refo3_clk@c0 {
reg = <0x0c0 0x20>;
compatible = "microchip,pic32mzda-refoclk";
clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
<5>, <7>, <8>, <9>;
#clock-cells = <0>;
clock-output-names = "refo3_clk";
};
/* Reference Oscillator clock */
REFCLKO4:refo4_clk@e0 {
reg = <0x0e0 0x20>;
compatible = "microchip,pic32mzda-refoclk";
clocks = <&SYSCLK>, <&PBCLK1>, <&POSC>, <&FRC>, <&LPRC>,
<&SOSC>, <&SYSPLL>, <&REFIx>, <&BFRC>;
microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
<5>, <7>, <8>, <9>;
#clock-cells = <0>;
clock-output-names = "refo4_clk";
};
/* Reference Oscillator clock, LCD */
REFCLKO5:refo5_clk@100 {
reg = <0x100 0x20>;
compatible = "microchip,pic32mzda-refoclk";
clocks = <&SYSCLK>,<&PBCLK1>,<&POSC>,<&FRC>,<&LPRC>,
<&SOSC>,<&SYSPLL>,<&REFIx>,<&BFRC>;
microchip,clock-indices = <0>, <1>, <2>, <3>, <4>,
<5>, <7>, <8>, <9>;
#clock-cells = <0>;
clock-output-names = "refo5_clk";
};
};
};
/*
* Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <dt-bindings/interrupt-controller/irq.h>
#include "pic32mzda-clk.dtsi"
/ {
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&evic>;
aliases {
gpio0 = &gpio0;
gpio1 = &gpio1;
gpio2 = &gpio2;
gpio3 = &gpio3;
gpio4 = &gpio4;
gpio5 = &gpio5;
gpio6 = &gpio6;
gpio7 = &gpio7;
gpio8 = &gpio8;
gpio9 = &gpio9;
serial0 = &uart1;
serial1 = &uart2;
serial2 = &uart3;
serial3 = &uart4;
serial4 = &uart5;
serial5 = &uart6;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = "mti,mips14KEc";
device_type = "cpu";
};
};
soc {
compatible = "microchip,pic32mzda-infra";
interrupts = <0 IRQ_TYPE_EDGE_RISING>;
};
evic: interrupt-controller@1f810000 {
compatible = "microchip,pic32mzda-evic";
interrupt-controller;
#interrupt-cells = <2>;
reg = <0x1f810000 0x1000>;
microchip,external-irqs = <3 8 13 18 23>;
};
pic32_pinctrl: pinctrl@1f801400{
#address-cells = <1>;
#size-cells = <1>;
compatible = "microchip,pic32mzda-pinctrl";
reg = <0x1f801400 0x400>;
clocks = <&PBCLK1>;
};
/* PORTA */
gpio0: gpio0@1f860000 {
compatible = "microchip,pic32mzda-gpio";
reg = <0x1f860000 0x100>;
interrupts = <118 IRQ_TYPE_LEVEL_HIGH>;
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
clocks = <&PBCLK4>;
microchip,gpio-bank = <0>;
gpio-ranges = <&pic32_pinctrl 0 0 16>;
};
/* PORTB */
gpio1: gpio1@1f860100 {
compatible = "microchip,pic32mzda-gpio";
reg = <0x1f860100 0x100>;
interrupts = <119 IRQ_TYPE_LEVEL_HIGH>;
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
clocks = <&PBCLK4>;
microchip,gpio-bank = <1>;
gpio-ranges = <&pic32_pinctrl 0 16 16>;
};
/* PORTC */
gpio2: gpio2@1f860200 {
compatible = "microchip,pic32mzda-gpio";
reg = <0x1f860200 0x100>;
interrupts = <120 IRQ_TYPE_LEVEL_HIGH>;
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
clocks = <&PBCLK4>;
microchip,gpio-bank = <2>;
gpio-ranges = <&pic32_pinctrl 0 32 16>;
};
/* PORTD */
gpio3: gpio3@1f860300 {
compatible = "microchip,pic32mzda-gpio";
reg = <0x1f860300 0x100>;
interrupts = <121 IRQ_TYPE_LEVEL_HIGH>;
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
clocks = <&PBCLK4>;
microchip,gpio-bank = <3>;
gpio-ranges = <&pic32_pinctrl 0 48 16>;
};
/* PORTE */
gpio4: gpio4@1f860400 {
compatible = "microchip,pic32mzda-gpio";
reg = <0x1f860400 0x100>;
interrupts = <122 IRQ_TYPE_LEVEL_HIGH>;
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
clocks = <&PBCLK4>;
microchip,gpio-bank = <4>;
gpio-ranges = <&pic32_pinctrl 0 64 16>;
};
/* PORTF */
gpio5: gpio5@1f860500 {
compatible = "microchip,pic32mzda-gpio";
reg = <0x1f860500 0x100>;
interrupts = <123 IRQ_TYPE_LEVEL_HIGH>;
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
clocks = <&PBCLK4>;
microchip,gpio-bank = <5>;
gpio-ranges = <&pic32_pinctrl 0 80 16>;
};
/* PORTG */
gpio6: gpio6@1f860600 {
compatible = "microchip,pic32mzda-gpio";
reg = <0x1f860600 0x100>;
interrupts = <124 IRQ_TYPE_LEVEL_HIGH>;
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
clocks = <&PBCLK4>;
microchip,gpio-bank = <6>;
gpio-ranges = <&pic32_pinctrl 0 96 16>;
};
/* PORTH */
gpio7: gpio7@1f860700 {
compatible = "microchip,pic32mzda-gpio";
reg = <0x1f860700 0x100>;
interrupts = <125 IRQ_TYPE_LEVEL_HIGH>;
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
clocks = <&PBCLK4>;
microchip,gpio-bank = <7>;
gpio-ranges = <&pic32_pinctrl 0 112 16>;
};
/* PORTI does not exist */
/* PORTJ */
gpio8: gpio8@1f860800 {
compatible = "microchip,pic32mzda-gpio";
reg = <0x1f860800 0x100>;
interrupts = <126 IRQ_TYPE_LEVEL_HIGH>;
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
clocks = <&PBCLK4>;
microchip,gpio-bank = <8>;
gpio-ranges = <&pic32_pinctrl 0 128 16>;
};
/* PORTK */
gpio9: gpio9@1f860900 {
compatible = "microchip,pic32mzda-gpio";
reg = <0x1f860900 0x100>;
interrupts = <127 IRQ_TYPE_LEVEL_HIGH>;
#gpio-cells = <2>;
gpio-controller;
interrupt-controller;
#interrupt-cells = <2>;
clocks = <&PBCLK4>;
microchip,gpio-bank = <9>;
gpio-ranges = <&pic32_pinctrl 0 144 16>;
};
sdhci: sdhci@1f8ec000 {
compatible = "microchip,pic32mzda-sdhci";
reg = <0x1f8ec000 0x100>;
interrupts = <191 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&REFCLKO4>, <&PBCLK5>;
clock-names = "base_clk", "sys_clk";
bus-width = <4>;
cap-sd-highspeed;
status = "disabled";
};
uart1: serial@1f822000 {
compatible = "microchip,pic32mzda-uart";
reg = <0x1f822000 0x50>;
interrupts = <112 IRQ_TYPE_LEVEL_HIGH>,
<113 IRQ_TYPE_LEVEL_HIGH>,
<114 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&PBCLK2>;
status = "disabled";
};
uart2: serial@1f822200 {
compatible = "microchip,pic32mzda-uart";
reg = <0x1f822200 0x50>;
interrupts = <145 IRQ_TYPE_LEVEL_HIGH>,
<146 IRQ_TYPE_LEVEL_HIGH>,
<147 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&PBCLK2>;
status = "disabled";
};
uart3: serial@1f822400 {
compatible = "microchip,pic32mzda-uart";
reg = <0x1f822400 0x50>;
interrupts = <157 IRQ_TYPE_LEVEL_HIGH>,
<158 IRQ_TYPE_LEVEL_HIGH>,
<159 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&PBCLK2>;
status = "disabled";
};
uart4: serial@1f822600 {
compatible = "microchip,pic32mzda-uart";
reg = <0x1f822600 0x50>;
interrupts = <170 IRQ_TYPE_LEVEL_HIGH>,
<171 IRQ_TYPE_LEVEL_HIGH>,
<172 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&PBCLK2>;
status = "disabled";
};
uart5: serial@1f822800 {
compatible = "microchip,pic32mzda-uart";
reg = <0x1f822800 0x50>;
interrupts = <179 IRQ_TYPE_LEVEL_HIGH>,
<180 IRQ_TYPE_LEVEL_HIGH>,
<181 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&PBCLK2>;
status = "disabled";
};
uart6: serial@1f822A00 {
compatible = "microchip,pic32mzda-uart";
reg = <0x1f822A00 0x50>;
interrupts = <188 IRQ_TYPE_LEVEL_HIGH>,
<189 IRQ_TYPE_LEVEL_HIGH>,
<190 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&PBCLK2>;
status = "disabled";
};
};
/*
* Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include "pic32mzda.dtsi"
/ {
compatible = "microchip,pic32mzda-sk", "microchip,pic32mzda";
model = "Microchip PIC32MZDA Starter Kit";
memory {
device_type = "memory";
reg = <0x08000000 0x08000000>;
};
chosen {
bootargs = "earlyprintk=ttyPIC1,115200n8r console=ttyPIC1,115200n8";
};
leds0 {
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&user_leds_s0>;
led@1 {
label = "pic32mzda_sk:red:led1";
gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
};
led@2 {
label = "pic32mzda_sk:yellow:led2";
gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "mmc0";
};
led@3 {
label = "pic32mzda_sk:green:led3";
gpios = <&gpio7 2 GPIO_ACTIVE_HIGH>;
default-state = "on";
};
};
keys0 {
compatible = "gpio-keys";
pinctrl-0 = <&user_buttons_s0>;
pinctrl-names = "default";
#address-cells = <1>;
#size-cells = <0>;
button@sw1 {
label = "ESC";
linux,code = <1>;
gpios = <&gpio1 12 0>;
};
button@sw2 {
label = "Home";
linux,code = <102>;
gpios = <&gpio1 13 0>;
};
button@sw3 {
label = "Menu";
linux,code = <139>;
gpios = <&gpio1 14 0>;
};
};
};
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart2>;
status = "okay";
};
&uart4 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart4>;
status = "okay";
};
&sdhci {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sdhc1>;
status = "okay";
assigned-clocks = <&REFCLKO2>,<&REFCLKO4>,<&REFCLKO5>;
assigned-clock-rates = <50000000>,<25000000>,<40000000>;
};
&pic32_pinctrl {
pinctrl_sdhc1: sdhc1_pins0 {
pins = "A6", "D4", "G13", "G12", "G14", "A7", "A0";
microchip,digital;
};
user_leds_s0: user_leds_s0 {
pins = "H0", "H1", "H2";
output-low;
microchip,digital;
};
user_buttons_s0: user_buttons_s0 {
pins = "B12", "B13", "B14";
microchip,digital;
input-enable;
bias-pull-up;
};
pinctrl_uart2: pinctrl_uart2 {
uart2-tx {
pins = "G9";
function = "U2TX";
microchip,digital;
output-high;
};
uart2-rx {
pins = "B0";
function = "U2RX";
microchip,digital;
input-enable;
};
};
pinctrl_uart4: uart4-0 {
uart4-tx {
pins = "C3";
function = "U4TX";
microchip,digital;
output-high;
};
uart4-rx {
pins = "E8";
function = "U4RX";
microchip,digital;
input-enable;
};
};
};
......@@ -125,6 +125,21 @@ rst: reset-controller@1806001c {
};
};
usb@1b000100 {
compatible = "qca,ar7100-ehci", "generic-ehci";
reg = <0x1b000100 0x100>;
interrupts = <3>;
resets = <&rst 5>;
has-transaction-translator;
phy-names = "usb";
phys = <&usb_phy>;
status = "disabled";
};
spi@1f000000 {
compatible = "qca,ar9132-spi", "qca,ar7100-spi";
reg = <0x1f000000 0x10>;
......@@ -138,4 +153,15 @@ spi@1f000000 {
#size-cells = <0>;
};
};
usb_phy: usb-phy {
compatible = "qca,ar7100-usb-phy";
reset-names = "usb-phy", "usb-suspend-override";
resets = <&rst 4>, <&rst 3>;
#phy-cells = <0>;
status = "disabled";
};
};
......@@ -35,6 +35,10 @@ pll-controller@18050000 {
};
};
usb@1b000100 {
status = "okay";
};
spi@1f000000 {
status = "okay";
num-cs = <1>;
......@@ -65,6 +69,10 @@ partition@2 {
};
};
usb-phy {
status = "okay";
};
gpio-keys {
compatible = "gpio-keys-polled";
#address-cells = <1>;
......
CONFIG_MACH_PIC32=y
CONFIG_DTB_PIC32_MZDA_SK=y
CONFIG_HZ_100=y
CONFIG_PREEMPT_VOLUNTARY=y
# CONFIG_SECCOMP is not set
CONFIG_SYSVIPC=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_RELAY=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_EMBEDDED=y
# CONFIG_COMPAT_BRK is not set
CONFIG_SLAB=y
CONFIG_JUMP_LABEL=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_BLK_DEV_BSGLIB=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_SGI_PARTITION=y
CONFIG_BINFMT_MISC=m
# CONFIG_SUSPEND is not set
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_FIRMWARE_IN_KERNEL is not set
# CONFIG_ALLOW_DEV_COREDUMP is not set
CONFIG_BLK_DEV_LOOP=m
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_SCAN_ASYNC=y
# CONFIG_SCSI_LOWLEVEL is not set
CONFIG_INPUT_LEDS=m
CONFIG_INPUT_POLLDEV=y
CONFIG_INPUT_MOUSEDEV=m
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_EVBUG=m
# CONFIG_KEYBOARD_ATKBD is not set
CONFIG_KEYBOARD_GPIO=m
CONFIG_KEYBOARD_GPIO_POLLED=m
# CONFIG_MOUSE_PS2 is not set
# CONFIG_SERIO is not set
CONFIG_SERIAL_PIC32=y
CONFIG_SERIAL_PIC32_CONSOLE=y
CONFIG_HW_RANDOM=y
CONFIG_RAW_DRIVER=m
CONFIG_GPIO_SYSFS=y
# CONFIG_HWMON is not set
CONFIG_HIDRAW=y
# CONFIG_USB_SUPPORT is not set
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_MICROCHIP_PIC32=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=m
CONFIG_LEDS_TRIGGER_ONESHOT=m
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_GPIO=m
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
# CONFIG_MIPS_PLATFORM_DEVICES is not set
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_AUTOFS4_FS=m
CONFIG_FUSE_FS=m
CONFIG_FSCACHE=m
CONFIG_ISO9660_FS=m
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
CONFIG_UDF_FS=m
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_PROC_KCORE=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_SQUASHFS=m
CONFIG_SQUASHFS_XATTR=y
CONFIG_SQUASHFS_LZ4=y
CONFIG_SQUASHFS_LZO=y
CONFIG_SQUASHFS_XZ=y
......@@ -11,55 +11,77 @@
#ifndef __ASM_CACHEOPS_H
#define __ASM_CACHEOPS_H
/*
* Most cache ops are split into a 2 bit field identifying the cache, and a 3
* bit field identifying the cache operation.
*/
#define CacheOp_Cache 0x03
#define CacheOp_Op 0x1c
#define Cache_I 0x00
#define Cache_D 0x01
#define Cache_T 0x02
#define Cache_S 0x03
#define Index_Writeback_Inv 0x00
#define Index_Load_Tag 0x04
#define Index_Store_Tag 0x08
#define Hit_Invalidate 0x10
#define Hit_Writeback_Inv 0x14 /* not with Cache_I though */
#define Hit_Writeback 0x18
/*
* Cache Operations available on all MIPS processors with R4000-style caches
*/
#define Index_Invalidate_I 0x00
#define Index_Writeback_Inv_D 0x01
#define Index_Load_Tag_I 0x04
#define Index_Load_Tag_D 0x05
#define Index_Store_Tag_I 0x08
#define Index_Store_Tag_D 0x09
#define Hit_Invalidate_I 0x10
#define Hit_Invalidate_D 0x11
#define Hit_Writeback_Inv_D 0x15
#define Index_Invalidate_I (Cache_I | Index_Writeback_Inv)
#define Index_Writeback_Inv_D (Cache_D | Index_Writeback_Inv)
#define Index_Load_Tag_I (Cache_I | Index_Load_Tag)
#define Index_Load_Tag_D (Cache_D | Index_Load_Tag)
#define Index_Store_Tag_I (Cache_I | Index_Store_Tag)
#define Index_Store_Tag_D (Cache_D | Index_Store_Tag)
#define Hit_Invalidate_I (Cache_I | Hit_Invalidate)
#define Hit_Invalidate_D (Cache_D | Hit_Invalidate)
#define Hit_Writeback_Inv_D (Cache_D | Hit_Writeback_Inv)
/*
* R4000-specific cacheops
*/
#define Create_Dirty_Excl_D 0x0d
#define Fill 0x14
#define Hit_Writeback_I 0x18
#define Hit_Writeback_D 0x19
#define Create_Dirty_Excl_D (Cache_D | 0x0c)
#define Fill (Cache_I | 0x14)
#define Hit_Writeback_I (Cache_I | Hit_Writeback)
#define Hit_Writeback_D (Cache_D | Hit_Writeback)
/*
* R4000SC and R4400SC-specific cacheops
*/
#define Index_Invalidate_SI 0x02
#define Index_Writeback_Inv_SD 0x03
#define Index_Load_Tag_SI 0x06
#define Index_Load_Tag_SD 0x07
#define Index_Store_Tag_SI 0x0A
#define Index_Store_Tag_SD 0x0B
#define Create_Dirty_Excl_SD 0x0f
#define Hit_Invalidate_SI 0x12
#define Hit_Invalidate_SD 0x13
#define Hit_Writeback_Inv_SD 0x17
#define Hit_Writeback_SD 0x1b
#define Hit_Set_Virtual_SI 0x1e
#define Hit_Set_Virtual_SD 0x1f
#define Cache_SI 0x02
#define Cache_SD 0x03
#define Index_Invalidate_SI (Cache_SI | Index_Writeback_Inv)
#define Index_Writeback_Inv_SD (Cache_SD | Index_Writeback_Inv)
#define Index_Load_Tag_SI (Cache_SI | Index_Load_Tag)
#define Index_Load_Tag_SD (Cache_SD | Index_Load_Tag)
#define Index_Store_Tag_SI (Cache_SI | Index_Store_Tag)
#define Index_Store_Tag_SD (Cache_SD | Index_Store_Tag)
#define Create_Dirty_Excl_SD (Cache_SD | 0x0c)
#define Hit_Invalidate_SI (Cache_SI | Hit_Invalidate)
#define Hit_Invalidate_SD (Cache_SD | Hit_Invalidate)
#define Hit_Writeback_Inv_SD (Cache_SD | Hit_Writeback_Inv)
#define Hit_Writeback_SD (Cache_SD | Hit_Writeback)
#define Hit_Set_Virtual_SI (Cache_SI | 0x1c)
#define Hit_Set_Virtual_SD (Cache_SD | 0x1c)
/*
* R5000-specific cacheops
*/
#define R5K_Page_Invalidate_S 0x17
#define R5K_Page_Invalidate_S (Cache_S | 0x14)
/*
* RM7000-specific cacheops
*/
#define Page_Invalidate_T 0x16
#define Index_Store_Tag_T 0x0a
#define Index_Load_Tag_T 0x06
#define Page_Invalidate_T (Cache_T | 0x14)
#define Index_Store_Tag_T (Cache_T | Index_Store_Tag)
#define Index_Load_Tag_T (Cache_T | Index_Load_Tag)
/*
* R10000-specific cacheops
......@@ -67,22 +89,22 @@
* Cacheops 0x02, 0x06, 0x0a, 0x0c-0x0e, 0x16, 0x1a and 0x1e are unused.
* Most of the _S cacheops are identical to the R4000SC _SD cacheops.
*/
#define Index_Writeback_Inv_S 0x03
#define Index_Load_Tag_S 0x07
#define Index_Store_Tag_S 0x0B
#define Hit_Invalidate_S 0x13
#define Index_Writeback_Inv_S (Cache_S | Index_Writeback_Inv)
#define Index_Load_Tag_S (Cache_S | Index_Load_Tag)
#define Index_Store_Tag_S (Cache_S | Index_Store_Tag)
#define Hit_Invalidate_S (Cache_S | Hit_Invalidate)
#define Cache_Barrier 0x14
#define Hit_Writeback_Inv_S 0x17
#define Index_Load_Data_I 0x18
#define Index_Load_Data_D 0x19
#define Index_Load_Data_S 0x1b
#define Index_Store_Data_I 0x1c
#define Index_Store_Data_D 0x1d
#define Index_Store_Data_S 0x1f
#define Hit_Writeback_Inv_S (Cache_S | Hit_Writeback_Inv)
#define Index_Load_Data_I (Cache_I | 0x18)
#define Index_Load_Data_D (Cache_D | 0x18)
#define Index_Load_Data_S (Cache_S | 0x18)
#define Index_Store_Data_I (Cache_I | 0x1c)
#define Index_Store_Data_D (Cache_D | 0x1c)
#define Index_Store_Data_S (Cache_S | 0x1c)
/*
* Loongson2-specific cacheops
*/
#define Hit_Invalidate_I_Loongson2 0x00
#define Hit_Invalidate_I_Loongson2 (Cache_I | 0x00)
#endif /* __ASM_CACHEOPS_H */
......@@ -414,4 +414,11 @@
# define cpu_has_small_pages (cpu_data[0].options & MIPS_CPU_SP)
#endif
#ifndef cpu_has_nan_legacy
#define cpu_has_nan_legacy (cpu_data[0].options & MIPS_CPU_NAN_LEGACY)
#endif
#ifndef cpu_has_nan_2008
#define cpu_has_nan_2008 (cpu_data[0].options & MIPS_CPU_NAN_2008)
#endif
#endif /* __ASM_CPU_FEATURES_H */
......@@ -386,6 +386,8 @@ enum cpu_type_enum {
#define MIPS_CPU_BP_GHIST 0x8000000000ull /* R12K+ Branch Prediction Global History */
#define MIPS_CPU_SP 0x10000000000ull /* Small (1KB) page support */
#define MIPS_CPU_FTLB 0x20000000000ull /* CPU has Fixed-page-size TLB */
#define MIPS_CPU_NAN_LEGACY 0x40000000000ull /* Legacy NaN implemented */
#define MIPS_CPU_NAN_2008 0x80000000000ull /* 2008 NaN implemented */
/*
* CPU ASE encodings
......
......@@ -12,7 +12,6 @@
#include <linux/fs.h>
#include <uapi/linux/elf.h>
#include <asm/cpu-info.h>
#include <asm/current.h>
/* ELF header e_flags defines. */
......@@ -44,6 +43,7 @@
#define EF_MIPS_OPTIONS_FIRST 0x00000080
#define EF_MIPS_32BITMODE 0x00000100
#define EF_MIPS_FP64 0x00000200
#define EF_MIPS_NAN2008 0x00000400
#define EF_MIPS_ABI 0x0000f000
#define EF_MIPS_ARCH 0xf0000000
......@@ -305,7 +305,7 @@ do { \
\
current->thread.abi = &mips_abi; \
\
current->thread.fpu.fcr31 = boot_cpu_data.fpu_csr31; \
mips_set_personality_nan(state); \
} while (0)
#endif /* CONFIG_32BIT */
......@@ -367,7 +367,7 @@ do { \
else \
current->thread.abi = &mips_abi; \
\
current->thread.fpu.fcr31 = boot_cpu_data.fpu_csr31; \
mips_set_personality_nan(state); \
\
p = personality(current->personality); \
if (p != PER_LINUX32 && p != PER_LINUX) \
......@@ -432,6 +432,7 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
int uses_interp);
struct arch_elf_state {
int nan_2008;
int fp_abi;
int interp_fp_abi;
int overall_fp_mode;
......@@ -440,17 +441,23 @@ struct arch_elf_state {
#define MIPS_ABI_FP_UNKNOWN (-1) /* Unknown FP ABI (kernel internal) */
#define INIT_ARCH_ELF_STATE { \
.nan_2008 = -1, \
.fp_abi = MIPS_ABI_FP_UNKNOWN, \
.interp_fp_abi = MIPS_ABI_FP_UNKNOWN, \
.overall_fp_mode = -1, \
}
/* Whether to accept legacy-NaN and 2008-NaN user binaries. */
extern bool mips_use_nan_legacy;
extern bool mips_use_nan_2008;
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,
extern int arch_check_elf(void *ehdr, bool has_interpreter, void *interp_ehdr,
struct arch_elf_state *state);
extern void mips_set_personality_nan(struct arch_elf_state *state);
extern void mips_set_personality_fp(struct arch_elf_state *state);
#endif /* _ASM_ELF_H */
......@@ -79,7 +79,7 @@ int mm_isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
/*
* Break instruction with special math emu break code set
*/
#define BREAK_MATH (0x0000000d | (BRK_MEMU << 16))
#define BREAK_MATH(micromips) (((micromips) ? 0x7 : 0xd) | (BRK_MEMU << 16))
#define SIGNALLING_NAN 0x7ff800007ff80000LL
......
......@@ -275,6 +275,7 @@ static inline void __iomem * __ioremap_mode(phys_addr_t offset, unsigned long si
*/
#define ioremap_cachable(offset, size) \
__ioremap_mode((offset), (size), _page_cachable_default)
#define ioremap_cache ioremap_cachable
/*
* These two are MIPS specific ioremap variant. ioremap_cacheable_cow
......
......@@ -84,41 +84,11 @@ static inline void arch_local_irq_restore(unsigned long flags)
: "memory");
}
static inline void __arch_local_irq_restore(unsigned long flags)
{
__asm__ __volatile__(
" .set push \n"
" .set noreorder \n"
" .set noat \n"
#if defined(CONFIG_IRQ_MIPS_CPU)
/*
* Slow, but doesn't suffer from a relatively unlikely race
* condition we're having since days 1.
*/
" beqz %[flags], 1f \n"
" di \n"
" ei \n"
"1: \n"
#else
/*
* Fast, dangerous. Life is fun, life is good.
*/
" mfc0 $1, $12 \n"
" ins $1, %[flags], 0, 1 \n"
" mtc0 $1, $12 \n"
#endif
" " __stringify(__irq_disable_hazard) " \n"
" .set pop \n"
: [flags] "=r" (flags)
: "0" (flags)
: "memory");
}
#else
/* Functions that require preempt_{dis,en}able() are in mips-atomic.c */
void arch_local_irq_disable(void);
unsigned long arch_local_irq_save(void);
void arch_local_irq_restore(unsigned long flags);
void __arch_local_irq_restore(unsigned long flags);
#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
static inline void arch_local_irq_enable(void)
......
......@@ -92,14 +92,6 @@
#define KVM_INVALID_INST 0xdeadbeef
#define KVM_INVALID_ADDR 0xdeadbeef
#define KVM_MALTA_GUEST_RTC_ADDR 0xb8000070UL
#define GUEST_TICKS_PER_JIFFY (40000000/HZ)
#define MS_TO_NS(x) (x * 1E6L)
#define CAUSEB_DC 27
#define CAUSEF_DC (_ULCAST_(1) << 27)
extern atomic_t kvm_mips_instance;
extern kvm_pfn_t (*kvm_mips_gfn_to_pfn)(struct kvm *kvm, gfn_t gfn);
extern void (*kvm_mips_release_pfn_clean)(kvm_pfn_t pfn);
......@@ -289,34 +281,6 @@ enum mips_mmu_types {
MMU_TYPE_R8000
};
/*
* Trap codes
*/
#define T_INT 0 /* Interrupt pending */
#define T_TLB_MOD 1 /* TLB modified fault */
#define T_TLB_LD_MISS 2 /* TLB miss on load or ifetch */
#define T_TLB_ST_MISS 3 /* TLB miss on a store */
#define T_ADDR_ERR_LD 4 /* Address error on a load or ifetch */
#define T_ADDR_ERR_ST 5 /* Address error on a store */
#define T_BUS_ERR_IFETCH 6 /* Bus error on an ifetch */
#define T_BUS_ERR_LD_ST 7 /* Bus error on a load or store */
#define T_SYSCALL 8 /* System call */
#define T_BREAK 9 /* Breakpoint */
#define T_RES_INST 10 /* Reserved instruction exception */
#define T_COP_UNUSABLE 11 /* Coprocessor unusable */
#define T_OVFLOW 12 /* Arithmetic overflow */
/*
* Trap definitions added for r4000 port.
*/
#define T_TRAP 13 /* Trap instruction */
#define T_VCEI 14 /* Virtual coherency exception */
#define T_MSAFPE 14 /* MSA floating point exception */
#define T_FPE 15 /* Floating point exception */
#define T_MSADIS 21 /* MSA disabled exception */
#define T_WATCH 23 /* Watch address reference */
#define T_VCED 31 /* Virtual coherency data */
/* Resume Flags */
#define RESUME_FLAG_DR (1<<0) /* Reload guest nonvolatile state? */
#define RESUME_FLAG_HOST (1<<1) /* Resume host? */
......@@ -686,7 +650,6 @@ extern void kvm_mips_dump_host_tlbs(void);
extern void kvm_mips_dump_guest_tlbs(struct kvm_vcpu *vcpu);
extern void kvm_mips_flush_host_tlb(int skip_kseg0);
extern int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long entryhi);
extern int kvm_mips_host_tlb_inv_index(struct kvm_vcpu *vcpu, int index);
extern int kvm_mips_guest_tlb_lookup(struct kvm_vcpu *vcpu,
unsigned long entryhi);
......
......@@ -115,6 +115,7 @@ static inline int soc_is_qca955x(void)
return soc_is_qca9556() || soc_is_qca9558();
}
void ath79_ddr_wb_flush(unsigned int reg);
void ath79_ddr_set_pci_windows(void);
extern void __iomem *ath79_pll_base;
......
......@@ -30,6 +30,4 @@ u8 *bcm63xx_nvram_get_name(void);
*/
int bcm63xx_nvram_get_mac_address(u8 *mac);
int bcm63xx_nvram_get_psi_size(void);
#endif /* BCM63XX_NVRAM_H */
/*
* Joshua Henderson <joshua.henderson@microchip.com>
* Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
*
* 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.
*/
#ifndef __ASM_MACH_PIC32_CPU_FEATURE_OVERRIDES_H
#define __ASM_MACH_PIC32_CPU_FEATURE_OVERRIDES_H
/*
* CPU feature overrides for PIC32 boards
*/
#ifdef CONFIG_CPU_MIPS32
#define cpu_has_vint 1
#define cpu_has_veic 0
#define cpu_has_tlb 1
#define cpu_has_4kex 1
#define cpu_has_4k_cache 1
#define cpu_has_fpu 0
#define cpu_has_counter 1
#define cpu_has_llsc 1
#define cpu_has_nofpuex 0
#define cpu_icache_snoops_remote_store 1
#endif
#ifdef CONFIG_CPU_MIPS64
#error This platform does not support 64bit.
#endif
#endif /* __ASM_MACH_PIC32_CPU_FEATURE_OVERRIDES_H */
/*
* Joshua Henderson <joshua.henderson@microchip.com>
* Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
*
* This program is free software; you can distribute 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 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_PIC32_IRQ_H
#define __ASM_MACH_PIC32_IRQ_H
#define NR_IRQS 256
#define MIPS_CPU_IRQ_BASE 0
#include_next <irq.h>
#endif /* __ASM_MACH_PIC32_IRQ_H */
/*
* Joshua Henderson <joshua.henderson@microchip.com>
* Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
*
* This program is free software; you can distribute 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 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_PIC32_H
#define _ASM_MACH_PIC32_H
#include <linux/io.h>
/*
* PIC32 register offsets for SET/CLR/INV where supported.
*/
#define PIC32_CLR(_reg) ((_reg) + 0x04)
#define PIC32_SET(_reg) ((_reg) + 0x08)
#define PIC32_INV(_reg) ((_reg) + 0x0C)
/*
* PIC32 Base Register Offsets
*/
#define PIC32_BASE_CONFIG 0x1f800000
#define PIC32_BASE_OSC 0x1f801200
#define PIC32_BASE_RESET 0x1f801240
#define PIC32_BASE_PPS 0x1f801400
#define PIC32_BASE_UART 0x1f822000
#define PIC32_BASE_PORT 0x1f860000
#define PIC32_BASE_DEVCFG2 0x1fc4ff44
/*
* Register unlock sequence required for some register access.
*/
void pic32_syskey_unlock_debug(const char *fn, const ulong ln);
#define pic32_syskey_unlock() \
pic32_syskey_unlock_debug(__func__, __LINE__)
#endif /* _ASM_MACH_PIC32_H */
/*
* Joshua Henderson <joshua.henderson@microchip.com>
* Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
*
* This program is free software; you can distribute 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 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_PIC32_SPACES_H
#define _ASM_MACH_PIC32_SPACES_H
#ifdef CONFIG_PIC32MZDA
#define PHYS_OFFSET _AC(0x08000000, UL)
#define UNCAC_BASE _AC(0xa8000000, UL)
#endif
#include <asm/mach-generic/spaces.h>
#endif /* __ASM_MACH_PIC32_SPACES_H */
#ifndef __ASM_MACH_RALINK_IRQ_H
#define __ASM_MACH_RALINK_IRQ_H
#define GIC_NUM_INTRS 64
#define NR_IRQS 256
#include_next <irq.h>
#endif
/*
* 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.
*
* Copyright (C) 2015 John Crispin <blogic@openwrt.org>
*/
#ifndef _MT7621_REGS_H_
#define _MT7621_REGS_H_
#define MT7621_PALMBUS_BASE 0x1C000000
#define MT7621_PALMBUS_SIZE 0x03FFFFFF
#define MT7621_SYSC_BASE 0x1E000000
#define SYSC_REG_CHIP_NAME0 0x00
#define SYSC_REG_CHIP_NAME1 0x04
#define SYSC_REG_CHIP_REV 0x0c
#define SYSC_REG_SYSTEM_CONFIG0 0x10
#define SYSC_REG_SYSTEM_CONFIG1 0x14
#define CHIP_REV_PKG_MASK 0x1
#define CHIP_REV_PKG_SHIFT 16
#define CHIP_REV_VER_MASK 0xf
#define CHIP_REV_VER_SHIFT 8
#define CHIP_REV_ECO_MASK 0xf
#define MT7621_DRAM_BASE 0x0
#define MT7621_DDR2_SIZE_MIN 32
#define MT7621_DDR2_SIZE_MAX 256
#define MT7621_CHIP_NAME0 0x3637544D
#define MT7621_CHIP_NAME1 0x20203132
#define MIPS_GIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8)
#endif
/*
* Ralink MT7621 specific CPU feature overrides
*
* Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
* Copyright (C) 2015 Felix Fietkau <nbd@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 _MT7621_CPU_FEATURE_OVERRIDES_H
#define _MT7621_CPU_FEATURE_OVERRIDES_H
#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_watch 1
#define cpu_has_divec 1
#define cpu_has_prefetch 1
#define cpu_has_ejtag 1
#define cpu_has_llsc 1
#define cpu_has_mips16 1
#define cpu_has_mdmx 0
#define cpu_has_mips3d 0
#define cpu_has_smartmips 0
#define cpu_has_mips32r1 1
#define cpu_has_mips32r2 1
#define cpu_has_mips64r1 0
#define cpu_has_mips64r2 0
#define cpu_has_dsp 1
#define cpu_has_dsp2 0
#define cpu_has_mipsmt 1
#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
#define cpu_dcache_line_size() 32
#define cpu_icache_line_size() 32
#define cpu_has_dc_aliases 0
#define cpu_has_vtag_icache 0
#define cpu_has_rixi 0
#define cpu_has_tlbinv 0
#define cpu_has_userlocal 1
#endif /* _MT7621_CPU_FEATURE_OVERRIDES_H */
......@@ -243,6 +243,10 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80)
#define CM_GCR_BASE_CMDEFTGT_IOCU0 2
#define CM_GCR_BASE_CMDEFTGT_IOCU1 3
/* GCR_RESET_EXT_BASE register fields */
#define CM_GCR_RESET_EXT_BASE_EVARESET BIT(31)
#define CM_GCR_RESET_EXT_BASE_UEB BIT(30)
/* GCR_ACCESS register fields */
#define CM_GCR_ACCESS_ACCESSEN_SHF 0
#define CM_GCR_ACCESS_ACCESSEN_MSK (_ULCAST_(0xff) << 0)
......
......@@ -52,7 +52,7 @@ do { \
__this_cpu_inc(mipsr2emustats.M); \
err = __get_user(nir, (u32 __user *)regs->cp0_epc); \
if (!err) { \
if (nir == BREAK_MATH) \
if (nir == BREAK_MATH(0)) \
__this_cpu_inc(mipsr2bdemustats.M); \
} \
preempt_enable(); \
......
......@@ -394,6 +394,8 @@
#define CAUSEF_IV (_ULCAST_(1) << 23)
#define CAUSEB_PCI 26
#define CAUSEF_PCI (_ULCAST_(1) << 26)
#define CAUSEB_DC 27
#define CAUSEF_DC (_ULCAST_(1) << 27)
#define CAUSEB_CE 28
#define CAUSEF_CE (_ULCAST_(3) << 28)
#define CAUSEB_TI 30
......@@ -401,6 +403,38 @@
#define CAUSEB_BD 31
#define CAUSEF_BD (_ULCAST_(1) << 31)
/*
* Cause.ExcCode trap codes.
*/
#define EXCCODE_INT 0 /* Interrupt pending */
#define EXCCODE_MOD 1 /* TLB modified fault */
#define EXCCODE_TLBL 2 /* TLB miss on load or ifetch */
#define EXCCODE_TLBS 3 /* TLB miss on a store */
#define EXCCODE_ADEL 4 /* Address error on a load or ifetch */
#define EXCCODE_ADES 5 /* Address error on a store */
#define EXCCODE_IBE 6 /* Bus error on an ifetch */
#define EXCCODE_DBE 7 /* Bus error on a load or store */
#define EXCCODE_SYS 8 /* System call */
#define EXCCODE_BP 9 /* Breakpoint */
#define EXCCODE_RI 10 /* Reserved instruction exception */
#define EXCCODE_CPU 11 /* Coprocessor unusable */
#define EXCCODE_OV 12 /* Arithmetic overflow */
#define EXCCODE_TR 13 /* Trap instruction */
#define EXCCODE_MSAFPE 14 /* MSA floating point exception */
#define EXCCODE_FPE 15 /* Floating point exception */
#define EXCCODE_TLBRI 19 /* TLB Read-Inhibit exception */
#define EXCCODE_TLBXI 20 /* TLB Execution-Inhibit exception */
#define EXCCODE_MSADIS 21 /* MSA disabled exception */
#define EXCCODE_MDMX 22 /* MDMX unusable exception */
#define EXCCODE_WATCH 23 /* Watch address reference */
#define EXCCODE_MCHECK 24 /* Machine check */
#define EXCCODE_THREAD 25 /* Thread exceptions (MT) */
#define EXCCODE_DSPDIS 26 /* DSP disabled exception */
#define EXCCODE_GE 27 /* Virtualized guest exception (VZ) */
/* Implementation specific trap codes used by MIPS cores */
#define MIPS_EXCCODE_TLBPAR 16 /* TLB parity error exception */
/*
* Bits in the coprocessor 0 config register.
*/
......
......@@ -33,7 +33,7 @@
#define PAGE_SHIFT 16
#endif
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE - 1))
#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
/*
* This is used for calculating the real page sizes
......
......@@ -353,7 +353,7 @@ static inline pte_t pte_mkdirty(pte_t pte)
static inline pte_t pte_mkyoung(pte_t pte)
{
pte_val(pte) |= _PAGE_ACCESSED;
#ifdef CONFIG_CPU_MIPSR2
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
if (!(pte_val(pte) & _PAGE_NO_READ))
pte_val(pte) |= _PAGE_SILENT_READ;
else
......@@ -542,7 +542,7 @@ static inline pmd_t pmd_mkyoung(pmd_t pmd)
{
pmd_val(pmd) |= _PAGE_ACCESSED;
#ifdef CONFIG_CPU_MIPSR2
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
if (!(pmd_val(pmd) & _PAGE_NO_READ))
pmd_val(pmd) |= _PAGE_SILENT_READ;
else
......
......@@ -116,7 +116,8 @@ enum cop_op {
dmtc_op = 0x05, ctc_op = 0x06,
mthc0_op = 0x06, mthc_op = 0x07,
bc_op = 0x08, bc1eqz_op = 0x09,
bc1nez_op = 0x0d, cop_op = 0x10,
mfmc0_op = 0x0b, bc1nez_op = 0x0d,
wrpgpr_op = 0x0e, cop_op = 0x10,
copm_op = 0x18
};
......@@ -529,7 +530,7 @@ enum MIPS6e_i8_func {
};
/*
* (microMIPS & MIPS16e) NOP instruction.
* (microMIPS) NOP instruction.
*/
#define MM_NOP16 0x0c00
......@@ -679,7 +680,7 @@ struct fp0_format { /* FPU multiply and add format (MIPS32) */
;))))))
};
struct mm_fp0_format { /* FPU multipy and add format (microMIPS) */
struct mm_fp0_format { /* FPU multiply and add format (microMIPS) */
__BITFIELD_FIELD(unsigned int opcode : 6,
__BITFIELD_FIELD(unsigned int ft : 5,
__BITFIELD_FIELD(unsigned int fs : 5,
......@@ -799,6 +800,13 @@ struct mm_x_format { /* Scaled indexed load format (microMIPS) */
;)))))
};
struct mm_a_format { /* ADDIUPC format (microMIPS) */
__BITFIELD_FIELD(unsigned int opcode : 6,
__BITFIELD_FIELD(unsigned int rs : 3,
__BITFIELD_FIELD(signed int simmediate : 23,
;)))
};
/*
* microMIPS instruction formats (16-bit length)
*/
......@@ -940,6 +948,7 @@ union mips_instruction {
struct mm_i_format mm_i_format;
struct mm_m_format mm_m_format;
struct mm_x_format mm_x_format;
struct mm_a_format mm_a_format;
struct mm_b0_format mm_b0_format;
struct mm_b1_format mm_b1_format;
struct mm16_m_format mm16_m_format ;
......
......@@ -190,7 +190,7 @@ static inline void check_daddi(void)
printk("Checking for the daddi bug... ");
local_irq_save(flags);
handler = set_except_vector(12, handle_daddi_ov);
handler = set_except_vector(EXCCODE_OV, handle_daddi_ov);
/*
* The following code fails to trigger an overflow exception
* when executed on R4000 rev. 2.2 or 3.0 (PRId 00000422 or
......@@ -214,7 +214,7 @@ static inline void check_daddi(void)
".set pop"
: "=r" (v), "=&r" (tmp)
: "I" (0xffffffffffffdb9aUL), "I" (0x1234));
set_except_vector(12, handler);
set_except_vector(EXCCODE_OV, handler);
local_irq_restore(flags);
if (daddi_ov) {
......@@ -225,14 +225,14 @@ static inline void check_daddi(void)
printk("yes, workaround... ");
local_irq_save(flags);
handler = set_except_vector(12, handle_daddi_ov);
handler = set_except_vector(EXCCODE_OV, handle_daddi_ov);
asm volatile(
"addiu %1, $0, %2\n\t"
"dsrl %1, %1, 1\n\t"
"daddi %0, %1, %3"
: "=r" (v), "=&r" (tmp)
: "I" (0xffffffffffffdb9aUL), "I" (0x1234));
set_except_vector(12, handler);
set_except_vector(EXCCODE_OV, handler);
local_irq_restore(flags);
if (daddi_ov) {
......
......@@ -98,6 +98,161 @@ static inline void cpu_set_fpu_fcsr_mask(struct cpuinfo_mips *c)
c->fpu_msk31 = ~(fcsr0 ^ fcsr1) & ~mask;
}
/*
* Determine the IEEE 754 NaN encodings and ABS.fmt/NEG.fmt execution modes
* supported by FPU hardware.
*/
static void cpu_set_fpu_2008(struct cpuinfo_mips *c)
{
if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) {
unsigned long sr, fir, fcsr, fcsr0, fcsr1;
sr = read_c0_status();
__enable_fpu(FPU_AS_IS);
fir = read_32bit_cp1_register(CP1_REVISION);
if (fir & MIPS_FPIR_HAS2008) {
fcsr = read_32bit_cp1_register(CP1_STATUS);
fcsr0 = fcsr & ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008);
write_32bit_cp1_register(CP1_STATUS, fcsr0);
fcsr0 = read_32bit_cp1_register(CP1_STATUS);
fcsr1 = fcsr | FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
write_32bit_cp1_register(CP1_STATUS, fcsr1);
fcsr1 = read_32bit_cp1_register(CP1_STATUS);
write_32bit_cp1_register(CP1_STATUS, fcsr);
if (!(fcsr0 & FPU_CSR_NAN2008))
c->options |= MIPS_CPU_NAN_LEGACY;
if (fcsr1 & FPU_CSR_NAN2008)
c->options |= MIPS_CPU_NAN_2008;
if ((fcsr0 ^ fcsr1) & FPU_CSR_ABS2008)
c->fpu_msk31 &= ~FPU_CSR_ABS2008;
else
c->fpu_csr31 |= fcsr & FPU_CSR_ABS2008;
if ((fcsr0 ^ fcsr1) & FPU_CSR_NAN2008)
c->fpu_msk31 &= ~FPU_CSR_NAN2008;
else
c->fpu_csr31 |= fcsr & FPU_CSR_NAN2008;
} else {
c->options |= MIPS_CPU_NAN_LEGACY;
}
write_c0_status(sr);
} else {
c->options |= MIPS_CPU_NAN_LEGACY;
}
}
/*
* IEEE 754 conformance mode to use. Affects the NaN encoding and the
* ABS.fmt/NEG.fmt execution mode.
*/
static enum { STRICT, LEGACY, STD2008, RELAXED } ieee754 = STRICT;
/*
* Set the IEEE 754 NaN encodings and the ABS.fmt/NEG.fmt execution modes
* to support by the FPU emulator according to the IEEE 754 conformance
* mode selected. Note that "relaxed" straps the emulator so that it
* allows 2008-NaN binaries even for legacy processors.
*/
static void cpu_set_nofpu_2008(struct cpuinfo_mips *c)
{
c->options &= ~(MIPS_CPU_NAN_2008 | MIPS_CPU_NAN_LEGACY);
c->fpu_csr31 &= ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008);
c->fpu_msk31 &= ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008);
switch (ieee754) {
case STRICT:
if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) {
c->options |= MIPS_CPU_NAN_2008 | MIPS_CPU_NAN_LEGACY;
} else {
c->options |= MIPS_CPU_NAN_LEGACY;
c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
}
break;
case LEGACY:
c->options |= MIPS_CPU_NAN_LEGACY;
c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
break;
case STD2008:
c->options |= MIPS_CPU_NAN_2008;
c->fpu_csr31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
break;
case RELAXED:
c->options |= MIPS_CPU_NAN_2008 | MIPS_CPU_NAN_LEGACY;
break;
}
}
/*
* Override the IEEE 754 NaN encoding and ABS.fmt/NEG.fmt execution mode
* according to the "ieee754=" parameter.
*/
static void cpu_set_nan_2008(struct cpuinfo_mips *c)
{
switch (ieee754) {
case STRICT:
mips_use_nan_legacy = !!cpu_has_nan_legacy;
mips_use_nan_2008 = !!cpu_has_nan_2008;
break;
case LEGACY:
mips_use_nan_legacy = !!cpu_has_nan_legacy;
mips_use_nan_2008 = !cpu_has_nan_legacy;
break;
case STD2008:
mips_use_nan_legacy = !cpu_has_nan_2008;
mips_use_nan_2008 = !!cpu_has_nan_2008;
break;
case RELAXED:
mips_use_nan_legacy = true;
mips_use_nan_2008 = true;
break;
}
}
/*
* IEEE 754 NaN encoding and ABS.fmt/NEG.fmt execution mode override
* settings:
*
* strict: accept binaries that request a NaN encoding supported by the FPU
* legacy: only accept legacy-NaN binaries
* 2008: only accept 2008-NaN binaries
* relaxed: accept any binaries regardless of whether supported by the FPU
*/
static int __init ieee754_setup(char *s)
{
if (!s)
return -1;
else if (!strcmp(s, "strict"))
ieee754 = STRICT;
else if (!strcmp(s, "legacy"))
ieee754 = LEGACY;
else if (!strcmp(s, "2008"))
ieee754 = STD2008;
else if (!strcmp(s, "relaxed"))
ieee754 = RELAXED;
else
return -1;
if (!(boot_cpu_data.options & MIPS_CPU_FPU))
cpu_set_nofpu_2008(&boot_cpu_data);
cpu_set_nan_2008(&boot_cpu_data);
return 0;
}
early_param("ieee754", ieee754_setup);
/*
* Set the FIR feature flags for the FPU emulator.
*/
......@@ -113,6 +268,8 @@ static void cpu_set_nofpu_id(struct cpuinfo_mips *c)
if (c->isa_level & (MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6))
value |= MIPS_FPIR_F64 | MIPS_FPIR_L | MIPS_FPIR_W;
if (c->options & MIPS_CPU_NAN_2008)
value |= MIPS_FPIR_HAS2008;
c->fpu_id = value;
}
......@@ -137,6 +294,8 @@ static void cpu_set_fpu_opts(struct cpuinfo_mips *c)
}
cpu_set_fpu_fcsr_mask(c);
cpu_set_fpu_2008(c);
cpu_set_nan_2008(c);
}
/*
......@@ -147,6 +306,8 @@ static void cpu_set_nofpu_opts(struct cpuinfo_mips *c)
c->options &= ~MIPS_CPU_FPU;
c->fpu_msk31 = mips_nofpu_msk31;
cpu_set_nofpu_2008(c);
cpu_set_nan_2008(c);
cpu_set_nofpu_id(c);
}
......
......@@ -11,6 +11,12 @@
#include <linux/elf.h>
#include <linux/sched.h>
#include <asm/cpu-info.h>
/* Whether to accept legacy-NaN and 2008-NaN user binaries. */
bool mips_use_nan_legacy;
bool mips_use_nan_2008;
/* FPU modes */
enum {
FP_FRE,
......@@ -68,15 +74,23 @@ static struct mode_req none_req = { true, true, false, true, true };
int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
bool is_interp, struct arch_elf_state *state)
{
struct elf32_hdr *ehdr32 = _ehdr;
union {
struct elf32_hdr e32;
struct elf64_hdr e64;
} *ehdr = _ehdr;
struct elf32_phdr *phdr32 = _phdr;
struct elf64_phdr *phdr64 = _phdr;
struct mips_elf_abiflags_v0 abiflags;
bool elf32;
u32 flags;
int ret;
elf32 = ehdr->e32.e_ident[EI_CLASS] == ELFCLASS32;
flags = elf32 ? ehdr->e32.e_flags : ehdr->e64.e_flags;
/* Lets see if this is an O32 ELF */
if (ehdr32->e_ident[EI_CLASS] == ELFCLASS32) {
if (ehdr32->e_flags & EF_MIPS_FP64) {
if (elf32) {
if (flags & EF_MIPS_FP64) {
/*
* Set MIPS_ABI_FP_OLD_64 for EF_MIPS_FP64. We will override it
* later if needed
......@@ -120,13 +134,50 @@ int arch_elf_pt_proc(void *_ehdr, void *_phdr, struct file *elf,
return 0;
}
int arch_check_elf(void *_ehdr, bool has_interpreter,
int arch_check_elf(void *_ehdr, bool has_interpreter, void *_interp_ehdr,
struct arch_elf_state *state)
{
struct elf32_hdr *ehdr = _ehdr;
union {
struct elf32_hdr e32;
struct elf64_hdr e64;
} *ehdr = _ehdr;
union {
struct elf32_hdr e32;
struct elf64_hdr e64;
} *iehdr = _interp_ehdr;
struct mode_req prog_req, interp_req;
int fp_abi, interp_fp_abi, abi0, abi1, max_abi;
bool is_mips64;
bool elf32;
u32 flags;
elf32 = ehdr->e32.e_ident[EI_CLASS] == ELFCLASS32;
flags = elf32 ? ehdr->e32.e_flags : ehdr->e64.e_flags;
/*
* Determine the NaN personality, reject the binary if not allowed.
* Also ensure that any interpreter matches the executable.
*/
if (flags & EF_MIPS_NAN2008) {
if (mips_use_nan_2008)
state->nan_2008 = 1;
else
return -ENOEXEC;
} else {
if (mips_use_nan_legacy)
state->nan_2008 = 0;
else
return -ENOEXEC;
}
if (has_interpreter) {
bool ielf32;
u32 iflags;
ielf32 = iehdr->e32.e_ident[EI_CLASS] == ELFCLASS32;
iflags = ielf32 ? iehdr->e32.e_flags : iehdr->e64.e_flags;
if ((flags ^ iflags) & EF_MIPS_NAN2008)
return -ELIBBAD;
}
if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
return 0;
......@@ -142,21 +193,18 @@ int arch_check_elf(void *_ehdr, bool has_interpreter,
abi0 = abi1 = fp_abi;
}
is_mips64 = (ehdr->e_ident[EI_CLASS] == ELFCLASS64) ||
(ehdr->e_flags & EF_MIPS_ABI2);
if (elf32 && !(flags & EF_MIPS_ABI2)) {
/* Default to a mode capable of running code expecting FR=0 */
state->overall_fp_mode = cpu_has_mips_r6 ? FP_FRE : FP_FR0;
if (is_mips64) {
/* Allow all ABIs we know about */
max_abi = MIPS_ABI_FP_64A;
} else {
/* MIPS64 code always uses FR=1, thus the default is easy */
state->overall_fp_mode = FP_FR1;
/* Disallow access to the various FPXX & FP64 ABIs */
max_abi = MIPS_ABI_FP_SOFT;
} else {
/* Default to a mode capable of running code expecting FR=0 */
state->overall_fp_mode = cpu_has_mips_r6 ? FP_FRE : FP_FR0;
/* Allow all ABIs we know about */
max_abi = MIPS_ABI_FP_64A;
}
if ((abi0 > max_abi && abi0 != MIPS_ABI_FP_UNKNOWN) ||
......@@ -254,3 +302,27 @@ void mips_set_personality_fp(struct arch_elf_state *state)
BUG();
}
}
/*
* Select the IEEE 754 NaN encoding and ABS.fmt/NEG.fmt execution mode
* in FCSR according to the ELF NaN personality.
*/
void mips_set_personality_nan(struct arch_elf_state *state)
{
struct cpuinfo_mips *c = &boot_cpu_data;
struct task_struct *t = current;
t->thread.fpu.fcr31 = c->fpu_csr31;
switch (state->nan_2008) {
case 0:
break;
case 1:
if (!(c->fpu_msk31 & FPU_CSR_NAN2008))
t->thread.fpu.fcr31 |= FPU_CSR_NAN2008;
if (!(c->fpu_msk31 & FPU_CSR_ABS2008))
t->thread.fpu.fcr31 |= FPU_CSR_ABS2008;
break;
default:
BUG();
}
}
......@@ -21,7 +21,7 @@ static struct txx9_pio_reg __iomem *txx9_pioptr;
static int txx9_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
return __raw_readl(&txx9_pioptr->din) & (1 << offset);
return !!(__raw_readl(&txx9_pioptr->din) & (1 << offset));
}
static void txx9_gpio_set_raw(unsigned int offset, int value)
......
......@@ -548,9 +548,6 @@ static const struct pt_regs_offset regoffset_table[] = {
REG_OFFSET_NAME(c0_badvaddr, cp0_badvaddr),
REG_OFFSET_NAME(c0_cause, cp0_cause),
REG_OFFSET_NAME(c0_epc, cp0_epc),
#ifdef CONFIG_MIPS_MT_SMTC
REG_OFFSET_NAME(c0_tcstatus, cp0_tcstatus),
#endif
#ifdef CONFIG_CPU_CAVIUM_OCTEON
REG_OFFSET_NAME(mpl0, mpl[0]),
REG_OFFSET_NAME(mpl1, mpl[1]),
......
......@@ -623,7 +623,7 @@ static void __init request_crashkernel(struct resource *res)
#define USE_PROM_CMDLINE IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER)
#define USE_DTB_CMDLINE IS_ENABLED(CONFIG_MIPS_CMDLINE_FROM_DTB)
#define EXTEND_WITH_PROM IS_ENABLED(CONFIG_MIPS_CMDLINE_EXTEND)
#define EXTEND_WITH_PROM IS_ENABLED(CONFIG_MIPS_CMDLINE_DTB_EXTEND)
static void __init arch_mem_init(char **cmdline_p)
{
......
......@@ -202,6 +202,9 @@ static void boot_core(unsigned core)
/* Ensure its coherency is disabled */
write_gcr_co_coherence(0);
/* Start it with the legacy memory map and exception base */
write_gcr_co_reset_ext_base(CM_GCR_RESET_EXT_BASE_UEB);
/* Ensure the core can access the GCRs */
access = read_gcr_access();
access |= 1 << (CM_GCR_ACCESS_ACCESSEN_SHF + core);
......
......@@ -17,34 +17,22 @@
#include <asm/barrier.h>
#include <asm/mipsregs.h>
static atomic_t count_start_flag = ATOMIC_INIT(0);
static unsigned int initcount = 0;
static atomic_t count_count_start = ATOMIC_INIT(0);
static atomic_t count_count_stop = ATOMIC_INIT(0);
static atomic_t count_reference = ATOMIC_INIT(0);
#define COUNTON 100
#define NR_LOOPS 5
#define NR_LOOPS 3
void synchronise_count_master(int cpu)
{
int i;
unsigned long flags;
unsigned int initcount;
printk(KERN_INFO "Synchronize counters for CPU %u: ", cpu);
local_irq_save(flags);
/*
* Notify the slaves that it's time to start
*/
atomic_set(&count_reference, read_c0_count());
atomic_set(&count_start_flag, cpu);
smp_wmb();
/* Count will be initialised to current timer for all CPU's */
initcount = read_c0_count();
/*
* We loop a few times to get a primed instruction cache,
* then the last pass is more or less synchronised and
......@@ -63,9 +51,13 @@ void synchronise_count_master(int cpu)
atomic_set(&count_count_stop, 0);
smp_wmb();
/* this lets the slaves write their count register */
/* Let the slave writes its count register */
atomic_inc(&count_count_start);
/* Count will be initialised to current timer */
if (i == 1)
initcount = read_c0_count();
/*
* Everyone initialises count in the last loop:
*/
......@@ -73,7 +65,7 @@ void synchronise_count_master(int cpu)
write_c0_count(initcount);
/*
* Wait for all slaves to leave the synchronization point:
* Wait for slave to leave the synchronization point:
*/
while (atomic_read(&count_count_stop) != 1)
mb();
......@@ -83,7 +75,6 @@ void synchronise_count_master(int cpu)
}
/* Arrange for an interrupt in a short while */
write_c0_compare(read_c0_count() + COUNTON);
atomic_set(&count_start_flag, 0);
local_irq_restore(flags);
......@@ -98,19 +89,12 @@ void synchronise_count_master(int cpu)
void synchronise_count_slave(int cpu)
{
int i;
unsigned int initcount;
/*
* Not every cpu is online at the time this gets called,
* so we first wait for the master to say everyone is ready
*/
while (atomic_read(&count_start_flag) != cpu)
mb();
/* Count will be initialised to next expire for all CPU's */
initcount = atomic_read(&count_reference);
for (i = 0; i < NR_LOOPS; i++) {
atomic_inc(&count_count_start);
while (atomic_read(&count_count_start) != 2)
......
......@@ -2250,7 +2250,7 @@ void __init trap_init(void)
* Only some CPUs have the watch exceptions.
*/
if (cpu_has_watch)
set_except_vector(23, handle_watch);
set_except_vector(EXCCODE_WATCH, handle_watch);
/*
* Initialise interrupt handlers
......@@ -2277,27 +2277,27 @@ void __init trap_init(void)
if (board_be_init)
board_be_init();
set_except_vector(0, using_rollback_handler() ? rollback_handle_int
: handle_int);
set_except_vector(1, handle_tlbm);
set_except_vector(2, handle_tlbl);
set_except_vector(3, handle_tlbs);
set_except_vector(EXCCODE_INT, using_rollback_handler() ?
rollback_handle_int : handle_int);
set_except_vector(EXCCODE_MOD, handle_tlbm);
set_except_vector(EXCCODE_TLBL, handle_tlbl);
set_except_vector(EXCCODE_TLBS, handle_tlbs);
set_except_vector(4, handle_adel);
set_except_vector(5, handle_ades);
set_except_vector(EXCCODE_ADEL, handle_adel);
set_except_vector(EXCCODE_ADES, handle_ades);
set_except_vector(6, handle_ibe);
set_except_vector(7, handle_dbe);
set_except_vector(EXCCODE_IBE, handle_ibe);
set_except_vector(EXCCODE_DBE, handle_dbe);
set_except_vector(8, handle_sys);
set_except_vector(9, handle_bp);
set_except_vector(10, rdhwr_noopt ? handle_ri :
set_except_vector(EXCCODE_SYS, handle_sys);
set_except_vector(EXCCODE_BP, handle_bp);
set_except_vector(EXCCODE_RI, rdhwr_noopt ? handle_ri :
(cpu_has_vtag_icache ?
handle_ri_rdhwr_vivt : handle_ri_rdhwr));
set_except_vector(11, handle_cpu);
set_except_vector(12, handle_ov);
set_except_vector(13, handle_tr);
set_except_vector(14, handle_msa_fpe);
set_except_vector(EXCCODE_CPU, handle_cpu);
set_except_vector(EXCCODE_OV, handle_ov);
set_except_vector(EXCCODE_TR, handle_tr);
set_except_vector(EXCCODE_MSAFPE, handle_msa_fpe);
if (current_cpu_type() == CPU_R6000 ||
current_cpu_type() == CPU_R6000A) {
......@@ -2318,25 +2318,25 @@ void __init trap_init(void)
board_nmi_handler_setup();
if (cpu_has_fpu && !cpu_has_nofpuex)
set_except_vector(15, handle_fpe);
set_except_vector(EXCCODE_FPE, handle_fpe);
set_except_vector(16, handle_ftlb);
set_except_vector(MIPS_EXCCODE_TLBPAR, handle_ftlb);
if (cpu_has_rixiex) {
set_except_vector(19, tlb_do_page_fault_0);
set_except_vector(20, tlb_do_page_fault_0);
set_except_vector(EXCCODE_TLBRI, tlb_do_page_fault_0);
set_except_vector(EXCCODE_TLBXI, tlb_do_page_fault_0);
}
set_except_vector(21, handle_msa);
set_except_vector(22, handle_mdmx);
set_except_vector(EXCCODE_MSADIS, handle_msa);
set_except_vector(EXCCODE_MDMX, handle_mdmx);
if (cpu_has_mcheck)
set_except_vector(24, handle_mcheck);
set_except_vector(EXCCODE_MCHECK, handle_mcheck);
if (cpu_has_mipsmt)
set_except_vector(25, handle_mt);
set_except_vector(EXCCODE_THREAD, handle_mt);
set_except_vector(26, handle_dsp);
set_except_vector(EXCCODE_DSPDIS, handle_dsp);
if (board_cache_error_setup)
board_cache_error_setup();
......
......@@ -11,4 +11,4 @@
#include <linux/kvm_host.h>
struct kvm_mips_callbacks *kvm_mips_callbacks;
EXPORT_SYMBOL(kvm_mips_callbacks);
EXPORT_SYMBOL_GPL(kvm_mips_callbacks);
......@@ -86,10 +86,8 @@ int kvm_mips_trans_mfc0(uint32_t inst, uint32_t *opc, struct kvm_vcpu *vcpu)
} else {
mfc0_inst = LW_TEMPLATE;
mfc0_inst |= ((rt & 0x1f) << 16);
mfc0_inst |=
offsetof(struct mips_coproc,
reg[rd][sel]) + offsetof(struct kvm_mips_commpage,
cop0);
mfc0_inst |= offsetof(struct kvm_mips_commpage,
cop0.reg[rd][sel]);
}
if (KVM_GUEST_KSEGX(opc) == KVM_GUEST_KSEG0) {
......@@ -123,9 +121,7 @@ int kvm_mips_trans_mtc0(uint32_t inst, uint32_t *opc, struct kvm_vcpu *vcpu)
sel = inst & 0x7;
mtc0_inst |= ((rt & 0x1f) << 16);
mtc0_inst |=
offsetof(struct mips_coproc,
reg[rd][sel]) + offsetof(struct kvm_mips_commpage, cop0);
mtc0_inst |= offsetof(struct kvm_mips_commpage, cop0.reg[rd][sel]);
if (KVM_GUEST_KSEGX(opc) == KVM_GUEST_KSEG0) {
kseg0_opc =
......
......@@ -20,6 +20,7 @@
#include <linux/random.h>
#include <asm/page.h>
#include <asm/cacheflush.h>
#include <asm/cacheops.h>
#include <asm/cpu-info.h>
#include <asm/mmu_context.h>
#include <asm/tlbflush.h>
......@@ -29,7 +30,6 @@
#include <asm/r4kcache.h>
#define CONFIG_MIPS_MT
#include "opcode.h"
#include "interrupt.h"
#include "commpage.h"
......@@ -1239,21 +1239,20 @@ enum emulation_result kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc,
er = EMULATE_FAIL;
break;
case mfmcz_op:
case mfmc0_op:
#ifdef KVM_MIPS_DEBUG_COP0_COUNTERS
cop0->stat[MIPS_CP0_STATUS][0]++;
#endif
if (rt != 0) {
if (rt != 0)
vcpu->arch.gprs[rt] =
kvm_read_c0_guest_status(cop0);
}
/* EI */
if (inst & 0x20) {
kvm_debug("[%#lx] mfmcz_op: EI\n",
kvm_debug("[%#lx] mfmc0_op: EI\n",
vcpu->arch.pc);
kvm_set_c0_guest_status(cop0, ST0_IE);
} else {
kvm_debug("[%#lx] mfmcz_op: DI\n",
kvm_debug("[%#lx] mfmc0_op: DI\n",
vcpu->arch.pc);
kvm_clear_c0_guest_status(cop0, ST0_IE);
}
......@@ -1545,19 +1544,6 @@ int kvm_mips_sync_icache(unsigned long va, struct kvm_vcpu *vcpu)
return 0;
}
#define MIPS_CACHE_OP_INDEX_INV 0x0
#define MIPS_CACHE_OP_INDEX_LD_TAG 0x1
#define MIPS_CACHE_OP_INDEX_ST_TAG 0x2
#define MIPS_CACHE_OP_IMP 0x3
#define MIPS_CACHE_OP_HIT_INV 0x4
#define MIPS_CACHE_OP_FILL_WB_INV 0x5
#define MIPS_CACHE_OP_HIT_HB 0x6
#define MIPS_CACHE_OP_FETCH_LOCK 0x7
#define MIPS_CACHE_ICACHE 0x0
#define MIPS_CACHE_DCACHE 0x1
#define MIPS_CACHE_SEC 0x3
enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
uint32_t cause,
struct kvm_run *run,
......@@ -1582,8 +1568,8 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
base = (inst >> 21) & 0x1f;
op_inst = (inst >> 16) & 0x1f;
offset = (int16_t)inst;
cache = (inst >> 16) & 0x3;
op = (inst >> 18) & 0x7;
cache = op_inst & CacheOp_Cache;
op = op_inst & CacheOp_Op;
va = arch->gprs[base] + offset;
......@@ -1595,14 +1581,14 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
* invalidate the caches entirely by stepping through all the
* ways/indexes
*/
if (op == MIPS_CACHE_OP_INDEX_INV) {
if (op == Index_Writeback_Inv) {
kvm_debug("@ %#lx/%#lx CACHE (cache: %#x, op: %#x, base[%d]: %#lx, offset: %#x\n",
vcpu->arch.pc, vcpu->arch.gprs[31], cache, op, base,
arch->gprs[base], offset);
if (cache == MIPS_CACHE_DCACHE)
if (cache == Cache_D)
r4k_blast_dcache();
else if (cache == MIPS_CACHE_ICACHE)
else if (cache == Cache_I)
r4k_blast_icache();
else {
kvm_err("%s: unsupported CACHE INDEX operation\n",
......@@ -1675,9 +1661,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
skip_fault:
/* XXXKYMA: Only a subset of cache ops are supported, used by Linux */
if (cache == MIPS_CACHE_DCACHE
&& (op == MIPS_CACHE_OP_FILL_WB_INV
|| op == MIPS_CACHE_OP_HIT_INV)) {
if (op_inst == Hit_Writeback_Inv_D || op_inst == Hit_Invalidate_D) {
flush_dcache_line(va);
#ifdef CONFIG_KVM_MIPS_DYN_TRANS
......@@ -1687,7 +1671,7 @@ enum emulation_result kvm_mips_emulate_cache(uint32_t inst, uint32_t *opc,
*/
kvm_mips_trans_cache_va(inst, opc, vcpu);
#endif
} else if (op == MIPS_CACHE_OP_HIT_INV && cache == MIPS_CACHE_ICACHE) {
} else if (op_inst == Hit_Invalidate_I) {
flush_dcache_line(va);
flush_icache_line(va);
......@@ -1781,7 +1765,7 @@ enum emulation_result kvm_mips_emulate_syscall(unsigned long cause,
kvm_debug("Delivering SYSCALL @ pc %#lx\n", arch->pc);
kvm_change_c0_guest_cause(cop0, (0xff),
(T_SYSCALL << CAUSEB_EXCCODE));
(EXCCODE_SYS << CAUSEB_EXCCODE));
/* Set PC to the exception entry point */
arch->pc = KVM_GUEST_KSEG0 + 0x180;
......@@ -1828,7 +1812,7 @@ enum emulation_result kvm_mips_emulate_tlbmiss_ld(unsigned long cause,
}
kvm_change_c0_guest_cause(cop0, (0xff),
(T_TLB_LD_MISS << CAUSEB_EXCCODE));
(EXCCODE_TLBL << CAUSEB_EXCCODE));
/* setup badvaddr, context and entryhi registers for the guest */
kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
......@@ -1874,7 +1858,7 @@ enum emulation_result kvm_mips_emulate_tlbinv_ld(unsigned long cause,
}
kvm_change_c0_guest_cause(cop0, (0xff),
(T_TLB_LD_MISS << CAUSEB_EXCCODE));
(EXCCODE_TLBL << CAUSEB_EXCCODE));
/* setup badvaddr, context and entryhi registers for the guest */
kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
......@@ -1918,7 +1902,7 @@ enum emulation_result kvm_mips_emulate_tlbmiss_st(unsigned long cause,
}
kvm_change_c0_guest_cause(cop0, (0xff),
(T_TLB_ST_MISS << CAUSEB_EXCCODE));
(EXCCODE_TLBS << CAUSEB_EXCCODE));
/* setup badvaddr, context and entryhi registers for the guest */
kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
......@@ -1962,7 +1946,7 @@ enum emulation_result kvm_mips_emulate_tlbinv_st(unsigned long cause,
}
kvm_change_c0_guest_cause(cop0, (0xff),
(T_TLB_ST_MISS << CAUSEB_EXCCODE));
(EXCCODE_TLBS << CAUSEB_EXCCODE));
/* setup badvaddr, context and entryhi registers for the guest */
kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
......@@ -2033,7 +2017,8 @@ enum emulation_result kvm_mips_emulate_tlbmod(unsigned long cause,
arch->pc = KVM_GUEST_KSEG0 + 0x180;
}
kvm_change_c0_guest_cause(cop0, (0xff), (T_TLB_MOD << CAUSEB_EXCCODE));
kvm_change_c0_guest_cause(cop0, (0xff),
(EXCCODE_MOD << CAUSEB_EXCCODE));
/* setup badvaddr, context and entryhi registers for the guest */
kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);
......@@ -2068,7 +2053,7 @@ enum emulation_result kvm_mips_emulate_fpu_exc(unsigned long cause,
arch->pc = KVM_GUEST_KSEG0 + 0x180;
kvm_change_c0_guest_cause(cop0, (0xff),
(T_COP_UNUSABLE << CAUSEB_EXCCODE));
(EXCCODE_CPU << CAUSEB_EXCCODE));
kvm_change_c0_guest_cause(cop0, (CAUSEF_CE), (0x1 << CAUSEB_CE));
return EMULATE_DONE;
......@@ -2096,7 +2081,7 @@ enum emulation_result kvm_mips_emulate_ri_exc(unsigned long cause,
kvm_debug("Delivering RI @ pc %#lx\n", arch->pc);
kvm_change_c0_guest_cause(cop0, (0xff),
(T_RES_INST << CAUSEB_EXCCODE));
(EXCCODE_RI << CAUSEB_EXCCODE));
/* Set PC to the exception entry point */
arch->pc = KVM_GUEST_KSEG0 + 0x180;
......@@ -2131,7 +2116,7 @@ enum emulation_result kvm_mips_emulate_bp_exc(unsigned long cause,
kvm_debug("Delivering BP @ pc %#lx\n", arch->pc);
kvm_change_c0_guest_cause(cop0, (0xff),
(T_BREAK << CAUSEB_EXCCODE));
(EXCCODE_BP << CAUSEB_EXCCODE));
/* Set PC to the exception entry point */
arch->pc = KVM_GUEST_KSEG0 + 0x180;
......@@ -2166,7 +2151,7 @@ enum emulation_result kvm_mips_emulate_trap_exc(unsigned long cause,
kvm_debug("Delivering TRAP @ pc %#lx\n", arch->pc);
kvm_change_c0_guest_cause(cop0, (0xff),
(T_TRAP << CAUSEB_EXCCODE));
(EXCCODE_TR << CAUSEB_EXCCODE));
/* Set PC to the exception entry point */
arch->pc = KVM_GUEST_KSEG0 + 0x180;
......@@ -2201,7 +2186,7 @@ enum emulation_result kvm_mips_emulate_msafpe_exc(unsigned long cause,
kvm_debug("Delivering MSAFPE @ pc %#lx\n", arch->pc);
kvm_change_c0_guest_cause(cop0, (0xff),
(T_MSAFPE << CAUSEB_EXCCODE));
(EXCCODE_MSAFPE << CAUSEB_EXCCODE));
/* Set PC to the exception entry point */
arch->pc = KVM_GUEST_KSEG0 + 0x180;
......@@ -2236,7 +2221,7 @@ enum emulation_result kvm_mips_emulate_fpe_exc(unsigned long cause,
kvm_debug("Delivering FPE @ pc %#lx\n", arch->pc);
kvm_change_c0_guest_cause(cop0, (0xff),
(T_FPE << CAUSEB_EXCCODE));
(EXCCODE_FPE << CAUSEB_EXCCODE));
/* Set PC to the exception entry point */
arch->pc = KVM_GUEST_KSEG0 + 0x180;
......@@ -2271,7 +2256,7 @@ enum emulation_result kvm_mips_emulate_msadis_exc(unsigned long cause,
kvm_debug("Delivering MSADIS @ pc %#lx\n", arch->pc);
kvm_change_c0_guest_cause(cop0, (0xff),
(T_MSADIS << CAUSEB_EXCCODE));
(EXCCODE_MSADIS << CAUSEB_EXCCODE));
/* Set PC to the exception entry point */
arch->pc = KVM_GUEST_KSEG0 + 0x180;
......@@ -2480,25 +2465,25 @@ enum emulation_result kvm_mips_check_privilege(unsigned long cause,
if (usermode) {
switch (exccode) {
case T_INT:
case T_SYSCALL:
case T_BREAK:
case T_RES_INST:
case T_TRAP:
case T_MSAFPE:
case T_FPE:
case T_MSADIS:
case EXCCODE_INT:
case EXCCODE_SYS:
case EXCCODE_BP:
case EXCCODE_RI:
case EXCCODE_TR:
case EXCCODE_MSAFPE:
case EXCCODE_FPE:
case EXCCODE_MSADIS:
break;
case T_COP_UNUSABLE:
case EXCCODE_CPU:
if (((cause & CAUSEF_CE) >> CAUSEB_CE) == 0)
er = EMULATE_PRIV_FAIL;
break;
case T_TLB_MOD:
case EXCCODE_MOD:
break;
case T_TLB_LD_MISS:
case EXCCODE_TLBL:
/*
* We we are accessing Guest kernel space, then send an
* address error exception to the guest
......@@ -2507,12 +2492,12 @@ enum emulation_result kvm_mips_check_privilege(unsigned long cause,
kvm_debug("%s: LD MISS @ %#lx\n", __func__,
badvaddr);
cause &= ~0xff;
cause |= (T_ADDR_ERR_LD << CAUSEB_EXCCODE);
cause |= (EXCCODE_ADEL << CAUSEB_EXCCODE);
er = EMULATE_PRIV_FAIL;
}
break;
case T_TLB_ST_MISS:
case EXCCODE_TLBS:
/*
* We we are accessing Guest kernel space, then send an
* address error exception to the guest
......@@ -2521,26 +2506,26 @@ enum emulation_result kvm_mips_check_privilege(unsigned long cause,
kvm_debug("%s: ST MISS @ %#lx\n", __func__,
badvaddr);
cause &= ~0xff;
cause |= (T_ADDR_ERR_ST << CAUSEB_EXCCODE);
cause |= (EXCCODE_ADES << CAUSEB_EXCCODE);
er = EMULATE_PRIV_FAIL;
}
break;
case T_ADDR_ERR_ST:
case EXCCODE_ADES:
kvm_debug("%s: address error ST @ %#lx\n", __func__,
badvaddr);
if ((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR) {
cause &= ~0xff;
cause |= (T_TLB_ST_MISS << CAUSEB_EXCCODE);
cause |= (EXCCODE_TLBS << CAUSEB_EXCCODE);
}
er = EMULATE_PRIV_FAIL;
break;
case T_ADDR_ERR_LD:
case EXCCODE_ADEL:
kvm_debug("%s: address error LD @ %#lx\n", __func__,
badvaddr);
if ((badvaddr & PAGE_MASK) == KVM_GUEST_COMMPAGE_ADDR) {
cause &= ~0xff;
cause |= (T_TLB_LD_MISS << CAUSEB_EXCCODE);
cause |= (EXCCODE_TLBL << CAUSEB_EXCCODE);
}
er = EMULATE_PRIV_FAIL;
break;
......@@ -2584,12 +2569,11 @@ enum emulation_result kvm_mips_handle_tlbmiss(unsigned long cause,
*/
index = kvm_mips_guest_tlb_lookup(vcpu,
(va & VPN2_MASK) |
(kvm_read_c0_guest_entryhi
(vcpu->arch.cop0) & ASID_MASK));
(kvm_read_c0_guest_entryhi(vcpu->arch.cop0) & ASID_MASK));
if (index < 0) {
if (exccode == T_TLB_LD_MISS) {
if (exccode == EXCCODE_TLBL) {
er = kvm_mips_emulate_tlbmiss_ld(cause, opc, run, vcpu);
} else if (exccode == T_TLB_ST_MISS) {
} else if (exccode == EXCCODE_TLBS) {
er = kvm_mips_emulate_tlbmiss_st(cause, opc, run, vcpu);
} else {
kvm_err("%s: invalid exc code: %d\n", __func__,
......@@ -2604,10 +2588,10 @@ enum emulation_result kvm_mips_handle_tlbmiss(unsigned long cause,
* exception to the guest
*/
if (!TLB_IS_VALID(*tlb, va)) {
if (exccode == T_TLB_LD_MISS) {
if (exccode == EXCCODE_TLBL) {
er = kvm_mips_emulate_tlbinv_ld(cause, opc, run,
vcpu);
} else if (exccode == T_TLB_ST_MISS) {
} else if (exccode == EXCCODE_TLBS) {
er = kvm_mips_emulate_tlbinv_st(cause, opc, run,
vcpu);
} else {
......
......@@ -128,7 +128,7 @@ int kvm_mips_irq_deliver_cb(struct kvm_vcpu *vcpu, unsigned int priority,
&& (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL)))
&& (kvm_read_c0_guest_status(cop0) & IE_IRQ5)) {
allowed = 1;
exccode = T_INT;
exccode = EXCCODE_INT;
}
break;
......@@ -137,7 +137,7 @@ int kvm_mips_irq_deliver_cb(struct kvm_vcpu *vcpu, unsigned int priority,
&& (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL)))
&& (kvm_read_c0_guest_status(cop0) & IE_IRQ0)) {
allowed = 1;
exccode = T_INT;
exccode = EXCCODE_INT;
}
break;
......@@ -146,7 +146,7 @@ int kvm_mips_irq_deliver_cb(struct kvm_vcpu *vcpu, unsigned int priority,
&& (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL)))
&& (kvm_read_c0_guest_status(cop0) & IE_IRQ1)) {
allowed = 1;
exccode = T_INT;
exccode = EXCCODE_INT;
}
break;
......@@ -155,7 +155,7 @@ int kvm_mips_irq_deliver_cb(struct kvm_vcpu *vcpu, unsigned int priority,
&& (!(kvm_read_c0_guest_status(cop0) & (ST0_EXL | ST0_ERL)))
&& (kvm_read_c0_guest_status(cop0) & IE_IRQ2)) {
allowed = 1;
exccode = T_INT;
exccode = EXCCODE_INT;
}
break;
......
......@@ -335,7 +335,7 @@ NESTED (MIPSX(GuestException), CALLFRAME_SIZ, ra)
/* Now restore the host state just enough to run the handlers */
/* Swtich EBASE to the one used by Linux */
/* Switch EBASE to the one used by Linux */
/* load up the host EBASE */
mfc0 v0, CP0_STATUS
......@@ -490,7 +490,7 @@ __kvm_mips_return_to_guest:
REG_ADDU t3, t1, t2
LONG_L k0, (t3)
andi k0, k0, 0xff
mtc0 k0,CP0_ENTRYHI
mtc0 k0, CP0_ENTRYHI
ehb
/* Disable RDHWR access */
......
......@@ -229,7 +229,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
kzalloc(npages * sizeof(unsigned long), GFP_KERNEL);
if (!kvm->arch.guest_pmap) {
kvm_err("Failed to allocate guest PMAP");
kvm_err("Failed to allocate guest PMAP\n");
return;
}
......@@ -1264,8 +1264,8 @@ int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
}
switch (exccode) {
case T_INT:
kvm_debug("[%d]T_INT @ %p\n", vcpu->vcpu_id, opc);
case EXCCODE_INT:
kvm_debug("[%d]EXCCODE_INT @ %p\n", vcpu->vcpu_id, opc);
++vcpu->stat.int_exits;
trace_kvm_exit(vcpu, INT_EXITS);
......@@ -1276,8 +1276,8 @@ int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
ret = RESUME_GUEST;
break;
case T_COP_UNUSABLE:
kvm_debug("T_COP_UNUSABLE: @ PC: %p\n", opc);
case EXCCODE_CPU:
kvm_debug("EXCCODE_CPU: @ PC: %p\n", opc);
++vcpu->stat.cop_unusable_exits;
trace_kvm_exit(vcpu, COP_UNUSABLE_EXITS);
......@@ -1287,13 +1287,13 @@ int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
ret = RESUME_HOST;
break;
case T_TLB_MOD:
case EXCCODE_MOD:
++vcpu->stat.tlbmod_exits;
trace_kvm_exit(vcpu, TLBMOD_EXITS);
ret = kvm_mips_callbacks->handle_tlb_mod(vcpu);
break;
case T_TLB_ST_MISS:
case EXCCODE_TLBS:
kvm_debug("TLB ST fault: cause %#x, status %#lx, PC: %p, BadVaddr: %#lx\n",
cause, kvm_read_c0_guest_status(vcpu->arch.cop0), opc,
badvaddr);
......@@ -1303,7 +1303,7 @@ int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
ret = kvm_mips_callbacks->handle_tlb_st_miss(vcpu);
break;
case T_TLB_LD_MISS:
case EXCCODE_TLBL:
kvm_debug("TLB LD fault: cause %#x, PC: %p, BadVaddr: %#lx\n",
cause, opc, badvaddr);
......@@ -1312,55 +1312,55 @@ int kvm_mips_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
ret = kvm_mips_callbacks->handle_tlb_ld_miss(vcpu);
break;
case T_ADDR_ERR_ST:
case EXCCODE_ADES:
++vcpu->stat.addrerr_st_exits;
trace_kvm_exit(vcpu, ADDRERR_ST_EXITS);
ret = kvm_mips_callbacks->handle_addr_err_st(vcpu);
break;
case T_ADDR_ERR_LD:
case EXCCODE_ADEL:
++vcpu->stat.addrerr_ld_exits;
trace_kvm_exit(vcpu, ADDRERR_LD_EXITS);
ret = kvm_mips_callbacks->handle_addr_err_ld(vcpu);
break;
case T_SYSCALL:
case EXCCODE_SYS:
++vcpu->stat.syscall_exits;
trace_kvm_exit(vcpu, SYSCALL_EXITS);
ret = kvm_mips_callbacks->handle_syscall(vcpu);
break;
case T_RES_INST:
case EXCCODE_RI:
++vcpu->stat.resvd_inst_exits;
trace_kvm_exit(vcpu, RESVD_INST_EXITS);
ret = kvm_mips_callbacks->handle_res_inst(vcpu);
break;
case T_BREAK:
case EXCCODE_BP:
++vcpu->stat.break_inst_exits;
trace_kvm_exit(vcpu, BREAK_INST_EXITS);
ret = kvm_mips_callbacks->handle_break(vcpu);
break;
case T_TRAP:
case EXCCODE_TR:
++vcpu->stat.trap_inst_exits;
trace_kvm_exit(vcpu, TRAP_INST_EXITS);
ret = kvm_mips_callbacks->handle_trap(vcpu);
break;
case T_MSAFPE:
case EXCCODE_MSAFPE:
++vcpu->stat.msa_fpe_exits;
trace_kvm_exit(vcpu, MSA_FPE_EXITS);
ret = kvm_mips_callbacks->handle_msa_fpe(vcpu);
break;
case T_FPE:
case EXCCODE_FPE:
++vcpu->stat.fpe_exits;
trace_kvm_exit(vcpu, FPE_EXITS);
ret = kvm_mips_callbacks->handle_fpe(vcpu);
break;
case T_MSADIS:
case EXCCODE_MSADIS:
++vcpu->stat.msa_disabled_exits;
trace_kvm_exit(vcpu, MSA_DISABLED_EXITS);
ret = kvm_mips_callbacks->handle_msa_disabled(vcpu);
......@@ -1620,7 +1620,7 @@ static struct notifier_block kvm_mips_csr_die_notifier = {
.notifier_call = kvm_mips_csr_die_notify,
};
int __init kvm_mips_init(void)
static int __init kvm_mips_init(void)
{
int ret;
......@@ -1646,7 +1646,7 @@ int __init kvm_mips_init(void)
return 0;
}
void __exit kvm_mips_exit(void)
static void __exit kvm_mips_exit(void)
{
kvm_exit();
......
/*
* 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) 2012 MIPS Technologies, Inc. All rights reserved.
* Authors: Sanjay Lal <sanjayl@kymasys.com>
*/
/* Define opcode values not defined in <asm/isnt.h> */
#ifndef __KVM_MIPS_OPCODE_H__
#define __KVM_MIPS_OPCODE_H__
/* COP0 Ops */
#define mfmcz_op 0x0b /* 01011 */
#define wrpgpr_op 0x0e /* 01110 */
/* COP0 opcodes (only if COP0 and CO=1): */
#define wait_op 0x20 /* 100000 */
#endif /* __KVM_MIPS_OPCODE_H__ */
......@@ -35,17 +35,17 @@
#define PRIx64 "llx"
atomic_t kvm_mips_instance;
EXPORT_SYMBOL(kvm_mips_instance);
EXPORT_SYMBOL_GPL(kvm_mips_instance);
/* These function pointers are initialized once the KVM module is loaded */
kvm_pfn_t (*kvm_mips_gfn_to_pfn)(struct kvm *kvm, gfn_t gfn);
EXPORT_SYMBOL(kvm_mips_gfn_to_pfn);
EXPORT_SYMBOL_GPL(kvm_mips_gfn_to_pfn);
void (*kvm_mips_release_pfn_clean)(kvm_pfn_t pfn);
EXPORT_SYMBOL(kvm_mips_release_pfn_clean);
EXPORT_SYMBOL_GPL(kvm_mips_release_pfn_clean);
bool (*kvm_mips_is_error_pfn)(kvm_pfn_t pfn);
EXPORT_SYMBOL(kvm_mips_is_error_pfn);
EXPORT_SYMBOL_GPL(kvm_mips_is_error_pfn);
uint32_t kvm_mips_get_kernel_asid(struct kvm_vcpu *vcpu)
{
......@@ -111,7 +111,7 @@ void kvm_mips_dump_host_tlbs(void)
mtc0_tlbw_hazard();
local_irq_restore(flags);
}
EXPORT_SYMBOL(kvm_mips_dump_host_tlbs);
EXPORT_SYMBOL_GPL(kvm_mips_dump_host_tlbs);
void kvm_mips_dump_guest_tlbs(struct kvm_vcpu *vcpu)
{
......@@ -139,7 +139,7 @@ void kvm_mips_dump_guest_tlbs(struct kvm_vcpu *vcpu)
(tlb.tlb_lo1 >> 3) & 7, tlb.tlb_mask);
}
}
EXPORT_SYMBOL(kvm_mips_dump_guest_tlbs);
EXPORT_SYMBOL_GPL(kvm_mips_dump_guest_tlbs);
static int kvm_mips_map_page(struct kvm *kvm, gfn_t gfn)
{
......@@ -191,7 +191,7 @@ unsigned long kvm_mips_translate_guest_kseg0_to_hpa(struct kvm_vcpu *vcpu,
return (kvm->arch.guest_pmap[gfn] << PAGE_SHIFT) + offset;
}
EXPORT_SYMBOL(kvm_mips_translate_guest_kseg0_to_hpa);
EXPORT_SYMBOL_GPL(kvm_mips_translate_guest_kseg0_to_hpa);
/* XXXKYMA: Must be called with interrupts disabled */
/* set flush_dcache_mask == 0 if no dcache flush required */
......@@ -308,7 +308,7 @@ int kvm_mips_handle_kseg0_tlb_fault(unsigned long badvaddr,
return kvm_mips_host_tlb_write(vcpu, entryhi, entrylo0, entrylo1,
flush_dcache_mask);
}
EXPORT_SYMBOL(kvm_mips_handle_kseg0_tlb_fault);
EXPORT_SYMBOL_GPL(kvm_mips_handle_kseg0_tlb_fault);
int kvm_mips_handle_commpage_tlb_fault(unsigned long badvaddr,
struct kvm_vcpu *vcpu)
......@@ -351,7 +351,7 @@ int kvm_mips_handle_commpage_tlb_fault(unsigned long badvaddr,
return 0;
}
EXPORT_SYMBOL(kvm_mips_handle_commpage_tlb_fault);
EXPORT_SYMBOL_GPL(kvm_mips_handle_commpage_tlb_fault);
int kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu,
struct kvm_mips_tlb *tlb,
......@@ -401,7 +401,7 @@ int kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu,
return kvm_mips_host_tlb_write(vcpu, entryhi, entrylo0, entrylo1,
tlb->tlb_mask);
}
EXPORT_SYMBOL(kvm_mips_handle_mapped_seg_tlb_fault);
EXPORT_SYMBOL_GPL(kvm_mips_handle_mapped_seg_tlb_fault);
int kvm_mips_guest_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long entryhi)
{
......@@ -422,7 +422,7 @@ int kvm_mips_guest_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long entryhi)
return index;
}
EXPORT_SYMBOL(kvm_mips_guest_tlb_lookup);
EXPORT_SYMBOL_GPL(kvm_mips_guest_tlb_lookup);
int kvm_mips_host_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long vaddr)
{
......@@ -458,7 +458,7 @@ int kvm_mips_host_tlb_lookup(struct kvm_vcpu *vcpu, unsigned long vaddr)
return idx;
}
EXPORT_SYMBOL(kvm_mips_host_tlb_lookup);
EXPORT_SYMBOL_GPL(kvm_mips_host_tlb_lookup);
int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long va)
{
......@@ -505,44 +505,7 @@ int kvm_mips_host_tlb_inv(struct kvm_vcpu *vcpu, unsigned long va)
return 0;
}
EXPORT_SYMBOL(kvm_mips_host_tlb_inv);
/* XXXKYMA: Fix Guest USER/KERNEL no longer share the same ASID */
int kvm_mips_host_tlb_inv_index(struct kvm_vcpu *vcpu, int index)
{
unsigned long flags, old_entryhi;
if (index >= current_cpu_data.tlbsize)
BUG();
local_irq_save(flags);
old_entryhi = read_c0_entryhi();
write_c0_entryhi(UNIQUE_ENTRYHI(index));
mtc0_tlbw_hazard();
write_c0_index(index);
mtc0_tlbw_hazard();
write_c0_entrylo0(0);
mtc0_tlbw_hazard();
write_c0_entrylo1(0);
mtc0_tlbw_hazard();
tlb_write_indexed();
mtc0_tlbw_hazard();
tlbw_use_hazard();
write_c0_entryhi(old_entryhi);
mtc0_tlbw_hazard();
tlbw_use_hazard();
local_irq_restore(flags);
return 0;
}
EXPORT_SYMBOL_GPL(kvm_mips_host_tlb_inv);
void kvm_mips_flush_host_tlb(int skip_kseg0)
{
......@@ -594,7 +557,7 @@ void kvm_mips_flush_host_tlb(int skip_kseg0)
local_irq_restore(flags);
}
EXPORT_SYMBOL(kvm_mips_flush_host_tlb);
EXPORT_SYMBOL_GPL(kvm_mips_flush_host_tlb);
void kvm_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu,
struct kvm_vcpu *vcpu)
......@@ -642,7 +605,7 @@ void kvm_local_flush_tlb_all(void)
local_irq_restore(flags);
}
EXPORT_SYMBOL(kvm_local_flush_tlb_all);
EXPORT_SYMBOL_GPL(kvm_local_flush_tlb_all);
/**
* kvm_mips_migrate_count() - Migrate timer.
......@@ -673,8 +636,8 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
local_irq_save(flags);
if (((vcpu->arch.
guest_kernel_asid[cpu] ^ asid_cache(cpu)) & ASID_VERSION_MASK)) {
if ((vcpu->arch.guest_kernel_asid[cpu] ^ asid_cache(cpu)) &
ASID_VERSION_MASK) {
kvm_get_new_mmu_context(&vcpu->arch.guest_kernel_mm, cpu, vcpu);
vcpu->arch.guest_kernel_asid[cpu] =
vcpu->arch.guest_kernel_mm.context.asid[cpu];
......@@ -739,7 +702,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
local_irq_restore(flags);
}
EXPORT_SYMBOL(kvm_arch_vcpu_load);
EXPORT_SYMBOL_GPL(kvm_arch_vcpu_load);
/* ASID can change if another task is scheduled during preemption */
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
......@@ -768,7 +731,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
local_irq_restore(flags);
}
EXPORT_SYMBOL(kvm_arch_vcpu_put);
EXPORT_SYMBOL_GPL(kvm_arch_vcpu_put);
uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu)
{
......@@ -813,4 +776,4 @@ uint32_t kvm_get_inst(uint32_t *opc, struct kvm_vcpu *vcpu)
return inst;
}
EXPORT_SYMBOL(kvm_get_inst);
EXPORT_SYMBOL_GPL(kvm_get_inst);
......@@ -16,7 +16,6 @@
#include <linux/kvm_host.h>
#include "opcode.h"
#include "interrupt.h"
static gpa_t kvm_trap_emul_gva_to_gpa_cb(gva_t gva)
......
......@@ -57,7 +57,6 @@ notrace void arch_local_irq_disable(void)
}
EXPORT_SYMBOL(arch_local_irq_disable);
notrace unsigned long arch_local_irq_save(void)
{
unsigned long flags;
......@@ -111,31 +110,4 @@ notrace void arch_local_irq_restore(unsigned long flags)
}
EXPORT_SYMBOL(arch_local_irq_restore);
notrace void __arch_local_irq_restore(unsigned long flags)
{
unsigned long __tmp1;
preempt_disable();
__asm__ __volatile__(
" .set push \n"
" .set noreorder \n"
" .set noat \n"
" mfc0 $1, $12 \n"
" andi %[flags], 1 \n"
" ori $1, 0x1f \n"
" xori $1, 0x1f \n"
" or %[flags], $1 \n"
" mtc0 %[flags], $12 \n"
" " __stringify(__irq_disable_hazard) " \n"
" .set pop \n"
: [flags] "=r" (__tmp1)
: "0" (flags)
: "memory");
preempt_enable();
}
EXPORT_SYMBOL(__arch_local_irq_restore);
#endif /* !CONFIG_CPU_MIPSR2 */
#endif /* !CONFIG_CPU_MIPSR2 && !CONFIG_CPU_MIPSR6 */
......@@ -22,6 +22,27 @@ ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS
endif
endif
cflags-$(CONFIG_CPU_LOONGSON3) += -Wa,--trap
#
# binutils from v2.25 on and gcc starting from v4.9.0 treat -march=loongson3a
# as MIPS64 R2; older versions as just R1. This leaves the possibility open
# that GCC might generate R2 code for -march=loongson3a which then is rejected
# by GAS. The cc-option can't probe for this behaviour so -march=loongson3a
# can't easily be used safely within the kbuild framework.
#
ifeq ($(call cc-ifversion, -ge, 0409, y), y)
ifeq ($(call ld-ifversion, -ge, 22500000, y), y)
cflags-$(CONFIG_CPU_LOONGSON3) += \
$(call cc-option,-march=loongson3a -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64)
else
cflags-$(CONFIG_CPU_LOONGSON3) += \
$(call cc-option,-march=mips64r2,-mips64r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64)
endif
else
cflags-$(CONFIG_CPU_LOONGSON3) += \
$(call cc-option,-march=mips64r2,-mips64r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64)
endif
#
# Loongson Machines' Support
#
......
......@@ -13,6 +13,9 @@
#define SMBUS_PCI_REG64 0x64
#define SMBUS_PCI_REGB4 0xb4
#define HPET_MIN_CYCLES 64
#define HPET_MIN_PROG_DELTA (HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1))
static DEFINE_SPINLOCK(hpet_lock);
DEFINE_PER_CPU(struct clock_event_device, hpet_clockevent_device);
......@@ -161,8 +164,9 @@ static int hpet_next_event(unsigned long delta,
cnt += delta;
hpet_write(HPET_T0_CMP, cnt);
res = ((int)(hpet_read(HPET_COUNTER) - cnt) > 0) ? -ETIME : 0;
return res;
res = (int)(cnt - hpet_read(HPET_COUNTER));
return res < HPET_MIN_CYCLES ? -ETIME : 0;
}
static irqreturn_t hpet_irq_handler(int irq, void *data)
......@@ -237,7 +241,7 @@ void __init setup_hpet_timer(void)
cd->cpumask = cpumask_of(cpu);
clockevent_set_clock(cd, HPET_FREQ);
cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
cd->min_delta_ns = 5000;
cd->min_delta_ns = clockevent_delta2ns(HPET_MIN_PROG_DELTA, cd);
clockevents_register_device(cd);
setup_irq(HPET_T0_IRQ, &hpet_irq);
......
......@@ -30,13 +30,13 @@
#include "smp.h"
DEFINE_PER_CPU(int, cpu_state);
DEFINE_PER_CPU(uint32_t, core0_c0count);
static void *ipi_set0_regs[16];
static void *ipi_clear0_regs[16];
static void *ipi_status0_regs[16];
static void *ipi_en0_regs[16];
static void *ipi_mailbox_buf[16];
static uint32_t core0_c0count[NR_CPUS];
/* read a 32bit value from ipi register */
#define loongson3_ipi_read32(addr) readl(addr)
......@@ -275,12 +275,14 @@ void loongson3_ipi_interrupt(struct pt_regs *regs)
if (action & SMP_ASK_C0COUNT) {
BUG_ON(cpu != 0);
c0count = read_c0_count();
for (i = 1; i < num_possible_cpus(); i++)
per_cpu(core0_c0count, i) = c0count;
c0count = c0count ? c0count : 1;
for (i = 1; i < nr_cpu_ids; i++)
core0_c0count[i] = c0count;
__wbflush(); /* Let others see the result ASAP */
}
}
#define MAX_LOOPS 1111
#define MAX_LOOPS 800
/*
* SMP init and finish on secondary CPUs
*/
......@@ -305,16 +307,20 @@ static void loongson3_init_secondary(void)
cpu_logical_map(cpu) / loongson_sysconf.cores_per_package;
i = 0;
__this_cpu_write(core0_c0count, 0);
core0_c0count[cpu] = 0;
loongson3_send_ipi_single(0, SMP_ASK_C0COUNT);
while (!__this_cpu_read(core0_c0count)) {
while (!core0_c0count[cpu]) {
i++;
cpu_relax();
}
if (i > MAX_LOOPS)
i = MAX_LOOPS;
initcount = __this_cpu_read(core0_c0count) + i;
if (cpu_data[cpu].package)
initcount = core0_c0count[cpu] + i;
else /* Local access is faster for loops */
initcount = core0_c0count[cpu] + i/2;
write_c0_count(initcount);
}
......
......@@ -1266,6 +1266,8 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
*/
sig = mips_dsemul(xcp, ir,
contpc);
if (sig < 0)
break;
if (sig)
xcp->cp0_epc = bcpc;
/*
......@@ -1319,6 +1321,8 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
* instruction in the dslot
*/
sig = mips_dsemul(xcp, ir, contpc);
if (sig < 0)
break;
if (sig)
xcp->cp0_epc = bcpc;
/* SIGILL forces out of the emulation loop. */
......
......@@ -23,21 +23,32 @@
union ieee754dp ieee754dp_neg(union ieee754dp x)
{
unsigned int oldrm;
union ieee754dp y;
if (ieee754_csr.abs2008) {
y = x;
DPSIGN(y) = !DPSIGN(x);
} else {
unsigned int oldrm;
oldrm = ieee754_csr.rm;
ieee754_csr.rm = FPU_CSR_RD;
y = ieee754dp_sub(ieee754dp_zero(0), x);
ieee754_csr.rm = oldrm;
}
return y;
}
union ieee754dp ieee754dp_abs(union ieee754dp x)
{
unsigned int oldrm;
union ieee754dp y;
if (ieee754_csr.abs2008) {
y = x;
DPSIGN(y) = 0;
} else {
unsigned int oldrm;
oldrm = ieee754_csr.rm;
ieee754_csr.rm = FPU_CSR_RD;
if (DPSIGN(x))
......@@ -45,5 +56,6 @@ union ieee754dp ieee754dp_abs(union ieee754dp x)
else
y = ieee754dp_add(ieee754dp_zero(0), x);
ieee754_csr.rm = oldrm;
}
return y;
}
......@@ -38,10 +38,13 @@ int ieee754dp_tint(union ieee754dp x)
switch (xc) {
case IEEE754_CLASS_SNAN:
case IEEE754_CLASS_QNAN:
case IEEE754_CLASS_INF:
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754si_indef();
case IEEE754_CLASS_INF:
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754si_overflow(xs);
case IEEE754_CLASS_ZERO:
return 0;
......@@ -53,7 +56,7 @@ int ieee754dp_tint(union ieee754dp x)
/* Set invalid. We will only use overflow for floating
point overflow */
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754si_indef();
return ieee754si_overflow(xs);
}
/* oh gawd */
if (xe > DP_FBITS) {
......@@ -93,7 +96,7 @@ int ieee754dp_tint(union ieee754dp x)
if ((xm >> 31) != 0 && (xs == 0 || xm != 0x80000000)) {
/* This can happen after rounding */
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754si_indef();
return ieee754si_overflow(xs);
}
if (round || sticky)
ieee754_setcx(IEEE754_INEXACT);
......
......@@ -38,10 +38,13 @@ s64 ieee754dp_tlong(union ieee754dp x)
switch (xc) {
case IEEE754_CLASS_SNAN:
case IEEE754_CLASS_QNAN:
case IEEE754_CLASS_INF:
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754di_indef();
case IEEE754_CLASS_INF:
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754di_overflow(xs);
case IEEE754_CLASS_ZERO:
return 0;
......@@ -56,7 +59,7 @@ s64 ieee754dp_tlong(union ieee754dp x)
/* Set invalid. We will only use overflow for floating
point overflow */
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754di_indef();
return ieee754di_overflow(xs);
}
/* oh gawd */
if (xe > DP_FBITS) {
......@@ -97,7 +100,7 @@ s64 ieee754dp_tlong(union ieee754dp x)
if ((xm >> 63) != 0) {
/* This can happen after rounding */
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754di_indef();
return ieee754di_overflow(xs);
}
if (round || sticky)
ieee754_setcx(IEEE754_INEXACT);
......
......@@ -31,17 +31,41 @@ struct emuframe {
unsigned long epc;
};
/*
* Set up an emulation frame for instruction IR, from a delay slot of
* a branch jumping to CPC. Return 0 if successful, -1 if no emulation
* required, otherwise a signal number causing a frame setup failure.
*/
int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
{
int isa16 = get_isa16_mode(regs->cp0_epc);
mips_instruction break_math;
struct emuframe __user *fr;
int err;
if ((get_isa16_mode(regs->cp0_epc) && ((ir >> 16) == MM_NOP16)) ||
(ir == 0)) {
/* NOP is easy */
regs->cp0_epc = cpc;
clear_delay_slot(regs);
return 0;
if (ir == 0)
return -1;
/* microMIPS instructions */
if (isa16) {
union mips_instruction insn = { .word = ir };
/* NOP16 aka MOVE16 $0, $0 */
if ((ir >> 16) == MM_NOP16)
return -1;
/* ADDIUPC */
if (insn.mm_a_format.opcode == mm_addiupc_op) {
unsigned int rs;
s32 v;
rs = (((insn.mm_a_format.rs + 0x1e) & 0xf) + 2);
v = regs->cp0_epc & ~3;
v += insn.mm_a_format.simmediate << 2;
regs->regs[rs] = (long)v;
return -1;
}
}
pr_debug("dsemul %lx %lx\n", regs->cp0_epc, cpc);
......@@ -55,14 +79,10 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
* Algorithmics used a system call instruction, and
* borrowed that vector. MIPS/Linux version is a bit
* more heavyweight in the interests of portability and
* multiprocessor support. For Linux we generate a
* an unaligned access and force an address error exception.
*
* For embedded systems (stand-alone) we prefer to use a
* non-existing CP1 instruction. This prevents us from emulating
* branches, but gives us a cleaner interface to the exception
* handler (single entry point).
* multiprocessor support. For Linux we use a BREAK 514
* instruction causing a breakpoint exception.
*/
break_math = BREAK_MATH(isa16);
/* Ensure that the two instructions are in the same cache line */
fr = (struct emuframe __user *)
......@@ -72,14 +92,18 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
if (unlikely(!access_ok(VERIFY_WRITE, fr, sizeof(struct emuframe))))
return SIGBUS;
if (get_isa16_mode(regs->cp0_epc)) {
err = __put_user(ir >> 16, (u16 __user *)(&fr->emul));
err |= __put_user(ir & 0xffff, (u16 __user *)((long)(&fr->emul) + 2));
err |= __put_user(BREAK_MATH >> 16, (u16 __user *)(&fr->badinst));
err |= __put_user(BREAK_MATH & 0xffff, (u16 __user *)((long)(&fr->badinst) + 2));
if (isa16) {
err = __put_user(ir >> 16,
(u16 __user *)(&fr->emul));
err |= __put_user(ir & 0xffff,
(u16 __user *)((long)(&fr->emul) + 2));
err |= __put_user(break_math >> 16,
(u16 __user *)(&fr->badinst));
err |= __put_user(break_math & 0xffff,
(u16 __user *)((long)(&fr->badinst) + 2));
} else {
err = __put_user(ir, &fr->emul);
err |= __put_user((mips_instruction)BREAK_MATH, &fr->badinst);
err |= __put_user(break_math, &fr->badinst);
}
err |= __put_user((mips_instruction)BD_COOKIE, &fr->cookie);
......@@ -90,8 +114,7 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
return SIGBUS;
}
regs->cp0_epc = ((unsigned long) &fr->emul) |
get_isa16_mode(regs->cp0_epc);
regs->cp0_epc = (unsigned long)&fr->emul | isa16;
flush_cache_sigtramp((unsigned long)&fr->emul);
......@@ -100,6 +123,7 @@ int mips_dsemul(struct pt_regs *regs, mips_instruction ir, unsigned long cpc)
int do_dsemulret(struct pt_regs *xcp)
{
int isa16 = get_isa16_mode(xcp->cp0_epc);
struct emuframe __user *fr;
unsigned long epc;
u32 insn, cookie;
......@@ -122,16 +146,19 @@ int do_dsemulret(struct pt_regs *xcp)
* - Is the instruction pointed to by the EPC an BREAK_MATH?
* - Is the following memory word the BD_COOKIE?
*/
if (get_isa16_mode(xcp->cp0_epc)) {
err = __get_user(instr[0], (u16 __user *)(&fr->badinst));
err |= __get_user(instr[1], (u16 __user *)((long)(&fr->badinst) + 2));
if (isa16) {
err = __get_user(instr[0],
(u16 __user *)(&fr->badinst));
err |= __get_user(instr[1],
(u16 __user *)((long)(&fr->badinst) + 2));
insn = (instr[0] << 16) | instr[1];
} else {
err = __get_user(insn, &fr->badinst);
}
err |= __get_user(cookie, &fr->cookie);
if (unlikely(err || (insn != BREAK_MATH) || (cookie != BD_COOKIE))) {
if (unlikely(err ||
insn != BREAK_MATH(isa16) || cookie != BD_COOKIE)) {
MIPS_FPU_EMU_INC_STATS(errors);
return 0;
}
......
......@@ -59,7 +59,8 @@ const union ieee754dp __ieee754dp_spcvals[] = {
DPCNST(1, 3, 0x4000000000000ULL), /* - 10.0 */
DPCNST(0, DP_EMAX + 1, 0x0000000000000ULL), /* + infinity */
DPCNST(1, DP_EMAX + 1, 0x0000000000000ULL), /* - infinity */
DPCNST(0, DP_EMAX + 1, 0x7FFFFFFFFFFFFULL), /* + indef quiet Nan */
DPCNST(0, DP_EMAX + 1, 0x7FFFFFFFFFFFFULL), /* + ind legacy qNaN */
DPCNST(0, DP_EMAX + 1, 0x8000000000000ULL), /* + indef 2008 qNaN */
DPCNST(0, DP_EMAX, 0xFFFFFFFFFFFFFULL), /* + max */
DPCNST(1, DP_EMAX, 0xFFFFFFFFFFFFFULL), /* - max */
DPCNST(0, DP_EMIN, 0x0000000000000ULL), /* + min normal */
......@@ -82,7 +83,8 @@ const union ieee754sp __ieee754sp_spcvals[] = {
SPCNST(1, 3, 0x200000), /* - 10.0 */
SPCNST(0, SP_EMAX + 1, 0x000000), /* + infinity */
SPCNST(1, SP_EMAX + 1, 0x000000), /* - infinity */
SPCNST(0, SP_EMAX + 1, 0x3FFFFF), /* + indef quiet Nan */
SPCNST(0, SP_EMAX + 1, 0x3FFFFF), /* + indef legacy quiet NaN */
SPCNST(0, SP_EMAX + 1, 0x400000), /* + indef 2008 quiet NaN */
SPCNST(0, SP_EMAX, 0x7FFFFF), /* + max normal */
SPCNST(1, SP_EMAX, 0x7FFFFF), /* - max normal */
SPCNST(0, SP_EMIN, 0x000000), /* + min normal */
......
......@@ -221,15 +221,16 @@ union ieee754dp ieee754dp_dump(char *s, union ieee754dp x);
#define IEEE754_SPCVAL_NTEN 5 /* -10.0 */
#define IEEE754_SPCVAL_PINFINITY 6 /* +inf */
#define IEEE754_SPCVAL_NINFINITY 7 /* -inf */
#define IEEE754_SPCVAL_INDEF 8 /* quiet NaN */
#define IEEE754_SPCVAL_PMAX 9 /* +max norm */
#define IEEE754_SPCVAL_NMAX 10 /* -max norm */
#define IEEE754_SPCVAL_PMIN 11 /* +min norm */
#define IEEE754_SPCVAL_NMIN 12 /* -min norm */
#define IEEE754_SPCVAL_PMIND 13 /* +min denorm */
#define IEEE754_SPCVAL_NMIND 14 /* -min denorm */
#define IEEE754_SPCVAL_P1E31 15 /* + 1.0e31 */
#define IEEE754_SPCVAL_P1E63 16 /* + 1.0e63 */
#define IEEE754_SPCVAL_INDEF_LEG 8 /* legacy quiet NaN */
#define IEEE754_SPCVAL_INDEF_2008 9 /* IEEE 754-2008 quiet NaN */
#define IEEE754_SPCVAL_PMAX 10 /* +max norm */
#define IEEE754_SPCVAL_NMAX 11 /* -max norm */
#define IEEE754_SPCVAL_PMIN 12 /* +min norm */
#define IEEE754_SPCVAL_NMIN 13 /* -min norm */
#define IEEE754_SPCVAL_PMIND 14 /* +min denorm */
#define IEEE754_SPCVAL_NMIND 15 /* -min denorm */
#define IEEE754_SPCVAL_P1E31 16 /* + 1.0e31 */
#define IEEE754_SPCVAL_P1E63 17 /* + 1.0e63 */
extern const union ieee754dp __ieee754dp_spcvals[];
extern const union ieee754sp __ieee754sp_spcvals[];
......@@ -243,7 +244,8 @@ extern const union ieee754sp __ieee754sp_spcvals[];
#define ieee754dp_zero(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
#define ieee754dp_one(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
#define ieee754dp_ten(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
#define ieee754dp_indef() (ieee754dp_spcvals[IEEE754_SPCVAL_INDEF])
#define ieee754dp_indef() (ieee754dp_spcvals[IEEE754_SPCVAL_INDEF_LEG + \
ieee754_csr.nan2008])
#define ieee754dp_max(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
#define ieee754dp_min(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
#define ieee754dp_mind(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
......@@ -254,7 +256,8 @@ extern const union ieee754sp __ieee754sp_spcvals[];
#define ieee754sp_zero(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
#define ieee754sp_one(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
#define ieee754sp_ten(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
#define ieee754sp_indef() (ieee754sp_spcvals[IEEE754_SPCVAL_INDEF])
#define ieee754sp_indef() (ieee754sp_spcvals[IEEE754_SPCVAL_INDEF_LEG + \
ieee754_csr.nan2008])
#define ieee754sp_max(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
#define ieee754sp_min(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
#define ieee754sp_mind(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
......@@ -266,12 +269,25 @@ extern const union ieee754sp __ieee754sp_spcvals[];
*/
static inline int ieee754si_indef(void)
{
return INT_MAX;
return ieee754_csr.nan2008 ? 0 : INT_MAX;
}
static inline s64 ieee754di_indef(void)
{
return S64_MAX;
return ieee754_csr.nan2008 ? 0 : S64_MAX;
}
/*
* Overflow integer value
*/
static inline int ieee754si_overflow(int xs)
{
return ieee754_csr.nan2008 && xs ? INT_MIN : INT_MAX;
}
static inline s64 ieee754di_overflow(int xs)
{
return ieee754_csr.nan2008 && xs ? S64_MIN : S64_MAX;
}
/* result types for xctx.rt */
......
......@@ -37,8 +37,11 @@ static inline int ieee754dp_isnan(union ieee754dp x)
static inline int ieee754dp_issnan(union ieee754dp x)
{
int qbit;
assert(ieee754dp_isnan(x));
return (DPMANT(x) & DP_MBIT(DP_FBITS - 1)) == DP_MBIT(DP_FBITS - 1);
qbit = (DPMANT(x) & DP_MBIT(DP_FBITS - 1)) == DP_MBIT(DP_FBITS - 1);
return ieee754_csr.nan2008 ^ qbit;
}
......@@ -51,7 +54,12 @@ union ieee754dp __cold ieee754dp_nanxcpt(union ieee754dp r)
assert(ieee754dp_issnan(r));
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754dp_indef();
if (ieee754_csr.nan2008)
DPMANT(r) |= DP_MBIT(DP_FBITS - 1);
else
r = ieee754dp_indef();
return r;
}
static u64 ieee754dp_get_rounding(int sn, u64 xm)
......
......@@ -63,10 +63,10 @@ static inline int ieee754_class_nan(int xc)
if (ve == SP_EMAX+1+SP_EBIAS) { \
if (vm == 0) \
vc = IEEE754_CLASS_INF; \
else if (vm & SP_MBIT(SP_FBITS-1)) \
vc = IEEE754_CLASS_SNAN; \
else \
else if (ieee754_csr.nan2008 ^ !(vm & SP_MBIT(SP_FBITS - 1))) \
vc = IEEE754_CLASS_QNAN; \
else \
vc = IEEE754_CLASS_SNAN; \
} else if (ve == SP_EMIN-1+SP_EBIAS) { \
if (vm) { \
ve = SP_EMIN; \
......@@ -97,10 +97,10 @@ static inline int ieee754_class_nan(int xc)
if (ve == DP_EMAX+1+DP_EBIAS) { \
if (vm == 0) \
vc = IEEE754_CLASS_INF; \
else if (vm & DP_MBIT(DP_FBITS-1)) \
vc = IEEE754_CLASS_SNAN; \
else \
else if (ieee754_csr.nan2008 ^ !(vm & DP_MBIT(DP_FBITS - 1))) \
vc = IEEE754_CLASS_QNAN; \
else \
vc = IEEE754_CLASS_SNAN; \
} else if (ve == DP_EMIN-1+DP_EBIAS) { \
if (vm) { \
ve = DP_EMIN; \
......
......@@ -37,8 +37,11 @@ static inline int ieee754sp_isnan(union ieee754sp x)
static inline int ieee754sp_issnan(union ieee754sp x)
{
int qbit;
assert(ieee754sp_isnan(x));
return SPMANT(x) & SP_MBIT(SP_FBITS - 1);
qbit = (SPMANT(x) & SP_MBIT(SP_FBITS - 1)) == SP_MBIT(SP_FBITS - 1);
return ieee754_csr.nan2008 ^ qbit;
}
......@@ -51,7 +54,12 @@ union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r)
assert(ieee754sp_issnan(r));
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754sp_indef();
if (ieee754_csr.nan2008)
SPMANT(r) |= SP_MBIT(SP_FBITS - 1);
else
r = ieee754sp_indef();
return r;
}
static unsigned ieee754sp_get_rounding(int sn, unsigned xm)
......
......@@ -44,13 +44,16 @@ union ieee754sp ieee754sp_fdp(union ieee754dp x)
switch (xc) {
case IEEE754_CLASS_SNAN:
return ieee754sp_nanxcpt(ieee754sp_nan_fdp(xs, xm));
x = ieee754dp_nanxcpt(x);
EXPLODEXDP;
/* Fall through. */
case IEEE754_CLASS_QNAN:
y = ieee754sp_nan_fdp(xs, xm);
if (!ieee754_csr.nan2008) {
EXPLODEYSP;
if (!ieee754_class_nan(yc))
y = ieee754sp_indef();
}
return y;
case IEEE754_CLASS_INF:
......
......@@ -23,21 +23,32 @@
union ieee754sp ieee754sp_neg(union ieee754sp x)
{
unsigned int oldrm;
union ieee754sp y;
if (ieee754_csr.abs2008) {
y = x;
SPSIGN(y) = !SPSIGN(x);
} else {
unsigned int oldrm;
oldrm = ieee754_csr.rm;
ieee754_csr.rm = FPU_CSR_RD;
y = ieee754sp_sub(ieee754sp_zero(0), x);
ieee754_csr.rm = oldrm;
}
return y;
}
union ieee754sp ieee754sp_abs(union ieee754sp x)
{
unsigned int oldrm;
union ieee754sp y;
if (ieee754_csr.abs2008) {
y = x;
SPSIGN(y) = 0;
} else {
unsigned int oldrm;
oldrm = ieee754_csr.rm;
ieee754_csr.rm = FPU_CSR_RD;
if (SPSIGN(x))
......@@ -45,5 +56,6 @@ union ieee754sp ieee754sp_abs(union ieee754sp x)
else
y = ieee754sp_add(ieee754sp_zero(0), x);
ieee754_csr.rm = oldrm;
}
return y;
}
......@@ -38,10 +38,13 @@ int ieee754sp_tint(union ieee754sp x)
switch (xc) {
case IEEE754_CLASS_SNAN:
case IEEE754_CLASS_QNAN:
case IEEE754_CLASS_INF:
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754si_indef();
case IEEE754_CLASS_INF:
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754si_overflow(xs);
case IEEE754_CLASS_ZERO:
return 0;
......@@ -56,7 +59,7 @@ int ieee754sp_tint(union ieee754sp x)
/* Set invalid. We will only use overflow for floating
point overflow */
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754si_indef();
return ieee754si_overflow(xs);
}
/* oh gawd */
if (xe > SP_FBITS) {
......@@ -97,7 +100,7 @@ int ieee754sp_tint(union ieee754sp x)
if ((xm >> 31) != 0) {
/* This can happen after rounding */
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754si_indef();
return ieee754si_overflow(xs);
}
if (round || sticky)
ieee754_setcx(IEEE754_INEXACT);
......
......@@ -39,10 +39,13 @@ s64 ieee754sp_tlong(union ieee754sp x)
switch (xc) {
case IEEE754_CLASS_SNAN:
case IEEE754_CLASS_QNAN:
case IEEE754_CLASS_INF:
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754di_indef();
case IEEE754_CLASS_INF:
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754di_overflow(xs);
case IEEE754_CLASS_ZERO:
return 0;
......@@ -57,7 +60,7 @@ s64 ieee754sp_tlong(union ieee754sp x)
/* Set invalid. We will only use overflow for floating
point overflow */
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754di_indef();
return ieee754di_overflow(xs);
}
/* oh gawd */
if (xe > SP_FBITS) {
......@@ -94,7 +97,7 @@ s64 ieee754sp_tlong(union ieee754sp x)
if ((xm >> 63) != 0) {
/* This can happen after rounding */
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754di_indef();
return ieee754di_overflow(xs);
}
if (round || sticky)
ieee754_setcx(IEEE754_INEXACT);
......
......@@ -241,7 +241,7 @@ static void output_pgtable_bits_defines(void)
#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
pr_define("_PAGE_HUGE_SHIFT %d\n", _PAGE_HUGE_SHIFT);
#endif
#ifdef CONFIG_CPU_MIPSR2
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
if (cpu_has_rixi) {
#ifdef _PAGE_NO_EXEC_SHIFT
pr_define("_PAGE_NO_EXEC_SHIFT %d\n", _PAGE_NO_EXEC_SHIFT);
......
......@@ -43,6 +43,7 @@ obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o
obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o
obj-$(CONFIG_LANTIQ) += fixup-lantiq.o
obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o
obj-$(CONFIG_SOC_MT7620) += pci-mt7620.o
obj-$(CONFIG_SOC_RT288X) += pci-rt2880.o
obj-$(CONFIG_SOC_RT3883) += pci-rt3883.o
obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
......
/*
* Ralink MT7620A SoC PCI support
*
* Copyright (C) 2007-2013 Bruce Chang (Mediatek)
* Copyright (C) 2013-2016 John Crispin <blogic@openwrt.org>
*
* 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.
*/
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/io.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_pci.h>
#include <linux/reset.h>
#include <linux/platform_device.h>
#include <asm/mach-ralink/ralink_regs.h>
#include <asm/mach-ralink/mt7620.h>
#define RALINK_PCI_IO_MAP_BASE 0x10160000
#define RALINK_PCI_MEMORY_BASE 0x0
#define RALINK_INT_PCIE0 4
#define RALINK_CLKCFG1 0x30
#define RALINK_GPIOMODE 0x60
#define PPLL_CFG1 0x9c
#define PDRV_SW_SET BIT(23)
#define PPLL_DRV 0xa0
#define PDRV_SW_SET (1<<31)
#define LC_CKDRVPD (1<<19)
#define LC_CKDRVOHZ (1<<18)
#define LC_CKDRVHZ (1<<17)
#define LC_CKTEST (1<<16)
/* PCI Bridge registers */
#define RALINK_PCI_PCICFG_ADDR 0x00
#define PCIRST BIT(1)
#define RALINK_PCI_PCIENA 0x0C
#define PCIINT2 BIT(20)
#define RALINK_PCI_CONFIG_ADDR 0x20
#define RALINK_PCI_CONFIG_DATA_VIRT_REG 0x24
#define RALINK_PCI_MEMBASE 0x28
#define RALINK_PCI_IOBASE 0x2C
/* PCI RC registers */
#define RALINK_PCI0_BAR0SETUP_ADDR 0x10
#define RALINK_PCI0_IMBASEBAR0_ADDR 0x18
#define RALINK_PCI0_ID 0x30
#define RALINK_PCI0_CLASS 0x34
#define RALINK_PCI0_SUBID 0x38
#define RALINK_PCI0_STATUS 0x50
#define PCIE_LINK_UP_ST BIT(0)
#define PCIEPHY0_CFG 0x90
#define RALINK_PCIEPHY_P0_CTL_OFFSET 0x7498
#define RALINK_PCIE0_CLK_EN (1 << 26)
#define BUSY 0x80000000
#define WAITRETRY_MAX 10
#define WRITE_MODE (1UL << 23)
#define DATA_SHIFT 0
#define ADDR_SHIFT 8
static void __iomem *bridge_base;
static void __iomem *pcie_base;
static struct reset_control *rstpcie0;
static inline void bridge_w32(u32 val, unsigned reg)
{
iowrite32(val, bridge_base + reg);
}
static inline u32 bridge_r32(unsigned reg)
{
return ioread32(bridge_base + reg);
}
static inline void pcie_w32(u32 val, unsigned reg)
{
iowrite32(val, pcie_base + reg);
}
static inline u32 pcie_r32(unsigned reg)
{
return ioread32(pcie_base + reg);
}
static inline void pcie_m32(u32 clr, u32 set, unsigned reg)
{
u32 val = pcie_r32(reg);
val &= ~clr;
val |= set;
pcie_w32(val, reg);
}
static int wait_pciephy_busy(void)
{
unsigned long reg_value = 0x0, retry = 0;
while (1) {
reg_value = pcie_r32(PCIEPHY0_CFG);
if (reg_value & BUSY)
mdelay(100);
else
break;
if (retry++ > WAITRETRY_MAX) {
printk(KERN_WARN "PCIE-PHY retry failed.\n");
return -1;
}
}
return 0;
}
static void pcie_phy(unsigned long addr, unsigned long val)
{
wait_pciephy_busy();
pcie_w32(WRITE_MODE | (val << DATA_SHIFT) | (addr << ADDR_SHIFT),
PCIEPHY0_CFG);
mdelay(1);
wait_pciephy_busy();
}
static int pci_config_read(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *val)
{
unsigned int slot = PCI_SLOT(devfn);
u8 func = PCI_FUNC(devfn);
u32 address;
u32 data;
u32 num = 0;
if (bus)
num = bus->number;
address = (((where & 0xF00) >> 8) << 24) | (num << 16) | (slot << 11) |
(func << 8) | (where & 0xfc) | 0x80000000;
bridge_w32(address, RALINK_PCI_CONFIG_ADDR);
data = bridge_r32(RALINK_PCI_CONFIG_DATA_VIRT_REG);
switch (size) {
case 1:
*val = (data >> ((where & 3) << 3)) & 0xff;
break;
case 2:
*val = (data >> ((where & 3) << 3)) & 0xffff;
break;
case 4:
*val = data;
break;
}
return PCIBIOS_SUCCESSFUL;
}
static int pci_config_write(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 val)
{
unsigned int slot = PCI_SLOT(devfn);
u8 func = PCI_FUNC(devfn);
u32 address;
u32 data;
u32 num = 0;
if (bus)
num = bus->number;
address = (((where & 0xF00) >> 8) << 24) | (num << 16) | (slot << 11) |
(func << 8) | (where & 0xfc) | 0x80000000;
bridge_w32(address, RALINK_PCI_CONFIG_ADDR);
data = bridge_r32(RALINK_PCI_CONFIG_DATA_VIRT_REG);
switch (size) {
case 1:
data = (data & ~(0xff << ((where & 3) << 3))) |
(val << ((where & 3) << 3));
break;
case 2:
data = (data & ~(0xffff << ((where & 3) << 3))) |
(val << ((where & 3) << 3));
break;
case 4:
data = val;
break;
}
bridge_w32(data, RALINK_PCI_CONFIG_DATA_VIRT_REG);
return PCIBIOS_SUCCESSFUL;
}
struct pci_ops mt7620_pci_ops = {
.read = pci_config_read,
.write = pci_config_write,
};
static struct resource mt7620_res_pci_mem1;
static struct resource mt7620_res_pci_io1;
struct pci_controller mt7620_controller = {
.pci_ops = &mt7620_pci_ops,
.mem_resource = &mt7620_res_pci_mem1,
.mem_offset = 0x00000000UL,
.io_resource = &mt7620_res_pci_io1,
.io_offset = 0x00000000UL,
.io_map_base = 0xa0000000,
};
static int mt7620_pci_hw_init(struct platform_device *pdev)
{
/* bypass PCIe DLL */
pcie_phy(0x0, 0x80);
pcie_phy(0x1, 0x04);
/* Elastic buffer control */
pcie_phy(0x68, 0xB4);
/* put core into reset */
pcie_m32(0, PCIRST, RALINK_PCI_PCICFG_ADDR);
reset_control_assert(rstpcie0);
/* disable power and all clocks */
rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1);
rt_sysc_m32(LC_CKDRVPD, PDRV_SW_SET, PPLL_DRV);
/* bring core out of reset */
reset_control_deassert(rstpcie0);
rt_sysc_m32(0, RALINK_PCIE0_CLK_EN, RALINK_CLKCFG1);
mdelay(100);
if (!(rt_sysc_r32(PPLL_CFG1) & PDRV_SW_SET)) {
dev_err(&pdev->dev, "MT7620 PPLL unlock\n");
reset_control_assert(rstpcie0);
rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1);
return -1;
}
/* power up the bus */
rt_sysc_m32(LC_CKDRVHZ | LC_CKDRVOHZ, LC_CKDRVPD | PDRV_SW_SET,
PPLL_DRV);
return 0;
}
static int mt7628_pci_hw_init(struct platform_device *pdev)
{
u32 val = 0;
/* bring the core out of reset */
rt_sysc_m32(BIT(16), 0, RALINK_GPIOMODE);
reset_control_deassert(rstpcie0);
/* enable the pci clk */
rt_sysc_m32(0, RALINK_PCIE0_CLK_EN, RALINK_CLKCFG1);
mdelay(100);
/* voodoo from the SDK driver */
pcie_m32(~0xff, 0x5, RALINK_PCIEPHY_P0_CTL_OFFSET);
pci_config_read(NULL, 0, 0x70c, 4, &val);
val &= ~(0xff) << 8;
val |= 0x50 << 8;
pci_config_write(NULL, 0, 0x70c, 4, val);
pci_config_read(NULL, 0, 0x70c, 4, &val);
dev_err(&pdev->dev, "Port 0 N_FTS = %x\n", (unsigned int) val);
return 0;
}
static int mt7620_pci_probe(struct platform_device *pdev)
{
struct resource *bridge_res = platform_get_resource(pdev,
IORESOURCE_MEM, 0);
struct resource *pcie_res = platform_get_resource(pdev,
IORESOURCE_MEM, 1);
u32 val = 0;
rstpcie0 = devm_reset_control_get(&pdev->dev, "pcie0");
if (IS_ERR(rstpcie0))
return PTR_ERR(rstpcie0);
bridge_base = devm_ioremap_resource(&pdev->dev, bridge_res);
if (!bridge_base)
return -ENOMEM;
pcie_base = devm_ioremap_resource(&pdev->dev, pcie_res);
if (!pcie_base)
return -ENOMEM;
iomem_resource.start = 0;
iomem_resource.end = ~0;
ioport_resource.start = 0;
ioport_resource.end = ~0;
/* bring up the pci core */
switch (ralink_soc) {
case MT762X_SOC_MT7620A:
if (mt7620_pci_hw_init(pdev))
return -1;
break;
case MT762X_SOC_MT7628AN:
if (mt7628_pci_hw_init(pdev))
return -1;
break;
default:
dev_err(&pdev->dev, "pcie is not supported on this hardware\n");
return -1;
}
mdelay(50);
/* enable write access */
pcie_m32(PCIRST, 0, RALINK_PCI_PCICFG_ADDR);
mdelay(100);
/* check if there is a card present */
if ((pcie_r32(RALINK_PCI0_STATUS) & PCIE_LINK_UP_ST) == 0) {
reset_control_assert(rstpcie0);
rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1);
if (ralink_soc == MT762X_SOC_MT7620A)
rt_sysc_m32(LC_CKDRVPD, PDRV_SW_SET, PPLL_DRV);
dev_err(&pdev->dev, "PCIE0 no card, disable it(RST&CLK)\n");
return -1;
}
/* setup ranges */
bridge_w32(0xffffffff, RALINK_PCI_MEMBASE);
bridge_w32(RALINK_PCI_IO_MAP_BASE, RALINK_PCI_IOBASE);
pcie_w32(0x7FFF0001, RALINK_PCI0_BAR0SETUP_ADDR);
pcie_w32(RALINK_PCI_MEMORY_BASE, RALINK_PCI0_IMBASEBAR0_ADDR);
pcie_w32(0x06040001, RALINK_PCI0_CLASS);
/* enable interrupts */
pcie_m32(0, PCIINT2, RALINK_PCI_PCIENA);
/* voodoo from the SDK driver */
pci_config_read(NULL, 0, 4, 4, &val);
pci_config_write(NULL, 0, 4, 4, val | 0x7);
pci_load_of_ranges(&mt7620_controller, pdev->dev.of_node);
register_pci_controller(&mt7620_controller);
return 0;
}
int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
u16 cmd;
u32 val;
int irq = 0;
if ((dev->bus->number == 0) && (slot == 0)) {
pcie_w32(0x7FFF0001, RALINK_PCI0_BAR0SETUP_ADDR);
pci_config_write(dev->bus, 0, PCI_BASE_ADDRESS_0, 4,
RALINK_PCI_MEMORY_BASE);
pci_config_read(dev->bus, 0, PCI_BASE_ADDRESS_0, 4, &val);
} else if ((dev->bus->number == 1) && (slot == 0x0)) {
irq = RALINK_INT_PCIE0;
} else {
dev_err(&dev->dev, "no irq found - bus=0x%x, slot = 0x%x\n",
dev->bus->number, slot);
return 0;
}
dev_err(&dev->dev, "card - bus=0x%x, slot = 0x%x irq=%d\n",
dev->bus->number, slot, irq);
/* configure the cache line size to 0x14 */
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x14);
/* configure latency timer to 0xff */
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xff);
pci_read_config_word(dev, PCI_COMMAND, &cmd);
/* setup the slot */
cmd = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
pci_write_config_word(dev, PCI_COMMAND, cmd);
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
return irq;
}
int pcibios_plat_dev_init(struct pci_dev *dev)
{
return 0;
}
static const struct of_device_id mt7620_pci_ids[] = {
{ .compatible = "mediatek,mt7620-pci" },
{},
};
MODULE_DEVICE_TABLE(of, mt7620_pci_ids);
static struct platform_driver mt7620_pci_driver = {
.probe = mt7620_pci_probe,
.driver = {
.name = "mt7620-pci",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(mt7620_pci_ids),
},
};
static int __init mt7620_pci_init(void)
{
return platform_driver_register(&mt7620_pci_driver);
}
arch_initcall(mt7620_pci_init);
if MACH_PIC32
choice
prompt "Machine Type"
config PIC32MZDA
bool "Microchip PIC32MZDA Platform"
select BOOT_ELF32
select BOOT_RAW
select CEVT_R4K
select CSRC_R4K
select DMA_NONCOHERENT
select SYS_HAS_CPU_MIPS32_R2
select SYS_HAS_EARLY_PRINTK
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
select ARCH_REQUIRE_GPIOLIB
select HAVE_MACH_CLKDEV
select COMMON_CLK
select CLKDEV_LOOKUP
select LIBFDT
select USE_OF
select PINCTRL
select PIC32_EVIC
help
Support for the Microchip PIC32MZDA microcontroller.
This is a 32-bit microcontroller with support for external or
internally packaged DDR2 memory up to 128MB.
For more information, see <http://www.microchip.com/>.
endchoice
choice
prompt "Devicetree selection"
default DTB_PIC32_NONE
help
Select the devicetree.
config DTB_PIC32_NONE
bool "None"
config DTB_PIC32_MZDA_SK
bool "PIC32MZDA Starter Kit"
depends on PIC32MZDA
select BUILTIN_DTB
endchoice
endif # MACH_PIC32
#
# Joshua Henderson, <joshua.henderson@microchip.com>
# Copyright (C) 2015 Microchip Technology, Inc. All rights reserved.
#
obj-$(CONFIG_MACH_PIC32) += common/
obj-$(CONFIG_PIC32MZDA) += pic32mzda/
#
# PIC32MZDA
#
platform-$(CONFIG_PIC32MZDA) += pic32/
cflags-$(CONFIG_PIC32MZDA) += -I$(srctree)/arch/mips/include/asm/mach-pic32
load-$(CONFIG_PIC32MZDA) += 0xffffffff88000000
all-$(CONFIG_PIC32MZDA) := $(COMPRESSION_FNAME).bin
#
# Joshua Henderson, <joshua.henderson@microchip.com>
# Copyright (C) 2015 Microchip Technology, Inc. All rights reserved.
#
obj-y = reset.o irq.o
/*
* Joshua Henderson <joshua.henderson@microchip.com>
* Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
*
* This program is free software; you can distribute 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 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.
*/
#include <linux/init.h>
#include <linux/irqchip.h>
#include <asm/irq.h>
void __init arch_init_irq(void)
{
irqchip_init();
}
/*
* Joshua Henderson <joshua.henderson@microchip.com>
* Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
*
* This program is free software; you can distribute 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 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.
*/
#include <linux/init.h>
#include <linux/pm.h>
#include <asm/reboot.h>
#include <asm/mach-pic32/pic32.h>
#define PIC32_RSWRST 0x10
static void pic32_halt(void)
{
while (1) {
__asm__(".set push;\n"
".set arch=r4000;\n"
"wait;\n"
".set pop;\n"
);
}
}
static void pic32_machine_restart(char *command)
{
void __iomem *reg =
ioremap(PIC32_BASE_RESET + PIC32_RSWRST, sizeof(u32));
pic32_syskey_unlock();
/* magic write/read */
__raw_writel(1, reg);
(void)__raw_readl(reg);
pic32_halt();
}
static void pic32_machine_halt(void)
{
local_irq_disable();
pic32_halt();
}
static int __init mips_reboot_setup(void)
{
_machine_restart = pic32_machine_restart;
_machine_halt = pic32_machine_halt;
pm_power_off = pic32_machine_halt;
return 0;
}
arch_initcall(mips_reboot_setup);
#
# Joshua Henderson, <joshua.henderson@microchip.com>
# Copyright (C) 2015 Microchip Technology, Inc. All rights reserved.
#
obj-y := init.o time.o config.o
obj-$(CONFIG_EARLY_PRINTK) += early_console.o \
early_pin.o \
early_clk.o
/*
* Purna Chandra Mandal, purna.mandal@microchip.com
* Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
*
* This program is free software; you can distribute 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 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.
*/
#include <linux/init.h>
#include <linux/io.h>
#include <linux/of_platform.h>
#include <asm/mach-pic32/pic32.h>
#include "pic32mzda.h"
#define PIC32_CFGCON 0x0000
#define PIC32_DEVID 0x0020
#define PIC32_SYSKEY 0x0030
#define PIC32_CFGEBIA 0x00c0
#define PIC32_CFGEBIC 0x00d0
#define PIC32_CFGCON2 0x00f0
#define PIC32_RCON 0x1240
static void __iomem *pic32_conf_base;
static DEFINE_SPINLOCK(config_lock);
static u32 pic32_reset_status;
static u32 pic32_conf_get_reg_field(u32 offset, u32 rshift, u32 mask)
{
u32 v;
v = readl(pic32_conf_base + offset);
v >>= rshift;
v &= mask;
return v;
}
static u32 pic32_conf_modify_atomic(u32 offset, u32 mask, u32 set)
{
u32 v;
unsigned long flags;
spin_lock_irqsave(&config_lock, flags);
v = readl(pic32_conf_base + offset);
v &= ~mask;
v |= (set & mask);
writel(v, pic32_conf_base + offset);
spin_unlock_irqrestore(&config_lock, flags);
return 0;
}
int pic32_enable_lcd(void)
{
return pic32_conf_modify_atomic(PIC32_CFGCON2, BIT(31), BIT(31));
}
int pic32_disable_lcd(void)
{
return pic32_conf_modify_atomic(PIC32_CFGCON2, BIT(31), 0);
}
int pic32_set_lcd_mode(int mode)
{
u32 mask = mode ? BIT(30) : 0;
return pic32_conf_modify_atomic(PIC32_CFGCON2, BIT(30), mask);
}
int pic32_set_sdhci_adma_fifo_threshold(u32 rthrsh, u32 wthrsh)
{
u32 clr, set;
clr = (0x3ff << 4) | (0x3ff << 16);
set = (rthrsh << 4) | (wthrsh << 16);
return pic32_conf_modify_atomic(PIC32_CFGCON2, clr, set);
}
void pic32_syskey_unlock_debug(const char *func, const ulong line)
{
void __iomem *syskey = pic32_conf_base + PIC32_SYSKEY;
pr_debug("%s: called from %s:%lu\n", __func__, func, line);
writel(0x00000000, syskey);
writel(0xAA996655, syskey);
writel(0x556699AA, syskey);
}
static u32 pic32_get_device_id(void)
{
return pic32_conf_get_reg_field(PIC32_DEVID, 0, 0x0fffffff);
}
static u32 pic32_get_device_version(void)
{
return pic32_conf_get_reg_field(PIC32_DEVID, 28, 0xf);
}
u32 pic32_get_boot_status(void)
{
return pic32_reset_status;
}
EXPORT_SYMBOL(pic32_get_boot_status);
void __init pic32_config_init(void)
{
pic32_conf_base = ioremap(PIC32_BASE_CONFIG, 0x110);
if (!pic32_conf_base)
panic("pic32: config base not mapped");
/* Boot Status */
pic32_reset_status = readl(pic32_conf_base + PIC32_RCON);
writel(-1, PIC32_CLR(pic32_conf_base + PIC32_RCON));
/* Device Inforation */
pr_info("Device Id: 0x%08x, Device Ver: 0x%04x\n",
pic32_get_device_id(),
pic32_get_device_version());
}
/*
* Joshua Henderson <joshua.henderson@microchip.com>
* Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
*
* This program is free software; you can distribute 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 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.
*/
#include <asm/mach-pic32/pic32.h>
#include "pic32mzda.h"
/* Oscillators, PLL & clocks */
#define ICLK_MASK 0x00000080
#define PLLDIV_MASK 0x00000007
#define CUROSC_MASK 0x00000007
#define PLLMUL_MASK 0x0000007F
#define PB_MASK 0x00000007
#define FRC1 0
#define FRC2 7
#define SPLL 1
#define POSC 2
#define FRC_CLK 8000000
#define PIC32_POSC_FREQ 24000000
#define OSCCON 0x0000
#define SPLLCON 0x0020
#define PB1DIV 0x0140
u32 pic32_get_sysclk(void)
{
u32 osc_freq = 0;
u32 pllclk;
u32 frcdivn;
u32 osccon;
u32 spllcon;
int curr_osc;
u32 plliclk;
u32 pllidiv;
u32 pllodiv;
u32 pllmult;
u32 frcdiv;
void __iomem *osc_base = ioremap(PIC32_BASE_OSC, 0x200);
osccon = __raw_readl(osc_base + OSCCON);
spllcon = __raw_readl(osc_base + SPLLCON);
plliclk = (spllcon & ICLK_MASK);
pllidiv = ((spllcon >> 8) & PLLDIV_MASK) + 1;
pllodiv = ((spllcon >> 24) & PLLDIV_MASK);
pllmult = ((spllcon >> 16) & PLLMUL_MASK) + 1;
frcdiv = ((osccon >> 24) & PLLDIV_MASK);
pllclk = plliclk ? FRC_CLK : PIC32_POSC_FREQ;
frcdivn = ((1 << frcdiv) + 1) + (128 * (frcdiv == 7));
if (pllodiv < 2)
pllodiv = 2;
else if (pllodiv < 5)
pllodiv = (1 << pllodiv);
else
pllodiv = 32;
curr_osc = (int)((osccon >> 12) & CUROSC_MASK);
switch (curr_osc) {
case FRC1:
case FRC2:
osc_freq = FRC_CLK / frcdivn;
break;
case SPLL:
osc_freq = ((pllclk / pllidiv) * pllmult) / pllodiv;
break;
case POSC:
osc_freq = PIC32_POSC_FREQ;
break;
default:
break;
}
iounmap(osc_base);
return osc_freq;
}
u32 pic32_get_pbclk(int bus)
{
u32 clk_freq;
void __iomem *osc_base = ioremap(PIC32_BASE_OSC, 0x200);
u32 pbxdiv = PB1DIV + ((bus - 1) * 0x10);
u32 pbdiv = (__raw_readl(osc_base + pbxdiv) & PB_MASK) + 1;
iounmap(osc_base);
clk_freq = pic32_get_sysclk();
return clk_freq / pbdiv;
}
/*
* Joshua Henderson <joshua.henderson@microchip.com>
* Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
*
* This program is free software; you can distribute 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 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.
*/
#include <asm/mach-pic32/pic32.h>
#include <asm/fw/fw.h>
#include "pic32mzda.h"
#include "early_pin.h"
/* Default early console parameters */
#define EARLY_CONSOLE_PORT 1
#define EARLY_CONSOLE_BAUDRATE 115200
#define UART_ENABLE BIT(15)
#define UART_ENABLE_RX BIT(12)
#define UART_ENABLE_TX BIT(10)
#define UART_TX_FULL BIT(9)
/* UART1(x == 0) - UART6(x == 5) */
#define UART_BASE(x) ((x) * 0x0200)
#define U_MODE(x) UART_BASE(x)
#define U_STA(x) (UART_BASE(x) + 0x10)
#define U_TXR(x) (UART_BASE(x) + 0x20)
#define U_BRG(x) (UART_BASE(x) + 0x40)
static void __iomem *uart_base;
static char console_port = -1;
static int __init configure_uart_pins(int port)
{
switch (port) {
case 1:
pic32_pps_input(IN_FUNC_U2RX, IN_RPB0);
pic32_pps_output(OUT_FUNC_U2TX, OUT_RPG9);
break;
case 5:
pic32_pps_input(IN_FUNC_U6RX, IN_RPD0);
pic32_pps_output(OUT_FUNC_U6TX, OUT_RPB8);
break;
default:
return -1;
}
return 0;
}
static void __init configure_uart(char port, int baud)
{
u32 pbclk;
pbclk = pic32_get_pbclk(2);
__raw_writel(0, uart_base + U_MODE(port));
__raw_writel(((pbclk / baud) / 16) - 1, uart_base + U_BRG(port));
__raw_writel(UART_ENABLE, uart_base + U_MODE(port));
__raw_writel(UART_ENABLE_TX | UART_ENABLE_RX,
uart_base + PIC32_SET(U_STA(port)));
}
static void __init setup_early_console(char port, int baud)
{
if (configure_uart_pins(port))
return;
console_port = port;
configure_uart(console_port, baud);
}
static char * __init pic32_getcmdline(void)
{
/*
* arch_mem_init() has not been called yet, so we don't have a real
* command line setup if using CONFIG_CMDLINE_BOOL.
*/
#ifdef CONFIG_CMDLINE_OVERRIDE
return CONFIG_CMDLINE;
#else
return fw_getcmdline();
#endif
}
static int __init get_port_from_cmdline(char *arch_cmdline)
{
char *s;
int port = -1;
if (!arch_cmdline || *arch_cmdline == '\0')
goto _out;
s = strstr(arch_cmdline, "earlyprintk=");
if (s) {
s = strstr(s, "ttyS");
if (s)
s += 4;
else
goto _out;
port = (*s) - '0';
}
_out:
return port;
}
static int __init get_baud_from_cmdline(char *arch_cmdline)
{
char *s;
int baud = -1;
if (!arch_cmdline || *arch_cmdline == '\0')
goto _out;
s = strstr(arch_cmdline, "earlyprintk=");
if (s) {
s = strstr(s, "ttyS");
if (s)
s += 6;
else
goto _out;
baud = 0;
while (*s >= '0' && *s <= '9')
baud = baud * 10 + *s++ - '0';
}
_out:
return baud;
}
void __init fw_init_early_console(char port)
{
char *arch_cmdline = pic32_getcmdline();
int baud = -1;
uart_base = ioremap_nocache(PIC32_BASE_UART, 0xc00);
baud = get_baud_from_cmdline(arch_cmdline);
if (port == -1)
port = get_port_from_cmdline(arch_cmdline);
if (port == -1)
port = EARLY_CONSOLE_PORT;
if (baud == -1)
baud = EARLY_CONSOLE_BAUDRATE;
setup_early_console(port, baud);
}
int prom_putchar(char c)
{
if (console_port >= 0) {
while (__raw_readl(
uart_base + U_STA(console_port)) & UART_TX_FULL)
;
__raw_writel(c, uart_base + U_TXR(console_port));
}
return 1;
}
/*
* Joshua Henderson <joshua.henderson@microchip.com>
* Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
*
* This program is free software; you can distribute 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 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.
*/
#include <asm/io.h>
#include "early_pin.h"
#define PPS_BASE 0x1f800000
/* Input PPS Registers */
#define INT1R 0x1404
#define INT2R 0x1408
#define INT3R 0x140C
#define INT4R 0x1410
#define T2CKR 0x1418
#define T3CKR 0x141C
#define T4CKR 0x1420
#define T5CKR 0x1424
#define T6CKR 0x1428
#define T7CKR 0x142C
#define T8CKR 0x1430
#define T9CKR 0x1434
#define IC1R 0x1438
#define IC2R 0x143C
#define IC3R 0x1440
#define IC4R 0x1444
#define IC5R 0x1448
#define IC6R 0x144C
#define IC7R 0x1450
#define IC8R 0x1454
#define IC9R 0x1458
#define OCFAR 0x1460
#define U1RXR 0x1468
#define U1CTSR 0x146C
#define U2RXR 0x1470
#define U2CTSR 0x1474
#define U3RXR 0x1478
#define U3CTSR 0x147C
#define U4RXR 0x1480
#define U4CTSR 0x1484
#define U5RXR 0x1488
#define U5CTSR 0x148C
#define U6RXR 0x1490
#define U6CTSR 0x1494
#define SDI1R 0x149C
#define SS1R 0x14A0
#define SDI2R 0x14A8
#define SS2R 0x14AC
#define SDI3R 0x14B4
#define SS3R 0x14B8
#define SDI4R 0x14C0
#define SS4R 0x14C4
#define SDI5R 0x14CC
#define SS5R 0x14D0
#define SDI6R 0x14D8
#define SS6R 0x14DC
#define C1RXR 0x14E0
#define C2RXR 0x14E4
#define REFCLKI1R 0x14E8
#define REFCLKI3R 0x14F0
#define REFCLKI4R 0x14F4
static const struct
{
int function;
int reg;
} input_pin_reg[] = {
{ IN_FUNC_INT3, INT3R },
{ IN_FUNC_T2CK, T2CKR },
{ IN_FUNC_T6CK, T6CKR },
{ IN_FUNC_IC3, IC3R },
{ IN_FUNC_IC7, IC7R },
{ IN_FUNC_U1RX, U1RXR },
{ IN_FUNC_U2CTS, U2CTSR },
{ IN_FUNC_U5RX, U5RXR },
{ IN_FUNC_U6CTS, U6CTSR },
{ IN_FUNC_SDI1, SDI1R },
{ IN_FUNC_SDI3, SDI3R },
{ IN_FUNC_SDI5, SDI5R },
{ IN_FUNC_SS6, SS6R },
{ IN_FUNC_REFCLKI1, REFCLKI1R },
{ IN_FUNC_INT4, INT4R },
{ IN_FUNC_T5CK, T5CKR },
{ IN_FUNC_T7CK, T7CKR },
{ IN_FUNC_IC4, IC4R },
{ IN_FUNC_IC8, IC8R },
{ IN_FUNC_U3RX, U3RXR },
{ IN_FUNC_U4CTS, U4CTSR },
{ IN_FUNC_SDI2, SDI2R },
{ IN_FUNC_SDI4, SDI4R },
{ IN_FUNC_C1RX, C1RXR },
{ IN_FUNC_REFCLKI4, REFCLKI4R },
{ IN_FUNC_INT2, INT2R },
{ IN_FUNC_T3CK, T3CKR },
{ IN_FUNC_T8CK, T8CKR },
{ IN_FUNC_IC2, IC2R },
{ IN_FUNC_IC5, IC5R },
{ IN_FUNC_IC9, IC9R },
{ IN_FUNC_U1CTS, U1CTSR },
{ IN_FUNC_U2RX, U2RXR },
{ IN_FUNC_U5CTS, U5CTSR },
{ IN_FUNC_SS1, SS1R },
{ IN_FUNC_SS3, SS3R },
{ IN_FUNC_SS4, SS4R },
{ IN_FUNC_SS5, SS5R },
{ IN_FUNC_C2RX, C2RXR },
{ IN_FUNC_INT1, INT1R },
{ IN_FUNC_T4CK, T4CKR },
{ IN_FUNC_T9CK, T9CKR },
{ IN_FUNC_IC1, IC1R },
{ IN_FUNC_IC6, IC6R },
{ IN_FUNC_U3CTS, U3CTSR },
{ IN_FUNC_U4RX, U4RXR },
{ IN_FUNC_U6RX, U6RXR },
{ IN_FUNC_SS2, SS2R },
{ IN_FUNC_SDI6, SDI6R },
{ IN_FUNC_OCFA, OCFAR },
{ IN_FUNC_REFCLKI3, REFCLKI3R },
};
void pic32_pps_input(int function, int pin)
{
void __iomem *pps_base = ioremap_nocache(PPS_BASE, 0xF4);
int i;
for (i = 0; i < ARRAY_SIZE(input_pin_reg); i++) {
if (input_pin_reg[i].function == function) {
__raw_writel(pin, pps_base + input_pin_reg[i].reg);
return;
}
}
iounmap(pps_base);
}
/* Output PPS Registers */
#define RPA14R 0x1538
#define RPA15R 0x153C
#define RPB0R 0x1540
#define RPB1R 0x1544
#define RPB2R 0x1548
#define RPB3R 0x154C
#define RPB5R 0x1554
#define RPB6R 0x1558
#define RPB7R 0x155C
#define RPB8R 0x1560
#define RPB9R 0x1564
#define RPB10R 0x1568
#define RPB14R 0x1578
#define RPB15R 0x157C
#define RPC1R 0x1584
#define RPC2R 0x1588
#define RPC3R 0x158C
#define RPC4R 0x1590
#define RPC13R 0x15B4
#define RPC14R 0x15B8
#define RPD0R 0x15C0
#define RPD1R 0x15C4
#define RPD2R 0x15C8
#define RPD3R 0x15CC
#define RPD4R 0x15D0
#define RPD5R 0x15D4
#define RPD6R 0x15D8
#define RPD7R 0x15DC
#define RPD9R 0x15E4
#define RPD10R 0x15E8
#define RPD11R 0x15EC
#define RPD12R 0x15F0
#define RPD14R 0x15F8
#define RPD15R 0x15FC
#define RPE3R 0x160C
#define RPE5R 0x1614
#define RPE8R 0x1620
#define RPE9R 0x1624
#define RPF0R 0x1640
#define RPF1R 0x1644
#define RPF2R 0x1648
#define RPF3R 0x164C
#define RPF4R 0x1650
#define RPF5R 0x1654
#define RPF8R 0x1660
#define RPF12R 0x1670
#define RPF13R 0x1674
#define RPG0R 0x1680
#define RPG1R 0x1684
#define RPG6R 0x1698
#define RPG7R 0x169C
#define RPG8R 0x16A0
#define RPG9R 0x16A4
static const struct
{
int pin;
int reg;
} output_pin_reg[] = {
{ OUT_RPD2, RPD2R },
{ OUT_RPG8, RPG8R },
{ OUT_RPF4, RPF4R },
{ OUT_RPD10, RPD10R },
{ OUT_RPF1, RPF1R },
{ OUT_RPB9, RPB9R },
{ OUT_RPB10, RPB10R },
{ OUT_RPC14, RPC14R },
{ OUT_RPB5, RPB5R },
{ OUT_RPC1, RPC1R },
{ OUT_RPD14, RPD14R },
{ OUT_RPG1, RPG1R },
{ OUT_RPA14, RPA14R },
{ OUT_RPD6, RPD6R },
{ OUT_RPD3, RPD3R },
{ OUT_RPG7, RPG7R },
{ OUT_RPF5, RPF5R },
{ OUT_RPD11, RPD11R },
{ OUT_RPF0, RPF0R },
{ OUT_RPB1, RPB1R },
{ OUT_RPE5, RPE5R },
{ OUT_RPC13, RPC13R },
{ OUT_RPB3, RPB3R },
{ OUT_RPC4, RPC4R },
{ OUT_RPD15, RPD15R },
{ OUT_RPG0, RPG0R },
{ OUT_RPA15, RPA15R },
{ OUT_RPD7, RPD7R },
{ OUT_RPD9, RPD9R },
{ OUT_RPG6, RPG6R },
{ OUT_RPB8, RPB8R },
{ OUT_RPB15, RPB15R },
{ OUT_RPD4, RPD4R },
{ OUT_RPB0, RPB0R },
{ OUT_RPE3, RPE3R },
{ OUT_RPB7, RPB7R },
{ OUT_RPF12, RPF12R },
{ OUT_RPD12, RPD12R },
{ OUT_RPF8, RPF8R },
{ OUT_RPC3, RPC3R },
{ OUT_RPE9, RPE9R },
{ OUT_RPD1, RPD1R },
{ OUT_RPG9, RPG9R },
{ OUT_RPB14, RPB14R },
{ OUT_RPD0, RPD0R },
{ OUT_RPB6, RPB6R },
{ OUT_RPD5, RPD5R },
{ OUT_RPB2, RPB2R },
{ OUT_RPF3, RPF3R },
{ OUT_RPF13, RPF13R },
{ OUT_RPC2, RPC2R },
{ OUT_RPE8, RPE8R },
{ OUT_RPF2, RPF2R },
};
void pic32_pps_output(int function, int pin)
{
void __iomem *pps_base = ioremap_nocache(PPS_BASE, 0x170);
int i;
for (i = 0; i < ARRAY_SIZE(output_pin_reg); i++) {
if (output_pin_reg[i].pin == pin) {
__raw_writel(function,
pps_base + output_pin_reg[i].reg);
return;
}
}
iounmap(pps_base);
}
/*
* Joshua Henderson <joshua.henderson@microchip.com>
* Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
*
* This program is free software; you can distribute 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 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 _PIC32MZDA_EARLY_PIN_H
#define _PIC32MZDA_EARLY_PIN_H
/*
* This is a complete, yet overly simplistic and unoptimized, PIC32MZDA PPS
* configuration only useful before we have full pinctrl initialized.
*/
/* Input PPS Functions */
enum {
IN_FUNC_INT3,
IN_FUNC_T2CK,
IN_FUNC_T6CK,
IN_FUNC_IC3,
IN_FUNC_IC7,
IN_FUNC_U1RX,
IN_FUNC_U2CTS,
IN_FUNC_U5RX,
IN_FUNC_U6CTS,
IN_FUNC_SDI1,
IN_FUNC_SDI3,
IN_FUNC_SDI5,
IN_FUNC_SS6,
IN_FUNC_REFCLKI1,
IN_FUNC_INT4,
IN_FUNC_T5CK,
IN_FUNC_T7CK,
IN_FUNC_IC4,
IN_FUNC_IC8,
IN_FUNC_U3RX,
IN_FUNC_U4CTS,
IN_FUNC_SDI2,
IN_FUNC_SDI4,
IN_FUNC_C1RX,
IN_FUNC_REFCLKI4,
IN_FUNC_INT2,
IN_FUNC_T3CK,
IN_FUNC_T8CK,
IN_FUNC_IC2,
IN_FUNC_IC5,
IN_FUNC_IC9,
IN_FUNC_U1CTS,
IN_FUNC_U2RX,
IN_FUNC_U5CTS,
IN_FUNC_SS1,
IN_FUNC_SS3,
IN_FUNC_SS4,
IN_FUNC_SS5,
IN_FUNC_C2RX,
IN_FUNC_INT1,
IN_FUNC_T4CK,
IN_FUNC_T9CK,
IN_FUNC_IC1,
IN_FUNC_IC6,
IN_FUNC_U3CTS,
IN_FUNC_U4RX,
IN_FUNC_U6RX,
IN_FUNC_SS2,
IN_FUNC_SDI6,
IN_FUNC_OCFA,
IN_FUNC_REFCLKI3,
};
/* Input PPS Pins */
#define IN_RPD2 0x00
#define IN_RPG8 0x01
#define IN_RPF4 0x02
#define IN_RPD10 0x03
#define IN_RPF1 0x04
#define IN_RPB9 0x05
#define IN_RPB10 0x06
#define IN_RPC14 0x07
#define IN_RPB5 0x08
#define IN_RPC1 0x0A
#define IN_RPD14 0x0B
#define IN_RPG1 0x0C
#define IN_RPA14 0x0D
#define IN_RPD6 0x0E
#define IN_RPD3 0x00
#define IN_RPG7 0x01
#define IN_RPF5 0x02
#define IN_RPD11 0x03
#define IN_RPF0 0x04
#define IN_RPB1 0x05
#define IN_RPE5 0x06
#define IN_RPC13 0x07
#define IN_RPB3 0x08
#define IN_RPC4 0x0A
#define IN_RPD15 0x0B
#define IN_RPG0 0x0C
#define IN_RPA15 0x0D
#define IN_RPD7 0x0E
#define IN_RPD9 0x00
#define IN_RPG6 0x01
#define IN_RPB8 0x02
#define IN_RPB15 0x03
#define IN_RPD4 0x04
#define IN_RPB0 0x05
#define IN_RPE3 0x06
#define IN_RPB7 0x07
#define IN_RPF12 0x09
#define IN_RPD12 0x0A
#define IN_RPF8 0x0B
#define IN_RPC3 0x0C
#define IN_RPE9 0x0D
#define IN_RPD1 0x00
#define IN_RPG9 0x01
#define IN_RPB14 0x02
#define IN_RPD0 0x03
#define IN_RPB6 0x05
#define IN_RPD5 0x06
#define IN_RPB2 0x07
#define IN_RPF3 0x08
#define IN_RPF13 0x09
#define IN_RPF2 0x0B
#define IN_RPC2 0x0C
#define IN_RPE8 0x0D
/* Output PPS Pins */
enum {
OUT_RPD2,
OUT_RPG8,
OUT_RPF4,
OUT_RPD10,
OUT_RPF1,
OUT_RPB9,
OUT_RPB10,
OUT_RPC14,
OUT_RPB5,
OUT_RPC1,
OUT_RPD14,
OUT_RPG1,
OUT_RPA14,
OUT_RPD6,
OUT_RPD3,
OUT_RPG7,
OUT_RPF5,
OUT_RPD11,
OUT_RPF0,
OUT_RPB1,
OUT_RPE5,
OUT_RPC13,
OUT_RPB3,
OUT_RPC4,
OUT_RPD15,
OUT_RPG0,
OUT_RPA15,
OUT_RPD7,
OUT_RPD9,
OUT_RPG6,
OUT_RPB8,
OUT_RPB15,
OUT_RPD4,
OUT_RPB0,
OUT_RPE3,
OUT_RPB7,
OUT_RPF12,
OUT_RPD12,
OUT_RPF8,
OUT_RPC3,
OUT_RPE9,
OUT_RPD1,
OUT_RPG9,
OUT_RPB14,
OUT_RPD0,
OUT_RPB6,
OUT_RPD5,
OUT_RPB2,
OUT_RPF3,
OUT_RPF13,
OUT_RPC2,
OUT_RPE8,
OUT_RPF2,
};
/* Output PPS Functions */
#define OUT_FUNC_U3TX 0x01
#define OUT_FUNC_U4RTS 0x02
#define OUT_FUNC_SDO1 0x05
#define OUT_FUNC_SDO2 0x06
#define OUT_FUNC_SDO3 0x07
#define OUT_FUNC_SDO5 0x09
#define OUT_FUNC_SS6 0x0A
#define OUT_FUNC_OC3 0x0B
#define OUT_FUNC_OC6 0x0C
#define OUT_FUNC_REFCLKO4 0x0D
#define OUT_FUNC_C2OUT 0x0E
#define OUT_FUNC_C1TX 0x0F
#define OUT_FUNC_U1TX 0x01
#define OUT_FUNC_U2RTS 0x02
#define OUT_FUNC_U5TX 0x03
#define OUT_FUNC_U6RTS 0x04
#define OUT_FUNC_SDO1 0x05
#define OUT_FUNC_SDO2 0x06
#define OUT_FUNC_SDO3 0x07
#define OUT_FUNC_SDO4 0x08
#define OUT_FUNC_SDO5 0x09
#define OUT_FUNC_OC4 0x0B
#define OUT_FUNC_OC7 0x0C
#define OUT_FUNC_REFCLKO1 0x0F
#define OUT_FUNC_U3RTS 0x01
#define OUT_FUNC_U4TX 0x02
#define OUT_FUNC_U6TX 0x04
#define OUT_FUNC_SS1 0x05
#define OUT_FUNC_SS3 0x07
#define OUT_FUNC_SS4 0x08
#define OUT_FUNC_SS5 0x09
#define OUT_FUNC_SDO6 0x0A
#define OUT_FUNC_OC5 0x0B
#define OUT_FUNC_OC8 0x0C
#define OUT_FUNC_C1OUT 0x0E
#define OUT_FUNC_REFCLKO3 0x0F
#define OUT_FUNC_U1RTS 0x01
#define OUT_FUNC_U2TX 0x02
#define OUT_FUNC_U5RTS 0x03
#define OUT_FUNC_U6TX 0x04
#define OUT_FUNC_SS2 0x06
#define OUT_FUNC_SDO4 0x08
#define OUT_FUNC_SDO6 0x0A
#define OUT_FUNC_OC2 0x0B
#define OUT_FUNC_OC1 0x0C
#define OUT_FUNC_OC9 0x0D
#define OUT_FUNC_C2TX 0x0F
void pic32_pps_input(int function, int pin);
void pic32_pps_output(int function, int pin);
#endif
/*
* Joshua Henderson, joshua.henderson@microchip.com
* Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
*
* This program is free software; you can distribute 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 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.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/of_address.h>
#include <linux/of_fdt.h>
#include <linux/of_platform.h>
#include <linux/platform_data/sdhci-pic32.h>
#include <asm/fw/fw.h>
#include <asm/mips-boards/generic.h>
#include <asm/prom.h>
#include "pic32mzda.h"
const char *get_system_type(void)
{
return "PIC32MZDA";
}
static ulong get_fdtaddr(void)
{
ulong ftaddr = 0;
if ((fw_arg0 == -2) && fw_arg1 && !fw_arg2 && !fw_arg3)
return (ulong)fw_arg1;
if (__dtb_start < __dtb_end)
ftaddr = (ulong)__dtb_start;
return ftaddr;
}
void __init plat_mem_setup(void)
{
void *dtb;
dtb = (void *)get_fdtaddr();
if (!dtb) {
pr_err("pic32: no DTB found.\n");
return;
}
/*
* Load the builtin device tree. This causes the chosen node to be
* parsed resulting in our memory appearing.
*/
__dt_setup_arch(dtb);
pr_info("Found following command lines\n");
pr_info(" boot_command_line: %s\n", boot_command_line);
pr_info(" arcs_cmdline : %s\n", arcs_cmdline);
#ifdef CONFIG_CMDLINE_BOOL
pr_info(" builtin_cmdline : %s\n", CONFIG_CMDLINE);
#endif
if (dtb != __dtb_start)
strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE);
#ifdef CONFIG_EARLY_PRINTK
fw_init_early_console(-1);
#endif
pic32_config_init();
}
static __init void pic32_init_cmdline(int argc, char *argv[])
{
unsigned int count = COMMAND_LINE_SIZE - 1;
int i;
char *dst = &(arcs_cmdline[0]);
char *src;
for (i = 1; i < argc && count; ++i) {
src = argv[i];
while (*src && count) {
*dst++ = *src++;
--count;
}
*dst++ = ' ';
}
if (i > 1)
--dst;
*dst = 0;
}
void __init prom_init(void)
{
pic32_init_cmdline((int)fw_arg0, (char **)fw_arg1);
}
void __init prom_free_prom_memory(void)
{
}
void __init device_tree_init(void)
{
if (!initial_boot_params)
return;
unflatten_and_copy_device_tree();
}
static struct pic32_sdhci_platform_data sdhci_data = {
.setup_dma = pic32_set_sdhci_adma_fifo_threshold,
};
static struct of_dev_auxdata pic32_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("microchip,pic32mzda-sdhci", 0, "sdhci", &sdhci_data),
{ /* sentinel */}
};
static int __init pic32_of_prepare_platform_data(struct of_dev_auxdata *lookup)
{
struct device_node *root, *np;
struct resource res;
root = of_find_node_by_path("/");
for (; lookup->compatible; lookup++) {
np = of_find_compatible_node(NULL, NULL, lookup->compatible);
if (np) {
lookup->name = (char *)np->name;
if (lookup->phys_addr)
continue;
if (!of_address_to_resource(np, 0, &res))
lookup->phys_addr = res.start;
}
}
return 0;
}
static int __init plat_of_setup(void)
{
if (!of_have_populated_dt())
panic("Device tree not present");
pic32_of_prepare_platform_data(pic32_auxdata_lookup);
if (of_platform_populate(NULL, of_default_bus_match_table,
pic32_auxdata_lookup, NULL))
panic("Failed to populate DT");
return 0;
}
arch_initcall(plat_of_setup);
/*
* Joshua Henderson <joshua.henderson@microchip.com>
* Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
*
* This program is free software; you can distribute 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 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 PIC32MZDA_COMMON_H
#define PIC32MZDA_COMMON_H
/* early clock */
u32 pic32_get_pbclk(int bus);
u32 pic32_get_sysclk(void);
/* Device configuration */
void __init pic32_config_init(void);
int pic32_set_lcd_mode(int mode);
int pic32_set_sdhci_adma_fifo_threshold(u32 rthrs, u32 wthrs);
u32 pic32_get_boot_status(void);
int pic32_disable_lcd(void);
int pic32_enable_lcd(void);
#endif
/*
* Joshua Henderson <joshua.henderson@microchip.com>
* Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
*
* This program is free software; you can distribute 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 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.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clocksource.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/irqdomain.h>
#include <asm/time.h>
#include "pic32mzda.h"
static const struct of_device_id pic32_infra_match[] = {
{ .compatible = "microchip,pic32mzda-infra", },
{ },
};
#define DEFAULT_CORE_TIMER_INTERRUPT 0
static unsigned int pic32_xlate_core_timer_irq(void)
{
static struct device_node *node;
unsigned int irq;
node = of_find_matching_node(NULL, pic32_infra_match);
if (WARN_ON(!node))
goto default_map;
irq = irq_of_parse_and_map(node, 0);
if (!irq)
goto default_map;
return irq;
default_map:
return irq_create_mapping(NULL, DEFAULT_CORE_TIMER_INTERRUPT);
}
unsigned int get_c0_compare_int(void)
{
return pic32_xlate_core_timer_irq();
}
void __init plat_time_init(void)
{
struct clk *clk;
of_clk_init(NULL);
clk = clk_get_sys("cpu_clk", NULL);
if (IS_ERR(clk))
panic("unable to get CPU clock, err=%ld", PTR_ERR(clk));
clk_prepare_enable(clk);
pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
mips_hpt_frequency = clk_get_rate(clk) / 2;
clocksource_probe();
}
......@@ -12,6 +12,11 @@ config RALINK_ILL_ACC
depends on SOC_RT305X
default y
config IRQ_INTC
bool
default y
depends on !SOC_MT7621
choice
prompt "Ralink SoC selection"
default SOC_RT305X
......@@ -33,7 +38,18 @@ choice
config SOC_MT7620
bool "MT7620/8"
select HW_HAS_PCI
config SOC_MT7621
bool "MT7621"
select MIPS_CPU_SCACHE
select SYS_SUPPORTS_MULTITHREADING
select SYS_SUPPORTS_SMP
select SYS_SUPPORTS_MIPS_CPS
select MIPS_GIC
select COMMON_CLK
select CLKSRC_MIPS_GIC
select HW_HAS_PCI
endchoice
choice
......
......@@ -6,16 +6,24 @@
# Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
# Copyright (C) 2013 John Crispin <blogic@openwrt.org>
obj-y := prom.o of.o reset.o clk.o irq.o timer.o
obj-y := prom.o of.o reset.o
ifndef CONFIG_MIPS_GIC
obj-y += clk.o timer.o
endif
obj-$(CONFIG_CLKEVT_RT3352) += cevt-rt3352.o
obj-$(CONFIG_RALINK_ILL_ACC) += ill_acc.o
obj-$(CONFIG_IRQ_INTC) += irq.o
obj-$(CONFIG_MIPS_GIC) += irq-gic.o timer-gic.o
obj-$(CONFIG_SOC_RT288X) += rt288x.o
obj-$(CONFIG_SOC_RT305X) += rt305x.o
obj-$(CONFIG_SOC_RT3883) += rt3883.o
obj-$(CONFIG_SOC_MT7620) += mt7620.o
obj-$(CONFIG_SOC_MT7621) += mt7621.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
......
......@@ -27,3 +27,8 @@ cflags-$(CONFIG_SOC_RT3883) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt
#
load-$(CONFIG_SOC_MT7620) += 0xffffffff80000000
cflags-$(CONFIG_SOC_MT7620) += -I$(srctree)/arch/mips/include/asm/mach-ralink/mt7620
# Ralink MT7621
#
load-$(CONFIG_SOC_MT7621) += 0xffffffff80001000
cflags-$(CONFIG_SOC_MT7621) += -I$(srctree)/arch/mips/include/asm/mach-ralink/mt7621
/*
* 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.
*
* Copyright (C) 2015 Nikolay Martynov <mar.kolya@gmail.com>
* Copyright (C) 2015 John Crispin <blogic@openwrt.org>
*/
#include <linux/init.h>
#include <linux/of.h>
#include <linux/irqchip.h>
#include <linux/irqchip/mips-gic.h>
int get_c0_perfcount_int(void)
{
return gic_get_c0_perfcount_int();
}
EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
void __init arch_init_irq(void)
{
irqchip_init();
}
......@@ -107,31 +107,31 @@ static struct rt2880_pmx_group mt7620a_pinmux_data[] = {
};
static struct rt2880_pmx_func pwm1_grp_mt7628[] = {
FUNC("sdcx", 3, 19, 1),
FUNC("sdxc d6", 3, 19, 1),
FUNC("utif", 2, 19, 1),
FUNC("gpio", 1, 19, 1),
FUNC("pwm", 0, 19, 1),
FUNC("pwm1", 0, 19, 1),
};
static struct rt2880_pmx_func pwm0_grp_mt7628[] = {
FUNC("sdcx", 3, 18, 1),
FUNC("sdxc d7", 3, 18, 1),
FUNC("utif", 2, 18, 1),
FUNC("gpio", 1, 18, 1),
FUNC("pwm", 0, 18, 1),
FUNC("pwm0", 0, 18, 1),
};
static struct rt2880_pmx_func uart2_grp_mt7628[] = {
FUNC("sdcx", 3, 20, 2),
FUNC("sdxc d5 d4", 3, 20, 2),
FUNC("pwm", 2, 20, 2),
FUNC("gpio", 1, 20, 2),
FUNC("uart", 0, 20, 2),
FUNC("uart2", 0, 20, 2),
};
static struct rt2880_pmx_func uart1_grp_mt7628[] = {
FUNC("sdcx", 3, 45, 2),
FUNC("sw_r", 3, 45, 2),
FUNC("pwm", 2, 45, 2),
FUNC("gpio", 1, 45, 2),
FUNC("uart", 0, 45, 2),
FUNC("uart1", 0, 45, 2),
};
static struct rt2880_pmx_func i2c_grp_mt7628[] = {
......@@ -143,21 +143,21 @@ static struct rt2880_pmx_func i2c_grp_mt7628[] = {
static struct rt2880_pmx_func refclk_grp_mt7628[] = { FUNC("reclk", 0, 36, 1) };
static struct rt2880_pmx_func perst_grp_mt7628[] = { FUNC("perst", 0, 37, 1) };
static struct rt2880_pmx_func wdt_grp_mt7628[] = { FUNC("wdt", 0, 15, 38) };
static struct rt2880_pmx_func wdt_grp_mt7628[] = { FUNC("wdt", 0, 38, 1) };
static struct rt2880_pmx_func spi_grp_mt7628[] = { FUNC("spi", 0, 7, 4) };
static struct rt2880_pmx_func sd_mode_grp_mt7628[] = {
FUNC("jtag", 3, 22, 8),
FUNC("utif", 2, 22, 8),
FUNC("gpio", 1, 22, 8),
FUNC("sdcx", 0, 22, 8),
FUNC("sdxc", 0, 22, 8),
};
static struct rt2880_pmx_func uart0_grp_mt7628[] = {
FUNC("-", 3, 12, 2),
FUNC("-", 2, 12, 2),
FUNC("gpio", 1, 12, 2),
FUNC("uart", 0, 12, 2),
FUNC("uart0", 0, 12, 2),
};
static struct rt2880_pmx_func i2s_grp_mt7628[] = {
......@@ -171,7 +171,7 @@ static struct rt2880_pmx_func spi_cs1_grp_mt7628[] = {
FUNC("-", 3, 6, 1),
FUNC("refclk", 2, 6, 1),
FUNC("gpio", 1, 6, 1),
FUNC("spi", 0, 6, 1),
FUNC("spi cs1", 0, 6, 1),
};
static struct rt2880_pmx_func spis_grp_mt7628[] = {
......@@ -188,8 +188,24 @@ static struct rt2880_pmx_func gpio_grp_mt7628[] = {
FUNC("gpio", 0, 11, 1),
};
static struct rt2880_pmx_func wled_kn_grp_mt7628[] = {
FUNC("rsvd", 3, 35, 1),
FUNC("rsvd", 2, 35, 1),
FUNC("gpio", 1, 35, 1),
FUNC("wled_kn", 0, 35, 1),
};
static struct rt2880_pmx_func wled_an_grp_mt7628[] = {
FUNC("rsvd", 3, 35, 1),
FUNC("rsvd", 2, 35, 1),
FUNC("gpio", 1, 35, 1),
FUNC("wled_an", 0, 35, 1),
};
#define MT7628_GPIO_MODE_MASK 0x3
#define MT7628_GPIO_MODE_WLED_KN 48
#define MT7628_GPIO_MODE_WLED_AN 32
#define MT7628_GPIO_MODE_PWM1 30
#define MT7628_GPIO_MODE_PWM0 28
#define MT7628_GPIO_MODE_UART2 26
......@@ -209,7 +225,7 @@ static struct rt2880_pmx_func gpio_grp_mt7628[] = {
static struct rt2880_pmx_group mt7628an_pinmux_data[] = {
GRP_G("pmw1", pwm1_grp_mt7628, MT7628_GPIO_MODE_MASK,
1, MT7628_GPIO_MODE_PWM1),
GRP_G("pmw1", pwm0_grp_mt7628, MT7628_GPIO_MODE_MASK,
GRP_G("pmw0", pwm0_grp_mt7628, MT7628_GPIO_MODE_MASK,
1, MT7628_GPIO_MODE_PWM0),
GRP_G("uart2", uart2_grp_mt7628, MT7628_GPIO_MODE_MASK,
1, MT7628_GPIO_MODE_UART2),
......@@ -233,6 +249,10 @@ static struct rt2880_pmx_group mt7628an_pinmux_data[] = {
1, MT7628_GPIO_MODE_SPIS),
GRP_G("gpio", gpio_grp_mt7628, MT7628_GPIO_MODE_MASK,
1, MT7628_GPIO_MODE_GPIO),
GRP_G("wled_an", wled_an_grp_mt7628, MT7628_GPIO_MODE_MASK,
1, MT7628_GPIO_MODE_WLED_AN),
GRP_G("wled_kn", wled_kn_grp_mt7628, MT7628_GPIO_MODE_MASK,
1, MT7628_GPIO_MODE_WLED_KN),
{ 0 }
};
......@@ -436,10 +456,13 @@ void __init ralink_clk_init(void)
ralink_clk_add("10000100.timer", periph_rate);
ralink_clk_add("10000120.watchdog", periph_rate);
ralink_clk_add("10000b00.spi", sys_rate);
ralink_clk_add("10000b40.spi", sys_rate);
ralink_clk_add("10000c00.uartlite", periph_rate);
ralink_clk_add("10000d00.uart1", periph_rate);
ralink_clk_add("10000e00.uart2", periph_rate);
ralink_clk_add("10180000.wmac", xtal_rate);
if (IS_ENABLED(CONFIG_USB) && is_mt76x8()) {
if (IS_ENABLED(CONFIG_USB) && !is_mt76x8()) {
/*
* When the CPU goes into sleep mode, the BUS clock will be
* too low for USB to function properly. Adjust the busses
......@@ -552,7 +575,7 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
}
snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN,
"Ralink %s ver:%u eco:%u",
"MediaTek %s ver:%u eco:%u",
name,
(rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK,
(rev & CHIP_REV_ECO_MASK));
......
/*
* 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.
*
* Copyright (C) 2015 Nikolay Martynov <mar.kolya@gmail.com>
* Copyright (C) 2015 John Crispin <blogic@openwrt.org>
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <asm/mipsregs.h>
#include <asm/smp-ops.h>
#include <asm/mips-cm.h>
#include <asm/mips-cpc.h>
#include <asm/mach-ralink/ralink_regs.h>
#include <asm/mach-ralink/mt7621.h>
#include <pinmux.h>
#include "common.h"
#define SYSC_REG_SYSCFG 0x10
#define SYSC_REG_CPLL_CLKCFG0 0x2c
#define SYSC_REG_CUR_CLK_STS 0x44
#define CPU_CLK_SEL (BIT(30) | BIT(31))
#define MT7621_GPIO_MODE_UART1 1
#define MT7621_GPIO_MODE_I2C 2
#define MT7621_GPIO_MODE_UART3_MASK 0x3
#define MT7621_GPIO_MODE_UART3_SHIFT 3
#define MT7621_GPIO_MODE_UART3_GPIO 1
#define MT7621_GPIO_MODE_UART2_MASK 0x3
#define MT7621_GPIO_MODE_UART2_SHIFT 5
#define MT7621_GPIO_MODE_UART2_GPIO 1
#define MT7621_GPIO_MODE_JTAG 7
#define MT7621_GPIO_MODE_WDT_MASK 0x3
#define MT7621_GPIO_MODE_WDT_SHIFT 8
#define MT7621_GPIO_MODE_WDT_GPIO 1
#define MT7621_GPIO_MODE_PCIE_RST 0
#define MT7621_GPIO_MODE_PCIE_REF 2
#define MT7621_GPIO_MODE_PCIE_MASK 0x3
#define MT7621_GPIO_MODE_PCIE_SHIFT 10
#define MT7621_GPIO_MODE_PCIE_GPIO 1
#define MT7621_GPIO_MODE_MDIO_MASK 0x3
#define MT7621_GPIO_MODE_MDIO_SHIFT 12
#define MT7621_GPIO_MODE_MDIO_GPIO 1
#define MT7621_GPIO_MODE_RGMII1 14
#define MT7621_GPIO_MODE_RGMII2 15
#define MT7621_GPIO_MODE_SPI_MASK 0x3
#define MT7621_GPIO_MODE_SPI_SHIFT 16
#define MT7621_GPIO_MODE_SPI_GPIO 1
#define MT7621_GPIO_MODE_SDHCI_MASK 0x3
#define MT7621_GPIO_MODE_SDHCI_SHIFT 18
#define MT7621_GPIO_MODE_SDHCI_GPIO 1
static struct rt2880_pmx_func uart1_grp[] = { FUNC("uart1", 0, 1, 2) };
static struct rt2880_pmx_func i2c_grp[] = { FUNC("i2c", 0, 3, 2) };
static struct rt2880_pmx_func uart3_grp[] = {
FUNC("uart3", 0, 5, 4),
FUNC("i2s", 2, 5, 4),
FUNC("spdif3", 3, 5, 4),
};
static struct rt2880_pmx_func uart2_grp[] = {
FUNC("uart2", 0, 9, 4),
FUNC("pcm", 2, 9, 4),
FUNC("spdif2", 3, 9, 4),
};
static struct rt2880_pmx_func jtag_grp[] = { FUNC("jtag", 0, 13, 5) };
static struct rt2880_pmx_func wdt_grp[] = {
FUNC("wdt rst", 0, 18, 1),
FUNC("wdt refclk", 2, 18, 1),
};
static struct rt2880_pmx_func pcie_rst_grp[] = {
FUNC("pcie rst", MT7621_GPIO_MODE_PCIE_RST, 19, 1),
FUNC("pcie refclk", MT7621_GPIO_MODE_PCIE_REF, 19, 1)
};
static struct rt2880_pmx_func mdio_grp[] = { FUNC("mdio", 0, 20, 2) };
static struct rt2880_pmx_func rgmii2_grp[] = { FUNC("rgmii2", 0, 22, 12) };
static struct rt2880_pmx_func spi_grp[] = {
FUNC("spi", 0, 34, 7),
FUNC("nand1", 2, 34, 7),
};
static struct rt2880_pmx_func sdhci_grp[] = {
FUNC("sdhci", 0, 41, 8),
FUNC("nand2", 2, 41, 8),
};
static struct rt2880_pmx_func rgmii1_grp[] = { FUNC("rgmii1", 0, 49, 12) };
static struct rt2880_pmx_group mt7621_pinmux_data[] = {
GRP("uart1", uart1_grp, 1, MT7621_GPIO_MODE_UART1),
GRP("i2c", i2c_grp, 1, MT7621_GPIO_MODE_I2C),
GRP_G("uart3", uart3_grp, MT7621_GPIO_MODE_UART3_MASK,
MT7621_GPIO_MODE_UART3_GPIO, MT7621_GPIO_MODE_UART3_SHIFT),
GRP_G("uart2", uart2_grp, MT7621_GPIO_MODE_UART2_MASK,
MT7621_GPIO_MODE_UART2_GPIO, MT7621_GPIO_MODE_UART2_SHIFT),
GRP("jtag", jtag_grp, 1, MT7621_GPIO_MODE_JTAG),
GRP_G("wdt", wdt_grp, MT7621_GPIO_MODE_WDT_MASK,
MT7621_GPIO_MODE_WDT_GPIO, MT7621_GPIO_MODE_WDT_SHIFT),
GRP_G("pcie", pcie_rst_grp, MT7621_GPIO_MODE_PCIE_MASK,
MT7621_GPIO_MODE_PCIE_GPIO, MT7621_GPIO_MODE_PCIE_SHIFT),
GRP_G("mdio", mdio_grp, MT7621_GPIO_MODE_MDIO_MASK,
MT7621_GPIO_MODE_MDIO_GPIO, MT7621_GPIO_MODE_MDIO_SHIFT),
GRP("rgmii2", rgmii2_grp, 1, MT7621_GPIO_MODE_RGMII2),
GRP_G("spi", spi_grp, MT7621_GPIO_MODE_SPI_MASK,
MT7621_GPIO_MODE_SPI_GPIO, MT7621_GPIO_MODE_SPI_SHIFT),
GRP_G("sdhci", sdhci_grp, MT7621_GPIO_MODE_SDHCI_MASK,
MT7621_GPIO_MODE_SDHCI_GPIO, MT7621_GPIO_MODE_SDHCI_SHIFT),
GRP("rgmii1", rgmii1_grp, 1, MT7621_GPIO_MODE_RGMII1),
{ 0 }
};
phys_addr_t mips_cpc_default_phys_base(void)
{
panic("Cannot detect cpc address");
}
void __init ralink_clk_init(void)
{
int cpu_fdiv = 0;
int cpu_ffrac = 0;
int fbdiv = 0;
u32 clk_sts, syscfg;
u8 clk_sel = 0, xtal_mode;
u32 cpu_clk;
if ((rt_sysc_r32(SYSC_REG_CPLL_CLKCFG0) & CPU_CLK_SEL) != 0)
clk_sel = 1;
switch (clk_sel) {
case 0:
clk_sts = rt_sysc_r32(SYSC_REG_CUR_CLK_STS);
cpu_fdiv = ((clk_sts >> 8) & 0x1F);
cpu_ffrac = (clk_sts & 0x1F);
cpu_clk = (500 * cpu_ffrac / cpu_fdiv) * 1000 * 1000;
break;
case 1:
fbdiv = ((rt_sysc_r32(0x648) >> 4) & 0x7F) + 1;
syscfg = rt_sysc_r32(SYSC_REG_SYSCFG);
xtal_mode = (syscfg >> 6) & 0x7;
if (xtal_mode >= 6) {
/* 25Mhz Xtal */
cpu_clk = 25 * fbdiv * 1000 * 1000;
} else if (xtal_mode >= 3) {
/* 40Mhz Xtal */
cpu_clk = 40 * fbdiv * 1000 * 1000;
} else {
/* 20Mhz Xtal */
cpu_clk = 20 * fbdiv * 1000 * 1000;
}
break;
}
}
void __init ralink_of_remap(void)
{
rt_sysc_membase = plat_of_remap_node("mtk,mt7621-sysc");
rt_memc_membase = plat_of_remap_node("mtk,mt7621-memc");
if (!rt_sysc_membase || !rt_memc_membase)
panic("Failed to remap core resources");
}
void prom_soc_init(struct ralink_soc_info *soc_info)
{
void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7621_SYSC_BASE);
unsigned char *name = NULL;
u32 n0;
u32 n1;
u32 rev;
n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0);
n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1);
if (n0 == MT7621_CHIP_NAME0 && n1 == MT7621_CHIP_NAME1) {
name = "MT7621";
soc_info->compatible = "mtk,mt7621-soc";
} else {
panic("mt7621: unknown SoC, n0:%08x n1:%08x\n", n0, n1);
}
rev = __raw_readl(sysc + SYSC_REG_CHIP_REV);
snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN,
"MediaTek %s ver:%u eco:%u",
name,
(rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK,
(rev & CHIP_REV_ECO_MASK));
soc_info->mem_size_min = MT7621_DDR2_SIZE_MIN;
soc_info->mem_size_max = MT7621_DDR2_SIZE_MAX;
soc_info->mem_base = MT7621_DRAM_BASE;
rt2880_pinmux_data = mt7621_pinmux_data;
/* Early detection of CMP support */
mips_cm_probe();
mips_cpc_probe();
if (mips_cm_numiocu()) {
/*
* mips_cm_probe() wipes out bootloader
* config for CM regions and we have to configure them
* again. This SoC cannot talk to pamlbus devices
* witout proper iocu region set up.
*
* FIXME: it would be better to do this with values
* from DT, but we need this very early because
* without this we cannot talk to pretty much anything
* including serial.
*/
write_gcr_reg0_base(MT7621_PALMBUS_BASE);
write_gcr_reg0_mask(~MT7621_PALMBUS_SIZE |
CM_GCR_REGn_MASK_CMTGT_IOCU0);
}
if (!register_cps_smp_ops())
return;
if (!register_cmp_smp_ops())
return;
if (!register_vsmp_smp_ops())
return;
}
......@@ -119,5 +119,5 @@ void prom_soc_init(struct ralink_soc_info *soc_info)
soc_info->mem_size_max = RT2880_MEM_SIZE_MAX;
rt2880_pinmux_data = rt2880_pinmux_data_act;
ralink_soc == RT2880_SOC;
ralink_soc = RT2880_SOC;
}
......@@ -201,6 +201,7 @@ void __init ralink_clk_init(void)
ralink_clk_add("cpu", cpu_rate);
ralink_clk_add("sys", sys_rate);
ralink_clk_add("10000b00.spi", sys_rate);
ralink_clk_add("10000b40.spi", sys_rate);
ralink_clk_add("10000100.timer", wdt_rate);
ralink_clk_add("10000120.watchdog", wdt_rate);
ralink_clk_add("10000500.uart", uart_rate);
......
......@@ -109,6 +109,7 @@ void __init ralink_clk_init(void)
ralink_clk_add("10000120.watchdog", sys_rate);
ralink_clk_add("10000500.uart", 40000000);
ralink_clk_add("10000b00.spi", sys_rate);
ralink_clk_add("10000b40.spi", sys_rate);
ralink_clk_add("10000c00.uartlite", 40000000);
ralink_clk_add("10100000.ethernet", sys_rate);
ralink_clk_add("10180000.wmac", 40000000);
......
/*
* 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.
*
* Copyright (C) 2015 Nikolay Martynov <mar.kolya@gmail.com>
* Copyright (C) 2015 John Crispin <blogic@openwrt.org>
*/
#include <linux/init.h>
#include <linux/of.h>
#include <linux/clk-provider.h>
#include <linux/clocksource.h>
#include "common.h"
void __init plat_time_init(void)
{
ralink_of_remap();
of_clk_init(NULL);
clocksource_probe();
}
......@@ -89,7 +89,7 @@ static int rb532_gpio_get(struct gpio_chip *chip, unsigned offset)
struct rb532_gpio_chip *gpch;
gpch = container_of(chip, struct rb532_gpio_chip, chip);
return rb532_get_bit(offset, gpch->regbase + GPIOD);
return !!rb532_get_bit(offset, gpch->regbase + GPIOD);
}
/*
......
......@@ -689,7 +689,7 @@ static int txx9_iocled_get(struct gpio_chip *chip, unsigned int offset)
{
struct txx9_iocled_data *data =
container_of(chip, struct txx9_iocled_data, chip);
return data->cur_val & (1 << offset);
return !!(data->cur_val & (1 << offset));
}
static void txx9_iocled_set(struct gpio_chip *chip, unsigned int offset,
......
......@@ -130,6 +130,11 @@ config ORION_IRQCHIP
select IRQ_DOMAIN
select MULTI_IRQ_HANDLER
config PIC32_EVIC
bool
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
config RENESAS_INTC_IRQPIN
bool
select IRQ_DOMAIN
......
......@@ -58,3 +58,4 @@ obj-$(CONFIG_RENESAS_H8S_INTC) += irq-renesas-h8s.o
obj-$(CONFIG_ARCH_SA1100) += irq-sa11x0.o
obj-$(CONFIG_INGENIC_IRQ) += irq-ingenic.o
obj-$(CONFIG_IMX_GPCV2) += irq-imx-gpcv2.o
obj-$(CONFIG_PIC32_EVIC) += irq-pic32-evic.o
/*
* Cristian Birsan <cristian.birsan@microchip.com>
* Joshua Henderson <joshua.henderson@microchip.com>
* Copyright (C) 2016 Microchip Technology Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/irqchip.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/traps.h>
#include <asm/mach-pic32/pic32.h>
#define REG_INTCON 0x0000
#define REG_INTSTAT 0x0020
#define REG_IFS_OFFSET 0x0040
#define REG_IEC_OFFSET 0x00C0
#define REG_IPC_OFFSET 0x0140
#define REG_OFF_OFFSET 0x0540
#define MAJPRI_MASK 0x07
#define SUBPRI_MASK 0x03
#define PRIORITY_MASK 0x1F
#define PIC32_INT_PRI(pri, subpri) \
((((pri) & MAJPRI_MASK) << 2) | ((subpri) & SUBPRI_MASK))
struct evic_chip_data {
u32 irq_types[NR_IRQS];
u32 ext_irqs[8];
};
static struct irq_domain *evic_irq_domain;
static void __iomem *evic_base;
asmlinkage void __weak plat_irq_dispatch(void)
{
unsigned int irq, hwirq;
hwirq = readl(evic_base + REG_INTSTAT) & 0xFF;
irq = irq_linear_revmap(evic_irq_domain, hwirq);
do_IRQ(irq);
}
static struct evic_chip_data *irqd_to_priv(struct irq_data *data)
{
return (struct evic_chip_data *)data->domain->host_data;
}
static int pic32_set_ext_polarity(int bit, u32 type)
{
/*
* External interrupts can be either edge rising or edge falling,
* but not both.
*/
switch (type) {
case IRQ_TYPE_EDGE_RISING:
writel(BIT(bit), evic_base + PIC32_SET(REG_INTCON));
break;
case IRQ_TYPE_EDGE_FALLING:
writel(BIT(bit), evic_base + PIC32_CLR(REG_INTCON));
break;
default:
return -EINVAL;
}
return 0;
}
static int pic32_set_type_edge(struct irq_data *data,
unsigned int flow_type)
{
struct evic_chip_data *priv = irqd_to_priv(data);
int ret;
int i;
if (!(flow_type & IRQ_TYPE_EDGE_BOTH))
return -EBADR;
/* set polarity for external interrupts only */
for (i = 0; i < ARRAY_SIZE(priv->ext_irqs); i++) {
if (priv->ext_irqs[i] == data->hwirq) {
ret = pic32_set_ext_polarity(i + 1, flow_type);
if (ret)
return ret;
}
}
irqd_set_trigger_type(data, flow_type);
return IRQ_SET_MASK_OK;
}
static void pic32_bind_evic_interrupt(int irq, int set)
{
writel(set, evic_base + REG_OFF_OFFSET + irq * 4);
}
static void pic32_set_irq_priority(int irq, int priority)
{
u32 reg, shift;
reg = irq / 4;
shift = (irq % 4) * 8;
writel(PRIORITY_MASK << shift,
evic_base + PIC32_CLR(REG_IPC_OFFSET + reg * 0x10));
writel(priority << shift,
evic_base + PIC32_SET(REG_IPC_OFFSET + reg * 0x10));
}
#define IRQ_REG_MASK(_hwirq, _reg, _mask) \
do { \
_reg = _hwirq / 32; \
_mask = 1 << (_hwirq % 32); \
} while (0)
static int pic32_irq_domain_map(struct irq_domain *d, unsigned int virq,
irq_hw_number_t hw)
{
struct evic_chip_data *priv = d->host_data;
struct irq_data *data;
int ret;
u32 iecclr, ifsclr;
u32 reg, mask;
ret = irq_map_generic_chip(d, virq, hw);
if (ret)
return ret;
/*
* Piggyback on xlate function to move to an alternate chip as necessary
* at time of mapping instead of allowing the flow handler/chip to be
* changed later. This requires all interrupts to be configured through
* DT.
*/
if (priv->irq_types[hw] & IRQ_TYPE_SENSE_MASK) {
data = irq_domain_get_irq_data(d, virq);
irqd_set_trigger_type(data, priv->irq_types[hw]);
irq_setup_alt_chip(data, priv->irq_types[hw]);
}
IRQ_REG_MASK(hw, reg, mask);
iecclr = PIC32_CLR(REG_IEC_OFFSET + reg * 0x10);
ifsclr = PIC32_CLR(REG_IFS_OFFSET + reg * 0x10);
/* mask and clear flag */
writel(mask, evic_base + iecclr);
writel(mask, evic_base + ifsclr);
/* default priority is required */
pic32_set_irq_priority(hw, PIC32_INT_PRI(2, 0));
return ret;
}
int pic32_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
const u32 *intspec, unsigned int intsize,
irq_hw_number_t *out_hwirq, unsigned int *out_type)
{
struct evic_chip_data *priv = d->host_data;
if (WARN_ON(intsize < 2))
return -EINVAL;
if (WARN_ON(intspec[0] >= NR_IRQS))
return -EINVAL;
*out_hwirq = intspec[0];
*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
priv->irq_types[intspec[0]] = intspec[1] & IRQ_TYPE_SENSE_MASK;
return 0;
}
static const struct irq_domain_ops pic32_irq_domain_ops = {
.map = pic32_irq_domain_map,
.xlate = pic32_irq_domain_xlate,
};
static void __init pic32_ext_irq_of_init(struct irq_domain *domain)
{
struct device_node *node = irq_domain_get_of_node(domain);
struct evic_chip_data *priv = domain->host_data;
struct property *prop;
const __le32 *p;
u32 hwirq;
int i = 0;
const char *pname = "microchip,external-irqs";
of_property_for_each_u32(node, pname, prop, p, hwirq) {
if (i >= ARRAY_SIZE(priv->ext_irqs)) {
pr_warn("More than %d external irq, skip rest\n",
ARRAY_SIZE(priv->ext_irqs));
break;
}
priv->ext_irqs[i] = hwirq;
i++;
}
}
static int __init pic32_of_init(struct device_node *node,
struct device_node *parent)
{
struct irq_chip_generic *gc;
struct evic_chip_data *priv;
unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
int nchips, ret;
int i;
nchips = DIV_ROUND_UP(NR_IRQS, 32);
evic_base = of_iomap(node, 0);
if (!evic_base)
return -ENOMEM;
priv = kcalloc(nchips, sizeof(*priv), GFP_KERNEL);
if (!priv) {
ret = -ENOMEM;
goto err_iounmap;
}
evic_irq_domain = irq_domain_add_linear(node, nchips * 32,
&pic32_irq_domain_ops,
priv);
if (!evic_irq_domain) {
ret = -ENOMEM;
goto err_free_priv;
}
/*
* The PIC32 EVIC has a linear list of irqs and the type of each
* irq is determined by the hardware peripheral the EVIC is arbitrating.
* These irq types are defined in the datasheet as "persistent" and
* "non-persistent" which are mapped here to level and edge
* respectively. To manage the different flow handler requirements of
* each irq type, different chip_types are used.
*/
ret = irq_alloc_domain_generic_chips(evic_irq_domain, 32, 2,
"evic-level", handle_level_irq,
clr, 0, 0);
if (ret)
goto err_domain_remove;
board_bind_eic_interrupt = &pic32_bind_evic_interrupt;
for (i = 0; i < nchips; i++) {
u32 ifsclr = PIC32_CLR(REG_IFS_OFFSET + (i * 0x10));
u32 iec = REG_IEC_OFFSET + (i * 0x10);
gc = irq_get_domain_generic_chip(evic_irq_domain, i * 32);
gc->reg_base = evic_base;
gc->unused = 0;
/*
* Level/persistent interrupts have a special requirement that
* the condition generating the interrupt be cleared before the
* interrupt flag (ifs) can be cleared. chip.irq_eoi is used to
* complete the interrupt with an ack.
*/
gc->chip_types[0].type = IRQ_TYPE_LEVEL_MASK;
gc->chip_types[0].handler = handle_fasteoi_irq;
gc->chip_types[0].regs.ack = ifsclr;
gc->chip_types[0].regs.mask = iec;
gc->chip_types[0].chip.name = "evic-level";
gc->chip_types[0].chip.irq_eoi = irq_gc_ack_set_bit;
gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
gc->chip_types[0].chip.flags = IRQCHIP_SKIP_SET_WAKE;
/* Edge interrupts */
gc->chip_types[1].type = IRQ_TYPE_EDGE_BOTH;
gc->chip_types[1].handler = handle_edge_irq;
gc->chip_types[1].regs.ack = ifsclr;
gc->chip_types[1].regs.mask = iec;
gc->chip_types[1].chip.name = "evic-edge";
gc->chip_types[1].chip.irq_ack = irq_gc_ack_set_bit;
gc->chip_types[1].chip.irq_mask = irq_gc_mask_clr_bit;
gc->chip_types[1].chip.irq_unmask = irq_gc_mask_set_bit;
gc->chip_types[1].chip.irq_set_type = pic32_set_type_edge;
gc->chip_types[1].chip.flags = IRQCHIP_SKIP_SET_WAKE;
gc->private = &priv[i];
}
irq_set_default_host(evic_irq_domain);
/*
* External interrupts have software configurable edge polarity. These
* interrupts are defined in DT allowing polarity to be configured only
* for these interrupts when requested.
*/
pic32_ext_irq_of_init(evic_irq_domain);
return 0;
err_domain_remove:
irq_domain_remove(evic_irq_domain);
err_free_priv:
kfree(priv);
err_iounmap:
iounmap(evic_base);
return ret;
}
IRQCHIP_DECLARE(pic32_evic, "microchip,pic32mzda-evic", pic32_of_init);
......@@ -24,6 +24,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/bcm963xx_tag.h>
#include <linux/crc32.h>
#include <linux/module.h>
#include <linux/kernel.h>
......@@ -34,11 +35,8 @@
#include <linux/mtd/partitions.h>
#include <asm/mach-bcm63xx/bcm63xx_nvram.h>
#include <asm/mach-bcm63xx/bcm963xx_tag.h>
#include <asm/mach-bcm63xx/board_bcm963xx.h>
#define BCM63XX_EXTENDED_SIZE 0xBFC00000 /* Extended flash address */
#define BCM63XX_CFE_BLOCK_SIZE SZ_64K /* always at least 64KiB */
#define BCM63XX_CFE_MAGIC_OFFSET 0x4e0
......@@ -123,8 +121,8 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
pr_info("CFE boot tag found with version %s and board type %s\n",
tagversion, boardid);
kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE;
rootfsaddr = rootfsaddr - BCM63XX_EXTENDED_SIZE;
kerneladdr = kerneladdr - BCM963XX_EXTENDED_SIZE;
rootfsaddr = rootfsaddr - BCM963XX_EXTENDED_SIZE;
spareaddr = roundup(totallen, master->erasesize) + cfelen;
if (rootfsaddr < kerneladdr) {
......
......@@ -491,6 +491,7 @@ static inline int arch_elf_pt_proc(struct elfhdr *ehdr,
* arch_check_elf() - check an ELF executable
* @ehdr: The main ELF header
* @has_interp: True if the ELF has an interpreter, else false.
* @interp_ehdr: The interpreter's ELF header
* @state: Architecture-specific state preserved throughout the process
* of loading the ELF.
*
......@@ -502,6 +503,7 @@ static inline int arch_elf_pt_proc(struct elfhdr *ehdr,
* with that return code.
*/
static inline int arch_check_elf(struct elfhdr *ehdr, bool has_interp,
struct elfhdr *interp_ehdr,
struct arch_elf_state *state)
{
/* Dummy implementation, always proceed */
......@@ -829,7 +831,9 @@ static int load_elf_binary(struct linux_binprm *bprm)
* still possible to return an error to the code that invoked
* the exec syscall.
*/
retval = arch_check_elf(&loc->elf_ex, !!interpreter, &arch_state);
retval = arch_check_elf(&loc->elf_ex,
!!interpreter, &loc->interp_elf_ex,
&arch_state);
if (retval)
goto out_free_dentry;
......
#ifndef __LINUX_BCM963XX_NVRAM_H__
#define __LINUX_BCM963XX_NVRAM_H__
#include <linux/crc32.h>
#include <linux/if_ether.h>
#include <linux/sizes.h>
#include <linux/types.h>
/*
* Broadcom BCM963xx SoC board nvram data structure.
*
* The nvram structure varies in size depending on the SoC board version. Use
* the appropriate minimum BCM963XX_NVRAM_*_SIZE define for the information
* you need instead of sizeof(struct bcm963xx_nvram) as this may change.
*/
#define BCM963XX_NVRAM_V4_SIZE 300
#define BCM963XX_NVRAM_V5_SIZE (1 * SZ_1K)
#define BCM963XX_DEFAULT_PSI_SIZE 64
enum bcm963xx_nvram_nand_part {
BCM963XX_NVRAM_NAND_PART_BOOT = 0,
BCM963XX_NVRAM_NAND_PART_ROOTFS_1,
BCM963XX_NVRAM_NAND_PART_ROOTFS_2,
BCM963XX_NVRAM_NAND_PART_DATA,
BCM963XX_NVRAM_NAND_PART_BBT,
__BCM963XX_NVRAM_NAND_NR_PARTS
};
struct bcm963xx_nvram {
u32 version;
char bootline[256];
char name[16];
u32 main_tp_number;
u32 psi_size;
u32 mac_addr_count;
u8 mac_addr_base[ETH_ALEN];
u8 __reserved1[2];
u32 checksum_v4;
u8 __reserved2[292];
u32 nand_part_offset[__BCM963XX_NVRAM_NAND_NR_PARTS];
u32 nand_part_size[__BCM963XX_NVRAM_NAND_NR_PARTS];
u8 __reserved3[388];
u32 checksum_v5;
};
#define BCM963XX_NVRAM_NAND_PART_OFFSET(nvram, part) \
bcm963xx_nvram_nand_part_offset(nvram, BCM963XX_NVRAM_NAND_PART_ ##part)
static inline u64 __pure bcm963xx_nvram_nand_part_offset(
const struct bcm963xx_nvram *nvram,
enum bcm963xx_nvram_nand_part part)
{
return nvram->nand_part_offset[part] * SZ_1K;
}
#define BCM963XX_NVRAM_NAND_PART_SIZE(nvram, part) \
bcm963xx_nvram_nand_part_size(nvram, BCM963XX_NVRAM_NAND_PART_ ##part)
static inline u64 __pure bcm963xx_nvram_nand_part_size(
const struct bcm963xx_nvram *nvram,
enum bcm963xx_nvram_nand_part part)
{
return nvram->nand_part_size[part] * SZ_1K;
}
/*
* bcm963xx_nvram_checksum - Verify nvram checksum
*
* @nvram: pointer to full size nvram data structure
* @expected_out: optional pointer to store expected checksum value
* @actual_out: optional pointer to store actual checksum value
*
* Return: 0 if the checksum is valid, otherwise -EINVAL
*/
static int __maybe_unused bcm963xx_nvram_checksum(
const struct bcm963xx_nvram *nvram,
u32 *expected_out, u32 *actual_out)
{
u32 expected, actual;
size_t len;
if (nvram->version <= 4) {
expected = nvram->checksum_v4;
len = BCM963XX_NVRAM_V4_SIZE - sizeof(u32);
} else {
expected = nvram->checksum_v5;
len = BCM963XX_NVRAM_V5_SIZE - sizeof(u32);
}
/*
* Calculate the CRC32 value for the nvram with a checksum value
* of 0 without modifying or copying the nvram by combining:
* - The CRC32 of the nvram without the checksum value
* - The CRC32 of a zero checksum value (which is also 0)
*/
actual = crc32_le_combine(
crc32_le(~0, (u8 *)nvram, len), 0, sizeof(u32));
if (expected_out)
*expected_out = expected;
if (actual_out)
*actual_out = actual;
return expected == actual ? 0 : -EINVAL;
};
#endif /* __LINUX_BCM963XX_NVRAM_H__ */
#ifndef __BCM963XX_TAG_H
#define __BCM963XX_TAG_H
#ifndef __LINUX_BCM963XX_TAG_H__
#define __LINUX_BCM963XX_TAG_H__
#include <linux/types.h>
#define TAGVER_LEN 4 /* Length of Tag Version */
#define TAGLAYOUT_LEN 4 /* Length of FlashLayoutVer */
......@@ -10,8 +12,7 @@
#define CHIPID_LEN 6 /* Chip Id Length */
#define IMAGE_LEN 10 /* Length of Length Field */
#define ADDRESS_LEN 12 /* Length of Address field */
#define DUALFLAG_LEN 2 /* Dual Image flag Length */
#define INACTIVEFLAG_LEN 2 /* Inactie Flag Length */
#define IMAGE_SEQUENCE_LEN 4 /* Image sequence Length */
#define RSASIG_LEN 20 /* Length of RSA Signature in tag */
#define TAGINFO1_LEN 30 /* Length of vendor information field1 in tag */
#define FLASHLAYOUTVER_LEN 4 /* Length of Flash Layout Version String tag */
......@@ -26,6 +27,11 @@
"DWV-S0", \
}
/* Extended flash address, needs to be subtracted
* from bcm_tag flash image offsets.
*/
#define BCM963XX_EXTENDED_SIZE 0xBFC00000
/*
* The broadcom firmware assumes the rootfs starts the image,
* therefore uses the rootfs start (flash_image_address)
......@@ -65,10 +71,10 @@ struct bcm_tag {
char kernel_address[ADDRESS_LEN];
/* 128-137: Size of kernel */
char kernel_length[IMAGE_LEN];
/* 138-139: Unused at the moment */
char dual_image[DUALFLAG_LEN];
/* 140-141: Unused at the moment */
char inactive_flag[INACTIVEFLAG_LEN];
/* 138-141: Image sequence number
* (to be incremented when flashed with a new image)
*/
char image_sequence[IMAGE_SEQUENCE_LEN];
/* 142-161: RSA Signature (not used; some vendors may use this) */
char rsa_signature[RSASIG_LEN];
/* 162-191: Compilation and related information (not used in OpenWrt) */
......@@ -93,4 +99,4 @@ struct bcm_tag {
char reserved2[16];
};
#endif /* __BCM63XX_TAG_H */
#endif /* __LINUX_BCM63XX_TAG_H__ */
/*
* Purna Chandra Mandal, purna.mandal@microchip.com
* Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
*
* This program is free software; you can distribute 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 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 __PIC32_SDHCI_PDATA_H__
#define __PIC32_SDHCI_PDATA_H__
struct pic32_sdhci_platform_data {
/* read & write fifo threshold */
int (*setup_dma)(u32 rfifo, u32 wfifo);
};
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment