linux/arch/powerpc/sysdev/fsl_soc.c
<<
>>
Prefs
   1/*
   2 * FSL SoC setup code
   3 *
   4 * Maintained by Kumar Gala (see MAINTAINERS for contact information)
   5 *
   6 * 2006 (c) MontaVista Software, Inc.
   7 * Vitaly Bordug <vbordug@ru.mvista.com>
   8 *
   9 * This program is free software; you can redistribute  it and/or modify it
  10 * under  the terms of  the GNU General  Public License as published by the
  11 * Free Software Foundation;  either version 2 of the  License, or (at your
  12 * option) any later version.
  13 */
  14
  15#include <linux/stddef.h>
  16#include <linux/kernel.h>
  17#include <linux/init.h>
  18#include <linux/errno.h>
  19#include <linux/major.h>
  20#include <linux/delay.h>
  21#include <linux/irq.h>
  22#include <linux/export.h>
  23#include <linux/device.h>
  24#include <linux/platform_device.h>
  25#include <linux/of.h>
  26#include <linux/of_platform.h>
  27#include <linux/phy.h>
  28#include <linux/spi/spi.h>
  29#include <linux/fsl_devices.h>
  30#include <linux/fs_enet_pd.h>
  31#include <linux/fs_uart_pd.h>
  32
  33#include <linux/atomic.h>
  34#include <asm/io.h>
  35#include <asm/irq.h>
  36#include <asm/time.h>
  37#include <asm/prom.h>
  38#include <asm/machdep.h>
  39#include <sysdev/fsl_soc.h>
  40#include <mm/mmu_decl.h>
  41#include <asm/cpm2.h>
  42#include <asm/fsl_hcalls.h>     /* For the Freescale hypervisor */
  43
  44extern void init_fcc_ioports(struct fs_platform_info*);
  45extern void init_fec_ioports(struct fs_platform_info*);
  46extern void init_smc_ioports(struct fs_uart_platform_info*);
  47static phys_addr_t immrbase = -1;
  48
  49phys_addr_t get_immrbase(void)
  50{
  51        struct device_node *soc;
  52
  53        if (immrbase != -1)
  54                return immrbase;
  55
  56        soc = of_find_node_by_type(NULL, "soc");
  57        if (soc) {
  58                int size;
  59                u32 naddr;
  60                const __be32 *prop = of_get_property(soc, "#address-cells", &size);
  61
  62                if (prop && size == 4)
  63                        naddr = be32_to_cpup(prop);
  64                else
  65                        naddr = 2;
  66
  67                prop = of_get_property(soc, "ranges", &size);
  68                if (prop)
  69                        immrbase = of_translate_address(soc, prop + naddr);
  70
  71                of_node_put(soc);
  72        }
  73
  74        return immrbase;
  75}
  76
  77EXPORT_SYMBOL(get_immrbase);
  78
  79static u32 sysfreq = -1;
  80
  81u32 fsl_get_sys_freq(void)
  82{
  83        struct device_node *soc;
  84        const u32 *prop;
  85        int size;
  86
  87        if (sysfreq != -1)
  88                return sysfreq;
  89
  90        soc = of_find_node_by_type(NULL, "soc");
  91        if (!soc)
  92                return -1;
  93
  94        prop = of_get_property(soc, "clock-frequency", &size);
  95        if (!prop || size != sizeof(*prop) || *prop == 0)
  96                prop = of_get_property(soc, "bus-frequency", &size);
  97
  98        if (prop && size == sizeof(*prop))
  99                sysfreq = *prop;
 100
 101        of_node_put(soc);
 102        return sysfreq;
 103}
 104EXPORT_SYMBOL(fsl_get_sys_freq);
 105
 106#if defined(CONFIG_CPM2) || defined(CONFIG_QUICC_ENGINE) || defined(CONFIG_8xx)
 107
 108static u32 brgfreq = -1;
 109
 110u32 get_brgfreq(void)
 111{
 112        struct device_node *node;
 113        const unsigned int *prop;
 114        int size;
 115
 116        if (brgfreq != -1)
 117                return brgfreq;
 118
 119        node = of_find_compatible_node(NULL, NULL, "fsl,cpm-brg");
 120        if (node) {
 121                prop = of_get_property(node, "clock-frequency", &size);
 122                if (prop && size == 4)
 123                        brgfreq = *prop;
 124
 125                of_node_put(node);
 126                return brgfreq;
 127        }
 128
 129        /* Legacy device binding -- will go away when no users are left. */
 130        node = of_find_node_by_type(NULL, "cpm");
 131        if (!node)
 132                node = of_find_compatible_node(NULL, NULL, "fsl,qe");
 133        if (!node)
 134                node = of_find_node_by_type(NULL, "qe");
 135
 136        if (node) {
 137                prop = of_get_property(node, "brg-frequency", &size);
 138                if (prop && size == 4)
 139                        brgfreq = *prop;
 140
 141                if (brgfreq == -1 || brgfreq == 0) {
 142                        prop = of_get_property(node, "bus-frequency", &size);
 143                        if (prop && size == 4)
 144                                brgfreq = *prop / 2;
 145                }
 146                of_node_put(node);
 147        }
 148
 149        return brgfreq;
 150}
 151
 152EXPORT_SYMBOL(get_brgfreq);
 153
 154static u32 fs_baudrate = -1;
 155
 156u32 get_baudrate(void)
 157{
 158        struct device_node *node;
 159
 160        if (fs_baudrate != -1)
 161                return fs_baudrate;
 162
 163        node = of_find_node_by_type(NULL, "serial");
 164        if (node) {
 165                int size;
 166                const unsigned int *prop = of_get_property(node,
 167                                "current-speed", &size);
 168
 169                if (prop)
 170                        fs_baudrate = *prop;
 171                of_node_put(node);
 172        }
 173
 174        return fs_baudrate;
 175}
 176
 177EXPORT_SYMBOL(get_baudrate);
 178#endif /* CONFIG_CPM2 */
 179
 180#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
 181static __be32 __iomem *rstcr;
 182
 183static int __init setup_rstcr(void)
 184{
 185        struct device_node *np;
 186
 187        for_each_node_by_name(np, "global-utilities") {
 188                if ((of_get_property(np, "fsl,has-rstcr", NULL))) {
 189                        rstcr = of_iomap(np, 0) + 0xb0;
 190                        if (!rstcr)
 191                                printk (KERN_ERR "Error: reset control "
 192                                                "register not mapped!\n");
 193                        break;
 194                }
 195        }
 196
 197        if (!rstcr && ppc_md.restart == fsl_rstcr_restart)
 198                printk(KERN_ERR "No RSTCR register, warm reboot won't work\n");
 199
 200        of_node_put(np);
 201
 202        return 0;
 203}
 204
 205arch_initcall(setup_rstcr);
 206
 207void fsl_rstcr_restart(char *cmd)
 208{
 209        local_irq_disable();
 210        if (rstcr)
 211                /* set reset control register */
 212                out_be32(rstcr, 0x2);   /* HRESET_REQ */
 213
 214        while (1) ;
 215}
 216#endif
 217
 218#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
 219struct platform_diu_data_ops diu_ops;
 220EXPORT_SYMBOL(diu_ops);
 221#endif
 222
 223#ifdef CONFIG_EPAPR_PARAVIRT
 224/*
 225 * Restart the current partition
 226 *
 227 * This function should be assigned to the ppc_md.restart function pointer,
 228 * to initiate a partition restart when we're running under the Freescale
 229 * hypervisor.
 230 */
 231void fsl_hv_restart(char *cmd)
 232{
 233        pr_info("hv restart\n");
 234        fh_partition_restart(-1);
 235}
 236
 237/*
 238 * Halt the current partition
 239 *
 240 * This function should be assigned to the pm_power_off and ppc_md.halt
 241 * function pointers, to shut down the partition when we're running under
 242 * the Freescale hypervisor.
 243 */
 244void fsl_hv_halt(void)
 245{
 246        pr_info("hv exit\n");
 247        fh_partition_stop(-1);
 248}
 249#endif
 250