linux/arch/sh/kernel/cpu/sh4a/ubc.c
<<
>>
Prefs
   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