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