summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-02-17 20:27:54 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-17 20:27:54 +0300
commit878ba61aa98cbb97a513757800e77613f856a029 (patch)
treec03b8373cdb7163f81141a867c9cda1a9f71e73e /drivers
parentea7531ac4a9d0b39edce43472147dc41cc2b7a34 (diff)
parentdf1a66812535e04bfd960e15d5be4893853b6730 (diff)
downloadlinux-878ba61aa98cbb97a513757800e77613f856a029.tar.xz
Merge tag 'soc-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC platform changes from Olof Johansson: "New and updated SoC support. Also included are some cleanups where the platform maintainers hadn't separated cleanups from new developent in separate branches. Some of the larger things worth pointing out: - A large set of changes from Alexandre Belloni and Nicolas Ferre preparing at91 platforms for multiplatform and cleaning up quite a bit in the process. - Removal of CSR's "Marco" SoC platform that never made it out to the market. We love seeing these since it means the vendor published support before product was out, which is exactly what we want! New platforms this release are: - Conexant Digicolor (CX92755 SoC) - Hisilicon HiP01 SoC - CSR/sirf Atlas7 SoC - ST STiH418 SoC - Common code changes for Nvidia Tegra132 (64-bit SoC) We're seeing more and more platforms having a harder time labelling changes as cleanups vs new development -- which is a good sign that we've come quite far on the cleanup effort. So over time we might start combining the cleanup and new-development branches more" * tag 'soc-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (124 commits) ARM: at91/trivial: unify functions and machine names ARM: at91: remove at91_dt_initialize and machine init_early() ARM: at91: change board files into SoC files ARM: at91: remove at91_boot_soc ARM: at91: move alternative initial mapping to board-dt-sama5.c ARM: at91: merge all SOC_AT91SAM9xxx ARM: at91: at91rm9200: set idle and restart from rm9200_dt_device_init() ARM: digicolor: select syscon and timer ARM: zynq: Simplify SLCR initialization ARM: zynq: PM: Fixed simple typo. ARM: zynq: Setup default gpio number for Xilinx Zynq ARM: digicolor: add low level debug support ARM: initial support for Conexant Digicolor CX92755 SoC ARM: OMAP2+: Add dm816x hwmod support ARM: OMAP2+: Add clock domain support for dm816x ARM: OMAP2+: Add board-generic.c entry for ti81xx ARM: at91: pm: remove warning to remove SOC_AT91SAM9263 usage ARM: at91: remove unused mach/system_rev.h ARM: at91: stop using HAVE_AT91_DBGUx ARM: at91: fix ordering of SRAM and PM initialization ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/bus/mvebu-mbus.c286
-rw-r--r--drivers/clk/at91/pmc.c9
-rw-r--r--drivers/clk/sunxi/clk-sunxi.c1
-rw-r--r--drivers/clocksource/Kconfig3
-rw-r--r--drivers/clocksource/Makefile2
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra.c1
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra30.c9
-rw-r--r--drivers/soc/tegra/pmc.c124
8 files changed, 357 insertions, 78 deletions
diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c
index 81bf297f1034..fb9ec6221730 100644
--- a/drivers/bus/mvebu-mbus.c
+++ b/drivers/bus/mvebu-mbus.c
@@ -58,6 +58,7 @@
#include <linux/debugfs.h>
#include <linux/log2.h>
#include <linux/syscore_ops.h>
+#include <linux/memblock.h>
/*
* DDR target is the same on all platforms.
@@ -69,6 +70,7 @@
*/
#define WIN_CTRL_OFF 0x0000
#define WIN_CTRL_ENABLE BIT(0)
+#define WIN_CTRL_SYNCBARRIER BIT(1)
#define WIN_CTRL_TGT_MASK 0xf0
#define WIN_CTRL_TGT_SHIFT 4
#define WIN_CTRL_ATTR_MASK 0xff00
@@ -82,6 +84,9 @@
#define WIN_REMAP_LOW 0xffff0000
#define WIN_REMAP_HI_OFF 0x000c
+#define UNIT_SYNC_BARRIER_OFF 0x84
+#define UNIT_SYNC_BARRIER_ALL 0xFFFF
+
#define ATTR_HW_COHERENCY (0x1 << 4)
#define DDR_BASE_CS_OFF(n) (0x0000 + ((n) << 3))
@@ -97,7 +102,9 @@
/* Relative to mbusbridge_base */
#define MBUS_BRIDGE_CTRL_OFF 0x0
+#define MBUS_BRIDGE_SIZE_MASK 0xffff0000
#define MBUS_BRIDGE_BASE_OFF 0x4
+#define MBUS_BRIDGE_BASE_MASK 0xffff0000
/* Maximum number of windows, for all known platforms */
#define MBUS_WINS_MAX 20
@@ -106,9 +113,9 @@ struct mvebu_mbus_state;
struct mvebu_mbus_soc_data {
unsigned int num_wins;
- unsigned int num_remappable_wins;
bool has_mbus_bridge;
unsigned int (*win_cfg_offset)(const int win);
+ unsigned int (*win_remap_offset)(const int win);
void (*setup_cpu_target)(struct mvebu_mbus_state *s);
int (*save_cpu_target)(struct mvebu_mbus_state *s,
u32 *store_addr);
@@ -154,6 +161,13 @@ const struct mbus_dram_target_info *mv_mbus_dram_info(void)
}
EXPORT_SYMBOL_GPL(mv_mbus_dram_info);
+/* Checks whether the given window has remap capability */
+static bool mvebu_mbus_window_is_remappable(struct mvebu_mbus_state *mbus,
+ const int win)
+{
+ return mbus->soc->win_remap_offset(win) != MVEBU_MBUS_NO_REMAP;
+}
+
/*
* Functions to manipulate the address decoding windows
*/
@@ -185,9 +199,12 @@ static void mvebu_mbus_read_window(struct mvebu_mbus_state *mbus,
*attr = (ctrlreg & WIN_CTRL_ATTR_MASK) >> WIN_CTRL_ATTR_SHIFT;
if (remap) {
- if (win < mbus->soc->num_remappable_wins) {
- u32 remap_low = readl(addr + WIN_REMAP_LO_OFF);
- u32 remap_hi = readl(addr + WIN_REMAP_HI_OFF);
+ if (mvebu_mbus_window_is_remappable(mbus, win)) {
+ u32 remap_low, remap_hi;
+ void __iomem *addr_rmp = mbus->mbuswins_base +
+ mbus->soc->win_remap_offset(win);
+ remap_low = readl(addr_rmp + WIN_REMAP_LO_OFF);
+ remap_hi = readl(addr_rmp + WIN_REMAP_HI_OFF);
*remap = ((u64)remap_hi << 32) | remap_low;
} else
*remap = 0;
@@ -200,10 +217,11 @@ static void mvebu_mbus_disable_window(struct mvebu_mbus_state *mbus,
void __iomem *addr;
addr = mbus->mbuswins_base + mbus->soc->win_cfg_offset(win);
-
writel(0, addr + WIN_BASE_OFF);
writel(0, addr + WIN_CTRL_OFF);
- if (win < mbus->soc->num_remappable_wins) {
+
+ if (mvebu_mbus_window_is_remappable(mbus, win)) {
+ addr = mbus->mbuswins_base + mbus->soc->win_remap_offset(win);
writel(0, addr + WIN_REMAP_LO_OFF);
writel(0, addr + WIN_REMAP_HI_OFF);
}
@@ -211,14 +229,6 @@ static void mvebu_mbus_disable_window(struct mvebu_mbus_state *mbus,
/* Checks whether the given window number is available */
-/* On Armada XP, 375 and 38x the MBus window 13 has the remap
- * capability, like windows 0 to 7. However, the mvebu-mbus driver
- * isn't currently taking into account this special case, which means
- * that when window 13 is actually used, the remap registers are left
- * to 0, making the device using this MBus window unavailable. The
- * quick fix for stable is to not use window 13. A follow up patch
- * will correctly handle this window.
-*/
static int mvebu_mbus_window_is_free(struct mvebu_mbus_state *mbus,
const int win)
{
@@ -226,9 +236,6 @@ static int mvebu_mbus_window_is_free(struct mvebu_mbus_state *mbus,
mbus->soc->win_cfg_offset(win);
u32 ctrl = readl(addr + WIN_CTRL_OFF);
- if (win == 13)
- return false;
-
return !(ctrl & WIN_CTRL_ENABLE);
}
@@ -316,17 +323,22 @@ static int mvebu_mbus_setup_window(struct mvebu_mbus_state *mbus,
ctrl = ((size - 1) & WIN_CTRL_SIZE_MASK) |
(attr << WIN_CTRL_ATTR_SHIFT) |
(target << WIN_CTRL_TGT_SHIFT) |
+ WIN_CTRL_SYNCBARRIER |
WIN_CTRL_ENABLE;
writel(base & WIN_BASE_LOW, addr + WIN_BASE_OFF);
writel(ctrl, addr + WIN_CTRL_OFF);
- if (win < mbus->soc->num_remappable_wins) {
+
+ if (mvebu_mbus_window_is_remappable(mbus, win)) {
+ void __iomem *addr_rmp = mbus->mbuswins_base +
+ mbus->soc->win_remap_offset(win);
+
if (remap == MVEBU_MBUS_NO_REMAP)
remap_addr = base;
else
remap_addr = remap;
- writel(remap_addr & WIN_REMAP_LOW, addr + WIN_REMAP_LO_OFF);
- writel(0, addr + WIN_REMAP_HI_OFF);
+ writel(remap_addr & WIN_REMAP_LOW, addr_rmp + WIN_REMAP_LO_OFF);
+ writel(0, addr_rmp + WIN_REMAP_HI_OFF);
}
return 0;
@@ -340,19 +352,27 @@ static int mvebu_mbus_alloc_window(struct mvebu_mbus_state *mbus,
int win;
if (remap == MVEBU_MBUS_NO_REMAP) {
- for (win = mbus->soc->num_remappable_wins;
- win < mbus->soc->num_wins; win++)
+ for (win = 0; win < mbus->soc->num_wins; win++) {
+ if (mvebu_mbus_window_is_remappable(mbus, win))
+ continue;
+
if (mvebu_mbus_window_is_free(mbus, win))
return mvebu_mbus_setup_window(mbus, win, base,
size, remap,
target, attr);
+ }
}
+ for (win = 0; win < mbus->soc->num_wins; win++) {
+ /* Skip window if need remap but is not supported */
+ if ((remap != MVEBU_MBUS_NO_REMAP) &&
+ !mvebu_mbus_window_is_remappable(mbus, win))
+ continue;
- for (win = 0; win < mbus->soc->num_wins; win++)
if (mvebu_mbus_window_is_free(mbus, win))
return mvebu_mbus_setup_window(mbus, win, base, size,
remap, target, attr);
+ }
return -ENOMEM;
}
@@ -464,7 +484,7 @@ static int mvebu_devs_debug_show(struct seq_file *seq, void *v)
((wbase & (u64)(wsize - 1)) != 0))
seq_puts(seq, " (Invalid base/size!!)");
- if (win < mbus->soc->num_remappable_wins) {
+ if (mvebu_mbus_window_is_remappable(mbus, win)) {
seq_printf(seq, " (remap %016llx)\n",
(unsigned long long)wremap);
} else
@@ -490,12 +510,12 @@ static const struct file_operations mvebu_devs_debug_fops = {
* SoC-specific functions and definitions
*/
-static unsigned int orion_mbus_win_offset(int win)
+static unsigned int generic_mbus_win_cfg_offset(int win)
{
return win << 4;
}
-static unsigned int armada_370_xp_mbus_win_offset(int win)
+static unsigned int armada_370_xp_mbus_win_cfg_offset(int win)
{
/* The register layout is a bit annoying and the below code
* tries to cope with it.
@@ -515,7 +535,7 @@ static unsigned int armada_370_xp_mbus_win_offset(int win)
return 0x90 + ((win - 8) << 3);
}
-static unsigned int mv78xx0_mbus_win_offset(int win)
+static unsigned int mv78xx0_mbus_win_cfg_offset(int win)
{
if (win < 8)
return win << 4;
@@ -523,36 +543,140 @@ static unsigned int mv78xx0_mbus_win_offset(int win)
return 0x900 + ((win - 8) << 4);
}
+static unsigned int generic_mbus_win_remap_2_offset(int win)
+{
+ if (win < 2)
+ return generic_mbus_win_cfg_offset(win);
+ else
+ return MVEBU_MBUS_NO_REMAP;
+}
+
+static unsigned int generic_mbus_win_remap_4_offset(int win)
+{
+ if (win < 4)
+ return generic_mbus_win_cfg_offset(win);
+ else
+ return MVEBU_MBUS_NO_REMAP;
+}
+
+static unsigned int generic_mbus_win_remap_8_offset(int win)
+{
+ if (win < 8)
+ return generic_mbus_win_cfg_offset(win);
+ else
+ return MVEBU_MBUS_NO_REMAP;
+}
+
+static unsigned int armada_xp_mbus_win_remap_offset(int win)
+{
+ if (win < 8)
+ return generic_mbus_win_cfg_offset(win);
+ else if (win == 13)
+ return 0xF0 - WIN_REMAP_LO_OFF;
+ else
+ return MVEBU_MBUS_NO_REMAP;
+}
+
+/*
+ * Use the memblock information to find the MBus bridge hole in the
+ * physical address space.
+ */
+static void __init
+mvebu_mbus_find_bridge_hole(uint64_t *start, uint64_t *end)
+{
+ struct memblock_region *r;
+ uint64_t s = 0;
+
+ for_each_memblock(memory, r) {
+ /*
+ * This part of the memory is above 4 GB, so we don't
+ * care for the MBus bridge hole.
+ */
+ if (r->base >= 0x100000000)
+ continue;
+
+ /*
+ * The MBus bridge hole is at the end of the RAM under
+ * the 4 GB limit.
+ */
+ if (r->base + r->size > s)
+ s = r->base + r->size;
+ }
+
+ *start = s;
+ *end = 0x100000000;
+}
+
static void __init
mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus)
{
int i;
int cs;
+ uint64_t mbus_bridge_base, mbus_bridge_end;
mvebu_mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
+ mvebu_mbus_find_bridge_hole(&mbus_bridge_base, &mbus_bridge_end);
+
for (i = 0, cs = 0; i < 4; i++) {
- u32 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i));
- u32 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i));
+ u64 base = readl(mbus->sdramwins_base + DDR_BASE_CS_OFF(i));
+ u64 size = readl(mbus->sdramwins_base + DDR_SIZE_CS_OFF(i));
+ u64 end;
+ struct mbus_dram_window *w;
+
+ /* Ignore entries that are not enabled */
+ if (!(size & DDR_SIZE_ENABLED))
+ continue;
/*
- * We only take care of entries for which the chip
- * select is enabled, and that don't have high base
- * address bits set (devices can only access the first
- * 32 bits of the memory).
+ * Ignore entries whose base address is above 2^32,
+ * since devices cannot DMA to such high addresses
*/
- if ((size & DDR_SIZE_ENABLED) &&
- !(base & DDR_BASE_CS_HIGH_MASK)) {
- struct mbus_dram_window *w;
+ if (base & DDR_BASE_CS_HIGH_MASK)
+ continue;
- w = &mvebu_mbus_dram_info.cs[cs++];
- w->cs_index = i;
- w->mbus_attr = 0xf & ~(1 << i);
- if (mbus->hw_io_coherency)
- w->mbus_attr |= ATTR_HW_COHERENCY;
- w->base = base & DDR_BASE_CS_LOW_MASK;
- w->size = (size | ~DDR_SIZE_MASK) + 1;
+ base = base & DDR_BASE_CS_LOW_MASK;
+ size = (size | ~DDR_SIZE_MASK) + 1;
+ end = base + size;
+
+ /*
+ * Adjust base/size of the current CS to make sure it
+ * doesn't overlap with the MBus bridge hole. This is
+ * particularly important for devices that do DMA from
+ * DRAM to a SRAM mapped in a MBus window, such as the
+ * CESA cryptographic engine.
+ */
+
+ /*
+ * The CS is fully enclosed inside the MBus bridge
+ * area, so ignore it.
+ */
+ if (base >= mbus_bridge_base && end <= mbus_bridge_end)
+ continue;
+
+ /*
+ * Beginning of CS overlaps with end of MBus, raise CS
+ * base address, and shrink its size.
+ */
+ if (base >= mbus_bridge_base && end > mbus_bridge_end) {
+ size -= mbus_bridge_end - base;
+ base = mbus_bridge_end;
}
+
+ /*
+ * End of CS overlaps with beginning of MBus, shrink
+ * CS size.
+ */
+ if (base < mbus_bridge_base && end > mbus_bridge_base)
+ size -= end - mbus_bridge_base;
+
+ w = &mvebu_mbus_dram_info.cs[cs++];
+ w->cs_index = i;
+ w->mbus_attr = 0xf & ~(1 << i);
+ if (mbus->hw_io_coherency)
+ w->mbus_attr |= ATTR_HW_COHERENCY;
+ w->base = base;
+ w->size = size;
}
mvebu_mbus_dram_info.num_cs = cs;
}
@@ -632,30 +756,40 @@ int mvebu_mbus_save_cpu_target(u32 *store_addr)
return mbus_state.soc->save_cpu_target(&mbus_state, store_addr);
}
-static const struct mvebu_mbus_soc_data armada_370_xp_mbus_data = {
+static const struct mvebu_mbus_soc_data armada_370_mbus_data = {
.num_wins = 20,
- .num_remappable_wins = 8,
.has_mbus_bridge = true,
- .win_cfg_offset = armada_370_xp_mbus_win_offset,
+ .win_cfg_offset = armada_370_xp_mbus_win_cfg_offset,
+ .win_remap_offset = generic_mbus_win_remap_8_offset,
+ .setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
+ .show_cpu_target = mvebu_sdram_debug_show_orion,
.save_cpu_target = mvebu_mbus_default_save_cpu_target,
+};
+
+static const struct mvebu_mbus_soc_data armada_xp_mbus_data = {
+ .num_wins = 20,
+ .has_mbus_bridge = true,
+ .win_cfg_offset = armada_370_xp_mbus_win_cfg_offset,
+ .win_remap_offset = armada_xp_mbus_win_remap_offset,
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
.show_cpu_target = mvebu_sdram_debug_show_orion,
+ .save_cpu_target = mvebu_mbus_default_save_cpu_target,
};
static const struct mvebu_mbus_soc_data kirkwood_mbus_data = {
.num_wins = 8,
- .num_remappable_wins = 4,
- .win_cfg_offset = orion_mbus_win_offset,
+ .win_cfg_offset = generic_mbus_win_cfg_offset,
.save_cpu_target = mvebu_mbus_default_save_cpu_target,
+ .win_remap_offset = generic_mbus_win_remap_4_offset,
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
.show_cpu_target = mvebu_sdram_debug_show_orion,
};
static const struct mvebu_mbus_soc_data dove_mbus_data = {
.num_wins = 8,
- .num_remappable_wins = 4,
- .win_cfg_offset = orion_mbus_win_offset,
+ .win_cfg_offset = generic_mbus_win_cfg_offset,
.save_cpu_target = mvebu_mbus_dove_save_cpu_target,
+ .win_remap_offset = generic_mbus_win_remap_4_offset,
.setup_cpu_target = mvebu_mbus_dove_setup_cpu_target,
.show_cpu_target = mvebu_sdram_debug_show_dove,
};
@@ -666,36 +800,40 @@ static const struct mvebu_mbus_soc_data dove_mbus_data = {
*/
static const struct mvebu_mbus_soc_data orion5x_4win_mbus_data = {
.num_wins = 8,
- .num_remappable_wins = 4,
- .win_cfg_offset = orion_mbus_win_offset,
+ .win_cfg_offset = generic_mbus_win_cfg_offset,
.save_cpu_target = mvebu_mbus_default_save_cpu_target,
+ .win_remap_offset = generic_mbus_win_remap_4_offset,
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
.show_cpu_target = mvebu_sdram_debug_show_orion,
};
static const struct mvebu_mbus_soc_data orion5x_2win_mbus_data = {
.num_wins = 8,
- .num_remappable_wins = 2,
- .win_cfg_offset = orion_mbus_win_offset,
+ .win_cfg_offset = generic_mbus_win_cfg_offset,
.save_cpu_target = mvebu_mbus_default_save_cpu_target,
+ .win_remap_offset = generic_mbus_win_remap_2_offset,
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
.show_cpu_target = mvebu_sdram_debug_show_orion,
};
static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = {
.num_wins = 14,
- .num_remappable_wins = 8,
- .win_cfg_offset = mv78xx0_mbus_win_offset,
+ .win_cfg_offset = mv78xx0_mbus_win_cfg_offset,
.save_cpu_target = mvebu_mbus_default_save_cpu_target,
+ .win_remap_offset = generic_mbus_win_remap_8_offset,
.setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
.show_cpu_target = mvebu_sdram_debug_show_orion,
};
static const struct of_device_id of_mvebu_mbus_ids[] = {
{ .compatible = "marvell,armada370-mbus",
- .data = &armada_370_xp_mbus_data, },
+ .data = &armada_370_mbus_data, },
+ { .compatible = "marvell,armada375-mbus",
+ .data = &armada_xp_mbus_data, },
+ { .compatible = "marvell,armada380-mbus",
+ .data = &armada_xp_mbus_data, },
{ .compatible = "marvell,armadaxp-mbus",
- .data = &armada_370_xp_mbus_data, },
+ .data = &armada_xp_mbus_data, },
{ .compatible = "marvell,kirkwood-mbus",
.data = &kirkwood_mbus_data, },
{ .compatible = "marvell,dove-mbus",
@@ -802,15 +940,19 @@ static int mvebu_mbus_suspend(void)
for (win = 0; win < s->soc->num_wins; win++) {
void __iomem *addr = s->mbuswins_base +
s->soc->win_cfg_offset(win);
+ void __iomem *addr_rmp;
s->wins[win].base = readl(addr + WIN_BASE_OFF);
s->wins[win].ctrl = readl(addr + WIN_CTRL_OFF);
- if (win >= s->soc->num_remappable_wins)
+ if (!mvebu_mbus_window_is_remappable(s, win))
continue;
- s->wins[win].remap_lo = readl(addr + WIN_REMAP_LO_OFF);
- s->wins[win].remap_hi = readl(addr + WIN_REMAP_HI_OFF);
+ addr_rmp = s->mbuswins_base +
+ s->soc->win_remap_offset(win);
+
+ s->wins[win].remap_lo = readl(addr_rmp + WIN_REMAP_LO_OFF);
+ s->wins[win].remap_hi = readl(addr_rmp + WIN_REMAP_HI_OFF);
}
s->mbus_bridge_ctrl = readl(s->mbusbridge_base +
@@ -834,15 +976,19 @@ static void mvebu_mbus_resume(void)
for (win = 0; win < s->soc->num_wins; win++) {
void __iomem *addr = s->mbuswins_base +
s->soc->win_cfg_offset(win);
+ void __iomem *addr_rmp;
writel(s->wins[win].base, addr + WIN_BASE_OFF);
writel(s->wins[win].ctrl, addr + WIN_CTRL_OFF);
- if (win >= s->soc->num_remappable_wins)
+ if (!mvebu_mbus_window_is_remappable(s, win))
continue;
- writel(s->wins[win].remap_lo, addr + WIN_REMAP_LO_OFF);
- writel(s->wins[win].remap_hi, addr + WIN_REMAP_HI_OFF);
+ addr_rmp = s->mbuswins_base +
+ s->soc->win_remap_offset(win);
+
+ writel(s->wins[win].remap_lo, addr_rmp + WIN_REMAP_LO_OFF);
+ writel(s->wins[win].remap_hi, addr_rmp + WIN_REMAP_HI_OFF);
}
}
@@ -857,7 +1003,8 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
phys_addr_t sdramwins_phys_base,
size_t sdramwins_size,
phys_addr_t mbusbridge_phys_base,
- size_t mbusbridge_size)
+ size_t mbusbridge_size,
+ bool is_coherent)
{
int win;
@@ -889,6 +1036,10 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
mbus->soc->setup_cpu_target(mbus);
+ if (is_coherent)
+ writel(UNIT_SYNC_BARRIER_ALL,
+ mbus->mbuswins_base + UNIT_SYNC_BARRIER_OFF);
+
register_syscore_ops(&mvebu_mbus_syscore_ops);
return 0;
@@ -916,7 +1067,7 @@ int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base,
mbuswins_phys_base,
mbuswins_size,
sdramwins_phys_base,
- sdramwins_size, 0, 0);
+ sdramwins_size, 0, 0, false);
}
#ifdef CONFIG_OF
@@ -1118,7 +1269,8 @@ int __init mvebu_mbus_dt_init(bool is_coherent)
sdramwins_res.start,
resource_size(&sdramwins_res),
mbusbridge_res.start,
- resource_size(&mbusbridge_res));
+ resource_size(&mbusbridge_res),
+ is_coherent);
if (ret)
return ret;
diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 386999b4f8eb..f07c8152e5cc 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -27,6 +27,15 @@
void __iomem *at91_pmc_base;
EXPORT_SYMBOL_GPL(at91_pmc_base);
+void at91rm9200_idle(void)
+{
+ /*
+ * Disable the processor clock. The processor will be automatically
+ * re-enabled by an interrupt or by a reset.
+ */
+ at91_pmc_write(AT91_PMC_SCDR, AT91_PMC_PCK);
+}
+
void at91sam9_idle(void)
{
at91_pmc_write(AT91_PMC_SCDR, AT91_PMC_PCK);
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 570202582dcf..1818f404538d 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -1226,6 +1226,7 @@ static void __init sun6i_init_clocks(struct device_node *node)
ARRAY_SIZE(sun6i_critical_clocks));
}
CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks);
+CLK_OF_DECLARE(sun6i_a31s_clk_init, "allwinner,sun6i-a31s", sun6i_init_clocks);
CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks);
static void __init sun9i_init_clocks(struct device_node *node)
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 717f40e875fc..1c2506f68122 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -54,6 +54,9 @@ config SUN5I_HSTIMER
select CLKSRC_MMIO
bool
+config TEGRA_TIMER
+ bool
+
config VT8500_TIMER
bool
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 3359121570c7..752d5c70b0ef 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -29,7 +29,7 @@ obj-$(CONFIG_ARCH_U300) += timer-u300.o
obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o
obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o
obj-$(CONFIG_MESON6_TIMER) += meson6_timer.o
-obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o
+obj-$(CONFIG_TEGRA_TIMER) += tegra20_timer.o
obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o
obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o
obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm_kona_timer.o
diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c
index 011a3363c265..c0d660f1aaac 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
@@ -81,6 +81,7 @@ static const struct of_device_id car_match[] __initconst = {
{ .compatible = "nvidia,tegra30-car", },
{ .compatible = "nvidia,tegra114-car", },
{ .compatible = "nvidia,tegra124-car", },
+ { .compatible = "nvidia,tegra132-car", },
{},
};
diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c
index 8646fa920d8d..4d2f71bf65c5 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra30.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra30.c
@@ -56,7 +56,7 @@ struct tegra_fuse_info {
static void __iomem *fuse_base;
static struct clk *fuse_clk;
-static struct tegra_fuse_info *fuse_info;
+static const struct tegra_fuse_info *fuse_info;
u32 tegra30_fuse_readl(const unsigned int offset)
{
@@ -78,18 +78,18 @@ u32 tegra30_fuse_readl(const unsigned int offset)
return val;
}
-static struct tegra_fuse_info tegra30_info = {
+static const struct tegra_fuse_info tegra30_info = {
.size = 0x2a4,
.spare_bit = 0x144,
.speedo_idx = SPEEDO_TEGRA30,
};
-static struct tegra_fuse_info tegra114_info = {
+static const struct tegra_fuse_info tegra114_info = {
.size = 0x2a0,
.speedo_idx = SPEEDO_TEGRA114,
};
-static struct tegra_fuse_info tegra124_info = {
+static const struct tegra_fuse_info tegra124_info = {
.size = 0x300,
.speedo_idx = SPEEDO_TEGRA124,
};
@@ -182,6 +182,7 @@ static void __init legacy_fuse_init(void)
fuse_info = &tegra114_info;
break;
case TEGRA124:
+ case TEGRA132:
fuse_info = &tegra124_info;
break;
default:
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index a2c0ceb95f8f..c956395cf46f 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -70,6 +70,10 @@
#define PMC_SCRATCH41 0x140
+#define PMC_SENSOR_CTRL 0x1b0
+#define PMC_SENSOR_CTRL_SCRATCH_WRITE (1 << 2)
+#define PMC_SENSOR_CTRL_ENABLE_RST (1 << 1)
+
#define IO_DPD_REQ 0x1b8
#define IO_DPD_REQ_CODE_IDLE (0 << 30)
#define IO_DPD_REQ_CODE_OFF (1 << 30)
@@ -81,6 +85,18 @@
#define IO_DPD2_STATUS 0x1c4
#define SEL_DPD_TIM 0x1c8
+#define PMC_SCRATCH54 0x258
+#define PMC_SCRATCH54_DATA_SHIFT 8
+#define PMC_SCRATCH54_ADDR_SHIFT 0
+
+#define PMC_SCRATCH55 0x25c
+#define PMC_SCRATCH55_RESET_TEGRA (1 << 31)
+#define PMC_SCRATCH55_CNTRL_ID_SHIFT 27
+#define PMC_SCRATCH55_PINMUX_SHIFT 24
+#define PMC_SCRATCH55_16BITOP (1 << 15)
+#define PMC_SCRATCH55_CHECKSUM_SHIFT 16
+#define PMC_SCRATCH55_I2CSLV1_SHIFT 0
+
#define GPU_RG_CNTRL 0x2d4
struct tegra_pmc_soc {
@@ -88,6 +104,9 @@ struct tegra_pmc_soc {
const char *const *powergates;
unsigned int num_cpu_powergates;
const u8 *cpu_powergates;
+
+ bool has_tsense_reset;
+ bool has_gpu_clamps;
};
/**
@@ -110,6 +129,7 @@ struct tegra_pmc_soc {
* @powergates_lock: mutex for power gate register access
*/
struct tegra_pmc {
+ struct device *dev;
void __iomem *base;
struct clk *clk;
@@ -225,11 +245,11 @@ int tegra_powergate_remove_clamping(int id)
return -EINVAL;
/*
- * The Tegra124 GPU has a separate register (with different semantics)
- * to remove clamps.
+ * On Tegra124 and later, the clamps for the GPU are controlled by a
+ * separate register (with different semantics).
*/
- if (tegra_get_chip_id() == TEGRA124) {
- if (id == TEGRA_POWERGATE_3D) {
+ if (id == TEGRA_POWERGATE_3D) {
+ if (pmc->soc->has_gpu_clamps) {
tegra_pmc_writel(0, GPU_RG_CNTRL);
return 0;
}
@@ -703,6 +723,83 @@ static void tegra_pmc_init(struct tegra_pmc *pmc)
tegra_pmc_writel(value, PMC_CNTRL);
}
+void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc)
+{
+ static const char disabled[] = "emergency thermal reset disabled";
+ u32 pmu_addr, ctrl_id, reg_addr, reg_data, pinmux;
+ struct device *dev = pmc->dev;
+ struct device_node *np;
+ u32 value, checksum;
+
+ if (!pmc->soc->has_tsense_reset)
+ goto out;
+
+ np = of_find_node_by_name(pmc->dev->of_node, "i2c-thermtrip");
+ if (!np) {
+ dev_warn(dev, "i2c-thermtrip node not found, %s.\n", disabled);
+ goto out;
+ }
+
+ if (of_property_read_u32(np, "nvidia,i2c-controller-id", &ctrl_id)) {
+ dev_err(dev, "I2C controller ID missing, %s.\n", disabled);
+ goto out;
+ }
+
+ if (of_property_read_u32(np, "nvidia,bus-addr", &pmu_addr)) {
+ dev_err(dev, "nvidia,bus-addr missing, %s.\n", disabled);
+ goto out;
+ }
+
+ if (of_property_read_u32(np, "nvidia,reg-addr", &reg_addr)) {
+ dev_err(dev, "nvidia,reg-addr missing, %s.\n", disabled);
+ goto out;
+ }
+
+ if (of_property_read_u32(np, "nvidia,reg-data", &reg_data)) {
+ dev_err(dev, "nvidia,reg-data missing, %s.\n", disabled);
+ goto out;
+ }
+
+ if (of_property_read_u32(np, "nvidia,pinmux-id", &pinmux))
+ pinmux = 0;
+
+ value = tegra_pmc_readl(PMC_SENSOR_CTRL);
+ value |= PMC_SENSOR_CTRL_SCRATCH_WRITE;
+ tegra_pmc_writel(value, PMC_SENSOR_CTRL);
+
+ value = (reg_data << PMC_SCRATCH54_DATA_SHIFT) |
+ (reg_addr << PMC_SCRATCH54_ADDR_SHIFT);
+ tegra_pmc_writel(value, PMC_SCRATCH54);
+
+ value = PMC_SCRATCH55_RESET_TEGRA;
+ value |= ctrl_id << PMC_SCRATCH55_CNTRL_ID_SHIFT;
+ value |= pinmux << PMC_SCRATCH55_PINMUX_SHIFT;
+ value |= pmu_addr << PMC_SCRATCH55_I2CSLV1_SHIFT;
+
+ /*
+ * Calculate checksum of SCRATCH54, SCRATCH55 fields. Bits 23:16 will
+ * contain the checksum and are currently zero, so they are not added.
+ */
+ checksum = reg_addr + reg_data + (value & 0xff) + ((value >> 8) & 0xff)
+ + ((value >> 24) & 0xff);
+ checksum &= 0xff;
+ checksum = 0x100 - checksum;
+
+ value |= checksum << PMC_SCRATCH55_CHECKSUM_SHIFT;
+
+ tegra_pmc_writel(value, PMC_SCRATCH55);
+
+ value = tegra_pmc_readl(PMC_SENSOR_CTRL);
+ value |= PMC_SENSOR_CTRL_ENABLE_RST;
+ tegra_pmc_writel(value, PMC_SENSOR_CTRL);
+
+ dev_info(pmc->dev, "emergency thermal reset enabled\n");
+
+out:
+ of_node_put(np);
+ return;
+}
+
static int tegra_pmc_probe(struct platform_device *pdev)
{
void __iomem *base = pmc->base;
@@ -728,8 +825,12 @@ static int tegra_pmc_probe(struct platform_device *pdev)
return err;
}
+ pmc->dev = &pdev->dev;
+
tegra_pmc_init(pmc);
+ tegra_pmc_init_tsense_reset(pmc);
+
if (IS_ENABLED(CONFIG_DEBUG_FS)) {
err = tegra_powergate_debugfs_init();
if (err < 0)
@@ -739,7 +840,7 @@ static int tegra_pmc_probe(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM_SLEEP
+#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
static int tegra_pmc_suspend(struct device *dev)
{
tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41);
@@ -753,10 +854,11 @@ static int tegra_pmc_resume(struct device *dev)
return 0;
}
-#endif
static SIMPLE_DEV_PM_OPS(tegra_pmc_pm_ops, tegra_pmc_suspend, tegra_pmc_resume);
+#endif
+
static const char * const tegra20_powergates[] = {
[TEGRA_POWERGATE_CPU] = "cpu",
[TEGRA_POWERGATE_3D] = "3d",
@@ -772,6 +874,8 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = {
.powergates = tegra20_powergates,
.num_cpu_powergates = 0,
.cpu_powergates = NULL,
+ .has_tsense_reset = false,
+ .has_gpu_clamps = false,
};
static const char * const tegra30_powergates[] = {
@@ -803,6 +907,8 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
.powergates = tegra30_powergates,
.num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates),
.cpu_powergates = tegra30_cpu_powergates,
+ .has_tsense_reset = true,
+ .has_gpu_clamps = false,
};
static const char * const tegra114_powergates[] = {
@@ -838,6 +944,8 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
.powergates = tegra114_powergates,
.num_cpu_powergates = ARRAY_SIZE(tegra114_cpu_powergates),
.cpu_powergates = tegra114_cpu_powergates,
+ .has_tsense_reset = true,
+ .has_gpu_clamps = false,
};
static const char * const tegra124_powergates[] = {
@@ -879,6 +987,8 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
.powergates = tegra124_powergates,
.num_cpu_powergates = ARRAY_SIZE(tegra124_cpu_powergates),
.cpu_powergates = tegra124_cpu_powergates,
+ .has_tsense_reset = true,
+ .has_gpu_clamps = true,
};
static const struct of_device_id tegra_pmc_match[] = {
@@ -894,7 +1004,9 @@ static struct platform_driver tegra_pmc_driver = {
.name = "tegra-pmc",
.suppress_bind_attrs = true,
.of_match_table = tegra_pmc_match,
+#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
.pm = &tegra_pmc_pm_ops,
+#endif
},
.probe = tegra_pmc_probe,
};