Path: blob/master/arch/powerpc/platforms/8xx/m8xx_setup.c
10819 views
/*1* Copyright (C) 1995 Linus Torvalds2* Adapted from 'alpha' version by Gary Thomas3* Modified by Cort Dougan ([email protected])4* Modified for MBX using prep/chrp/pmac functions by Dan ([email protected])5* Further modified for generic 8xx by Dan.6*/78/*9* bootup setup stuff..10*/1112#include <linux/kernel.h>13#include <linux/interrupt.h>14#include <linux/init.h>15#include <linux/time.h>16#include <linux/rtc.h>17#include <linux/fsl_devices.h>1819#include <asm/io.h>20#include <asm/mpc8xx.h>21#include <asm/8xx_immap.h>22#include <asm/prom.h>23#include <asm/fs_pd.h>24#include <mm/mmu_decl.h>2526#include <sysdev/mpc8xx_pic.h>2728#include "mpc8xx.h"2930struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops;3132extern int cpm_pic_init(void);33extern int cpm_get_irq(void);3435/* A place holder for time base interrupts, if they are ever enabled. */36static irqreturn_t timebase_interrupt(int irq, void *dev)37{38printk ("timebase_interrupt()\n");3940return IRQ_HANDLED;41}4243static struct irqaction tbint_irqaction = {44.handler = timebase_interrupt,45.name = "tbint",46};4748/* per-board overridable init_internal_rtc() function. */49void __init __attribute__ ((weak))50init_internal_rtc(void)51{52sit8xx_t __iomem *sys_tmr = immr_map(im_sit);5354/* Disable the RTC one second and alarm interrupts. */55clrbits16(&sys_tmr->sit_rtcsc, (RTCSC_SIE | RTCSC_ALE));5657/* Enable the RTC */58setbits16(&sys_tmr->sit_rtcsc, (RTCSC_RTF | RTCSC_RTE));59immr_unmap(sys_tmr);60}6162static int __init get_freq(char *name, unsigned long *val)63{64struct device_node *cpu;65const unsigned int *fp;66int found = 0;6768/* The cpu node should have timebase and clock frequency properties */69cpu = of_find_node_by_type(NULL, "cpu");7071if (cpu) {72fp = of_get_property(cpu, name, NULL);73if (fp) {74found = 1;75*val = *fp;76}7778of_node_put(cpu);79}8081return found;82}8384/* The decrementer counts at the system (internal) clock frequency divided by85* sixteen, or external oscillator divided by four. We force the processor86* to use system clock divided by sixteen.87*/88void __init mpc8xx_calibrate_decr(void)89{90struct device_node *cpu;91cark8xx_t __iomem *clk_r1;92car8xx_t __iomem *clk_r2;93sitk8xx_t __iomem *sys_tmr1;94sit8xx_t __iomem *sys_tmr2;95int irq, virq;9697clk_r1 = immr_map(im_clkrstk);9899/* Unlock the SCCR. */100out_be32(&clk_r1->cark_sccrk, ~KAPWR_KEY);101out_be32(&clk_r1->cark_sccrk, KAPWR_KEY);102immr_unmap(clk_r1);103104/* Force all 8xx processors to use divide by 16 processor clock. */105clk_r2 = immr_map(im_clkrst);106setbits32(&clk_r2->car_sccr, 0x02000000);107immr_unmap(clk_r2);108109/* Processor frequency is MHz.110*/111ppc_proc_freq = 50000000;112if (!get_freq("clock-frequency", &ppc_proc_freq))113printk(KERN_ERR "WARNING: Estimating processor frequency "114"(not found)\n");115116ppc_tb_freq = ppc_proc_freq / 16;117printk("Decrementer Frequency = 0x%lx\n", ppc_tb_freq);118119/* Perform some more timer/timebase initialization. This used120* to be done elsewhere, but other changes caused it to get121* called more than once....that is a bad thing.122*123* First, unlock all of the registers we are going to modify.124* To protect them from corruption during power down, registers125* that are maintained by keep alive power are "locked". To126* modify these registers we have to write the key value to127* the key location associated with the register.128* Some boards power up with these unlocked, while others129* are locked. Writing anything (including the unlock code?)130* to the unlocked registers will lock them again. So, here131* we guarantee the registers are locked, then we unlock them132* for our use.133*/134sys_tmr1 = immr_map(im_sitk);135out_be32(&sys_tmr1->sitk_tbscrk, ~KAPWR_KEY);136out_be32(&sys_tmr1->sitk_rtcsck, ~KAPWR_KEY);137out_be32(&sys_tmr1->sitk_tbk, ~KAPWR_KEY);138out_be32(&sys_tmr1->sitk_tbscrk, KAPWR_KEY);139out_be32(&sys_tmr1->sitk_rtcsck, KAPWR_KEY);140out_be32(&sys_tmr1->sitk_tbk, KAPWR_KEY);141immr_unmap(sys_tmr1);142143init_internal_rtc();144145/* Enabling the decrementer also enables the timebase interrupts146* (or from the other point of view, to get decrementer interrupts147* we have to enable the timebase). The decrementer interrupt148* is wired into the vector table, nothing to do here for that.149*/150cpu = of_find_node_by_type(NULL, "cpu");151virq= irq_of_parse_and_map(cpu, 0);152irq = virq_to_hw(virq);153154sys_tmr2 = immr_map(im_sit);155out_be16(&sys_tmr2->sit_tbscr, ((1 << (7 - (irq/2))) << 8) |156(TBSCR_TBF | TBSCR_TBE));157immr_unmap(sys_tmr2);158159if (setup_irq(virq, &tbint_irqaction))160panic("Could not allocate timer IRQ!");161}162163/* The RTC on the MPC8xx is an internal register.164* We want to protect this during power down, so we need to unlock,165* modify, and re-lock.166*/167168int mpc8xx_set_rtc_time(struct rtc_time *tm)169{170sitk8xx_t __iomem *sys_tmr1;171sit8xx_t __iomem *sys_tmr2;172int time;173174sys_tmr1 = immr_map(im_sitk);175sys_tmr2 = immr_map(im_sit);176time = mktime(tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,177tm->tm_hour, tm->tm_min, tm->tm_sec);178179out_be32(&sys_tmr1->sitk_rtck, KAPWR_KEY);180out_be32(&sys_tmr2->sit_rtc, time);181out_be32(&sys_tmr1->sitk_rtck, ~KAPWR_KEY);182183immr_unmap(sys_tmr2);184immr_unmap(sys_tmr1);185return 0;186}187188void mpc8xx_get_rtc_time(struct rtc_time *tm)189{190unsigned long data;191sit8xx_t __iomem *sys_tmr = immr_map(im_sit);192193/* Get time from the RTC. */194data = in_be32(&sys_tmr->sit_rtc);195to_tm(data, tm);196tm->tm_year -= 1900;197tm->tm_mon -= 1;198immr_unmap(sys_tmr);199return;200}201202void mpc8xx_restart(char *cmd)203{204car8xx_t __iomem *clk_r = immr_map(im_clkrst);205206207local_irq_disable();208209setbits32(&clk_r->car_plprcr, 0x00000080);210/* Clear the ME bit in MSR to cause checkstop on machine check211*/212mtmsr(mfmsr() & ~0x1000);213214in_8(&clk_r->res[0]);215panic("Restart failed\n");216}217218static void cpm_cascade(unsigned int irq, struct irq_desc *desc)219{220struct irq_chip *chip;221int cascade_irq;222223if ((cascade_irq = cpm_get_irq()) >= 0) {224struct irq_desc *cdesc = irq_to_desc(cascade_irq);225226generic_handle_irq(cascade_irq);227228chip = irq_desc_get_chip(cdesc);229chip->irq_eoi(&cdesc->irq_data);230}231232chip = irq_desc_get_chip(desc);233chip->irq_eoi(&desc->irq_data);234}235236/* Initialize the internal interrupt controllers. The number of237* interrupts supported can vary with the processor type, and the238* 82xx family can have up to 64.239* External interrupts can be either edge or level triggered, and240* need to be initialized by the appropriate driver.241*/242void __init mpc8xx_pics_init(void)243{244int irq;245246if (mpc8xx_pic_init()) {247printk(KERN_ERR "Failed interrupt 8xx controller initialization\n");248return;249}250251irq = cpm_pic_init();252if (irq != NO_IRQ)253irq_set_chained_handler(irq, cpm_cascade);254}255256257