Commit 0bbf2119 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://android.git.kernel.org/kernel/tegra

* 'for-linus' of git://android.git.kernel.org/kernel/tegra: (61 commits)
  ARM: tegra: trimslice: initialize PCI-e only when running on TrimSlice
  ARM: tegra: add PCI Express power gating
  ARM: tegra: PCIE minor code refactoring
  ARM: Tegra: DMA: Fail safe if initialization fails
  ARM: Tegra: Rename clk_dev1/2 to cdev1/2
  ARM: Tegra: Rename I2S clocks to match driver name
  ARM: Tegra: Make tegra_dma_init a postcore_initcall
  ARM: tegra: add seaboard, wario and kaen boards
  ARM: tegra: harmony: fix pinmux for MMC slot
  ARM: tegra: harmony: register sdhci devices
  ARM: tegra: remove stale nvidia atag handler
  ARM: tegra: common device resources
  ARM: tegra: harmony: move over to tegra_gpio_config
  ARM: tegra: add tegra_gpio_table and tegra_gpio_config
  ARM: tegra: Hide EMC scaling config behind ARCH_TEGRA
  ARM: tegra: Fix typo in TEGRA_IRQ_TO_GPIO
  ARM: tegra: common: Enable core clocks
  ARM: tegra: timer: Enable timer and rtc clocks
  ARM: tegra: Move tegra_common_init to tegra_init_early
  ARM: tegra: clock: prevent accidental disables of cpu clock
  ...
parents 51e8703b d5fdafd3
CONFIG_EXPERIMENTAL=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_CGROUPS=y
CONFIG_CGROUP_DEBUG=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_RESOURCE_COUNTERS=y
CONFIG_CGROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_EMBEDDED=y
# CONFIG_SYSCTL_SYSCALL is not set
# CONFIG_ELF_CORE is not set
CONFIG_SLAB=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_IOSCHED_DEADLINE is not set
# CONFIG_IOSCHED_CFQ is not set
CONFIG_ARCH_TEGRA=y
CONFIG_MACH_HARMONY=y
CONFIG_TEGRA_DEBUG_UARTD=y
CONFIG_ARM_ERRATA_742230=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
CONFIG_NR_CPUS=2
CONFIG_PREEMPT=y
CONFIG_AEABI=y
# CONFIG_OABI_COMPAT is not set
CONFIG_HIGHMEM=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
CONFIG_VFP=y
CONFIG_PM=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_NET_KEY=y
CONFIG_INET=y
CONFIG_INET_ESP=y
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
# CONFIG_INET_DIAG is not set
CONFIG_IPV6=y
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_OPTIMISTIC_DAD=y
CONFIG_INET6_AH=y
CONFIG_INET6_ESP=y
CONFIG_INET6_IPCOMP=y
CONFIG_IPV6_MIP6=y
CONFIG_IPV6_TUNNEL=y
CONFIG_IPV6_MULTIPLE_TABLES=y
# CONFIG_WIRELESS is not set
# CONFIG_FIRMWARE_IN_KERNEL is not set
CONFIG_BLK_DEV_LOOP=y
CONFIG_MISC_DEVICES=y
CONFIG_AD525X_DPOT=y
CONFIG_AD525X_DPOT_I2C=y
CONFIG_ICS932S401=y
CONFIG_APDS9802ALS=y
CONFIG_ISL29003=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_WLAN is not set
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
# CONFIG_LEGACY_PTYS is not set
# CONFIG_HW_RANDOM is not set
CONFIG_I2C=y
# CONFIG_HWMON is not set
# CONFIG_MFD_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT2_FS_SECURITY=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
# CONFIG_DNOTIFY is not set
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
CONFIG_SCHEDSTATS=y
CONFIG_TIMER_STATS=y
CONFIG_DEBUG_SLAB=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_VM=y
CONFIG_DEBUG_SG=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_DEBUG_LL=y
CONFIG_EARLY_PRINTK=y
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_ARC4=y
CONFIG_CRYPTO_TWOFISH=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRC_CCITT=y
CONFIG_CRC16=y
...@@ -27,6 +27,31 @@ config MACH_HARMONY ...@@ -27,6 +27,31 @@ config MACH_HARMONY
help help
Support for nVidia Harmony development platform Support for nVidia Harmony development platform
config MACH_KAEN
bool "Kaen board"
select MACH_SEABOARD
help
Support for the Kaen version of Seaboard
config MACH_SEABOARD
bool "Seaboard board"
help
Support for nVidia Seaboard development platform. It will
also be included for some of the derivative boards that
have large similarities with the seaboard design.
config MACH_TRIMSLICE
bool "TrimSlice board"
select TEGRA_PCI
help
Support for CompuLab TrimSlice platform
config MACH_WARIO
bool "Wario board"
select MACH_SEABOARD
help
Support for the Wario version of Seaboard
choice choice
prompt "Low-level debug console UART" prompt "Low-level debug console UART"
default TEGRA_DEBUG_UART_NONE default TEGRA_DEBUG_UART_NONE
...@@ -58,4 +83,7 @@ config TEGRA_SYSTEM_DMA ...@@ -58,4 +83,7 @@ config TEGRA_SYSTEM_DMA
Adds system DMA functionality for NVIDIA Tegra SoCs, used by Adds system DMA functionality for NVIDIA Tegra SoCs, used by
several Tegra device drivers several Tegra device drivers
config TEGRA_EMC_SCALING_ENABLE
bool "Enable scaling the memory frequency"
endif endif
obj-y += common.o obj-y += common.o
obj-y += devices.o
obj-y += io.o obj-y += io.o
obj-y += irq.o legacy_irq.o obj-y += irq.o legacy_irq.o
obj-y += clock.o obj-y += clock.o
obj-y += timer.o obj-y += timer.o
obj-y += gpio.o obj-y += gpio.o
obj-y += pinmux.o obj-y += pinmux.o
obj-y += powergate.o
obj-y += fuse.o obj-y += fuse.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clock.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clock.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_dvfs.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pinmux-t2-tables.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pinmux-t2-tables.o
obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
...@@ -19,3 +21,9 @@ obj-$(CONFIG_TEGRA_PCI) += pcie.o ...@@ -19,3 +21,9 @@ obj-$(CONFIG_TEGRA_PCI) += pcie.o
obj-${CONFIG_MACH_HARMONY} += board-harmony.o obj-${CONFIG_MACH_HARMONY} += board-harmony.o
obj-${CONFIG_MACH_HARMONY} += board-harmony-pinmux.o obj-${CONFIG_MACH_HARMONY} += board-harmony-pinmux.o
obj-${CONFIG_MACH_HARMONY} += board-harmony-pcie.o obj-${CONFIG_MACH_HARMONY} += board-harmony-pcie.o
obj-${CONFIG_MACH_SEABOARD} += board-seaboard.o
obj-${CONFIG_MACH_SEABOARD} += board-seaboard-pinmux.o
obj-${CONFIG_MACH_TRIMSLICE} += board-trimslice.o
obj-${CONFIG_MACH_TRIMSLICE} += board-trimslice-pinmux.o
...@@ -15,8 +15,10 @@ ...@@ -15,8 +15,10 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/gpio.h>
#include <mach/pinmux.h> #include <mach/pinmux.h>
#include "gpio-names.h"
#include "board-harmony.h" #include "board-harmony.h"
static struct tegra_pingroup_config harmony_pinmux[] = { static struct tegra_pingroup_config harmony_pinmux[] = {
...@@ -34,10 +36,10 @@ static struct tegra_pingroup_config harmony_pinmux[] = { ...@@ -34,10 +36,10 @@ static struct tegra_pingroup_config harmony_pinmux[] = {
{TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_DAP4, TEGRA_MUX_DAP4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_DAP4, TEGRA_MUX_DAP4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_DDC, TEGRA_MUX_I2C2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, {TEGRA_PINGROUP_DDC, TEGRA_MUX_I2C2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_DTA, TEGRA_MUX_SDIO2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_DTA, TEGRA_MUX_SDIO2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_DTB, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_DTB, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_DTC, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_DTC, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_DTD, TEGRA_MUX_SDIO2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_DTD, TEGRA_MUX_SDIO2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL},
{TEGRA_PINGROUP_DTE, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_DTE, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_DTF, TEGRA_MUX_I2C3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, {TEGRA_PINGROUP_DTF, TEGRA_MUX_I2C3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
{TEGRA_PINGROUP_GMA, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, {TEGRA_PINGROUP_GMA, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
...@@ -138,7 +140,18 @@ static struct tegra_pingroup_config harmony_pinmux[] = { ...@@ -138,7 +140,18 @@ static struct tegra_pingroup_config harmony_pinmux[] = {
{TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, {TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
}; };
static struct tegra_gpio_table gpio_table[] = {
{ .gpio = TEGRA_GPIO_PI5, .enable = true }, /* mmc2 cd */
{ .gpio = TEGRA_GPIO_PH1, .enable = true }, /* mmc2 wp */
{ .gpio = TEGRA_GPIO_PT3, .enable = true }, /* mmc2 pwr */
{ .gpio = TEGRA_GPIO_PH2, .enable = true }, /* mmc4 cd */
{ .gpio = TEGRA_GPIO_PH3, .enable = true }, /* mmc4 wp */
{ .gpio = TEGRA_GPIO_PI6, .enable = true }, /* mmc4 pwr */
};
void harmony_pinmux_init(void) void harmony_pinmux_init(void)
{ {
tegra_pinmux_config_table(harmony_pinmux, ARRAY_SIZE(harmony_pinmux)); tegra_pinmux_config_table(harmony_pinmux, ARRAY_SIZE(harmony_pinmux));
tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
} }
...@@ -30,35 +30,13 @@ ...@@ -30,35 +30,13 @@
#include <mach/iomap.h> #include <mach/iomap.h>
#include <mach/irqs.h> #include <mach/irqs.h>
#include <mach/sdhci.h>
#include "board.h" #include "board.h"
#include "board-harmony.h" #include "board-harmony.h"
#include "clock.h" #include "clock.h"
#include "devices.h"
/* NVidia bootloader tags */ #include "gpio-names.h"
#define ATAG_NVIDIA 0x41000801
#define ATAG_NVIDIA_RM 0x1
#define ATAG_NVIDIA_DISPLAY 0x2
#define ATAG_NVIDIA_FRAMEBUFFER 0x3
#define ATAG_NVIDIA_CHIPSHMOO 0x4
#define ATAG_NVIDIA_CHIPSHMOOPHYS 0x5
#define ATAG_NVIDIA_PRESERVED_MEM_0 0x10000
#define ATAG_NVIDIA_PRESERVED_MEM_N 2
#define ATAG_NVIDIA_FORCE_32 0x7fffffff
struct tag_tegra {
__u32 bootarg_key;
__u32 bootarg_len;
char bootarg[1];
};
static int __init parse_tag_nvidia(const struct tag *tag)
{
return 0;
}
__tagtable(ATAG_NVIDIA, parse_tag_nvidia);
static struct plat_serial8250_port debug_uart_platform_data[] = { static struct plat_serial8250_port debug_uart_platform_data[] = {
{ {
...@@ -84,6 +62,9 @@ static struct platform_device debug_uart = { ...@@ -84,6 +62,9 @@ static struct platform_device debug_uart = {
static struct platform_device *harmony_devices[] __initdata = { static struct platform_device *harmony_devices[] __initdata = {
&debug_uart, &debug_uart,
&tegra_sdhci_device1,
&tegra_sdhci_device2,
&tegra_sdhci_device4,
}; };
static void __init tegra_harmony_fixup(struct machine_desc *desc, static void __init tegra_harmony_fixup(struct machine_desc *desc,
...@@ -102,22 +83,45 @@ static __initdata struct tegra_clk_init_table harmony_clk_init_table[] = { ...@@ -102,22 +83,45 @@ static __initdata struct tegra_clk_init_table harmony_clk_init_table[] = {
{ NULL, NULL, 0, 0}, { NULL, NULL, 0, 0},
}; };
static struct tegra_sdhci_platform_data sdhci_pdata1 = {
.cd_gpio = -1,
.wp_gpio = -1,
.power_gpio = -1,
};
static struct tegra_sdhci_platform_data sdhci_pdata2 = {
.cd_gpio = TEGRA_GPIO_PI5,
.wp_gpio = TEGRA_GPIO_PH1,
.power_gpio = TEGRA_GPIO_PT3,
};
static struct tegra_sdhci_platform_data sdhci_pdata4 = {
.cd_gpio = TEGRA_GPIO_PH2,
.wp_gpio = TEGRA_GPIO_PH3,
.power_gpio = TEGRA_GPIO_PI6,
.is_8bit = 1,
};
static void __init tegra_harmony_init(void) static void __init tegra_harmony_init(void)
{ {
tegra_common_init();
tegra_clk_init_from_table(harmony_clk_init_table); tegra_clk_init_from_table(harmony_clk_init_table);
harmony_pinmux_init(); harmony_pinmux_init();
tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1;
tegra_sdhci_device2.dev.platform_data = &sdhci_pdata2;
tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
platform_add_devices(harmony_devices, ARRAY_SIZE(harmony_devices)); platform_add_devices(harmony_devices, ARRAY_SIZE(harmony_devices));
} }
MACHINE_START(HARMONY, "harmony") MACHINE_START(HARMONY, "harmony")
.boot_params = 0x00000100, .boot_params = 0x00000100,
.fixup = tegra_harmony_fixup, .fixup = tegra_harmony_fixup,
.init_irq = tegra_init_irq,
.init_machine = tegra_harmony_init,
.map_io = tegra_map_common_io, .map_io = tegra_map_common_io,
.init_early = tegra_init_early,
.init_irq = tegra_init_irq,
.timer = &tegra_timer, .timer = &tegra_timer,
.init_machine = tegra_harmony_init,
MACHINE_END MACHINE_END
This diff is collapsed.
/*
* Copyright (c) 2010, 2011 NVIDIA Corporation.
* Copyright (C) 2010, 2011 Google, Inc.
*
* 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.
*
* 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/init.h>
#include <linux/platform_device.h>
#include <linux/serial_8250.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/io.h>
#include <linux/gpio_keys.h>
#include <mach/iomap.h>
#include <mach/irqs.h>
#include <mach/sdhci.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include "board.h"
#include "board-seaboard.h"
#include "clock.h"
#include "devices.h"
#include "gpio-names.h"
static struct plat_serial8250_port debug_uart_platform_data[] = {
{
/* Memory and IRQ filled in before registration */
.flags = UPF_BOOT_AUTOCONF,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = 216000000,
}, {
.flags = 0,
}
};
static struct platform_device debug_uart = {
.name = "serial8250",
.id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = debug_uart_platform_data,
},
};
static __initdata struct tegra_clk_init_table seaboard_clk_init_table[] = {
/* name parent rate enabled */
{ "uartb", "pll_p", 216000000, true},
{ "uartd", "pll_p", 216000000, true},
{ NULL, NULL, 0, 0},
};
static struct gpio_keys_button seaboard_gpio_keys_buttons[] = {
{
.code = SW_LID,
.gpio = TEGRA_GPIO_LIDSWITCH,
.active_low = 0,
.desc = "Lid",
.type = EV_SW,
.wakeup = 1,
.debounce_interval = 1,
},
{
.code = KEY_POWER,
.gpio = TEGRA_GPIO_POWERKEY,
.active_low = 1,
.desc = "Power",
.type = EV_KEY,
.wakeup = 1,
},
};
static struct gpio_keys_platform_data seaboard_gpio_keys = {
.buttons = seaboard_gpio_keys_buttons,
.nbuttons = ARRAY_SIZE(seaboard_gpio_keys_buttons),
};
static struct platform_device seaboard_gpio_keys_device = {
.name = "gpio-keys",
.id = -1,
.dev = {
.platform_data = &seaboard_gpio_keys,
}
};
static struct tegra_sdhci_platform_data sdhci_pdata1 = {
.cd_gpio = -1,
.wp_gpio = -1,
.power_gpio = -1,
};
static struct tegra_sdhci_platform_data sdhci_pdata3 = {
.cd_gpio = TEGRA_GPIO_PI5,
.wp_gpio = TEGRA_GPIO_PH1,
.power_gpio = TEGRA_GPIO_PI6,
};
static struct tegra_sdhci_platform_data sdhci_pdata4 = {
.cd_gpio = -1,
.wp_gpio = -1,
.power_gpio = -1,
.is_8bit = 1,
};
static struct platform_device *seaboard_devices[] __initdata = {
&debug_uart,
&tegra_pmu_device,
&tegra_sdhci_device1,
&tegra_sdhci_device3,
&tegra_sdhci_device4,
&seaboard_gpio_keys_device,
};
static void __init __tegra_seaboard_init(void)
{
seaboard_pinmux_init();
tegra_clk_init_from_table(seaboard_clk_init_table);
tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1;
tegra_sdhci_device3.dev.platform_data = &sdhci_pdata3;
tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
platform_add_devices(seaboard_devices, ARRAY_SIZE(seaboard_devices));
}
static void __init tegra_seaboard_init(void)
{
/* Seaboard uses UARTD for the debug port. */
debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTD_BASE);
debug_uart_platform_data[0].mapbase = TEGRA_UARTD_BASE;
debug_uart_platform_data[0].irq = INT_UARTD;
__tegra_seaboard_init();
}
static void __init tegra_kaen_init(void)
{
/* Kaen uses UARTB for the debug port. */
debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTB_BASE);
debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE;
debug_uart_platform_data[0].irq = INT_UARTB;
__tegra_seaboard_init();
}
static void __init tegra_wario_init(void)
{
/* Wario uses UARTB for the debug port. */
debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTB_BASE);
debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE;
debug_uart_platform_data[0].irq = INT_UARTB;
__tegra_seaboard_init();
}
MACHINE_START(SEABOARD, "seaboard")
.boot_params = 0x00000100,
.map_io = tegra_map_common_io,
.init_early = tegra_init_early,
.init_irq = tegra_init_irq,
.timer = &tegra_timer,
.init_machine = tegra_seaboard_init,
MACHINE_END
MACHINE_START(KAEN, "kaen")
.boot_params = 0x00000100,
.map_io = tegra_map_common_io,
.init_early = tegra_init_early,
.init_irq = tegra_init_irq,
.timer = &tegra_timer,
.init_machine = tegra_kaen_init,
MACHINE_END
MACHINE_START(WARIO, "wario")
.boot_params = 0x00000100,
.map_io = tegra_map_common_io,
.init_early = tegra_init_early,
.init_irq = tegra_init_irq,
.timer = &tegra_timer,
.init_machine = tegra_wario_init,
MACHINE_END
/*
* arch/arm/mach-tegra/board-seaboard.h
*
* Copyright (C) 2010 Google, Inc.
*
* 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.
*
*/
#ifndef _MACH_TEGRA_BOARD_SEABOARD_H
#define _MACH_TEGRA_BOARD_SEABOARD_H
#define TEGRA_GPIO_LIDSWITCH TEGRA_GPIO_PC7
#define TEGRA_GPIO_USB1 TEGRA_GPIO_PD0
#define TEGRA_GPIO_POWERKEY TEGRA_GPIO_PV2
#define TEGRA_GPIO_BACKLIGHT TEGRA_GPIO_PD4
#define TEGRA_GPIO_LVDS_SHUTDOWN TEGRA_GPIO_PB2
#define TEGRA_GPIO_BACKLIGHT_PWM TEGRA_GPIO_PU5
#define TEGRA_GPIO_BACKLIGHT_VDD TEGRA_GPIO_PW0
#define TEGRA_GPIO_EN_VDD_PNL TEGRA_GPIO_PC6
#define TEGRA_GPIO_MAGNETOMETER TEGRA_GPIO_PN5
#define TEGRA_GPIO_ISL29018_IRQ TEGRA_GPIO_PZ2
#define TEGRA_GPIO_AC_ONLINE TEGRA_GPIO_PV3
#define TPS_GPIO_BASE TEGRA_NR_GPIOS
#define TPS_GPIO_WWAN_PWR (TPS_GPIO_BASE + 2)
void seaboard_pinmux_init(void);
#endif
This diff is collapsed.
/*
* arch/arm/mach-tegra/board-trimslice.c
*
* Copyright (C) 2011 CompuLab, Ltd.
* Author: Mike Rapoport <mike@compulab.co.il>
*
* Based on board-harmony.c
* Copyright (C) 2010 Google, Inc.
*
* 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/init.h>
#include <linux/platform_device.h>
#include <linux/serial_8250.h>
#include <linux/io.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/setup.h>
#include <mach/iomap.h>
#include "board.h"
#include "clock.h"
#include "board-trimslice.h"
static struct plat_serial8250_port debug_uart_platform_data[] = {
{
.membase = IO_ADDRESS(TEGRA_UARTA_BASE),
.mapbase = TEGRA_UARTA_BASE,
.irq = INT_UARTA,
.flags = UPF_BOOT_AUTOCONF,
.iotype = UPIO_MEM,
.regshift = 2,
.uartclk = 216000000,
}, {
.flags = 0
}
};
static struct platform_device debug_uart = {
.name = "serial8250",
.id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = debug_uart_platform_data,
},
};
static struct platform_device *trimslice_devices[] __initdata = {
&debug_uart,
};
static void __init tegra_trimslice_fixup(struct machine_desc *desc,
struct tag *tags, char **cmdline, struct meminfo *mi)
{
mi->nr_banks = 2;
mi->bank[0].start = PHYS_OFFSET;
mi->bank[0].size = 448 * SZ_1M;
mi->bank[1].start = SZ_512M;
mi->bank[1].size = SZ_512M;
}
static __initdata struct tegra_clk_init_table trimslice_clk_init_table[] = {
/* name parent rate enabled */
{ "uarta", "pll_p", 216000000, true },
{ NULL, NULL, 0, 0},
};
static int __init tegra_trimslice_pci_init(void)
{
if (!machine_is_trimslice())
return 0;
return tegra_pcie_init(true, true);
}
subsys_initcall(tegra_trimslice_pci_init);
static void __init tegra_trimslice_init(void)
{
tegra_clk_init_from_table(trimslice_clk_init_table);
trimslice_pinmux_init();
platform_add_devices(trimslice_devices, ARRAY_SIZE(trimslice_devices));
}
MACHINE_START(TRIMSLICE, "trimslice")
.boot_params = 0x00000100,
.fixup = tegra_trimslice_fixup,
.map_io = tegra_map_common_io,
.init_early = tegra_init_early,
.init_irq = tegra_init_irq,
.timer = &tegra_timer,
.init_machine = tegra_trimslice_init,
MACHINE_END
/* /*
* arch/arm/mach-tegra/tegra2_dvfs.h * arch/arm/mach-tegra/board-trimslice.h
* *
* Copyright (C) 2010 Google, Inc. * Copyright (C) 2011 CompuLab, Ltd.
*
* Author:
* Colin Cross <ccross@google.com>
* *
* This software is licensed under the terms of the GNU General Public * This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and * License version 2, as published by the Free Software Foundation, and
...@@ -17,4 +14,9 @@ ...@@ -17,4 +14,9 @@
* *
*/ */
extern struct dvfs tegra_dvfs_virtual_cpu_dvfs; #ifndef _MACH_TEGRA_BOARD_TRIMSLICE_H
#define _MACH_TEGRA_BOARD_TRIMSLICE_H
void trimslice_pinmux_init(void);
#endif
...@@ -23,7 +23,9 @@ ...@@ -23,7 +23,9 @@
#include <linux/types.h> #include <linux/types.h>
void __init tegra_common_init(void); void tegra_assert_system_reset(char mode, const char *cmd);
void __init tegra_init_early(void);
void __init tegra_map_common_io(void); void __init tegra_map_common_io(void);
void __init tegra_init_irq(void); void __init tegra_init_irq(void);
void __init tegra_init_clock(void); void __init tegra_init_clock(void);
......
This diff is collapsed.
...@@ -20,8 +20,9 @@ ...@@ -20,8 +20,9 @@
#ifndef __MACH_TEGRA_CLOCK_H #ifndef __MACH_TEGRA_CLOCK_H
#define __MACH_TEGRA_CLOCK_H #define __MACH_TEGRA_CLOCK_H
#include <linux/list.h>
#include <linux/clkdev.h> #include <linux/clkdev.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#define DIV_BUS (1 << 0) #define DIV_BUS (1 << 0)
#define DIV_U71 (1 << 1) #define DIV_U71 (1 << 1)
...@@ -41,36 +42,13 @@ ...@@ -41,36 +42,13 @@
#define ENABLE_ON_INIT (1 << 28) #define ENABLE_ON_INIT (1 << 28)
struct clk; struct clk;
struct regulator;
struct dvfs_table {
unsigned long rate;
int millivolts;
};
struct dvfs_process_id_table {
int process_id;
struct dvfs_table *table;
};
struct dvfs {
struct regulator *reg;
struct dvfs_table *table;
int max_millivolts;
int process_id_table_length;
const char *reg_id;
bool cpu;
struct dvfs_process_id_table process_id_table[];
};
struct clk_mux_sel { struct clk_mux_sel {
struct clk *input; struct clk *input;
u32 value; u32 value;
}; };
struct clk_pll_table { struct clk_pll_freq_table {
unsigned long input_rate; unsigned long input_rate;
unsigned long output_rate; unsigned long output_rate;
u16 n; u16 n;
...@@ -86,6 +64,7 @@ struct clk_ops { ...@@ -86,6 +64,7 @@ struct clk_ops {
int (*set_parent)(struct clk *, struct clk *); int (*set_parent)(struct clk *, struct clk *);
int (*set_rate)(struct clk *, unsigned long); int (*set_rate)(struct clk *, unsigned long);
long (*round_rate)(struct clk *, unsigned long); long (*round_rate)(struct clk *, unsigned long);
void (*reset)(struct clk *, bool);
}; };
enum clk_state { enum clk_state {
...@@ -96,55 +75,64 @@ enum clk_state { ...@@ -96,55 +75,64 @@ enum clk_state {
struct clk { struct clk {
/* node for master clocks list */ /* node for master clocks list */
struct list_head node; struct list_head node; /* node for list of all clocks */
struct list_head children; /* list of children */ struct clk_lookup lookup;
struct list_head sibling; /* node for children */
#ifdef CONFIG_DEBUG_FS
struct dentry *dent;
struct dentry *parent_dent;
#endif
struct clk_ops *ops;
struct clk *parent;
struct clk_lookup lookup;
unsigned long rate;
unsigned long max_rate;
u32 flags;
u32 refcnt;
const char *name;
u32 reg;
u32 reg_shift;
unsigned int clk_num;
enum clk_state state;
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
bool set; struct dentry *dent;
#endif #endif
bool set;
struct clk_ops *ops;
unsigned long rate;
unsigned long max_rate;
unsigned long min_rate;
u32 flags;
const char *name;
u32 refcnt;
enum clk_state state;
struct clk *parent;
u32 div;
u32 mul;
/* PLL */
unsigned long input_min;
unsigned long input_max;
unsigned long cf_min;
unsigned long cf_max;
unsigned long vco_min;
unsigned long vco_max;
const struct clk_pll_table *pll_table;
/* DIV */
u32 div;
u32 mul;
/* MUX */
const struct clk_mux_sel *inputs; const struct clk_mux_sel *inputs;
u32 sel; u32 reg;
u32 reg_mask; u32 reg_shift;
/* Virtual cpu clock */
struct clk *main;
struct clk *backup;
struct dvfs *dvfs; struct list_head shared_bus_list;
union {
struct {
unsigned int clk_num;
} periph;
struct {
unsigned long input_min;
unsigned long input_max;
unsigned long cf_min;
unsigned long cf_max;
unsigned long vco_min;
unsigned long vco_max;
const struct clk_pll_freq_table *freq_table;
int lock_delay;
} pll;
struct {
u32 sel;
u32 reg_mask;
} mux;
struct {
struct clk *main;
struct clk *backup;
} cpu;
struct {
struct list_head node;
bool enabled;
unsigned long rate;
} shared_bus_user;
} u;
spinlock_t spinlock;
}; };
struct clk_duplicate { struct clk_duplicate {
const char *name; const char *name;
struct clk_lookup lookup; struct clk_lookup lookup;
...@@ -163,11 +151,10 @@ void tegra2_periph_reset_assert(struct clk *c); ...@@ -163,11 +151,10 @@ void tegra2_periph_reset_assert(struct clk *c);
void clk_init(struct clk *clk); void clk_init(struct clk *clk);
struct clk *tegra_get_clock_by_name(const char *name); struct clk *tegra_get_clock_by_name(const char *name);
unsigned long clk_measure_input_freq(void); unsigned long clk_measure_input_freq(void);
void clk_disable_locked(struct clk *c);
int clk_enable_locked(struct clk *c);
int clk_set_parent_locked(struct clk *c, struct clk *parent);
int clk_set_rate_locked(struct clk *c, unsigned long rate);
int clk_reparent(struct clk *c, struct clk *parent); int clk_reparent(struct clk *c, struct clk *parent);
void tegra_clk_init_from_table(struct tegra_clk_init_table *table); void tegra_clk_init_from_table(struct tegra_clk_init_table *table);
unsigned long clk_get_rate_locked(struct clk *c);
int clk_set_rate_locked(struct clk *c, unsigned long rate);
void tegra2_sdmmc_tap_delay(struct clk *c, int delay);
#endif #endif
...@@ -25,12 +25,25 @@ ...@@ -25,12 +25,25 @@
#include <asm/hardware/cache-l2x0.h> #include <asm/hardware/cache-l2x0.h>
#include <mach/iomap.h> #include <mach/iomap.h>
#include <mach/dma.h> #include <mach/system.h>
#include "board.h" #include "board.h"
#include "clock.h" #include "clock.h"
#include "fuse.h" #include "fuse.h"
void (*arch_reset)(char mode, const char *cmd) = tegra_assert_system_reset;
void tegra_assert_system_reset(char mode, const char *cmd)
{
void __iomem *reset = IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x04);
u32 reg;
/* use *_related to avoid spinlock since caches are off */
reg = readl_relaxed(reset);
reg |= 0x04;
writel_relaxed(reg, reset);
}
static __initdata struct tegra_clk_init_table common_clk_init_table[] = { static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
/* name parent rate enabled */ /* name parent rate enabled */
{ "clk_m", NULL, 0, true }, { "clk_m", NULL, 0, true },
...@@ -42,6 +55,9 @@ static __initdata struct tegra_clk_init_table common_clk_init_table[] = { ...@@ -42,6 +55,9 @@ static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
{ "sclk", "pll_p_out4", 108000000, true }, { "sclk", "pll_p_out4", 108000000, true },
{ "hclk", "sclk", 108000000, true }, { "hclk", "sclk", 108000000, true },
{ "pclk", "hclk", 54000000, true }, { "pclk", "hclk", 54000000, true },
{ "csite", NULL, 0, true },
{ "emc", NULL, 0, true },
{ "cpu", NULL, 0, true },
{ NULL, NULL, 0, 0}, { NULL, NULL, 0, 0},
}; };
...@@ -50,21 +66,18 @@ void __init tegra_init_cache(void) ...@@ -50,21 +66,18 @@ void __init tegra_init_cache(void)
#ifdef CONFIG_CACHE_L2X0 #ifdef CONFIG_CACHE_L2X0
void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
writel(0x331, p + L2X0_TAG_LATENCY_CTRL); writel_relaxed(0x331, p + L2X0_TAG_LATENCY_CTRL);
writel(0x441, p + L2X0_DATA_LATENCY_CTRL); writel_relaxed(0x441, p + L2X0_DATA_LATENCY_CTRL);
l2x0_init(p, 0x6C080001, 0x8200c3fe); l2x0_init(p, 0x6C080001, 0x8200c3fe);
#endif #endif
} }
void __init tegra_common_init(void) void __init tegra_init_early(void)
{ {
tegra_init_fuse(); tegra_init_fuse();
tegra_init_clock(); tegra_init_clock();
tegra_clk_init_from_table(common_clk_init_table); tegra_clk_init_from_table(common_clk_init_table);
tegra_init_cache(); tegra_init_cache();
#ifdef CONFIG_TEGRA_SYSTEM_DMA
tegra_dma_init();
#endif
} }
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/suspend.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -36,21 +37,25 @@ ...@@ -36,21 +37,25 @@
/* Frequency table index must be sequential starting at 0 */ /* Frequency table index must be sequential starting at 0 */
static struct cpufreq_frequency_table freq_table[] = { static struct cpufreq_frequency_table freq_table[] = {
{ 0, 312000 }, { 0, 216000 },
{ 1, 456000 }, { 1, 312000 },
{ 2, 608000 }, { 2, 456000 },
{ 3, 760000 }, { 3, 608000 },
{ 4, 816000 }, { 4, 760000 },
{ 5, 912000 }, { 5, 816000 },
{ 6, 1000000 }, { 6, 912000 },
{ 7, CPUFREQ_TABLE_END }, { 7, 1000000 },
{ 8, CPUFREQ_TABLE_END },
}; };
#define NUM_CPUS 2 #define NUM_CPUS 2
static struct clk *cpu_clk; static struct clk *cpu_clk;
static struct clk *emc_clk;
static unsigned long target_cpu_speed[NUM_CPUS]; static unsigned long target_cpu_speed[NUM_CPUS];
static DEFINE_MUTEX(tegra_cpu_lock);
static bool is_suspended;
int tegra_verify_speed(struct cpufreq_policy *policy) int tegra_verify_speed(struct cpufreq_policy *policy)
{ {
...@@ -68,22 +73,28 @@ unsigned int tegra_getspeed(unsigned int cpu) ...@@ -68,22 +73,28 @@ unsigned int tegra_getspeed(unsigned int cpu)
return rate; return rate;
} }
static int tegra_update_cpu_speed(void) static int tegra_update_cpu_speed(unsigned long rate)
{ {
int i;
unsigned long rate = 0;
int ret = 0; int ret = 0;
struct cpufreq_freqs freqs; struct cpufreq_freqs freqs;
for_each_online_cpu(i)
rate = max(rate, target_cpu_speed[i]);
freqs.old = tegra_getspeed(0); freqs.old = tegra_getspeed(0);
freqs.new = rate; freqs.new = rate;
if (freqs.old == freqs.new) if (freqs.old == freqs.new)
return ret; return ret;
/*
* Vote on memory bus frequency based on cpu frequency
* This sets the minimum frequency, display or avp may request higher
*/
if (rate >= 816000)
clk_set_rate(emc_clk, 600000000); /* cpu 816 MHz, emc max */
else if (rate >= 456000)
clk_set_rate(emc_clk, 300000000); /* cpu 456 MHz, emc 150Mhz */
else
clk_set_rate(emc_clk, 100000000); /* emc 50Mhz */
for_each_online_cpu(freqs.cpu) for_each_online_cpu(freqs.cpu)
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
...@@ -92,7 +103,7 @@ static int tegra_update_cpu_speed(void) ...@@ -92,7 +103,7 @@ static int tegra_update_cpu_speed(void)
freqs.old, freqs.new); freqs.old, freqs.new);
#endif #endif
ret = clk_set_rate_cansleep(cpu_clk, freqs.new * 1000); ret = clk_set_rate(cpu_clk, freqs.new * 1000);
if (ret) { if (ret) {
pr_err("cpu-tegra: Failed to set cpu frequency to %d kHz\n", pr_err("cpu-tegra: Failed to set cpu frequency to %d kHz\n",
freqs.new); freqs.new);
...@@ -105,12 +116,30 @@ static int tegra_update_cpu_speed(void) ...@@ -105,12 +116,30 @@ static int tegra_update_cpu_speed(void)
return 0; return 0;
} }
static unsigned long tegra_cpu_highest_speed(void)
{
unsigned long rate = 0;
int i;
for_each_online_cpu(i)
rate = max(rate, target_cpu_speed[i]);
return rate;
}
static int tegra_target(struct cpufreq_policy *policy, static int tegra_target(struct cpufreq_policy *policy,
unsigned int target_freq, unsigned int target_freq,
unsigned int relation) unsigned int relation)
{ {
int idx; int idx;
unsigned int freq; unsigned int freq;
int ret = 0;
mutex_lock(&tegra_cpu_lock);
if (is_suspended) {
ret = -EBUSY;
goto out;
}
cpufreq_frequency_table_target(policy, freq_table, target_freq, cpufreq_frequency_table_target(policy, freq_table, target_freq,
relation, &idx); relation, &idx);
...@@ -119,9 +148,34 @@ static int tegra_target(struct cpufreq_policy *policy, ...@@ -119,9 +148,34 @@ static int tegra_target(struct cpufreq_policy *policy,
target_cpu_speed[policy->cpu] = freq; target_cpu_speed[policy->cpu] = freq;
return tegra_update_cpu_speed(); ret = tegra_update_cpu_speed(tegra_cpu_highest_speed());
out:
mutex_unlock(&tegra_cpu_lock);
return ret;
} }
static int tegra_pm_notify(struct notifier_block *nb, unsigned long event,
void *dummy)
{
mutex_lock(&tegra_cpu_lock);
if (event == PM_SUSPEND_PREPARE) {
is_suspended = true;
pr_info("Tegra cpufreq suspend: setting frequency to %d kHz\n",
freq_table[0].frequency);
tegra_update_cpu_speed(freq_table[0].frequency);
} else if (event == PM_POST_SUSPEND) {
is_suspended = false;
}
mutex_unlock(&tegra_cpu_lock);
return NOTIFY_OK;
}
static struct notifier_block tegra_cpu_pm_notifier = {
.notifier_call = tegra_pm_notify,
};
static int tegra_cpu_init(struct cpufreq_policy *policy) static int tegra_cpu_init(struct cpufreq_policy *policy)
{ {
if (policy->cpu >= NUM_CPUS) if (policy->cpu >= NUM_CPUS)
...@@ -131,6 +185,15 @@ static int tegra_cpu_init(struct cpufreq_policy *policy) ...@@ -131,6 +185,15 @@ static int tegra_cpu_init(struct cpufreq_policy *policy)
if (IS_ERR(cpu_clk)) if (IS_ERR(cpu_clk))
return PTR_ERR(cpu_clk); return PTR_ERR(cpu_clk);
emc_clk = clk_get_sys("cpu", "emc");
if (IS_ERR(emc_clk)) {
clk_put(cpu_clk);
return PTR_ERR(emc_clk);
}
clk_enable(emc_clk);
clk_enable(cpu_clk);
cpufreq_frequency_table_cpuinfo(policy, freq_table); cpufreq_frequency_table_cpuinfo(policy, freq_table);
cpufreq_frequency_table_get_attr(freq_table, policy->cpu); cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
policy->cur = tegra_getspeed(policy->cpu); policy->cur = tegra_getspeed(policy->cpu);
...@@ -142,12 +205,17 @@ static int tegra_cpu_init(struct cpufreq_policy *policy) ...@@ -142,12 +205,17 @@ static int tegra_cpu_init(struct cpufreq_policy *policy)
policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
cpumask_copy(policy->related_cpus, cpu_possible_mask); cpumask_copy(policy->related_cpus, cpu_possible_mask);
if (policy->cpu == 0)
register_pm_notifier(&tegra_cpu_pm_notifier);
return 0; return 0;
} }
static int tegra_cpu_exit(struct cpufreq_policy *policy) static int tegra_cpu_exit(struct cpufreq_policy *policy)
{ {
cpufreq_frequency_table_cpuinfo(policy, freq_table); cpufreq_frequency_table_cpuinfo(policy, freq_table);
clk_disable(emc_clk);
clk_put(emc_clk);
clk_put(cpu_clk); clk_put(cpu_clk);
return 0; return 0;
} }
......
This diff is collapsed.
/*
* Copyright (C) 2010,2011 Google, Inc.
*
* Author:
* Colin Cross <ccross@android.com>
* Erik Gilling <ccross@android.com>
*
* 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.
*
*/
#ifndef __MACH_TEGRA_DEVICES_H
#define __MACH_TEGRA_DEVICES_H
#include <linux/platform_device.h>
extern struct platform_device tegra_sdhci_device1;
extern struct platform_device tegra_sdhci_device2;
extern struct platform_device tegra_sdhci_device3;
extern struct platform_device tegra_sdhci_device4;
extern struct platform_device tegra_i2c_device1;
extern struct platform_device tegra_i2c_device2;
extern struct platform_device tegra_i2c_device3;
extern struct platform_device tegra_i2c_device4;
extern struct platform_device tegra_spi_device1;
extern struct platform_device tegra_spi_device2;
extern struct platform_device tegra_spi_device3;
extern struct platform_device tegra_spi_device4;
extern struct platform_device tegra_ehci1_device;
extern struct platform_device tegra_ehci2_device;
extern struct platform_device tegra_ehci3_device;
extern struct platform_device tegra_uarta_device;
extern struct platform_device tegra_uartb_device;
extern struct platform_device tegra_uartc_device;
extern struct platform_device tegra_uartd_device;
extern struct platform_device tegra_uarte_device;
extern struct platform_device tegra_pmu_device;
#endif
This diff is collapsed.
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <mach/iomap.h> #include <mach/iomap.h>
#include <mach/suspend.h>
#define GPIO_BANK(x) ((x) >> 5) #define GPIO_BANK(x) ((x) >> 5)
#define GPIO_PORT(x) (((x) >> 3) & 0x3) #define GPIO_PORT(x) (((x) >> 3) & 0x3)
...@@ -380,6 +381,20 @@ static int __init tegra_gpio_init(void) ...@@ -380,6 +381,20 @@ static int __init tegra_gpio_init(void)
postcore_initcall(tegra_gpio_init); postcore_initcall(tegra_gpio_init);
void __init tegra_gpio_config(struct tegra_gpio_table *table, int num)
{
int i;
for (i = 0; i < num; i++) {
int gpio = table[i].gpio;
if (table[i].enable)
tegra_gpio_enable(gpio);
else
tegra_gpio_disable(gpio);
}
}
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h> #include <linux/debugfs.h>
......
...@@ -25,9 +25,7 @@ struct clk; ...@@ -25,9 +25,7 @@ struct clk;
void tegra_periph_reset_deassert(struct clk *c); void tegra_periph_reset_deassert(struct clk *c);
void tegra_periph_reset_assert(struct clk *c); void tegra_periph_reset_assert(struct clk *c);
int clk_enable_cansleep(struct clk *clk); unsigned long clk_get_rate_all_locked(struct clk *c);
void clk_disable_cansleep(struct clk *clk); void tegra_sdmmc_tap_delay(struct clk *c, int delay);
int clk_set_rate_cansleep(struct clk *clk, unsigned long rate);
int clk_set_parent_cansleep(struct clk *clk, struct clk *parent);
#endif #endif
...@@ -19,30 +19,15 @@ ...@@ -19,30 +19,15 @@
*/ */
#include <mach/io.h> #include <mach/io.h>
#include <mach/iomap.h>
.macro addruart, rp, rv .macro addruart, rp, rv
ldr \rp, =IO_APB_PHYS @ physical ldr \rp, =IO_APB_PHYS @ physical
ldr \rv, =IO_APB_VIRT @ virtual ldr \rv, =IO_APB_VIRT @ virtual
#if defined(CONFIG_TEGRA_DEBUG_UART_NONE) orr \rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF)
#error "A debug UART must be selected in the kernel config to use DEBUG_LL" orr \rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF00)
#elif defined(CONFIG_TEGRA_DEBUG_UARTA) orr \rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF)
orr \rp, \rp, #0x6000 orr \rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF00)
orr \rv, \rv, #0x6000
#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
orr \rp, \rp, #0x6000
orr \rp, \rp, #0x40
orr \rv, \rv, #0x6000
orr \rv, \rv, #0x40
#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
orr \rp, \rp, #0x6200
orr \rv, \rv, #0x6200
#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
orr \rp, \rp, #0x6300
orr \rv, \rv, #0x6300
#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
orr \rp, \rp, #0x6400
orr \rv, \rv, #0x6400
#endif
.endm .endm
#define UART_SHIFT 2 #define UART_SHIFT 2
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#ifndef __MACH_TEGRA_GPIO_H #ifndef __MACH_TEGRA_GPIO_H
#define __MACH_TEGRA_GPIO_H #define __MACH_TEGRA_GPIO_H
#include <linux/init.h>
#include <mach/irqs.h> #include <mach/irqs.h>
#define TEGRA_NR_GPIOS INT_GPIO_NR #define TEGRA_NR_GPIOS INT_GPIO_NR
...@@ -31,7 +32,7 @@ ...@@ -31,7 +32,7 @@
#define gpio_cansleep __gpio_cansleep #define gpio_cansleep __gpio_cansleep
#define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio)) #define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio))
#define TEGRA_IRQ_TO_GPIO(irq) ((gpio) - INT_GPIO_BASE) #define TEGRA_IRQ_TO_GPIO(irq) ((irq) - INT_GPIO_BASE)
static inline int gpio_to_irq(unsigned int gpio) static inline int gpio_to_irq(unsigned int gpio)
{ {
...@@ -47,6 +48,12 @@ static inline int irq_to_gpio(unsigned int irq) ...@@ -47,6 +48,12 @@ static inline int irq_to_gpio(unsigned int irq)
return -EINVAL; return -EINVAL;
} }
struct tegra_gpio_table {
int gpio; /* GPIO number */
bool enable; /* Enable for GPIO at init? */
};
void tegra_gpio_config(struct tegra_gpio_table *table, int num);
void tegra_gpio_enable(int gpio); void tegra_gpio_enable(int gpio);
void tegra_gpio_disable(int gpio); void tegra_gpio_disable(int gpio);
......
/*
* arch/arm/mach-tegra/include/mach/harmony_audio.h
*
* Copyright 2011 NVIDIA, Inc.
*
* 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.
*
*/
struct harmony_audio_platform_data {
int gpio_spkr_en;
int gpio_hp_det;
int gpio_int_mic_en;
int gpio_ext_mic_en;
};
...@@ -26,6 +26,9 @@ ...@@ -26,6 +26,9 @@
#define TEGRA_IRAM_BASE 0x40000000 #define TEGRA_IRAM_BASE 0x40000000
#define TEGRA_IRAM_SIZE SZ_256K #define TEGRA_IRAM_SIZE SZ_256K
#define TEGRA_HOST1X_BASE 0x50000000
#define TEGRA_HOST1X_SIZE 0x24000
#define TEGRA_ARM_PERIF_BASE 0x50040000 #define TEGRA_ARM_PERIF_BASE 0x50040000
#define TEGRA_ARM_PERIF_SIZE SZ_8K #define TEGRA_ARM_PERIF_SIZE SZ_8K
...@@ -35,12 +38,30 @@ ...@@ -35,12 +38,30 @@
#define TEGRA_ARM_INT_DIST_BASE 0x50041000 #define TEGRA_ARM_INT_DIST_BASE 0x50041000
#define TEGRA_ARM_INT_DIST_SIZE SZ_4K #define TEGRA_ARM_INT_DIST_SIZE SZ_4K
#define TEGRA_MPE_BASE 0x54040000
#define TEGRA_MPE_SIZE SZ_256K
#define TEGRA_VI_BASE 0x54080000
#define TEGRA_VI_SIZE SZ_256K
#define TEGRA_ISP_BASE 0x54100000
#define TEGRA_ISP_SIZE SZ_256K
#define TEGRA_DISPLAY_BASE 0x54200000 #define TEGRA_DISPLAY_BASE 0x54200000
#define TEGRA_DISPLAY_SIZE SZ_256K #define TEGRA_DISPLAY_SIZE SZ_256K
#define TEGRA_DISPLAY2_BASE 0x54240000 #define TEGRA_DISPLAY2_BASE 0x54240000
#define TEGRA_DISPLAY2_SIZE SZ_256K #define TEGRA_DISPLAY2_SIZE SZ_256K
#define TEGRA_HDMI_BASE 0x54280000
#define TEGRA_HDMI_SIZE SZ_256K
#define TEGRA_GART_BASE 0x58000000
#define TEGRA_GART_SIZE SZ_32M
#define TEGRA_RES_SEMA_BASE 0x60001000
#define TEGRA_RES_SEMA_SIZE SZ_4K
#define TEGRA_PRIMARY_ICTLR_BASE 0x60004000 #define TEGRA_PRIMARY_ICTLR_BASE 0x60004000
#define TEGRA_PRIMARY_ICTLR_SIZE SZ_64 #define TEGRA_PRIMARY_ICTLR_SIZE SZ_64
...@@ -140,6 +161,18 @@ ...@@ -140,6 +161,18 @@
#define TEGRA_PWFM_BASE 0x7000A000 #define TEGRA_PWFM_BASE 0x7000A000
#define TEGRA_PWFM_SIZE SZ_256 #define TEGRA_PWFM_SIZE SZ_256
#define TEGRA_PWFM0_BASE 0x7000A000
#define TEGRA_PWFM0_SIZE 4
#define TEGRA_PWFM1_BASE 0x7000A010
#define TEGRA_PWFM1_SIZE 4
#define TEGRA_PWFM2_BASE 0x7000A020
#define TEGRA_PWFM2_SIZE 4
#define TEGRA_PWFM3_BASE 0x7000A030
#define TEGRA_PWFM3_SIZE 4
#define TEGRA_MIPI_BASE 0x7000B000 #define TEGRA_MIPI_BASE 0x7000B000
#define TEGRA_MIPI_SIZE SZ_256 #define TEGRA_MIPI_SIZE SZ_256
...@@ -221,4 +254,18 @@ ...@@ -221,4 +254,18 @@
#define TEGRA_SDMMC4_BASE 0xC8000600 #define TEGRA_SDMMC4_BASE 0xC8000600
#define TEGRA_SDMMC4_SIZE SZ_512 #define TEGRA_SDMMC4_SIZE SZ_512
#if defined(CONFIG_TEGRA_DEBUG_UART_NONE)
# define TEGRA_DEBUG_UART_BASE 0
#elif defined(CONFIG_TEGRA_DEBUG_UARTA)
# define TEGRA_DEBUG_UART_BASE TEGRA_UARTA_BASE
#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
# define TEGRA_DEBUG_UART_BASE TEGRA_UARTB_BASE
#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
# define TEGRA_DEBUG_UART_BASE TEGRA_UARTC_BASE
#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
# define TEGRA_DEBUG_UART_BASE TEGRA_UARTD_BASE
#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
# define TEGRA_DEBUG_UART_BASE TEGRA_UARTE_BASE
#endif
#endif #endif
...@@ -88,7 +88,7 @@ ...@@ -88,7 +88,7 @@
#define INT_SYS_STATS_MON (INT_SEC_BASE + 22) #define INT_SYS_STATS_MON (INT_SEC_BASE + 22)
#define INT_GPIO5 (INT_SEC_BASE + 23) #define INT_GPIO5 (INT_SEC_BASE + 23)
#define INT_CPU0_PMU_INTR (INT_SEC_BASE + 24) #define INT_CPU0_PMU_INTR (INT_SEC_BASE + 24)
#define INT_CPU2_PMU_INTR (INT_SEC_BASE + 25) #define INT_CPU1_PMU_INTR (INT_SEC_BASE + 25)
#define INT_SEC_RES_26 (INT_SEC_BASE + 26) #define INT_SEC_RES_26 (INT_SEC_BASE + 26)
#define INT_S_LINK1 (INT_SEC_BASE + 27) #define INT_S_LINK1 (INT_SEC_BASE + 27)
#define INT_APB_DMA_COP (INT_SEC_BASE + 28) #define INT_APB_DMA_COP (INT_SEC_BASE + 28)
...@@ -166,10 +166,18 @@ ...@@ -166,10 +166,18 @@
#define INT_QUAD_RES_30 (INT_QUAD_BASE + 30) #define INT_QUAD_RES_30 (INT_QUAD_BASE + 30)
#define INT_QUAD_RES_31 (INT_QUAD_BASE + 31) #define INT_QUAD_RES_31 (INT_QUAD_BASE + 31)
#define INT_GPIO_BASE (INT_QUAD_BASE + 32) #define INT_MAIN_NR (INT_QUAD_BASE + 32 - INT_PRI_BASE)
#define INT_GPIO_BASE (INT_PRI_BASE + INT_MAIN_NR)
#define INT_GPIO_NR (28 * 8) #define INT_GPIO_NR (28 * 8)
#define NR_IRQS (INT_GPIO_BASE + INT_GPIO_NR) #define TEGRA_NR_IRQS (INT_GPIO_BASE + INT_GPIO_NR)
#define INT_BOARD_BASE TEGRA_NR_IRQS
#define NR_BOARD_IRQS 32
#define NR_IRQS (INT_BOARD_BASE + NR_BOARD_IRQS)
#endif #endif
#endif #endif
...@@ -27,5 +27,9 @@ int tegra_legacy_force_irq_status(unsigned int irq); ...@@ -27,5 +27,9 @@ int tegra_legacy_force_irq_status(unsigned int irq);
void tegra_legacy_select_fiq(unsigned int irq, bool fiq); void tegra_legacy_select_fiq(unsigned int irq, bool fiq);
unsigned long tegra_legacy_vfiq(int nr); unsigned long tegra_legacy_vfiq(int nr);
unsigned long tegra_legacy_class(int nr); unsigned long tegra_legacy_class(int nr);
int tegra_legacy_irq_set_wake(int irq, int enable);
void tegra_legacy_irq_set_lp1_wake_mask(void);
void tegra_legacy_irq_restore_mask(void);
void tegra_init_legacy_irq(void);
#endif #endif
...@@ -167,6 +167,16 @@ enum tegra_drive_pingroup { ...@@ -167,6 +167,16 @@ enum tegra_drive_pingroup {
TEGRA_DRIVE_PINGROUP_XM2D, TEGRA_DRIVE_PINGROUP_XM2D,
TEGRA_DRIVE_PINGROUP_XM2CLK, TEGRA_DRIVE_PINGROUP_XM2CLK,
TEGRA_DRIVE_PINGROUP_MEMCOMP, TEGRA_DRIVE_PINGROUP_MEMCOMP,
TEGRA_DRIVE_PINGROUP_SDIO1,
TEGRA_DRIVE_PINGROUP_CRT,
TEGRA_DRIVE_PINGROUP_DDC,
TEGRA_DRIVE_PINGROUP_GMA,
TEGRA_DRIVE_PINGROUP_GMB,
TEGRA_DRIVE_PINGROUP_GMC,
TEGRA_DRIVE_PINGROUP_GMD,
TEGRA_DRIVE_PINGROUP_GME,
TEGRA_DRIVE_PINGROUP_OWR,
TEGRA_DRIVE_PINGROUP_UAD,
TEGRA_MAX_DRIVE_PINGROUP, TEGRA_MAX_DRIVE_PINGROUP,
}; };
......
/*
* drivers/regulator/tegra-regulator.c
*
* Copyright (c) 2010 Google, Inc
*
* Author:
* Colin Cross <ccross@google.com>
*
* 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.
*
*/
#ifndef _MACH_TEGRA_POWERGATE_H_
#define _MACH_TEGRA_POWERGATE_H_
#define TEGRA_POWERGATE_CPU 0
#define TEGRA_POWERGATE_3D 1
#define TEGRA_POWERGATE_VENC 2
#define TEGRA_POWERGATE_PCIE 3
#define TEGRA_POWERGATE_VDEC 4
#define TEGRA_POWERGATE_L2 5
#define TEGRA_POWERGATE_MPE 6
#define TEGRA_NUM_POWERGATE 7
int tegra_powergate_power_on(int id);
int tegra_powergate_power_off(int id);
bool tegra_powergate_is_powered(int id);
int tegra_powergate_remove_clamping(int id);
/* Must be called with clk disabled, and returns with clk enabled */
int tegra_powergate_sequence_power_up(int id, struct clk *clk);
#endif /* _MACH_TEGRA_POWERGATE_H_ */
/* /*
* arch/arm/mach-tegra/tegra2_dvfs.c * arch/arm/mach-tegra/include/mach/suspend.h
* *
* Copyright (C) 2010 Google, Inc. * Copyright (C) 2010 Google, Inc.
* *
...@@ -17,70 +17,22 @@ ...@@ -17,70 +17,22 @@
* *
*/ */
#include <linux/kernel.h>
#include "clock.h" #ifndef _MACH_TEGRA_SUSPEND_H_
#include "tegra2_dvfs.h" #define _MACH_TEGRA_SUSPEND_H_
static struct dvfs_table virtual_cpu_process_0[] = { void tegra_pinmux_suspend(void);
{314000000, 750}, void tegra_irq_suspend(void);
{456000000, 825}, void tegra_gpio_suspend(void);
{608000000, 900}, void tegra_clk_suspend(void);
{760000000, 975}, void tegra_dma_suspend(void);
{817000000, 1000}, void tegra_timer_suspend(void);
{912000000, 1050},
{1000000000, 1100},
{0, 0},
};
static struct dvfs_table virtual_cpu_process_1[] = { void tegra_pinmux_resume(void);
{314000000, 750}, void tegra_irq_resume(void);
{456000000, 825}, void tegra_gpio_resume(void);
{618000000, 900}, void tegra_clk_resume(void);
{770000000, 975}, void tegra_dma_resume(void);
{827000000, 1000}, void tegra_timer_resume(void);
{922000000, 1050},
{1000000000, 1100},
{0, 0},
};
static struct dvfs_table virtual_cpu_process_2[] = { #endif /* _MACH_TEGRA_SUSPEND_H_ */
{494000000, 750},
{675000000, 825},
{817000000, 875},
{922000000, 925},
{1000000000, 975},
{0, 0},
};
static struct dvfs_table virtual_cpu_process_3[] = {
{730000000, 750},
{760000000, 775},
{845000000, 800},
{1000000000, 875},
{0, 0},
};
struct dvfs tegra_dvfs_virtual_cpu_dvfs = {
.reg_id = "vdd_cpu",
.process_id_table = {
{
.process_id = 0,
.table = virtual_cpu_process_0,
},
{
.process_id = 1,
.table = virtual_cpu_process_1,
},
{
.process_id = 2,
.table = virtual_cpu_process_2,
},
{
.process_id = 3,
.table = virtual_cpu_process_3,
},
},
.process_id_table_length = 4,
.cpu = 1,
};
...@@ -24,16 +24,10 @@ ...@@ -24,16 +24,10 @@
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/iomap.h> #include <mach/iomap.h>
static inline void arch_idle(void) extern void (*arch_reset)(char mode, const char *cmd);
{
}
static inline void arch_reset(char mode, const char *cmd) static inline void arch_idle(void)
{ {
void __iomem *reset = IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x04);
u32 reg = readl(reset);
reg |= 0x04;
writel(reg, reset);
} }
#endif #endif
...@@ -26,23 +26,9 @@ ...@@ -26,23 +26,9 @@
#include <mach/iomap.h> #include <mach/iomap.h>
#if defined(CONFIG_TEGRA_DEBUG_UARTA)
#define DEBUG_UART_BASE TEGRA_UARTA_BASE
#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
#define DEBUG_UART_BASE TEGRA_UARTB_BASE
#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
#define DEBUG_UART_BASE TEGRA_UARTC_BASE
#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
#define DEBUG_UART_BASE TEGRA_UARTD_BASE
#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
#define DEBUG_UART_BASE TEGRA_UARTE_BASE
#else
#define DEBUG_UART_BASE NULL
#endif
static void putc(int c) static void putc(int c)
{ {
volatile u8 *uart = (volatile u8 *)DEBUG_UART_BASE; volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE;
int shift = 2; int shift = 2;
if (uart == NULL) if (uart == NULL)
...@@ -59,7 +45,7 @@ static inline void flush(void) ...@@ -59,7 +45,7 @@ static inline void flush(void)
static inline void arch_decomp_setup(void) static inline void arch_decomp_setup(void)
{ {
volatile u8 *uart = (volatile u8 *)DEBUG_UART_BASE; volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE;
int shift = 2; int shift = 2;
if (uart == NULL) if (uart == NULL)
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
...@@ -26,73 +27,119 @@ ...@@ -26,73 +27,119 @@
#include <asm/hardware/gic.h> #include <asm/hardware/gic.h>
#include <mach/iomap.h> #include <mach/iomap.h>
#include <mach/legacy_irq.h>
#include <mach/suspend.h>
#include "board.h" #include "board.h"
#define INT_SYS_NR (INT_GPIO_BASE - INT_PRI_BASE) #define PMC_CTRL 0x0
#define INT_SYS_SZ (INT_SEC_BASE - INT_PRI_BASE) #define PMC_CTRL_LATCH_WAKEUPS (1 << 5)
#define PPI_NR ((INT_SYS_NR+INT_SYS_SZ-1)/INT_SYS_SZ) #define PMC_WAKE_MASK 0xc
#define PMC_WAKE_LEVEL 0x10
#define PMC_WAKE_STATUS 0x14
#define PMC_SW_WAKE_STATUS 0x18
#define PMC_DPD_SAMPLE 0x20
#define APBDMA_IRQ_STA_CPU 0x14 static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
#define APBDMA_IRQ_MASK_SET 0x20
#define APBDMA_IRQ_MASK_CLR 0x24
#define ICTLR_CPU_IER 0x20 static u32 tegra_lp0_wake_enb;
#define ICTLR_CPU_IER_SET 0x24 static u32 tegra_lp0_wake_level;
#define ICTLR_CPU_IER_CLR 0x28 static u32 tegra_lp0_wake_level_any;
#define ICTLR_CPU_IEP_CLASS 0x2c
#define ICTLR_COP_IER 0x30
#define ICTLR_COP_IER_SET 0x34
#define ICTLR_COP_IER_CLR 0x38
#define ICTLR_COP_IEP_CLASS 0x3c
static void (*tegra_gic_mask_irq)(struct irq_data *d); static void (*tegra_gic_mask_irq)(struct irq_data *d);
static void (*tegra_gic_unmask_irq)(struct irq_data *d); static void (*tegra_gic_unmask_irq)(struct irq_data *d);
static void (*tegra_gic_ack_irq)(struct irq_data *d);
#define irq_to_ictlr(irq) (((irq) - 32) >> 5) /* ensures that sufficient time is passed for a register write to
static void __iomem *tegra_ictlr_base = IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE); * serialize into the 32KHz domain */
#define ictlr_to_virt(ictlr) (tegra_ictlr_base + (ictlr) * 0x100) static void pmc_32kwritel(u32 val, unsigned long offs)
{
writel(val, pmc + offs);
udelay(130);
}
int tegra_set_lp1_wake(int irq, int enable)
{
return tegra_legacy_irq_set_wake(irq, enable);
}
void tegra_set_lp0_wake_pads(u32 wake_enb, u32 wake_level, u32 wake_any)
{
u32 temp;
u32 status;
u32 lvl;
wake_level &= wake_enb;
wake_any &= wake_enb;
wake_level |= (tegra_lp0_wake_level & tegra_lp0_wake_enb);
wake_any |= (tegra_lp0_wake_level_any & tegra_lp0_wake_enb);
wake_enb |= tegra_lp0_wake_enb;
pmc_32kwritel(0, PMC_SW_WAKE_STATUS);
temp = readl(pmc + PMC_CTRL);
temp |= PMC_CTRL_LATCH_WAKEUPS;
pmc_32kwritel(temp, PMC_CTRL);
temp &= ~PMC_CTRL_LATCH_WAKEUPS;
pmc_32kwritel(temp, PMC_CTRL);
status = readl(pmc + PMC_SW_WAKE_STATUS);
lvl = readl(pmc + PMC_WAKE_LEVEL);
/* flip the wakeup trigger for any-edge triggered pads
* which are currently asserting as wakeups */
lvl ^= status;
lvl &= wake_any;
wake_level |= lvl;
writel(wake_level, pmc + PMC_WAKE_LEVEL);
/* Enable DPD sample to trigger sampling pads data and direction
* in which pad will be driven during lp0 mode*/
writel(0x1, pmc + PMC_DPD_SAMPLE);
writel(wake_enb, pmc + PMC_WAKE_MASK);
}
static void tegra_mask(struct irq_data *d) static void tegra_mask(struct irq_data *d)
{ {
void __iomem *addr = ictlr_to_virt(irq_to_ictlr(d->irq));
tegra_gic_mask_irq(d); tegra_gic_mask_irq(d);
writel(1 << (d->irq & 31), addr+ICTLR_CPU_IER_CLR); tegra_legacy_mask_irq(d->irq);
} }
static void tegra_unmask(struct irq_data *d) static void tegra_unmask(struct irq_data *d)
{ {
void __iomem *addr = ictlr_to_virt(irq_to_ictlr(d->irq));
tegra_gic_unmask_irq(d); tegra_gic_unmask_irq(d);
writel(1<<(d->irq&31), addr+ICTLR_CPU_IER_SET); tegra_legacy_unmask_irq(d->irq);
} }
#ifdef CONFIG_PM static void tegra_ack(struct irq_data *d)
{
tegra_legacy_force_irq_clr(d->irq);
tegra_gic_ack_irq(d);
}
static int tegra_set_wake(struct irq_data *d, unsigned int on) static int tegra_retrigger(struct irq_data *d)
{ {
return 0; tegra_legacy_force_irq_set(d->irq);
return 1;
} }
#endif
static struct irq_chip tegra_irq = { static struct irq_chip tegra_irq = {
.name = "PPI", .name = "PPI",
.irq_mask = tegra_mask, .irq_ack = tegra_ack,
.irq_unmask = tegra_unmask, .irq_mask = tegra_mask,
#ifdef CONFIG_PM .irq_unmask = tegra_unmask,
.irq_set_wake = tegra_set_wake, .irq_retrigger = tegra_retrigger,
#endif
}; };
void __init tegra_init_irq(void) void __init tegra_init_irq(void)
{ {
struct irq_chip *gic; struct irq_chip *gic;
unsigned int i; unsigned int i;
int irq;
for (i = 0; i < PPI_NR; i++) { tegra_init_legacy_irq();
writel(~0, ictlr_to_virt(i) + ICTLR_CPU_IER_CLR);
writel(0, ictlr_to_virt(i) + ICTLR_CPU_IEP_CLASS);
}
gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE),
IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100)); IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
...@@ -100,72 +147,15 @@ void __init tegra_init_irq(void) ...@@ -100,72 +147,15 @@ void __init tegra_init_irq(void)
gic = get_irq_chip(29); gic = get_irq_chip(29);
tegra_gic_unmask_irq = gic->irq_unmask; tegra_gic_unmask_irq = gic->irq_unmask;
tegra_gic_mask_irq = gic->irq_mask; tegra_gic_mask_irq = gic->irq_mask;
tegra_irq.irq_ack = gic->irq_ack; tegra_gic_ack_irq = gic->irq_ack;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
tegra_irq.irq_set_affinity = gic->irq_set_affinity; tegra_irq.irq_set_affinity = gic->irq_set_affinity;
#endif #endif
for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) { for (i = 0; i < INT_MAIN_NR; i++) {
set_irq_chip(i, &tegra_irq); irq = INT_PRI_BASE + i;
set_irq_handler(i, handle_level_irq); set_irq_chip(irq, &tegra_irq);
set_irq_flags(i, IRQF_VALID); set_irq_handler(irq, handle_level_irq);
set_irq_flags(irq, IRQF_VALID);
} }
} }
#ifdef CONFIG_PM
static u32 cop_ier[PPI_NR];
static u32 cpu_ier[PPI_NR];
static u32 cpu_iep[PPI_NR];
void tegra_irq_suspend(void)
{
unsigned long flags;
int i;
for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
struct irq_desc *desc = irq_to_desc(i);
if (!desc)
continue;
if (desc->status & IRQ_WAKEUP) {
pr_debug("irq %d is wakeup\n", i);
continue;
}
disable_irq(i);
}
local_irq_save(flags);
for (i = 0; i < PPI_NR; i++) {
void __iomem *ictlr = ictlr_to_virt(i);
cpu_ier[i] = readl(ictlr + ICTLR_CPU_IER);
cpu_iep[i] = readl(ictlr + ICTLR_CPU_IEP_CLASS);
cop_ier[i] = readl(ictlr + ICTLR_COP_IER);
writel(~0, ictlr + ICTLR_COP_IER_CLR);
}
local_irq_restore(flags);
}
void tegra_irq_resume(void)
{
unsigned long flags;
int i;
local_irq_save(flags);
for (i = 0; i < PPI_NR; i++) {
void __iomem *ictlr = ictlr_to_virt(i);
writel(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
writel(~0ul, ictlr + ICTLR_CPU_IER_CLR);
writel(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
writel(0, ictlr + ICTLR_COP_IEP_CLASS);
writel(~0ul, ictlr + ICTLR_COP_IER_CLR);
writel(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
}
local_irq_restore(flags);
for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
struct irq_desc *desc = irq_to_desc(i);
if (!desc || (desc->status & IRQ_WAKEUP))
continue;
enable_irq(i);
}
}
#endif
...@@ -18,17 +18,30 @@ ...@@ -18,17 +18,30 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <mach/iomap.h> #include <mach/iomap.h>
#include <mach/irqs.h>
#include <mach/legacy_irq.h> #include <mach/legacy_irq.h>
#define ICTLR_CPU_IER 0x20 #define INT_SYS_NR (INT_GPIO_BASE - INT_PRI_BASE)
#define ICTLR_CPU_IER_SET 0x24 #define INT_SYS_SZ (INT_SEC_BASE - INT_PRI_BASE)
#define ICTLR_CPU_IER_CLR 0x28 #define PPI_NR ((INT_SYS_NR+INT_SYS_SZ-1)/INT_SYS_SZ)
#define ICTLR_CPU_IEP_CLASS 0x2C
#define ICTLR_CPU_IEP_VFIQ 0x08 #define ICTLR_CPU_IEP_VFIQ 0x08
#define ICTLR_CPU_IEP_FIR 0x14 #define ICTLR_CPU_IEP_FIR 0x14
#define ICTLR_CPU_IEP_FIR_SET 0x18 #define ICTLR_CPU_IEP_FIR_SET 0x18
#define ICTLR_CPU_IEP_FIR_CLR 0x1c #define ICTLR_CPU_IEP_FIR_CLR 0x1c
#define ICTLR_CPU_IER 0x20
#define ICTLR_CPU_IER_SET 0x24
#define ICTLR_CPU_IER_CLR 0x28
#define ICTLR_CPU_IEP_CLASS 0x2C
#define ICTLR_COP_IER 0x30
#define ICTLR_COP_IER_SET 0x34
#define ICTLR_COP_IER_CLR 0x38
#define ICTLR_COP_IEP_CLASS 0x3c
#define NUM_ICTLRS 4
static void __iomem *ictlr_reg_base[] = { static void __iomem *ictlr_reg_base[] = {
IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE), IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE),
IO_ADDRESS(TEGRA_SECONDARY_ICTLR_BASE), IO_ADDRESS(TEGRA_SECONDARY_ICTLR_BASE),
...@@ -36,6 +49,9 @@ static void __iomem *ictlr_reg_base[] = { ...@@ -36,6 +49,9 @@ static void __iomem *ictlr_reg_base[] = {
IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE), IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE),
}; };
static u32 tegra_legacy_wake_mask[4];
static u32 tegra_legacy_saved_mask[4];
/* When going into deep sleep, the CPU is powered down, taking the GIC with it /* When going into deep sleep, the CPU is powered down, taking the GIC with it
In order to wake, the wake interrupts need to be enabled in the legacy In order to wake, the wake interrupts need to be enabled in the legacy
interrupt controller. */ interrupt controller. */
...@@ -112,3 +128,88 @@ unsigned long tegra_legacy_class(int nr) ...@@ -112,3 +128,88 @@ unsigned long tegra_legacy_class(int nr)
base = ictlr_reg_base[nr]; base = ictlr_reg_base[nr];
return readl(base + ICTLR_CPU_IEP_CLASS); return readl(base + ICTLR_CPU_IEP_CLASS);
} }
int tegra_legacy_irq_set_wake(int irq, int enable)
{
irq -= 32;
if (enable)
tegra_legacy_wake_mask[irq >> 5] |= 1 << (irq & 31);
else
tegra_legacy_wake_mask[irq >> 5] &= ~(1 << (irq & 31));
return 0;
}
void tegra_legacy_irq_set_lp1_wake_mask(void)
{
void __iomem *base;
int i;
for (i = 0; i < NUM_ICTLRS; i++) {
base = ictlr_reg_base[i];
tegra_legacy_saved_mask[i] = readl(base + ICTLR_CPU_IER);
writel(tegra_legacy_wake_mask[i], base + ICTLR_CPU_IER);
}
}
void tegra_legacy_irq_restore_mask(void)
{
void __iomem *base;
int i;
for (i = 0; i < NUM_ICTLRS; i++) {
base = ictlr_reg_base[i];
writel(tegra_legacy_saved_mask[i], base + ICTLR_CPU_IER);
}
}
void tegra_init_legacy_irq(void)
{
int i;
for (i = 0; i < NUM_ICTLRS; i++) {
void __iomem *ictlr = ictlr_reg_base[i];
writel(~0, ictlr + ICTLR_CPU_IER_CLR);
writel(0, ictlr + ICTLR_CPU_IEP_CLASS);
}
}
#ifdef CONFIG_PM
static u32 cop_ier[NUM_ICTLRS];
static u32 cpu_ier[NUM_ICTLRS];
static u32 cpu_iep[NUM_ICTLRS];
void tegra_irq_suspend(void)
{
unsigned long flags;
int i;
local_irq_save(flags);
for (i = 0; i < NUM_ICTLRS; i++) {
void __iomem *ictlr = ictlr_reg_base[i];
cpu_ier[i] = readl(ictlr + ICTLR_CPU_IER);
cpu_iep[i] = readl(ictlr + ICTLR_CPU_IEP_CLASS);
cop_ier[i] = readl(ictlr + ICTLR_COP_IER);
writel(~0, ictlr + ICTLR_COP_IER_CLR);
}
local_irq_restore(flags);
}
void tegra_irq_resume(void)
{
unsigned long flags;
int i;
local_irq_save(flags);
for (i = 0; i < NUM_ICTLRS; i++) {
void __iomem *ictlr = ictlr_reg_base[i];
writel(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
writel(~0ul, ictlr + ICTLR_CPU_IER_CLR);
writel(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
writel(0, ictlr + ICTLR_COP_IEP_CLASS);
writel(~0ul, ictlr + ICTLR_COP_IER_CLR);
writel(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
}
local_irq_restore(flags);
}
#endif
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <mach/pinmux.h> #include <mach/pinmux.h>
#include <mach/iomap.h> #include <mach/iomap.h>
#include <mach/clk.h> #include <mach/clk.h>
#include <mach/powergate.h>
/* register definitions */ /* register definitions */
#define AFI_OFFSET 0x3800 #define AFI_OFFSET 0x3800
...@@ -682,24 +683,41 @@ static void tegra_pcie_xclk_clamp(bool clamp) ...@@ -682,24 +683,41 @@ static void tegra_pcie_xclk_clamp(bool clamp)
pmc_writel(reg, PMC_SCRATCH42); pmc_writel(reg, PMC_SCRATCH42);
} }
static int tegra_pcie_power_on(void) static void tegra_pcie_power_off(void)
{ {
tegra_pcie_xclk_clamp(true);
tegra_periph_reset_assert(tegra_pcie.pcie_xclk); tegra_periph_reset_assert(tegra_pcie.pcie_xclk);
tegra_pcie_xclk_clamp(false); tegra_periph_reset_assert(tegra_pcie.afi_clk);
tegra_periph_reset_assert(tegra_pcie.pex_clk);
clk_enable(tegra_pcie.afi_clk); tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
clk_enable(tegra_pcie.pex_clk); tegra_pcie_xclk_clamp(true);
return clk_enable(tegra_pcie.pll_e);
} }
static void tegra_pcie_power_off(void) static int tegra_pcie_power_regate(void)
{ {
int err;
tegra_pcie_power_off();
tegra_pcie_xclk_clamp(true);
tegra_periph_reset_assert(tegra_pcie.pcie_xclk); tegra_periph_reset_assert(tegra_pcie.pcie_xclk);
tegra_periph_reset_assert(tegra_pcie.afi_clk); tegra_periph_reset_assert(tegra_pcie.afi_clk);
tegra_periph_reset_assert(tegra_pcie.pex_clk);
tegra_pcie_xclk_clamp(true); err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE,
tegra_pcie.pex_clk);
if (err) {
pr_err("PCIE: powerup sequence failed: %d\n", err);
return err;
}
tegra_periph_reset_deassert(tegra_pcie.afi_clk);
tegra_pcie_xclk_clamp(false);
clk_enable(tegra_pcie.afi_clk);
clk_enable(tegra_pcie.pex_clk);
return clk_enable(tegra_pcie.pll_e);
} }
static int tegra_pcie_clocks_get(void) static int tegra_pcie_clocks_get(void)
...@@ -759,7 +777,7 @@ static int __init tegra_pcie_get_resources(void) ...@@ -759,7 +777,7 @@ static int __init tegra_pcie_get_resources(void)
return err; return err;
} }
err = tegra_pcie_power_on(); err = tegra_pcie_power_regate();
if (err) { if (err) {
pr_err("PCIE: failed to power up: %d\n", err); pr_err("PCIE: failed to power up: %d\n", err);
goto err_pwr_on; goto err_pwr_on;
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <mach/iomap.h> #include <mach/iomap.h>
#include <mach/pinmux.h> #include <mach/pinmux.h>
#include <mach/suspend.h>
#define DRIVE_PINGROUP(pg_name, r) \ #define DRIVE_PINGROUP(pg_name, r) \
[TEGRA_DRIVE_PINGROUP_ ## pg_name] = { \ [TEGRA_DRIVE_PINGROUP_ ## pg_name] = { \
...@@ -65,6 +66,16 @@ const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE ...@@ -65,6 +66,16 @@ const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE
DRIVE_PINGROUP(XM2D, 0x8cc), DRIVE_PINGROUP(XM2D, 0x8cc),
DRIVE_PINGROUP(XM2CLK, 0x8d0), DRIVE_PINGROUP(XM2CLK, 0x8d0),
DRIVE_PINGROUP(MEMCOMP, 0x8d4), DRIVE_PINGROUP(MEMCOMP, 0x8d4),
DRIVE_PINGROUP(SDIO1, 0x8e0),
DRIVE_PINGROUP(CRT, 0x8ec),
DRIVE_PINGROUP(DDC, 0x8f0),
DRIVE_PINGROUP(GMA, 0x8f4),
DRIVE_PINGROUP(GMB, 0x8f8),
DRIVE_PINGROUP(GMC, 0x8fc),
DRIVE_PINGROUP(GMD, 0x900),
DRIVE_PINGROUP(GME, 0x904),
DRIVE_PINGROUP(OWR, 0x908),
DRIVE_PINGROUP(UAD, 0x90c),
}; };
#define PINGROUP(pg_name, vdd, f0, f1, f2, f3, f_safe, \ #define PINGROUP(pg_name, vdd, f0, f1, f2, f3, f_safe, \
...@@ -216,7 +227,8 @@ const struct tegra_pingroup_desc tegra_soc_pingroups[TEGRA_MAX_PINGROUP] = { ...@@ -216,7 +227,8 @@ const struct tegra_pingroup_desc tegra_soc_pingroups[TEGRA_MAX_PINGROUP] = {
#define PULLUPDOWN_REG_NUM 5 #define PULLUPDOWN_REG_NUM 5
static u32 pinmux_reg[TRISTATE_REG_NUM + PIN_MUX_CTL_REG_NUM + static u32 pinmux_reg[TRISTATE_REG_NUM + PIN_MUX_CTL_REG_NUM +
PULLUPDOWN_REG_NUM]; PULLUPDOWN_REG_NUM +
ARRAY_SIZE(tegra_soc_drive_pingroups)];
static inline unsigned long pg_readl(unsigned long offset) static inline unsigned long pg_readl(unsigned long offset)
{ {
...@@ -233,14 +245,17 @@ void tegra_pinmux_suspend(void) ...@@ -233,14 +245,17 @@ void tegra_pinmux_suspend(void)
unsigned int i; unsigned int i;
u32 *ctx = pinmux_reg; u32 *ctx = pinmux_reg;
for (i = 0; i < TRISTATE_REG_NUM; i++)
*ctx++ = pg_readl(TRISTATE_REG_A + i*4);
for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++) for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++)
*ctx++ = pg_readl(PIN_MUX_CTL_REG_A + i*4); *ctx++ = pg_readl(PIN_MUX_CTL_REG_A + i*4);
for (i = 0; i < PULLUPDOWN_REG_NUM; i++) for (i = 0; i < PULLUPDOWN_REG_NUM; i++)
*ctx++ = pg_readl(PULLUPDOWN_REG_A + i*4); *ctx++ = pg_readl(PULLUPDOWN_REG_A + i*4);
for (i = 0; i < TRISTATE_REG_NUM; i++)
*ctx++ = pg_readl(TRISTATE_REG_A + i*4);
for (i = 0; i < ARRAY_SIZE(tegra_soc_drive_pingroups); i++)
*ctx++ = pg_readl(tegra_soc_drive_pingroups[i].reg);
} }
void tegra_pinmux_resume(void) void tegra_pinmux_resume(void)
...@@ -256,5 +271,8 @@ void tegra_pinmux_resume(void) ...@@ -256,5 +271,8 @@ void tegra_pinmux_resume(void)
for (i = 0; i < TRISTATE_REG_NUM; i++) for (i = 0; i < TRISTATE_REG_NUM; i++)
pg_writel(*ctx++, TRISTATE_REG_A + i*4); pg_writel(*ctx++, TRISTATE_REG_A + i*4);
for (i = 0; i < ARRAY_SIZE(tegra_soc_drive_pingroups); i++)
pg_writel(*ctx++, tegra_soc_drive_pingroups[i].reg);
} }
#endif #endif
/*
* drivers/powergate/tegra-powergate.c
*
* Copyright (c) 2010 Google, Inc
*
* Author:
* Colin Cross <ccross@google.com>
*
* 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/clk.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/seq_file.h>
#include <linux/spinlock.h>
#include <mach/clk.h>
#include <mach/iomap.h>
#include <mach/powergate.h>
#define PWRGATE_TOGGLE 0x30
#define PWRGATE_TOGGLE_START (1 << 8)
#define REMOVE_CLAMPING 0x34
#define PWRGATE_STATUS 0x38
static DEFINE_SPINLOCK(tegra_powergate_lock);
static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
static u32 pmc_read(unsigned long reg)
{
return readl(pmc + reg);
}
static void pmc_write(u32 val, unsigned long reg)
{
writel(val, pmc + reg);
}
static int tegra_powergate_set(int id, bool new_state)
{
bool status;
unsigned long flags;
spin_lock_irqsave(&tegra_powergate_lock, flags);
status = pmc_read(PWRGATE_STATUS) & (1 << id);
if (status == new_state) {
spin_unlock_irqrestore(&tegra_powergate_lock, flags);
return -EINVAL;
}
pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
spin_unlock_irqrestore(&tegra_powergate_lock, flags);
return 0;
}
int tegra_powergate_power_on(int id)
{
if (id < 0 || id >= TEGRA_NUM_POWERGATE)
return -EINVAL;
return tegra_powergate_set(id, true);
}
int tegra_powergate_power_off(int id)
{
if (id < 0 || id >= TEGRA_NUM_POWERGATE)
return -EINVAL;
return tegra_powergate_set(id, false);
}
bool tegra_powergate_is_powered(int id)
{
u32 status;
if (id < 0 || id >= TEGRA_NUM_POWERGATE)
return -EINVAL;
status = pmc_read(PWRGATE_STATUS) & (1 << id);
return !!status;
}
int tegra_powergate_remove_clamping(int id)
{
u32 mask;
if (id < 0 || id >= TEGRA_NUM_POWERGATE)
return -EINVAL;
/*
* Tegra 2 has a bug where PCIE and VDE clamping masks are
* swapped relatively to the partition ids
*/
if (id == TEGRA_POWERGATE_VDEC)
mask = (1 << TEGRA_POWERGATE_PCIE);
else if (id == TEGRA_POWERGATE_PCIE)
mask = (1 << TEGRA_POWERGATE_VDEC);
else
mask = (1 << id);
pmc_write(mask, REMOVE_CLAMPING);
return 0;
}
/* Must be called with clk disabled, and returns with clk enabled */
int tegra_powergate_sequence_power_up(int id, struct clk *clk)
{
int ret;
tegra_periph_reset_assert(clk);
ret = tegra_powergate_power_on(id);
if (ret)
goto err_power;
ret = clk_enable(clk);
if (ret)
goto err_clk;
udelay(10);
ret = tegra_powergate_remove_clamping(id);
if (ret)
goto err_clamp;
udelay(10);
tegra_periph_reset_deassert(clk);
return 0;
err_clamp:
clk_disable(clk);
err_clk:
tegra_powergate_power_off(id);
err_power:
return ret;
}
#ifdef CONFIG_DEBUG_FS
static const char * const powergate_name[] = {
[TEGRA_POWERGATE_CPU] = "cpu",
[TEGRA_POWERGATE_3D] = "3d",
[TEGRA_POWERGATE_VENC] = "venc",
[TEGRA_POWERGATE_VDEC] = "vdec",
[TEGRA_POWERGATE_PCIE] = "pcie",
[TEGRA_POWERGATE_L2] = "l2",
[TEGRA_POWERGATE_MPE] = "mpe",
};
static int powergate_show(struct seq_file *s, void *data)
{
int i;
seq_printf(s, " powergate powered\n");
seq_printf(s, "------------------\n");
for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
seq_printf(s, " %9s %7s\n", powergate_name[i],
tegra_powergate_is_powered(i) ? "yes" : "no");
return 0;
}
static int powergate_open(struct inode *inode, struct file *file)
{
return single_open(file, powergate_show, inode->i_private);
}
static const struct file_operations powergate_fops = {
.open = powergate_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int __init powergate_debugfs_init(void)
{
struct dentry *d;
int err = -ENOMEM;
d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
&powergate_fops);
if (!d)
return -ENOMEM;
return err;
}
late_initcall(powergate_debugfs_init);
#endif
This diff is collapsed.
/*
* Copyright (C) 2011 Google, Inc.
*
* Author:
* Colin Cross <ccross@android.com>
*
* 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/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
#include <mach/iomap.h>
#include "tegra2_emc.h"
#ifdef CONFIG_TEGRA_EMC_SCALING_ENABLE
static bool emc_enable = true;
#else
static bool emc_enable;
#endif
module_param(emc_enable, bool, 0644);
static void __iomem *emc = IO_ADDRESS(TEGRA_EMC_BASE);
static const struct tegra_emc_table *tegra_emc_table;
static int tegra_emc_table_size;
static inline void emc_writel(u32 val, unsigned long addr)
{
writel(val, emc + addr);
}
static inline u32 emc_readl(unsigned long addr)
{
return readl(emc + addr);
}
static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
0x2c, /* RC */
0x30, /* RFC */
0x34, /* RAS */
0x38, /* RP */
0x3c, /* R2W */
0x40, /* W2R */
0x44, /* R2P */
0x48, /* W2P */
0x4c, /* RD_RCD */
0x50, /* WR_RCD */
0x54, /* RRD */
0x58, /* REXT */
0x5c, /* WDV */
0x60, /* QUSE */
0x64, /* QRST */
0x68, /* QSAFE */
0x6c, /* RDV */
0x70, /* REFRESH */
0x74, /* BURST_REFRESH_NUM */
0x78, /* PDEX2WR */
0x7c, /* PDEX2RD */
0x80, /* PCHG2PDEN */
0x84, /* ACT2PDEN */
0x88, /* AR2PDEN */
0x8c, /* RW2PDEN */
0x90, /* TXSR */
0x94, /* TCKE */
0x98, /* TFAW */
0x9c, /* TRPAB */
0xa0, /* TCLKSTABLE */
0xa4, /* TCLKSTOP */
0xa8, /* TREFBW */
0xac, /* QUSE_EXTRA */
0x114, /* FBIO_CFG6 */
0xb0, /* ODT_WRITE */
0xb4, /* ODT_READ */
0x104, /* FBIO_CFG5 */
0x2bc, /* CFG_DIG_DLL */
0x2c0, /* DLL_XFORM_DQS */
0x2c4, /* DLL_XFORM_QUSE */
0x2e0, /* ZCAL_REF_CNT */
0x2e4, /* ZCAL_WAIT_CNT */
0x2a8, /* AUTO_CAL_INTERVAL */
0x2d0, /* CFG_CLKTRIM_0 */
0x2d4, /* CFG_CLKTRIM_1 */
0x2d8, /* CFG_CLKTRIM_2 */
};
/* Select the closest EMC rate that is higher than the requested rate */
long tegra_emc_round_rate(unsigned long rate)
{
int i;
int best = -1;
unsigned long distance = ULONG_MAX;
if (!tegra_emc_table)
return -EINVAL;
if (!emc_enable)
return -EINVAL;
pr_debug("%s: %lu\n", __func__, rate);
/*
* The EMC clock rate is twice the bus rate, and the bus rate is
* measured in kHz
*/
rate = rate / 2 / 1000;
for (i = 0; i < tegra_emc_table_size; i++) {
if (tegra_emc_table[i].rate >= rate &&
(tegra_emc_table[i].rate - rate) < distance) {
distance = tegra_emc_table[i].rate - rate;
best = i;
}
}
if (best < 0)
return -EINVAL;
pr_debug("%s: using %lu\n", __func__, tegra_emc_table[best].rate);
return tegra_emc_table[best].rate * 2 * 1000;
}
/*
* The EMC registers have shadow registers. When the EMC clock is updated
* in the clock controller, the shadow registers are copied to the active
* registers, allowing glitchless memory bus frequency changes.
* This function updates the shadow registers for a new clock frequency,
* and relies on the clock lock on the emc clock to avoid races between
* multiple frequency changes
*/
int tegra_emc_set_rate(unsigned long rate)
{
int i;
int j;
if (!tegra_emc_table)
return -EINVAL;
/*
* The EMC clock rate is twice the bus rate, and the bus rate is
* measured in kHz
*/
rate = rate / 2 / 1000;
for (i = 0; i < tegra_emc_table_size; i++)
if (tegra_emc_table[i].rate == rate)
break;
if (i >= tegra_emc_table_size)
return -EINVAL;
pr_debug("%s: setting to %lu\n", __func__, rate);
for (j = 0; j < TEGRA_EMC_NUM_REGS; j++)
emc_writel(tegra_emc_table[i].regs[j], emc_reg_addr[j]);
emc_readl(tegra_emc_table[i].regs[TEGRA_EMC_NUM_REGS - 1]);
return 0;
}
void tegra_init_emc(const struct tegra_emc_table *table, int table_size)
{
tegra_emc_table = table;
tegra_emc_table_size = table_size;
}
/*
* Copyright (C) 2011 Google, Inc.
*
* Author:
* Colin Cross <ccross@android.com>
*
* 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.
*
*/
#define TEGRA_EMC_NUM_REGS 46
struct tegra_emc_table {
unsigned long rate;
u32 regs[TEGRA_EMC_NUM_REGS];
};
int tegra_emc_set_rate(unsigned long rate);
long tegra_emc_round_rate(unsigned long rate);
void tegra_init_emc(const struct tegra_emc_table *table, int table_size);
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/err.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
...@@ -33,10 +34,15 @@ ...@@ -33,10 +34,15 @@
#include <mach/iomap.h> #include <mach/iomap.h>
#include <mach/irqs.h> #include <mach/irqs.h>
#include <mach/suspend.h>
#include "board.h" #include "board.h"
#include "clock.h" #include "clock.h"
#define RTC_SECONDS 0x08
#define RTC_SHADOW_SECONDS 0x0c
#define RTC_MILLISECONDS 0x10
#define TIMERUS_CNTR_1US 0x10 #define TIMERUS_CNTR_1US 0x10
#define TIMERUS_USEC_CFG 0x14 #define TIMERUS_USEC_CFG 0x14
#define TIMERUS_CNTR_FREEZE 0x4c #define TIMERUS_CNTR_FREEZE 0x4c
...@@ -49,9 +55,11 @@ ...@@ -49,9 +55,11 @@
#define TIMER_PTV 0x0 #define TIMER_PTV 0x0
#define TIMER_PCR 0x4 #define TIMER_PCR 0x4
struct tegra_timer;
static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE); static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE);
static void __iomem *rtc_base = IO_ADDRESS(TEGRA_RTC_BASE);
static struct timespec persistent_ts;
static u64 persistent_ms, last_persistent_ms;
#define timer_writel(value, reg) \ #define timer_writel(value, reg) \
__raw_writel(value, (u32)timer_reg_base + (reg)) __raw_writel(value, (u32)timer_reg_base + (reg))
...@@ -132,6 +140,42 @@ static void notrace tegra_update_sched_clock(void) ...@@ -132,6 +140,42 @@ static void notrace tegra_update_sched_clock(void)
update_sched_clock(&cd, cyc, (u32)~0); update_sched_clock(&cd, cyc, (u32)~0);
} }
/*
* tegra_rtc_read - Reads the Tegra RTC registers
* Care must be taken that this funciton is not called while the
* tegra_rtc driver could be executing to avoid race conditions
* on the RTC shadow register
*/
u64 tegra_rtc_read_ms(void)
{
u32 ms = readl(rtc_base + RTC_MILLISECONDS);
u32 s = readl(rtc_base + RTC_SHADOW_SECONDS);
return (u64)s * MSEC_PER_SEC + ms;
}
/*
* read_persistent_clock - Return time from a persistent clock.
*
* Reads the time from a source which isn't disabled during PM, the
* 32k sync timer. Convert the cycles elapsed since last read into
* nsecs and adds to a monotonically increasing timespec.
* Care must be taken that this funciton is not called while the
* tegra_rtc driver could be executing to avoid race conditions
* on the RTC shadow register
*/
void read_persistent_clock(struct timespec *ts)
{
u64 delta;
struct timespec *tsp = &persistent_ts;
last_persistent_ms = persistent_ms;
persistent_ms = tegra_rtc_read_ms();
delta = persistent_ms - last_persistent_ms;
timespec_add_ns(tsp, delta * NSEC_PER_MSEC);
*ts = *tsp;
}
static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id) static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id)
{ {
struct clock_event_device *evt = (struct clock_event_device *)dev_id; struct clock_event_device *evt = (struct clock_event_device *)dev_id;
...@@ -150,9 +194,22 @@ static struct irqaction tegra_timer_irq = { ...@@ -150,9 +194,22 @@ static struct irqaction tegra_timer_irq = {
static void __init tegra_init_timer(void) static void __init tegra_init_timer(void)
{ {
struct clk *clk;
unsigned long rate = clk_measure_input_freq(); unsigned long rate = clk_measure_input_freq();
int ret; int ret;
clk = clk_get_sys("timer", NULL);
BUG_ON(IS_ERR(clk));
clk_enable(clk);
/*
* rtc registers are used by read_persistent_clock, keep the rtc clock
* enabled
*/
clk = clk_get_sys("rtc-tegra", NULL);
BUG_ON(IS_ERR(clk));
clk_enable(clk);
#ifdef CONFIG_HAVE_ARM_TWD #ifdef CONFIG_HAVE_ARM_TWD
twd_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x600); twd_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x600);
#endif #endif
...@@ -196,10 +253,22 @@ static void __init tegra_init_timer(void) ...@@ -196,10 +253,22 @@ static void __init tegra_init_timer(void)
tegra_clockevent.cpumask = cpu_all_mask; tegra_clockevent.cpumask = cpu_all_mask;
tegra_clockevent.irq = tegra_timer_irq.irq; tegra_clockevent.irq = tegra_timer_irq.irq;
clockevents_register_device(&tegra_clockevent); clockevents_register_device(&tegra_clockevent);
return;
} }
struct sys_timer tegra_timer = { struct sys_timer tegra_timer = {
.init = tegra_init_timer, .init = tegra_init_timer,
}; };
#ifdef CONFIG_PM
static u32 usec_config;
void tegra_timer_suspend(void)
{
usec_config = timer_readl(TIMERUS_USEC_CFG);
}
void tegra_timer_resume(void)
{
timer_writel(usec_config, TIMERUS_USEC_CFG);
}
#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