• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/arch/sh/kernel/cpu/sh4a/
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
33static struct sh_ubc sh4a_ubc;
34
35static 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
41static 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
47static 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
57static 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
66static 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
78static unsigned long sh4a_ubc_triggered_mask(void)
79{
80	return __raw_readl(UBC_CCMFR);
81}
82
83static void sh4a_ubc_clear_triggered_mask(unsigned long mask)
84{
85	__raw_writel(__raw_readl(UBC_CCMFR) & ~mask, UBC_CCMFR);
86}
87
88static 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
101static 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}
133arch_initcall(sh4a_ubc_init);
134