91 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			91 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0+
 | |
| /*
 | |
|  * Copyright (C) 2020, Novatek Inc. - All Rights Reserved
 | |
|  */
 | |
| 
 | |
| #include <asm/io.h>
 | |
| #include "common.h"
 | |
| #include <errno.h>
 | |
| #include <malloc.h>
 | |
| #include <asm/arch/IOAddress.h>
 | |
| #include <asm/arch/hardware.h>
 | |
| #include <asm/nvt-common/nvt_types.h>
 | |
| #include <asm/nvt-common/nvt_common.h>
 | |
| #include <asm/nvt-common/rcw_macro.h>
 | |
| #include <linux/libfdt.h>
 | |
| 
 | |
| #define PAD_GETREG(ofs)         readl((void __iomem *)(IOADDR_PAD_REG_BASE + ofs))
 | |
| #define PAD_SETREG(ofs,value)   writel(value, (void __iomem *)(IOADDR_PAD_REG_BASE + ofs))
 | |
| 
 | |
| #define PAD_PIN_NOT_EXIST       (64) // For backward compatible
 | |
| #define PAD_PUPD0_REG_OFS       0x00
 | |
| 
 | |
| static ER pad_set_pull_updown(u32 pin, u32 pulltype)
 | |
| {
 | |
| 	UINT dw_offset, bit_offset;
 | |
| 	REGVALUE    reg_data;
 | |
| 
 | |
| 	if(pin == PAD_PIN_NOT_EXIST) {
 | |
| 		pr_err("Not Existed Pad Pin\r\n");
 | |
| 		return E_NOEXS;
 | |
| 	}
 | |
| 
 | |
| 	bit_offset = pin & 0x1F;
 | |
| 	dw_offset = (pin >> 5);
 | |
| 
 | |
| 	reg_data = PAD_GETREG(PAD_PUPD0_REG_OFS + (dw_offset << 2));
 | |
| 	reg_data &= ~(3 << bit_offset);
 | |
| 	PAD_SETREG(PAD_PUPD0_REG_OFS + (dw_offset << 2), reg_data);
 | |
| 	reg_data |= (pulltype << bit_offset);
 | |
| 	PAD_SETREG(PAD_PUPD0_REG_OFS + (dw_offset << 2), reg_data);
 | |
| 	return E_OK;
 | |
| }
 | |
| 
 | |
| static int fdt_node_check_pad_config(const void *fdt, int nodeoffset)
 | |
| {
 | |
| 	const void *prop;
 | |
| 	int len;
 | |
| 
 | |
| 	prop = fdt_getprop(fdt, nodeoffset, "pad_config", &len);
 | |
| 
 | |
| 	if (prop)
 | |
| 		return len;
 | |
| 	else
 | |
| 		return 0;
 | |
| }
 | |
| 
 | |
| static void fdt_node_offset_by_pad_config(const void *fdt, int startoffset)
 | |
| {
 | |
| 	int offset;
 | |
| 	int ndepth = 0;
 | |
| 
 | |
| 	for (offset = fdt_next_node(fdt, startoffset, &ndepth);
 | |
| 		(offset >= 0) && (ndepth > 0);
 | |
| 		offset = fdt_next_node(fdt, offset, &ndepth)) {
 | |
| 		if (ndepth == 1) {
 | |
| 			if (fdt_node_check_pad_config(fdt, offset) > 0) {
 | |
| 				u32 *cell = NULL;
 | |
| 				cell = (u32*)fdt_getprop((const void*)fdt, offset, "pad_config", NULL);
 | |
| 				if (pad_set_pull_updown(__be32_to_cpu(cell[2]), __be32_to_cpu(cell[3]))) {
 | |
| 					pr_err("failed to set pin 0x%x pull value 0x%x\n", __be32_to_cpu(cell[2]), __be32_to_cpu(cell[3]));
 | |
| 					break;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| void nvt_pad_init(void)
 | |
| {
 | |
| 	ulong fdt_addr = nvt_readl((ulong)nvt_shminfo_boot_fdt_addr);
 | |
| 	int nodeoffset;
 | |
| 	char path[20] = {0};
 | |
| 
 | |
| 	sprintf(path,"/top@%x",IOADDR_TOP_REG_BASE);
 | |
| 
 | |
| 	nodeoffset = fdt_path_offset((const void*)fdt_addr, path);
 | |
| 
 | |
| 	fdt_node_offset_by_pad_config((const void*)fdt_addr, nodeoffset);
 | |
| }
 | 
