SHARE
TWEET

H3_SDK_20150601_lichee/linux-3.4/drivers/arisc/arisc_dvfs.c

a guest Nov 21st, 2015 758 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  *  drivers/arisc/interfaces/arisc_dvfs.c
  3.  *
  4.  * Copyright (c) 2012 Allwinner.
  5.  * 2012-05-01 Written by sunny (sunny@allwinnertech.com).
  6.  * 2012-10-01 Written by superm (superm@allwinnertech.com).
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21.  */
  22.  
  23. #include "../arisc_i.h"
  24. #include <mach/sys_config.h>
  25. #include <mach/sunxi-chip.h>
  26.  
  27. typedef struct arisc_freq_voltage
  28. {
  29.         u32 freq;       //cpu frequency
  30.         u32 voltage;    //voltage for the frequency
  31.         u32 axi_div;    //the divide ratio of axi bus
  32. } arisc_freq_voltage_t;
  33.  
  34. static int arisc_dvfs_get_cfg(char *main, char *sub, u32 *val)
  35. {
  36.         script_item_u script_val;
  37.         script_item_value_type_e type;
  38.         type = script_get_item(main, sub, &script_val);
  39.         if (SCIRPT_ITEM_VALUE_TYPE_INT != type) {
  40.                 ARISC_ERR("arisc dvfs config:%s type:%d err!\n", sub, type);
  41.                 return -EINVAL;
  42.         }
  43.         *val = script_val.val;
  44.         ARISC_INF("arisc dvfs config [%s] [%s] : %d\n", main, sub, *val);
  45.         return 0;
  46. }
  47.  
  48. //cpu voltage-freq table
  49. #if (defined CONFIG_ARCH_SUN8IW1P1) || (defined CONFIG_ARCH_SUN8IW3P1) || (defined CONFIG_ARCH_SUN8IW5P1) || \
  50.     (defined CONFIG_ARCH_SUN8IW7P1)
  51. static struct arisc_freq_voltage arisc_vf_table[ARISC_DVFS_VF_TABLE_MAX] =
  52. {
  53.         //freq          //voltage   //axi_div
  54.         {900000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (600Mhz, 1008Mhz]
  55.         {600000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (420Mhz, 600Mhz]
  56.         {420000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (360Mhz, 420Mhz]
  57.         {360000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (300Mhz, 360Mhz]
  58.         {300000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (240Mhz, 300Mhz]
  59.         {240000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (120Mhz, 240Mhz]
  60.         {120000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (60Mhz,  120Mhz]
  61.         {60000000,      1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (0Mhz,   60Mhz]
  62.         {0,             1200,       3}, //end of cpu dvfs table
  63.         {0,             1200,       3}, //end of cpu dvfs table
  64.         {0,             1200,       3}, //end of cpu dvfs table
  65.         {0,             1200,       3}, //end of cpu dvfs table
  66.         {0,             1200,       3}, //end of cpu dvfs table
  67.         {0,             1200,       3}, //end of cpu dvfs table
  68.         {0,             1200,       3}, //end of cpu dvfs table
  69.         {0,             1200,       3}, //end of cpu dvfs table
  70. };
  71. #elif defined (CONFIG_ARCH_SUN9IW1P1) || (defined CONFIG_ARCH_SUN8IW6P1) || (defined CONFIG_ARCH_SUN8IW9P1)
  72. static struct arisc_freq_voltage arisc_vf_table[2][ARISC_DVFS_VF_TABLE_MAX] =
  73. {
  74.         {
  75.         //freq          //voltage   //axi_div
  76.         {900000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (600Mhz, 1008Mhz]
  77.         {600000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (420Mhz, 600Mhz]
  78.         {420000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (360Mhz, 420Mhz]
  79.         {360000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (300Mhz, 360Mhz]
  80.         {300000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (240Mhz, 300Mhz]
  81.         {240000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (120Mhz, 240Mhz]
  82.         {120000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (60Mhz,  120Mhz]
  83.         {60000000,      1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (0Mhz,   60Mhz]
  84.         {0,             1200,       3}, //end of cpu dvfs table
  85.         {0,             1200,       3}, //end of cpu dvfs table
  86.         {0,             1200,       3}, //end of cpu dvfs table
  87.         {0,             1200,       3}, //end of cpu dvfs table
  88.         {0,             1200,       3}, //end of cpu dvfs table
  89.         {0,             1200,       3}, //end of cpu dvfs table
  90.         {0,             1200,       3}, //end of cpu dvfs table
  91.         {0,             1200,       3}, //end of cpu dvfs table
  92.         },
  93.  
  94.         {
  95.         //freq          //voltage   //axi_div
  96.         {900000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (600Mhz, 1008Mhz]
  97.         {600000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (420Mhz, 600Mhz]
  98.         {420000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (360Mhz, 420Mhz]
  99.         {360000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (300Mhz, 360Mhz]
  100.         {300000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (240Mhz, 300Mhz]
  101.         {240000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (120Mhz, 240Mhz]
  102.         {120000000,     1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (60Mhz,  120Mhz]
  103.         {60000000,      1200,       3}, //cpu0 vdd is 1.20v if cpu freq is (0Mhz,   60Mhz]
  104.         {0,             1200,       3}, //end of cpu dvfs table
  105.         {0,             1200,       3}, //end of cpu dvfs table
  106.         {0,             1200,       3}, //end of cpu dvfs table
  107.         {0,             1200,       3}, //end of cpu dvfs table
  108.         {0,             1200,       3}, //end of cpu dvfs table
  109.         {0,             1200,       3}, //end of cpu dvfs table
  110.         {0,             1200,       3}, //end of cpu dvfs table
  111.         {0,             1200,       3}, //end of cpu dvfs table
  112.         },
  113. };
  114. #endif
  115.  
  116. #if (defined CONFIG_ARCH_SUN8IW1P1) || (defined CONFIG_ARCH_SUN8IW3P1) || (defined CONFIG_ARCH_SUN8IW5P1) || \
  117.     (defined CONFIG_ARCH_SUN8IW7P1)
  118. int arisc_dvfs_cfg_vf_table(void)
  119. {
  120.         u32    value = 0;
  121.         int    index = 0;
  122.         int    result = 0;
  123.         int    vf_table_size = 0;
  124.         char   vf_table_main_key[64];
  125.         char   vf_table_sub_key[64];
  126.         struct arisc_message *pmessage;
  127.         u32    ver;
  128.         u32    is_def_table = 0;
  129.         spinlock_t    dvfs_lock;    /* spinlock for dvfs */
  130.         unsigned long dvfs_flag;
  131. #if (defined CONFIG_ARCH_SUN8IW7P1)
  132.         script_item_u script_val;
  133.         script_item_value_type_e type;
  134.         script_item_u *pin_list;
  135.         int pin_count = 0;
  136.         int pin_index = 0;
  137.         struct gpio_config *pin_cfg;
  138.         char pin_name[SUNXI_PIN_NAME_MAX_LEN];
  139.         unsigned long config;
  140.         unsigned int board_vendor;
  141. #endif
  142.  
  143.         /* initialize message manager spinlock */
  144.         spin_lock_init(&(dvfs_lock));
  145.         dvfs_flag = 0;
  146.  
  147.         spin_lock_irqsave(&(dvfs_lock), dvfs_flag);
  148.         ver = readl(IO_ADDRESS(SUNXI_SRAMCTRL_PBASE + 0x24));
  149.         ver |= 0x1 << 15;
  150.         writel(ver, IO_ADDRESS(SUNXI_SRAMCTRL_PBASE + 0x24));
  151.         ver = readl(IO_ADDRESS(SUNXI_SRAMCTRL_PBASE + 0x24)) >> 16;
  152.         spin_unlock_irqrestore(&(dvfs_lock), dvfs_flag);
  153.  
  154.         if (ver == 0x1661) {
  155.                 if (arisc_dvfs_get_cfg("dvfs_table_bak", "LV_count", &vf_table_size)) {
  156.                         strcpy(vf_table_main_key, "dvfs_table");
  157.                         is_def_table = 1;
  158.                 } else {
  159.                         strcpy(vf_table_main_key, "dvfs_table_bak");
  160.                         is_def_table = 0;
  161.                 }
  162.         } else {
  163.                 strcpy(vf_table_main_key, "dvfs_table");
  164.                 is_def_table = 1;
  165.         }
  166.  
  167.         /* parse system config v-f table information */
  168.         if (arisc_dvfs_get_cfg(vf_table_main_key, "LV_count", &vf_table_size)) {
  169.                 ARISC_WRN("parse system config dvfs_table size fail\n");
  170.         }
  171.         for (index = 0; index < vf_table_size; index++) {
  172.                 sprintf(vf_table_sub_key, "LV%d_freq", index + 1);
  173.                 if (arisc_dvfs_get_cfg(vf_table_main_key, vf_table_sub_key, &value) == 0) {
  174.                         arisc_vf_table[index].freq = value;
  175.                 }
  176.                 sprintf(vf_table_sub_key, "LV%d_volt", index + 1);
  177.                 if (arisc_dvfs_get_cfg(vf_table_main_key, vf_table_sub_key, &value) == 0) {
  178.                         if ((value < 1100) && (ver == 0x1661) && (is_def_table)) {
  179.                                 value = 1100;
  180.                         }
  181.                         arisc_vf_table[index].voltage = value;
  182.                 }
  183.         }
  184.  
  185.         /* allocate a message frame */
  186.         pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
  187.         if (pmessage == NULL) {
  188.                 ARISC_WRN("allocate message failed\n");
  189.                 return -ENOMEM;
  190.         }
  191.         for (index = 0; index < ARISC_DVFS_VF_TABLE_MAX; index++) {
  192.                 /* initialize message
  193.                  *
  194.                  * |paras[0]|paras[1]|paras[2]|paras[3]|paras[4]|
  195.                  * | index  |  freq  |voltage |axi_div |  pll  |
  196.                  */
  197.                 pmessage->type       = ARISC_CPUX_DVFS_CFG_VF_REQ;
  198.                 pmessage->paras[0]   = index;
  199.                 pmessage->paras[1]   = arisc_vf_table[index].freq;
  200.                 pmessage->paras[2]   = arisc_vf_table[index].voltage;
  201.                 pmessage->paras[3]   = arisc_vf_table[index].axi_div;
  202.                 pmessage->paras[4]   = 0;
  203.                 pmessage->state      = ARISC_MESSAGE_INITIALIZED;
  204.                 pmessage->cb.handler = NULL;
  205.                 pmessage->cb.arg     = NULL;
  206.  
  207.                 ARISC_INF("v-f table: index %d freq %d vol %d axi_div %d\n",
  208.                 pmessage->paras[0], pmessage->paras[1], pmessage->paras[2], pmessage->paras[3]);
  209.  
  210.                 /* send request message */
  211.                 arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
  212.  
  213.                 //check config fail or not
  214.                 if (pmessage->result) {
  215.                         ARISC_WRN("config dvfs v-f table [%d] fail\n", index);
  216.                         result = -EINVAL;
  217.                         break;
  218.                 }
  219.         }
  220. #if (defined CONFIG_ARCH_SUN8IW7P1)
  221. /* [pmuic_type]:0~2, 0:none, 1:gpio, 2:i2c
  222.  * [gpio0_cfg ]:bit0~15:gpio num, bit16:used
  223.  * [gpio1_cfg ]:bit0~15:gpio num, bit16:used
  224.  * [pmu_level0]:bit0~15:voltage(mV), bit16~19:gpio0 state, bit20~23:gpio1 state
  225.  * [pmu_level1]:bit0~15:voltage(mV), bit16~19:gpio0 state, bit20~23:gpio1 state
  226.  * [pmu_level2]:bit0~15:voltage(mV), bit16~19:gpio0 state, bit20~23:gpio1 state
  227.  * [pmu_level3]:bit0~15:voltage(mV), bit16~19:gpio0 state, bit20~23:gpio1 state
  228.  */
  229. #define GPIO_USED_CFG(x) ((x) | (1<<16))
  230. #define VOL_LEVEL_CFG(x) ((x)%10000) | ((((x)/10000)%10)<<16) | ((((x)/100000)%10)<<20)
  231.  
  232.         /* get pmuic type */
  233.         type = script_get_item("dvfs_table", "pmuic_type", &script_val);
  234.         if (SCIRPT_ITEM_VALUE_TYPE_INT != type) {
  235.                 ARISC_ERR("arisc dvfs config err! type:%d\n", type);
  236.                 return -EINVAL;
  237.         }
  238.         pmessage->paras[0] = script_val.val;
  239.  
  240.         board_vendor = sunxi_get_board_vendor_id();
  241.         if (!(board_vendor&0x08))    /*for costdown board*/
  242.                 pmessage->paras[0] = 0;
  243.  
  244.         if (pmessage->paras[0] != 1) /* not gpio pmu */
  245.                 goto out;
  246.  
  247.         /* get gpio config */
  248.         pmessage->paras[1] = 0;
  249.         pmessage->paras[2] = 0;
  250.         pin_count = script_get_pio_list ("dvfs_table", &pin_list);
  251.         for (pin_index = 0; pin_index < pin_count; pin_index++) {
  252.                 pin_cfg = &(pin_list[pin_index].gpio);
  253.                 sunxi_gpio_to_name(pin_cfg->gpio, pin_name);
  254.                 config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, pin_cfg->mul_sel);
  255.                 pin_config_set(SUNXI_PINCTRL, pin_name, config);
  256.                 if (pin_cfg->pull != GPIO_PULL_DEFAULT) {
  257.                         config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_PUD, pin_cfg->pull);
  258.                         pin_config_set (SUNXI_PINCTRL, pin_name, config);
  259.                 }
  260.                 if (pin_cfg->drv_level != GPIO_DRVLVL_DEFAULT) {
  261.                         config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DRV, pin_cfg->drv_level);
  262.                         pin_config_set (SUNXI_PINCTRL, pin_name, config);
  263.                 }
  264.                 if (pin_cfg->data != GPIO_DATA_DEFAULT) {
  265.                         config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT, pin_cfg->data);
  266.                         pin_config_set (SUNXI_PINCTRL, pin_name, config);
  267.                 }
  268.                 /* NOTE: only used PL, the gpio group info. is discard */
  269.                 pmessage->paras[1 + pin_index] = GPIO_USED_CFG((pin_cfg->gpio) % SUNXI_BANK_SIZE);
  270.                 ARISC_INF("%s,%d,id:%d,num:%d,reg:%x\n", __func__, __LINE__, pin_index, \
  271.                           pin_cfg->gpio, pmessage->paras[1 + pin_index]);
  272.         }
  273.  
  274.         if (pin_count < 2) /* only gpio0 used */
  275.                 vf_table_size = 2;
  276.         else
  277.                 vf_table_size = 4;
  278.  
  279.         for (index = 0; index < vf_table_size; index++) {
  280.                 sprintf(vf_table_sub_key, "pmu_level%d", index);
  281.                 type = script_get_item(vf_table_main_key, vf_table_sub_key, &script_val);
  282.                 if (SCIRPT_ITEM_VALUE_TYPE_INT != type) {
  283.                         ARISC_ERR("arisc dvfs config err! type:%d\n", type);
  284.                         return -EINVAL;
  285.                 }
  286.                 pmessage->paras[3 + index] = VOL_LEVEL_CFG(script_val.val);
  287.         }
  288.  
  289. out:
  290.         pmessage->type       = ARISC_CPUX_DVFS_CFG_REQ;
  291.         pmessage->state      = ARISC_MESSAGE_INITIALIZED;
  292.         pmessage->cb.handler = NULL;
  293.         pmessage->cb.arg     = NULL;
  294.  
  295.         arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
  296.  
  297.         if (pmessage->result) {
  298.                 ARISC_WRN("config dvfs cfg fail\n");
  299.                 result = -EINVAL;
  300.         }
  301. #endif
  302.         /* free allocated message */
  303.         arisc_message_free(pmessage);
  304.  
  305.         return result;
  306.  
  307. }
  308.  
  309. #elif defined CONFIG_ARCH_SUN8IW5P1
  310. int arisc_dvfs_cfg_vf_table(void)
  311. {
  312.         u32    value = 0;
  313.         int    index = 0;
  314.         int    result = 0;
  315.         int    vf_table_size = 0;
  316.         char   vf_table_main_key[64];
  317.         char   vf_table_sub_key[64];
  318.         int    vf_table_count = 0;
  319.         int    vf_table_type = 0;
  320.         struct arisc_message *pmessage;
  321.  
  322.         if (arisc_dvfs_get_cfg("dvfs_table", "vf_table_count", &vf_table_count)) {
  323.                 ARISC_LOG("%s: support only one vf_table\n", __func__);
  324.                 sprintf(vf_table_main_key, "%s", "dvfs_table");
  325.         } else {
  326.                 vf_table_type = sunxi_get_soc_bin();
  327.                 sprintf(vf_table_main_key, "%s%d", "vf_table", vf_table_type);
  328.         }
  329.         pr_info("%s: vf table type [%d=%s]\n", __func__, vf_table_type, vf_table_main_key);
  330.  
  331.         /* parse system config v-f table information */
  332.         if (arisc_dvfs_get_cfg(vf_table_main_key, "LV_count", &vf_table_size)) {
  333.                 ARISC_WRN("parse system config dvfs_table size fail\n");
  334.         }
  335.         for (index = 0; index < vf_table_size; index++) {
  336.                 sprintf(vf_table_sub_key, "LV%d_freq", index + 1);
  337.                 if (arisc_dvfs_get_cfg(vf_table_main_key, vf_table_sub_key, &value) == 0) {
  338.                         arisc_vf_table[index].freq = value;
  339.                 }
  340.                 pr_info("%s: freq [%s-%d=%d]\n", __func__, vf_table_sub_key, index, value);
  341.                 sprintf(vf_table_sub_key, "LV%d_volt", index + 1);
  342.                 if (arisc_dvfs_get_cfg(vf_table_main_key, vf_table_sub_key, &value) == 0) {
  343.                         arisc_vf_table[index].voltage = value;
  344.                 }
  345.                 pr_info("%s: volt [%s-%d=%d]\n", __func__, vf_table_sub_key, index, value);
  346.         }
  347.  
  348.         /* allocate a message frame */
  349.         pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
  350.         if (pmessage == NULL) {
  351.                 ARISC_WRN("allocate message failed\n");
  352.                 return -ENOMEM;
  353.         }
  354.         for (index = 0; index < ARISC_DVFS_VF_TABLE_MAX; index++) {
  355.                 /* initialize message
  356.                  *
  357.                  * |paras[0]|paras[1]|paras[2]|paras[3]|paras[4]|
  358.                  * | index  |  freq  |voltage |axi_div |  pll  |
  359.                  */
  360.                 pmessage->type       = ARISC_CPUX_DVFS_CFG_VF_REQ;
  361.                 pmessage->paras[0]   = index;
  362.                 pmessage->paras[1]   = arisc_vf_table[index].freq;
  363.                 pmessage->paras[2]   = arisc_vf_table[index].voltage;
  364.                 pmessage->paras[3]   = arisc_vf_table[index].axi_div;
  365.                 pmessage->paras[4]   = 0;
  366.                 pmessage->state      = ARISC_MESSAGE_INITIALIZED;
  367.                 pmessage->cb.handler = NULL;
  368.                 pmessage->cb.arg     = NULL;
  369.  
  370.                 ARISC_INF("v-f table: index %d freq %d vol %d axi_div %d\n",
  371.                 pmessage->paras[0], pmessage->paras[1], pmessage->paras[2], pmessage->paras[3]);
  372.  
  373.  
  374.                 /* send request message */
  375.                 arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
  376.  
  377.                 //check config fail or not
  378.                 if (pmessage->result) {
  379.                         ARISC_WRN("config dvfs v-f table [%d] fail\n", index);
  380.                         result = -EINVAL;
  381.                         break;
  382.                 }
  383.         }
  384.         /* free allocated message */
  385.         arisc_message_free(pmessage);
  386.  
  387.         return result;
  388. }
  389.  
  390. #elif (defined CONFIG_ARCH_SUN9IW1P1)
  391. int arisc_dvfs_cfg_vf_table(void)
  392. {
  393.         u32    value = 0;
  394.         int    index = 0;
  395.         int    cluster = 0;
  396.         int    result = 0;
  397.         int    vf_table_size[2] = {0, 0};
  398.         char   vf_table_main_key[64];
  399.         char   vf_table_sub_key[64];
  400.         char   cluster_name[2] = {'L', 'B'};
  401.         int    vf_table_count = 0;
  402.         int    vf_table_type = 0;
  403.         struct arisc_message *pmessage;
  404.  
  405.         if (arisc_dvfs_get_cfg("dvfs_table", "vf_table_count", &vf_table_count)) {
  406.                 ARISC_LOG("%s: support only one vf_table\n", __func__);
  407.                 sprintf(vf_table_main_key, "%s", "dvfs_table");
  408.         } else {
  409.                 vf_table_type = sunxi_get_soc_bin();
  410.                 sprintf(vf_table_main_key, "%s%d", "vf_table", vf_table_type);
  411.         }
  412.         ARISC_INF("%s: vf table type [%d=%s]\n", __func__, vf_table_type, vf_table_main_key);
  413.  
  414.         /* parse system config v-f table information */
  415.         for (cluster = 0; cluster < 2; cluster++) {
  416.                 sprintf(vf_table_sub_key, "%c_LV_count", cluster_name[cluster]);
  417.                 if (arisc_dvfs_get_cfg(vf_table_main_key, vf_table_sub_key, &vf_table_size[cluster])) {
  418.                         ARISC_WRN("parse system config dvfs_table size fail\n");
  419.                 }
  420.  
  421.                 for (index = 0; index < vf_table_size[cluster]; index++) {
  422.                         sprintf(vf_table_sub_key, "%c_LV%d_freq", cluster_name[cluster], index + 1);
  423.                         if (arisc_dvfs_get_cfg(vf_table_main_key, vf_table_sub_key, &value) == 0) {
  424.                                 arisc_vf_table[cluster][index].freq = value;
  425.                         }
  426.                         ARISC_INF("%s: freq [%s-%d=%d]\n", __func__, vf_table_sub_key, index, value);
  427.                         sprintf(vf_table_sub_key, "%c_LV%d_volt", cluster_name[cluster], index + 1);
  428.                         if (arisc_dvfs_get_cfg(vf_table_main_key, vf_table_sub_key, &value) == 0) {
  429.                                 arisc_vf_table[cluster][index].voltage = value;
  430.                         }
  431.                         ARISC_INF("%s: volt [%s-%d=%d]\n", __func__, vf_table_sub_key, index, value);
  432.                 }
  433.         }
  434.  
  435.         /* allocate a message frame */
  436.         pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
  437.         if (pmessage == NULL) {
  438.                 ARISC_WRN("allocate message failed\n");
  439.                 return -ENOMEM;
  440.         }
  441.         for (cluster = 0; cluster < 2; cluster++) {
  442.                 for (index = 0; index < ARISC_DVFS_VF_TABLE_MAX; index++) {
  443.                         /* initialize message
  444.                          *
  445.                          * |paras[0]|paras[1]|paras[2]|paras[3]|paras[4]|
  446.                          * | index  |  freq  |voltage |axi_div |  pll   |
  447.                          */
  448.                         pmessage->type       = ARISC_CPUX_DVFS_CFG_VF_REQ;
  449.                         pmessage->paras[0]   = index;
  450.                         pmessage->paras[1]   = arisc_vf_table[cluster][index].freq;
  451.                         pmessage->paras[2]   = arisc_vf_table[cluster][index].voltage;
  452.                         pmessage->paras[3]   = arisc_vf_table[cluster][index].axi_div;
  453.                         pmessage->paras[4]   = cluster;
  454.                         pmessage->state      = ARISC_MESSAGE_INITIALIZED;
  455.                         pmessage->cb.handler = NULL;
  456.                         pmessage->cb.arg     = NULL;
  457.  
  458.                         ARISC_INF("v-f table: cluster %d index %d freq %d vol %d axi_div %d\n",
  459.                         pmessage->paras[4], pmessage->paras[0], pmessage->paras[1], pmessage->paras[2], pmessage->paras[3]);
  460.  
  461.                         /* send request message */
  462.                         arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
  463.  
  464.                         //check config fail or not
  465.                         if (pmessage->result) {
  466.                                 ARISC_WRN("config dvfs v-f table [%d][%d] fail\n", cluster, index);
  467.                                 result = -EINVAL;
  468.                                 break;
  469.                         }
  470.                 }
  471.         }
  472.  
  473.         /* free allocated message */
  474.         arisc_message_free(pmessage);
  475.  
  476.         return result;
  477. }
  478. #elif (defined CONFIG_ARCH_SUN8IW6P1) || (defined CONFIG_ARCH_SUN8IW9P1)
  479. int arisc_dvfs_cfg_vf_table(void)
  480. {
  481.         u32    value = 0;
  482.         int    index = 0;
  483.         int    cluster = 0;
  484.         int    result = 0;
  485.         int    vf_table_size[2] = {0, 0};
  486.         char   vf_table_main_key[64];
  487.         char   vf_table_sub_key[64];
  488.         char   cluster_name[2] = {'L', 'B'};
  489.         int    vf_table_count = 0;
  490.         int    vf_table_type = 0;
  491.         struct arisc_message *pmessage;
  492.  
  493.         if (arisc_dvfs_get_cfg("dvfs_table", "vf_table_count", &vf_table_count)) {
  494.                 ARISC_LOG("%s: support only one vf_table\n", __func__);
  495.                 sprintf(vf_table_main_key, "%s", "dvfs_table");
  496.         } else {
  497.                 vf_table_type = sunxi_get_soc_bin();
  498.                 sprintf(vf_table_main_key, "%s%d", "vf_table", vf_table_type);
  499.         }
  500.         ARISC_INF("%s: vf table type [%d=%s]\n", __func__, vf_table_type, vf_table_main_key);
  501.  
  502.         /* parse system config v-f table information */
  503.         for (cluster = 0; cluster < 1; cluster++) {
  504.                 sprintf(vf_table_sub_key, "%c_LV_count", cluster_name[cluster]);
  505.                 if (arisc_dvfs_get_cfg(vf_table_main_key, vf_table_sub_key, &vf_table_size[cluster])) {
  506.                         ARISC_WRN("parse system config dvfs_table size fail\n");
  507.                 }
  508.  
  509.                 for (index = 0; index < vf_table_size[cluster]; index++) {
  510.                         sprintf(vf_table_sub_key, "%c_LV%d_freq", cluster_name[cluster], index + 1);
  511.                         if (arisc_dvfs_get_cfg(vf_table_main_key, vf_table_sub_key, &value) == 0) {
  512.                                 arisc_vf_table[cluster][index].freq = value;
  513.                         }
  514.                         ARISC_INF("%s: freq [%s-%d=%d]\n", __func__, vf_table_sub_key, index, value);
  515.                         sprintf(vf_table_sub_key, "%c_LV%d_volt", cluster_name[cluster], index + 1);
  516.                         if (arisc_dvfs_get_cfg(vf_table_main_key, vf_table_sub_key, &value) == 0) {
  517.                                 arisc_vf_table[cluster][index].voltage = value;
  518.                         }
  519.                         ARISC_INF("%s: volt [%s-%d=%d]\n", __func__, vf_table_sub_key, index, value);
  520.                 }
  521.         }
  522.  
  523.         /* allocate a message frame */
  524.         pmessage = arisc_message_allocate(ARISC_MESSAGE_ATTR_HARDSYN);
  525.         if (pmessage == NULL) {
  526.                 ARISC_WRN("allocate message failed\n");
  527.                 return -ENOMEM;
  528.         }
  529.         for (cluster = 0; cluster < 1; cluster++) {
  530.                 for (index = 0; index < ARISC_DVFS_VF_TABLE_MAX; index++) {
  531.                         /* initialize message
  532.                          *
  533.                          * |paras[0]|paras[1]|paras[2]|paras[3]|paras[4]|
  534.                          * | index  |  freq  |voltage |axi_div |  pll   |
  535.                          */
  536.                         pmessage->type       = ARISC_CPUX_DVFS_CFG_VF_REQ;
  537.                         pmessage->paras[0]   = index;
  538.                         pmessage->paras[1]   = arisc_vf_table[cluster][index].freq;
  539.                         pmessage->paras[2]   = arisc_vf_table[cluster][index].voltage;
  540.                         pmessage->paras[3]   = arisc_vf_table[cluster][index].axi_div;
  541.                         pmessage->paras[4]   = cluster;
  542.                         pmessage->state      = ARISC_MESSAGE_INITIALIZED;
  543.                         pmessage->cb.handler = NULL;
  544.                         pmessage->cb.arg     = NULL;
  545.  
  546.                         ARISC_INF("v-f table: cluster %d index %d freq %d vol %d axi_div %d\n",
  547.                         pmessage->paras[4], pmessage->paras[0], pmessage->paras[1], pmessage->paras[2], pmessage->paras[3]);
  548.  
  549.                         /* send request message */
  550.                         arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
  551.  
  552.                         //check config fail or not
  553.                         if (pmessage->result) {
  554.                                 ARISC_WRN("config dvfs v-f table [%d][%d] fail\n", cluster, index);
  555.                                 result = -EINVAL;
  556.                                 break;
  557.                         }
  558.                 }
  559.         }
  560.  
  561.         /* free allocated message */
  562.         arisc_message_free(pmessage);
  563.  
  564.         return result;
  565. }
  566. #endif
  567.  
  568. /*
  569.  * set specific pll target frequency.
  570.  * @freq:    target frequency to be set, based on KHZ;
  571.  * @pll:     which pll will be set
  572.  * @mode:    the attribute of message, whether syn or asyn;
  573.  * @cb:      callback handler;
  574.  * @cb_arg:  callback handler arguments;
  575.  *
  576.  * return: result, 0 - set frequency successed,
  577.  *                !0 - set frequency failed;
  578.  */
  579. int arisc_dvfs_set_cpufreq(unsigned int freq, unsigned int pll, unsigned long mode, arisc_cb_t cb, void *cb_arg)
  580. {
  581.         unsigned int          msg_attr = 0;
  582.         struct arisc_message *pmessage;
  583.         int                   result = 0;
  584.  
  585.         if (mode & ARISC_DVFS_SYN) {
  586.                 msg_attr |= ARISC_MESSAGE_ATTR_HARDSYN;
  587.         }
  588.  
  589.         /* allocate a message frame */
  590.         pmessage = arisc_message_allocate(msg_attr);
  591.         if (pmessage == NULL) {
  592.                 ARISC_WRN("allocate message failed\n");
  593.                 return -ENOMEM;
  594.         }
  595.  
  596.         /* initialize message
  597.          *
  598.          * |paras[0]|paras[1]|
  599.          * |freq    |pll     |
  600.          */
  601.         pmessage->type       = ARISC_CPUX_DVFS_REQ;
  602.         pmessage->paras[0]   = freq;
  603.         pmessage->paras[1]   = pll;
  604.         pmessage->state      = ARISC_MESSAGE_INITIALIZED;
  605.         pmessage->cb.handler = cb;
  606.         pmessage->cb.arg     = cb_arg;
  607.  
  608.         ARISC_INF("arisc dvfs request : %d\n", freq);
  609.         arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT);
  610.  
  611.         /* dvfs mode : syn or not */
  612.         if (mode & ARISC_DVFS_SYN) {
  613.                 result = pmessage->result;
  614.                 arisc_message_free(pmessage);
  615.         }
  616.  
  617.         return result;
  618. }
  619. EXPORT_SYMBOL(arisc_dvfs_set_cpufreq);
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top