ccci_util_lib_sys.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /*
  2. *Copyright(C)2017 MediaTek Inc.
  3. *
  4. *This program is free software;you can redistribute it and/or modify it under
  5. *the terms of the GNU General Public License version 2 as published by the
  6. *Free Software Foundation.
  7. *
  8. *This program is distributed in the hope that it will be useful,but WITHOUT
  9. *ANY WARRANTY;without even the implied warranty of MERCHANTABILITY or FITNESS
  10. *FOR A PARTICULAR PURPOSE.
  11. *See http://www.gnu.org/licenses/gpl-2.0.html for more details.
  12. */
  13. #include <mt-plat/sync_write.h>
  14. #include <mt-plat/mt_ccci_common.h>
  15. #include <linux/slab.h>
  16. #include <linux/kobject.h>
  17. #include "ccci_util_log.h"
  18. #include "ccci_util_lib_sys.h"
  19. #define CCCI_KOBJ_NAME "ccci"
  20. struct ccci_info {
  21. struct kobject kobj;
  22. unsigned int ccci_attr_count;
  23. };
  24. struct ccci_attribute {
  25. struct attribute attr;
  26. ssize_t (*show)(char *buf);
  27. ssize_t (*store)(const char *buf, size_t count);
  28. };
  29. #define CCCI_ATTR(_name, _mode, _show, _store) \
  30. static struct ccci_attribute ccci_attr_##_name = { \
  31. .attr = {.name = __stringify(_name), .mode = _mode }, \
  32. .show = _show, \
  33. .store = _store, \
  34. }
  35. static struct ccci_info *ccci_sys_info;
  36. static void ccci_obj_release(struct kobject *kobj)
  37. {
  38. struct ccci_info *ccci_info_temp = container_of(kobj, struct ccci_info, kobj);
  39. kfree(ccci_info_temp);
  40. ccci_sys_info = NULL; /* as ccci_info_temp==ccci_sys_info */
  41. }
  42. static ssize_t ccci_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
  43. {
  44. ssize_t len = 0;
  45. struct ccci_attribute *a = container_of(attr, struct ccci_attribute, attr);
  46. if (a->show)
  47. len = a->show(buf);
  48. return len;
  49. }
  50. static ssize_t ccci_attr_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count)
  51. {
  52. ssize_t len = 0;
  53. struct ccci_attribute *a = container_of(attr, struct ccci_attribute, attr);
  54. if (a->store)
  55. len = a->store(buf, count);
  56. return len;
  57. }
  58. static const struct sysfs_ops ccci_sysfs_ops = {
  59. .show = ccci_attr_show,
  60. .store = ccci_attr_store
  61. };
  62. /*======================================= */
  63. /* CCCI common sys attribute part */
  64. /*======================================= */
  65. /* Sys -- boot status */
  66. static get_status_func_t get_status_func[MAX_MD_NUM];
  67. static boot_md_func_t boot_md_func[MAX_MD_NUM];
  68. static int get_md_status(int md_id, char val[], int size)
  69. {
  70. if ((md_id < MAX_MD_NUM) && (get_status_func[md_id] != NULL))
  71. (get_status_func[md_id]) (md_id, val, size);
  72. else
  73. snprintf(val, 32, "md%d:n/a", md_id + 1);
  74. return 0;
  75. }
  76. static int trigger_md_boot(int md_id)
  77. {
  78. if ((md_id < MAX_MD_NUM) && (boot_md_func[md_id] != NULL)) {
  79. (boot_md_func[md_id]) (md_id);
  80. return 0;
  81. }
  82. return -1;
  83. }
  84. static ssize_t boot_status_show(char *buf)
  85. {
  86. char md1_sta_str[32];
  87. char md2_sta_str[32];
  88. char md3_sta_str[32];
  89. char md5_sta_str[32];
  90. /* MD1 --- */
  91. get_md_status(MD_SYS1, md1_sta_str, 32);
  92. /* MD2 --- */
  93. get_md_status(MD_SYS2, md2_sta_str, 32);
  94. /* MD3 */
  95. get_md_status(MD_SYS3, md3_sta_str, 32);
  96. /* MD5 */
  97. get_md_status(MD_SYS5, md5_sta_str, 32);
  98. /* Final string */
  99. return snprintf(buf, 32 * 4 + 3 * 4 + 1, "%s | %s | %s | md4:n/a | %s\n", md1_sta_str, md2_sta_str, md3_sta_str,
  100. md5_sta_str);
  101. }
  102. static ssize_t boot_status_store(const char *buf, size_t count)
  103. {
  104. unsigned int md_id;
  105. md_id = buf[0] - '0';
  106. CCCI_UTIL_INF_MSG("md%d get boot store\n", md_id + 1);
  107. if (md_id < MAX_MD_NUM) {
  108. if (trigger_md_boot(md_id) != 0)
  109. CCCI_UTIL_INF_MSG("md%d n/a\n", md_id + 1);
  110. } else
  111. CCCI_UTIL_INF_MSG("invalid id(%d)\n", md_id + 1);
  112. return count;
  113. }
  114. CCCI_ATTR(boot, 0660, &boot_status_show, &boot_status_store);
  115. /* Sys -- enable status */
  116. static ssize_t ccci_md_enable_show(char *buf)
  117. {
  118. int i;
  119. char md_en[MAX_MD_NUM];
  120. for (i = 0; i < MAX_MD_NUM; i++) {
  121. if (get_modem_is_enabled(MD_SYS1 + i))
  122. md_en[i] = 'E';
  123. else
  124. md_en[i] = 'D';
  125. }
  126. /* Final string */
  127. return snprintf(buf, 32, "%c-%c-%c-%c-%c (1->5)\n", md_en[0], md_en[1], md_en[2], md_en[3], md_en[4]);
  128. }
  129. CCCI_ATTR(md_en, 0660, &ccci_md_enable_show, NULL);
  130. /* Sys -- Versin */
  131. static unsigned int ccci_port_ver = 3;
  132. static ssize_t ccci_version_show(char *buf)
  133. {
  134. return snprintf(buf, 16, "%d\n", ccci_port_ver); /* ECCCI */
  135. }
  136. void update_ccci_port_ver(unsigned int new_ver)
  137. {
  138. ccci_port_ver = new_ver;
  139. }
  140. CCCI_ATTR(version, 0644, &ccci_version_show, NULL);
  141. static ssize_t debug_enable_show(char *buf)
  142. {
  143. int curr = 0;
  144. curr = snprintf(buf, 16, "%d\n", ccci_debug_enable);
  145. return curr;
  146. }
  147. static ssize_t debug_enable_store(const char *buf, size_t count)
  148. {
  149. ccci_debug_enable = buf[0] - '0';
  150. return count;
  151. }
  152. CCCI_ATTR(debug, 0660, &debug_enable_show, &debug_enable_store);
  153. static ssize_t kcfg_setting_show(char *buf)
  154. {
  155. unsigned int curr = 0;
  156. unsigned int actual_write;
  157. char md_en[MAX_MD_NUM];
  158. unsigned int md_num = 0;
  159. int i;
  160. for (i = 0; i < MAX_MD_NUM; i++) {
  161. if (get_modem_is_enabled(MD_SYS1 + i)) {
  162. md_num++;
  163. md_en[i] = '1';
  164. } else
  165. md_en[i] = '0';
  166. }
  167. /* MD enable setting part */
  168. /* Reserve 16 byte to store size info */
  169. actual_write = snprintf(&buf[curr], 4096 - 16 - curr, "[modem num]:%d\n", md_num);
  170. curr += actual_write;
  171. /* Reserve 16 byte to store size info */
  172. actual_write = snprintf(&buf[curr], 4096 - 16 - curr,
  173. "[modem en]:%c-%c-%c-%c-%c\n", md_en[0], md_en[1], md_en[2], md_en[3], md_en[4]);
  174. curr += actual_write;
  175. /* Feature option part */
  176. #ifdef CONFIG_EVDO_DT_SUPPORT
  177. actual_write = snprintf(&buf[curr], 4096 - curr, "[EVDO_DT_SUPPORT]:1\n");
  178. #else
  179. actual_write = snprintf(&buf[curr], 4096 - curr, "[EVDO_DT_SUPPORT]:0\n");
  180. #endif
  181. curr += actual_write;
  182. #ifdef CONFIG_MTK_LTE_DC_SUPPORT
  183. actual_write = snprintf(&buf[curr], 4096 - curr, "[MTK_LTE_DC_SUPPORT]:1\n");
  184. #else
  185. actual_write = snprintf(&buf[curr], 4096 - curr, "[MTK_LTE_DC_SUPPORT]:0\n");
  186. #endif
  187. curr += actual_write;
  188. #ifdef CONFIG_MTK_ECCCI_C2K
  189. actual_write = snprintf(&buf[curr], 4096 - curr, "[MTK_ECCCI_C2K]:1\n");
  190. curr += actual_write;
  191. #endif
  192. /* Add total size to tail */
  193. actual_write = snprintf(&buf[curr], 4096 - curr, "total:%d\n", curr);
  194. curr += actual_write;
  195. CCCI_UTIL_INF_MSG("cfg_info_buffer size:%d\n", curr);
  196. return (ssize_t) curr;
  197. }
  198. static ssize_t kcfg_setting_store(const char *buf, size_t count)
  199. {
  200. return count;
  201. }
  202. CCCI_ATTR(kcfg_setting, 0444, &kcfg_setting_show, &kcfg_setting_store);
  203. /* Sys -- Add to group */
  204. static struct attribute *ccci_default_attrs[] = {
  205. &ccci_attr_boot.attr,
  206. &ccci_attr_version.attr,
  207. &ccci_attr_md_en.attr,
  208. &ccci_attr_debug.attr,
  209. &ccci_attr_kcfg_setting.attr,
  210. NULL
  211. };
  212. static struct kobj_type ccci_ktype = {
  213. .release = ccci_obj_release,
  214. .sysfs_ops = &ccci_sysfs_ops,
  215. .default_attrs = ccci_default_attrs
  216. };
  217. int ccci_sysfs_add_modem(int md_id, void *kobj, void *ktype, get_status_func_t get_sta_func, boot_md_func_t boot_func)
  218. {
  219. int ret;
  220. static int md_add_flag;
  221. md_add_flag = 0;
  222. if (!ccci_sys_info) {
  223. CCCI_UTIL_ERR_MSG("common sys not ready\n");
  224. return -CCCI_ERR_SYSFS_NOT_READY;
  225. }
  226. if (md_add_flag & (1 << md_id)) {
  227. CCCI_UTIL_ERR_MSG("md%d sys dup add\n", md_id + 1);
  228. return -CCCI_ERR_SYSFS_NOT_READY;
  229. }
  230. ret =
  231. kobject_init_and_add((struct kobject *)kobj, (struct kobj_type *)ktype, &ccci_sys_info->kobj, "mdsys%d",
  232. md_id + 1);
  233. if (ret < 0) {
  234. kobject_put(kobj);
  235. CCCI_UTIL_ERR_MSG_WITH_ID(md_id, "fail to add md kobject\n");
  236. } else {
  237. md_add_flag |= (1 << md_id);
  238. get_status_func[md_id] = get_sta_func;
  239. boot_md_func[md_id] = boot_func;
  240. }
  241. return ret;
  242. }
  243. int ccci_common_sysfs_init(void)
  244. {
  245. int ret = 0;
  246. int i;
  247. ccci_sys_info = kmalloc(sizeof(struct ccci_info), GFP_KERNEL);
  248. if (!ccci_sys_info)
  249. return -ENOMEM;
  250. memset(ccci_sys_info, 0, sizeof(struct ccci_info));
  251. ret = kobject_init_and_add(&ccci_sys_info->kobj, &ccci_ktype, kernel_kobj, CCCI_KOBJ_NAME);
  252. if (ret < 0) {
  253. kobject_put(&ccci_sys_info->kobj);
  254. CCCI_UTIL_ERR_MSG("fail to add ccci kobject\n");
  255. return ret;
  256. }
  257. for (i = 0; i < MAX_MD_NUM; i++) {
  258. get_status_func[i] = NULL;
  259. boot_md_func[i] = NULL;
  260. }
  261. ccci_sys_info->ccci_attr_count = ARRAY_SIZE(ccci_default_attrs) - 1;
  262. CCCI_UTIL_DBG_MSG("ccci attr cnt %d\n", ccci_sys_info->ccci_attr_count);
  263. return ret;
  264. }