1// SPDX-License-Identifier: GPL-2.0
2/*
3 * arch/sh/kernel/cpu/sh4a/ubc.c
4 *
5 * On-chip UBC support for SH-4A CPUs.
6 *
7 * Copyright (C) 2009 - 2010  Paul Mundt
8 */
9#include <linux/init.h>
10#include <linux/err.h>
11#include <linux/clk.h>
12#include <linux/io.h>
13#include <asm/hw_breakpoint.h>
14
15#define UBC_CBR(idx)	(0xff200000 + (0x20 * idx))
16#define UBC_CRR(idx)	(0xff200004 + (0x20 * idx))
17#define UBC_CAR(idx)	(0xff200008 + (0x20 * idx))
18#define UBC_CAMR(idx)	(0xff20000c + (0x20 * idx))
19
20#define UBC_CCMFR	0xff200600
21#define UBC_CBCR	0xff200620
22
23/* CRR */
24#define UBC_CRR_PCB	(1 << 1)
25#define UBC_CRR_BIE	(1 << 0)
26
27/* CBR */
28#define UBC_CBR_CE	(1 << 0)
29
30static struct sh_ubc sh4a_ubc;
31
32static void sh4a_ubc_enable(struct arch_hw_breakpoint *info, int idx)
33{
34	__raw_writel(UBC_CBR_CE | info->len | info->type, UBC_CBR(idx));
35	__raw_writel(info->address, UBC_CAR(idx));
36}
37
38static void sh4a_ubc_disable(struct arch_hw_breakpoint *info, int idx)
39{
40	__raw_writel(0, UBC_CBR(idx));
41	__raw_writel(0, UBC_CAR(idx));
42}
43
44static void sh4a_ubc_enable_all(unsigned long mask)
45{
46	int i;
47
48	for (i = 0; i < sh4a_ubc.num_events; i++)
49		if (mask & (1 << i))
50			__raw_writel(__raw_readl(UBC_CBR(i)) | UBC_CBR_CE,
51				     UBC_CBR(i));
52}
53
54static void sh4a_ubc_disable_all(void)
55{
56	int i;
57
58	for (i = 0; i < sh4a_ubc.num_events; i++)
59		__raw_writel(__raw_readl(UBC_CBR(i)) & ~UBC_CBR_CE,
60			     UBC_CBR(i));
61}
62
63static unsigned long sh4a_ubc_active_mask(void)
64{
65	unsigned long active = 0;
66	int i;
67
68	for (i = 0; i < sh4a_ubc.num_events; i++)
69		if (__raw_readl(UBC_CBR(i)) & UBC_CBR_CE)
70			active |= (1 << i);
71
72	return active;
73}
74
75static unsigned long sh4a_ubc_triggered_mask(void)
76{
77	return __raw_readl(UBC_CCMFR);
78}
79
80static void sh4a_ubc_clear_triggered_mask(unsigned long mask)
81{
82	__raw_writel(__raw_readl(UBC_CCMFR) & ~mask, UBC_CCMFR);
83}
84
85static struct sh_ubc sh4a_ubc = {
86	.name			= "SH-4A",
87	.num_events		= 2,
88	.trap_nr		= 0x1e0,
89	.enable			= sh4a_ubc_enable,
90	.disable		= sh4a_ubc_disable,
91	.enable_all		= sh4a_ubc_enable_all,
92	.disable_all		= sh4a_ubc_disable_all,
93	.active_mask		= sh4a_ubc_active_mask,
94	.triggered_mask		= sh4a_ubc_triggered_mask,
95	.clear_triggered_mask	= sh4a_ubc_clear_triggered_mask,
96};
97
98static int __init sh4a_ubc_init(void)
99{
100	struct clk *ubc_iclk = clk_get(NULL, "ubc0");
101	int i;
102
103	/*
104	 * The UBC MSTP bit is optional, as not all platforms will have
105	 * it. Just ignore it if we can't find it.
106	 */
107	if (IS_ERR(ubc_iclk))
108		ubc_iclk = NULL;
109
110	clk_enable(ubc_iclk);
111
112	__raw_writel(0, UBC_CBCR);
113
114	for (i = 0; i < sh4a_ubc.num_events; i++) {
115		__raw_writel(0, UBC_CAMR(i));
116		__raw_writel(0, UBC_CBR(i));
117
118		__raw_writel(UBC_CRR_BIE | UBC_CRR_PCB, UBC_CRR(i));
119
120		/* dummy read for write posting */
121		(void)__raw_readl(UBC_CRR(i));
122	}
123
124	clk_disable(ubc_iclk);
125
126	sh4a_ubc.clk = ubc_iclk;
127
128	return register_sh_ubc(&sh4a_ubc);
129}
130arch_initcall(sh4a_ubc_init);
131