blob: 630fac974c275dfc48d743f197bca4fd4f8b9a2c [file] [log] [blame]
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#ifndef __DMC_MONITOR_H__
#define __DMC_MONITOR_H__
#define PROTECT_READ BIT(0)
#define PROTECT_WRITE BIT(1)
#define DMC_MON_RW 0x8200004A
#define DMC_READ_VIOLATION BIT(0)
#define DMC_WRITE_VIOLATION BIT(1)
#define DMC_DEBUG_WRITE BIT(0)
#define DMC_DEBUG_READ BIT(1)
#define DMC_DEBUG_CMA BIT(2)
/*
* Address is aligned to 64 KB
*/
#define DMC_ADDR_SIZE (0x10000)
#define DMC_TAG "DMC VIOLATION"
/* for T7 */
#define POLICY_INCLUDE BIT(1)
struct dmc_monitor;
struct dmc_mon_ops {
void (*handle_irq)(struct dmc_monitor *mon, void *data);
int (*set_montor)(struct dmc_monitor *mon);
void (*disable)(struct dmc_monitor *mon);
size_t (*dump_reg)(char *buf);
};
struct dmc_monitor {
void __iomem *io_mem1; /* For dmc 1 */
void __iomem *io_mem2; /* For dmc 2 */
void __iomem *io_mem3; /* For dmc 3 */
void __iomem *io_mem4; /* For dmc 4 */
unsigned long io_base; /* For secure world access */
unsigned long addr_start; /* monitor start address */
unsigned long addr_end; /* monitor end address */
u64 device; /* monitor device mask */
u32 mon_number; /* monitor number */
u8 debug; /* monitor debug */
unsigned short port_num; /* how many devices? */
unsigned char chip; /* chip ID */
unsigned char configs; /* config for dmc */
unsigned long last_addr;
unsigned long same_page;
unsigned long last_status;
struct ddr_port_desc *port;
struct dmc_mon_ops *ops;
struct delayed_work work;
};
void dmc_monitor_disable(void);
/*
* start: physical start address, aligned to 64KB
* end: physical end address, aligned to 64KB
* dev_mask: device bit to set
* en: 0: close monitor, 1: enable monitor
*/
int dmc_set_monitor(unsigned long start, unsigned long end,
unsigned long dev_mask, int en);
/*
* start: physical start address, aligned to 64KB
* end: physical end address, aligned to 64KB
* port_name: name of port to set, see ddr_port_desc for each chip in
* drivers/amlogic/ddr_tool/ddr_port_desc.c
* en: 0: close monitor, 1: enable monitor
*/
int dmc_set_monitor_by_name(unsigned long start, unsigned long end,
const char *port_name, int en);
unsigned int get_all_dev_mask(void);
/*
* Following functions are internal used only
*/
unsigned long dmc_prot_rw(void __iomem *base, unsigned long addr,
unsigned long value, int rw);
char *to_ports(int id);
char *to_sub_ports(int mid, int sid, char *id_str);
void show_violation_mem(unsigned long addr);
extern struct dmc_monitor *dmc_mon;
#ifdef CONFIG_AMLOGIC_DMC_MONITOR_GX
extern struct dmc_mon_ops gx_dmc_mon_ops;
#endif
#ifdef CONFIG_AMLOGIC_DMC_MONITOR_G12
extern struct dmc_mon_ops g12_dmc_mon_ops;
#endif
#ifdef CONFIG_AMLOGIC_DMC_MONITOR_C1
extern struct dmc_mon_ops c1_dmc_mon_ops;
#endif
#ifdef CONFIG_AMLOGIC_DMC_MONITOR_TM2
extern struct dmc_mon_ops tm2_dmc_mon_ops;
#endif
#ifdef CONFIG_AMLOGIC_DMC_MONITOR_T7
extern struct dmc_mon_ops t7_dmc_mon_ops;
#endif
#ifdef CONFIG_AMLOGIC_DMC_MONITOR_S4
extern struct dmc_mon_ops s4_dmc_mon_ops;
#endif
#ifdef CONFIG_AMLOGIC_DMC_MONITOR
int __init dmc_monitor_init(void);
void dmc_monitor_exit(void);
#else
static int dmc_monitor_init(void)
{
return 0;
}
void dmc_monitor_exit(void)
{
}
#endif
#ifdef CONFIG_AMLOGIC_USER_FAULT
void set_dump_dmc_func(void *f);
#else
void __weak set_dump_dmc_func(void *f) {}
#endif /* CONFIG_AMLOGIC_USER_FAULT */
#endif /* __DMC_MONITOR_H__ */