linux/arch/arm/mach-imx/anatop.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
   4 * Copyright 2017-2018 NXP.
   5 */
   6
   7#include <linux/err.h>
   8#include <linux/io.h>
   9#include <linux/of.h>
  10#include <linux/of_address.h>
  11#include <linux/mfd/syscon.h>
  12#include <linux/regmap.h>
  13#include "common.h"
  14#include "hardware.h"
  15
  16#define REG_SET         0x4
  17#define REG_CLR         0x8
  18
  19#define ANADIG_REG_2P5          0x130
  20#define ANADIG_REG_CORE         0x140
  21#define ANADIG_ANA_MISC0        0x150
  22#define ANADIG_DIGPROG          0x260
  23#define ANADIG_DIGPROG_IMX6SL   0x280
  24#define ANADIG_DIGPROG_IMX7D    0x800
  25
  26#define SRC_SBMR2               0x1c
  27
  28#define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG    0x40000
  29#define BM_ANADIG_REG_2P5_ENABLE_PULLDOWN       0x8
  30#define BM_ANADIG_REG_CORE_FET_ODRIVE           0x20000000
  31#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG    0x1000
  32/* Below MISC0_DISCON_HIGH_SNVS is only for i.MX6SL */
  33#define BM_ANADIG_ANA_MISC0_DISCON_HIGH_SNVS    0x2000
  34
  35static struct regmap *anatop;
  36
  37static void imx_anatop_enable_weak2p5(bool enable)
  38{
  39        u32 reg, val;
  40
  41        regmap_read(anatop, ANADIG_ANA_MISC0, &val);
  42
  43        /* can only be enabled when stop_mode_config is clear. */
  44        reg = ANADIG_REG_2P5;
  45        reg += (enable && (val & BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG) == 0) ?
  46                REG_SET : REG_CLR;
  47        regmap_write(anatop, reg, BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG);
  48}
  49
  50static void imx_anatop_enable_fet_odrive(bool enable)
  51{
  52        regmap_write(anatop, ANADIG_REG_CORE + (enable ? REG_SET : REG_CLR),
  53                BM_ANADIG_REG_CORE_FET_ODRIVE);
  54}
  55
  56static inline void imx_anatop_enable_2p5_pulldown(bool enable)
  57{
  58        regmap_write(anatop, ANADIG_REG_2P5 + (enable ? REG_SET : REG_CLR),
  59                BM_ANADIG_REG_2P5_ENABLE_PULLDOWN);
  60}
  61
  62static inline void imx_anatop_disconnect_high_snvs(bool enable)
  63{
  64        regmap_write(anatop, ANADIG_ANA_MISC0 + (enable ? REG_SET : REG_CLR),
  65                BM_ANADIG_ANA_MISC0_DISCON_HIGH_SNVS);
  66}
  67
  68void imx_anatop_pre_suspend(void)
  69{
  70        if (imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2)
  71                imx_anatop_enable_2p5_pulldown(true);
  72        else
  73                imx_anatop_enable_weak2p5(true);
  74
  75        imx_anatop_enable_fet_odrive(true);
  76
  77        if (cpu_is_imx6sl())
  78                imx_anatop_disconnect_high_snvs(true);
  79}
  80
  81void imx_anatop_post_resume(void)
  82{
  83        if (imx_mmdc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2)
  84                imx_anatop_enable_2p5_pulldown(false);
  85        else
  86                imx_anatop_enable_weak2p5(false);
  87
  88        imx_anatop_enable_fet_odrive(false);
  89
  90        if (cpu_is_imx6sl())
  91                imx_anatop_disconnect_high_snvs(false);
  92}
  93
  94void __init imx_init_revision_from_anatop(void)
  95{
  96        struct device_node *np, *src_np;
  97        void __iomem *anatop_base;
  98        unsigned int revision;
  99        u32 digprog;
 100        u16 offset = ANADIG_DIGPROG;
 101        u8 major_part, minor_part;
 102
 103        np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
 104        anatop_base = of_iomap(np, 0);
 105        WARN_ON(!anatop_base);
 106        if (of_device_is_compatible(np, "fsl,imx6sl-anatop"))
 107                offset = ANADIG_DIGPROG_IMX6SL;
 108        if (of_device_is_compatible(np, "fsl,imx7d-anatop"))
 109                offset = ANADIG_DIGPROG_IMX7D;
 110        digprog = readl_relaxed(anatop_base + offset);
 111        iounmap(anatop_base);
 112
 113        /*
 114         * On i.MX7D digprog value match linux version format, so
 115         * it needn't map again and we can use register value directly.
 116         */
 117        if (of_device_is_compatible(np, "fsl,imx7d-anatop")) {
 118                revision = digprog & 0xff;
 119        } else {
 120                /*
 121                 * MAJOR: [15:8], the major silicon revison;
 122                 * MINOR: [7: 0], the minor silicon revison;
 123                 *
 124                 * please refer to the i.MX RM for the detailed
 125                 * silicon revison bit define.
 126                 * format the major part and minor part to match the
 127                 * linux kernel soc version format.
 128                 */
 129                major_part = (digprog >> 8) & 0xf;
 130                minor_part = digprog & 0xf;
 131                revision = ((major_part + 1) << 4) | minor_part;
 132
 133                if ((digprog >> 16) == MXC_CPU_IMX6ULL) {
 134                        void __iomem *src_base;
 135                        u32 sbmr2;
 136
 137                        src_np = of_find_compatible_node(NULL, NULL,
 138                                                     "fsl,imx6ul-src");
 139                        src_base = of_iomap(np, 0);
 140                        of_node_put(src_np);
 141                        WARN_ON(!src_base);
 142                        sbmr2 = readl_relaxed(src_base + SRC_SBMR2);
 143                        iounmap(src_base);
 144
 145                        /* src_sbmr2 bit 6 is to identify if it is i.MX6ULZ */
 146                        if (sbmr2 & (1 << 6)) {
 147                                digprog &= ~(0xff << 16);
 148                                digprog |= (MXC_CPU_IMX6ULZ << 16);
 149                        }
 150                }
 151        }
 152        of_node_put(np);
 153
 154        mxc_set_cpu_type(digprog >> 16 & 0xff);
 155        imx_set_soc_revision(revision);
 156}
 157
 158void __init imx_anatop_init(void)
 159{
 160        anatop = syscon_regmap_lookup_by_compatible("fsl,imx6q-anatop");
 161        if (IS_ERR(anatop))
 162                pr_err("%s: failed to find imx6q-anatop regmap!\n", __func__);
 163}
 164