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