1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 1995 Linus Torvalds 4 * Adapted from 'alpha' version by Gary Thomas 5 * Modified by Cort Dougan (cort@cs.nmt.edu) 6 * Modified for MBX using prep/chrp/pmac functions by Dan (dmalek@jlc.net) 7 * Further modified for generic 8xx by Dan. 8 */ 9 10 /* 11 * bootup setup stuff.. 12 */ 13 14 #include <linux/kernel.h> 15 #include <linux/interrupt.h> 16 #include <linux/init.h> 17 #include <linux/time.h> 18 #include <linux/rtc.h> 19 #include <linux/fsl_devices.h> 20 #include <linux/of.h> 21 #include <linux/of_irq.h> 22 23 #include <asm/io.h> 24 #include <asm/8xx_immap.h> 25 #include <mm/mmu_decl.h> 26 27 #include "pic.h" 28 29 #include "mpc8xx.h" 30 31 /* A place holder for time base interrupts, if they are ever enabled. */ 32 static irqreturn_t timebase_interrupt(int irq, void *dev) 33 { 34 printk ("timebase_interrupt()\n"); 35 36 return IRQ_HANDLED; 37 } 38 39 static int __init get_freq(char *name, unsigned long *val) 40 { 41 struct device_node *cpu; 42 const unsigned int *fp; 43 int found = 0; 44 45 /* The cpu node should have timebase and clock frequency properties */ 46 cpu = of_get_cpu_node(0, NULL); 47 48 if (cpu) { 49 fp = of_get_property(cpu, name, NULL); 50 if (fp) { 51 found = 1; 52 *val = *fp; 53 } 54 55 of_node_put(cpu); 56 } 57 58 return found; 59 } 60 61 /* The decrementer counts at the system (internal) clock frequency divided by 62 * sixteen, or external oscillator divided by four. We force the processor 63 * to use system clock divided by sixteen. 64 */ 65 void __init mpc8xx_calibrate_decr(void) 66 { 67 struct device_node *cpu; 68 int irq, virq; 69 70 /* Unlock the SCCR. */ 71 out_be32(&mpc8xx_immr->im_clkrstk.cark_sccrk, ~KAPWR_KEY); 72 out_be32(&mpc8xx_immr->im_clkrstk.cark_sccrk, KAPWR_KEY); 73 74 /* Force all 8xx processors to use divide by 16 processor clock. */ 75 setbits32(&mpc8xx_immr->im_clkrst.car_sccr, 0x02000000); 76 77 /* Processor frequency is MHz. 78 */ 79 ppc_proc_freq = 50000000; 80 if (!get_freq("clock-frequency", &ppc_proc_freq)) 81 printk(KERN_ERR "WARNING: Estimating processor frequency " 82 "(not found)\n"); 83 84 ppc_tb_freq = ppc_proc_freq / 16; 85 printk("Decrementer Frequency = 0x%lx\n", ppc_tb_freq); 86 87 /* Perform some more timer/timebase initialization. This used 88 * to be done elsewhere, but other changes caused it to get 89 * called more than once....that is a bad thing. 90 * 91 * First, unlock all of the registers we are going to modify. 92 * To protect them from corruption during power down, registers 93 * that are maintained by keep alive power are "locked". To 94 * modify these registers we have to write the key value to 95 * the key location associated with the register. 96 * Some boards power up with these unlocked, while others 97 * are locked. Writing anything (including the unlock code?) 98 * to the unlocked registers will lock them again. So, here 99 * we guarantee the registers are locked, then we unlock them 100 * for our use. 101 */ 102 out_be32(&mpc8xx_immr->im_sitk.sitk_tbscrk, ~KAPWR_KEY); 103 out_be32(&mpc8xx_immr->im_sitk.sitk_rtcsck, ~KAPWR_KEY); 104 out_be32(&mpc8xx_immr->im_sitk.sitk_tbk, ~KAPWR_KEY); 105 out_be32(&mpc8xx_immr->im_sitk.sitk_tbscrk, KAPWR_KEY); 106 out_be32(&mpc8xx_immr->im_sitk.sitk_rtcsck, KAPWR_KEY); 107 out_be32(&mpc8xx_immr->im_sitk.sitk_tbk, KAPWR_KEY); 108 109 /* Disable the RTC one second and alarm interrupts. */ 110 clrbits16(&mpc8xx_immr->im_sit.sit_rtcsc, (RTCSC_SIE | RTCSC_ALE)); 111 112 /* Enable the RTC */ 113 setbits16(&mpc8xx_immr->im_sit.sit_rtcsc, (RTCSC_RTF | RTCSC_RTE)); 114 115 /* Enabling the decrementer also enables the timebase interrupts 116 * (or from the other point of view, to get decrementer interrupts 117 * we have to enable the timebase). The decrementer interrupt 118 * is wired into the vector table, nothing to do here for that. 119 */ 120 cpu = of_get_cpu_node(0, NULL); 121 virq= irq_of_parse_and_map(cpu, 0); 122 of_node_put(cpu); 123 irq = virq_to_hw(virq); 124 125 out_be16(&mpc8xx_immr->im_sit.sit_tbscr, 126 ((1 << (7 - (irq / 2))) << 8) | (TBSCR_TBF | TBSCR_TBE)); 127 128 if (request_irq(virq, timebase_interrupt, IRQF_NO_THREAD, "tbint", 129 NULL)) 130 panic("Could not allocate timer IRQ!"); 131 } 132 133 /* The RTC on the MPC8xx is an internal register. 134 * We want to protect this during power down, so we need to unlock, 135 * modify, and re-lock. 136 */ 137 138 int mpc8xx_set_rtc_time(struct rtc_time *tm) 139 { 140 time64_t time; 141 142 time = rtc_tm_to_time64(tm); 143 144 out_be32(&mpc8xx_immr->im_sitk.sitk_rtck, KAPWR_KEY); 145 out_be32(&mpc8xx_immr->im_sit.sit_rtc, (u32)time); 146 out_be32(&mpc8xx_immr->im_sitk.sitk_rtck, ~KAPWR_KEY); 147 148 return 0; 149 } 150 151 void mpc8xx_get_rtc_time(struct rtc_time *tm) 152 { 153 unsigned long data; 154 155 /* Get time from the RTC. */ 156 data = in_be32(&mpc8xx_immr->im_sit.sit_rtc); 157 rtc_time64_to_tm(data, tm); 158 return; 159 } 160 161 void __noreturn mpc8xx_restart(char *cmd) 162 { 163 local_irq_disable(); 164 165 setbits32(&mpc8xx_immr->im_clkrst.car_plprcr, 0x00000080); 166 /* Clear the ME bit in MSR to cause checkstop on machine check 167 */ 168 mtmsr(mfmsr() & ~0x1000); 169 170 in_8(&mpc8xx_immr->im_clkrst.res[0]); 171 panic("Restart failed\n"); 172 } 173