18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * cmu.c, Clock Mask Unit routines for the NEC VR4100 series. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2001-2002 MontaVista Software Inc. 68c2ecf20Sopenharmony_ci * Author: Yoichi Yuasa <source@mvista.com> 78c2ecf20Sopenharmony_ci * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@linux-mips.org> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci/* 108c2ecf20Sopenharmony_ci * Changes: 118c2ecf20Sopenharmony_ci * MontaVista Software Inc. <source@mvista.com> 128c2ecf20Sopenharmony_ci * - New creation, NEC VR4122 and VR4131 are supported. 138c2ecf20Sopenharmony_ci * - Added support for NEC VR4111 and VR4121. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * Yoichi Yuasa <yuasa@linux-mips.org> 168c2ecf20Sopenharmony_ci * - Added support for NEC VR4133. 178c2ecf20Sopenharmony_ci */ 188c2ecf20Sopenharmony_ci#include <linux/export.h> 198c2ecf20Sopenharmony_ci#include <linux/init.h> 208c2ecf20Sopenharmony_ci#include <linux/ioport.h> 218c2ecf20Sopenharmony_ci#include <linux/smp.h> 228c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 238c2ecf20Sopenharmony_ci#include <linux/types.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include <asm/cpu.h> 268c2ecf20Sopenharmony_ci#include <asm/io.h> 278c2ecf20Sopenharmony_ci#include <asm/vr41xx/vr41xx.h> 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define CMU_TYPE1_BASE 0x0b000060UL 308c2ecf20Sopenharmony_ci#define CMU_TYPE1_SIZE 0x4 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#define CMU_TYPE2_BASE 0x0f000060UL 338c2ecf20Sopenharmony_ci#define CMU_TYPE2_SIZE 0x4 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define CMU_TYPE3_BASE 0x0f000060UL 368c2ecf20Sopenharmony_ci#define CMU_TYPE3_SIZE 0x8 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#define CMUCLKMSK 0x0 398c2ecf20Sopenharmony_ci #define MSKPIU 0x0001 408c2ecf20Sopenharmony_ci #define MSKSIU 0x0002 418c2ecf20Sopenharmony_ci #define MSKAIU 0x0004 428c2ecf20Sopenharmony_ci #define MSKKIU 0x0008 438c2ecf20Sopenharmony_ci #define MSKFIR 0x0010 448c2ecf20Sopenharmony_ci #define MSKDSIU 0x0820 458c2ecf20Sopenharmony_ci #define MSKCSI 0x0040 468c2ecf20Sopenharmony_ci #define MSKPCIU 0x0080 478c2ecf20Sopenharmony_ci #define MSKSSIU 0x0100 488c2ecf20Sopenharmony_ci #define MSKSHSP 0x0200 498c2ecf20Sopenharmony_ci #define MSKFFIR 0x0400 508c2ecf20Sopenharmony_ci #define MSKSCSI 0x1000 518c2ecf20Sopenharmony_ci #define MSKPPCIU 0x2000 528c2ecf20Sopenharmony_ci#define CMUCLKMSK2 0x4 538c2ecf20Sopenharmony_ci #define MSKCEU 0x0001 548c2ecf20Sopenharmony_ci #define MSKMAC0 0x0002 558c2ecf20Sopenharmony_ci #define MSKMAC1 0x0004 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic void __iomem *cmu_base; 588c2ecf20Sopenharmony_cistatic uint16_t cmuclkmsk, cmuclkmsk2; 598c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(cmu_lock); 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci#define cmu_read(offset) readw(cmu_base + (offset)) 628c2ecf20Sopenharmony_ci#define cmu_write(offset, value) writew((value), cmu_base + (offset)) 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_civoid vr41xx_supply_clock(vr41xx_clock_t clock) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci spin_lock_irq(&cmu_lock); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci switch (clock) { 698c2ecf20Sopenharmony_ci case PIU_CLOCK: 708c2ecf20Sopenharmony_ci cmuclkmsk |= MSKPIU; 718c2ecf20Sopenharmony_ci break; 728c2ecf20Sopenharmony_ci case SIU_CLOCK: 738c2ecf20Sopenharmony_ci cmuclkmsk |= MSKSIU | MSKSSIU; 748c2ecf20Sopenharmony_ci break; 758c2ecf20Sopenharmony_ci case AIU_CLOCK: 768c2ecf20Sopenharmony_ci cmuclkmsk |= MSKAIU; 778c2ecf20Sopenharmony_ci break; 788c2ecf20Sopenharmony_ci case KIU_CLOCK: 798c2ecf20Sopenharmony_ci cmuclkmsk |= MSKKIU; 808c2ecf20Sopenharmony_ci break; 818c2ecf20Sopenharmony_ci case FIR_CLOCK: 828c2ecf20Sopenharmony_ci cmuclkmsk |= MSKFIR | MSKFFIR; 838c2ecf20Sopenharmony_ci break; 848c2ecf20Sopenharmony_ci case DSIU_CLOCK: 858c2ecf20Sopenharmony_ci if (current_cpu_type() == CPU_VR4111 || 868c2ecf20Sopenharmony_ci current_cpu_type() == CPU_VR4121) 878c2ecf20Sopenharmony_ci cmuclkmsk |= MSKDSIU; 888c2ecf20Sopenharmony_ci else 898c2ecf20Sopenharmony_ci cmuclkmsk |= MSKSIU | MSKDSIU; 908c2ecf20Sopenharmony_ci break; 918c2ecf20Sopenharmony_ci case CSI_CLOCK: 928c2ecf20Sopenharmony_ci cmuclkmsk |= MSKCSI | MSKSCSI; 938c2ecf20Sopenharmony_ci break; 948c2ecf20Sopenharmony_ci case PCIU_CLOCK: 958c2ecf20Sopenharmony_ci cmuclkmsk |= MSKPCIU; 968c2ecf20Sopenharmony_ci break; 978c2ecf20Sopenharmony_ci case HSP_CLOCK: 988c2ecf20Sopenharmony_ci cmuclkmsk |= MSKSHSP; 998c2ecf20Sopenharmony_ci break; 1008c2ecf20Sopenharmony_ci case PCI_CLOCK: 1018c2ecf20Sopenharmony_ci cmuclkmsk |= MSKPPCIU; 1028c2ecf20Sopenharmony_ci break; 1038c2ecf20Sopenharmony_ci case CEU_CLOCK: 1048c2ecf20Sopenharmony_ci cmuclkmsk2 |= MSKCEU; 1058c2ecf20Sopenharmony_ci break; 1068c2ecf20Sopenharmony_ci case ETHER0_CLOCK: 1078c2ecf20Sopenharmony_ci cmuclkmsk2 |= MSKMAC0; 1088c2ecf20Sopenharmony_ci break; 1098c2ecf20Sopenharmony_ci case ETHER1_CLOCK: 1108c2ecf20Sopenharmony_ci cmuclkmsk2 |= MSKMAC1; 1118c2ecf20Sopenharmony_ci break; 1128c2ecf20Sopenharmony_ci default: 1138c2ecf20Sopenharmony_ci break; 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci if (clock == CEU_CLOCK || clock == ETHER0_CLOCK || 1178c2ecf20Sopenharmony_ci clock == ETHER1_CLOCK) 1188c2ecf20Sopenharmony_ci cmu_write(CMUCLKMSK2, cmuclkmsk2); 1198c2ecf20Sopenharmony_ci else 1208c2ecf20Sopenharmony_ci cmu_write(CMUCLKMSK, cmuclkmsk); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci spin_unlock_irq(&cmu_lock); 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(vr41xx_supply_clock); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_civoid vr41xx_mask_clock(vr41xx_clock_t clock) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci spin_lock_irq(&cmu_lock); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci switch (clock) { 1328c2ecf20Sopenharmony_ci case PIU_CLOCK: 1338c2ecf20Sopenharmony_ci cmuclkmsk &= ~MSKPIU; 1348c2ecf20Sopenharmony_ci break; 1358c2ecf20Sopenharmony_ci case SIU_CLOCK: 1368c2ecf20Sopenharmony_ci if (current_cpu_type() == CPU_VR4111 || 1378c2ecf20Sopenharmony_ci current_cpu_type() == CPU_VR4121) { 1388c2ecf20Sopenharmony_ci cmuclkmsk &= ~(MSKSIU | MSKSSIU); 1398c2ecf20Sopenharmony_ci } else { 1408c2ecf20Sopenharmony_ci if (cmuclkmsk & MSKDSIU) 1418c2ecf20Sopenharmony_ci cmuclkmsk &= ~MSKSSIU; 1428c2ecf20Sopenharmony_ci else 1438c2ecf20Sopenharmony_ci cmuclkmsk &= ~(MSKSIU | MSKSSIU); 1448c2ecf20Sopenharmony_ci } 1458c2ecf20Sopenharmony_ci break; 1468c2ecf20Sopenharmony_ci case AIU_CLOCK: 1478c2ecf20Sopenharmony_ci cmuclkmsk &= ~MSKAIU; 1488c2ecf20Sopenharmony_ci break; 1498c2ecf20Sopenharmony_ci case KIU_CLOCK: 1508c2ecf20Sopenharmony_ci cmuclkmsk &= ~MSKKIU; 1518c2ecf20Sopenharmony_ci break; 1528c2ecf20Sopenharmony_ci case FIR_CLOCK: 1538c2ecf20Sopenharmony_ci cmuclkmsk &= ~(MSKFIR | MSKFFIR); 1548c2ecf20Sopenharmony_ci break; 1558c2ecf20Sopenharmony_ci case DSIU_CLOCK: 1568c2ecf20Sopenharmony_ci if (current_cpu_type() == CPU_VR4111 || 1578c2ecf20Sopenharmony_ci current_cpu_type() == CPU_VR4121) { 1588c2ecf20Sopenharmony_ci cmuclkmsk &= ~MSKDSIU; 1598c2ecf20Sopenharmony_ci } else { 1608c2ecf20Sopenharmony_ci if (cmuclkmsk & MSKSSIU) 1618c2ecf20Sopenharmony_ci cmuclkmsk &= ~MSKDSIU; 1628c2ecf20Sopenharmony_ci else 1638c2ecf20Sopenharmony_ci cmuclkmsk &= ~(MSKSIU | MSKDSIU); 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci break; 1668c2ecf20Sopenharmony_ci case CSI_CLOCK: 1678c2ecf20Sopenharmony_ci cmuclkmsk &= ~(MSKCSI | MSKSCSI); 1688c2ecf20Sopenharmony_ci break; 1698c2ecf20Sopenharmony_ci case PCIU_CLOCK: 1708c2ecf20Sopenharmony_ci cmuclkmsk &= ~MSKPCIU; 1718c2ecf20Sopenharmony_ci break; 1728c2ecf20Sopenharmony_ci case HSP_CLOCK: 1738c2ecf20Sopenharmony_ci cmuclkmsk &= ~MSKSHSP; 1748c2ecf20Sopenharmony_ci break; 1758c2ecf20Sopenharmony_ci case PCI_CLOCK: 1768c2ecf20Sopenharmony_ci cmuclkmsk &= ~MSKPPCIU; 1778c2ecf20Sopenharmony_ci break; 1788c2ecf20Sopenharmony_ci case CEU_CLOCK: 1798c2ecf20Sopenharmony_ci cmuclkmsk2 &= ~MSKCEU; 1808c2ecf20Sopenharmony_ci break; 1818c2ecf20Sopenharmony_ci case ETHER0_CLOCK: 1828c2ecf20Sopenharmony_ci cmuclkmsk2 &= ~MSKMAC0; 1838c2ecf20Sopenharmony_ci break; 1848c2ecf20Sopenharmony_ci case ETHER1_CLOCK: 1858c2ecf20Sopenharmony_ci cmuclkmsk2 &= ~MSKMAC1; 1868c2ecf20Sopenharmony_ci break; 1878c2ecf20Sopenharmony_ci default: 1888c2ecf20Sopenharmony_ci break; 1898c2ecf20Sopenharmony_ci } 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci if (clock == CEU_CLOCK || clock == ETHER0_CLOCK || 1928c2ecf20Sopenharmony_ci clock == ETHER1_CLOCK) 1938c2ecf20Sopenharmony_ci cmu_write(CMUCLKMSK2, cmuclkmsk2); 1948c2ecf20Sopenharmony_ci else 1958c2ecf20Sopenharmony_ci cmu_write(CMUCLKMSK, cmuclkmsk); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci spin_unlock_irq(&cmu_lock); 1988c2ecf20Sopenharmony_ci} 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(vr41xx_mask_clock); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cistatic int __init vr41xx_cmu_init(void) 2038c2ecf20Sopenharmony_ci{ 2048c2ecf20Sopenharmony_ci unsigned long start, size; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci switch (current_cpu_type()) { 2078c2ecf20Sopenharmony_ci case CPU_VR4111: 2088c2ecf20Sopenharmony_ci case CPU_VR4121: 2098c2ecf20Sopenharmony_ci start = CMU_TYPE1_BASE; 2108c2ecf20Sopenharmony_ci size = CMU_TYPE1_SIZE; 2118c2ecf20Sopenharmony_ci break; 2128c2ecf20Sopenharmony_ci case CPU_VR4122: 2138c2ecf20Sopenharmony_ci case CPU_VR4131: 2148c2ecf20Sopenharmony_ci start = CMU_TYPE2_BASE; 2158c2ecf20Sopenharmony_ci size = CMU_TYPE2_SIZE; 2168c2ecf20Sopenharmony_ci break; 2178c2ecf20Sopenharmony_ci case CPU_VR4133: 2188c2ecf20Sopenharmony_ci start = CMU_TYPE3_BASE; 2198c2ecf20Sopenharmony_ci size = CMU_TYPE3_SIZE; 2208c2ecf20Sopenharmony_ci break; 2218c2ecf20Sopenharmony_ci default: 2228c2ecf20Sopenharmony_ci panic("Unexpected CPU of NEC VR4100 series"); 2238c2ecf20Sopenharmony_ci break; 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci if (request_mem_region(start, size, "CMU") == NULL) 2278c2ecf20Sopenharmony_ci return -EBUSY; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci cmu_base = ioremap(start, size); 2308c2ecf20Sopenharmony_ci if (cmu_base == NULL) { 2318c2ecf20Sopenharmony_ci release_mem_region(start, size); 2328c2ecf20Sopenharmony_ci return -EBUSY; 2338c2ecf20Sopenharmony_ci } 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci cmuclkmsk = cmu_read(CMUCLKMSK); 2368c2ecf20Sopenharmony_ci if (current_cpu_type() == CPU_VR4133) 2378c2ecf20Sopenharmony_ci cmuclkmsk2 = cmu_read(CMUCLKMSK2); 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci spin_lock_init(&cmu_lock); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci return 0; 2428c2ecf20Sopenharmony_ci} 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_cicore_initcall(vr41xx_cmu_init); 245