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