You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
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:
@@ -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).
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)))
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user