linux/arch/unicore32/kernel/puv3-core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  linux/arch/unicore32/kernel/puv3-core.c
   4 *
   5 * Code specific to PKUnity SoC and UniCore ISA
   6 *
   7 *      Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
   8 *      Copyright (C) 2001-2010 Guan Xuetao
   9 */
  10
  11#include <linux/init.h>
  12#include <linux/device.h>
  13#include <linux/amba/bus.h>
  14#include <linux/platform_device.h>
  15#include <linux/io.h>
  16#include <linux/cnt32_to_63.h>
  17#include <linux/usb/musb.h>
  18
  19#include <asm/irq.h>
  20#include <mach/hardware.h>
  21#include <mach/pm.h>
  22
  23/*
  24 * This is the PKUnity sched_clock implementation.  This has
  25 * a resolution of 271ns, and a maximum value of 32025597s (370 days).
  26 *
  27 * The return value is guaranteed to be monotonic in that range as
  28 * long as there is always less than 582 seconds between successive
  29 * calls to this function.
  30 *
  31 *  ( * 1E9 / CLOCK_TICK_RATE ) -> about 2235/32
  32 */
  33unsigned long long sched_clock(void)
  34{
  35        unsigned long long v = cnt32_to_63(readl(OST_OSCR));
  36
  37        /* original conservative method, but overflow frequently
  38         * v *= NSEC_PER_SEC >> 12;
  39         * do_div(v, CLOCK_TICK_RATE >> 12);
  40         */
  41        v = ((v & 0x7fffffffffffffffULL) * 2235) >> 5;
  42
  43        return v;
  44}
  45
  46static struct resource puv3_usb_resources[] = {
  47        /* order is significant! */
  48        {
  49                .start          = io_v2p(PKUNITY_USB_BASE),
  50                .end            = io_v2p(PKUNITY_USB_BASE) + 0x3ff,
  51                .flags          = IORESOURCE_MEM,
  52        }, {
  53                .start          = IRQ_USB,
  54                .flags          = IORESOURCE_IRQ,
  55        }, {
  56                .start          = IRQ_USB,
  57                .flags          = IORESOURCE_IRQ,
  58        },
  59};
  60
  61static struct musb_hdrc_config  puv3_usb_config[] = {
  62        {
  63                .num_eps = 16,
  64                .multipoint = 1,
  65#ifdef CONFIG_USB_INVENTRA_DMA
  66                .dma = 1,
  67                .dma_channels = 8,
  68#endif
  69        },
  70};
  71
  72static struct musb_hdrc_platform_data puv3_usb_plat = {
  73        .mode           = MUSB_HOST,
  74        .min_power      = 100,
  75        .clock          = 0,
  76        .config         = puv3_usb_config,
  77};
  78
  79static struct resource puv3_mmc_resources[] = {
  80        [0] = {
  81                .start  = io_v2p(PKUNITY_SDC_BASE),
  82                .end    = io_v2p(PKUNITY_SDC_BASE) + 0xfff,
  83                .flags  = IORESOURCE_MEM,
  84        },
  85        [1] = {
  86                .start  = IRQ_SDC,
  87                .end    = IRQ_SDC,
  88                .flags  = IORESOURCE_IRQ,
  89        },
  90};
  91
  92static struct resource puv3_unigfx_resources[] = {
  93        [0] = {
  94                .start  = io_v2p(PKUNITY_UNIGFX_BASE),
  95                .end    = io_v2p(PKUNITY_UNIGFX_BASE) + 0xfff,
  96                .flags  = IORESOURCE_MEM,
  97        },
  98};
  99
 100static struct resource puv3_rtc_resources[] = {
 101        [0] = {
 102                .start = io_v2p(PKUNITY_RTC_BASE),
 103                .end   = io_v2p(PKUNITY_RTC_BASE) + 0xff,
 104                .flags = IORESOURCE_MEM,
 105        },
 106        [1] = {
 107                .start = IRQ_RTCAlarm,
 108                .end   = IRQ_RTCAlarm,
 109                .flags = IORESOURCE_IRQ,
 110        },
 111        [2] = {
 112                .start = IRQ_RTC,
 113                .end   = IRQ_RTC,
 114                .flags = IORESOURCE_IRQ
 115        }
 116};
 117
 118static struct resource puv3_pwm_resources[] = {
 119        [0] = {
 120                .start  = io_v2p(PKUNITY_OST_BASE) + 0x80,
 121                .end    = io_v2p(PKUNITY_OST_BASE) + 0xff,
 122                .flags  = IORESOURCE_MEM,
 123        },
 124};
 125
 126static struct resource puv3_uart0_resources[] = {
 127        [0] = {
 128                .start = io_v2p(PKUNITY_UART0_BASE),
 129                .end   = io_v2p(PKUNITY_UART0_BASE) + 0xff,
 130                .flags = IORESOURCE_MEM,
 131        },
 132        [1] = {
 133                .start = IRQ_UART0,
 134                .end   = IRQ_UART0,
 135                .flags = IORESOURCE_IRQ
 136        }
 137};
 138
 139static struct resource puv3_uart1_resources[] = {
 140        [0] = {
 141                .start = io_v2p(PKUNITY_UART1_BASE),
 142                .end   = io_v2p(PKUNITY_UART1_BASE) + 0xff,
 143                .flags = IORESOURCE_MEM,
 144        },
 145        [1] = {
 146                .start = IRQ_UART1,
 147                .end   = IRQ_UART1,
 148                .flags = IORESOURCE_IRQ
 149        }
 150};
 151
 152static struct resource puv3_umal_resources[] = {
 153        [0] = {
 154                .start = io_v2p(PKUNITY_UMAL_BASE),
 155                .end   = io_v2p(PKUNITY_UMAL_BASE) + 0x1fff,
 156                .flags = IORESOURCE_MEM,
 157        },
 158        [1] = {
 159                .start = IRQ_UMAL,
 160                .end   = IRQ_UMAL,
 161                .flags = IORESOURCE_IRQ
 162        }
 163};
 164
 165#ifdef CONFIG_PUV3_PM
 166
 167#define SAVE(x)         sleep_save[SLEEP_SAVE_##x] = x
 168#define RESTORE(x)      x = sleep_save[SLEEP_SAVE_##x]
 169
 170/*
 171 * List of global PXA peripheral registers to preserve.
 172 * More ones like CP and general purpose register values are preserved
 173 * with the stack pointer in sleep.S.
 174 */
 175enum {
 176        SLEEP_SAVE_PM_PLLDDRCFG,
 177        SLEEP_SAVE_COUNT
 178};
 179
 180
 181static void puv3_cpu_pm_save(unsigned long *sleep_save)
 182{
 183/*      SAVE(PM_PLLDDRCFG); */
 184}
 185
 186static void puv3_cpu_pm_restore(unsigned long *sleep_save)
 187{
 188/*      RESTORE(PM_PLLDDRCFG); */
 189}
 190
 191static int puv3_cpu_pm_prepare(void)
 192{
 193        /* set resume return address */
 194        writel(virt_to_phys(puv3_cpu_resume), PM_DIVCFG);
 195        return 0;
 196}
 197
 198static void puv3_cpu_pm_enter(suspend_state_t state)
 199{
 200        /* Clear reset status */
 201        writel(RESETC_RSSR_HWR | RESETC_RSSR_WDR
 202                        | RESETC_RSSR_SMR | RESETC_RSSR_SWR, RESETC_RSSR);
 203
 204        switch (state) {
 205/*      case PM_SUSPEND_ON:
 206                puv3_cpu_idle();
 207                break; */
 208        case PM_SUSPEND_MEM:
 209                puv3_cpu_pm_prepare();
 210                puv3_cpu_suspend(PM_PMCR_SFB);
 211                break;
 212        }
 213}
 214
 215static int puv3_cpu_pm_valid(suspend_state_t state)
 216{
 217        return state == PM_SUSPEND_MEM;
 218}
 219
 220static void puv3_cpu_pm_finish(void)
 221{
 222        /* ensure not to come back here if it wasn't intended */
 223        /* PSPR = 0; */
 224}
 225
 226static struct puv3_cpu_pm_fns puv3_cpu_pm_fnss = {
 227        .save_count     = SLEEP_SAVE_COUNT,
 228        .valid          = puv3_cpu_pm_valid,
 229        .save           = puv3_cpu_pm_save,
 230        .restore        = puv3_cpu_pm_restore,
 231        .enter          = puv3_cpu_pm_enter,
 232        .prepare        = puv3_cpu_pm_prepare,
 233        .finish         = puv3_cpu_pm_finish,
 234};
 235
 236static void __init puv3_init_pm(void)
 237{
 238        puv3_cpu_pm_fns = &puv3_cpu_pm_fnss;
 239}
 240#else
 241static inline void puv3_init_pm(void) {}
 242#endif
 243
 244void puv3_ps2_init(void)
 245{
 246        struct clk *bclk32;
 247
 248        bclk32 = clk_get(NULL, "BUS32_CLK");
 249        writel(clk_get_rate(bclk32) / 200000, PS2_CNT); /* should > 5us */
 250}
 251
 252void __init puv3_core_init(void)
 253{
 254        puv3_init_pm();
 255        puv3_ps2_init();
 256
 257        platform_device_register_simple("PKUnity-v3-RTC", -1,
 258                        puv3_rtc_resources, ARRAY_SIZE(puv3_rtc_resources));
 259        platform_device_register_simple("PKUnity-v3-UMAL", -1,
 260                        puv3_umal_resources, ARRAY_SIZE(puv3_umal_resources));
 261        platform_device_register_simple("PKUnity-v3-MMC", -1,
 262                        puv3_mmc_resources, ARRAY_SIZE(puv3_mmc_resources));
 263        platform_device_register_simple("PKUnity-v3-UNIGFX", -1,
 264                        puv3_unigfx_resources, ARRAY_SIZE(puv3_unigfx_resources));
 265        platform_device_register_simple("PKUnity-v3-PWM", -1,
 266                        puv3_pwm_resources, ARRAY_SIZE(puv3_pwm_resources));
 267        platform_device_register_simple("PKUnity-v3-UART", 0,
 268                        puv3_uart0_resources, ARRAY_SIZE(puv3_uart0_resources));
 269        platform_device_register_simple("PKUnity-v3-UART", 1,
 270                        puv3_uart1_resources, ARRAY_SIZE(puv3_uart1_resources));
 271        platform_device_register_simple("PKUnity-v3-AC97", -1, NULL, 0);
 272        platform_device_register_resndata(NULL, "musb_hdrc", -1,
 273                        puv3_usb_resources, ARRAY_SIZE(puv3_usb_resources),
 274                        &puv3_usb_plat, sizeof(puv3_usb_plat));
 275}
 276
 277