aboutsummaryrefslogtreecommitdiff
path: root/drivers/misc/mediatek/ccci_util/ccci_util_lib_fo.c
blob: d614a72c286eb3cc1df9757cf695b3cfc3be1c95 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
#include <linux/module.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/mm.h>
#include <linux/kfifo.h>

#include <linux/firmware.h>
#include <linux/syscalls.h>
#include <linux/uaccess.h>
#include <linux/platform_device.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/memblock.h>
#include <asm/memblock.h>

#ifdef CONFIG_OF
#include <linux/of.h>
#include <linux/of_fdt.h>
#endif
#ifdef CONFIG_OF_RESERVED_MEM
#include <linux/of_reserved_mem.h>
#endif

#include <asm/setup.h>
#include <asm/atomic.h>
#include <mach/mt_typedefs.h>
#include <mach/mt_boot_common.h>

#include <mach/ccci_config.h>
#include <mach/mt_ccci_common.h>

#include "ccci_util_log.h"

//======================================================
// DFO support section
//======================================================
typedef struct fos_item  // Feature Option Setting
{
	char         *name;
	volatile int value;
}fos_item_t;
// DFO table
// TODO : the following macro can be removed sometime
// MD1
#ifdef  CONFIG_MTK_ENABLE_MD1
#define MTK_MD1_EN	(1)
#else
#define MTK_MD1_EN	(0)
#endif

#ifdef CONFIG_MTK_MD1_SUPPORT
#define MTK_MD1_SUPPORT	(CONFIG_MTK_MD1_SUPPORT)
#else
#define MTK_MD1_SUPPORT	(5)
#endif

// MD2
#ifdef  CONFIG_MTK_ENABLE_MD2
#define MTK_MD2_EN	(1)
#else
#define MTK_MD2_EN	(0)
#endif

#ifdef CONFIG_MTK_MD2_SUPPORT
#define MTK_MD2_SUPPORT	(CONFIG_MTK_MD2_SUPPORT)
#else
#define MTK_MD2_SUPPORT	(1)
#endif

// MD3
#ifdef  CONFIG_MTK_ENABLE_MD3
#define MTK_MD3_EN	(1)
#else
#define MTK_MD3_EN	(0)
#endif

#ifdef CONFIG_MTK_MD3_SUPPORT
#define MTK_MD3_SUPPORT	(CONFIG_MTK_MD3_SUPPORT)
#else
#define MTK_MD3_SUPPORT	(3)
#endif

// MD5
#ifdef  CONFIG_MTK_ENABLE_MD5
#define MTK_MD5_EN	(1)
#else
#define MTK_MD5_EN	(0)
#endif
#ifdef CONFIG_MTK_MD5_SUPPORT
#define MTK_MD5_SUPPORT	(CONFIG_MTK_MD5_SUPPORT)
#else
#define MTK_MD5_SUPPORT	(3)
#endif


//#define FEATURE_DFO_EN
static fos_item_t ccci_fos_default_setting[] =
{
	{"MTK_ENABLE_MD1",	MTK_MD1_EN},
	{"MTK_MD1_SUPPORT", MTK_MD1_SUPPORT},
	{"MTK_ENABLE_MD2",	MTK_MD2_EN},
	{"MTK_MD2_SUPPORT", MTK_MD2_SUPPORT},
	{"MTK_ENABLE_MD1",	MTK_MD3_EN},
	{"MTK_MD3_SUPPORT", MTK_MD3_SUPPORT},
	{"MTK_ENABLE_MD5",	MTK_MD5_EN},
	{"MTK_MD5_SUPPORT", MTK_MD5_SUPPORT},
};

// Tag value from LK
static unsigned char md_info_tag_val[4];
static unsigned int md_support[MAX_MD_NUM];
static unsigned int meta_md_support[MAX_MD_NUM];

int ccci_get_fo_setting(char item[], unsigned int *val)
{
	char *ccci_name;
	int  ccci_value;
	int  i;

	for (i=0; i<ARRAY_SIZE(ccci_fos_default_setting); i++) {
		ccci_name = ccci_fos_default_setting[i].name;
		ccci_value = ccci_fos_default_setting[i].value;
		if(!strcmp(ccci_name, item)) {
			CCCI_UTIL_ERR_MSG("FO:%s -> %08x\n", item, ccci_value);
			*val = (unsigned int)ccci_value;
			return 0;
		}
	}
	CCCI_UTIL_ERR_MSG("FO:%s not found\n", item);
	return -CCCI_ERR_INVALID_PARAM;
}
//--- LK tag and device tree -----
static unsigned long dt_chosen_node;
static int __init early_init_dt_get_chosen(unsigned long node, const char *uname, int depth, void *data)
{
	if (depth != 1 ||
	    (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
		return 0;
    dt_chosen_node=node;
	return 1;
}

static void lk_meta_tag_info_collect(void)
{
	// Device tree method
	char	*tags;
  int ret;
	ret = of_scan_flat_dt(early_init_dt_get_chosen, NULL);
  if(ret==0){
      CCCI_UTIL_INF_MSG("device node no chosen node\n");
      return;
  }
	tags = (char*)of_get_flat_dt_prop(dt_chosen_node, "atag,mdinfo", NULL);
	if (tags) {
	  tags+=8; // Fix me, Arm64 doesn't have atag defination now
		md_info_tag_val[0] = tags[0];
		md_info_tag_val[1] = tags[1];
		md_info_tag_val[2] = tags[2];
		md_info_tag_val[3] = tags[3];
		CCCI_UTIL_INF_MSG("Get MD info Tags\n");
		CCCI_UTIL_INF_MSG("md_inf[0]=%d\n", md_info_tag_val[0]);
		CCCI_UTIL_INF_MSG("md_inf[1]=%d\n", md_info_tag_val[1]);
		CCCI_UTIL_INF_MSG("md_inf[2]=%d\n", md_info_tag_val[2]);
		CCCI_UTIL_INF_MSG("md_inf[3]=%d\n", md_info_tag_val[3]);
	}else{
        CCCI_UTIL_INF_MSG("atag,mdinfo=NULL\n");
	}
}

//--- META arguments parse -------
static int ccci_parse_meta_md_setting(unsigned char args[])
{
	unsigned char md_active_setting = args[1];
	unsigned char md_setting_flag = args[0];
	int active_id =  -1;

	if(md_active_setting & MD1_EN)
		active_id = MD_SYS1;
	else if(md_active_setting & MD2_EN)
		active_id = MD_SYS2;
	else if(md_active_setting & MD3_EN)
		active_id = MD_SYS3;
	else if(md_active_setting & MD5_EN)
		active_id = MD_SYS5;
	else
		CCCI_UTIL_ERR_MSG("META MD setting not found [%d][%d]\n", args[0], args[1]);

	switch(active_id) 
	{
	case MD_SYS1:
	case MD_SYS2:
	case MD_SYS3:
	case MD_SYS5:
		if(md_setting_flag == MD_2G_FLAG) {
			meta_md_support[active_id] = modem_2g;
		} else if(md_setting_flag == MD_WG_FLAG) {
			meta_md_support[active_id] = modem_wg;
		} else if(md_setting_flag == MD_TG_FLAG) {
			meta_md_support[active_id] = modem_tg;
		} else if(md_setting_flag == MD_LWG_FLAG){
			meta_md_support[active_id] = modem_lwg;
		} else if(md_setting_flag == MD_LTG_FLAG){
			meta_md_support[active_id] = modem_ltg;
		} else if(md_setting_flag & MD_SGLTE_FLAG){
			meta_md_support[active_id] = modem_sglte;
		}
		CCCI_UTIL_INF_MSG("META MD%d to type:%d\n", active_id+1, meta_md_support[active_id]);
		break;
	}
	return 0;	
}

int get_modem_support_cap(int md_id)
{
	if(md_id < MAX_MD_NUM) {
		if(((get_boot_mode()==META_BOOT) || (get_boot_mode()==ADVMETA_BOOT)) && (meta_md_support[md_id]!=0))
			return meta_md_support[md_id];
		else
			return md_support[md_id];
	}
	return -1;
}

int set_modem_support_cap(int md_id, int new_val)
{
	if(md_id < MAX_MD_NUM) {
        if(((get_boot_mode()==META_BOOT) || (get_boot_mode()==ADVMETA_BOOT)) && (meta_md_support[md_id]!=0))
            meta_md_support[md_id] = new_val;
#ifndef MEIZU_OP_CUSTOMIZE
        else
            md_support[md_id] = new_val;
#endif
        return 0;
	}
	return -1;
}

//--- MD setting collect
// modem index is not continuous, so there may be gap in this arrays
static unsigned int md_usage_case = 0;

static unsigned int md_resv_mem_size[MAX_MD_NUM]; // MD ROM+RAM
static unsigned int md_resv_smem_size[MAX_MD_NUM]; // share memory
static unsigned int modem_size_list[MAX_MD_NUM];

static phys_addr_t md_resv_mem_list[MAX_MD_NUM];
static phys_addr_t md_resv_mem_addr[MAX_MD_NUM]; 
static phys_addr_t md_resv_smem_addr[MAX_MD_NUM]; 

int get_md_resv_mem_info(int md_id, phys_addr_t *r_rw_base, unsigned int *r_rw_size, phys_addr_t *srw_base, unsigned int *srw_size)
{
	if(md_id >= MAX_MD_NUM)
		return -1;

	if(r_rw_base!=NULL)
		*r_rw_base = md_resv_mem_addr[md_id];

	if(r_rw_size!=NULL)
		*r_rw_size = md_resv_mem_size[md_id];

	if(srw_base!=NULL)
		*srw_base = md_resv_smem_addr[md_id];

	if(srw_size!=NULL)
		*srw_size = md_resv_smem_size[md_id];

	return 0;
}

unsigned int get_md_smem_align(int md_id)
{
	return 0x4000;
}

unsigned int get_modem_is_enabled(int md_id)
{
	return !!(md_usage_case & (1<<md_id));
}

static void cal_md_settings(int md_id)
{
	unsigned int tmp;
	unsigned int md_en = 0;
	char tmp_buf[30];
	char* node_name = NULL;
	struct device_node *node=NULL; 
	snprintf(tmp_buf,sizeof(tmp_buf),"MTK_ENABLE_MD%d",(md_id+1));
	// MTK_ENABLE_MD*
	if(ccci_get_fo_setting(tmp_buf, &tmp) == 0) {
		if(tmp > 0)
			md_en = 1;
	}
	if(!(md_en && (md_usage_case&(1<<md_id)))){
		CCCI_UTIL_INF_MSG_WITH_ID(md_id,"md%d is disabled\n",(md_id+1));
		return;
	}
	// MTK_MD*_SUPPORT
	snprintf(tmp_buf,sizeof(tmp_buf),"MTK_MD%d_SUPPORT",(md_id+1));
	if(ccci_get_fo_setting(tmp_buf, &tmp) == 0) {
		md_support[md_id] = tmp;
	}
	// MD*_SMEM_SIZE
	if(md_id==MD_SYS1){
		node_name = "mediatek,MDCLDMA";
	}else if(md_id==MD_SYS2){
		node_name= "mediatek,AP_CCIF1";
	}else{
		CCCI_UTIL_ERR_MSG_WITH_ID(md_id,"md%d id is not supported,need to check\n",(md_id+1));
		md_usage_case &= ~(1<<md_id);
		return;
	}
	node = of_find_compatible_node(NULL, NULL, node_name);
	if(node){
		of_property_read_u32(node, "md_smem_size", &md_resv_smem_size[md_id]);
	}else{
		CCCI_UTIL_ERR_MSG_WITH_ID(md_id,"md%d smem size is not set in device tree,need to check\n",(md_id+1));
		md_usage_case &= ~(1<<md_id);
		return;
	}
	// MD ROM start address should be 32M align as remap hardware limitation
	md_resv_mem_addr[md_id] = md_resv_mem_list[md_id];
	/*
	 * for legacy CCCI: make share memory start address to be 2MB align, as share 
	 * memory size is 2MB - requested by MD MPU.
	 * for ECCCI: ROM+RAM size will be align to 1M, and share memory is 2K,
	 * 1M alignment is also 2K alignment.
	 */	
	md_resv_mem_size[md_id]= round_up(modem_size_list[md_id] - md_resv_smem_size[md_id], get_md_smem_align(md_id));
	md_resv_smem_addr[md_id] = md_resv_mem_list[md_id] + md_resv_mem_size[md_id];
	CCCI_UTIL_INF_MSG_WITH_ID(md_id,"md%d modem_total_size=0x%x,md_size=0x%x, smem_size=0x%x\n",(md_id+1),modem_size_list[md_id],md_resv_mem_size[md_id],md_resv_smem_size[md_id]);	
	if ((md_usage_case&(1<<md_id)) && ((md_resv_mem_addr[md_id]&(CCCI_MEM_ALIGN - 1)) != 0))
		CCCI_UTIL_ERR_MSG_WITH_ID(md_id,"md%d memory addr is not 32M align!!!\n",(md_id+1));

	if ((md_usage_case&(1<<md_id)) && ((md_resv_smem_addr[md_id]&(CCCI_SMEM_ALIGN_MD1 - 1)) != 0))
		CCCI_UTIL_ERR_MSG_WITH_ID(md_id,"md%d share memory addr %pa is not 0x%x align!!\n", (md_id+1),&md_resv_smem_addr[md_id], CCCI_SMEM_ALIGN_MD1);

	CCCI_UTIL_INF_MSG_WITH_ID(md_id,"MemStart: 0x%pa, MemSize:0x%08X\n",&md_resv_mem_addr[md_id], md_resv_mem_size[md_id]);
	CCCI_UTIL_INF_MSG_WITH_ID(md_id,"SMemStart: 0x%pa, SMemSize:0x%08X\n",&md_resv_smem_addr[md_id], md_resv_smem_size[md_id]);
}
    
void ccci_md_mem_reserve(void)
{
  CCCI_UTIL_INF_MSG("ccci_md_mem_reserve phased out.\n");
}
#ifdef CONFIG_OF_RESERVED_MEM
#define CCCI_MD1_MEM_RESERVED_KEY "reserve-memory-ccci_md1"
#define CCCI_MD2_MEM_RESERVED_KEY "reserve-memory-ccci_md2"
#include <mach/mtk_memcfg.h>
int ccci_reserve_mem_of_init(struct reserved_mem * rmem, unsigned long node, const char * uname)
{
  phys_addr_t rptr = 0;
  unsigned int rsize= 0;
  int md_id = -1;
  rptr = rmem->base;
  rsize= (unsigned int)rmem->size;	
  if(strcmp(uname, CCCI_MD1_MEM_RESERVED_KEY) == 0){
      md_id = MD_SYS1;
  }
  if(strcmp(uname, CCCI_MD2_MEM_RESERVED_KEY) == 0){
    md_id = MD_SYS2;
  }
  if(md_id<0){
    CCCI_UTIL_ERR_MSG_WITH_ID(md_id,"memory reserve key %s not support\n",uname);  
    return 0;
  }
  CCCI_UTIL_INF_MSG_WITH_ID(md_id,"reserve_mem_of_init, rptr=0x%pa, rsize=0x%x\n", &rptr, rsize);
  md_resv_mem_list[md_id] = rptr;  	
  modem_size_list[md_id]= rsize;
  md_usage_case |= (1<<md_id);
  return 0;
}
RESERVEDMEM_OF_DECLARE(ccci_reserve_mem_md1_init,CCCI_MD1_MEM_RESERVED_KEY,ccci_reserve_mem_of_init);
RESERVEDMEM_OF_DECLARE(ccci_reserve_mem_md2_init,CCCI_MD2_MEM_RESERVED_KEY,ccci_reserve_mem_of_init);
#endif
int ccci_util_fo_init(void)
{
	int idx;
	CCCI_UTIL_INF_MSG("ccci_util_fo_init 0.\n");
	lk_meta_tag_info_collect();
	// Parse META setting
	ccci_parse_meta_md_setting(md_info_tag_val);
	// Calculate memory layout
	for(idx=0;idx<MAX_MD_NUM;idx++)
	{
		cal_md_settings(idx);
	}
	CCCI_UTIL_INF_MSG("ccci_util_fo_init 2.\n");
	return 0;
}