Path: blob/master/arch/unicore32/kernel/puv3-core.c
10817 views
/*1* linux/arch/unicore32/kernel/puv3-core.c2*3* Code specific to PKUnity SoC and UniCore ISA4*5* Maintained by GUAN Xue-tao <[email protected]>6* Copyright (C) 2001-2010 Guan Xuetao7*8* This program is free software; you can redistribute it and/or modify9* it under the terms of the GNU General Public License version 2 as10* published by the Free Software Foundation.11*/1213#include <linux/init.h>14#include <linux/device.h>15#include <linux/sysdev.h>16#include <linux/amba/bus.h>17#include <linux/platform_device.h>18#include <linux/io.h>19#include <linux/cnt32_to_63.h>20#include <linux/usb/musb.h>2122#include <asm/irq.h>23#include <mach/hardware.h>24#include <mach/pm.h>2526/*27* This is the PKUnity sched_clock implementation. This has28* a resolution of 271ns, and a maximum value of 32025597s (370 days).29*30* The return value is guaranteed to be monotonic in that range as31* long as there is always less than 582 seconds between successive32* calls to this function.33*34* ( * 1E9 / CLOCK_TICK_RATE ) -> about 2235/3235*/36unsigned long long sched_clock(void)37{38unsigned long long v = cnt32_to_63(readl(OST_OSCR));3940/* original conservative method, but overflow frequently41* v *= NSEC_PER_SEC >> 12;42* do_div(v, CLOCK_TICK_RATE >> 12);43*/44v = ((v & 0x7fffffffffffffffULL) * 2235) >> 5;4546return v;47}4849static struct resource puv3_usb_resources[] = {50/* order is significant! */51{52.start = io_v2p(PKUNITY_USB_BASE),53.end = io_v2p(PKUNITY_USB_BASE) + 0x3ff,54.flags = IORESOURCE_MEM,55}, {56.start = IRQ_USB,57.flags = IORESOURCE_IRQ,58}, {59.start = IRQ_USB,60.flags = IORESOURCE_IRQ,61},62};6364static struct musb_hdrc_config puv3_usb_config[] = {65{66.num_eps = 16,67.multipoint = 1,68#ifdef CONFIG_USB_INVENTRA_DMA69.dma = 1,70.dma_channels = 8,71#endif72},73};7475static struct musb_hdrc_platform_data puv3_usb_plat = {76.mode = MUSB_HOST,77.min_power = 100,78.clock = 0,79.config = puv3_usb_config,80};8182static struct resource puv3_mmc_resources[] = {83[0] = {84.start = io_v2p(PKUNITY_SDC_BASE),85.end = io_v2p(PKUNITY_SDC_BASE) + 0xfff,86.flags = IORESOURCE_MEM,87},88[1] = {89.start = IRQ_SDC,90.end = IRQ_SDC,91.flags = IORESOURCE_IRQ,92},93};9495static struct resource puv3_unigfx_resources[] = {96[0] = {97.start = io_v2p(PKUNITY_UNIGFX_BASE),98.end = io_v2p(PKUNITY_UNIGFX_BASE) + 0xfff,99.flags = IORESOURCE_MEM,100},101};102103static struct resource puv3_rtc_resources[] = {104[0] = {105.start = io_v2p(PKUNITY_RTC_BASE),106.end = io_v2p(PKUNITY_RTC_BASE) + 0xff,107.flags = IORESOURCE_MEM,108},109[1] = {110.start = IRQ_RTCAlarm,111.end = IRQ_RTCAlarm,112.flags = IORESOURCE_IRQ,113},114[2] = {115.start = IRQ_RTC,116.end = IRQ_RTC,117.flags = IORESOURCE_IRQ118}119};120121static struct resource puv3_pwm_resources[] = {122[0] = {123.start = io_v2p(PKUNITY_OST_BASE) + 0x80,124.end = io_v2p(PKUNITY_OST_BASE) + 0xff,125.flags = IORESOURCE_MEM,126},127};128129static struct resource puv3_uart0_resources[] = {130[0] = {131.start = io_v2p(PKUNITY_UART0_BASE),132.end = io_v2p(PKUNITY_UART0_BASE) + 0xff,133.flags = IORESOURCE_MEM,134},135[1] = {136.start = IRQ_UART0,137.end = IRQ_UART0,138.flags = IORESOURCE_IRQ139}140};141142static struct resource puv3_uart1_resources[] = {143[0] = {144.start = io_v2p(PKUNITY_UART1_BASE),145.end = io_v2p(PKUNITY_UART1_BASE) + 0xff,146.flags = IORESOURCE_MEM,147},148[1] = {149.start = IRQ_UART1,150.end = IRQ_UART1,151.flags = IORESOURCE_IRQ152}153};154155static struct resource puv3_umal_resources[] = {156[0] = {157.start = io_v2p(PKUNITY_UMAL_BASE),158.end = io_v2p(PKUNITY_UMAL_BASE) + 0x1fff,159.flags = IORESOURCE_MEM,160},161[1] = {162.start = IRQ_UMAL,163.end = IRQ_UMAL,164.flags = IORESOURCE_IRQ165}166};167168#ifdef CONFIG_PUV3_PM169170#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x171#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]172173/*174* List of global PXA peripheral registers to preserve.175* More ones like CP and general purpose register values are preserved176* with the stack pointer in sleep.S.177*/178enum {179SLEEP_SAVE_PM_PLLDDRCFG,180SLEEP_SAVE_COUNT181};182183184static void puv3_cpu_pm_save(unsigned long *sleep_save)185{186/* SAVE(PM_PLLDDRCFG); */187}188189static void puv3_cpu_pm_restore(unsigned long *sleep_save)190{191/* RESTORE(PM_PLLDDRCFG); */192}193194static int puv3_cpu_pm_prepare(void)195{196/* set resume return address */197writel(virt_to_phys(puv3_cpu_resume), PM_DIVCFG);198return 0;199}200201static void puv3_cpu_pm_enter(suspend_state_t state)202{203/* Clear reset status */204writel(RESETC_RSSR_HWR | RESETC_RSSR_WDR205| RESETC_RSSR_SMR | RESETC_RSSR_SWR, RESETC_RSSR);206207switch (state) {208/* case PM_SUSPEND_ON:209puv3_cpu_idle();210break; */211case PM_SUSPEND_MEM:212puv3_cpu_pm_prepare();213puv3_cpu_suspend(PM_PMCR_SFB);214break;215}216}217218static int puv3_cpu_pm_valid(suspend_state_t state)219{220return state == PM_SUSPEND_MEM;221}222223static void puv3_cpu_pm_finish(void)224{225/* ensure not to come back here if it wasn't intended */226/* PSPR = 0; */227}228229static struct puv3_cpu_pm_fns puv3_cpu_pm_fnss = {230.save_count = SLEEP_SAVE_COUNT,231.valid = puv3_cpu_pm_valid,232.save = puv3_cpu_pm_save,233.restore = puv3_cpu_pm_restore,234.enter = puv3_cpu_pm_enter,235.prepare = puv3_cpu_pm_prepare,236.finish = puv3_cpu_pm_finish,237};238239static void __init puv3_init_pm(void)240{241puv3_cpu_pm_fns = &puv3_cpu_pm_fnss;242}243#else244static inline void puv3_init_pm(void) {}245#endif246247void puv3_ps2_init(void)248{249struct clk *bclk32;250251bclk32 = clk_get(NULL, "BUS32_CLK");252writel(clk_get_rate(bclk32) / 200000, PS2_CNT); /* should > 5us */253}254255void __init puv3_core_init(void)256{257puv3_init_pm();258puv3_ps2_init();259260platform_device_register_simple("PKUnity-v3-RTC", -1,261puv3_rtc_resources, ARRAY_SIZE(puv3_rtc_resources));262platform_device_register_simple("PKUnity-v3-UMAL", -1,263puv3_umal_resources, ARRAY_SIZE(puv3_umal_resources));264platform_device_register_simple("PKUnity-v3-MMC", -1,265puv3_mmc_resources, ARRAY_SIZE(puv3_mmc_resources));266platform_device_register_simple("PKUnity-v3-UNIGFX", -1,267puv3_unigfx_resources, ARRAY_SIZE(puv3_unigfx_resources));268platform_device_register_simple("PKUnity-v3-PWM", -1,269puv3_pwm_resources, ARRAY_SIZE(puv3_pwm_resources));270platform_device_register_simple("PKUnity-v3-UART", 0,271puv3_uart0_resources, ARRAY_SIZE(puv3_uart0_resources));272platform_device_register_simple("PKUnity-v3-UART", 1,273puv3_uart1_resources, ARRAY_SIZE(puv3_uart1_resources));274platform_device_register_simple("PKUnity-v3-AC97", -1, NULL, 0);275platform_device_register_resndata(&platform_bus, "musb_hdrc", -1,276puv3_usb_resources, ARRAY_SIZE(puv3_usb_resources),277&puv3_usb_plat, sizeof(puv3_usb_plat));278}279280281282