18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * arch/m68k/mvme16x/config.c 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 1995 Richard Hirst [richard@sleepie.demon.co.uk] 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Based on: 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * linux/amiga/config.c 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Copyright (C) 1993 Hamish Macdonald 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 138c2ecf20Sopenharmony_ci * License. See the file README.legal in the main directory of this archive 148c2ecf20Sopenharmony_ci * for more details. 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <linux/types.h> 188c2ecf20Sopenharmony_ci#include <linux/kernel.h> 198c2ecf20Sopenharmony_ci#include <linux/mm.h> 208c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 218c2ecf20Sopenharmony_ci#include <linux/tty.h> 228c2ecf20Sopenharmony_ci#include <linux/clocksource.h> 238c2ecf20Sopenharmony_ci#include <linux/console.h> 248c2ecf20Sopenharmony_ci#include <linux/linkage.h> 258c2ecf20Sopenharmony_ci#include <linux/init.h> 268c2ecf20Sopenharmony_ci#include <linux/major.h> 278c2ecf20Sopenharmony_ci#include <linux/genhd.h> 288c2ecf20Sopenharmony_ci#include <linux/rtc.h> 298c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 308c2ecf20Sopenharmony_ci#include <linux/module.h> 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#include <asm/bootinfo.h> 338c2ecf20Sopenharmony_ci#include <asm/bootinfo-vme.h> 348c2ecf20Sopenharmony_ci#include <asm/byteorder.h> 358c2ecf20Sopenharmony_ci#include <asm/setup.h> 368c2ecf20Sopenharmony_ci#include <asm/irq.h> 378c2ecf20Sopenharmony_ci#include <asm/traps.h> 388c2ecf20Sopenharmony_ci#include <asm/machdep.h> 398c2ecf20Sopenharmony_ci#include <asm/mvme16xhw.h> 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ciextern t_bdid mvme_bdid; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_cistatic MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic void mvme16x_get_model(char *model); 468c2ecf20Sopenharmony_ciextern void mvme16x_sched_init(irq_handler_t handler); 478c2ecf20Sopenharmony_ciextern int mvme16x_hwclk (int, struct rtc_time *); 488c2ecf20Sopenharmony_ciextern void mvme16x_reset (void); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ciint bcd2int (unsigned char b); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ciunsigned short mvme16x_config; 548c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mvme16x_config); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ciint __init mvme16x_parse_bootinfo(const struct bi_record *bi) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci uint16_t tag = be16_to_cpu(bi->tag); 608c2ecf20Sopenharmony_ci if (tag == BI_VME_TYPE || tag == BI_VME_BRDINFO) 618c2ecf20Sopenharmony_ci return 0; 628c2ecf20Sopenharmony_ci else 638c2ecf20Sopenharmony_ci return 1; 648c2ecf20Sopenharmony_ci} 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_civoid mvme16x_reset(void) 678c2ecf20Sopenharmony_ci{ 688c2ecf20Sopenharmony_ci pr_info("\r\n\nCalled mvme16x_reset\r\n" 698c2ecf20Sopenharmony_ci "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r"); 708c2ecf20Sopenharmony_ci /* The string of returns is to delay the reset until the whole 718c2ecf20Sopenharmony_ci * message is output. Assert reset bit in GCSR */ 728c2ecf20Sopenharmony_ci *(volatile char *)0xfff40107 = 0x80; 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic void mvme16x_get_model(char *model) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci p_bdid p = &mvme_bdid; 788c2ecf20Sopenharmony_ci char suf[4]; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci suf[1] = p->brdsuffix[0]; 818c2ecf20Sopenharmony_ci suf[2] = p->brdsuffix[1]; 828c2ecf20Sopenharmony_ci suf[3] = '\0'; 838c2ecf20Sopenharmony_ci suf[0] = suf[1] ? '-' : '\0'; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci sprintf(model, "Motorola MVME%x%s", be16_to_cpu(p->brdno), suf); 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic void mvme16x_get_hardware_list(struct seq_file *m) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci uint16_t brdno = be16_to_cpu(mvme_bdid.brdno); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci if (brdno == 0x0162 || brdno == 0x0172) 948c2ecf20Sopenharmony_ci { 958c2ecf20Sopenharmony_ci unsigned char rev = *(unsigned char *)MVME162_VERSION_REG; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci seq_printf (m, "VMEchip2 %spresent\n", 988c2ecf20Sopenharmony_ci rev & MVME16x_CONFIG_NO_VMECHIP2 ? "NOT " : ""); 998c2ecf20Sopenharmony_ci seq_printf (m, "SCSI interface %spresent\n", 1008c2ecf20Sopenharmony_ci rev & MVME16x_CONFIG_NO_SCSICHIP ? "NOT " : ""); 1018c2ecf20Sopenharmony_ci seq_printf (m, "Ethernet i/f %spresent\n", 1028c2ecf20Sopenharmony_ci rev & MVME16x_CONFIG_NO_ETHERNET ? "NOT " : ""); 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci/* 1078c2ecf20Sopenharmony_ci * This function is called during kernel startup to initialize 1088c2ecf20Sopenharmony_ci * the mvme16x IRQ handling routines. Should probably ensure 1098c2ecf20Sopenharmony_ci * that the base vectors for the VMEChip2 and PCCChip2 are valid. 1108c2ecf20Sopenharmony_ci */ 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cistatic void __init mvme16x_init_IRQ (void) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci m68k_setup_user_interrupt(VEC_USER, 192); 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci#define PCC2CHIP (0xfff42000) 1188c2ecf20Sopenharmony_ci#define PCCSCCMICR (PCC2CHIP + 0x1d) 1198c2ecf20Sopenharmony_ci#define PCCSCCTICR (PCC2CHIP + 0x1e) 1208c2ecf20Sopenharmony_ci#define PCCSCCRICR (PCC2CHIP + 0x1f) 1218c2ecf20Sopenharmony_ci#define PCCTPIACKR (PCC2CHIP + 0x25) 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci#ifdef CONFIG_EARLY_PRINTK 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci/**** cd2401 registers ****/ 1268c2ecf20Sopenharmony_ci#define CD2401_ADDR (0xfff45000) 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci#define CyGFRCR (0x81) 1298c2ecf20Sopenharmony_ci#define CyCCR (0x13) 1308c2ecf20Sopenharmony_ci#define CyCLR_CHAN (0x40) 1318c2ecf20Sopenharmony_ci#define CyINIT_CHAN (0x20) 1328c2ecf20Sopenharmony_ci#define CyCHIP_RESET (0x10) 1338c2ecf20Sopenharmony_ci#define CyENB_XMTR (0x08) 1348c2ecf20Sopenharmony_ci#define CyDIS_XMTR (0x04) 1358c2ecf20Sopenharmony_ci#define CyENB_RCVR (0x02) 1368c2ecf20Sopenharmony_ci#define CyDIS_RCVR (0x01) 1378c2ecf20Sopenharmony_ci#define CyCAR (0xee) 1388c2ecf20Sopenharmony_ci#define CyIER (0x11) 1398c2ecf20Sopenharmony_ci#define CyMdmCh (0x80) 1408c2ecf20Sopenharmony_ci#define CyRxExc (0x20) 1418c2ecf20Sopenharmony_ci#define CyRxData (0x08) 1428c2ecf20Sopenharmony_ci#define CyTxMpty (0x02) 1438c2ecf20Sopenharmony_ci#define CyTxRdy (0x01) 1448c2ecf20Sopenharmony_ci#define CyLICR (0x26) 1458c2ecf20Sopenharmony_ci#define CyRISR (0x89) 1468c2ecf20Sopenharmony_ci#define CyTIMEOUT (0x80) 1478c2ecf20Sopenharmony_ci#define CySPECHAR (0x70) 1488c2ecf20Sopenharmony_ci#define CyOVERRUN (0x08) 1498c2ecf20Sopenharmony_ci#define CyPARITY (0x04) 1508c2ecf20Sopenharmony_ci#define CyFRAME (0x02) 1518c2ecf20Sopenharmony_ci#define CyBREAK (0x01) 1528c2ecf20Sopenharmony_ci#define CyREOIR (0x84) 1538c2ecf20Sopenharmony_ci#define CyTEOIR (0x85) 1548c2ecf20Sopenharmony_ci#define CyMEOIR (0x86) 1558c2ecf20Sopenharmony_ci#define CyNOTRANS (0x08) 1568c2ecf20Sopenharmony_ci#define CyRFOC (0x30) 1578c2ecf20Sopenharmony_ci#define CyRDR (0xf8) 1588c2ecf20Sopenharmony_ci#define CyTDR (0xf8) 1598c2ecf20Sopenharmony_ci#define CyMISR (0x8b) 1608c2ecf20Sopenharmony_ci#define CyRISR (0x89) 1618c2ecf20Sopenharmony_ci#define CyTISR (0x8a) 1628c2ecf20Sopenharmony_ci#define CyMSVR1 (0xde) 1638c2ecf20Sopenharmony_ci#define CyMSVR2 (0xdf) 1648c2ecf20Sopenharmony_ci#define CyDSR (0x80) 1658c2ecf20Sopenharmony_ci#define CyDCD (0x40) 1668c2ecf20Sopenharmony_ci#define CyCTS (0x20) 1678c2ecf20Sopenharmony_ci#define CyDTR (0x02) 1688c2ecf20Sopenharmony_ci#define CyRTS (0x01) 1698c2ecf20Sopenharmony_ci#define CyRTPRL (0x25) 1708c2ecf20Sopenharmony_ci#define CyRTPRH (0x24) 1718c2ecf20Sopenharmony_ci#define CyCOR1 (0x10) 1728c2ecf20Sopenharmony_ci#define CyPARITY_NONE (0x00) 1738c2ecf20Sopenharmony_ci#define CyPARITY_E (0x40) 1748c2ecf20Sopenharmony_ci#define CyPARITY_O (0xC0) 1758c2ecf20Sopenharmony_ci#define Cy_5_BITS (0x04) 1768c2ecf20Sopenharmony_ci#define Cy_6_BITS (0x05) 1778c2ecf20Sopenharmony_ci#define Cy_7_BITS (0x06) 1788c2ecf20Sopenharmony_ci#define Cy_8_BITS (0x07) 1798c2ecf20Sopenharmony_ci#define CyCOR2 (0x17) 1808c2ecf20Sopenharmony_ci#define CyETC (0x20) 1818c2ecf20Sopenharmony_ci#define CyCtsAE (0x02) 1828c2ecf20Sopenharmony_ci#define CyCOR3 (0x16) 1838c2ecf20Sopenharmony_ci#define Cy_1_STOP (0x02) 1848c2ecf20Sopenharmony_ci#define Cy_2_STOP (0x04) 1858c2ecf20Sopenharmony_ci#define CyCOR4 (0x15) 1868c2ecf20Sopenharmony_ci#define CyREC_FIFO (0x0F) /* Receive FIFO threshold */ 1878c2ecf20Sopenharmony_ci#define CyCOR5 (0x14) 1888c2ecf20Sopenharmony_ci#define CyCOR6 (0x18) 1898c2ecf20Sopenharmony_ci#define CyCOR7 (0x07) 1908c2ecf20Sopenharmony_ci#define CyRBPR (0xcb) 1918c2ecf20Sopenharmony_ci#define CyRCOR (0xc8) 1928c2ecf20Sopenharmony_ci#define CyTBPR (0xc3) 1938c2ecf20Sopenharmony_ci#define CyTCOR (0xc0) 1948c2ecf20Sopenharmony_ci#define CySCHR1 (0x1f) 1958c2ecf20Sopenharmony_ci#define CySCHR2 (0x1e) 1968c2ecf20Sopenharmony_ci#define CyTPR (0xda) 1978c2ecf20Sopenharmony_ci#define CyPILR1 (0xe3) 1988c2ecf20Sopenharmony_ci#define CyPILR2 (0xe0) 1998c2ecf20Sopenharmony_ci#define CyPILR3 (0xe1) 2008c2ecf20Sopenharmony_ci#define CyCMR (0x1b) 2018c2ecf20Sopenharmony_ci#define CyASYNC (0x02) 2028c2ecf20Sopenharmony_ci#define CyLICR (0x26) 2038c2ecf20Sopenharmony_ci#define CyLIVR (0x09) 2048c2ecf20Sopenharmony_ci#define CySCRL (0x23) 2058c2ecf20Sopenharmony_ci#define CySCRH (0x22) 2068c2ecf20Sopenharmony_ci#define CyTFTC (0x80) 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_civoid mvme16x_cons_write(struct console *co, const char *str, unsigned count) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci volatile unsigned char *base_addr = (u_char *)CD2401_ADDR; 2118c2ecf20Sopenharmony_ci volatile u_char sink; 2128c2ecf20Sopenharmony_ci u_char ier; 2138c2ecf20Sopenharmony_ci int port; 2148c2ecf20Sopenharmony_ci u_char do_lf = 0; 2158c2ecf20Sopenharmony_ci int i = 0; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci /* Ensure transmitter is enabled! */ 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci port = 0; 2208c2ecf20Sopenharmony_ci base_addr[CyCAR] = (u_char)port; 2218c2ecf20Sopenharmony_ci while (base_addr[CyCCR]) 2228c2ecf20Sopenharmony_ci ; 2238c2ecf20Sopenharmony_ci base_addr[CyCCR] = CyENB_XMTR; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci ier = base_addr[CyIER]; 2268c2ecf20Sopenharmony_ci base_addr[CyIER] = CyTxMpty; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci while (1) { 2298c2ecf20Sopenharmony_ci if (in_8(PCCSCCTICR) & 0x20) 2308c2ecf20Sopenharmony_ci { 2318c2ecf20Sopenharmony_ci /* We have a Tx int. Acknowledge it */ 2328c2ecf20Sopenharmony_ci sink = in_8(PCCTPIACKR); 2338c2ecf20Sopenharmony_ci if ((base_addr[CyLICR] >> 2) == port) { 2348c2ecf20Sopenharmony_ci if (i == count) { 2358c2ecf20Sopenharmony_ci /* Last char of string is now output */ 2368c2ecf20Sopenharmony_ci base_addr[CyTEOIR] = CyNOTRANS; 2378c2ecf20Sopenharmony_ci break; 2388c2ecf20Sopenharmony_ci } 2398c2ecf20Sopenharmony_ci if (do_lf) { 2408c2ecf20Sopenharmony_ci base_addr[CyTDR] = '\n'; 2418c2ecf20Sopenharmony_ci str++; 2428c2ecf20Sopenharmony_ci i++; 2438c2ecf20Sopenharmony_ci do_lf = 0; 2448c2ecf20Sopenharmony_ci } 2458c2ecf20Sopenharmony_ci else if (*str == '\n') { 2468c2ecf20Sopenharmony_ci base_addr[CyTDR] = '\r'; 2478c2ecf20Sopenharmony_ci do_lf = 1; 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci else { 2508c2ecf20Sopenharmony_ci base_addr[CyTDR] = *str++; 2518c2ecf20Sopenharmony_ci i++; 2528c2ecf20Sopenharmony_ci } 2538c2ecf20Sopenharmony_ci base_addr[CyTEOIR] = 0; 2548c2ecf20Sopenharmony_ci } 2558c2ecf20Sopenharmony_ci else 2568c2ecf20Sopenharmony_ci base_addr[CyTEOIR] = CyNOTRANS; 2578c2ecf20Sopenharmony_ci } 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci base_addr[CyIER] = ier; 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci#endif 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_civoid __init config_mvme16x(void) 2668c2ecf20Sopenharmony_ci{ 2678c2ecf20Sopenharmony_ci p_bdid p = &mvme_bdid; 2688c2ecf20Sopenharmony_ci char id[40]; 2698c2ecf20Sopenharmony_ci uint16_t brdno = be16_to_cpu(p->brdno); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci mach_max_dma_address = 0xffffffff; 2728c2ecf20Sopenharmony_ci mach_sched_init = mvme16x_sched_init; 2738c2ecf20Sopenharmony_ci mach_init_IRQ = mvme16x_init_IRQ; 2748c2ecf20Sopenharmony_ci mach_hwclk = mvme16x_hwclk; 2758c2ecf20Sopenharmony_ci mach_reset = mvme16x_reset; 2768c2ecf20Sopenharmony_ci mach_get_model = mvme16x_get_model; 2778c2ecf20Sopenharmony_ci mach_get_hardware_list = mvme16x_get_hardware_list; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci /* Report board revision */ 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci if (strncmp("BDID", p->bdid, 4)) 2828c2ecf20Sopenharmony_ci { 2838c2ecf20Sopenharmony_ci pr_crit("Bug call .BRD_ID returned garbage - giving up\n"); 2848c2ecf20Sopenharmony_ci while (1) 2858c2ecf20Sopenharmony_ci ; 2868c2ecf20Sopenharmony_ci } 2878c2ecf20Sopenharmony_ci /* Board type is only set by newer versions of vmelilo/tftplilo */ 2888c2ecf20Sopenharmony_ci if (vme_brdtype == 0) 2898c2ecf20Sopenharmony_ci vme_brdtype = brdno; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci mvme16x_get_model(id); 2928c2ecf20Sopenharmony_ci pr_info("BRD_ID: %s BUG %x.%x %02x/%02x/%02x\n", id, p->rev >> 4, 2938c2ecf20Sopenharmony_ci p->rev & 0xf, p->yr, p->mth, p->day); 2948c2ecf20Sopenharmony_ci if (brdno == 0x0162 || brdno == 0x172) 2958c2ecf20Sopenharmony_ci { 2968c2ecf20Sopenharmony_ci unsigned char rev = *(unsigned char *)MVME162_VERSION_REG; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci mvme16x_config = rev | MVME16x_CONFIG_GOT_SCCA; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci pr_info("MVME%x Hardware status:\n", brdno); 3018c2ecf20Sopenharmony_ci pr_info(" CPU Type 68%s040\n", 3028c2ecf20Sopenharmony_ci rev & MVME16x_CONFIG_GOT_FPU ? "" : "LC"); 3038c2ecf20Sopenharmony_ci pr_info(" CPU clock %dMHz\n", 3048c2ecf20Sopenharmony_ci rev & MVME16x_CONFIG_SPEED_32 ? 32 : 25); 3058c2ecf20Sopenharmony_ci pr_info(" VMEchip2 %spresent\n", 3068c2ecf20Sopenharmony_ci rev & MVME16x_CONFIG_NO_VMECHIP2 ? "NOT " : ""); 3078c2ecf20Sopenharmony_ci pr_info(" SCSI interface %spresent\n", 3088c2ecf20Sopenharmony_ci rev & MVME16x_CONFIG_NO_SCSICHIP ? "NOT " : ""); 3098c2ecf20Sopenharmony_ci pr_info(" Ethernet interface %spresent\n", 3108c2ecf20Sopenharmony_ci rev & MVME16x_CONFIG_NO_ETHERNET ? "NOT " : ""); 3118c2ecf20Sopenharmony_ci } 3128c2ecf20Sopenharmony_ci else 3138c2ecf20Sopenharmony_ci { 3148c2ecf20Sopenharmony_ci mvme16x_config = MVME16x_CONFIG_GOT_LP | MVME16x_CONFIG_GOT_CD2401; 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci} 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_cistatic irqreturn_t mvme16x_abort_int (int irq, void *dev_id) 3198c2ecf20Sopenharmony_ci{ 3208c2ecf20Sopenharmony_ci unsigned long *new = (unsigned long *)vectors; 3218c2ecf20Sopenharmony_ci unsigned long *old = (unsigned long *)0xffe00000; 3228c2ecf20Sopenharmony_ci volatile unsigned char uc, *ucp; 3238c2ecf20Sopenharmony_ci uint16_t brdno = be16_to_cpu(mvme_bdid.brdno); 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci if (brdno == 0x0162 || brdno == 0x172) 3268c2ecf20Sopenharmony_ci { 3278c2ecf20Sopenharmony_ci ucp = (volatile unsigned char *)0xfff42043; 3288c2ecf20Sopenharmony_ci uc = *ucp | 8; 3298c2ecf20Sopenharmony_ci *ucp = uc; 3308c2ecf20Sopenharmony_ci } 3318c2ecf20Sopenharmony_ci else 3328c2ecf20Sopenharmony_ci { 3338c2ecf20Sopenharmony_ci *(volatile unsigned long *)0xfff40074 = 0x40000000; 3348c2ecf20Sopenharmony_ci } 3358c2ecf20Sopenharmony_ci *(new+4) = *(old+4); /* Illegal instruction */ 3368c2ecf20Sopenharmony_ci *(new+9) = *(old+9); /* Trace */ 3378c2ecf20Sopenharmony_ci *(new+47) = *(old+47); /* Trap #15 */ 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci if (brdno == 0x0162 || brdno == 0x172) 3408c2ecf20Sopenharmony_ci *(new+0x5e) = *(old+0x5e); /* ABORT switch */ 3418c2ecf20Sopenharmony_ci else 3428c2ecf20Sopenharmony_ci *(new+0x6e) = *(old+0x6e); /* ABORT switch */ 3438c2ecf20Sopenharmony_ci return IRQ_HANDLED; 3448c2ecf20Sopenharmony_ci} 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_cistatic u64 mvme16x_read_clk(struct clocksource *cs); 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_cistatic struct clocksource mvme16x_clk = { 3498c2ecf20Sopenharmony_ci .name = "pcc", 3508c2ecf20Sopenharmony_ci .rating = 250, 3518c2ecf20Sopenharmony_ci .read = mvme16x_read_clk, 3528c2ecf20Sopenharmony_ci .mask = CLOCKSOURCE_MASK(32), 3538c2ecf20Sopenharmony_ci .flags = CLOCK_SOURCE_IS_CONTINUOUS, 3548c2ecf20Sopenharmony_ci}; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_cistatic u32 clk_total; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci#define PCC_TIMER_CLOCK_FREQ 1000000 3598c2ecf20Sopenharmony_ci#define PCC_TIMER_CYCLES (PCC_TIMER_CLOCK_FREQ / HZ) 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci#define PCCTCMP1 (PCC2CHIP + 0x04) 3628c2ecf20Sopenharmony_ci#define PCCTCNT1 (PCC2CHIP + 0x08) 3638c2ecf20Sopenharmony_ci#define PCCTOVR1 (PCC2CHIP + 0x17) 3648c2ecf20Sopenharmony_ci#define PCCTIC1 (PCC2CHIP + 0x1b) 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci#define PCCTOVR1_TIC_EN 0x01 3678c2ecf20Sopenharmony_ci#define PCCTOVR1_COC_EN 0x02 3688c2ecf20Sopenharmony_ci#define PCCTOVR1_OVR_CLR 0x04 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci#define PCCTIC1_INT_LEVEL 6 3718c2ecf20Sopenharmony_ci#define PCCTIC1_INT_CLR 0x08 3728c2ecf20Sopenharmony_ci#define PCCTIC1_INT_EN 0x10 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cistatic irqreturn_t mvme16x_timer_int (int irq, void *dev_id) 3758c2ecf20Sopenharmony_ci{ 3768c2ecf20Sopenharmony_ci irq_handler_t timer_routine = dev_id; 3778c2ecf20Sopenharmony_ci unsigned long flags; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci local_irq_save(flags); 3808c2ecf20Sopenharmony_ci out_8(PCCTOVR1, PCCTOVR1_OVR_CLR | PCCTOVR1_TIC_EN | PCCTOVR1_COC_EN); 3818c2ecf20Sopenharmony_ci out_8(PCCTIC1, PCCTIC1_INT_EN | PCCTIC1_INT_CLR | PCCTIC1_INT_LEVEL); 3828c2ecf20Sopenharmony_ci clk_total += PCC_TIMER_CYCLES; 3838c2ecf20Sopenharmony_ci timer_routine(0, NULL); 3848c2ecf20Sopenharmony_ci local_irq_restore(flags); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci return IRQ_HANDLED; 3878c2ecf20Sopenharmony_ci} 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_civoid mvme16x_sched_init (irq_handler_t timer_routine) 3908c2ecf20Sopenharmony_ci{ 3918c2ecf20Sopenharmony_ci uint16_t brdno = be16_to_cpu(mvme_bdid.brdno); 3928c2ecf20Sopenharmony_ci int irq; 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci /* Using PCCchip2 or MC2 chip tick timer 1 */ 3958c2ecf20Sopenharmony_ci if (request_irq(MVME16x_IRQ_TIMER, mvme16x_timer_int, IRQF_TIMER, "timer", 3968c2ecf20Sopenharmony_ci timer_routine)) 3978c2ecf20Sopenharmony_ci panic ("Couldn't register timer int"); 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci out_be32(PCCTCNT1, 0); 4008c2ecf20Sopenharmony_ci out_be32(PCCTCMP1, PCC_TIMER_CYCLES); 4018c2ecf20Sopenharmony_ci out_8(PCCTOVR1, PCCTOVR1_OVR_CLR | PCCTOVR1_TIC_EN | PCCTOVR1_COC_EN); 4028c2ecf20Sopenharmony_ci out_8(PCCTIC1, PCCTIC1_INT_EN | PCCTIC1_INT_CLR | PCCTIC1_INT_LEVEL); 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci clocksource_register_hz(&mvme16x_clk, PCC_TIMER_CLOCK_FREQ); 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci if (brdno == 0x0162 || brdno == 0x172) 4078c2ecf20Sopenharmony_ci irq = MVME162_IRQ_ABORT; 4088c2ecf20Sopenharmony_ci else 4098c2ecf20Sopenharmony_ci irq = MVME167_IRQ_ABORT; 4108c2ecf20Sopenharmony_ci if (request_irq(irq, mvme16x_abort_int, 0, 4118c2ecf20Sopenharmony_ci "abort", mvme16x_abort_int)) 4128c2ecf20Sopenharmony_ci panic ("Couldn't register abort int"); 4138c2ecf20Sopenharmony_ci} 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_cistatic u64 mvme16x_read_clk(struct clocksource *cs) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci unsigned long flags; 4188c2ecf20Sopenharmony_ci u8 overflow, tmp; 4198c2ecf20Sopenharmony_ci u32 ticks; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci local_irq_save(flags); 4228c2ecf20Sopenharmony_ci tmp = in_8(PCCTOVR1) >> 4; 4238c2ecf20Sopenharmony_ci ticks = in_be32(PCCTCNT1); 4248c2ecf20Sopenharmony_ci overflow = in_8(PCCTOVR1) >> 4; 4258c2ecf20Sopenharmony_ci if (overflow != tmp) 4268c2ecf20Sopenharmony_ci ticks = in_be32(PCCTCNT1); 4278c2ecf20Sopenharmony_ci ticks += overflow * PCC_TIMER_CYCLES; 4288c2ecf20Sopenharmony_ci ticks += clk_total; 4298c2ecf20Sopenharmony_ci local_irq_restore(flags); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci return ticks; 4328c2ecf20Sopenharmony_ci} 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ciint bcd2int (unsigned char b) 4358c2ecf20Sopenharmony_ci{ 4368c2ecf20Sopenharmony_ci return ((b>>4)*10 + (b&15)); 4378c2ecf20Sopenharmony_ci} 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ciint mvme16x_hwclk(int op, struct rtc_time *t) 4408c2ecf20Sopenharmony_ci{ 4418c2ecf20Sopenharmony_ci#warning check me! 4428c2ecf20Sopenharmony_ci if (!op) { 4438c2ecf20Sopenharmony_ci rtc->ctrl = RTC_READ; 4448c2ecf20Sopenharmony_ci t->tm_year = bcd2int (rtc->bcd_year); 4458c2ecf20Sopenharmony_ci t->tm_mon = bcd2int(rtc->bcd_mth) - 1; 4468c2ecf20Sopenharmony_ci t->tm_mday = bcd2int (rtc->bcd_dom); 4478c2ecf20Sopenharmony_ci t->tm_hour = bcd2int (rtc->bcd_hr); 4488c2ecf20Sopenharmony_ci t->tm_min = bcd2int (rtc->bcd_min); 4498c2ecf20Sopenharmony_ci t->tm_sec = bcd2int (rtc->bcd_sec); 4508c2ecf20Sopenharmony_ci rtc->ctrl = 0; 4518c2ecf20Sopenharmony_ci if (t->tm_year < 70) 4528c2ecf20Sopenharmony_ci t->tm_year += 100; 4538c2ecf20Sopenharmony_ci } 4548c2ecf20Sopenharmony_ci return 0; 4558c2ecf20Sopenharmony_ci} 456