Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * CPU frequency scaling support for Armada 37xx platform.
0004  *
0005  * Copyright (C) 2017 Marvell
0006  *
0007  * Gregory CLEMENT <gregory.clement@free-electrons.com>
0008  */
0009 
0010 #include <linux/clk.h>
0011 #include <linux/cpu.h>
0012 #include <linux/cpufreq.h>
0013 #include <linux/err.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/io.h>
0016 #include <linux/mfd/syscon.h>
0017 #include <linux/module.h>
0018 #include <linux/of_address.h>
0019 #include <linux/of_device.h>
0020 #include <linux/of_irq.h>
0021 #include <linux/platform_device.h>
0022 #include <linux/pm_opp.h>
0023 #include <linux/regmap.h>
0024 #include <linux/slab.h>
0025 
0026 #include "cpufreq-dt.h"
0027 
0028 /* Clk register set */
0029 #define ARMADA_37XX_CLK_TBG_SEL     0
0030 #define ARMADA_37XX_CLK_TBG_SEL_CPU_OFF 22
0031 
0032 /* Power management in North Bridge register set */
0033 #define ARMADA_37XX_NB_L0L1 0x18
0034 #define ARMADA_37XX_NB_L2L3 0x1C
0035 #define  ARMADA_37XX_NB_TBG_DIV_OFF 13
0036 #define  ARMADA_37XX_NB_TBG_DIV_MASK    0x7
0037 #define  ARMADA_37XX_NB_CLK_SEL_OFF 11
0038 #define  ARMADA_37XX_NB_CLK_SEL_MASK    0x1
0039 #define  ARMADA_37XX_NB_CLK_SEL_TBG 0x1
0040 #define  ARMADA_37XX_NB_TBG_SEL_OFF 9
0041 #define  ARMADA_37XX_NB_TBG_SEL_MASK    0x3
0042 #define  ARMADA_37XX_NB_VDD_SEL_OFF 6
0043 #define  ARMADA_37XX_NB_VDD_SEL_MASK    0x3
0044 #define  ARMADA_37XX_NB_CONFIG_SHIFT    16
0045 #define ARMADA_37XX_NB_DYN_MOD  0x24
0046 #define  ARMADA_37XX_NB_CLK_SEL_EN  BIT(26)
0047 #define  ARMADA_37XX_NB_TBG_EN      BIT(28)
0048 #define  ARMADA_37XX_NB_DIV_EN      BIT(29)
0049 #define  ARMADA_37XX_NB_VDD_EN      BIT(30)
0050 #define  ARMADA_37XX_NB_DFS_EN      BIT(31)
0051 #define ARMADA_37XX_NB_CPU_LOAD 0x30
0052 #define  ARMADA_37XX_NB_CPU_LOAD_MASK   0x3
0053 #define  ARMADA_37XX_DVFS_LOAD_0    0
0054 #define  ARMADA_37XX_DVFS_LOAD_1    1
0055 #define  ARMADA_37XX_DVFS_LOAD_2    2
0056 #define  ARMADA_37XX_DVFS_LOAD_3    3
0057 
0058 /* AVS register set */
0059 #define ARMADA_37XX_AVS_CTL0        0x0
0060 #define  ARMADA_37XX_AVS_ENABLE     BIT(30)
0061 #define  ARMADA_37XX_AVS_HIGH_VDD_LIMIT 16
0062 #define  ARMADA_37XX_AVS_LOW_VDD_LIMIT  22
0063 #define  ARMADA_37XX_AVS_VDD_MASK   0x3F
0064 #define ARMADA_37XX_AVS_CTL2        0x8
0065 #define  ARMADA_37XX_AVS_LOW_VDD_EN BIT(6)
0066 #define ARMADA_37XX_AVS_VSET(x)     (0x1C + 4 * (x))
0067 
0068 /*
0069  * On Armada 37xx the Power management manages 4 level of CPU load,
0070  * each level can be associated with a CPU clock source, a CPU
0071  * divider, a VDD level, etc...
0072  */
0073 #define LOAD_LEVEL_NR   4
0074 
0075 #define MIN_VOLT_MV 1000
0076 #define MIN_VOLT_MV_FOR_L1_1000MHZ 1108
0077 #define MIN_VOLT_MV_FOR_L1_1200MHZ 1155
0078 
0079 /*  AVS value for the corresponding voltage (in mV) */
0080 static int avs_map[] = {
0081     747, 758, 770, 782, 793, 805, 817, 828, 840, 852, 863, 875, 887, 898,
0082     910, 922, 933, 945, 957, 968, 980, 992, 1003, 1015, 1027, 1038, 1050,
0083     1062, 1073, 1085, 1097, 1108, 1120, 1132, 1143, 1155, 1167, 1178, 1190,
0084     1202, 1213, 1225, 1237, 1248, 1260, 1272, 1283, 1295, 1307, 1318, 1330,
0085     1342
0086 };
0087 
0088 struct armada37xx_cpufreq_state {
0089     struct platform_device *pdev;
0090     struct device *cpu_dev;
0091     struct regmap *regmap;
0092     u32 nb_l0l1;
0093     u32 nb_l2l3;
0094     u32 nb_dyn_mod;
0095     u32 nb_cpu_load;
0096 };
0097 
0098 static struct armada37xx_cpufreq_state *armada37xx_cpufreq_state;
0099 
0100 struct armada_37xx_dvfs {
0101     u32 cpu_freq_max;
0102     u8 divider[LOAD_LEVEL_NR];
0103     u32 avs[LOAD_LEVEL_NR];
0104 };
0105 
0106 static struct armada_37xx_dvfs armada_37xx_dvfs[] = {
0107     /*
0108      * The cpufreq scaling for 1.2 GHz variant of the SOC is currently
0109      * unstable because we do not know how to configure it properly.
0110      */
0111     /* {.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} }, */
0112     {.cpu_freq_max = 1000*1000*1000, .divider = {1, 2, 4, 5} },
0113     {.cpu_freq_max = 800*1000*1000,  .divider = {1, 2, 3, 4} },
0114     {.cpu_freq_max = 600*1000*1000,  .divider = {2, 4, 5, 6} },
0115 };
0116 
0117 static struct armada_37xx_dvfs *armada_37xx_cpu_freq_info_get(u32 freq)
0118 {
0119     int i;
0120 
0121     for (i = 0; i < ARRAY_SIZE(armada_37xx_dvfs); i++) {
0122         if (freq == armada_37xx_dvfs[i].cpu_freq_max)
0123             return &armada_37xx_dvfs[i];
0124     }
0125 
0126     pr_err("Unsupported CPU frequency %d MHz\n", freq/1000000);
0127     return NULL;
0128 }
0129 
0130 /*
0131  * Setup the four level managed by the hardware. Once the four level
0132  * will be configured then the DVFS will be enabled.
0133  */
0134 static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base,
0135                          struct regmap *clk_base, u8 *divider)
0136 {
0137     u32 cpu_tbg_sel;
0138     int load_lvl;
0139 
0140     /* Determine to which TBG clock is CPU connected */
0141     regmap_read(clk_base, ARMADA_37XX_CLK_TBG_SEL, &cpu_tbg_sel);
0142     cpu_tbg_sel >>= ARMADA_37XX_CLK_TBG_SEL_CPU_OFF;
0143     cpu_tbg_sel &= ARMADA_37XX_NB_TBG_SEL_MASK;
0144 
0145     for (load_lvl = 0; load_lvl < LOAD_LEVEL_NR; load_lvl++) {
0146         unsigned int reg, mask, val, offset = 0;
0147 
0148         if (load_lvl <= ARMADA_37XX_DVFS_LOAD_1)
0149             reg = ARMADA_37XX_NB_L0L1;
0150         else
0151             reg = ARMADA_37XX_NB_L2L3;
0152 
0153         if (load_lvl == ARMADA_37XX_DVFS_LOAD_0 ||
0154             load_lvl == ARMADA_37XX_DVFS_LOAD_2)
0155             offset += ARMADA_37XX_NB_CONFIG_SHIFT;
0156 
0157         /* Set cpu clock source, for all the level we use TBG */
0158         val = ARMADA_37XX_NB_CLK_SEL_TBG << ARMADA_37XX_NB_CLK_SEL_OFF;
0159         mask = (ARMADA_37XX_NB_CLK_SEL_MASK
0160             << ARMADA_37XX_NB_CLK_SEL_OFF);
0161 
0162         /* Set TBG index, for all levels we use the same TBG */
0163         val = cpu_tbg_sel << ARMADA_37XX_NB_TBG_SEL_OFF;
0164         mask = (ARMADA_37XX_NB_TBG_SEL_MASK
0165             << ARMADA_37XX_NB_TBG_SEL_OFF);
0166 
0167         /*
0168          * Set cpu divider based on the pre-computed array in
0169          * order to have balanced step.
0170          */
0171         val |= divider[load_lvl] << ARMADA_37XX_NB_TBG_DIV_OFF;
0172         mask |= (ARMADA_37XX_NB_TBG_DIV_MASK
0173             << ARMADA_37XX_NB_TBG_DIV_OFF);
0174 
0175         /* Set VDD divider which is actually the load level. */
0176         val |= load_lvl << ARMADA_37XX_NB_VDD_SEL_OFF;
0177         mask |= (ARMADA_37XX_NB_VDD_SEL_MASK
0178             << ARMADA_37XX_NB_VDD_SEL_OFF);
0179 
0180         val <<= offset;
0181         mask <<= offset;
0182 
0183         regmap_update_bits(base, reg, mask, val);
0184     }
0185 }
0186 
0187 /*
0188  * Find out the armada 37x supported AVS value whose voltage value is
0189  * the round-up closest to the target voltage value.
0190  */
0191 static u32 armada_37xx_avs_val_match(int target_vm)
0192 {
0193     u32 avs;
0194 
0195     /* Find out the round-up closest supported voltage value */
0196     for (avs = 0; avs < ARRAY_SIZE(avs_map); avs++)
0197         if (avs_map[avs] >= target_vm)
0198             break;
0199 
0200     /*
0201      * If all supported voltages are smaller than target one,
0202      * choose the largest supported voltage
0203      */
0204     if (avs == ARRAY_SIZE(avs_map))
0205         avs = ARRAY_SIZE(avs_map) - 1;
0206 
0207     return avs;
0208 }
0209 
0210 /*
0211  * For Armada 37xx soc, L0(VSET0) VDD AVS value is set to SVC revision
0212  * value or a default value when SVC is not supported.
0213  * - L0 can be read out from the register of AVS_CTRL_0 and L0 voltage
0214  *   can be got from the mapping table of avs_map.
0215  * - L1 voltage should be about 100mv smaller than L0 voltage
0216  * - L2 & L3 voltage should be about 150mv smaller than L0 voltage.
0217  * This function calculates L1 & L2 & L3 AVS values dynamically based
0218  * on L0 voltage and fill all AVS values to the AVS value table.
0219  * When base CPU frequency is 1000 or 1200 MHz then there is additional
0220  * minimal avs value for load L1.
0221  */
0222 static void __init armada37xx_cpufreq_avs_configure(struct regmap *base,
0223                         struct armada_37xx_dvfs *dvfs)
0224 {
0225     unsigned int target_vm;
0226     int load_level = 0;
0227     u32 l0_vdd_min;
0228 
0229     if (base == NULL)
0230         return;
0231 
0232     /* Get L0 VDD min value */
0233     regmap_read(base, ARMADA_37XX_AVS_CTL0, &l0_vdd_min);
0234     l0_vdd_min = (l0_vdd_min >> ARMADA_37XX_AVS_LOW_VDD_LIMIT) &
0235         ARMADA_37XX_AVS_VDD_MASK;
0236     if (l0_vdd_min >= ARRAY_SIZE(avs_map))  {
0237         pr_err("L0 VDD MIN %d is not correct.\n", l0_vdd_min);
0238         return;
0239     }
0240     dvfs->avs[0] = l0_vdd_min;
0241 
0242     if (avs_map[l0_vdd_min] <= MIN_VOLT_MV) {
0243         /*
0244          * If L0 voltage is smaller than 1000mv, then all VDD sets
0245          * use L0 voltage;
0246          */
0247         u32 avs_min = armada_37xx_avs_val_match(MIN_VOLT_MV);
0248 
0249         for (load_level = 1; load_level < LOAD_LEVEL_NR; load_level++)
0250             dvfs->avs[load_level] = avs_min;
0251 
0252         /*
0253          * Set the avs values for load L0 and L1 when base CPU frequency
0254          * is 1000/1200 MHz to its typical initial values according to
0255          * the Armada 3700 Hardware Specifications.
0256          */
0257         if (dvfs->cpu_freq_max >= 1000*1000*1000) {
0258             if (dvfs->cpu_freq_max >= 1200*1000*1000)
0259                 avs_min = armada_37xx_avs_val_match(MIN_VOLT_MV_FOR_L1_1200MHZ);
0260             else
0261                 avs_min = armada_37xx_avs_val_match(MIN_VOLT_MV_FOR_L1_1000MHZ);
0262             dvfs->avs[0] = dvfs->avs[1] = avs_min;
0263         }
0264 
0265         return;
0266     }
0267 
0268     /*
0269      * L1 voltage is equal to L0 voltage - 100mv and it must be
0270      * larger than 1000mv
0271      */
0272 
0273     target_vm = avs_map[l0_vdd_min] - 100;
0274     target_vm = target_vm > MIN_VOLT_MV ? target_vm : MIN_VOLT_MV;
0275     dvfs->avs[1] = armada_37xx_avs_val_match(target_vm);
0276 
0277     /*
0278      * L2 & L3 voltage is equal to L0 voltage - 150mv and it must
0279      * be larger than 1000mv
0280      */
0281     target_vm = avs_map[l0_vdd_min] - 150;
0282     target_vm = target_vm > MIN_VOLT_MV ? target_vm : MIN_VOLT_MV;
0283     dvfs->avs[2] = dvfs->avs[3] = armada_37xx_avs_val_match(target_vm);
0284 
0285     /*
0286      * Fix the avs value for load L1 when base CPU frequency is 1000/1200 MHz,
0287      * otherwise the CPU gets stuck when switching from load L1 to load L0.
0288      * Also ensure that avs value for load L1 is not higher than for L0.
0289      */
0290     if (dvfs->cpu_freq_max >= 1000*1000*1000) {
0291         u32 avs_min_l1;
0292 
0293         if (dvfs->cpu_freq_max >= 1200*1000*1000)
0294             avs_min_l1 = armada_37xx_avs_val_match(MIN_VOLT_MV_FOR_L1_1200MHZ);
0295         else
0296             avs_min_l1 = armada_37xx_avs_val_match(MIN_VOLT_MV_FOR_L1_1000MHZ);
0297 
0298         if (avs_min_l1 > dvfs->avs[0])
0299             avs_min_l1 = dvfs->avs[0];
0300 
0301         if (dvfs->avs[1] < avs_min_l1)
0302             dvfs->avs[1] = avs_min_l1;
0303     }
0304 }
0305 
0306 static void __init armada37xx_cpufreq_avs_setup(struct regmap *base,
0307                         struct armada_37xx_dvfs *dvfs)
0308 {
0309     unsigned int avs_val = 0;
0310     int load_level = 0;
0311 
0312     if (base == NULL)
0313         return;
0314 
0315     /* Disable AVS before the configuration */
0316     regmap_update_bits(base, ARMADA_37XX_AVS_CTL0,
0317                ARMADA_37XX_AVS_ENABLE, 0);
0318 
0319 
0320     /* Enable low voltage mode */
0321     regmap_update_bits(base, ARMADA_37XX_AVS_CTL2,
0322                ARMADA_37XX_AVS_LOW_VDD_EN,
0323                ARMADA_37XX_AVS_LOW_VDD_EN);
0324 
0325 
0326     for (load_level = 1; load_level < LOAD_LEVEL_NR; load_level++) {
0327         avs_val = dvfs->avs[load_level];
0328         regmap_update_bits(base, ARMADA_37XX_AVS_VSET(load_level-1),
0329             ARMADA_37XX_AVS_VDD_MASK << ARMADA_37XX_AVS_HIGH_VDD_LIMIT |
0330             ARMADA_37XX_AVS_VDD_MASK << ARMADA_37XX_AVS_LOW_VDD_LIMIT,
0331             avs_val << ARMADA_37XX_AVS_HIGH_VDD_LIMIT |
0332             avs_val << ARMADA_37XX_AVS_LOW_VDD_LIMIT);
0333     }
0334 
0335     /* Enable AVS after the configuration */
0336     regmap_update_bits(base, ARMADA_37XX_AVS_CTL0,
0337                ARMADA_37XX_AVS_ENABLE,
0338                ARMADA_37XX_AVS_ENABLE);
0339 
0340 }
0341 
0342 static void armada37xx_cpufreq_disable_dvfs(struct regmap *base)
0343 {
0344     unsigned int reg = ARMADA_37XX_NB_DYN_MOD,
0345         mask = ARMADA_37XX_NB_DFS_EN;
0346 
0347     regmap_update_bits(base, reg, mask, 0);
0348 }
0349 
0350 static void __init armada37xx_cpufreq_enable_dvfs(struct regmap *base)
0351 {
0352     unsigned int val, reg = ARMADA_37XX_NB_CPU_LOAD,
0353         mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
0354 
0355     /* Start with the highest load (0) */
0356     val = ARMADA_37XX_DVFS_LOAD_0;
0357     regmap_update_bits(base, reg, mask, val);
0358 
0359     /* Now enable DVFS for the CPUs */
0360     reg = ARMADA_37XX_NB_DYN_MOD;
0361     mask =  ARMADA_37XX_NB_CLK_SEL_EN | ARMADA_37XX_NB_TBG_EN |
0362         ARMADA_37XX_NB_DIV_EN | ARMADA_37XX_NB_VDD_EN |
0363         ARMADA_37XX_NB_DFS_EN;
0364 
0365     regmap_update_bits(base, reg, mask, mask);
0366 }
0367 
0368 static int armada37xx_cpufreq_suspend(struct cpufreq_policy *policy)
0369 {
0370     struct armada37xx_cpufreq_state *state = armada37xx_cpufreq_state;
0371 
0372     regmap_read(state->regmap, ARMADA_37XX_NB_L0L1, &state->nb_l0l1);
0373     regmap_read(state->regmap, ARMADA_37XX_NB_L2L3, &state->nb_l2l3);
0374     regmap_read(state->regmap, ARMADA_37XX_NB_CPU_LOAD,
0375             &state->nb_cpu_load);
0376     regmap_read(state->regmap, ARMADA_37XX_NB_DYN_MOD, &state->nb_dyn_mod);
0377 
0378     return 0;
0379 }
0380 
0381 static int armada37xx_cpufreq_resume(struct cpufreq_policy *policy)
0382 {
0383     struct armada37xx_cpufreq_state *state = armada37xx_cpufreq_state;
0384 
0385     /* Ensure DVFS is disabled otherwise the following registers are RO */
0386     armada37xx_cpufreq_disable_dvfs(state->regmap);
0387 
0388     regmap_write(state->regmap, ARMADA_37XX_NB_L0L1, state->nb_l0l1);
0389     regmap_write(state->regmap, ARMADA_37XX_NB_L2L3, state->nb_l2l3);
0390     regmap_write(state->regmap, ARMADA_37XX_NB_CPU_LOAD,
0391              state->nb_cpu_load);
0392 
0393     /*
0394      * NB_DYN_MOD register is the one that actually enable back DVFS if it
0395      * was enabled before the suspend operation. This must be done last
0396      * otherwise other registers are not writable.
0397      */
0398     regmap_write(state->regmap, ARMADA_37XX_NB_DYN_MOD, state->nb_dyn_mod);
0399 
0400     return 0;
0401 }
0402 
0403 static int __init armada37xx_cpufreq_driver_init(void)
0404 {
0405     struct cpufreq_dt_platform_data pdata;
0406     struct armada_37xx_dvfs *dvfs;
0407     struct platform_device *pdev;
0408     unsigned long freq;
0409     unsigned int base_frequency;
0410     struct regmap *nb_clk_base, *nb_pm_base, *avs_base;
0411     struct device *cpu_dev;
0412     int load_lvl, ret;
0413     struct clk *clk, *parent;
0414 
0415     nb_clk_base =
0416         syscon_regmap_lookup_by_compatible("marvell,armada-3700-periph-clock-nb");
0417     if (IS_ERR(nb_clk_base))
0418         return -ENODEV;
0419 
0420     nb_pm_base =
0421         syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm");
0422 
0423     if (IS_ERR(nb_pm_base))
0424         return -ENODEV;
0425 
0426     avs_base =
0427         syscon_regmap_lookup_by_compatible("marvell,armada-3700-avs");
0428 
0429     /* if AVS is not present don't use it but still try to setup dvfs */
0430     if (IS_ERR(avs_base)) {
0431         pr_info("Syscon failed for Adapting Voltage Scaling: skip it\n");
0432         avs_base = NULL;
0433     }
0434     /* Before doing any configuration on the DVFS first, disable it */
0435     armada37xx_cpufreq_disable_dvfs(nb_pm_base);
0436 
0437     /*
0438      * On CPU 0 register the operating points supported (which are
0439      * the nominal CPU frequency and full integer divisions of
0440      * it).
0441      */
0442     cpu_dev = get_cpu_device(0);
0443     if (!cpu_dev) {
0444         dev_err(cpu_dev, "Cannot get CPU\n");
0445         return -ENODEV;
0446     }
0447 
0448     clk = clk_get(cpu_dev, 0);
0449     if (IS_ERR(clk)) {
0450         dev_err(cpu_dev, "Cannot get clock for CPU0\n");
0451         return PTR_ERR(clk);
0452     }
0453 
0454     parent = clk_get_parent(clk);
0455     if (IS_ERR(parent)) {
0456         dev_err(cpu_dev, "Cannot get parent clock for CPU0\n");
0457         clk_put(clk);
0458         return PTR_ERR(parent);
0459     }
0460 
0461     /* Get parent CPU frequency */
0462     base_frequency =  clk_get_rate(parent);
0463 
0464     if (!base_frequency) {
0465         dev_err(cpu_dev, "Failed to get parent clock rate for CPU\n");
0466         clk_put(clk);
0467         return -EINVAL;
0468     }
0469 
0470     dvfs = armada_37xx_cpu_freq_info_get(base_frequency);
0471     if (!dvfs) {
0472         clk_put(clk);
0473         return -EINVAL;
0474     }
0475 
0476     armada37xx_cpufreq_state = kmalloc(sizeof(*armada37xx_cpufreq_state),
0477                        GFP_KERNEL);
0478     if (!armada37xx_cpufreq_state) {
0479         clk_put(clk);
0480         return -ENOMEM;
0481     }
0482 
0483     armada37xx_cpufreq_state->regmap = nb_pm_base;
0484 
0485     armada37xx_cpufreq_avs_configure(avs_base, dvfs);
0486     armada37xx_cpufreq_avs_setup(avs_base, dvfs);
0487 
0488     armada37xx_cpufreq_dvfs_setup(nb_pm_base, nb_clk_base, dvfs->divider);
0489     clk_put(clk);
0490 
0491     for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR;
0492          load_lvl++) {
0493         unsigned long u_volt = avs_map[dvfs->avs[load_lvl]] * 1000;
0494         freq = base_frequency / dvfs->divider[load_lvl];
0495         ret = dev_pm_opp_add(cpu_dev, freq, u_volt);
0496         if (ret)
0497             goto remove_opp;
0498 
0499 
0500     }
0501 
0502     /* Now that everything is setup, enable the DVFS at hardware level */
0503     armada37xx_cpufreq_enable_dvfs(nb_pm_base);
0504 
0505     memset(&pdata, 0, sizeof(pdata));
0506     pdata.suspend = armada37xx_cpufreq_suspend;
0507     pdata.resume = armada37xx_cpufreq_resume;
0508 
0509     pdev = platform_device_register_data(NULL, "cpufreq-dt", -1, &pdata,
0510                          sizeof(pdata));
0511     ret = PTR_ERR_OR_ZERO(pdev);
0512     if (ret)
0513         goto disable_dvfs;
0514 
0515     armada37xx_cpufreq_state->cpu_dev = cpu_dev;
0516     armada37xx_cpufreq_state->pdev = pdev;
0517     platform_set_drvdata(pdev, dvfs);
0518     return 0;
0519 
0520 disable_dvfs:
0521     armada37xx_cpufreq_disable_dvfs(nb_pm_base);
0522 remove_opp:
0523     /* clean-up the already added opp before leaving */
0524     while (load_lvl-- > ARMADA_37XX_DVFS_LOAD_0) {
0525         freq = base_frequency / dvfs->divider[load_lvl];
0526         dev_pm_opp_remove(cpu_dev, freq);
0527     }
0528 
0529     kfree(armada37xx_cpufreq_state);
0530 
0531     return ret;
0532 }
0533 /* late_initcall, to guarantee the driver is loaded after A37xx clock driver */
0534 late_initcall(armada37xx_cpufreq_driver_init);
0535 
0536 static void __exit armada37xx_cpufreq_driver_exit(void)
0537 {
0538     struct platform_device *pdev = armada37xx_cpufreq_state->pdev;
0539     struct armada_37xx_dvfs *dvfs = platform_get_drvdata(pdev);
0540     unsigned long freq;
0541     int load_lvl;
0542 
0543     platform_device_unregister(pdev);
0544 
0545     armada37xx_cpufreq_disable_dvfs(armada37xx_cpufreq_state->regmap);
0546 
0547     for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR; load_lvl++) {
0548         freq = dvfs->cpu_freq_max / dvfs->divider[load_lvl];
0549         dev_pm_opp_remove(armada37xx_cpufreq_state->cpu_dev, freq);
0550     }
0551 
0552     kfree(armada37xx_cpufreq_state);
0553 }
0554 module_exit(armada37xx_cpufreq_driver_exit);
0555 
0556 static const struct of_device_id __maybe_unused armada37xx_cpufreq_of_match[] = {
0557     { .compatible = "marvell,armada-3700-nb-pm" },
0558     { },
0559 };
0560 MODULE_DEVICE_TABLE(of, armada37xx_cpufreq_of_match);
0561 
0562 MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
0563 MODULE_DESCRIPTION("Armada 37xx cpufreq driver");
0564 MODULE_LICENSE("GPL");