ubc.c (2858B)
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);