linux/arch/arm/mach-vt8500/vt8500.c
<<
>>
Prefs
   1/*
   2 *  arch/arm/mach-vt8500/vt8500.c
   3 *
   4 *  Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19 */
  20
  21#include <linux/io.h>
  22#include <linux/pm.h>
  23#include <linux/reboot.h>
  24
  25#include <asm/mach-types.h>
  26#include <asm/mach/arch.h>
  27#include <asm/mach/time.h>
  28#include <asm/mach/map.h>
  29
  30#include <linux/of.h>
  31#include <linux/of_address.h>
  32#include <linux/of_irq.h>
  33#include <linux/of_platform.h>
  34
  35#define LEGACY_GPIO_BASE        0xD8110000
  36#define LEGACY_PMC_BASE         0xD8130000
  37
  38/* Registers in GPIO Controller */
  39#define VT8500_GPIO_MUX_REG     0x200
  40
  41/* Registers in Power Management Controller */
  42#define VT8500_HCR_REG          0x12
  43#define VT8500_PMSR_REG         0x60
  44
  45static void __iomem *pmc_base;
  46
  47static void vt8500_restart(enum reboot_mode mode, const char *cmd)
  48{
  49        if (pmc_base)
  50                writel(1, pmc_base + VT8500_PMSR_REG);
  51}
  52
  53static struct map_desc vt8500_io_desc[] __initdata = {
  54        /* SoC MMIO registers */
  55        [0] = {
  56                .virtual        = 0xf8000000,
  57                .pfn            = __phys_to_pfn(0xd8000000),
  58                .length         = 0x00390000, /* max of all chip variants */
  59                .type           = MT_DEVICE
  60        },
  61};
  62
  63static void __init vt8500_map_io(void)
  64{
  65        iotable_init(vt8500_io_desc, ARRAY_SIZE(vt8500_io_desc));
  66}
  67
  68static void vt8500_power_off(void)
  69{
  70        local_irq_disable();
  71        writew(5, pmc_base + VT8500_HCR_REG);
  72        asm("mcr p15, 0, %0, c7, c0, 4" : : "r" (0));
  73}
  74
  75static void __init vt8500_init(void)
  76{
  77        struct device_node *np;
  78#if defined(CONFIG_FB_VT8500) || defined(CONFIG_FB_WM8505)
  79        struct device_node *fb;
  80        void __iomem *gpio_base;
  81#endif
  82
  83#ifdef CONFIG_FB_VT8500
  84        fb = of_find_compatible_node(NULL, NULL, "via,vt8500-fb");
  85        if (fb) {
  86                np = of_find_compatible_node(NULL, NULL, "via,vt8500-gpio");
  87                if (np) {
  88                        gpio_base = of_iomap(np, 0);
  89
  90                        if (!gpio_base)
  91                                pr_err("%s: of_iomap(gpio_mux) failed\n",
  92                                                                __func__);
  93
  94                        of_node_put(np);
  95                } else {
  96                        gpio_base = ioremap(LEGACY_GPIO_BASE, 0x1000);
  97                        if (!gpio_base)
  98                                pr_err("%s: ioremap(legacy_gpio_mux) failed\n",
  99                                                                __func__);
 100                }
 101                if (gpio_base) {
 102                        writel(readl(gpio_base + VT8500_GPIO_MUX_REG) | 1,
 103                                gpio_base + VT8500_GPIO_MUX_REG);
 104                        iounmap(gpio_base);
 105                } else
 106                        pr_err("%s: Could not remap GPIO mux\n", __func__);
 107
 108                of_node_put(fb);
 109        }
 110#endif
 111
 112#ifdef CONFIG_FB_WM8505
 113        fb = of_find_compatible_node(NULL, NULL, "wm,wm8505-fb");
 114        if (fb) {
 115                np = of_find_compatible_node(NULL, NULL, "wm,wm8505-gpio");
 116                if (!np)
 117                        np = of_find_compatible_node(NULL, NULL,
 118                                                        "wm,wm8650-gpio");
 119                if (np) {
 120                        gpio_base = of_iomap(np, 0);
 121
 122                        if (!gpio_base)
 123                                pr_err("%s: of_iomap(gpio_mux) failed\n",
 124                                                                __func__);
 125
 126                        of_node_put(np);
 127                } else {
 128                        gpio_base = ioremap(LEGACY_GPIO_BASE, 0x1000);
 129                        if (!gpio_base)
 130                                pr_err("%s: ioremap(legacy_gpio_mux) failed\n",
 131                                                                __func__);
 132                }
 133                if (gpio_base) {
 134                        writel(readl(gpio_base + VT8500_GPIO_MUX_REG) |
 135                                0x80000000, gpio_base + VT8500_GPIO_MUX_REG);
 136                        iounmap(gpio_base);
 137                } else
 138                        pr_err("%s: Could not remap GPIO mux\n", __func__);
 139
 140                of_node_put(fb);
 141        }
 142#endif
 143
 144        np = of_find_compatible_node(NULL, NULL, "via,vt8500-pmc");
 145        if (np) {
 146                pmc_base = of_iomap(np, 0);
 147
 148                if (!pmc_base)
 149                        pr_err("%s:of_iomap(pmc) failed\n", __func__);
 150
 151                of_node_put(np);
 152        } else {
 153                pmc_base = ioremap(LEGACY_PMC_BASE, 0x1000);
 154                if (!pmc_base)
 155                        pr_err("%s:ioremap(power_off) failed\n", __func__);
 156        }
 157        if (pmc_base)
 158                pm_power_off = &vt8500_power_off;
 159        else
 160                pr_err("%s: PMC Hibernation register could not be remapped, not enabling power off!\n", __func__);
 161
 162        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 163}
 164
 165static const char * const vt8500_dt_compat[] = {
 166        "via,vt8500",
 167        "wm,wm8650",
 168        "wm,wm8505",
 169        "wm,wm8750",
 170        "wm,wm8850",
 171        NULL
 172};
 173
 174DT_MACHINE_START(WMT_DT, "VIA/Wondermedia SoC (Device Tree Support)")
 175        .dt_compat      = vt8500_dt_compat,
 176        .map_io         = vt8500_map_io,
 177        .init_machine   = vt8500_init,
 178        .restart        = vt8500_restart,
 179MACHINE_END
 180
 181