Guest User

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

a guest
Nov 21st, 2015
869
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