The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/arm64/nvidia/tegra210/tegra210_pmc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright 2020 Michal Meloun <mmel@FreeBSD.org>
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/bus.h>
   34 #include <sys/kernel.h>
   35 #include <sys/module.h>
   36 #include <sys/malloc.h>
   37 #include <sys/mutex.h>
   38 #include <sys/rman.h>
   39 
   40 #include <machine/bus.h>
   41 
   42 #include <dev/extres/clk/clk.h>
   43 #include <dev/extres/hwreset/hwreset.h>
   44 #include <dev/ofw/ofw_bus.h>
   45 #include <dev/ofw/ofw_bus_subr.h>
   46 #include <dev/psci/smccc.h>
   47 
   48 #include <arm/nvidia/tegra_pmc.h>
   49 
   50 #define PMC_CNTRL                       0x000
   51 #define  PMC_CNTRL_SHUTDOWN_OE                  (1 << 22)
   52 #define  PMC_CNTRL_CPUPWRGOOD_SEL_MASK          (0x3 << 20)
   53 #define  PMC_CNTRL_CPUPWRGOOD_SEL_SHIFT         20
   54 #define  PMC_CNTRL_CPUPWRGOOD_EN                (1 << 19)
   55 #define  PMC_CNTRL_FUSE_OVERRIDE                (1 << 18)
   56 #define  PMC_CNTRL_INTR_POLARITY                (1 << 17)
   57 #define  PMC_CNTRL_CPU_PWRREQ_OE                (1 << 16)
   58 #define  PMC_CNTRL_CPU_PWRREQ_POLARITY          (1 << 15)
   59 #define  PMC_CNTRL_SIDE_EFFECT_LP0              (1 << 14)
   60 #define  PMC_CNTRL_AOINIT                       (1 << 13)
   61 #define  PMC_CNTRL_PWRGATE_DIS                  (1 << 12)
   62 #define  PMC_CNTRL_SYSCLK_OE                    (1 << 11)
   63 #define  PMC_CNTRL_SYSCLK_POLARITY              (1 << 10)
   64 #define  PMC_CNTRL_PWRREQ_OE                    (1 <<  9)
   65 #define  PMC_CNTRL_PWRREQ_POLARITY              (1 <<  8)
   66 #define  PMC_CNTRL_BLINK_EN                     (1 <<  7)
   67 #define  PMC_CNTRL_GLITCHDET_DIS                (1 <<  6)
   68 #define  PMC_CNTRL_LATCHWAKE_EN                 (1 <<  5)
   69 #define  PMC_CNTRL_MAIN_RST                     (1 <<  4)
   70 #define  PMC_CNTRL_KBC_RST                      (1 <<  3)
   71 #define  PMC_CNTRL_RTC_RST                      (1 <<  2)
   72 #define  PMC_CNTRL_RTC_CLK_DIS                  (1 <<  1)
   73 #define  PMC_CNTRL_KBC_CLK_DIS                  (1 <<  0)
   74 
   75 #define PMC_DPD_SAMPLE                  0x020
   76 
   77 #define PMC_CLAMP_STATUS                0x02C
   78 #define   PMC_CLAMP_STATUS_PARTID(x)            (1 << ((x) & 0x1F))
   79 
   80 #define PMC_PWRGATE_TOGGLE              0x030
   81 #define  PMC_PWRGATE_TOGGLE_START               (1 << 8)
   82 #define  PMC_PWRGATE_TOGGLE_PARTID(x)           (((x) & 0x1F) << 0)
   83 
   84 #define PMC_REMOVE_CLAMPING_CMD         0x034
   85 #define   PMC_REMOVE_CLAMPING_CMD_PARTID(x)     (1 << ((x) & 0x1F))
   86 
   87 #define PMC_PWRGATE_STATUS              0x038
   88 #define PMC_PWRGATE_STATUS_PARTID(x)            (1 << ((x) & 0x1F))
   89 
   90 #define PMC_SCRATCH0                    0x050
   91 #define  PMC_SCRATCH0_MODE_RECOVERY             (1 << 31)
   92 #define  PMC_SCRATCH0_MODE_BOOTLOADER           (1 << 30)
   93 #define  PMC_SCRATCH0_MODE_RCM                  (1 << 1)
   94 #define  PMC_SCRATCH0_MODE_MASK                 (PMC_SCRATCH0_MODE_RECOVERY | \
   95                                                 PMC_SCRATCH0_MODE_BOOTLOADER | \
   96                                                 PMC_SCRATCH0_MODE_RCM)
   97 
   98 #define PMC_CPUPWRGOOD_TIMER            0x0c8
   99 #define PMC_CPUPWROFF_TIMER             0x0cc
  100 
  101 #define PMC_SCRATCH41                   0x140
  102 
  103 #define PMC_SENSOR_CTRL                 0x1b0
  104 #define PMC_SENSOR_CTRL_BLOCK_SCRATCH_WRITE     (1 << 2)
  105 #define PMC_SENSOR_CTRL_ENABLE_RST              (1 << 1)
  106 #define PMC_SENSOR_CTRL_ENABLE_PG               (1 << 0)
  107 
  108 #define PMC_IO_DPD_REQ                  0x1b8
  109 #define  PMC_IO_DPD_REQ_CODE_IDLE               (0 << 30)
  110 #define  PMC_IO_DPD_REQ_CODE_OFF                (1 << 30)
  111 #define  PMC_IO_DPD_REQ_CODE_ON                 (2 << 30)
  112 #define  PMC_IO_DPD_REQ_CODE_MASK               (3 << 30)
  113 
  114 #define PMC_IO_DPD_STATUS               0x1bc
  115 #define  PMC_IO_DPD_STATUS_HDMI                 (1 << 28)
  116 #define PMC_IO_DPD2_REQ                 0x1c0
  117 #define PMC_IO_DPD2_STATUS              0x1c4
  118 #define  PMC_IO_DPD2_STATUS_HV                  (1 << 6)
  119 #define PMC_SEL_DPD_TIM                 0x1c8
  120 
  121 #define PMC_SCRATCH54                   0x258
  122 #define PMC_SCRATCH54_DATA_SHIFT                8
  123 #define PMC_SCRATCH54_ADDR_SHIFT                0
  124 
  125 #define PMC_SCRATCH55                   0x25c
  126 #define PMC_SCRATCH55_RST_ENABLE                (1 << 31)
  127 #define PMC_SCRATCH55_CNTRL_TYPE                (1 << 30)
  128 #define PMC_SCRATCH55_CNTRL_ID_SHIFT            27
  129 #define PMC_SCRATCH55_CNTRL_ID_MASK             0x07
  130 #define PMC_SCRATCH55_PINMUX_SHIFT              24
  131 #define PMC_SCRATCH55_PINMUX_MASK               0x07
  132 #define PMC_SCRATCH55_CHECKSUM_SHIFT            16
  133 #define PMC_SCRATCH55_CHECKSUM_MASK             0xFF
  134 #define PMC_SCRATCH55_16BITOP                   (1 << 15)
  135 #define PMC_SCRATCH55_I2CSLV1_SHIFT             0
  136 #define PMC_SCRATCH55_I2CSLV1_MASK              0x7F
  137 
  138 #define PMC_GPU_RG_CNTRL                0x2d4
  139 
  140 /* Secure access */
  141 #define PMC_SMC                         0xc2fffe00
  142 #define PMC_SMC_READ                    0xaa
  143 #define PMC_SMC_WRITE                   0xbb
  144 
  145 #define PMC_LOCK(_sc)           mtx_lock(&(_sc)->mtx)
  146 #define PMC_UNLOCK(_sc)         mtx_unlock(&(_sc)->mtx)
  147 #define PMC_LOCK_INIT(_sc)      mtx_init(&(_sc)->mtx,                   \
  148             device_get_nameunit(_sc->dev), "tegra210_pmc", MTX_DEF)
  149 #define PMC_LOCK_DESTROY(_sc)   mtx_destroy(&(_sc)->mtx);
  150 #define PMC_ASSERT_LOCKED(_sc)  mtx_assert(&(_sc)->mtx, MA_OWNED);
  151 #define PMC_ASSERT_UNLOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_NOTOWNED);
  152 
  153 struct tegra210_pmc_softc {
  154         device_t                dev;
  155         struct resource         *mem_res;
  156         clk_t                   clk;
  157         struct mtx              mtx;
  158         bool                    secure_access;
  159 
  160         uint32_t                rate;
  161         enum tegra_suspend_mode suspend_mode;
  162         uint32_t                cpu_good_time;
  163         uint32_t                cpu_off_time;
  164         uint32_t                core_osc_time;
  165         uint32_t                core_pmu_time;
  166         uint32_t                core_off_time;
  167         int                     corereq_high;
  168         int                     sysclkreq_high;
  169         int                     combined_req;
  170         int                     cpu_pwr_good_en;
  171         uint32_t                lp0_vec_phys;
  172         uint32_t                lp0_vec_size;
  173 };
  174 
  175 static struct ofw_compat_data compat_data[] = {
  176         {"nvidia,tegra210-pmc",         1},
  177         {NULL,                          0},
  178 };
  179 
  180 static struct tegra210_pmc_softc *pmc_sc;
  181 
  182 static inline struct tegra210_pmc_softc *
  183 tegra210_pmc_get_sc(void)
  184 {
  185         if (pmc_sc == NULL)
  186                 panic("To early call to Tegra PMC driver.\n");
  187         return (pmc_sc);
  188 }
  189 
  190 static void
  191 WR4(struct tegra210_pmc_softc *sc, bus_size_t r, uint32_t v)
  192 {
  193         struct arm_smccc_res res;
  194 
  195         if (sc->secure_access) {
  196                 arm_smccc_smc(PMC_SMC, PMC_SMC_WRITE, r, v, 0, 0, 0, 0, &res);
  197                 if (res.a0 != 0)
  198                         device_printf(sc->dev," PMC SMC write failed: %lu\n",
  199                             res.a0);
  200         }
  201 
  202         bus_write_4(sc->mem_res, r, v);
  203 }
  204 
  205 static uint32_t
  206 RD4(struct tegra210_pmc_softc *sc, bus_size_t r)
  207 {
  208         struct arm_smccc_res res;
  209 
  210         if (sc->secure_access) {
  211                 arm_smccc_smc(PMC_SMC, PMC_SMC_READ, r, 0, 0, 0, 0, 0, &res);
  212                 if (res.a0 != 0)
  213                         device_printf(sc->dev," PMC SMC write failed: %lu\n",
  214                             res.a0);
  215                 return((uint32_t)res.a1);
  216         }
  217 
  218         return(bus_read_4(sc->mem_res, r));
  219 }
  220 
  221 static int
  222 tegra210_pmc_set_powergate(struct tegra210_pmc_softc *sc,
  223     enum tegra_powergate_id id, int ena)
  224 {
  225         uint32_t reg;
  226         int i;
  227 
  228         PMC_LOCK(sc);
  229 
  230         reg = RD4(sc, PMC_PWRGATE_STATUS) & PMC_PWRGATE_STATUS_PARTID(id);
  231         if (((reg != 0) && ena) || ((reg == 0) && !ena)) {
  232                 PMC_UNLOCK(sc);
  233                 return (0);
  234         }
  235 
  236         for (i = 100; i > 0; i--) {
  237                 reg = RD4(sc, PMC_PWRGATE_TOGGLE);
  238                 if ((reg & PMC_PWRGATE_TOGGLE_START) == 0)
  239                         break;
  240                 DELAY(1);
  241         }
  242         if (i <= 0)
  243                 device_printf(sc->dev,
  244                     "Timeout when waiting for TOGGLE_START\n");
  245 
  246         WR4(sc, PMC_PWRGATE_TOGGLE,
  247             PMC_PWRGATE_TOGGLE_START | PMC_PWRGATE_TOGGLE_PARTID(id));
  248 
  249         for (i = 100; i > 0; i--) {
  250                 reg = RD4(sc, PMC_PWRGATE_TOGGLE);
  251                 if ((reg & PMC_PWRGATE_TOGGLE_START) == 0)
  252                         break;
  253                 DELAY(1);
  254         }
  255         if (i <= 0)
  256                 device_printf(sc->dev,
  257                     "Timeout when waiting for TOGGLE_START\n");
  258                 PMC_UNLOCK(sc);
  259         return (0);
  260 }
  261 
  262 int
  263 tegra_powergate_remove_clamping(enum tegra_powergate_id  id)
  264 {
  265         struct tegra210_pmc_softc *sc;
  266         uint32_t reg;
  267         enum tegra_powergate_id swid;
  268         int i;
  269 
  270         sc = tegra210_pmc_get_sc();
  271 
  272         if (id == TEGRA_POWERGATE_3D) {
  273                 WR4(sc, PMC_GPU_RG_CNTRL, 0);
  274                 return (0);
  275         }
  276 
  277         reg = RD4(sc, PMC_PWRGATE_STATUS);
  278         if ((reg & PMC_PWRGATE_STATUS_PARTID(id)) == 0)
  279                 panic("Attempt to remove clamping for unpowered partition.\n");
  280 
  281         if (id == TEGRA_POWERGATE_PCX)
  282                 swid = TEGRA_POWERGATE_VDE;
  283         else if (id == TEGRA_POWERGATE_VDE)
  284                 swid = TEGRA_POWERGATE_PCX;
  285         else
  286                 swid = id;
  287         WR4(sc, PMC_REMOVE_CLAMPING_CMD, PMC_REMOVE_CLAMPING_CMD_PARTID(swid));
  288 
  289         for (i = 100; i > 0; i--) {
  290                 reg = RD4(sc, PMC_REMOVE_CLAMPING_CMD);
  291                 if ((reg & PMC_REMOVE_CLAMPING_CMD_PARTID(swid)) == 0)
  292                         break;
  293                 DELAY(1);
  294         }
  295         if (i <= 0)
  296                 device_printf(sc->dev, "Timeout when remove clamping\n");
  297 
  298         reg = RD4(sc, PMC_CLAMP_STATUS);
  299         if ((reg & PMC_CLAMP_STATUS_PARTID(id)) != 0)
  300                 panic("Cannot remove clamping\n");
  301 
  302         return (0);
  303 }
  304 
  305 int
  306 tegra_powergate_is_powered(enum tegra_powergate_id id)
  307 {
  308         struct tegra210_pmc_softc *sc;
  309         uint32_t reg;
  310 
  311         sc = tegra210_pmc_get_sc();
  312 
  313         reg = RD4(sc, PMC_PWRGATE_STATUS);
  314         return ((reg & PMC_PWRGATE_STATUS_PARTID(id)) ? 1 : 0);
  315 }
  316 
  317 int
  318 tegra_powergate_power_on(enum tegra_powergate_id id)
  319 {
  320         struct tegra210_pmc_softc *sc;
  321         int rv, i;
  322 
  323         sc = tegra210_pmc_get_sc();
  324 
  325         rv = tegra210_pmc_set_powergate(sc, id, 1);
  326         if (rv != 0) {
  327                 device_printf(sc->dev, "Cannot set powergate: %d\n", id);
  328                 return (rv);
  329         }
  330 
  331         for (i = 100; i > 0; i--) {
  332                 if (tegra_powergate_is_powered(id))
  333                         break;
  334                 DELAY(1);
  335         }
  336         if (i <= 0) {
  337                 device_printf(sc->dev, "Timeout when waiting on power up\n");
  338                 return(ETIMEDOUT);
  339         }
  340 
  341         return (rv);
  342 }
  343 
  344 int
  345 tegra_powergate_power_off(enum tegra_powergate_id id)
  346 {
  347         struct tegra210_pmc_softc *sc;
  348         int rv, i;
  349 
  350         sc = tegra210_pmc_get_sc();
  351 
  352         rv = tegra210_pmc_set_powergate(sc, id, 0);
  353         if (rv != 0) {
  354                 device_printf(sc->dev, "Cannot set powergate: %d\n", id);
  355                 return (rv);
  356         }
  357         for (i = 100; i > 0; i--) {
  358                 if (!tegra_powergate_is_powered(id))
  359                         break;
  360                 DELAY(1);
  361         }
  362         if (i <= 0)
  363                 device_printf(sc->dev, "Timeout when waiting on power off\n");
  364 
  365         return (rv);
  366 }
  367 
  368 int
  369 tegra_powergate_sequence_power_up(enum tegra_powergate_id id, clk_t clk,
  370     hwreset_t rst)
  371 {
  372         struct tegra210_pmc_softc *sc;
  373         int rv;
  374 
  375         sc = tegra210_pmc_get_sc();
  376 
  377         rv = hwreset_assert(rst);
  378         if (rv != 0) {
  379                 device_printf(sc->dev, "Cannot assert reset\n");
  380                 return (rv);
  381         }
  382 
  383         rv = clk_stop(clk);
  384         if (rv != 0) {
  385                 device_printf(sc->dev, "Cannot stop clock\n");
  386                 goto clk_fail;
  387         }
  388 
  389         rv = tegra_powergate_power_on(id);
  390         if (rv != 0) {
  391                 device_printf(sc->dev, "Cannot power on powergate\n");
  392                 goto clk_fail;
  393         }
  394 
  395         rv = clk_enable(clk);
  396         if (rv != 0) {
  397                 device_printf(sc->dev, "Cannot enable clock\n");
  398                 goto clk_fail;
  399         }
  400         DELAY(20);
  401 
  402         rv = tegra_powergate_remove_clamping(id);
  403         if (rv != 0) {
  404                 device_printf(sc->dev, "Cannot remove clamping\n");
  405                 goto fail;
  406         }
  407         rv = hwreset_deassert(rst);
  408         if (rv != 0) {
  409                 device_printf(sc->dev, "Cannot unreset reset\n");
  410                 goto fail;
  411         }
  412         return 0;
  413 
  414 fail:
  415         clk_disable(clk);
  416 clk_fail:
  417         hwreset_assert(rst);
  418         tegra_powergate_power_off(id);
  419         return (rv);
  420 }
  421 
  422 static int
  423 tegra210_pmc_parse_fdt(struct tegra210_pmc_softc *sc, phandle_t node)
  424 {
  425         int rv;
  426         uint32_t tmp;
  427         uint32_t tmparr[2];
  428 
  429         rv = OF_getencprop(node, "nvidia,suspend-mode", &tmp, sizeof(tmp));
  430         if (rv > 0) {
  431                 switch (tmp) {
  432                 case 0:
  433                         sc->suspend_mode = TEGRA_SUSPEND_LP0;
  434                         break;
  435 
  436                 case 1:
  437                         sc->suspend_mode = TEGRA_SUSPEND_LP1;
  438                         break;
  439 
  440                 case 2:
  441                         sc->suspend_mode = TEGRA_SUSPEND_LP2;
  442                         break;
  443 
  444                 default:
  445                         sc->suspend_mode = TEGRA_SUSPEND_NONE;
  446                         break;
  447                 }
  448         }
  449 
  450         rv = OF_getencprop(node, "nvidia,cpu-pwr-good-time", &tmp, sizeof(tmp));
  451         if (rv > 0) {
  452                 sc->cpu_good_time = tmp;
  453                 sc->suspend_mode = TEGRA_SUSPEND_NONE;
  454         }
  455 
  456         rv = OF_getencprop(node, "nvidia,cpu-pwr-off-time", &tmp, sizeof(tmp));
  457         if (rv > 0) {
  458                 sc->cpu_off_time = tmp;
  459                 sc->suspend_mode = TEGRA_SUSPEND_NONE;
  460         }
  461 
  462         rv = OF_getencprop(node, "nvidia,core-pwr-good-time", tmparr,
  463             sizeof(tmparr));
  464         if (rv == sizeof(tmparr)) {
  465                 sc->core_osc_time = tmparr[0];
  466                 sc->core_pmu_time = tmparr[1];
  467                 sc->suspend_mode = TEGRA_SUSPEND_NONE;
  468         }
  469 
  470         rv = OF_getencprop(node, "nvidia,core-pwr-off-time", &tmp, sizeof(tmp));
  471         if (rv > 0) {
  472                 sc->core_off_time = tmp;
  473                 sc->suspend_mode = TEGRA_SUSPEND_NONE;
  474         }
  475 
  476         sc->corereq_high =
  477             OF_hasprop(node, "nvidia,core-power-req-active-high");
  478         sc->sysclkreq_high =
  479             OF_hasprop(node, "nvidia,sys-clock-req-active-high");
  480         sc->combined_req =
  481             OF_hasprop(node, "nvidia,combined-power-req");
  482         sc->cpu_pwr_good_en =
  483             OF_hasprop(node, "nvidia,cpu-pwr-good-en");
  484 
  485         rv = OF_getencprop(node, "nvidia,lp0-vec", tmparr, sizeof(tmparr));
  486         if (rv == sizeof(tmparr)) {
  487 
  488                 sc->lp0_vec_phys = tmparr[0];
  489                 sc->core_pmu_time = tmparr[1];
  490                 sc->lp0_vec_size = TEGRA_SUSPEND_NONE;
  491                 if (sc->suspend_mode == TEGRA_SUSPEND_LP0)
  492                         sc->suspend_mode = TEGRA_SUSPEND_LP1;
  493         }
  494         return 0;
  495 }
  496 
  497 static void
  498 tegra210_pmc_check_secure(struct tegra210_pmc_softc *sc)
  499 {
  500         uint32_t orig;
  501 
  502         sc->secure_access = false;
  503 
  504         /*
  505          * If PMC is coverd by secure trust zone, all reads returns 0,
  506          * Use scratch0 register acvcess test
  507          */
  508         orig = RD4(sc, PMC_SCRATCH0);
  509         WR4(sc, PMC_SCRATCH0, 0xDEADBEEF);
  510         if (RD4(sc, PMC_SCRATCH0) == 0) {
  511                 sc->secure_access = true;
  512                 return;
  513         }
  514         WR4(sc, PMC_SCRATCH0, 0xBADC0DE);
  515         if (RD4(sc, PMC_SCRATCH0) == 0) {
  516                 sc->secure_access = true;
  517                 return;
  518         }
  519         WR4(sc, PMC_SCRATCH0, orig);
  520 }
  521 
  522 static int
  523 tegra210_pmc_probe(device_t dev)
  524 {
  525 
  526         if (!ofw_bus_status_okay(dev))
  527                 return (ENXIO);
  528 
  529         if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
  530                 return (ENXIO);
  531 
  532         device_set_desc(dev, "Tegra PMC");
  533         return (BUS_PROBE_DEFAULT);
  534 }
  535 
  536 static int
  537 tegra210_pmc_detach(device_t dev)
  538 {
  539 
  540         /* This device is always present. */
  541         return (EBUSY);
  542 }
  543 
  544 static int
  545 tegra210_pmc_attach(device_t dev)
  546 {
  547         struct tegra210_pmc_softc *sc;
  548         int rid, rv;
  549         uint32_t reg;
  550         phandle_t node;
  551 
  552         sc = device_get_softc(dev);
  553         sc->dev = dev;
  554         node = ofw_bus_get_node(dev);
  555         PMC_LOCK_INIT(sc);
  556 
  557         rv = tegra210_pmc_parse_fdt(sc, node);
  558         if (rv != 0) {
  559                 device_printf(sc->dev, "Cannot parse FDT data\n");
  560                 return (rv);
  561         }
  562 
  563         rv = clk_get_by_ofw_name(sc->dev, 0, "pclk", &sc->clk);
  564         if (rv != 0) {
  565                 device_printf(sc->dev, "Cannot get \"pclk\" clock\n");
  566                 return (ENXIO);
  567         }
  568 
  569         rid = 0;
  570         sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  571             RF_ACTIVE);
  572         if (sc->mem_res == NULL) {
  573                 device_printf(dev, "Cannot allocate memory resources\n");
  574                 return (ENXIO);
  575         }
  576 
  577         tegra210_pmc_check_secure(sc);
  578 
  579         /* Enable CPU power request. */
  580         reg = RD4(sc, PMC_CNTRL);
  581         reg |= PMC_CNTRL_CPU_PWRREQ_OE;
  582         WR4(sc, PMC_CNTRL, reg);
  583 
  584         /* Set sysclk output polarity */
  585         reg = RD4(sc, PMC_CNTRL);
  586         if (sc->sysclkreq_high)
  587                 reg &= ~PMC_CNTRL_SYSCLK_POLARITY;
  588         else
  589                 reg |= PMC_CNTRL_SYSCLK_POLARITY;
  590         WR4(sc, PMC_CNTRL, reg);
  591 
  592         /* Enable sysclk request. */
  593         reg = RD4(sc, PMC_CNTRL);
  594         reg |= PMC_CNTRL_SYSCLK_OE;
  595         WR4(sc, PMC_CNTRL, reg);
  596 
  597         /*
  598          * Remove HDMI from deep power down mode.
  599          * XXX mote this to HDMI driver
  600          */
  601         reg = RD4(sc, PMC_IO_DPD_STATUS);
  602         reg &= ~ PMC_IO_DPD_STATUS_HDMI;
  603         WR4(sc, PMC_IO_DPD_STATUS, reg);
  604 
  605         reg = RD4(sc, PMC_IO_DPD2_STATUS);
  606         reg &= ~ PMC_IO_DPD2_STATUS_HV;
  607         WR4(sc, PMC_IO_DPD2_STATUS, reg);
  608 
  609         if (pmc_sc != NULL)
  610                 panic("tegra210_pmc: double driver attach");
  611         pmc_sc = sc;
  612         return (0);
  613 }
  614 
  615 static device_method_t tegra210_pmc_methods[] = {
  616         /* Device interface */
  617         DEVMETHOD(device_probe,         tegra210_pmc_probe),
  618         DEVMETHOD(device_attach,        tegra210_pmc_attach),
  619         DEVMETHOD(device_detach,        tegra210_pmc_detach),
  620 
  621         DEVMETHOD_END
  622 };
  623 
  624 static DEFINE_CLASS_0(pmc, tegra210_pmc_driver, tegra210_pmc_methods,
  625     sizeof(struct tegra210_pmc_softc));
  626 EARLY_DRIVER_MODULE(tegra210_pmc, simplebus, tegra210_pmc_driver, NULL, NULL,
  627     70);

Cache object: e1d60d5a1c51509abd02726f200a1c5a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.