Merge tag 'tegra-for-3.12-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra into next/soc

From: Stephen Warren:
ARM: tegra: core SoC enhancements for 3.12

This branch includes a number of enhancements to core SoC support for
Tegra devices. The major new features are:

* Adds a new CPU-power-gated cpuidle state for Tegra114.
* Adds initial system suspend support for Tegra114, initially supporting
  just CPU-power-gating during suspend.
* Adds "LP1" suspend mode support for all of Tegra20/30/114. This mode
  both gates CPU power, and places the DRAM into self-refresh mode.
* A new DT-driven PCIe driver to Tegra20/30. The driver is also moved
  from arch/arm/mach-tegra/ to drivers/pci/host/.

The PCIe driver work depends on the following tag from Thomas Petazzoni:
git://git.infradead.org/linux-mvebu.git mis-3.12.2
... which is merged into the middle of this pull request.

* tag 'tegra-for-3.12-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-tegra: (33 commits)
  ARM: tegra: disable LP2 cpuidle state if PCIe is enabled
  MAINTAINERS: Add myself as Tegra PCIe maintainer
  PCI: tegra: set up PADS_REFCLK_CFG1
  PCI: tegra: Add Tegra 30 PCIe support
  PCI: tegra: Move PCIe driver to drivers/pci/host
  PCI: msi: add default MSI operations for !HAVE_GENERIC_HARDIRQS platforms
  ARM: tegra: add LP1 suspend support for Tegra114
  ARM: tegra: add LP1 suspend support for Tegra20
  ARM: tegra: add LP1 suspend support for Tegra30
  ARM: tegra: add common LP1 suspend support
  clk: tegra114: add LP1 suspend/resume support
  ARM: tegra: config the polarity of the request of sys clock
  ARM: tegra: add common resume handling code for LP1 resuming
  ARM: pci: add ->add_bus() and ->remove_bus() hooks to hw_pci
  of: pci: add registry of MSI chips
  PCI: Introduce new MSI chip infrastructure
  PCI: remove ARCH_SUPPORTS_MSI kconfig option
  PCI: use weak functions for MSI arch-specific functions
  ARM: tegra: unify Tegra's Kconfig a bit more
  ARM: tegra: remove the limitation that Tegra114 can't support suspend
  ...

Signed-off-by: Kevin Hilman <khilman@linaro.org>
This commit is contained in:
Kevin Hilman
2013-08-21 10:16:55 -07:00
60 changed files with 3522 additions and 1151 deletions
@@ -0,0 +1,163 @@
NVIDIA Tegra PCIe controller
Required properties:
- compatible: "nvidia,tegra20-pcie" or "nvidia,tegra30-pcie"
- device_type: Must be "pci"
- reg: A list of physical base address and length for each set of controller
registers. Must contain an entry for each entry in the reg-names property.
- reg-names: Must include the following entries:
"pads": PADS registers
"afi": AFI registers
"cs": configuration space region
- interrupts: A list of interrupt outputs of the controller. Must contain an
entry for each entry in the interrupt-names property.
- interrupt-names: Must include the following entries:
"intr": The Tegra interrupt that is asserted for controller interrupts
"msi": The Tegra interrupt that is asserted when an MSI is received
- pex-clk-supply: Supply voltage for internal reference clock
- vdd-supply: Power supply for controller (1.05V)
- avdd-supply: Power supply for controller (1.05V) (not required for Tegra20)
- bus-range: Range of bus numbers associated with this controller
- #address-cells: Address representation for root ports (must be 3)
- cell 0 specifies the bus and device numbers of the root port:
[23:16]: bus number
[15:11]: device number
- cell 1 denotes the upper 32 address bits and should be 0
- cell 2 contains the lower 32 address bits and is used to translate to the
CPU address space
- #size-cells: Size representation for root ports (must be 2)
- ranges: Describes the translation of addresses for root ports and standard
PCI regions. The entries must be 6 cells each, where the first three cells
correspond to the address as described for the #address-cells property
above, the fourth cell is the physical CPU address to translate to and the
fifth and six cells are as described for the #size-cells property above.
- The first two entries are expected to translate the addresses for the root
port registers, which are referenced by the assigned-addresses property of
the root port nodes (see below).
- The remaining entries setup the mapping for the standard I/O, memory and
prefetchable PCI regions. The first cell determines the type of region
that is setup:
- 0x81000000: I/O memory region
- 0x82000000: non-prefetchable memory region
- 0xc2000000: prefetchable memory region
Please refer to the standard PCI bus binding document for a more detailed
explanation.
- clocks: List of clock inputs of the controller. Must contain an entry for
each entry in the clock-names property.
- clock-names: Must include the following entries:
"pex": The Tegra clock of that name
"afi": The Tegra clock of that name
"pcie_xclk": The Tegra clock of that name
"pll_e": The Tegra clock of that name
"cml": The Tegra clock of that name (not required for Tegra20)
Root ports are defined as subnodes of the PCIe controller node.
Required properties:
- device_type: Must be "pci"
- assigned-addresses: Address and size of the port configuration registers
- reg: PCI bus address of the root port
- #address-cells: Must be 3
- #size-cells: Must be 2
- ranges: Sub-ranges distributed from the PCIe controller node. An empty
property is sufficient.
- nvidia,num-lanes: Number of lanes to use for this port. Valid combinations
are:
- Root port 0 uses 4 lanes, root port 1 is unused.
- Both root ports use 2 lanes.
Example:
SoC DTSI:
pcie-controller {
compatible = "nvidia,tegra20-pcie";
device_type = "pci";
reg = <0x80003000 0x00000800 /* PADS registers */
0x80003800 0x00000200 /* AFI registers */
0x90000000 0x10000000>; /* configuration space */
reg-names = "pads", "afi", "cs";
interrupts = <0 98 0x04 /* controller interrupt */
0 99 0x04>; /* MSI interrupt */
interrupt-names = "intr", "msi";
bus-range = <0x00 0xff>;
#address-cells = <3>;
#size-cells = <2>;
ranges = <0x82000000 0 0x80000000 0x80000000 0 0x00001000 /* port 0 registers */
0x82000000 0 0x80001000 0x80001000 0 0x00001000 /* port 1 registers */
0x81000000 0 0 0x82000000 0 0x00010000 /* downstream I/O */
0x82000000 0 0xa0000000 0xa0000000 0 0x10000000 /* non-prefetchable memory */
0xc2000000 0 0xb0000000 0xb0000000 0 0x10000000>; /* prefetchable memory */
clocks = <&tegra_car 70>, <&tegra_car 72>, <&tegra_car 74>,
<&tegra_car 118>;
clock-names = "pex", "afi", "pcie_xclk", "pll_e";
status = "disabled";
pci@1,0 {
device_type = "pci";
assigned-addresses = <0x82000800 0 0x80000000 0 0x1000>;
reg = <0x000800 0 0 0 0>;
status = "disabled";
#address-cells = <3>;
#size-cells = <2>;
ranges;
nvidia,num-lanes = <2>;
};
pci@2,0 {
device_type = "pci";
assigned-addresses = <0x82001000 0 0x80001000 0 0x1000>;
reg = <0x001000 0 0 0 0>;
status = "disabled";
#address-cells = <3>;
#size-cells = <2>;
ranges;
nvidia,num-lanes = <2>;
};
};
Board DTS:
pcie-controller {
status = "okay";
vdd-supply = <&pci_vdd_reg>;
pex-clk-supply = <&pci_clk_reg>;
/* root port 00:01.0 */
pci@1,0 {
status = "okay";
/* bridge 01:00.0 (optional) */
pci@0,0 {
reg = <0x010000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
/* endpoint 02:00.0 */
pci@0,0 {
reg = <0x020000 0 0 0 0>;
};
};
};
};
Note that devices on the PCI bus are dynamically discovered using PCI's bus
enumeration and therefore don't need corresponding device nodes in DT. However
if a device on the PCI bus provides a non-probeable bus such as I2C or SPI,
device nodes need to be added in order to allow the bus' children to be
instantiated at the proper location in the operating system's device tree (as
illustrated by the optional nodes in the example above).
+7
View File
@@ -6275,6 +6275,13 @@ F: Documentation/PCI/
F: drivers/pci/
F: include/linux/pci*
PCI DRIVER FOR NVIDIA TEGRA
M: Thierry Reding <thierry.reding@gmail.com>
L: linux-tegra@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
F: drivers/pci/host/pci-tegra.c
PCMCIA SUBSYSTEM
P: Linux PCMCIA Team
L: linux-pcmcia@lists.infradead.org
-1
View File
@@ -441,7 +441,6 @@ config ARCH_NETX
config ARCH_IOP13XX
bool "IOP13xx-based"
depends on MMU
select ARCH_SUPPORTS_MSI
select CPU_XSC3
select NEED_MACH_MEMORY_H
select NEED_RET_TO_USER
+4
View File
@@ -36,6 +36,8 @@ struct hw_pci {
resource_size_t start,
resource_size_t size,
resource_size_t align);
void (*add_bus)(struct pci_bus *bus);
void (*remove_bus)(struct pci_bus *bus);
};
/*
@@ -63,6 +65,8 @@ struct pci_sys_data {
resource_size_t start,
resource_size_t size,
resource_size_t align);
void (*add_bus)(struct pci_bus *bus);
void (*remove_bus)(struct pci_bus *bus);
void *private_data; /* platform controller private data */
};
+16
View File
@@ -363,6 +363,20 @@ void pcibios_fixup_bus(struct pci_bus *bus)
}
EXPORT_SYMBOL(pcibios_fixup_bus);
void pcibios_add_bus(struct pci_bus *bus)
{
struct pci_sys_data *sys = bus->sysdata;
if (sys->add_bus)
sys->add_bus(bus);
}
void pcibios_remove_bus(struct pci_bus *bus)
{
struct pci_sys_data *sys = bus->sysdata;
if (sys->remove_bus)
sys->remove_bus(bus);
}
/*
* Swizzle the device pin each time we cross a bridge. If a platform does
* not provide a swizzle function, we perform the standard PCI swizzling.
@@ -464,6 +478,8 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
sys->swizzle = hw->swizzle;
sys->map_irq = hw->map_irq;
sys->align_resource = hw->align_resource;
sys->add_bus = hw->add_bus;
sys->remove_bus = hw->remove_bus;
INIT_LIST_HEAD(&sys->resources);
if (hw->private_data)
+9 -20
View File
@@ -2,19 +2,27 @@ config ARCH_TEGRA
bool "NVIDIA Tegra" if ARCH_MULTI_V7
select ARCH_HAS_CPUFREQ
select ARCH_REQUIRE_GPIOLIB
select ARM_GIC
select CLKDEV_LOOKUP
select CLKSRC_MMIO
select CLKSRC_OF
select COMMON_CLK
select CPU_V7
select GENERIC_CLOCKEVENTS
select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if LOCAL_TIMERS
select HAVE_CLK
select HAVE_SMP
select MIGHT_HAVE_CACHE_L2X0
select PINCTRL
select SOC_BUS
select SPARSE_IRQ
select USB_ARCH_HAS_EHCI if USB_SUPPORT
select USB_ULPI if USB_PHY
select USB_ULPI_VIEWPORT if USB_PHY
select USE_OF
select MIGHT_HAVE_PCI
select ARCH_SUPPORTS_MSI
help
This enables support for NVIDIA Tegra based systems.
@@ -27,15 +35,9 @@ config ARCH_TEGRA_2x_SOC
select ARM_ERRATA_720789
select ARM_ERRATA_754327 if SMP
select ARM_ERRATA_764369 if SMP
select ARM_GIC
select CPU_V7
select PINCTRL
select PINCTRL_TEGRA20
select PL310_ERRATA_727915 if CACHE_L2X0
select PL310_ERRATA_769419 if CACHE_L2X0
select USB_ARCH_HAS_EHCI if USB_SUPPORT
select USB_ULPI if USB_PHY
select USB_ULPI_VIEWPORT if USB_PHY
help
Support for NVIDIA Tegra AP20 and T20 processors, based on the
ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -44,14 +46,8 @@ config ARCH_TEGRA_3x_SOC
bool "Enable support for Tegra30 family"
select ARM_ERRATA_754322
select ARM_ERRATA_764369 if SMP
select ARM_GIC
select CPU_V7
select PINCTRL
select PINCTRL_TEGRA30
select PL310_ERRATA_769419 if CACHE_L2X0
select USB_ARCH_HAS_EHCI if USB_SUPPORT
select USB_ULPI if USB_PHY
select USB_ULPI_VIEWPORT if USB_PHY
help
Support for NVIDIA Tegra T30 processor family, based on the
ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -59,20 +55,13 @@ config ARCH_TEGRA_3x_SOC
config ARCH_TEGRA_114_SOC
bool "Enable support for Tegra114 family"
select HAVE_ARM_ARCH_TIMER
select ARM_GIC
select ARM_ERRATA_798181
select ARM_L1_CACHE_SHIFT_6
select CPU_V7
select PINCTRL
select PINCTRL_TEGRA114
help
Support for NVIDIA Tegra T114 processor family, based on the
ARM CortexA15MP CPU
config TEGRA_PCI
bool "PCI Express support"
depends on ARCH_TEGRA_2x_SOC
select PCI
config TEGRA_AHB
bool "Enable AHB driver for NVIDIA Tegra SoCs"
default y
+3 -3
View File
@@ -17,24 +17,24 @@ obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20_speedo.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += sleep-tegra20.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pm-tegra20.o
ifeq ($(CONFIG_CPU_IDLE),y)
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += cpuidle-tegra20.o
endif
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30_speedo.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += sleep-tegra30.o
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += pm-tegra30.o
ifeq ($(CONFIG_CPU_IDLE),y)
obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += cpuidle-tegra30.o
endif
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
obj-$(CONFIG_TEGRA_PCI) += pcie.o
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114_speedo.o
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += sleep-tegra30.o
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += pm-tegra30.o
ifeq ($(CONFIG_CPU_IDLE),y)
obj-$(CONFIG_ARCH_TEGRA_114_SOC) += cpuidle-tegra114.o
endif
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += board-harmony-pcie.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += board-paz00.o
-89
View File
@@ -1,89 +0,0 @@
/*
* arch/arm/mach-tegra/board-harmony-pcie.c
*
* Copyright (C) 2010 CompuLab, Ltd.
* Mike Rapoport <mike@compulab.co.il>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/err.h>
#include <linux/of_gpio.h>
#include <linux/regulator/consumer.h>
#include <asm/mach-types.h>
#include "board.h"
#ifdef CONFIG_TEGRA_PCI
int __init harmony_pcie_init(void)
{
struct device_node *np;
int en_vdd_1v05;
struct regulator *regulator = NULL;
int err;
np = of_find_node_by_path("/regulators/regulator@3");
if (!np) {
pr_err("%s: of_find_node_by_path failed\n", __func__);
return -ENODEV;
}
en_vdd_1v05 = of_get_named_gpio(np, "gpio", 0);
if (en_vdd_1v05 < 0) {
pr_err("%s: of_get_named_gpio failed: %d\n", __func__,
en_vdd_1v05);
return en_vdd_1v05;
}
err = gpio_request(en_vdd_1v05, "EN_VDD_1V05");
if (err) {
pr_err("%s: gpio_request failed: %d\n", __func__, err);
return err;
}
gpio_direction_output(en_vdd_1v05, 1);
regulator = regulator_get(NULL, "vdd_ldo0,vddio_pex_clk");
if (IS_ERR(regulator)) {
err = PTR_ERR(regulator);
pr_err("%s: regulator_get failed: %d\n", __func__, err);
goto err_reg;
}
err = regulator_enable(regulator);
if (err) {
pr_err("%s: regulator_enable failed: %d\n", __func__, err);
goto err_en;
}
err = tegra_pcie_init(true, true);
if (err) {
pr_err("%s: tegra_pcie_init failed: %d\n", __func__, err);
goto err_pcie;
}
return 0;
err_pcie:
regulator_disable(regulator);
err_en:
regulator_put(regulator);
err_reg:
gpio_free(en_vdd_1v05);
return err;
}
#endif
-8
View File
@@ -31,7 +31,6 @@ void __init tegra_init_early(void);
void __init tegra_map_common_io(void);
void __init tegra_init_irq(void);
void __init tegra_dt_init_irq(void);
int __init tegra_pcie_init(bool init_port0, bool init_port1);
void tegra_init_late(void);
@@ -48,13 +47,6 @@ int __init tegra_powergate_debugfs_init(void);
static inline int tegra_powergate_debugfs_init(void) { return 0; }
#endif
int __init harmony_regulator_init(void);
#ifdef CONFIG_TEGRA_PCI
int __init harmony_pcie_init(void);
#else
static inline int harmony_pcie_init(void) { return 0; }
#endif
void __init tegra_paz00_wifikill_init(void);
#endif
-1
View File
@@ -2,4 +2,3 @@ extern struct smp_operations tegra_smp_ops;
extern int tegra_cpu_kill(unsigned int cpu);
extern void tegra_cpu_die(unsigned int cpu);
extern int tegra_cpu_disable(unsigned int cpu);
+50 -1
View File
@@ -17,15 +17,64 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/cpuidle.h>
#include <linux/cpu_pm.h>
#include <linux/clockchips.h>
#include <asm/cpuidle.h>
#include <asm/suspend.h>
#include <asm/smp_plat.h>
#include "pm.h"
#include "sleep.h"
#ifdef CONFIG_PM_SLEEP
#define TEGRA114_MAX_STATES 2
#else
#define TEGRA114_MAX_STATES 1
#endif
#ifdef CONFIG_PM_SLEEP
static int tegra114_idle_power_down(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
{
local_fiq_disable();
tegra_set_cpu_in_lp2();
cpu_pm_enter();
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
cpu_pm_exit();
tegra_clear_cpu_in_lp2();
local_fiq_enable();
return index;
}
#endif
static struct cpuidle_driver tegra_idle_driver = {
.name = "tegra_idle",
.owner = THIS_MODULE,
.state_count = 1,
.state_count = TEGRA114_MAX_STATES,
.states = {
[0] = ARM_CPUIDLE_WFI_STATE_PWR(600),
#ifdef CONFIG_PM_SLEEP
[1] = {
.enter = tegra114_idle_power_down,
.exit_latency = 500,
.target_residency = 1000,
.power_usage = 0,
.flags = CPUIDLE_FLAG_TIME_VALID,
.name = "powered-down",
.desc = "CPU power gated",
},
#endif
},
};
+12
View File
@@ -211,6 +211,18 @@ static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev,
}
#endif
/*
* Tegra20 HW appears to have a bug such that PCIe device interrupts, whether
* they are legacy IRQs or MSI, are lost when LP2 is enabled. To work around
* this, simply disable LP2 if the PCI driver and DT node are both enabled.
*/
void tegra20_cpuidle_pcie_irqs_in_use(void)
{
pr_info_once(
"Disabling cpuidle LP2 state, since PCIe IRQs are in use\n");
tegra_idle_driver.states[1].disabled = true;
}
int __init tegra20_cpuidle_init(void)
{
return cpuidle_register(&tegra_idle_driver, cpu_possible_mask);
+10
View File
@@ -44,3 +44,13 @@ void __init tegra_cpuidle_init(void)
break;
}
}
void tegra_cpuidle_pcie_irqs_in_use(void)
{
switch (tegra_chip_id) {
case TEGRA20:
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
tegra20_cpuidle_pcie_irqs_in_use();
break;
}
}
+1
View File
@@ -19,6 +19,7 @@
#ifdef CONFIG_CPU_IDLE
int tegra20_cpuidle_init(void);
void tegra20_cpuidle_pcie_irqs_in_use(void);
int tegra30_cpuidle_init(void);
int tegra114_cpuidle_init(void);
void tegra_cpuidle_init(void);
+2
View File
@@ -86,6 +86,7 @@ void flowctrl_cpu_suspend_enter(unsigned int cpuid)
reg |= TEGRA20_FLOW_CTRL_CSR_WFE_CPU0 << cpuid;
break;
case TEGRA30:
case TEGRA114:
/* clear wfe bitmap */
reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;
/* clear wfi bitmap */
@@ -123,6 +124,7 @@ void flowctrl_cpu_suspend_exit(unsigned int cpuid)
reg &= ~TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP;
break;
case TEGRA30:
case TEGRA114:
/* clear wfe bitmap */
reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;
/* clear wfi bitmap */
+9
View File
@@ -28,9 +28,18 @@
#define FLOW_CTRL_SCLK_RESUME (1 << 27)
#define FLOW_CTRL_HALT_CPU_IRQ (1 << 10)
#define FLOW_CTRL_HALT_CPU_FIQ (1 << 8)
#define FLOW_CTRL_HALT_LIC_IRQ (1 << 11)
#define FLOW_CTRL_HALT_LIC_FIQ (1 << 10)
#define FLOW_CTRL_HALT_GIC_IRQ (1 << 9)
#define FLOW_CTRL_HALT_GIC_FIQ (1 << 8)
#define FLOW_CTRL_CPU0_CSR 0x8
#define FLOW_CTRL_CSR_INTR_FLAG (1 << 15)
#define FLOW_CTRL_CSR_EVENT_FLAG (1 << 14)
#define FLOW_CTRL_CSR_ENABLE_EXT_CRAIL (1 << 13)
#define FLOW_CTRL_CSR_ENABLE_EXT_NCPU (1 << 12)
#define FLOW_CTRL_CSR_ENABLE_EXT_MASK ( \
FLOW_CTRL_CSR_ENABLE_EXT_NCPU | \
FLOW_CTRL_CSR_ENABLE_EXT_CRAIL)
#define FLOW_CTRL_CSR_ENABLE (1 << 0)
#define FLOW_CTRL_HALT_CPU1_EVENTS 0x14
#define FLOW_CTRL_CPU1_CSR 0x18
+2 -1
View File
@@ -6,6 +6,7 @@
.section ".text.head", "ax"
ENTRY(tegra_secondary_startup)
bl v7_invalidate_l1
check_cpu_part_num 0xc09, r8, r9
bleq v7_invalidate_l1
b secondary_startup
ENDPROC(tegra_secondary_startup)
+1 -12
View File
@@ -37,7 +37,7 @@ int tegra_cpu_kill(unsigned cpu)
void __ref tegra_cpu_die(unsigned int cpu)
{
/* Clean L1 data cache */
tegra_disable_clean_inv_dcache();
tegra_disable_clean_inv_dcache(TEGRA_FLUSH_CACHE_LOUIS);
/* Shut down the current CPU. */
tegra_hotplug_shutdown();
@@ -46,17 +46,6 @@ void __ref tegra_cpu_die(unsigned int cpu)
BUG();
}
int tegra_cpu_disable(unsigned int cpu)
{
switch (tegra_chip_id) {
case TEGRA20:
case TEGRA30:
return cpu == 0 ? -EPERM : 0;
default:
return 0;
}
}
void __init tegra_hotplug_init(void)
{
if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
+8 -3
View File
@@ -24,6 +24,8 @@
#define TEGRA_IRAM_BASE 0x40000000
#define TEGRA_IRAM_SIZE SZ_256K
#define TEGRA_IRAM_CODE_AREA (TEGRA_IRAM_BASE + SZ_4K)
#define TEGRA_HOST1X_BASE 0x50000000
#define TEGRA_HOST1X_SIZE 0x24000
@@ -237,6 +239,12 @@
#define TEGRA_KFUSE_BASE 0x7000FC00
#define TEGRA_KFUSE_SIZE SZ_1K
#define TEGRA_EMC0_BASE 0x7001A000
#define TEGRA_EMC0_SIZE SZ_2K
#define TEGRA_EMC1_BASE 0x7001A800
#define TEGRA_EMC1_SIZE SZ_2K
#define TEGRA_CSITE_BASE 0x70040000
#define TEGRA_CSITE_SIZE SZ_256K
@@ -278,9 +286,6 @@
#define IO_APB_VIRT IOMEM(0xFE300000)
#define IO_APB_SIZE SZ_1M
#define TEGRA_PCIE_BASE 0x80000000
#define TEGRA_PCIE_IO_BASE (TEGRA_PCIE_BASE + SZ_4M)
#define IO_TO_VIRT_BETWEEN(p, st, sz) ((p) >= (st) && (p) < ((st) + (sz)))
#define IO_TO_VIRT_XLATE(p, pst, vst) (((p) - (pst) + (vst)))
+40
View File
@@ -18,10 +18,12 @@
*/
#include <linux/kernel.h>
#include <linux/cpu_pm.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/irqchip/arm-gic.h>
#include <linux/syscore_ops.h>
@@ -65,6 +67,7 @@ static u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS];
static u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS];
static u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS];
static void __iomem *tegra_gic_cpu_base;
#endif
bool tegra_pending_sgi(void)
@@ -213,8 +216,43 @@ int tegra_legacy_irq_syscore_init(void)
return 0;
}
static int tegra_gic_notifier(struct notifier_block *self,
unsigned long cmd, void *v)
{
switch (cmd) {
case CPU_PM_ENTER:
writel_relaxed(0x1E0, tegra_gic_cpu_base + GIC_CPU_CTRL);
break;
}
return NOTIFY_OK;
}
static struct notifier_block tegra_gic_notifier_block = {
.notifier_call = tegra_gic_notifier,
};
static const struct of_device_id tegra114_dt_gic_match[] __initconst = {
{ .compatible = "arm,cortex-a15-gic" },
{ }
};
static void tegra114_gic_cpu_pm_registration(void)
{
struct device_node *dn;
dn = of_find_matching_node(NULL, tegra114_dt_gic_match);
if (!dn)
return;
tegra_gic_cpu_base = of_iomap(dn, 1);
cpu_pm_register_notifier(&tegra_gic_notifier_block);
}
#else
#define tegra_set_wake NULL
static void tegra114_gic_cpu_pm_registration(void) { }
#endif
void __init tegra_init_irq(void)
@@ -252,4 +290,6 @@ void __init tegra_init_irq(void)
if (!of_have_populated_dt())
gic_init(0, 29, distbase,
IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
tegra114_gic_cpu_pm_registration();
}

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