uboot/drivers/clk/imx/clk-imx8qm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright 2018 NXP
   4 * Peng Fan <peng.fan@nxp.com>
   5 */
   6
   7#include <common.h>
   8#include <clk-uclass.h>
   9#include <dm.h>
  10#include <log.h>
  11#include <asm/arch/sci/sci.h>
  12#include <asm/arch/clock.h>
  13#include <dt-bindings/clock/imx8qm-clock.h>
  14#include <dt-bindings/soc/imx_rsrc.h>
  15#include <misc.h>
  16
  17#include "clk-imx8.h"
  18
  19#if CONFIG_IS_ENABLED(CMD_CLK)
  20struct imx8_clks imx8_clk_names[] = {
  21        { IMX8QM_A53_DIV, "A53_DIV" },
  22        { IMX8QM_UART0_CLK, "UART0" },
  23        { IMX8QM_UART1_CLK, "UART1" },
  24        { IMX8QM_UART2_CLK, "UART2" },
  25        { IMX8QM_UART3_CLK, "UART3" },
  26        { IMX8QM_SDHC0_CLK, "SDHC0" },
  27        { IMX8QM_SDHC1_CLK, "SDHC1" },
  28        { IMX8QM_SDHC2_CLK, "SDHC2" },
  29        { IMX8QM_ENET0_AHB_CLK, "ENET0_AHB" },
  30        { IMX8QM_ENET0_IPG_CLK, "ENET0_IPG" },
  31        { IMX8QM_ENET0_REF_DIV, "ENET0_REF" },
  32        { IMX8QM_ENET0_PTP_CLK, "ENET0_PTP" },
  33        { IMX8QM_ENET1_AHB_CLK, "ENET1_AHB" },
  34        { IMX8QM_ENET1_IPG_CLK, "ENET1_IPG" },
  35        { IMX8QM_ENET1_REF_DIV, "ENET1_REF" },
  36        { IMX8QM_ENET1_PTP_CLK, "ENET1_PTP" },
  37};
  38
  39int num_clks = ARRAY_SIZE(imx8_clk_names);
  40#endif
  41
  42ulong imx8_clk_get_rate(struct clk *clk)
  43{
  44        sc_pm_clk_t pm_clk;
  45        ulong rate;
  46        u16 resource;
  47        int ret;
  48
  49        debug("%s(#%lu)\n", __func__, clk->id);
  50
  51        switch (clk->id) {
  52        case IMX8QM_A53_DIV:
  53                resource = SC_R_A53;
  54                pm_clk = SC_PM_CLK_CPU;
  55                break;
  56        case IMX8QM_I2C0_IPG_CLK:
  57        case IMX8QM_I2C0_CLK:
  58        case IMX8QM_I2C0_DIV:
  59                resource = SC_R_I2C_0;
  60                pm_clk = SC_PM_CLK_PER;
  61                break;
  62        case IMX8QM_I2C1_IPG_CLK:
  63        case IMX8QM_I2C1_CLK:
  64        case IMX8QM_I2C1_DIV:
  65                resource = SC_R_I2C_1;
  66                pm_clk = SC_PM_CLK_PER;
  67                break;
  68        case IMX8QM_I2C2_IPG_CLK:
  69        case IMX8QM_I2C2_CLK:
  70        case IMX8QM_I2C2_DIV:
  71                resource = SC_R_I2C_2;
  72                pm_clk = SC_PM_CLK_PER;
  73                break;
  74        case IMX8QM_I2C3_IPG_CLK:
  75        case IMX8QM_I2C3_CLK:
  76        case IMX8QM_I2C3_DIV:
  77                resource = SC_R_I2C_3;
  78                pm_clk = SC_PM_CLK_PER;
  79                break;
  80        case IMX8QM_SDHC0_IPG_CLK:
  81        case IMX8QM_SDHC0_CLK:
  82        case IMX8QM_SDHC0_DIV:
  83                resource = SC_R_SDHC_0;
  84                pm_clk = SC_PM_CLK_PER;
  85                break;
  86        case IMX8QM_SDHC1_IPG_CLK:
  87        case IMX8QM_SDHC1_CLK:
  88        case IMX8QM_SDHC1_DIV:
  89                resource = SC_R_SDHC_1;
  90                pm_clk = SC_PM_CLK_PER;
  91                break;
  92        case IMX8QM_SDHC2_IPG_CLK:
  93        case IMX8QM_SDHC2_CLK:
  94        case IMX8QM_SDHC2_DIV:
  95                resource = SC_R_SDHC_2;
  96                pm_clk = SC_PM_CLK_PER;
  97                break;
  98        case IMX8QM_UART0_IPG_CLK:
  99        case IMX8QM_UART0_CLK:
 100                resource = SC_R_UART_0;
 101                pm_clk = SC_PM_CLK_PER;
 102                break;
 103        case IMX8QM_UART1_CLK:
 104                resource = SC_R_UART_1;
 105                pm_clk = SC_PM_CLK_PER;
 106                break;
 107        case IMX8QM_UART2_CLK:
 108                resource = SC_R_UART_2;
 109                pm_clk = SC_PM_CLK_PER;
 110                break;
 111        case IMX8QM_UART3_CLK:
 112                resource = SC_R_UART_3;
 113                pm_clk = SC_PM_CLK_PER;
 114                break;
 115        case IMX8QM_ENET0_IPG_CLK:
 116        case IMX8QM_ENET0_AHB_CLK:
 117        case IMX8QM_ENET0_REF_DIV:
 118        case IMX8QM_ENET0_PTP_CLK:
 119                resource = SC_R_ENET_0;
 120                pm_clk = SC_PM_CLK_PER;
 121                break;
 122        case IMX8QM_ENET1_IPG_CLK:
 123        case IMX8QM_ENET1_AHB_CLK:
 124        case IMX8QM_ENET1_REF_DIV:
 125        case IMX8QM_ENET1_PTP_CLK:
 126                resource = SC_R_ENET_1;
 127                pm_clk = SC_PM_CLK_PER;
 128                break;
 129        default:
 130                if (clk->id < IMX8QM_UART0_IPG_CLK ||
 131                    clk->id >= IMX8QM_CLK_END) {
 132                        printf("%s(Invalid clk ID #%lu)\n",
 133                               __func__, clk->id);
 134                        return -EINVAL;
 135                }
 136                return -EINVAL;
 137        };
 138
 139        ret = sc_pm_get_clock_rate(-1, resource, pm_clk,
 140                                   (sc_pm_clock_rate_t *)&rate);
 141        if (ret) {
 142                printf("%s err %d\n", __func__, ret);
 143                return ret;
 144        }
 145
 146        return rate;
 147}
 148
 149ulong imx8_clk_set_rate(struct clk *clk, unsigned long rate)
 150{
 151        sc_pm_clk_t pm_clk;
 152        u32 new_rate = rate;
 153        u16 resource;
 154        int ret;
 155
 156        debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate);
 157
 158        switch (clk->id) {
 159        case IMX8QM_I2C0_IPG_CLK:
 160        case IMX8QM_I2C0_CLK:
 161        case IMX8QM_I2C0_DIV:
 162                resource = SC_R_I2C_0;
 163                pm_clk = SC_PM_CLK_PER;
 164                break;
 165        case IMX8QM_I2C1_IPG_CLK:
 166        case IMX8QM_I2C1_CLK:
 167        case IMX8QM_I2C1_DIV:
 168                resource = SC_R_I2C_1;
 169                pm_clk = SC_PM_CLK_PER;
 170                break;
 171        case IMX8QM_I2C2_IPG_CLK:
 172        case IMX8QM_I2C2_CLK:
 173        case IMX8QM_I2C2_DIV:
 174                resource = SC_R_I2C_2;
 175                pm_clk = SC_PM_CLK_PER;
 176                break;
 177        case IMX8QM_I2C3_IPG_CLK:
 178        case IMX8QM_I2C3_CLK:
 179        case IMX8QM_I2C3_DIV:
 180                resource = SC_R_I2C_3;
 181                pm_clk = SC_PM_CLK_PER;
 182                break;
 183        case IMX8QM_UART0_CLK:
 184                resource = SC_R_UART_0;
 185                pm_clk = SC_PM_CLK_PER;
 186                break;
 187        case IMX8QM_UART1_CLK:
 188                resource = SC_R_UART_1;
 189                pm_clk = SC_PM_CLK_PER;
 190                break;
 191        case IMX8QM_UART2_CLK:
 192                resource = SC_R_UART_2;
 193                pm_clk = SC_PM_CLK_PER;
 194                break;
 195        case IMX8QM_UART3_CLK:
 196                resource = SC_R_UART_3;
 197                pm_clk = SC_PM_CLK_PER;
 198                break;
 199        case IMX8QM_SDHC0_IPG_CLK:
 200        case IMX8QM_SDHC0_CLK:
 201        case IMX8QM_SDHC0_DIV:
 202                resource = SC_R_SDHC_0;
 203                pm_clk = SC_PM_CLK_PER;
 204                break;
 205        case IMX8QM_SDHC1_IPG_CLK:
 206        case IMX8QM_SDHC1_CLK:
 207        case IMX8QM_SDHC1_DIV:
 208                resource = SC_R_SDHC_1;
 209                pm_clk = SC_PM_CLK_PER;
 210                break;
 211        case IMX8QM_SDHC2_IPG_CLK:
 212        case IMX8QM_SDHC2_CLK:
 213        case IMX8QM_SDHC2_DIV:
 214                resource = SC_R_SDHC_2;
 215                pm_clk = SC_PM_CLK_PER;
 216                break;
 217        case IMX8QM_ENET0_IPG_CLK:
 218        case IMX8QM_ENET0_AHB_CLK:
 219        case IMX8QM_ENET0_REF_DIV:
 220        case IMX8QM_ENET0_PTP_CLK:
 221        case IMX8QM_ENET0_ROOT_DIV:
 222                resource = SC_R_ENET_0;
 223                pm_clk = SC_PM_CLK_PER;
 224                break;
 225        case IMX8QM_ENET1_IPG_CLK:
 226        case IMX8QM_ENET1_AHB_CLK:
 227        case IMX8QM_ENET1_REF_DIV:
 228        case IMX8QM_ENET1_PTP_CLK:
 229        case IMX8QM_ENET1_ROOT_DIV:
 230                resource = SC_R_ENET_1;
 231                pm_clk = SC_PM_CLK_PER;
 232                break;
 233        default:
 234                if (clk->id < IMX8QM_UART0_IPG_CLK ||
 235                    clk->id >= IMX8QM_CLK_END) {
 236                        printf("%s(Invalid clk ID #%lu)\n",
 237                               __func__, clk->id);
 238                        return -EINVAL;
 239                }
 240                return -EINVAL;
 241        };
 242
 243        ret = sc_pm_set_clock_rate(-1, resource, pm_clk, &new_rate);
 244        if (ret) {
 245                printf("%s err %d\n", __func__, ret);
 246                return ret;
 247        }
 248
 249        return new_rate;
 250}
 251
 252int __imx8_clk_enable(struct clk *clk, bool enable)
 253{
 254        sc_pm_clk_t pm_clk;
 255        u16 resource;
 256        int ret;
 257
 258        debug("%s(#%lu)\n", __func__, clk->id);
 259
 260        switch (clk->id) {
 261        case IMX8QM_I2C0_IPG_CLK:
 262        case IMX8QM_I2C0_CLK:
 263        case IMX8QM_I2C0_DIV:
 264                resource = SC_R_I2C_0;
 265                pm_clk = SC_PM_CLK_PER;
 266                break;
 267        case IMX8QM_I2C1_IPG_CLK:
 268        case IMX8QM_I2C1_CLK:
 269        case IMX8QM_I2C1_DIV:
 270                resource = SC_R_I2C_1;
 271                pm_clk = SC_PM_CLK_PER;
 272                break;
 273        case IMX8QM_I2C2_IPG_CLK:
 274        case IMX8QM_I2C2_CLK:
 275        case IMX8QM_I2C2_DIV:
 276                resource = SC_R_I2C_2;
 277                pm_clk = SC_PM_CLK_PER;
 278                break;
 279        case IMX8QM_I2C3_IPG_CLK:
 280        case IMX8QM_I2C3_CLK:
 281        case IMX8QM_I2C3_DIV:
 282                resource = SC_R_I2C_3;
 283                pm_clk = SC_PM_CLK_PER;
 284                break;
 285        case IMX8QM_UART0_CLK:
 286                resource = SC_R_UART_0;
 287                pm_clk = SC_PM_CLK_PER;
 288                break;
 289        case IMX8QM_UART1_CLK:
 290                resource = SC_R_UART_1;
 291                pm_clk = SC_PM_CLK_PER;
 292                break;
 293        case IMX8QM_UART2_CLK:
 294                resource = SC_R_UART_2;
 295                pm_clk = SC_PM_CLK_PER;
 296                break;
 297        case IMX8QM_UART3_CLK:
 298                resource = SC_R_UART_3;
 299                pm_clk = SC_PM_CLK_PER;
 300                break;
 301        case IMX8QM_SDHC0_IPG_CLK:
 302        case IMX8QM_SDHC0_CLK:
 303        case IMX8QM_SDHC0_DIV:
 304                resource = SC_R_SDHC_0;
 305                pm_clk = SC_PM_CLK_PER;
 306                break;
 307        case IMX8QM_SDHC1_IPG_CLK:
 308        case IMX8QM_SDHC1_CLK:
 309        case IMX8QM_SDHC1_DIV:
 310                resource = SC_R_SDHC_1;
 311                pm_clk = SC_PM_CLK_PER;
 312                break;
 313        case IMX8QM_SDHC2_IPG_CLK:
 314        case IMX8QM_SDHC2_CLK:
 315        case IMX8QM_SDHC2_DIV:
 316                resource = SC_R_SDHC_2;
 317                pm_clk = SC_PM_CLK_PER;
 318                break;
 319        case IMX8QM_ENET0_IPG_CLK:
 320        case IMX8QM_ENET0_AHB_CLK:
 321        case IMX8QM_ENET0_REF_DIV:
 322        case IMX8QM_ENET0_PTP_CLK:
 323                resource = SC_R_ENET_0;
 324                pm_clk = SC_PM_CLK_PER;
 325                break;
 326        case IMX8QM_ENET1_IPG_CLK:
 327        case IMX8QM_ENET1_AHB_CLK:
 328        case IMX8QM_ENET1_REF_DIV:
 329        case IMX8QM_ENET1_PTP_CLK:
 330                resource = SC_R_ENET_1;
 331                pm_clk = SC_PM_CLK_PER;
 332                break;
 333        default:
 334                if (clk->id < IMX8QM_UART0_IPG_CLK ||
 335                    clk->id >= IMX8QM_CLK_END) {
 336                        printf("%s(Invalid clk ID #%lu)\n",
 337                               __func__, clk->id);
 338                        return -EINVAL;
 339                }
 340                return -EINVAL;
 341        }
 342
 343        ret = sc_pm_clock_enable(-1, resource, pm_clk, enable, 0);
 344        if (ret) {
 345                printf("%s err %d\n", __func__, ret);
 346                return ret;
 347        }
 348
 349        return 0;
 350}
 351