From 53a23b6441c469bcf3914eeaab8d72039550b34b Mon Sep 17 00:00:00 2001
From: Dmitry Ermakov <de@dimer.org.ua>
Date: Wed, 9 Mar 2022 21:14:58 +0300
Subject: [PATCH] Fixes for Ingenic

---
 .../patches/0005-disable-i2c-clk-get.patch    | 537 +-----------------
 .../board/t31/kernel/t31.generic.config       |   2 +-
 .../files/script/load_ingenic                 | 136 ++---
 3 files changed, 78 insertions(+), 597 deletions(-)

diff --git a/br-ext-chip-ingenic/board/t31/kernel/patches/0005-disable-i2c-clk-get.patch b/br-ext-chip-ingenic/board/t31/kernel/patches/0005-disable-i2c-clk-get.patch
index 4a1836db..9a8dbc8d 100644
--- a/br-ext-chip-ingenic/board/t31/kernel/patches/0005-disable-i2c-clk-get.patch
+++ b/br-ext-chip-ingenic/board/t31/kernel/patches/0005-disable-i2c-clk-get.patch
@@ -1,121 +1,9 @@
---- a/mnt/pk/Dev/dvr/openipc/openipc-t31/output/build/linux-3.10.14/arch/mips/xburst/soc-t31/common/clk/clk_cgu.c
-+++ /dev/null
-@@ -1,525 +0,0 @@
--#include <linux/spinlock.h>
--#include <linux/io.h>
--#include <linux/clk.h>
--#include <linux/delay.h>
--#include <linux/err.h>
--#include <soc/cache.h>
--#include <soc/cpm.h>
--#include <soc/base.h>
--#include <soc/extal.h>
--#include <soc/ddr.h>
--#include "clk.h"
--static DEFINE_SPINLOCK(cpm_cgu_lock);
--struct clk_selectors {
--	unsigned int route[4];
--};
--enum {
--	SELECTOR_A = 0,
--	SELECTOR_2,
--	SELECTOR_C,
--	SELECTOR_3,
--	SELECTOR_MSC_MUX,
--	SELECTOR_F,
--	SELECTOR_H
--};
--const struct clk_selectors selector[] = {
--#define CLK(X)  CLK_ID_##X
--/*
-- *         bit31,bit30
-- *          0   , 0       STOP
-- *          0   , 1       SCLKA
-- *          1   , 0       MPLL
-- *          1   , 1       INVALID
-- */
--	[SELECTOR_A].route = {CLK(STOP),CLK(SCLKA),CLK(MPLL),CLK(INVALID)},
--/*
-- *         bit31,bit30
-- *          0   , x       SCLKA
-- *          0   , x       SCLKA
-- *          1   , x       MPLL
-- *          1   , x       MPLL
-- */
--	[SELECTOR_2].route  = {CLK(SCLKA),CLK(SCLKA),CLK(MPLL),CLK(MPLL)},
--/*
-- *         bit31,bit30
-- *          0   , 0       EXT1
-- *          0   , 1       EXT1
-- *          1   , 0       SCLKA
-- *          1   , 1       MPLL
-- */
--	[SELECTOR_C].route = {CLK(EXT1) ,CLK(EXT1),CLK(SCLKA),CLK(MPLL)},
--/*
-- *         bit31,bit30
-- *          0   , 0       SCLKA
-- *          0   , 1       MPLL
-- *          1   , 0       VPLL
-- *          1   , 1       VPLL
-- */
--	[SELECTOR_3].route = {CLK(SCLKA),CLK(MPLL),CLK(VPLL),CLK(VPLL)},
--
--/*
-- *         bit31,bit30
-- *          0   , 0       MSC_MUX
-- *          0   , 1       MSC_MUX
-- *          1   , 0       MSC_MUX
-- *          1   , 1       MSC_MUX
-- */
--	[SELECTOR_MSC_MUX].route = {CLK(SCLKA),CLK(SCLKA),CLK(MPLL),CLK(MPLL)},
--/*
-- *         bit31,bit30
-- *          0   , x       SCLKA
-- *          0   , x       SCLKA
-- *          1   , x       OTGPHY
-- *          1   , x       OTGPHY
-- */
--	[SELECTOR_F].route = {CLK(SCLKA),CLK(SCLKA),CLK(OTGPHY),CLK(OTGPHY)},
--	/*
--	 *		   bit31,bit30
--	 *			0	, 0 	  SCLKA
--	 *			0	, 1 	  MPLL
--	 *			1	, 0 	  VPLL
--	 *			1	, 1 	  INVALID
--	 */
--	[SELECTOR_H].route = {CLK(SCLKA),CLK(MPLL),CLK(VPLL),CLK(INVALID)},
--
--#undef CLK
--};
--
--#define IS_CGU_CLK(x) (x&CLK_FLG_CGU)
--
--struct cgu_clk {
--	/* off: reg offset. ce_busy_stop: CE offset  + 1 is busy. coe : coe for div .div: div bit width */
--	/* ext: extal/pll sel bit. sels: {select} */
--	int off,ce_busy_stop,coe,div,sel,cache;
--};
--static struct cgu_clk cgu_clks[] = {
--	[CGU_DDR] = 	{ CPM_DDRCDR, 27, 1, 4, SELECTOR_A},
--	[CGU_VPU] = 	{ CPM_VPUCDR, 27, 1, 4, SELECTOR_H},
--	[CGU_MACPHY] = 	{ CPM_MACCDR, 27, 1, 8, SELECTOR_H},
--	[CGU_RSA] = 	{ CPM_RSACDR, 27, 1, 4, SELECTOR_H},
--	[CGU_LPC] = 	{ CPM_LPCDR,  26, 1, 8, SELECTOR_H},
--	[CGU_MSC_MUX]=	{ CPM_MSC0CDR, 27, 2, 0, SELECTOR_MSC_MUX},/*TODO:what does it mean?*/
--	[CGU_MSC0] = 	{ CPM_MSC0CDR, 27, 2, 8, SELECTOR_H},
--	[CGU_MSC1] = 	{ CPM_MSC1CDR, 27, 2, 8, SELECTOR_H},
--	[CGU_I2S_SPK] = 	{ CPM_I2SSPKCDR, 29, 0, 20, SELECTOR_H}, /*TODO:check*/
--	[CGU_I2S_MIC] = 	{ CPM_I2SMICCDR, 29, 0, 20, SELECTOR_H}, /*TODO:check*/
--	[CGU_SSI] = 	{ CPM_SSICDR, 26, 1, 8, SELECTOR_H},
--	[CGU_CIM] =     { CPM_CIMCDR, 27, 1, 8, SELECTOR_H},
--	[CGU_ISP] = 	{ CPM_ISPCDR, 27, 1, 4, SELECTOR_H},
--};
--
--static unsigned long cgu_get_rate(struct clk *clk)
--{
--	unsigned long x;
--	unsigned long flags;
--	int no = CLK_CGU_NO(clk->flags);
+--- a/arch/mips/xburst/soc-t31/common/clk/clk_cgu.c
++++ b/arch/mips/xburst/soc-t31/common/clk/clk_cgu.c
+@@ -113,18 +113,18 @@
+ 	unsigned long x;
+ 	unsigned long flags;
+ 	int no = CLK_CGU_NO(clk->flags);
 -
 -	if (!(strcmp(clk->name, "cgu_i2s_spk")) || !(strcmp(clk->name, "cgu_i2s_mic"))) {
 -		unsigned int reg_val = 0;
@@ -128,401 +16,18 @@
 -				__func__, clk->parent->rate, clk->rate, m, n, cpm_inl(cgu_clks[no].off));
 -		return (clk->parent->rate * m) / n;
 -	}
--
--	if(clk->parent == get_clk_from_id(CLK_ID_EXT1))
--		return clk->parent->rate;
--	if(no == CGU_MSC_MUX)
--		return clk->parent->rate;
--	if(cgu_clks[no].div == 0)
--		return clk_get_rate(clk->parent);
--	spin_lock_irqsave(&cpm_cgu_lock,flags);
--	x = cpm_inl(cgu_clks[no].off);
--	x &= (1 << cgu_clks[no].div) - 1;
--	x = (x + 1) * cgu_clks[no].coe;
--
--	spin_unlock_irqrestore(&cpm_cgu_lock,flags);
--	return clk->parent->rate / x;
--}
--static int cgu_enable(struct clk *clk,int on)
--{
--	int no = CLK_CGU_NO(clk->flags);
--	int reg_val;
--	int ce,stop,busy;
--	int prev_on;
--	unsigned int mask;
--	unsigned long flags;
--	if(no == CGU_MSC_MUX)
--		return 0;
--
--	spin_lock_irqsave(&cpm_cgu_lock,flags);
--
--	if (!(strcmp(clk->name, "cgu_i2s_spk")) || !(strcmp(clk->name, "cgu_i2s_mic"))) {
--		reg_val = cpm_inl(cgu_clks[no].off);
--		reg_val |= (1 << 29);
--		cpm_outl(reg_val,cgu_clks[no].off);
--		printk(KERN_DEBUG"%s,%s reg val = 0x%08x\n",
--				__func__, clk->name, cpm_inl(cgu_clks[no].off));
--		goto cgu_enable_finish;
--	}
--
--	reg_val = cpm_inl(cgu_clks[no].off);
--	stop = cgu_clks[no].ce_busy_stop;
--	busy = stop + 1;
--	ce = stop + 2;
--	prev_on = !(reg_val & (1 << stop));
--	mask = (1 << cgu_clks[no].div) - 1;
--	if(prev_on && on)
--		goto cgu_enable_finish;
--	if((!prev_on) && (!on))
--		goto cgu_enable_finish;
--	if(on){
--		if(cgu_clks[no].cache && ((cgu_clks[no].cache & mask) != (reg_val & mask))) {
--			unsigned int x = cgu_clks[no].cache;
--			x = (x & ~(0x1 << stop)) | (0x1 << ce);
--			cpm_outl(x,cgu_clks[no].off);
--			while(cpm_test_bit(busy,cgu_clks[no].off)) {
--				printk("wait stable.[%d][%s]\n",__LINE__,clk->name);
--			}
--			cpm_clear_bit(ce, cgu_clks[no].off);
--			x &= (1 << cgu_clks[no].div) - 1;
--			x = (x + 1) * cgu_clks[no].coe;
--			clk->rate = clk->parent->rate / x;
--			cgu_clks[no].cache = 0;
--		} else {
--			reg_val |= (1 << ce);
--			reg_val &= ~(1 << stop);
--			cpm_outl(reg_val,cgu_clks[no].off);
--			cpm_clear_bit(ce,cgu_clks[no].off);
--		}
--	} else {
--		reg_val |= (1 << ce);
--		reg_val |= ( 1<< stop);
--		cpm_outl(reg_val,cgu_clks[no].off);
--		cpm_clear_bit(ce,cgu_clks[no].off);
--	}
--
--cgu_enable_finish:
--	spin_unlock_irqrestore(&cpm_cgu_lock,flags);
--	return 0;
--}
--
--static int cgu_set_rate(struct clk *clk, unsigned long rate)
--{
--	unsigned long x,tmp;
--	int i,no = CLK_CGU_NO(clk->flags);
--	int ce,stop,busy;
--
--	unsigned int reg_val, mask;
--	unsigned long flags;
--	unsigned long long m, n;
--	unsigned long long m_mul;
--	unsigned long long tmp_value;
--	unsigned long long tmp_rate = (unsigned long long)rate;
--	unsigned char sig = 0;
--	unsigned long long max = 0xfffff;
--	unsigned long long min = 1;
--	/* CLK_ID_CGU_I2S could be exten clk. */
--	//if(clk->parent == get_clk_from_id(CLK_ID_EXT1) && (clk->CLK_ID != CLK_ID_CGU_I2S))
--	//    //return -1;
--	//
--	if(no == CGU_MSC_MUX)
--		return -1;
--	if (!(strcmp(clk->name, "cgu_i2s_spk")) || !(strcmp(clk->name, "cgu_i2s_mic"))) {
--		for(m=1;m<=0x1ff;m++)
--		{
--			m_mul = clk->parent->rate * m;
--			max = 0xfffff;
--			min = 1;
--			while(max >= min){
--				n = (max + min) >> 1;
--				tmp_value = (unsigned long long)(n*tmp_rate);
--				if( m_mul == tmp_value )
--				{
--					sig = 1;
--					break;
--				}else if (tmp_value > m_mul)
--					max = n - 1;
--				else
--					min = n + 1;
--			}
--			if( sig )
--			{
--				clk->rate = rate;
--				break;
--			}
--		}
--
--		reg_val = cpm_inl(cgu_clks[no].off) & 0xf0000000;
--		reg_val |= (m << 20) | (n << 0);
--		cpm_outl(reg_val,cgu_clks[no].off);
--		printk(KERN_DEBUG"%s, parent = %ld, rate = %ld, n = %lld, reg val = 0x%08x\n",
--				__func__, clk->parent->rate, clk->rate, n, cpm_inl(cgu_clks[no].off));
--		return 0;
--	}
--	spin_lock_irqsave(&cpm_cgu_lock,flags);
--	mask = (1 << cgu_clks[no].div) - 1;
--	tmp = clk->parent->rate / cgu_clks[no].coe;
--	for (i = 1; i <= mask+1; i++) {
--		if ((tmp / i) <= rate)
--			break;
--	}
--	i--;
--	if(i > mask)
--		i = mask;
--	reg_val = cpm_inl(cgu_clks[no].off);
--	x = reg_val & ~mask;
--	x |= i;
--	stop = cgu_clks[no].ce_busy_stop;
--	busy = stop + 1;
--	ce = stop + 2;
--	if(x & (1 << stop)) {
--		if (cgu_clks[no].cache) {
--			cgu_clks[no].cache &= ~mask;
--			cgu_clks[no].cache |= i;
--		} else {
--			cgu_clks[no].cache = x;
--		}
--		clk->rate = tmp  / (i + 1);
--	}
--	else if((mask & reg_val) != i){
--
--		x = (x & ~(0x1 << stop)) | (0x1 << ce);
--		cpm_outl(x, cgu_clks[no].off);
--		while(cpm_test_bit(busy,cgu_clks[no].off))
--			printk("wait stable.[%d][%s]\n",__LINE__,clk->name);
--		x &= ~(1 << ce);
--		cpm_outl(x, cgu_clks[no].off);
--		cgu_clks[no].cache = 0;
--		clk->rate = tmp  / (i + 1);
--	}
--	spin_unlock_irqrestore(&cpm_cgu_lock,flags);
--	return 0;
--}
--
--static struct clk * cgu_get_parent(struct clk *clk)
--{
--	unsigned int no,cgu,idx,pidx;
--
--	no = CLK_CGU_NO(clk->flags);
--	if(!(strcmp(clk->name, "cgu_i2s_mic"))){
--		/* the operation uses for t31, because that the bits[30~31] of 0x10000084 is readonly */
--		cgu = *(volatile unsigned int*)(0xb0000070); // the register is i2s speaker pll.
--	}else{
--		cgu = cpm_inl(cgu_clks[no].off);
--	}
--	idx = cgu >> 30;
--	pidx = selector[cgu_clks[no].sel].route[idx];
--	if (pidx == CLK_ID_STOP || pidx == CLK_ID_INVALID)
--		return NULL;
--
--	return get_clk_from_id(pidx);
--}
--
--static int cgu_set_parent(struct clk *clk, struct clk *parent)
--{
--	int i,tmp;
--	int no = CLK_CGU_NO(clk->flags);
--	unsigned int reg_val,cgu,mask;
--	int ce,stop,busy;
--	unsigned long flags;
--	stop = cgu_clks[no].ce_busy_stop;
--	busy = stop + 1;
--	ce = stop + 2;
--	mask = (1 << cgu_clks[no].div) - 1;
--
--	for(i = 0;i < 4;i++) {
--		if(selector[cgu_clks[no].sel].route[i] == get_clk_id(parent)){
--			break;
--		}
--	}
--	if(i >= 4)
--		return -EINVAL;
--	spin_lock_irqsave(&cpm_cgu_lock,flags);
--	cgu = cpm_inl(cgu_clks[no].off);
--	reg_val = cgu;
--	if(cgu_clks[no].sel == SELECTOR_2) {
--		if(i == 0)
--			cgu &= ~(1 << 31);
--		else
--			cgu |= (1 << 31);
--	}else {
--		cgu &= ~(3 << 30);
--		cgu |= i << 30;
--	}
--
--	tmp = parent->rate / cgu_clks[no].coe;
--	for (i = 1; i <= mask+1; i++) {
--		if ((tmp / i) <= clk->rate)
--			break;
--	}
--	i--;
--	mask = (1 << cgu_clks[no].div) - 1;
--	cgu = (cgu & ~(0x1 << stop)) | (0x1 << ce);
--	cgu = cgu & ~mask;
--	cgu |= i;
--
--	if(reg_val & (1 << stop))
--		cgu_clks[no].cache = cgu;
--	else if((mask & reg_val) != i){
--		cpm_outl(cgu, cgu_clks[no].off);
--		while(cpm_test_bit(busy,cgu_clks[no].off))
--			printk("wait stable.[%d][%s]\n",__LINE__,clk->name);
--		cgu &= ~(1 << ce);
--		cpm_outl(cgu, cgu_clks[no].off);
--		cgu_clks[no].cache = 0;
--	}
--
--	clk->parent = parent;
--
--	spin_unlock_irqrestore(&cpm_cgu_lock,flags);
--	return 0;
--}
--
--static int cgu_is_enabled(struct clk *clk) {
--	int no = CLK_CGU_NO(clk->flags);
--	int stop;
--	stop = cgu_clks[no].ce_busy_stop;
--	return !(cpm_inl(cgu_clks[no].off) & (1 << stop));
--}
--static struct clk_ops clk_cgu_ops = {
--	.enable	= cgu_enable,
--	.get_rate = cgu_get_rate,
--	.set_rate = cgu_set_rate,
--	.get_parent = cgu_get_parent,
--	.set_parent = cgu_set_parent,
--};
--
--#define CONVERT_DDR_RATE (50 * 1000 * 1000)
--#define UP_DIV 1
--#define DOWN_DIV 2
--#define REG32(x) *(volatile unsigned int *)(x)
--
--#define OFF_TDR         (0x00)
--#define OFF_LCR         (0x0C)
--#define OFF_LSR         (0x14)
--
--#define LSR_TDRQ        (1 << 5)
--#define LSR_TEMT        (1 << 6)
--
--#define U1_IOBASE (UART1_IOBASE + 0xa0000000)
--#define TCSM_PCHAR(x)							\
--	*((volatile unsigned int*)(U1_IOBASE+OFF_TDR)) = x;		\
--	while ((*((volatile unsigned int*)(U1_IOBASE + OFF_LSR)) & (LSR_TDRQ | LSR_TEMT)) != (LSR_TDRQ | LSR_TEMT))
--
--static inline void serial_put_hex(unsigned int x) {
--	int i;
--	unsigned int d;
--	for(i = 7;i >= 0;i--) {
--		d = (x  >> (i * 4)) & 0xf;
--		if(d < 10) d += '0';
--		else d += 'A' - 10;
--		TCSM_PCHAR(d);
--	}
--}
--static int ddr_set_rate(struct clk *clk, unsigned long rate)
--{
--	unsigned int ddr_cgu = cpm_inl(CPM_DDRCDR);
--	unsigned int div = ddr_cgu & 0xf;
--	unsigned int up = 0;
--	unsigned int ret = 0;
--	unsigned long flags,fail;
--	printk("aaaaaaaaaaaaaaaaa\n");
--	if(rate > CONVERT_DDR_RATE){
--		if(clk->rate <= CONVERT_DDR_RATE) {
--			up = UP_DIV;
--			div >>= 1;
--			clk->rate = 100 * 1000 * 1000;
--		}
--	}else{
--		if(clk->rate > CONVERT_DDR_RATE) {
--			up = DOWN_DIV;
--			div <<= 1;
--			clk->rate = 50 * 1000 * 1000;
--		}
--	}
--	printk("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa div= %d\n",div);
--	spin_lock_irqsave(&cpm_cgu_lock,flags);
--	cache_prefetch(DDRCLAB1,200);
--	fast_iob();
--DDRCLAB1:
--	REG32(0xb3012068) = 0;
--
--	ddr_cgu |= (1 << 29) | (1 << 26);
--	ddr_cgu &= ~(1 << 24);
--	ddr_cgu &= ~0xf;
--	TCSM_PCHAR('1');
--	cpm_outl(ddr_cgu,CPM_DDRCDR);
--	TCSM_PCHAR('a');
--	ddr_cgu |= (1 << 25);
--	ddr_cgu |= div;
--	TCSM_PCHAR('2');
--	cpm_outl(ddr_cgu,CPM_DDRCDR);
--	fail = 0;
--	TCSM_PCHAR('3');
--	while(cpm_inl(CPM_DDRCDR) & 1 << 28) {
--		serial_put_hex(cpm_inl(CPM_DDRCDR));
--		TCSM_PCHAR('\r');
--		TCSM_PCHAR('\n');
--	}
--	TCSM_PCHAR('4');
--	cpm_clear_bit(25,CPM_DDRCDR);
--	REG32(0xb3012068) = 0xf0000100;
--        fail = REG32(0xa0000000);
--	if(cpm_inl(CPM_DDRCDR) & 1 << 24) {
--		printk("fail!\n");
--	}else
--		printk("ok!\n");
--
--	//printk("REG32(0xb301206c) = %x\n",REG32(0xb301206c));
--
--	spin_unlock_irqrestore(&cpm_cgu_lock,flags);
--	return ret;
--
--}
--static struct clk_ops clk_ddr_ops = {
--	.enable	= cgu_enable,
--	.get_rate = cgu_get_rate,
--	.set_rate = ddr_set_rate,
--	.get_parent = cgu_get_parent,
--	.set_parent = cgu_set_parent,
--
--};
--void __init init_cgu_clk(struct clk *clk)
--{
--	int no;
--	int id;
--	//printk("REG32(0xb3012088) = %x\n",REG32(0xb3012088));
--
--
--	if (clk->flags & CLK_FLG_PARENT) {
--		id = CLK_PARENT(clk->flags);
--		clk->parent = get_clk_from_id(id);
--	} else {
--		clk->parent = cgu_get_parent(clk);
--	}
--	no = CLK_CGU_NO(clk->flags);
--	cgu_clks[no].cache = 0;
--	clk->rate = cgu_get_rate(clk);
--	if(cgu_is_enabled(clk)) {
--		clk->flags |= CLK_FLG_ENABLE;
--	}
--
--	if(no == CGU_MSC_MUX)
--		clk->ops = NULL;
--	else if(no == CGU_DDR){
--		clk->ops = &clk_ddr_ops;
--		if(ddr_readl(DDRP_PIR) & DDRP_PIR_DLLBYP){  /*TODO:zm*/
--                    /**
--                     * DDR request cpm to stop clk
--                     * (0x9 << 28) DDR_CLKSTP_CFG (0x13012068)
--                     * CPM response ddr stop clk request (1 << 26) (0x1000002c)
--                     */
--                    cpm_set_bit(26,CPM_DDRCDR);
--                    REG32(0xb3012068) |= 0x9 << 28;
--                }
--		REG32(0xb3012088) |= 4 << 16;
--	}
--	else
--		clk->ops = &clk_cgu_ops;
--
--}
++// FixMe: This leads to hang during boot with GCC>5.5.0
++//	if (!(strcmp(clk->name, "cgu_i2s_spk")) || !(strcmp(clk->name, "cgu_i2s_mic"))) {
++//		unsigned int reg_val = 0;
++//		int m = 0, n = 0;
++//		reg_val = cpm_inl(cgu_clks[no].off) & 0xf0000000;
++//		n = reg_val & 0xfffff;
++//		m = (reg_val >> 20) & 0x1ff;
++//
++//		printk(KERN_DEBUG"%s, parent = %ld, rate = %ld, m = %d, n = %d, reg val = 0x%08x\n",
++//				__func__, clk->parent->rate, clk->rate, m, n, cpm_inl(cgu_clks[no].off));
++//		return (clk->parent->rate * m) / n;
++//	}
+ 
+ 	if(clk->parent == get_clk_from_id(CLK_ID_EXT1))
+ 		return clk->parent->rate;
diff --git a/br-ext-chip-ingenic/board/t31/kernel/t31.generic.config b/br-ext-chip-ingenic/board/t31/kernel/t31.generic.config
index 3ceda481..29cbf6f5 100644
--- a/br-ext-chip-ingenic/board/t31/kernel/t31.generic.config
+++ b/br-ext-chip-ingenic/board/t31/kernel/t31.generic.config
@@ -961,7 +961,7 @@ CONFIG_SERIAL_JZ47XX_UART1=y
 CONFIG_I2C=y
 CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_COMPAT=y
-# CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_CHARDEV=y
 # CONFIG_I2C_MUX is not set
 CONFIG_I2C_HELPER_AUTO=y
 CONFIG_I2C_ALGOBIT=y
diff --git a/general/package/ingenic-osdrv-t31/files/script/load_ingenic b/general/package/ingenic-osdrv-t31/files/script/load_ingenic
index 20f62ae2..bf2350d4 100755
--- a/general/package/ingenic-osdrv-t31/files/script/load_ingenic
+++ b/general/package/ingenic-osdrv-t31/files/script/load_ingenic
@@ -2,108 +2,84 @@
 
 KMOD_PATH=/lib/modules/3.10.14__isvp_swan_1.0__/ingenic
 
-PARAMS=$(cat <<-EOF
-sensor:sc2232
-isp_param:isp_clk=100000000
+echo 1 >/proc/sys/vm/overcommit_memory
 
-sensor:gc2053
-sensor_param:sensor_max_fps=25 data_interface=1
-isp_param:isp_clk=125000000
-
-sensor:sc2135
-isp_param:isp_clk=125000000
-
-sensor:imx307
-isp_param:isp_clk=125000000 ispw=1920 isph=1080 isptop=20 ispleft=12
-
-sensor:sc2335
-isp_param:isp_clk=125000000 ispw=1920 isph=1080
-
-EOF
-)
-
-echo 1 > /proc/sys/vm/overcommit_memory
-
-check_return()
-{
-	if [ $? -ne 0 ] ;then
-		echo err: $1
-		echo exit
-		exit
-	fi
+check_return() {
+    if [ $? -ne 0 ]; then
+        echo err: $1
+        echo exit
+        exit
+    fi
 }
 
-lsmod | grep "avpu" > /dev/null
+lsmod | grep "avpu" >/dev/null
 if [ $? -ne 0 ]; then
-	insmod ${KMOD_PATH/%\//}/avpu.ko
-	check_return "insmod avpu"
+    insmod ${KMOD_PATH/%\//}/avpu.ko clk_name='vpll' avpu_clk=400000000
+    check_return "insmod avpu"
 fi
 
-lsmod | grep "sinfo" > /dev/null
-if [ $? -ne 0 ] ;then
-	insmod ${KMOD_PATH/%\//}/sinfo.ko
-	check_return "insmod sinfo"
+lsmod | grep "sinfo" >/dev/null
+if [ $? -ne 0 ]; then
+    insmod ${KMOD_PATH/%\//}/sinfo.ko
+    check_return "insmod sinfo"
 fi
 
 echo 1 >/proc/jz/sinfo/info
 check_return "start sinfo"
 
-SENSOR_INFO=`cat /proc/jz/sinfo/info`
+SENSOR_INFO=$(cat /proc/jz/sinfo/info)
 check_return "get sensor type"
 
 SENSOR=${SENSOR_INFO#*:}
-ISP_PARAM="isp_clk=125000000"
-SENSOR_PARAM=
-START=0
-echo ${PARAMS} | while read str
-do
-	#echo $str
-	#ignore blank line
-	if [ "$str" = "" ];then
-		continue
-	fi
-	name=${str%:*}
-	value=${str#*:}
-	if [ ${START} = 0 ];then
-		if [ "$value" = "$SENSOR" ];then
-			START=1
-		fi
-	else
-		case ${name} in
-			"isp_param")
-				ISP_PARAM=${value}
-				;;
-			"sensor_param")
-				SENSOR_PARAM=${value}
-				;;
-			*)
-				break;
-				;;
-		esac
-	fi
-done
+
+case ${SENSOR} in
+    "sc2232")
+        ISP_PARAM="isp_clk=125000000"
+        SENSOR_PARAM=""
+    ;;
+    "sc2135")
+        ISP_PARAM="isp_clk=100000000"
+        SENSOR_PARAM=""
+    ;;
+    "sc2335")
+        ISP_PARAM="isp_clk=100000000 isp_ch0_pre_dequeue_time=20 isp_ch0_pre_dequeue_interrupt_process=0 isp_memopt=1"
+        SENSOR_PARAM=""
+    ;;
+    "gc2053")
+        ISP_PARAM="isp_clk=125000000"
+        SENSOR_PARAM="sensor_max_fps=25 data_interface=1"
+    ;;
+    "imx307")
+        ISP_PARAM="isp_clk=125000000 ispw=1920 isph=1080 isptop=20 ispleft=12"
+        SENSOR_PARAM=""
+    ;;
+    *)
+		ISP_PARAM="isp_clk=125000000"
+		SENSOR_PARAM=""
+        break
+    ;;
+esac
 
 echo --------------------
 echo "ISP_PARAM: ${ISP_PARAM}"
 echo "SENSOR: ${SENSOR}"
 echo "SENSOR_PARAM: ${SENSOR_PARAM}"
+echo --------------------
 
-lsmod | grep "tx_isp" > /dev/null
-if [ $? -ne 0 ] ;then
-	insmod ${KMOD_PATH/%\//}/tx-isp-t31.ko  ${ISP_PARAM}
-	check_return "insmod isp drv"
+lsmod | grep "tx_isp" >/dev/null
+if [ $? -ne 0 ]; then
+    insmod ${KMOD_PATH/%\//}/tx-isp-t31.ko ${ISP_PARAM}
+    check_return "insmod isp drv"
 fi
 
-lsmod | grep "audio" > /dev/null
-if [ $? -ne 0 ] ;then
-        insmod ${KMOD_PATH/%\//}/audio.ko
-        check_return "insmod audio"
+lsmod | grep "audio" >/dev/null
+if [ $? -ne 0 ]; then
+    insmod ${KMOD_PATH/%\//}/audio.ko
+    check_return "insmod audio"
 fi
 
-lsmod | grep ${SENSOR} > /dev/null
-if [ $? -ne 0 ] ;then
-	insmod ${KMOD_PATH/%\//}/sensor_${SENSOR}_t31.ko ${SENSOR_PARAM}
-	check_return "insmod sensor drv"
+lsmod | grep ${SENSOR} >/dev/null
+if [ $? -ne 0 ]; then
+    insmod ${KMOD_PATH/%\//}/sensor_${SENSOR}_t31.ko ${SENSOR_PARAM}
+    check_return "insmod sensor drv"
 fi
-
-