diff options
author | Vinayak Pane <vpane@nvidia.com> | 2013-05-17 18:43:46 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 13:14:57 -0700 |
commit | 569be578f94abb2731cfaa6a86651c6235baeeeb (patch) | |
tree | 6a0ca3e6f640e31980292974eeae917e251be30a /arch/arm | |
parent | a91b0b88be465691c327bd8e1bab95e3082139ca (diff) |
arm: tegra14: bbc: prepare emc for coredump
When BBC crash is detected via IPC mailbox, prepare EMC
so that the coredump can be collected by FILD.
Restore it back to normal when fild turns off BBC.
Change-Id: I47ff8dee93e714aa2d8a4d4c46e1cfa1cac7cf03
Signed-off-by: Vinayak Pane <vpane@nvidia.com>
Reviewed-on: http://git-master/r/230027
Reviewed-by: Steve Lin <stlin@nvidia.com>
Reviewed-by: Neil Patel <neilp@nvidia.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-tegra/tegra_bb.c | 55 |
1 files changed, 41 insertions, 14 deletions
diff --git a/arch/arm/mach-tegra/tegra_bb.c b/arch/arm/mach-tegra/tegra_bb.c index cb949b8b79b3..ac1cfc507cd1 100644 --- a/arch/arm/mach-tegra/tegra_bb.c +++ b/arch/arm/mach-tegra/tegra_bb.c @@ -49,8 +49,10 @@ #define TEGRA_BB_STATUS_MASK (0xffff) #define TEGRA_BB_IPC_COLDBOOT (0x0001) #define TEGRA_BB_IPC_READY (0x0005) +#define TEGRA_BB_BOOT_RESTART_FW_REQ (0x0003) #define BBC_MC_MIN_FREQ 600000000 +#define BBC_MC_MAX_FREQ 700000000 #define APBDEV_PMC_EVENT_COUNTER_0 (0x44c) #define APBDEV_PMC_EVENT_COUNTER_0_EN_MASK (1<<20) @@ -101,6 +103,7 @@ enum bbc_pm_state { BBC_REMOVE_FLOOR = 1, BBC_SET_FLOOR, + BBC_CRASHDUMP_FLOOR, }; struct tegra_bb { @@ -291,6 +294,19 @@ static int tegra_bb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) return VM_FAULT_NOPAGE; } +static inline void tegra_bb_enable_mem_req_soon(void) +{ + void __iomem *fctrl = IO_ADDRESS(TEGRA_FLOW_CTRL_BASE); + int val = readl(fctrl + FLOW_CTLR_IPC_FLOW_IPC_STS_0); + + /* AP2BB_MSC_STS[3] is to mask or unmask + * mem_req_soon interrupt to interrupt controller */ + val = val | (0x8 << FLOW_CTLR_IPC_FLOW_IPC_STS_0_AP2BB_MSC_STS_SHIFT); + writel(val, fctrl + FLOW_CTLR_IPC_FLOW_IPC_SET_0); + + pr_debug("%s: fctrl ipc_sts = %x\n", __func__, val); +} + static int tegra_bb_map(struct file *filp, struct vm_area_struct *vma) { struct miscdevice *miscdev = filp->private_data; @@ -577,6 +593,9 @@ static ssize_t store_tegra_bb_reset(struct device *dev, regulator_status = false; } + + bb->state = BBC_REMOVE_FLOOR; + queue_work(bb->workqueue, &bb->work); } else { /* power on bbc rails */ if (bb->vdd_bb_core && bb->vdd_bb_pll && @@ -589,8 +608,9 @@ static ssize_t store_tegra_bb_reset(struct device *dev, regulator_set_voltage(bb->vdd_bb_pll, 1100000, 1100000); regulator_enable(bb->vdd_bb_pll); - regulator_status = true; + + tegra_bb_enable_mem_req_soon(); } writel(1 << APBDEV_PMC_IPC_PMC_IPC_SET_0_AP2BB_RESET_SHIFT | @@ -766,6 +786,13 @@ static irqreturn_t tegra_bb_isr_handler(int irq, void *data) pr_debug("%s: notify sysfs status %d\n", __func__, sts); sysfs_notify_dirent(bb->sd); } + + if (sts == TEGRA_BB_BOOT_RESTART_FW_REQ) { + pr_debug("%s: boot_restart_fw_req\n", __func__); + bb->state = BBC_CRASHDUMP_FLOOR; + queue_work(bb->workqueue, &bb->work); + } + bb->status = sts; return IRQ_HANDLED; } @@ -794,19 +821,6 @@ static irqreturn_t tegra_bb_mem_req_soon(int irq, void *data) return IRQ_HANDLED; } -static inline void tegra_bb_enable_mem_req_soon(void) -{ - void __iomem *fctrl = IO_ADDRESS(TEGRA_FLOW_CTRL_BASE); - int val = readl(fctrl + FLOW_CTLR_IPC_FLOW_IPC_STS_0); - - /* AP2BB_MSC_STS[3] is to mask or unmask - * mem_req_soon interrupt to interrupt controller */ - val = val | (0x8 << FLOW_CTLR_IPC_FLOW_IPC_STS_0_AP2BB_MSC_STS_SHIFT); - writel(val, fctrl + FLOW_CTLR_IPC_FLOW_IPC_SET_0); - - pr_debug("%s: fctrl ipc_sts = %x\n", __func__, val); -} - static inline void pmc_32kwritel(u32 val, unsigned long offs) { void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); @@ -931,6 +945,19 @@ static void tegra_bb_emc_dvfs(struct work_struct *work) tegra_bb_enable_mem_req_soon(); irq_set_irq_type(bb->mem_req_soon, IRQF_TRIGGER_HIGH); return; + + case BBC_CRASHDUMP_FLOOR: + /* BBC is crashed and ready to send coredump. + * do not store prev_state */ + spin_unlock_irqrestore(&bb->lock, flags); + + pr_info("%s: bbc crash detected, set EMC to max\n", __func__); + if (bb->prev_state != BBC_SET_FLOOR) + clk_prepare_enable(bb->emc_clk); + + tegra_emc_dsr_override(TEGRA_EMC_DSR_OVERRIDE); + clk_set_rate(bb->emc_clk, BBC_MC_MAX_FREQ); + return; default: spin_unlock_irqrestore(&bb->lock, flags); break; |