cmu.c (5010B)
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 return 0; 240} 241 242core_initcall(vr41xx_cmu_init);