M: Jianxin Pan <jianxin.pan@amlogic.com>
M: Tao Guo <tao.guo@amlogic.com>
F: drivers/amlogic/debug/*
+F: include/linux/amlogic/debug*.h
AMLOGIC G12A spdif channel status
M: xing wang<xing.wang@amlogic.com>
#include <asm-generic/pci_iomap.h>
#include <xen/xen.h>
+#ifdef CONFIG_AMLOGIC_MODIFY
+#include <linux/amlogic/debug_ftrace_ramoops.h>
+#endif
/*
* ISA I/O bus memory addresses are 1:1 with the physical address.
*/
#define __raw_writew __raw_writew
static inline void __raw_writew(u16 val, volatile void __iomem *addr)
{
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
+#endif
asm volatile("strh %1, %0"
: : "Q" (*(volatile u16 __force *)addr), "r" (val));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
+#endif
}
#define __raw_readw __raw_readw
static inline u16 __raw_readw(const volatile void __iomem *addr)
{
u16 val;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd((unsigned long)addr);
+#endif
asm volatile("ldrh %0, %1"
: "=r" (val)
: "Q" (*(volatile u16 __force *)addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd_end((unsigned long)addr);
+#endif
return val;
}
#endif
#define __raw_writeb __raw_writeb
static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
{
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
+#endif
asm volatile("strb %1, %0"
: : "Qo" (*(volatile u8 __force *)addr), "r" (val));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
+#endif
}
#define __raw_writel __raw_writel
static inline void __raw_writel(u32 val, volatile void __iomem *addr)
{
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
+#endif
asm volatile("str %1, %0"
: : "Qo" (*(volatile u32 __force *)addr), "r" (val));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
+#endif
}
#define __raw_readb __raw_readb
static inline u8 __raw_readb(const volatile void __iomem *addr)
{
u8 val;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd((unsigned long)addr);
+#endif
asm volatile("ldrb %0, %1"
: "=r" (val)
: "Qo" (*(volatile u8 __force *)addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd_end((unsigned long)addr);
+#endif
return val;
}
static inline u32 __raw_readl(const volatile void __iomem *addr)
{
u32 val;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd((unsigned long)addr);
+#endif
asm volatile("ldr %0, %1"
: "=r" (val)
: "Qo" (*(volatile u32 __force *)addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd_end((unsigned long)addr);
+#endif
return val;
}
size_t count)
{
extern void mmioset(void *, unsigned int, size_t);
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)dst, (unsigned long)count);
+#endif
mmioset((void __force *)dst, c, count);
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)dst, (unsigned long)count);
+#endif
}
#define memset_io(dst,c,count) memset_io(dst,c,count)
size_t count)
{
extern void mmiocpy(void *, const void *, size_t);
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)to, (unsigned long)count);
+#endif
mmiocpy(to, (const void __force *)from, count);
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)to, (unsigned long)count);
+#endif
}
#define memcpy_fromio(to,from,count) memcpy_fromio(to,from,count)
size_t count)
{
extern void mmiocpy(void *, const void *, size_t);
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)to, (unsigned long)count);
+#endif
mmiocpy((void __force *)to, from, count);
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)to, (unsigned long)count);
+#endif
}
#define memcpy_toio(to,from,count) memcpy_toio(to,from,count)
#include <asm/cpufeature.h>
#include <xen/xen.h>
-
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+#include <linux/amlogic/debug_ftrace_ramoops.h>
+#endif
/*
* Generic IO read/write. These perform native-endian accesses.
*/
#define __raw_writeb __raw_writeb
static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
{
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
+#endif
asm volatile("strb %w0, [%1]" : : "rZ" (val), "r" (addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
+#endif
}
#define __raw_writew __raw_writew
static inline void __raw_writew(u16 val, volatile void __iomem *addr)
{
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
+#endif
asm volatile("strh %w0, [%1]" : : "rZ" (val), "r" (addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
+#endif
}
#define __raw_writel __raw_writel
static inline void __raw_writel(u32 val, volatile void __iomem *addr)
{
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
+#endif
asm volatile("str %w0, [%1]" : : "rZ" (val), "r" (addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
+#endif
}
#define __raw_writeq __raw_writeq
static inline void __raw_writeq(u64 val, volatile void __iomem *addr)
{
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)addr, (unsigned long)val);
+#endif
asm volatile("str %x0, [%1]" : : "rZ" (val), "r" (addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)addr, (unsigned long)val);
+#endif
}
#define __raw_readb __raw_readb
static inline u8 __raw_readb(const volatile void __iomem *addr)
{
u8 val;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd((unsigned long)addr);
+#endif
asm volatile(ALTERNATIVE("ldrb %w0, [%1]",
"ldarb %w0, [%1]",
ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
: "=r" (val) : "r" (addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd_end((unsigned long)addr);
+#endif
return val;
}
{
u16 val;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd((unsigned long)addr);
+#endif
asm volatile(ALTERNATIVE("ldrh %w0, [%1]",
"ldarh %w0, [%1]",
ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
: "=r" (val) : "r" (addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd_end((unsigned long)addr);
+#endif
return val;
}
static inline u32 __raw_readl(const volatile void __iomem *addr)
{
u32 val;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd((unsigned long)addr);
+#endif
asm volatile(ALTERNATIVE("ldr %w0, [%1]",
"ldar %w0, [%1]",
ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
: "=r" (val) : "r" (addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd_end((unsigned long)addr);
+#endif
return val;
}
static inline u64 __raw_readq(const volatile void __iomem *addr)
{
u64 val;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd((unsigned long)addr);
+#endif
asm volatile(ALTERNATIVE("ldr %0, [%1]",
"ldar %0, [%1]",
ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE)
: "=r" (val) : "r" (addr));
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd_end((unsigned long)addr);
+#endif
return val;
}
#include <linux/export.h>
#include <linux/types.h>
+#define SKIP_IO_TRACE
#include <linux/io.h>
+#undef SKIP_IO_TRACE
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+#include <linux/amlogic/debug_ftrace_ramoops.h>
+#endif
/*
* Copy data from IO memory space to "real" memory space.
*/
void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t count)
{
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd((unsigned long)addr);
+#endif
while (count && !IS_ALIGNED((unsigned long)from, 8)) {
*(u8 *)to = __raw_readb(from);
from++;
to++;
count--;
}
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_rd_end((unsigned long)addr);
+#endif
}
EXPORT_SYMBOL(__memcpy_fromio);
*/
void __memcpy_toio(volatile void __iomem *to, const void *from, size_t count)
{
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)addr, 0x1234);
+#endif
while (count && !IS_ALIGNED((unsigned long)to, 8)) {
__raw_writeb(*(u8 *)from, to);
from++;
to++;
count--;
}
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)addr, 0x1234);
+#endif
}
EXPORT_SYMBOL(__memcpy_toio);
{
u64 qc = (u8)c;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr((unsigned long)addr, 0xabcd);
+#endif
qc |= qc << 8;
qc |= qc << 16;
qc |= qc << 32;
dst++;
count--;
}
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_io_wr_end((unsigned long)addr, 0xabcd);
+#endif
}
EXPORT_SYMBOL(__memset_io);
default y
help
Add android atrace compatible function
+
+config AMLOGIC_DEBUG_FTRACE_PSTORE
+ bool "Amlogic ftrace pstore debug"
+ depends on AMLOGIC_DEBUG
+ depends on PSTORE_FTRACE
+ default y
+ help
+ Dump function call and register access to ramoops after watchdog
+ reboot.
+ Enable if doubt.
+
+
obj-$(CONFIG_AMLOGIC_DEBUG_LOCKUP) += debug_lockup.o
obj-$(CONFIG_AMLOGIC_DEBUG_ATRACE) += meson_atrace.o
+obj-$(CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE)+= debug_ftrace_ramoops.o
--- /dev/null
+/*
+ * drivers/amlogic/debug/debug_ftrace_ramoops.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * 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/compiler.h>
+#include <linux/irqflags.h>
+#include <linux/percpu.h>
+#include <linux/smp.h>
+#include <linux/atomic.h>
+#include <linux/types.h>
+#include <linux/ftrace.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/amlogic/debug_ftrace_ramoops.h>
+#include <../../../fs/pstore/internal.h>
+#include <linux/trace_clock.h>
+#include <linux/percpu.h>
+#include <linux/moduleparam.h>
+
+static DEFINE_PER_CPU(int, en);
+static DEFINE_PER_CPU(unsigned long, irq_flag);
+
+#define IRQ_D 1
+
+unsigned int dump_iomap;
+core_param(dump_iomap, dump_iomap, uint, 0664);
+
+unsigned int ramoops_ftrace_en;
+EXPORT_SYMBOL(ramoops_ftrace_en);
+
+int ramoops_io_en;
+EXPORT_SYMBOL(ramoops_io_en);
+core_param(ramoops_io_en, ramoops_io_en, int, 0664);
+
+const char *record_name[PSTORE_FLAG_IO_MAX] = {
+ "NULL",
+ "FUNC",
+ "IO-R",
+ "IO-W",
+ "IO-R-E",
+ "IO-W-E",
+};
+
+void notrace pstore_ftrace_save(struct pstore_ftrace_record *rec)
+{
+ int cpu = raw_smp_processor_id();
+
+ if (unlikely(oops_in_progress) || unlikely(per_cpu(en, cpu)))
+ return;
+ per_cpu(en, cpu) = 1;
+ pstore_ftrace_encode_cpu(rec, cpu);
+ strlcpy(rec->comm, current->comm, sizeof(rec->comm) - 1);
+ rec->pid = current->pid;
+ rec->time = trace_clock_local();
+ psinfo->write_buf(PSTORE_TYPE_FTRACE, 0, NULL, 0, (void *)rec,
+ 0, sizeof(*rec), psinfo);
+ per_cpu(en, cpu) = 0;
+}
+EXPORT_SYMBOL(pstore_ftrace_save);
+
+static void notrace pstore_function_dump(struct pstore_ftrace_record *rec,
+ struct seq_file *s)
+{
+ unsigned long sec = 0, ms = 0;
+ unsigned long long time = rec->time;
+
+ do_div(time, 1000000);
+ sec = (unsigned long)time / 1000;
+ ms = (unsigned long)time % 1000;
+ seq_printf(s, "[%04ld.%03ld@%d] <%5d-%s> <%pf <- %pF>\n",
+ sec, ms, pstore_ftrace_decode_cpu(rec), rec->pid, rec->comm,
+ (void *)rec->ip, (void *)rec->parent_ip);
+}
+
+void notrace pstore_io_rw_dump(struct pstore_ftrace_record *rec,
+ struct seq_file *s)
+{
+ unsigned long sec = 0, ms = 0;
+ unsigned long long time = rec->time;
+ unsigned int cpu = pstore_ftrace_decode_cpu(rec);
+
+ do_div(time, 1000000);
+ sec = (unsigned long)time / 1000;
+ ms = (unsigned long)time % 1000;
+ seq_printf(s, "[%04ld.%03ld@%d] <%5d-%6s> <%6s %08lx-%8lx> <%pf <- %pF>\n",
+ sec, ms, cpu, rec->pid, rec->comm, record_name[rec->flag],
+ rec->val1, (rec->flag == PSTORE_FLAG_IO_W) ? rec->val2 : 0,
+ (void *)rec->ip, (void *)rec->parent_ip);
+}
+
+void notrace pstore_ftrace_dump(struct pstore_ftrace_record *rec,
+ struct seq_file *s)
+{
+ switch (rec->flag & PSTORE_FLAG_MASK) {
+ case PSTORE_FLAG_FUNC:
+ pstore_function_dump(rec, s);
+ break;
+ case PSTORE_FLAG_IO_R:
+ case PSTORE_FLAG_IO_W:
+ case PSTORE_FLAG_IO_W_END:
+ case PSTORE_FLAG_IO_R_END:
+ pstore_io_rw_dump(rec, s);
+ break;
+ default:
+ seq_printf(s, "Unknown Msg:%x\n", rec->flag);
+ }
+}
+
+void notrace pstore_io_save(unsigned long reg, unsigned long val,
+ unsigned long parant, unsigned int flag)
+{
+ struct pstore_ftrace_record rec;
+ int cpu = get_cpu();
+
+ put_cpu();
+ if (!ramoops_ftrace_en || !ramoops_io_en)
+ return;
+
+ if ((flag == PSTORE_FLAG_IO_R || flag == PSTORE_FLAG_IO_W) && IRQ_D)
+ local_irq_save(per_cpu(irq_flag, cpu));
+
+ rec.ip = CALLER_ADDR0;
+ rec.parent_ip = parant;
+ rec.flag = flag;
+ rec.val1 = reg;
+ rec.val2 = val;
+ pstore_ftrace_save(&rec);
+
+ if ((flag == PSTORE_FLAG_IO_R_END || flag == PSTORE_FLAG_IO_W_END)
+ && IRQ_D)
+ local_irq_restore(per_cpu(irq_flag, cpu));
+}
+EXPORT_SYMBOL(pstore_io_save);
+
static void __iomem *meson_reg_map[IO_BUS_MAX] = { NULL };
-int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val)
+inline int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val)
{
if (bus_type < IO_BUS_MAX && (meson_reg_map[bus_type] != NULL)) {
*val = readl((meson_reg_map[bus_type]+reg));
}
EXPORT_SYMBOL(aml_reg_read);
-int aml_reg_write(u32 bus_type, unsigned int reg, unsigned int val)
+inline int aml_reg_write(u32 bus_type, unsigned int reg, unsigned int val)
{
if (bus_type < IO_BUS_MAX && (meson_reg_map[bus_type] != NULL)) {
writel(val, (meson_reg_map[bus_type]+reg));
static void __iomem *codecio_reg_map[CODECIO_BUS_MAX];
-static int codecio_reg_read(u32 bus_type, unsigned int reg, unsigned int *val)
+static inline int codecio_reg_read(u32 bus_type, u32 reg, u32 *val)
{
if (bus_type < CODECIO_BUS_MAX) {
if (codecio_reg_map[bus_type] == NULL) {
return -1;
}
-static int codecio_reg_write(u32 bus_type, unsigned int reg, unsigned int val)
+static inline int codecio_reg_write(u32 bus_type, u32 reg, u32 val)
{
if (bus_type < CODECIO_BUS_MAX) {
if (codecio_reg_map[bus_type] == NULL) {
MESON_CPU_MAJOR_ID_SM1, \
MESON_CPU_MAJOR_ID_TM2, \
0}
-int codec_apb_read(unsigned int reg)
-{
- unsigned int val = 0;
-
- aml_reg_read(IO_APB_BUS_BASE, reg << 2, &val);
- return val;
-}
-EXPORT_SYMBOL(codec_apb_read);
-
-void codec_apb_write(unsigned int reg, unsigned int val)
-{
- aml_reg_write(IO_APB_BUS_BASE, reg << 2, val);
-}
-EXPORT_SYMBOL(codec_apb_write);
static struct chip_register_ops m8_ops[] __initdata = {
{IO_DOS_BUS, 0, codecio_read_dosbus, codecio_write_dosbus},
*
*/
+#define SKIP_IO_TRACE
#include <linux/clk.h>
#include <linux/console.h>
#include <linux/delay.h>
* As such, the enable set/clear, pending set/clear and active bit
* registers are banked per-cpu for these sources.
*/
+#define SKIP_IO_TRACE
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/err.h>
#include <asm/barrier.h>
#include "internal.h"
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+#include <linux/amlogic/debug_ftrace_ramoops.h>
+#endif
+
static void notrace pstore_ftrace_call(unsigned long ip,
unsigned long parent_ip,
struct ftrace_ops *op,
return;
local_irq_save(flags);
-
rec.ip = ip;
rec.parent_ip = parent_ip;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ rec.flag = PSTORE_FLAG_FUNC;
+ pstore_ftrace_save(&rec);
+#else
pstore_ftrace_encode_cpu(&rec, raw_smp_processor_id());
psinfo->write_buf(PSTORE_TYPE_FTRACE, 0, NULL, 0, (void *)&rec,
0, sizeof(rec), psinfo);
-
+#endif
local_irq_restore(flags);
}
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/syslog.h>
+#include <linux/amlogic/debug_ftrace_ramoops.h>
#include "internal.h"
struct pstore_ftrace_seq_data *data = v;
struct pstore_ftrace_record *rec = (void *)(ps->data + data->off);
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ pstore_ftrace_dump(rec, s);
+#else
seq_printf(s, "%d %08lx %08lx %pf <- %pF\n",
pstore_ftrace_decode_cpu(rec), rec->ip, rec->parent_ip,
(void *)rec->ip, (void *)rec->parent_ip);
-
+#endif
return 0;
}
#ifndef PSTORE_CPU_IN_IP
unsigned int cpu;
#endif
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ int pid;
+ unsigned long val1;
+ unsigned long val2;
+ unsigned long long time;
+ unsigned char comm[8];
+ unsigned int flag;
+#endif
};
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+void notrace pstore_ftrace_save(struct pstore_ftrace_record *rec);
+void notrace pstore_ftrace_dump(struct pstore_ftrace_record *rec,
+ struct seq_file *s);
+#endif
+
static inline void
pstore_ftrace_encode_cpu(struct pstore_ftrace_record *rec, unsigned int cpu)
{
cxt->size = pdata->mem_size;
cxt->phys_addr = pdata->mem_address;
cxt->memtype = pdata->mem_type;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ cxt->memtype |= (!!ramoops_io_en);
+#endif
cxt->record_size = pdata->record_size;
cxt->console_size = pdata->console_size;
cxt->ftrace_size = pdata->ftrace_size;
cxt->console_size, 0);
if (err)
goto fail_init_cprz;
-
err = ramoops_init_prz(dev, cxt, &cxt->fprz, &paddr, cxt->ftrace_size,
LINUX_VERSION_CODE);
if (err)
cxt->size, (unsigned long long)cxt->phys_addr,
cxt->ecc_info.ecc_size, cxt->ecc_info.block_size);
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ if (ramoops_ftrace_size) {
+ cxt->fprz->flags |= (PRZ_FLAG_NO_LOCK | PRZ_FLAG_BIG_LOCK);
+ ramoops_ftrace_en = !persistent_ram_old_size(cxt->fprz);
+ }
+ pr_info("ramoops_io_en:%d %d old:0x%lx ftrace_size:0x%lx",
+ ramoops_io_en, ramoops_ftrace_en,
+ (unsigned long)persistent_ram_old_size(cxt->fprz),
+ ramoops_ftrace_size);
+#endif
+
return 0;
fail_buf:
*
*/
+#define SKIP_IO_TRACE
#define pr_fmt(fmt) "persistent_ram: " fmt
#include <linux/device.h>
}
/* increase and wrap the start pointer, returning the old value */
-static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a)
+static size_t notrace buffer_start_add(struct persistent_ram_zone *prz,
+ size_t a)
{
int old;
int new;
}
/* increase the size counter until it hits the max size */
-static void buffer_size_add(struct persistent_ram_zone *prz, size_t a)
+static void notrace buffer_size_add(struct persistent_ram_zone *prz, size_t a)
{
size_t old;
size_t new;
int c = count;
size_t start;
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ unsigned long flags = 0;
+
+ if (prz->flags & PRZ_FLAG_BIG_LOCK)
+ raw_spin_lock_irqsave(&prz->buffer_lock, flags);
+#endif
if (unlikely(c > prz->buffer_size)) {
s += c - prz->buffer_size;
c = prz->buffer_size;
persistent_ram_update_header_ecc(prz);
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ if (prz->flags & PRZ_FLAG_BIG_LOCK)
+ raw_spin_unlock_irqrestore(&prz->buffer_lock, flags);
+#endif
return count;
}
--- /dev/null
+/*
+ * include/linux/amlogic/debug_ftrace_ramoops.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __DEBUG_FTRACE_RAMOOPS_H__
+#define __DEBUG_FTRACE_RAMOOPS_H__
+#define __DEBUG_FTRACE_RAMOOPS_H__
+#include <linux/ftrace.h>
+
+extern unsigned int ramoops_ftrace_en;
+extern int ramoops_io_en;
+extern unsigned int dump_iomap;
+
+#define PSTORE_FLAG_FUNC 0x1
+#define PSTORE_FLAG_IO_R 0x2
+#define PSTORE_FLAG_IO_W 0x3
+#define PSTORE_FLAG_IO_R_END 0x4
+#define PSTORE_FLAG_IO_W_END 0x5
+#define PSTORE_FLAG_IO_MAX 0x6
+#define PSTORE_FLAG_MASK 0xF
+
+void notrace pstore_io_save(unsigned long reg, unsigned long val,
+ unsigned long parant, unsigned int flag);
+
+//#define SKIP_IO_TRACE
+#if (defined CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE) && (!defined SKIP_IO_TRACE)
+#define pstore_ftrace_io_wr(reg, val) \
+pstore_io_save(reg, val, CALLER_ADDR0, PSTORE_FLAG_IO_W)
+
+#define pstore_ftrace_io_wr_end(reg, val) \
+pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_W_END)
+
+#define pstore_ftrace_io_rd(reg) \
+pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_R)
+#define pstore_ftrace_io_rd_end(reg) \
+pstore_io_save(reg, 0, CALLER_ADDR0, PSTORE_FLAG_IO_R_END)
+
+#define need_dump_iomap() (ramoops_io_en | dump_iomap)
+
+#else
+#define pstore_ftrace_io_wr(reg, val) do { } while (0)
+#define pstore_ftrace_io_rd(reg) do { } while (0)
+#define need_dump_iomap() 0
+#define pstore_ftrace_io_wr_end(reg, val) do { } while (0)
+#define pstore_ftrace_io_rd_end(reg) do { } while (0)
+
+#endif
+
+#endif
IO_HIUBUS_BASE,
IO_BUS_MAX,
};
-extern int aml_reg_read(u32 bus_type, unsigned int reg, unsigned int *val);
-extern int aml_reg_write(u32 bus_type, unsigned int reg, unsigned int val);
+
+extern inline int aml_reg_read(u32 bus_type, u32 reg, u32 *val);
+extern inline int aml_reg_write(u32 bus_type, u32 reg, u32 val);
extern int aml_regmap_update_bits(u32 bus_type,
unsigned int reg, unsigned int mask,
unsigned int val);
* PRZ_FLAG_NO_LOCK is used. For all other cases, locking is required.
*/
#define PRZ_FLAG_NO_LOCK BIT(0)
+#define PRZ_FLAG_BIG_LOCK BIT(7)
struct persistent_ram_buffer;
struct rs_control;
#include <linux/export.h>
#include <asm/cacheflush.h>
#include <asm/pgtable.h>
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+#include <linux/moduleparam.h>
+#include <linux/amlogic/debug_ftrace_ramoops.h>
+#endif
#ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
static int __read_mostly ioremap_pud_capable;
return 0;
}
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+bool is_normal_memory(pgprot_t p)
+{
+#if defined(CONFIG_ARM)
+ return ((pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEALLOC);
+#elif defined(CONFIG_ARM64)
+ return (pgprot_val(p) & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL);
+#else
+#error "Unuspported architecture"
+#endif
+}
+#endif
+
int ioremap_page_range(unsigned long addr,
unsigned long end, phys_addr_t phys_addr, pgprot_t prot)
{
} while (pgd++, addr = next, addr != end);
flush_cache_vmap(start, end);
-
+#ifdef CONFIG_AMLOGIC_DEBUG_FTRACE_PSTORE
+ if (need_dump_iomap() && !is_normal_memory(prot))
+ pr_err("io__map <va:0x%08lx-0x%08lx> pa:0x%lx,port:0x%lx\n",
+ start, end, (unsigned long)phys_addr,
+ (unsigned long)pgprot_val(prot));
+#endif
return err;
}
EXPORT_SYMBOL_GPL(ioremap_page_range);