/* The decrementer counts at the system bus clock frequency * divided by four. The most accurate time base is connected to the * rtc. We read the decrementer change during one rtc tick * and multiply by 4 to get the system bus clock frequency. Since a * rtc tick is one seconds, and that's pretty long, we change the rtc * dividers temporarly to set them 64x faster ;) */ static int mpc52xx_ipbfreq(void) { struct mpc52xx_rtc __iomem *rtc = (struct mpc52xx_rtc __iomem *) MPC52xx_PA(MPC52xx_RTC_OFFSET); struct mpc52xx_cdm __iomem *cdm = (struct mpc52xx_cdm __iomem *) MPC52xx_PA(MPC52xx_CDM_OFFSET); int current_time, previous_time; int tbl_start, tbl_end; int xlbfreq, ipbfreq; out_be32(&rtc->dividers, 0x8f1f0000); /* Set RTC 64x faster */ previous_time = in_be32(&rtc->time); while ((current_time = in_be32(&rtc->time)) == previous_time) ; tbl_start = get_tbl(); previous_time = current_time; while ((current_time = in_be32(&rtc->time)) == previous_time) ; tbl_end = get_tbl(); out_be32(&rtc->dividers, 0xffff0000); /* Restore RTC */ xlbfreq = (tbl_end - tbl_start) << 8; ipbfreq = (in_8(&cdm->ipb_clk_sel) & 1) ? xlbfreq / 2 : xlbfreq; return ipbfreq; }
void __init mpc52xx_init_irq(void) { int i; u32 intr_ctrl; /* Remap the necessary zones */ intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE); sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE); if ((intr==NULL) || (sdma==NULL)) panic("Can't ioremap PIC/SDMA register for init_irq !"); /* Disable all interrupt sources. */ out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */ out_be32(&sdma->IntMask, 0xffffffff); /* 1 means disabled */ out_be32(&intr->per_mask, 0x7ffffc00); /* 1 means disabled */ out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */ intr_ctrl = in_be32(&intr->ctrl); intr_ctrl &= 0x00ff0000; /* Keeps IRQ[0-3] config */ intr_ctrl |= 0x0f000000 | /* clear IRQ 0-3 */ 0x00001000 | /* MEE master external enable */ 0x00000000 | /* 0 means disable IRQ 0-3 */ 0x00000001; /* CEb route critical normally */ out_be32(&intr->ctrl, intr_ctrl); /* Zero a bunch of the priority settings. */ out_be32(&intr->per_pri1, 0); out_be32(&intr->per_pri2, 0); out_be32(&intr->per_pri3, 0); out_be32(&intr->main_pri1, 0); out_be32(&intr->main_pri2, 0); /* Initialize irq_desc[i].chip's with mpc52xx_ic. */ for (i = 0; i < NR_IRQS; i++) { irq_desc[i].chip = &mpc52xx_ic; irq_desc[i].status = IRQ_LEVEL; } #define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03) for (i=0 ; i<4 ; i++) { int mode; mode = IRQn_MODE(intr_ctrl,i); if ((mode == 0x1) || (mode == 0x2)) irq_desc[i?MPC52xx_IRQ1+i-1:MPC52xx_IRQ0].status = 0; } }
void __init mpc52xx_setup_cpu(void) { struct mpc52xx_cdm __iomem *cdm; struct mpc52xx_xlb __iomem *xlb; /* Map zones */ cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE); xlb = ioremap(MPC52xx_PA(MPC52xx_XLB_OFFSET), MPC52xx_XLB_SIZE); if (!cdm || !xlb) { printk(KERN_ERR __FILE__ ": " "Error while mapping CDM/XLB during " "mpc52xx_setup_cpu\n"); goto unmap_regs; } /* Use internal 48 Mhz */ out_8(&cdm->ext_48mhz_en, 0x00); out_8(&cdm->fd_enable, 0x01); if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */ out_be16(&cdm->fd_counters, 0x0001); else out_be16(&cdm->fd_counters, 0x5555); /* Configure the XLB Arbiter priorities */ out_be32(&xlb->master_pri_enable, 0xff); out_be32(&xlb->master_priority, 0x11111111); /* Enable ram snooping for 1GB window */ out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_SNOOP); out_be32(&xlb->snoop_window, MPC52xx_PCI_TARGET_MEM | 0x1d); /* Disable XLB pipelining */ /* (cfr errata 292. We could do this only just before ATA PIO transaction and re-enable it after ...) */ out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_PLDIS); /* Unmap reg zone */ unmap_regs: if (cdm) iounmap(cdm); if (xlb) iounmap(xlb); }
unsigned long serial_init(int ignored, void *ignored2) { struct mpc52xx_gpio __iomem *gpio = (struct mpc52xx_gpio __iomem *) MPC52xx_PA(MPC52xx_GPIO_OFFSET); int divisor; int mode1; int mode2; u32 val32; static int been_here = 0; if (been_here) return 0; been_here = 1; val32 = in_be32(&gpio->port_config); val32 &= ~(0x7 << MPC52xx_PSC_CONFIG_SHIFT); val32 |= MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD << MPC52xx_PSC_CONFIG_SHIFT; out_be32(&gpio->port_config, val32); out_8(&psc->command, MPC52xx_PSC_RST_TX | MPC52xx_PSC_RX_DISABLE | MPC52xx_PSC_TX_ENABLE); out_8(&psc->command, MPC52xx_PSC_RST_RX); out_be32(&psc->sicr, 0x0); out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00); out_be16(&psc->tfalarm, 0xf8); out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1 | MPC52xx_PSC_RX_ENABLE | MPC52xx_PSC_TX_ENABLE); divisor = ((mpc52xx_ipbfreq() / (CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD * 16)) + 1) >> 1; mode1 = MPC52xx_PSC_MODE_8_BITS | MPC52xx_PSC_MODE_PARNONE | MPC52xx_PSC_MODE_ERR; mode2 = MPC52xx_PSC_MODE_ONE_STOP; out_8(&psc->ctur, divisor>>8); out_8(&psc->ctlr, divisor); out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1); out_8(&psc->mode, mode1); out_8(&psc->mode, mode2); return 0; /* ignored */ }
int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv) { static DEFINE_SPINLOCK(lock); struct mpc52xx_cdm __iomem *cdm; unsigned long flags; u16 mclken_div; u16 __iomem *reg; u32 mask; cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE); if (!cdm) { printk(KERN_ERR __FILE__ ": Error mapping CDM\n"); return -ENODEV; } mclken_div = 0x8000 | (clkdiv & 0x1FF); switch (psc_id) { case 1: reg = &cdm->mclken_div_psc1; mask = 0x20; break; case 2: reg = &cdm->mclken_div_psc2; mask = 0x40; break; case 3: reg = &cdm->mclken_div_psc3; mask = 0x80; break; case 6: reg = &cdm->mclken_div_psc6; mask = 0x10; break; default: return -ENODEV; } /* Set the rate and enable the clock */ spin_lock_irqsave(&lock, flags); out_be16(reg, mclken_div); out_be32(&cdm->clk_enables, in_be32(&cdm->clk_enables) | mask); spin_unlock_irqrestore(&lock, flags); iounmap(cdm); return 0; }
void __init mpc52xx_calibrate_decr(void) { int current_time, previous_time; int tbl_start, tbl_end; unsigned int xlbfreq, cpufreq, ipbfreq, pcifreq, divisor; xlbfreq = __res.bi_busfreq; /* if bootloader didn't pass bus frequencies, calculate them */ if (xlbfreq == 0) { /* Get RTC & Clock manager modules */ struct mpc52xx_rtc __iomem *rtc; struct mpc52xx_cdm __iomem *cdm; rtc = ioremap(MPC52xx_PA(MPC52xx_RTC_OFFSET), MPC52xx_RTC_SIZE); cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE); if ((rtc==NULL) || (cdm==NULL)) panic("Can't ioremap RTC/CDM while computing bus freq"); /* Count bus clock during 1/64 sec */ out_be32(&rtc->dividers, 0x8f1f0000); /* Set RTC 64x faster */ previous_time = in_be32(&rtc->time); while ((current_time = in_be32(&rtc->time)) == previous_time) ; tbl_start = get_tbl(); previous_time = current_time; while ((current_time = in_be32(&rtc->time)) == previous_time) ; tbl_end = get_tbl(); out_be32(&rtc->dividers, 0xffff0000); /* Restore RTC */ /* Compute all frequency from that & CDM settings */ xlbfreq = (tbl_end - tbl_start) << 8; cpufreq = (xlbfreq * core_mult[in_be32(&cdm->rstcfg)&0x1f])/10; ipbfreq = (in_8(&cdm->ipb_clk_sel) & 1) ? xlbfreq / 2 : xlbfreq; switch (in_8(&cdm->pci_clk_sel) & 3) { case 0: pcifreq = ipbfreq; break; case 1: pcifreq = ipbfreq / 2; break; default: pcifreq = xlbfreq / 4; break; } __res.bi_busfreq = xlbfreq; __res.bi_intfreq = cpufreq; __res.bi_ipbfreq = ipbfreq; __res.bi_pcifreq = pcifreq; /* Release mapping */ iounmap(rtc); iounmap(cdm); } divisor = 4; tb_ticks_per_jiffy = xlbfreq / HZ / divisor; tb_to_us = mulhwu_scale_factor(xlbfreq / divisor, 1000000); }
#include <asm/mpc52xx.h> #include <asm/mpc52xx_psc.h> #include <asm/serial.h> #include <asm/io.h> #include <asm/time.h> #ifdef MPC52xx_PF_CONSOLE_PORT #define MPC52xx_CONSOLE MPC52xx_PSCx_OFFSET(MPC52xx_PF_CONSOLE_PORT) #define MPC52xx_PSC_CONFIG_SHIFT ((MPC52xx_PF_CONSOLE_PORT-1)<<2) #else #error "MPC52xx_PF_CONSOLE_PORT not defined" #endif static struct mpc52xx_psc __iomem *psc = (struct mpc52xx_psc __iomem *) MPC52xx_PA(MPC52xx_CONSOLE); /* The decrementer counts at the system bus clock frequency * divided by four. The most accurate time base is connected to the * rtc. We read the decrementer change during one rtc tick * and multiply by 4 to get the system bus clock frequency. Since a * rtc tick is one seconds, and that's pretty long, we change the rtc * dividers temporarly to set them 64x faster ;) */ static int mpc52xx_ipbfreq(void) { struct mpc52xx_rtc __iomem *rtc = (struct mpc52xx_rtc __iomem *) MPC52xx_PA(MPC52xx_RTC_OFFSET); struct mpc52xx_cdm __iomem *cdm = (struct mpc52xx_cdm __iomem *) MPC52xx_PA(MPC52xx_CDM_OFFSET);
static void __init lite5200_setup_cpu(void) { struct mpc52xx_cdm __iomem *cdm; struct mpc52xx_gpio __iomem *gpio; struct mpc52xx_intr __iomem *intr; struct mpc52xx_xlb __iomem *xlb; u32 port_config; u32 intr_ctrl; /* Map zones */ cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE); gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE); xlb = ioremap(MPC52xx_PA(MPC52xx_XLB_OFFSET), MPC52xx_XLB_SIZE); intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE); if (!cdm || !gpio || !xlb || !intr) { printk("lite5200.c: Error while mapping CDM/GPIO/XLB/INTR during" "lite5200_setup_cpu\n"); goto unmap_regs; } /* Use internal 48 Mhz */ out_8(&cdm->ext_48mhz_en, 0x00); out_8(&cdm->fd_enable, 0x01); if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */ out_be16(&cdm->fd_counters, 0x0001); else out_be16(&cdm->fd_counters, 0x5555); /* Get port mux config */ port_config = in_be32(&gpio->port_config); /* 48Mhz internal, pin is GPIO */ port_config &= ~0x00800000; /* USB port */ port_config &= ~0x00007000; /* Differential mode - USB1 only */ port_config |= 0x00001000; /* Commit port config */ out_be32(&gpio->port_config, port_config); /* Configure the XLB Arbiter */ out_be32(&xlb->master_pri_enable, 0xff); out_be32(&xlb->master_priority, 0x11111111); /* Enable ram snooping for 1GB window */ out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_SNOOP); out_be32(&xlb->snoop_window, MPC52xx_PCI_TARGET_MEM | 0x1d); /* IRQ[0-3] setup : IRQ0 - Level Active Low */ /* IRQ[1-3] - Level Active High */ intr_ctrl = in_be32(&intr->ctrl); intr_ctrl &= ~0x00ff0000; intr_ctrl |= 0x00c00000; out_be32(&intr->ctrl, intr_ctrl); /* Unmap reg zone */ unmap_regs: if (cdm) iounmap(cdm); if (gpio) iounmap(gpio); if (xlb) iounmap(xlb); if (intr) iounmap(intr); }