linux/arch/unicore32/kernel/puv3-core.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/unicore32/kernel/puv3-core.c
   3 *
   4 * Code specific to PKUnity SoC and UniCore ISA
   5 *
   6 *      Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
   7 *      Copyright (C) 2001-2010 Guan Xuetao
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License version 2 as
  11 * published by the Free Software Foundation.
  12 */
  13
  14#include <linux/init.h>
  15#include <linux/device.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>
  21
  22#include <asm/irq.h>
  23#include <mach/hardware.h>
  24#include <mach/pm.h>
  25
  26/*
  27 * This is the PKUnity sched_clock implementation.  This has
  28 * 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 as
  31 * long as there is always less than 582 seconds between successive
  32 * calls to this function.
  33 *
  34 *  ( * 1E9 / CLOCK_TICK_RATE ) -> about 2235/32
  35 */
  36unsigned long long sched_clock(void)
  37{
  38        unsigned long long v = cnt32_to_63(readl(OST_OSCR));
  39
  40        /* original conservative method, but overflow frequently
  41         * v *= NSEC_PER_SEC >> 12;
  42         * do_div(v, CLOCK_TICK_RATE >> 12);
  43         */
  44        v = ((v & 0x7fffffffffffffffULL) * 2235) >> 5;
  45
  46        return v;
  47}
  48
  49static 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};
  63
  64static struct musb_hdrc_config  puv3_usb_config[] = {
  65        {
  66                .num_eps = 16,
  67                .multipoint = 1,
  68#ifdef CONFIG_USB_INVENTRA_DMA
  69                .dma = 1,
  70                .dma_channels = 8,
  71#endif
  72        },
  73};
  74
  75static 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};
  81
  82static 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};
  94
  95static 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};
 102
 103static 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_IRQ
 118        }
 119};
 120
 121static 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};
 128
 129static 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_IRQ
 139        }
 140};
 141
 142static 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_IRQ
 152        }
 153};
 154
 155static 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_IRQ
 165        }
 166};
 167
 168#ifdef CONFIG_PUV3_PM
 169
 170#define SAVE(x)         sleep_save[SLEEP_SAVE_##x] = x
 171#define RESTORE(x)      x = sleep_save[SLEEP_SAVE_##x]
 172
 173/*
 174 * List of global PXA peripheral registers to preserve.
 175 * More ones like CP and general purpose register values are preserved
 176 * with the stack pointer in sleep.S.
 177 */
 178enum {
 179        SLEEP_SAVE_PM_PLLDDRCFG,
 180        SLEEP_SAVE_COUNT
 181};
 182
 183
 184static void puv3_cpu_pm_save(unsigned long *sleep_save)
 185{
 186/*      SAVE(PM_PLLDDRCFG); */
 187}
 188
 189static void puv3_cpu_pm_restore(unsigned long *sleep_save)
 190{
 191/*      RESTORE(PM_PLLDDRCFG); */
 192}
 193
 194static int puv3_cpu_pm_prepare(void)
 195{
 196        /* set resume return address */
 197        writel(virt_to_phys(puv3_cpu_resume), PM_DIVCFG);
 198        return 0;
 199}
 200
 201static void puv3_cpu_pm_enter(suspend_state_t state)
 202{
 203        /* Clear reset status */
 204        writel(RESETC_RSSR_HWR | RESETC_RSSR_WDR
 205                        | RESETC_RSSR_SMR | RESETC_RSSR_SWR, RESETC_RSSR);
 206
 207        switch (state) {
 208/*      case PM_SUSPEND_ON:
 209                puv3_cpu_idle();
 210                break; */
 211        case PM_SUSPEND_MEM:
 212                puv3_cpu_pm_prepare();
 213                puv3_cpu_suspend(PM_PMCR_SFB);
 214                break;
 215        }
 216}
 217
 218static int puv3_cpu_pm_valid(suspend_state_t state)
 219{
 220        return state == PM_SUSPEND_MEM;
 221}
 222
 223static void puv3_cpu_pm_finish(void)
 224{
 225        /* ensure not to come back here if it wasn't intended */
 226        /* PSPR = 0; */
 227}
 228
 229static 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};
 238
 239static void __init puv3_init_pm(void)
 240{
 241        puv3_cpu_pm_fns = &puv3_cpu_pm_fnss;
 242}
 243#else
 244static inline void puv3_init_pm(void) {}
 245#endif
 246
 247void puv3_ps2_init(void)
 248{
 249        struct clk *bclk32;
 250
 251        bclk32 = clk_get(NULL, "BUS32_CLK");
 252        writel(clk_get_rate(bclk32) / 200000, PS2_CNT); /* should > 5us */
 253}
 254
 255void __init puv3_core_init(void)
 256{
 257        puv3_init_pm();
 258        puv3_ps2_init();
 259
 260        platform_device_register_simple("PKUnity-v3-RTC", -1,
 261                        puv3_rtc_resources, ARRAY_SIZE(puv3_rtc_resources));
 262        platform_device_register_simple("PKUnity-v3-UMAL", -1,
 263                        puv3_umal_resources, ARRAY_SIZE(puv3_umal_resources));
 264        platform_device_register_simple("PKUnity-v3-MMC", -1,
 265                        puv3_mmc_resources, ARRAY_SIZE(puv3_mmc_resources));
 266        platform_device_register_simple("PKUnity-v3-UNIGFX", -1,
 267                        puv3_unigfx_resources, ARRAY_SIZE(puv3_unigfx_resources));
 268        platform_device_register_simple("PKUnity-v3-PWM", -1,
 269                        puv3_pwm_resources, ARRAY_SIZE(puv3_pwm_resources));
 270        platform_device_register_simple("PKUnity-v3-UART", 0,
 271                        puv3_uart0_resources, ARRAY_SIZE(puv3_uart0_resources));
 272        platform_device_register_simple("PKUnity-v3-UART", 1,
 273                        puv3_uart1_resources, ARRAY_SIZE(puv3_uart1_resources));
 274        platform_device_register_simple("PKUnity-v3-AC97", -1, NULL, 0);
 275        platform_device_register_resndata(&platform_bus, "musb_hdrc", -1,
 276                        puv3_usb_resources, ARRAY_SIZE(puv3_usb_resources),
 277                        &puv3_usb_plat, sizeof(puv3_usb_plat));
 278}
 279
 280