linux/arch/mips/vr41xx/common/cmu.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  cmu.c, Clock Mask Unit routines for the NEC VR4100 series.
   4 *
   5 *  Copyright (C) 2001-2002  MontaVista Software Inc.
   6 *    Author: Yoichi Yuasa <source@mvista.com>
   7 *  Copyright (C) 2003-2005  Yoichi Yuasa <yuasa@linux-mips.org>
   8 */
   9/*
  10 * Changes:
  11 *  MontaVista Software Inc. <source@mvista.com>
  12 *  - New creation, NEC VR4122 and VR4131 are supported.
  13 *  - Added support for NEC VR4111 and VR4121.
  14 *
  15 *  Yoichi Yuasa <yuasa@linux-mips.org>
  16 *  - Added support for NEC VR4133.
  17 */
  18#include <linux/export.h>
  19#include <linux/init.h>
  20#include <linux/ioport.h>
  21#include <linux/smp.h>
  22#include <linux/spinlock.h>
  23#include <linux/types.h>
  24
  25#include <asm/cpu.h>
  26#include <asm/io.h>
  27#include <asm/vr41xx/vr41xx.h>
  28
  29#define CMU_TYPE1_BASE  0x0b000060UL
  30#define CMU_TYPE1_SIZE  0x4
  31
  32#define CMU_TYPE2_BASE  0x0f000060UL
  33#define CMU_TYPE2_SIZE  0x4
  34
  35#define CMU_TYPE3_BASE  0x0f000060UL
  36#define CMU_TYPE3_SIZE  0x8
  37
  38#define CMUCLKMSK       0x0
  39 #define MSKPIU         0x0001
  40 #define MSKSIU         0x0002
  41 #define MSKAIU         0x0004
  42 #define MSKKIU         0x0008
  43 #define MSKFIR         0x0010
  44 #define MSKDSIU        0x0820
  45 #define MSKCSI         0x0040
  46 #define MSKPCIU        0x0080
  47 #define MSKSSIU        0x0100
  48 #define MSKSHSP        0x0200
  49 #define MSKFFIR        0x0400
  50 #define MSKSCSI        0x1000
  51 #define MSKPPCIU       0x2000
  52#define CMUCLKMSK2      0x4
  53 #define MSKCEU         0x0001
  54 #define MSKMAC0        0x0002
  55 #define MSKMAC1        0x0004
  56
  57static void __iomem *cmu_base;
  58static uint16_t cmuclkmsk, cmuclkmsk2;
  59static DEFINE_SPINLOCK(cmu_lock);
  60
  61#define cmu_read(offset)                readw(cmu_base + (offset))
  62#define cmu_write(offset, value)        writew((value), cmu_base + (offset))
  63
  64void vr41xx_supply_clock(vr41xx_clock_t clock)
  65{
  66        spin_lock_irq(&cmu_lock);
  67
  68        switch (clock) {
  69        case PIU_CLOCK:
  70                cmuclkmsk |= MSKPIU;
  71                break;
  72        case SIU_CLOCK:
  73                cmuclkmsk |= MSKSIU | MSKSSIU;
  74                break;
  75        case AIU_CLOCK:
  76                cmuclkmsk |= MSKAIU;
  77                break;
  78        case KIU_CLOCK:
  79                cmuclkmsk |= MSKKIU;
  80                break;
  81        case FIR_CLOCK:
  82                cmuclkmsk |= MSKFIR | MSKFFIR;
  83                break;
  84        case DSIU_CLOCK:
  85                if (current_cpu_type() == CPU_VR4111 ||
  86                    current_cpu_type() == CPU_VR4121)
  87                        cmuclkmsk |= MSKDSIU;
  88                else
  89                        cmuclkmsk |= MSKSIU | MSKDSIU;
  90                break;
  91        case CSI_CLOCK:
  92                cmuclkmsk |= MSKCSI | MSKSCSI;
  93                break;
  94        case PCIU_CLOCK:
  95                cmuclkmsk |= MSKPCIU;
  96                break;
  97        case HSP_CLOCK:
  98                cmuclkmsk |= MSKSHSP;
  99                break;
 100        case PCI_CLOCK:
 101                cmuclkmsk |= MSKPPCIU;
 102                break;
 103        case CEU_CLOCK:
 104                cmuclkmsk2 |= MSKCEU;
 105                break;
 106        case ETHER0_CLOCK:
 107                cmuclkmsk2 |= MSKMAC0;
 108                break;
 109        case ETHER1_CLOCK:
 110                cmuclkmsk2 |= MSKMAC1;
 111                break;
 112        default:
 113                break;
 114        }
 115
 116        if (clock == CEU_CLOCK || clock == ETHER0_CLOCK ||
 117            clock == ETHER1_CLOCK)
 118                cmu_write(CMUCLKMSK2, cmuclkmsk2);
 119        else
 120                cmu_write(CMUCLKMSK, cmuclkmsk);
 121
 122        spin_unlock_irq(&cmu_lock);
 123}
 124
 125EXPORT_SYMBOL_GPL(vr41xx_supply_clock);
 126
 127void vr41xx_mask_clock(vr41xx_clock_t clock)
 128{
 129        spin_lock_irq(&cmu_lock);
 130
 131        switch (clock) {
 132        case PIU_CLOCK:
 133                cmuclkmsk &= ~MSKPIU;
 134                break;
 135        case SIU_CLOCK:
 136                if (current_cpu_type() == CPU_VR4111 ||
 137                    current_cpu_type() == CPU_VR4121) {
 138                        cmuclkmsk &= ~(MSKSIU | MSKSSIU);
 139                } else {
 140                        if (cmuclkmsk & MSKDSIU)
 141                                cmuclkmsk &= ~MSKSSIU;
 142                        else
 143                                cmuclkmsk &= ~(MSKSIU | MSKSSIU);
 144                }
 145                break;
 146        case AIU_CLOCK:
 147                cmuclkmsk &= ~MSKAIU;
 148                break;
 149        case KIU_CLOCK:
 150                cmuclkmsk &= ~MSKKIU;
 151                break;
 152        case FIR_CLOCK:
 153                cmuclkmsk &= ~(MSKFIR | MSKFFIR);
 154                break;
 155        case DSIU_CLOCK:
 156                if (current_cpu_type() == CPU_VR4111 ||
 157                    current_cpu_type() == CPU_VR4121) {
 158                        cmuclkmsk &= ~MSKDSIU;
 159                } else {
 160                        if (cmuclkmsk & MSKSSIU)
 161                                cmuclkmsk &= ~MSKDSIU;
 162                        else
 163                                cmuclkmsk &= ~(MSKSIU | MSKDSIU);
 164                }
 165                break;
 166        case CSI_CLOCK:
 167                cmuclkmsk &= ~(MSKCSI | MSKSCSI);
 168                break;
 169        case PCIU_CLOCK:
 170                cmuclkmsk &= ~MSKPCIU;
 171                break;
 172        case HSP_CLOCK:
 173                cmuclkmsk &= ~MSKSHSP;
 174                break;
 175        case PCI_CLOCK:
 176                cmuclkmsk &= ~MSKPPCIU;
 177                break;
 178        case CEU_CLOCK:
 179                cmuclkmsk2 &= ~MSKCEU;
 180                break;
 181        case ETHER0_CLOCK:
 182                cmuclkmsk2 &= ~MSKMAC0;
 183                break;
 184        case ETHER1_CLOCK:
 185                cmuclkmsk2 &= ~MSKMAC1;
 186                break;
 187        default:
 188                break;
 189        }
 190
 191        if (clock == CEU_CLOCK || clock == ETHER0_CLOCK ||
 192            clock == ETHER1_CLOCK)
 193                cmu_write(CMUCLKMSK2, cmuclkmsk2);
 194        else
 195                cmu_write(CMUCLKMSK, cmuclkmsk);
 196
 197        spin_unlock_irq(&cmu_lock);
 198}
 199
 200EXPORT_SYMBOL_GPL(vr41xx_mask_clock);
 201
 202static int __init vr41xx_cmu_init(void)
 203{
 204        unsigned long start, size;
 205
 206        switch (current_cpu_type()) {
 207        case CPU_VR4111:
 208        case CPU_VR4121:
 209                start = CMU_TYPE1_BASE;
 210                size = CMU_TYPE1_SIZE;
 211                break;
 212        case CPU_VR4122:
 213        case CPU_VR4131:
 214                start = CMU_TYPE2_BASE;
 215                size = CMU_TYPE2_SIZE;
 216                break;
 217        case CPU_VR4133:
 218                start = CMU_TYPE3_BASE;
 219                size = CMU_TYPE3_SIZE;
 220                break;
 221        default:
 222                panic("Unexpected CPU of NEC VR4100 series");
 223                break;
 224        }
 225
 226        if (request_mem_region(start, size, "CMU") == NULL)
 227                return -EBUSY;
 228
 229        cmu_base = ioremap(start, size);
 230        if (cmu_base == NULL) {
 231                release_mem_region(start, size);
 232                return -EBUSY;
 233        }
 234
 235        cmuclkmsk = cmu_read(CMUCLKMSK);
 236        if (current_cpu_type() == CPU_VR4133)
 237                cmuclkmsk2 = cmu_read(CMUCLKMSK2);
 238
 239        spin_lock_init(&cmu_lock);
 240
 241        return 0;
 242}
 243
 244core_initcall(vr41xx_cmu_init);
 245