blob: e2934c2d2396086c4727c81d0e86872490ef22fc [file] [log] [blame]
/* Himax Android Driver Sample Code for HMX83100 chipset
*
* Copyright (C) 2015 Himax Corporation.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include "himax_ic.h"
const struct firmware *i_TP_CRC_FW_128K;
const struct firmware *i_TP_CRC_FW_64K;
const struct firmware *i_TP_CRC_FW_124K;
const struct firmware *i_TP_CRC_FW_60K;
unsigned long FW_VER_MAJ_FLASH_ADDR;
unsigned long FW_VER_MAJ_FLASH_LENG;
unsigned long FW_VER_MIN_FLASH_ADDR;
unsigned long FW_VER_MIN_FLASH_LENG;
unsigned long CFG_VER_MAJ_FLASH_ADDR;
unsigned long CFG_VER_MAJ_FLASH_LENG;
unsigned long CFG_VER_MIN_FLASH_ADDR;
unsigned long CFG_VER_MIN_FLASH_LENG;
unsigned char IC_TYPE;
unsigned char IC_CHECKSUM;
/*0:Running, 1:Stop, 2:I2C Fail*/
int himax_hand_shaking(struct i2c_client *client)
{
int ret, result;
uint8_t hw_reset_check[1];
uint8_t hw_reset_check_2[1];
uint8_t buf0[2];
uint8_t IC_STATUS_CHECK = 0xAA;
memset(hw_reset_check, 0x00, sizeof(hw_reset_check));
memset(hw_reset_check_2, 0x00, sizeof(hw_reset_check_2));
buf0[0] = 0xF2;
if (IC_STATUS_CHECK == 0xAA) {
buf0[1] = 0xAA;
IC_STATUS_CHECK = 0x55;
} else {
buf0[1] = 0x55;
IC_STATUS_CHECK = 0xAA;
}
ret = i2c_himax_master_write(client,
buf0, 2, HIMAX_I2C_RETRY_TIMES);
if (ret < 0) {
E("[Himax]:write 0xF2 failed line: %d\n", __LINE__);
goto work_func_send_i2c_msg_fail;
}
msleep(50);
buf0[0] = 0xF2;
buf0[1] = 0x00;
ret = i2c_himax_master_write(client,
buf0, 2, HIMAX_I2C_RETRY_TIMES);
if (ret < 0) {
E("[Himax]:write 0x92 failed line: %d\n", __LINE__);
goto work_func_send_i2c_msg_fail;
}
usleep_range(1999, 2000);
ret = i2c_himax_read(client, 0xD1,
hw_reset_check, 1, HIMAX_I2C_RETRY_TIMES);
if (ret < 0) {
E("[Himax]:i2c_himax_read 0xD1 failed line: %d\n", __LINE__);
goto work_func_send_i2c_msg_fail;
}
if (IC_STATUS_CHECK != hw_reset_check[0]) {
usleep_range(1999, 2000);
ret = i2c_himax_read(client, 0xD1,
hw_reset_check_2, 1, HIMAX_I2C_RETRY_TIMES);
if (ret < 0) {
E("[Himax]:i2c_himax_read 0xD1 failed line: %d\n",
__LINE__);
goto work_func_send_i2c_msg_fail;
}
if (hw_reset_check[0] == hw_reset_check_2[0])
result = 1;
else
result = 0;
} else {
result = 0;
}
return result;
work_func_send_i2c_msg_fail:
return 2;
}
void himax_diag_register_set(struct i2c_client *client, uint8_t diag_command)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
if (diag_command != 0)
diag_command = diag_command + 5;
tmp_addr[3] = 0x80; tmp_addr[2] = 0x02;
tmp_addr[1] = 0x01; tmp_addr[0] = 0x80;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = diag_command;
himax_flash_write_burst(client, tmp_addr, tmp_data);
}
void himax_flash_dump_func(struct i2c_client *client,
uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer)
{
/*struct himax_ts_data *ts =
container_of(work, struct himax_ts_data, flash_work);*/
/*uint8_t sector = 0;*/
/*uint8_t page = 0;*/
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
uint8_t out_buffer[20];
uint8_t in_buffer[260];
int page_prog_start = 0;
int i = 0;
himax_sense_off(client);
himax_burst_enable(client, 0);
/*=============Dump Flash Start=============*/
/*=====================================*/
/* SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780*/
/*=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
tmp_data[3] = 0x00; tmp_data[2] = 0x02;
tmp_data[1] = 0x07; tmp_data[0] = 0x80;
himax_flash_write_burst(client, tmp_addr, tmp_data);
for (page_prog_start = 0 ; page_prog_start < Flash_Size;
page_prog_start = page_prog_start + 256) {
/*=====================================
SPI Transfer Control
Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF
Set read start address : 0x8000_0028 ==> 0x0000_0000
Set command : 0x8000_0024 ==> 0x0000_003B
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
tmp_data[3] = 0x69; tmp_data[2] = 0x40;
tmp_data[1] = 0x02; tmp_data[0] = 0xFF;
himax_flash_write_burst(client, tmp_addr, tmp_data);
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
if (page_prog_start < 0x100) {
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = (uint8_t)page_prog_start;
} else if (page_prog_start >= 0x100
&& page_prog_start < 0x10000) {
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = (uint8_t)(page_prog_start >> 8);
tmp_data[0] = (uint8_t)page_prog_start;
} else if (page_prog_start >= 0x10000
&& page_prog_start < 0x1000000) {
tmp_data[3] = 0x00;
tmp_data[2] = (uint8_t)(page_prog_start >> 16);
tmp_data[1] = (uint8_t)(page_prog_start >> 8);
tmp_data[0] = (uint8_t)page_prog_start;
}
himax_flash_write_burst(client, tmp_addr, tmp_data);
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x3B;
himax_flash_write_burst(client, tmp_addr, tmp_data);
/*=====================================
AHB_I2C Burst Read
Set SPI data register : 0x8000_002C ==> 0x00
=====================================*/
out_buffer[0] = 0x2C;
out_buffer[1] = 0x00;
out_buffer[2] = 0x00;
out_buffer[3] = 0x80;
i2c_himax_write(client, 0x00, out_buffer, 4, 3);
/*=====================================
Read access : 0x0C ==> 0x00
=====================================*/
out_buffer[0] = 0x00;
i2c_himax_write(client, 0x0C, out_buffer, 1, 3);
/*=====================================
Read 128 bytes two times
=====================================*/
i2c_himax_read(client, 0x08, in_buffer, 128, 3);
for (i = 0 ; i < 128 ; i++)
flash_buffer[i + page_prog_start]
= in_buffer[i];
i2c_himax_read(client, 0x08 , in_buffer, 128, 3);
for (i = 0 ; i < 128 ; i++)
flash_buffer[(i + 128) + page_prog_start]
= in_buffer[i];
I("%s:Verify Progress: %x\n", __func__, page_prog_start);
}
/*=============Dump Flash End=============*/
/*//msleep(100);
for( i=0 ; i<8 ;i++)
{
for(j=0 ; j<64 ; j++)
{
setFlashDumpProgress(i*32 + j);
}
}
*/
himax_sense_on(client, 0x01);
return;
}
int himax_chip_self_test(struct i2c_client *client)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[128];
int pf_value = 0x00;
uint8_t test_result_id = 0;
int j;
memset(tmp_addr, 0x00, sizeof(tmp_addr));
memset(tmp_data, 0x00, sizeof(tmp_data));
himax_interface_on(client);
himax_sense_off(client);
/*Set criteria*/
himax_burst_enable(client, 1);
tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
tmp_addr[1] = 0x80; tmp_addr[0] = 0x94;
tmp_data[3] = 0x14; tmp_data[2] = 0xC8;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
tmp_data[7] = 0x13; tmp_data[6] = 0x60;
tmp_data[5] = 0x0A; tmp_data[4] = 0x99;
himax_flash_write_burst_length(client, tmp_addr, tmp_data, 8);
/*start selftest*/
/* 0x9008_805C ==> 0x0000_0001*/
tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
tmp_addr[1] = 0x80; tmp_addr[0] = 0x5C;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x01;
himax_flash_write_burst(client, tmp_addr, tmp_data);
himax_sense_on(client, 1);
msleep(2000);
himax_sense_off(client);
msleep(20);
/*=====================================
Read test result ID : 0x9008_8078 ==> 0xA/0xB/0xC/0xF
=====================================*/
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
tmp_addr[1] = 0x80; tmp_addr[0] = 0x78;
himax_register_read(client, tmp_addr, 1, tmp_data);
test_result_id = tmp_data[0];
I("%s: check test result, test_result_id=%x, test_result=%x\n",
__func__ , test_result_id, tmp_data[0]);
if (test_result_id == 0xF) {
I("[Himax]: self-test pass\n");
pf_value = 0x1;
} else {
E("[Himax]: self-test fail\n");
pf_value = 0x0;
}
himax_burst_enable(client, 1);
for (j = 0 ; j < 10 ; j++) {
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
tmp_addr[3] = 0x90; tmp_addr[2] = 0x06;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x0C;
himax_register_read(client, tmp_addr, 1, tmp_data);
I("[Himax]: 9006000C = %d\n", tmp_data[0]);
if (tmp_data[0] != 0) {
tmp_data[3] = 0x90; tmp_data[2] = 0x06;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
if (i2c_himax_write(client, 0x00,
tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
}
tmp_data[0] = 0x00;
if (i2c_himax_write(client, 0x0C,
tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
}
i2c_himax_read(client, 0x08,
tmp_data, 124, HIMAX_I2C_RETRY_TIMES);
} else {
break;
}
}
himax_sense_on(client, 1);
msleep(120);
return pf_value;
}
void himax_set_HSEN_enable(struct i2c_client *client, uint8_t HSEN_enable)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
himax_burst_enable(client, 0);
tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
tmp_addr[1] = 0x80; tmp_addr[0] = 0x50;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = HSEN_enable;
himax_flash_write_burst(client, tmp_addr, tmp_data);
}
void himax_get_HSEN_enable(struct i2c_client *client, uint8_t *tmp_data)
{
uint8_t tmp_addr[4];
tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
tmp_addr[1] = 0x80; tmp_addr[0] = 0x50;
himax_register_read(client, tmp_addr, 1, tmp_data);
}
void himax_set_SMWP_enable(struct i2c_client *client, uint8_t SMWP_enable)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
tmp_addr[1] = 0x80; tmp_addr[0] = 0x54;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = SMWP_enable;
himax_flash_write_burst(client, tmp_addr, tmp_data);
}
void himax_get_SMWP_enable(struct i2c_client *client,
uint8_t *tmp_data)
{
uint8_t tmp_addr[4];
tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
tmp_addr[1] = 0x80; tmp_addr[0] = 0x54;
himax_register_read(client, tmp_addr, 1, tmp_data);
}
int himax_burst_enable(struct i2c_client *client, uint8_t auto_add_4_byte)
{
uint8_t tmp_data[4];
int err = -1;
tmp_data[0] = 0x31;
if (i2c_himax_write(client, 0x13,
tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return err;
}
tmp_data[0] = (0x10 | auto_add_4_byte);
if (i2c_himax_write(client, 0x0D,
tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return err;
}
return 0;
}
void himax_register_read(struct i2c_client *client,
uint8_t *read_addr, int read_length, uint8_t *read_data)
{
uint8_t tmp_data[4];
int i = 0;
int address = 0;
if (read_length > 256) {
E("%s: read len over 256!\n", __func__);
return;
}
if (read_length > 1)
himax_burst_enable(client, 1);
else
himax_burst_enable(client, 0);
address = (read_addr[3] << 24) +
(read_addr[2] << 16) +
(read_addr[1] << 8) +
read_addr[0];
i = address;
tmp_data[0] = (uint8_t)i;
tmp_data[1] = (uint8_t)(i >> 8);
tmp_data[2] = (uint8_t)(i >> 16);
tmp_data[3] = (uint8_t)(i >> 24);
if (i2c_himax_write(client, 0x00,
tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
tmp_data[0] = 0x00;
if (i2c_himax_write(client, 0x0C,
tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_read(client, 0x08,
read_data, read_length * 4, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (read_length > 1)
himax_burst_enable(client, 0);
}
void himax_flash_read(struct i2c_client *client,
uint8_t *reg_byte, uint8_t *read_data)
{
uint8_t tmpbyte[2];
if (i2c_himax_write(client, 0x00,
&reg_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_write(client, 0x01,
&reg_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_write(client, 0x02,
&reg_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_write(client, 0x03,
&reg_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
tmpbyte[0] = 0x00;
if (i2c_himax_write(client, 0x0C,
&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_read(client, 0x08,
&read_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_read(client, 0x09,
&read_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_read(client, 0x0A,
&read_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_read(client, 0x0B,
&read_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_read(client, 0x18,
&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
} /* No bus request*/
if (i2c_himax_read(client, 0x0F,
&tmpbyte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
} /* idle state*/
}
void himax_flash_write_burst(struct i2c_client *client,
uint8_t *reg_byte, uint8_t *write_data)
{
uint8_t data_byte[8];
int i = 0, j = 0;
for (i = 0 ; i < 4; i++)
data_byte[i] = reg_byte[i];
for (j = 4 ; j < 8; j++)
data_byte[j] = write_data[j-4];
if (i2c_himax_write(client, 0x00,
data_byte, 8, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
}
int himax_flash_write_burst_length(struct i2c_client *client,
uint8_t *reg_byte, uint8_t *write_data, int length)
{
uint8_t data_byte[256];
int i = 0, j = 0, err = -1;
for (i = 0 ; i < 4 ; i++)
data_byte[i] = reg_byte[i];
for (j = 4 ; j < length + 4 ; j++)
data_byte[j] = write_data[j - 4];
if (i2c_himax_write(client, 0x00,
data_byte, length + 4, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return err;
}
return 0;
}
int himax_register_write(struct i2c_client *client,
uint8_t *write_addr, int write_length, uint8_t *write_data)
{
int i = 0, address = 0;
int ret = 0, err = -1;
address = (write_addr[3] << 24) +
(write_addr[2] << 16) +
(write_addr[1] << 8) +
write_addr[0];
for (i = address ; i < address + write_length * 4;
i = i + 4) {
if (write_length > 1) {
ret = himax_burst_enable(client, 1);
if (ret)
return err;
} else {
ret = himax_burst_enable(client, 0);
if (ret)
return err;
}
ret = himax_flash_write_burst_length(client,
write_addr, write_data, write_length * 4);
if (ret < 0)
return err;
}
return 0;
}
void himax_sense_off(struct i2c_client *client)
{
uint8_t wdt_off = 0x00;
uint8_t tmp_addr[4];
uint8_t tmp_data[5];
himax_burst_enable(client, 0);
while (wdt_off == 0x00) {
/* 0x9000_800C ==> 0x0000_AC53*/
tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0xAC; tmp_data[0] = 0x53;
himax_flash_write_burst(client, tmp_addr, tmp_data);
/*=====================================*/
/* Read Watch Dog disable password :
0x9000_800C ==> 0x0000_AC53 */
/*=====================================*/
tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C;
himax_register_read(client, tmp_addr, 1, tmp_data);
/*Check WDT*/
if (tmp_data[0] == 0x53 && tmp_data[1] == 0xAC
&& tmp_data[2] == 0x00 && tmp_data[3] == 0x00)
wdt_off = 0x01;
else
wdt_off = 0x00;
}
/* VCOM //0x9008_806C ==> 0x0000_0001*/
tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
tmp_addr[1] = 0x80; tmp_addr[0] = 0x6C;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x01;
himax_flash_write_burst(client, tmp_addr, tmp_data);
msleep(20);
/* 0x9000_0010 ==> 0x0000_00DA*/
tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0xDA;
himax_flash_write_burst(client, tmp_addr, tmp_data);
/*=====================================
Read CPU clock off password : 0x9000_0010 ==> 0x0000_00DA
=====================================*/
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
himax_register_read(client, tmp_addr, 1, tmp_data);
I("%s: CPU clock off password data[0]=%x",
__func__, tmp_data[0]);
I(" data[1]=%x data[2]=%x data[3]=%x\n",
tmp_data[1], tmp_data[2], tmp_data[3]);
}
void himax_interface_on(struct i2c_client *client)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[5];
/*=====================================
Any Cmd for ineterface on : 0x9000_0000 ==> 0x0000_0000
=====================================*/
tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
himax_flash_read(client, tmp_addr, tmp_data); /*avoid RD/WR fail*/
}
bool wait_wip(struct i2c_client *client, int Timing)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
uint8_t in_buffer[10];
/*uint8_t out_buffer[20];*/
int retry_cnt = 0;
/*=====================================
SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
tmp_data[3] = 0x00; tmp_data[2] = 0x02;
tmp_data[1] = 0x07; tmp_data[0] = 0x80;
himax_flash_write_burst(client, tmp_addr, tmp_data);
in_buffer[0] = 0x01;
do {
/*=====================================
SPI Transfer Control : 0x8000_0020 ==> 0x4200_0003
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
tmp_data[3] = 0x42; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x03;
himax_flash_write_burst(client, tmp_addr, tmp_data);
/*=====================================
SPI Command : 0x8000_0024 ==> 0x0000_0005
read 0x8000_002C for 0x01, means wait success
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x05;
himax_flash_write_burst(client, tmp_addr, tmp_data);
in_buffer[0] = in_buffer[1] =
in_buffer[2] = in_buffer[3] = 0xFF;
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
himax_register_read(client, tmp_addr, 1, in_buffer);
if ((in_buffer[0] & 0x01) == 0x00)
return true;
retry_cnt++;
if (in_buffer[0] != 0x00 || in_buffer[1] != 0x00
|| in_buffer[2] != 0x00 || in_buffer[3] != 0x00){
I("%s:Wait wip retry_cnt:%d, buffer[0]=%d, ",
__func__, retry_cnt, in_buffer[0]);
I("buffer[1]=%d, buffer[2]=%d, buffer[3]=%d\n",
in_buffer[1], in_buffer[2], in_buffer[3]);
}
if (retry_cnt > 100) {
E("%s: Wait wip error!\n", __func__);
return false;
}
msleep(Timing);
} while ((in_buffer[0] & 0x01) == 0x01);
return true;
}
void himax_sense_on(struct i2c_client *client, uint8_t FlashMode)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[128];
himax_interface_on(client);
himax_burst_enable(client, 0);
/*CPU reset*/
/* 0x9000_0014 ==> 0x0000_00CA*/
tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0xCA;
himax_flash_write_burst(client, tmp_addr, tmp_data);
/*=====================================
Read pull low CPU reset signal : 0x9000_0014 ==> 0x0000_00CA
=====================================*/
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
himax_register_read(client, tmp_addr, 1, tmp_data);
I("%s: check pull low CPU reset signal data[0]=%x data[1]=%x ",
__func__, tmp_data[0], tmp_data[1]);
I("data[2]=%x data[3]=%x\n",
tmp_data[2], tmp_data[3]);
/* 0x9000_0014 ==> 0x0000_0000*/
tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
/*=====================================
Read revert pull low CPU reset signal : 0x9000_0014 ==> 0x0000_0000
=====================================*/
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
himax_register_read(client, tmp_addr, 1, tmp_data);
I("%s: revert pull low CPU reset signal data[0]=%x data[1]=%x ",
__func__, tmp_data[0], tmp_data[1]);
I("data[2]=%x data[3]=%x\n",
tmp_data[2], tmp_data[3]);
/*=====================================
Reset TCON
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x02;
tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
usleep_range(9999, 10000);
tmp_addr[3] = 0x80; tmp_addr[2] = 0x02;
tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x01;
himax_flash_write_burst(client, tmp_addr, tmp_data);
if (FlashMode == 0x00) { /*SRAM*/
/*=====================================
Re-map
=====================================*/
tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0xF1;
himax_flash_write_burst_length(client, tmp_addr, tmp_data, 4);
I("%s:83100_Chip_Re-map ON\n", __func__);
} else {
/*=====================================
Re-map off
=====================================*/
tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_flash_write_burst_length(client, tmp_addr, tmp_data, 4);
I("%s:83100_Chip_Re-map OFF\n", __func__);
}
/*=====================================
CPU clock on
=====================================*/
tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_flash_write_burst_length(client, tmp_addr, tmp_data, 4);
}
void himax_chip_erase(struct i2c_client *client)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
himax_burst_enable(client, 0);
/*=====================================
SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
tmp_data[3] = 0x00; tmp_data[2] = 0x02;
tmp_data[1] = 0x07; tmp_data[0] = 0x80;
himax_flash_write_burst(client, tmp_addr, tmp_data);
/*=====================================
Chip Erase
Write Enable :
1. 0x8000_0020 ==> 0x4700_0000
2. 0x8000_0024 ==> 0x0000_0006
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
tmp_data[3] = 0x47; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x06;
himax_flash_write_burst(client, tmp_addr, tmp_data);
/*=====================================
Chip Erase
Erase Command : 0x8000_0024 ==> 0x0000_00C7
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0xC7;
himax_flash_write_burst(client, tmp_addr, tmp_data);
msleep(2000);
if (!wait_wip(client, 100))
E("%s:83100_Chip_Erase Fail\n", __func__);
}
bool himax_block_erase(struct i2c_client *client)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
himax_burst_enable(client, 0);
/*=====================================
SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
tmp_data[3] = 0x00; tmp_data[2] = 0x02;
tmp_data[1] = 0x07; tmp_data[0] = 0x80;
himax_flash_write_burst(client, tmp_addr, tmp_data);
/*=====================================
Chip Erase
Write Enable :
1. 0x8000_0020 ==> 0x4700_0000
2. 0x8000_0024 ==> 0x0000_0006
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
tmp_data[3] = 0x47; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x06;
himax_flash_write_burst(client, tmp_addr, tmp_data);
/*=====================================
Block Erase
Erase Command :
0x8000_0028 ==> 0x0000_0000 //SPI addr
0x8000_0020 ==> 0x6700_0000 //control
0x8000_0024 ==> 0x0000_0052 //BE
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
tmp_data[3] = 0x67; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x52;
himax_flash_write_burst(client, tmp_addr, tmp_data);
msleep(1000);
if (!wait_wip(client, 100)) {
E("%s:83100_Erase Fail\n", __func__);
return false;
} else {
return true;
}
}
bool himax_sector_erase(struct i2c_client *client, int start_addr)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
int page_prog_start = 0;
himax_burst_enable(client, 0);
/*=====================================
SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
tmp_data[3] = 0x00; tmp_data[2] = 0x02;
tmp_data[1] = 0x07; tmp_data[0] = 0x80;
himax_flash_write_burst(client, tmp_addr, tmp_data);
for (page_prog_start = start_addr;
page_prog_start < start_addr + 0x0F000;
page_prog_start = page_prog_start + 0x1000) {
/*=====================================
Chip Erase
Write Enable :
1. 0x8000_0020 ==> 0x4700_0000
2. 0x8000_0024 ==> 0x0000_0006
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
tmp_data[3] = 0x47; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x06;
himax_flash_write_burst(client, tmp_addr, tmp_data);
/*=====================================
Sector Erase
Erase Command :
0x8000_0028 ==> 0x0000_0000 //SPI addr
0x8000_0020 ==> 0x6700_0000 //control
0x8000_0024 ==> 0x0000_0020 //SE
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
if (page_prog_start < 0x100) {
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = (uint8_t)page_prog_start;
} else if (page_prog_start >= 0x100
&& page_prog_start < 0x10000) {
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = (uint8_t)(page_prog_start >> 8);
tmp_data[0] = (uint8_t)page_prog_start;
} else if (page_prog_start >= 0x10000
&& page_prog_start < 0x1000000) {
tmp_data[3] = 0x00;
tmp_data[2] = (uint8_t)(page_prog_start >> 16);
tmp_data[1] = (uint8_t)(page_prog_start >> 8);
tmp_data[0] = (uint8_t)page_prog_start;
}
himax_flash_write_burst(client, tmp_addr, tmp_data);
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
tmp_data[3] = 0x67; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x20;
himax_flash_write_burst(client, tmp_addr, tmp_data);
msleep(200);
if (!wait_wip(client, 100)) {
E("%s:83100_Erase Fail\n", __func__);
return false;
}
}
return true;
}
void himax_sram_write(struct i2c_client *client, uint8_t *FW_content)
{
int i = 0;
uint8_t tmp_addr[4];
uint8_t tmp_data[64];
int FW_length = 0x4000; /* 0x4000 = 16K bin file */
/*himax_sense_off(client);*/
for (i = 0; i < FW_length; i = i + 64) {
himax_burst_enable(client, 1);
if (i < 0x100) {
tmp_addr[3] = 0x08;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00;
tmp_addr[0] = i;
} else if (i >= 0x100 && i < 0x10000) {
tmp_addr[3] = 0x08;
tmp_addr[2] = 0x00;
tmp_addr[1] = (i >> 8);
tmp_addr[0] = i;
}
memcpy(&tmp_data[0], &FW_content[i], 64);
himax_flash_write_burst_length(client, tmp_addr, tmp_data, 64);
}
if (!wait_wip(client, 100))
E("%s:83100_Sram_Write Fail\n", __func__);
}
bool himax_sram_verify(struct i2c_client *client,
uint8_t *FW_File, int FW_Size)
{
int i = 0;
uint8_t out_buffer[20];
uint8_t in_buffer[128];
uint8_t *get_fw_content;
get_fw_content = kzalloc(0x4000 * sizeof(uint8_t), GFP_KERNEL);
for (i = 0 ; i < 0x4000 ; i = i + 128) {
himax_burst_enable(client, 1);
/*=====================================
AHB_I2C Burst Read
=====================================*/
if (i < 0x100) {
out_buffer[3] = 0x08;
out_buffer[2] = 0x00;
out_buffer[1] = 0x00;
out_buffer[0] = i;
} else if (i >= 0x100 && i < 0x10000) {
out_buffer[3] = 0x08;
out_buffer[2] = 0x00;
out_buffer[1] = (i >> 8);
out_buffer[0] = i;
}
if (i2c_himax_write(client, 0x00, out_buffer,
4, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return false;
}
out_buffer[0] = 0x00;
if (i2c_himax_write(client, 0x0C, out_buffer,
1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return false;
}
if (i2c_himax_read(client, 0x08, in_buffer,
128, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return false;
}
memcpy(&get_fw_content[i], &in_buffer[0], 128);
}
for (i = 0 ; i < FW_Size ; i++) {
if (FW_File[i] != get_fw_content[i]) {
E("%s: fail! SRAM[%x]=%x NOT CRC_ifile=%x\n",
__func__, i, get_fw_content[i], FW_File[i]);
return false;
}
}
kfree(get_fw_content);
return true;
}
void himax_flash_programming(struct i2c_client *client,
uint8_t *FW_content, int FW_Size)
{
int page_prog_start = 0;
int program_length = 48;
int i = 0, j = 0, k = 0;
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
/* // Read for flash data, 128K //4 bytes for 0x80002C padding */
uint8_t buring_data[256];
/*himax_interface_on(client);*/
himax_burst_enable(client, 0);
/*=====================================
SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
tmp_data[3] = 0x00; tmp_data[2] = 0x02;
tmp_data[1] = 0x07; tmp_data[0] = 0x80;
himax_flash_write_burst(client, tmp_addr, tmp_data);
for (page_prog_start = 0 ; page_prog_start < FW_Size;
page_prog_start = page_prog_start + 256) {
/*msleep(5);*/
/*=====================================
Write Enable :
1. 0x8000_0020 ==> 0x4700_0000
2. 0x8000_0024 ==> 0x0000_0006
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
tmp_data[3] = 0x47; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_flash_write_burst(client, tmp_addr, tmp_data);
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x06;
himax_flash_write_burst(client, tmp_addr, tmp_data);
/*=====================================
SPI Transfer Control
Set 256 bytes page write : 0x8000_0020 ==> 0x610F_F000
Set read start address : 0x8000_0028 ==> 0x0000_0000
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
tmp_data[3] = 0x61; tmp_data[2] = 0x0F;
tmp_data[1] = 0xF0; tmp_data[0] = 0x00;
/*data bytes should be 0x6100_0000 +
((word_number)*4-1)*4096 = 0x6100_0000 +
0xFF000 = 0x610F_F000
Programmable size = 1 page = 256 bytes,
word_number = 256 byte / 4 = 64*/
himax_flash_write_burst(client, tmp_addr, tmp_data);
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
/* tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
// Flash start address 1st : 0x0000_0000 */
if (page_prog_start < 0x100) {
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = (uint8_t)page_prog_start;
} else if (page_prog_start >= 0x100
&& page_prog_start < 0x10000) {
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = (uint8_t)(page_prog_start >> 8);
tmp_data[0] = (uint8_t)page_prog_start;
} else if (page_prog_start >= 0x10000
&& page_prog_start < 0x1000000) {
tmp_data[3] = 0x00;
tmp_data[2] = (uint8_t)(page_prog_start >> 16);
tmp_data[1] = (uint8_t)(page_prog_start >> 8);
tmp_data[0] = (uint8_t)page_prog_start;
}
himax_flash_write_burst(client, tmp_addr, tmp_data);
/*=====================================
Send 16 bytes data : 0x8000_002C ==> 16 bytes data
=====================================*/
buring_data[0] = 0x2C;
buring_data[1] = 0x00;
buring_data[2] = 0x00;
buring_data[3] = 0x80;
for (i = /*0*/page_prog_start, j = 0;
i < 16 + page_prog_start/**/;
i++, j++) { /* <------ bin file*/
buring_data[j + 4] = FW_content[i];
}
if (i2c_himax_write(client, 0x00, buring_data,
20, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
/*=====================================
Write command : 0x8000_0024 ==> 0x0000_0002
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x02;
himax_flash_write_burst(client, tmp_addr, tmp_data);
/*=====================================
Send 240 bytes data : 0x8000_002C ==> 240 bytes data
=====================================*/
for (j = 0; j < 5; j++) {
for (i = (page_prog_start + 16 + (j * 48)), k = 0;
i < (page_prog_start + 16 + (j * 48)) + program_length;
i++, k++) { /*<------ bin file*/
buring_data[k+4] = FW_content[i];/*(byte)i;*/
}
if (i2c_himax_write(client, 0x00, buring_data,
program_length + 4,
HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
}
if (!wait_wip(client, 1))
E("%s:83100_Flash_Programming Fail\n", __func__);
}
}
bool himax_check_chip_version(struct i2c_client *client)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
uint8_t ret_data = 0x00;
int i = 0;
int ret = 0;
himax_sense_off(client);
for (i = 0 ; i < 5 ; i++) {
/* 1. Set DDREG_Req = 1 (0x9000_0020 = 0x0000_0001)
(Lock register R/W from driver) */
tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x01;
ret = himax_register_write(client, tmp_addr, 1, tmp_data);
if (ret)
return false;
/* 2. Set bank as 0 (0x8001_BD01 = 0x0000_0000)*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x01;
tmp_addr[1] = 0xBD; tmp_addr[0] = 0x01;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
ret = himax_register_write(client, tmp_addr, 1, tmp_data);
if (ret)
return false;
/* 3. Read driver ID register RF4H 1 byte (0x8001_F401)
// Driver register RF4H 1 byte value = 0x84H,
read back value will become 0x84848484 */
tmp_addr[3] = 0x80; tmp_addr[2] = 0x01;
tmp_addr[1] = 0xF4; tmp_addr[0] = 0x01;
himax_register_read(client, tmp_addr, 1, tmp_data);
ret_data = tmp_data[0];
I("%s:Read driver IC ID = %X\n", __func__, ret_data);
if (ret_data == 0x84) {
IC_TYPE = HX_83100_SERIES_PWON;
/*himax_sense_on(client, 0x01);*/
ret_data = true;
break;
} else {
ret_data = false;
E("%s:Read driver ID register Fail:\n", __func__);
}
}
/* 4. After read finish, set DDREG_Req = 0
(0x9000_0020 = 0x0000_0000) (Unlock register R/W from driver)*/
tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_register_write(client, tmp_addr, 1, tmp_data);
/*himax_sense_on(client, 0x01);*/
return ret_data;
}
/*#if 1*/
int himax_check_CRC(struct i2c_client *client, int mode)
{
bool burnFW_success = false;
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
int tmp_value;
int CRC_value = 0;
memset(tmp_data, 0x00, sizeof(tmp_data));
if (i_TP_CRC_FW_60K == NULL) {
I("%s: i_TP_CRC_FW_60K = NULL\n", __func__);
return 0;
} else if (i_TP_CRC_FW_64K == NULL) {
I("%s: i_TP_CRC_FW_64K = NULL\n", __func__);
return 0;
} else if (i_TP_CRC_FW_124K == NULL) {
I("%s: i_TP_CRC_FW_124K = NULL\n", __func__);
return 0;
} else if (i_TP_CRC_FW_128K == NULL) {
I("%s: i_TP_CRC_FW_128K = NULL\n", __func__);
return 0;
}
if (1) {
if (mode == fw_image_60k) {
himax_sram_write(client,
(unsigned char *)i_TP_CRC_FW_60K->data);
burnFW_success = himax_sram_verify(client,
(unsigned char *)i_TP_CRC_FW_60K->data, 0x4000);
} else if (mode == fw_image_64k) {
himax_sram_write(client,
(unsigned char *)i_TP_CRC_FW_64K->data);
burnFW_success = himax_sram_verify(client,
(unsigned char *)i_TP_CRC_FW_64K->data, 0x4000);
} else if (mode == fw_image_124k) {
himax_sram_write(client,
(unsigned char *)i_TP_CRC_FW_124K->data);
burnFW_success = himax_sram_verify(client,
(unsigned char *)i_TP_CRC_FW_124K->data, 0x4000);
} else if (mode == fw_image_128k) {
himax_sram_write(client,
(unsigned char *)i_TP_CRC_FW_128K->data);
burnFW_success = himax_sram_verify(client,
(unsigned char *)i_TP_CRC_FW_128K->data, 0x4000);
}
if (burnFW_success) {
I("%s: Start to do CRC FW mode=%d\n", __func__, mode);
himax_sense_on(client, 0x00); /* run CRC firmware*/
while (true) {
msleep(100);
tmp_addr[3] = 0x90;
tmp_addr[2] = 0x08;
tmp_addr[1] = 0x80;
tmp_addr[0] = 0x94;
himax_register_read(client,
tmp_addr, 1, tmp_data);
I("%s: CRC from firmware is %x, %x, %x, %x\n",
__func__, tmp_data[3], tmp_data[2],
tmp_data[1], tmp_data[0]);
/*
if (tmp_data[3] == 0xFF && tmp_data[2] == 0xFF
&& tmp_data[1] == 0xFF && tmp_data[0] == 0xFF) {
} else
break;
*/
if (!(tmp_data[3] == 0xFF
&& tmp_data[2] == 0xFF
&& tmp_data[1] == 0xFF
&& tmp_data[0] == 0xFF)) {
break;
}
}
CRC_value = tmp_data[3];
tmp_value = tmp_data[2] << 8;
CRC_value += tmp_value;
tmp_value = tmp_data[1] << 16;
CRC_value += tmp_value;
tmp_value = tmp_data[0] << 24;
CRC_value += tmp_value;
I("%s: CRC Value is %x\n", __func__, CRC_value);
/*Close Remapping*/
/*=====================================
Re-map close
=====================================*/
tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x00;
himax_flash_write_burst_length(client,
tmp_addr, tmp_data, 4);
return CRC_value;
} else {
E("%s: SRAM write fail\n", __func__);
return 0;
}
} else
I("%s: NO CRC Check File\n", __func__);
return 0;
}
bool Calculate_CRC_with_AP(unsigned char *FW_content,
int CRC_from_FW, int mode)
{
uint8_t tmp_data[4];
int i, j;
int fw_data;
int fw_data_2;
int CRC = 0xFFFFFFFF;
int PolyNomial = 0x82F63B78;
int length = 0;
if (mode == fw_image_128k)
length = 0x8000;
else if (mode == fw_image_124k)
length = 0x7C00;
else if (mode == fw_image_64k)
length = 0x4000;
else /*if (mode == fw_image_60k)*/
length = 0x3C00;
for (i = 0 ; i < length ; i++) {
fw_data = FW_content[i * 4];
for (j = 1 ; j < 4 ; j++) {
fw_data_2 = FW_content[i * 4 + j];
fw_data += (fw_data_2) << (8 * j);
}
CRC = fw_data ^ CRC;
for (j = 0 ; j < 32 ; j++) {
if ((CRC % 2) != 0)
CRC = ((CRC >> 1) & 0x7FFFFFFF) ^ PolyNomial;
else
CRC = (((CRC >> 1) ^ 0x7FFFFFFF) & 0x7FFFFFFF);
}
}
I("%s: CRC calculate from bin file is %x\n", __func__, CRC);
tmp_data[0] = (uint8_t)(CRC >> 24);
tmp_data[1] = (uint8_t)(CRC >> 16);
tmp_data[2] = (uint8_t)(CRC >> 8);
tmp_data[3] = (uint8_t) CRC;
CRC = tmp_data[0];
CRC += tmp_data[1] << 8;
CRC += tmp_data[2] << 16;
CRC += tmp_data[3] << 24;
I("%s: CRC calculate from bin file REVERSE %x\n", __func__, CRC);
I("%s: CRC calculate from FWis %x\n", __func__, CRC_from_FW);
if (CRC_from_FW == CRC)
return true;
else
return false;
}
/*#endif*/
int himax_load_CRC_bin_file(struct i2c_client *client)
{
int err = 0;
char *CRC_60_firmware_name = "HX_CRC_60.bin";
char *CRC_64_firmware_name = "HX_CRC_64.bin";
char *CRC_124_firmware_name = "HX_CRC_124.bin";
char *CRC_128_firmware_name = "HX_CRC_128.bin";
I("%s,Entering\n", __func__);
if (i_TP_CRC_FW_60K == NULL) {
I("load file name = %s\n", CRC_60_firmware_name);
err = request_firmware(&i_TP_CRC_FW_60K,
CRC_60_firmware_name, private_ts->dev);
if (err < 0) {
E("%s,fail in line%d error code=%d\n",
__func__, __LINE__, err);
err = -1;
goto request_60k_fw_fail;
}
} else
I("%s already load i_TP_CRC_FW_60K\n", __func__);
if (i_TP_CRC_FW_64K == NULL) {
I("load file name = %s\n", CRC_64_firmware_name);
err = request_firmware(&i_TP_CRC_FW_64K,
CRC_64_firmware_name, private_ts->dev);
if (err < 0) {
E("%s,fail in line%d error code=%d\n",
__func__, __LINE__, err);
err = -2;
goto request_64k_fw_fail;
}
} else
I("%s already load i_TP_CRC_FW_64K\n", __func__);
if (i_TP_CRC_FW_124K == NULL) {
I("load file name = %s\n", CRC_124_firmware_name);
err = request_firmware(&i_TP_CRC_FW_124K,
CRC_124_firmware_name, private_ts->dev);
if (err < 0) {
E("%s,fail in line%d error code=%d\n",
__func__, __LINE__, err);
err = -3;
goto request_124k_fw_fail;
}
} else
I("%s already load i_TP_CRC_FW_124K\n", __func__);
if (i_TP_CRC_FW_128K == NULL) {
I("load file name = %s\n", CRC_128_firmware_name);
err = request_firmware(&i_TP_CRC_FW_128K,
CRC_128_firmware_name, private_ts->dev);
if (err < 0) {
E("%s,fail in line%d error code=%d\n",
__func__, __LINE__, err);
err = -4;
goto request_128k_fw_fail;
}
} else
I("%s already load i_TP_CRC_FW_128K\n", __func__);
return err;
request_128k_fw_fail:
release_firmware(i_TP_CRC_FW_124K);
request_124k_fw_fail:
release_firmware(i_TP_CRC_FW_64K);
request_64k_fw_fail:
release_firmware(i_TP_CRC_FW_60K);
request_60k_fw_fail:
return err;
}
int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client,
unsigned char *fw, int len, bool change_iref)
{
int CRC_from_FW = 0;
int burnFW_success = 0;
if (len != 0x10000) {/*64k*/
E("%s: The file size is not 64K bytes\n", __func__);
return false;
}
himax_sense_off(client);
msleep(500);
himax_interface_on(client);
if (!himax_sector_erase(client, 0x00000)) {
E("%s:Sector erase fail!Please restart the IC.\n", __func__);
return false;
}
himax_flash_programming(client, fw, 0x0F000);
/*burnFW_success = himax_83100_Verify(fw, len);
if(burnFW_success==false)
return burnFW_success;*/
CRC_from_FW = himax_check_CRC(client, fw_image_60k);
burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_60k);
/*himax_sense_on(client, 0x01);*/
return burnFW_success;
}
int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client,
unsigned char *fw, int len, bool change_iref)
{
int CRC_from_FW = 0;
int burnFW_success = 0;
if (len != 0x10000) { /*64k*/
E("%s: The file size is not 64K bytes\n", __func__);
return false;
}
himax_sense_off(client);
msleep(500);
himax_interface_on(client);
himax_chip_erase(client);
himax_flash_programming(client, fw, len);
/*burnFW_success = himax_83100_Verify(fw, len);
if(burnFW_success==false)
return burnFW_success;*/
CRC_from_FW = himax_check_CRC(client, fw_image_64k);
burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_64k);
/*himax_sense_on(client, 0x01);*/
return burnFW_success;
}
int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client,
unsigned char *fw, int len, bool change_iref)
{
int CRC_from_FW = 0;
int burnFW_success = 0;
if (len != 0x20000) { /*128k*/
E("%s: The file size is not 128K bytes\n", __func__);
return false;
}
himax_sense_off(client);
msleep(500);
himax_interface_on(client);
if (!himax_block_erase(client)) {
E("%s:Block erase fail!Please restart the IC.\n", __func__);
return false;
}
if (!himax_sector_erase(client, 0x10000)) {
E("%s:Sector erase fail!Please restart the IC.\n", __func__);
return false;
}
himax_flash_programming(client, fw, 0x1F000);
/*burnFW_success = himax_83100_Verify(fw, len);
if(burnFW_success==false)
return burnFW_success;*/
CRC_from_FW = himax_check_CRC(client, fw_image_124k);
burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_124k);
/*himax_sense_on(client, 0x01);*/
return burnFW_success;
}
int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client,
unsigned char *fw, int len, bool change_iref)
{
int CRC_from_FW = 0;
int burnFW_success = 0;
if (len != 0x20000) { /*128k*/
E("%s: The file size is not 128K bytes\n", __func__);
return false;
}
himax_sense_off(client);
msleep(500);
himax_interface_on(client);
himax_chip_erase(client);
himax_flash_programming(client, fw, len);
/*burnFW_success = himax_83100_Verify(fw, len);
if(burnFW_success==false)
return burnFW_success;*/
CRC_from_FW = himax_check_CRC(client, fw_image_128k);
burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_128k);
/*himax_sense_on(client, 0x01); */
return burnFW_success;
}
void himax_touch_information(struct i2c_client *client)
{
uint8_t cmd[4];
char data[12] = {0};
I("%s:IC_TYPE =%d\n", __func__, IC_TYPE);
if (IC_TYPE == HX_83100_SERIES_PWON) {
cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xF8;
himax_register_read(client, cmd, 1, data);
ic_data->HX_RX_NUM = data[1];
ic_data->HX_TX_NUM = data[2];
ic_data->HX_MAX_PT = data[3];
cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xFC;
himax_register_read(client, cmd, 1, data);
if ((data[1] & 0x04) == 0x04)
ic_data->HX_XY_REVERSE = true;
else
ic_data->HX_XY_REVERSE = false;
ic_data->HX_Y_RES = data[3]*256;
cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x01; cmd[0] = 0x00;
himax_register_read(client, cmd, 1, data);
ic_data->HX_Y_RES = ic_data->HX_Y_RES + data[0];
ic_data->HX_X_RES = data[1]*256 + data[2];
cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0x8C;
himax_register_read(client, cmd, 1, data);
if ((data[0] & 0x01) == 1)
ic_data->HX_INT_IS_EDGE = true;
else
ic_data->HX_INT_IS_EDGE = false;
if (ic_data->HX_RX_NUM > 40)
ic_data->HX_RX_NUM = 29;
if (ic_data->HX_TX_NUM > 20)
ic_data->HX_TX_NUM = 16;
if (ic_data->HX_MAX_PT > 10)
ic_data->HX_MAX_PT = 10;
if (ic_data->HX_Y_RES > 2000)
ic_data->HX_Y_RES = 1280;
if (ic_data->HX_X_RES > 2000)
ic_data->HX_X_RES = 720;
#ifdef HX_EN_MUT_BUTTON
cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xE8;
himax_register_read(client, cmd, 1, data);
ic_data->HX_BT_NUM = data[3];
#endif
I("%s:HX_RX_NUM =%d,HX_TX_NUM =%d,HX_MAX_PT=%d\n",
__func__, ic_data->HX_RX_NUM,
ic_data->HX_TX_NUM, ic_data->HX_MAX_PT);
I("%s:HX_XY_REVERSE =%d,HX_Y_RES =%d,HX_X_RES=%d\n",
__func__, ic_data->HX_XY_REVERSE,
ic_data->HX_Y_RES, ic_data->HX_X_RES);
I("%s:HX_INT_IS_EDGE =%d\n",
__func__, ic_data->HX_INT_IS_EDGE);
} else {
ic_data->HX_RX_NUM = 0;
ic_data->HX_TX_NUM = 0;
ic_data->HX_BT_NUM = 0;
ic_data->HX_X_RES = 0;
ic_data->HX_Y_RES = 0;
ic_data->HX_MAX_PT = 0;
ic_data->HX_XY_REVERSE = false;
ic_data->HX_INT_IS_EDGE = false;
}
}
void himax_read_FW_ver(struct i2c_client *client)
{
uint8_t cmd[4];
uint8_t data[64];
/*=====================================
Read FW version : 0x0000_E303
=====================================*/
cmd[3] = 0x00; cmd[2] = 0x00; cmd[1] = 0xE3; cmd[0] = 0x00;
himax_register_read(client, cmd, 1, data);
ic_data->vendor_config_ver = data[3] << 8;
cmd[3] = 0x00; cmd[2] = 0x00; cmd[1] = 0xE3; cmd[0] = 0x04;
himax_register_read(client, cmd, 1, data);
ic_data->vendor_config_ver = data[0] | ic_data->vendor_config_ver;
I("CFG_VER : %X\n", ic_data->vendor_config_ver);
cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0x28;
himax_register_read(client, cmd, 1, data);
ic_data->vendor_fw_ver = data[0]<<8 | data[1];
I("FW_VER : %X\n", ic_data->vendor_fw_ver);
}
bool himax_ic_package_check(struct i2c_client *client)
{
/*#if 0*/
#ifdef HX_EN_CHECK_PATCH
uint8_t cmd[3];
uint8_t data[3];
memset(cmd, 0x00, sizeof(cmd));
memset(data, 0x00, sizeof(data));
if (i2c_himax_read(client, 0xD1, cmd, 3, HIMAX_I2C_RETRY_TIMES) < 0)
return false;
if (i2c_himax_read(client, 0x31, data, 3, HIMAX_I2C_RETRY_TIMES) < 0)
return false;
if ((data[0] == 0x85 && data[1] == 0x29)) {
IC_TYPE = HX_85XX_F_SERIES_PWON;
IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
/*Himax: Set FW and CFG Flash Address*/
FW_VER_MAJ_FLASH_ADDR = 64901; /*0xFD85*/
FW_VER_MAJ_FLASH_LENG = 1;
FW_VER_MIN_FLASH_ADDR = 64902; /*0xFD86*/
FW_VER_MIN_FLASH_LENG = 1;
CFG_VER_MAJ_FLASH_ADDR = 64928; /*0xFDA0*/
CFG_VER_MAJ_FLASH_LENG = 12;
CFG_VER_MIN_FLASH_ADDR = 64940; /*0xFDAC*/
CFG_VER_MIN_FLASH_LENG = 12;
I("Himax IC package 852x F\n");
}
if ((data[0] == 0x85 && data[1] == 0x30)
|| (cmd[0] == 0x05 && cmd[1] == 0x85 && cmd[2] == 0x29)) {
IC_TYPE = HX_85XX_E_SERIES_PWON;
IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
/*Himax: Set FW and CFG Flash Address*/
FW_VER_MAJ_FLASH_ADDR = 133; /*0x0085*/
FW_VER_MAJ_FLASH_LENG = 1;
FW_VER_MIN_FLASH_ADDR = 134; /*0x0086*/
FW_VER_MIN_FLASH_LENG = 1;
CFG_VER_MAJ_FLASH_ADDR = 160; /*0x00A0*/
CFG_VER_MAJ_FLASH_LENG = 12;
CFG_VER_MIN_FLASH_ADDR = 172; /*0x00AC*/
CFG_VER_MIN_FLASH_LENG = 12;
I("Himax IC package 852x E\n");
} else if ((data[0] == 0x85 && data[1] == 0x31)) {
IC_TYPE = HX_85XX_ES_SERIES_PWON;
IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
/*Himax: Set FW and CFG Flash Address*/
FW_VER_MAJ_FLASH_ADDR = 133; /*0x0085*/
FW_VER_MAJ_FLASH_LENG = 1;
FW_VER_MIN_FLASH_ADDR = 134; /*0x0086*/
FW_VER_MIN_FLASH_LENG = 1;
CFG_VER_MAJ_FLASH_ADDR = 160; /*0x00A0*/
CFG_VER_MAJ_FLASH_LENG = 12;
CFG_VER_MIN_FLASH_ADDR = 172; /*0x00AC*/
CFG_VER_MIN_FLASH_LENG = 12;
I("Himax IC package 852x ES\n");
} else if ((data[0] == 0x85 && data[1] == 0x28)
|| (cmd[0] == 0x04 && cmd[1] == 0x85
&& (cmd[2] == 0x26 || cmd[2] == 0x27
|| cmd[2] == 0x28))) {
IC_TYPE = HX_85XX_D_SERIES_PWON;
IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
/*Himax: Set FW and CFG Flash Address*/
FW_VER_MAJ_FLASH_ADDR = 133; /*0x0085*/
FW_VER_MAJ_FLASH_LENG = 1;
FW_VER_MIN_FLASH_ADDR = 134; /*0x0086*/
FW_VER_MIN_FLASH_LENG = 1;
CFG_VER_MAJ_FLASH_ADDR = 160; /*0x00A0*/
CFG_VER_MAJ_FLASH_LENG = 12;
CFG_VER_MIN_FLASH_ADDR = 172; /* 0x00AC*/
CFG_VER_MIN_FLASH_LENG = 12;
I("Himax IC package 852x D\n");
} else if ((data[0] == 0x85 && data[1] == 0x23) ||
(cmd[0] == 0x03 && cmd[1] == 0x85 &&
(cmd[2] == 0x26 || cmd[2] == 0x27 ||
cmd[2] == 0x28 || cmd[2] == 0x29))) {
IC_TYPE = HX_85XX_C_SERIES_PWON;
IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW;
/*Himax: Set FW and CFG Flash Address*/
FW_VER_MAJ_FLASH_ADDR = 133; /*0x0085*/
FW_VER_MAJ_FLASH_LENG = 1;
FW_VER_MIN_FLASH_ADDR = 134; /*0x0086*/
FW_VER_MIN_FLASH_LENG = 1;
CFG_VER_MAJ_FLASH_ADDR = 135; /*0x0087*/
CFG_VER_MAJ_FLASH_LENG = 12;
CFG_VER_MIN_FLASH_ADDR = 147; /*0x0093*/
CFG_VER_MIN_FLASH_LENG = 12;
I("Himax IC package 852x C\n");
} else if ((data[0] == 0x85 && data[1] == 0x26) ||
(cmd[0] == 0x02 && cmd[1] == 0x85 &&
(cmd[2] == 0x19 || cmd[2] == 0x25 || cmd[2] == 0x26))) {
IC_TYPE = HX_85XX_B_SERIES_PWON;
IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW;
/*Himax: Set FW and CFG Flash Address*/
FW_VER_MAJ_FLASH_ADDR = 133; /*0x0085*/
FW_VER_MAJ_FLASH_LENG = 1;
FW_VER_MIN_FLASH_ADDR = 728; /*0x02D8*/
FW_VER_MIN_FLASH_LENG = 1;
CFG_VER_MAJ_FLASH_ADDR = 692; /*0x02B4*/
CFG_VER_MAJ_FLASH_LENG = 3;
CFG_VER_MIN_FLASH_ADDR = 704; /*0x02C0*/
CFG_VER_MIN_FLASH_LENG = 3;
I("Himax IC package 852x B\n");
} else if ((data[0] == 0x85 && data[1] == 0x20) || (cmd[0] == 0x01 &&
cmd[1] == 0x85 && cmd[2] == 0x19)) {
IC_TYPE = HX_85XX_A_SERIES_PWON;
IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW;
I("Himax IC package 852x A\n");
} else {
E("Himax IC package incorrect!!\n");
}
#else
IC_TYPE = HX_83100_SERIES_PWON;
IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
/*Himax: Set FW and CFG Flash Address*/
FW_VER_MAJ_FLASH_ADDR = 57384; /*0xE028*/
FW_VER_MAJ_FLASH_LENG = 1;
FW_VER_MIN_FLASH_ADDR = 57385; /*0xE029*/
FW_VER_MIN_FLASH_LENG = 1;
CFG_VER_MAJ_FLASH_ADDR = 58115; /*0xE303*/
CFG_VER_MAJ_FLASH_LENG = 1;
CFG_VER_MIN_FLASH_ADDR = 58116; /*0xE304*/
CFG_VER_MIN_FLASH_LENG = 1;
I("Himax IC package 83100_in\n");
#endif
return true;
}
void himax_read_event_stack(struct i2c_client *client,
uint8_t *buf, uint8_t length)
{
uint8_t cmd[4];
cmd[3] = 0x90; cmd[2] = 0x06;
cmd[1] = 0x00; cmd[0] = 0x00;
if (i2c_himax_write(client, 0x00,
cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
}
cmd[0] = 0x00;
if (i2c_himax_write(client, 0x0C,
cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
}
i2c_himax_read(client, 0x08,
buf, length, HIMAX_I2C_RETRY_TIMES);
}
/*#if 0*/
#ifdef HX_EN_CHECK_PATCH
static void himax_83100_Flash_Write(uint8_t *reg_byte, uint8_t *write_data)
{
uint8_t tmpbyte[2];
if (i2c_himax_write(private_ts->client, 0x00,
&reg_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_write(private_ts->client, 0x01,
&reg_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_write(private_ts->client, 0x02,
&reg_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_write(private_ts->client,
0x03, &reg_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_write(private_ts->client,
0x04, &write_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_write(private_ts->client,
0x05, &write_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_write(private_ts->client,
0x06, &write_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_write(private_ts->client,
0x07, &write_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (isBusrtOn == false) {
tmpbyte[0] = 0x01;
if (i2c_himax_write(private_ts->client,
0x0C, &tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
}
}
#endif
/*#if 0*/
#ifdef HX_EN_CHECK_PATCH
static void himax_83100_Flash_Burst_Write
(uint8_t *reg_byte, uint8_t *write_data)
{
/*uint8_t tmpbyte[2];*/
int i = 0;
if (i2c_himax_write(private_ts->client, 0x00,
&reg_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_write(private_ts->client, 0x01,
&reg_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_write(private_ts->client, 0x02,
&reg_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_write(private_ts->client, 0x03,
&reg_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
/*Write 256 bytes with continue burst mode*/
for (i = 0 ; i < 256 ; i = i + 4) {
if (i2c_himax_write(private_ts->client,
0x04, &write_data[i], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_write(private_ts->client, 0x05,
&write_data[i+1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_write(private_ts->client, 0x06,
&write_data[i+2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
if (i2c_himax_write(private_ts->client, 0x07,
&write_data[i+3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}
}
/*if (isBusrtOn == false)
{
tmpbyte[0] = 0x01;
if (i2c_himax_write(private_ts->client,
0x0C, &tmpbyte[0], 1, 3) < 0) {
E("%s: i2c access fail!\n", __func__);
return;
}*/
}
#endif
/*#if 0*/
#ifdef HX_EN_CHECK_PATCH
static bool himax_83100_Verify(uint8_t *FW_File, int FW_Size)
{
uint8_t tmp_addr[4];
uint8_t tmp_data[4];
uint8_t out_buffer[20];
uint8_t in_buffer[260];
int fail_addr = 0, fail_cnt = 0;
int page_prog_start = 0;
int i = 0;
himax_interface_on(private_ts->client);
himax_burst_enable(private_ts->client, 0);
/*=====================================
SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
tmp_data[3] = 0x00; tmp_data[2] = 0x02;
tmp_data[1] = 0x07; tmp_data[0] = 0x80;
himax_83100_Flash_Write(tmp_addr, tmp_data);
for (page_prog_start = 0; page_prog_start < FW_Size;
page_prog_start = page_prog_start + 256) {
/*=====================================
SPI Transfer Control
Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF
Set read start address : 0x8000_0028 ==> 0x0000_0000
Set command : 0x8000_0024 ==> 0x0000_003B
=====================================*/
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
tmp_data[3] = 0x69; tmp_data[2] = 0x40;
tmp_data[1] = 0x02; tmp_data[0] = 0xFF;
himax_83100_Flash_Write(tmp_addr, tmp_data);
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
if (page_prog_start < 0x100) {
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = 0x00;
tmp_data[0] = (uint8_t)page_prog_start;
} else if (page_prog_start >= 0x100
&& page_prog_start < 0x10000) {
tmp_data[3] = 0x00;
tmp_data[2] = 0x00;
tmp_data[1] = (uint8_t)(page_prog_start >> 8);
tmp_data[0] = (uint8_t)page_prog_start;
} else if (page_prog_start >= 0x10000
&& page_prog_start < 0x1000000) {
tmp_data[3] = 0x00;
tmp_data[2] = (uint8_t)(page_prog_start >> 16);
tmp_data[1] = (uint8_t)(page_prog_start >> 8);
tmp_data[0] = (uint8_t)page_prog_start;
}
himax_83100_Flash_Write(tmp_addr, tmp_data);
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x00; tmp_data[0] = 0x3B;
himax_83100_Flash_Write(tmp_addr, tmp_data);
/*==================================
AHB_I2C Burst Read
Set SPI data register : 0x8000_002C ==> 0x00
==================================*/
out_buffer[0] = 0x2C;
out_buffer[1] = 0x00;
out_buffer[2] = 0x00;
out_buffer[3] = 0x80;
i2c_himax_write(private_ts->client, 0x00,
out_buffer, 4, HIMAX_I2C_RETRY_TIMES);
/*==================================
Read access : 0x0C ==> 0x00
==================================*/
out_buffer[0] = 0x00;
i2c_himax_write(private_ts->client, 0x0C,
out_buffer, 1, HIMAX_I2C_RETRY_TIMES);
/*==================================
Read 128 bytes two times
==================================*/
i2c_himax_read(private_ts->client, 0x08,
in_buffer, 128, HIMAX_I2C_RETRY_TIMES);
for (i = 0; i < 128; i++)
flash_buffer[i + page_prog_start] = in_buffer[i];
i2c_himax_read(private_ts->client, 0x08,
in_buffer, 128, HIMAX_I2C_RETRY_TIMES);
for (i = 0; i < 128; i++)
flash_buffer[(i + 128)
+ page_prog_start] = in_buffer[i];
/*tmp_addr[3] = 0x80;
tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
himax_register_read(tmp_addr, 32, out in_buffer);
for (int i = 0; i < 128; i++)
flash_buffer[i + page_prog_start] = in_buffer[i];
tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
himax_register_read(tmp_addr, 32, out in_buffer);
for (int i = 0; i < 128; i++)
flash_buffer[i + page_prog_start] = in_buffer[i];
*/
I("%s:Verify Progress: %x\n", __func__, page_prog_start);
}
fail_cnt = 0;
for (i = 0; i < FW_Size; i++) {
if (FW_File[i] != flash_buffer[i]) {
if (fail_cnt == 0)
fail_addr = i;
fail_cnt++;
/*E("%s Fail Block:%x\n", __func__, i);
return false;*/
}
}
if (fail_cnt > 0) {
E("%s:Start Fail Block:%x and fail block count=%x\n",
__func__, fail_addr, fail_cnt);
return false;
}
I("%s:Byte read verify pass.\n", __func__);
return true;
}
#endif
void himax_get_DSRAM_data(struct i2c_client *client, uint8_t *info_data)
{
int i;
int cnt = 0;
unsigned char tmp_addr[4];
unsigned char tmp_data[4];
uint8_t max_i2c_size = 32;
int total_size = ic_data->HX_TX_NUM * ic_data->HX_RX_NUM * 2;
int total_size_4bytes = total_size / 4;
int total_read_times = 0;
unsigned long address = 0x08000468;
tmp_addr[3] = 0x08; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x04; tmp_addr[0] = 0x64;
tmp_data[3] = 0x00; tmp_data[2] = 0x00;
tmp_data[1] = 0x5A; tmp_data[0] = 0xA5;
himax_flash_write_burst(client, tmp_addr, tmp_data);
do {
cnt++;
himax_register_read(client, tmp_addr, 1, tmp_data);
usleep_range(9999, 10000);
} while ((tmp_data[1] != 0xA5 || tmp_data[0] != 0x5A) && cnt < 100);
tmp_addr[3] = 0x08; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x04; tmp_addr[0] = 0x68;
if (total_size_4bytes % max_i2c_size == 0)
total_read_times = total_size_4bytes / max_i2c_size;
else
total_read_times = total_size_4bytes / max_i2c_size + 1;
for (i = 0 ; i < (total_read_times) ; i++) {
if (total_size_4bytes >= max_i2c_size) {
himax_register_read(client, tmp_addr,
max_i2c_size,
&info_data[i*max_i2c_size*4]);
total_size_4bytes = total_size_4bytes - max_i2c_size;
} else {
himax_register_read(client, tmp_addr,
total_size_4bytes % max_i2c_size,
&info_data[i*max_i2c_size*4]);
}
address += max_i2c_size * 4;
tmp_addr[1] = (uint8_t)((address>>8) & 0x00FF);
tmp_addr[0] = (uint8_t)((address) & 0x00FF);
}
tmp_addr[3] = 0x08; tmp_addr[2] = 0x00;
tmp_addr[1] = 0x04; tmp_addr[0] = 0x64;
tmp_data[3] = 0x11; tmp_data[2] = 0x22;
tmp_data[1] = 0x33; tmp_data[0] = 0x44;
himax_flash_write_burst(client, tmp_addr, tmp_data);
}
/*ts_work*/
int cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max)
{
int RawDataLen;
if (raw_cnt_rmd != 0x00)
RawDataLen = 124 - ((HX_MAX_PT + raw_cnt_max + 3) * 4) - 1;
else
RawDataLen = 124 - ((HX_MAX_PT + raw_cnt_max + 2) * 4) - 1;
return RawDataLen;
}
bool read_event_stack(struct i2c_client *client, uint8_t *buf, int length)
{
uint8_t cmd[4];
if (length > 56)
length = 124;
/*=====================
AHB I2C Burst Read
=====================*/
cmd[0] = 0x31;
if (i2c_himax_write(client, 0x13, cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
goto err_workqueue_out;
}
cmd[0] = 0x10;
if (i2c_himax_write(client, 0x0D, cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
goto err_workqueue_out;
}
/*=====================
Read event stack
=====================*/
cmd[3] = 0x90; cmd[2] = 0x06; cmd[1] = 0x00; cmd[0] = 0x00;
if (i2c_himax_write(client, 0x00, cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
goto err_workqueue_out;
}
cmd[0] = 0x00;
if (i2c_himax_write(client, 0x0C, cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
E("%s: i2c access fail!\n", __func__);
goto err_workqueue_out;
}
i2c_himax_read(client, 0x08, buf, length, HIMAX_I2C_RETRY_TIMES);
return 1;
err_workqueue_out:
return 0;
}
bool post_read_event_stack(struct i2c_client *client)
{
return 1;
}
bool diag_check_sum(uint8_t hx_touch_info_size,
uint8_t *buf) /*return checksum value*/
{
uint16_t check_sum_cal = 0;
int i;
/*Check 124th byte CRC*/
for (i = hx_touch_info_size, check_sum_cal = 0 ; i < 124 ; i = i + 2)
check_sum_cal += (buf[i + 1] * 256 + buf[i]);
if (check_sum_cal % 0x10000 != 0) {
I("%s:diag chksum fail!check_sum_cal=%X,hx_touchinfo_sz=%d,\n",
__func__, check_sum_cal, hx_touch_info_size);
return 0;
}
return 1;
}
void diag_parse_raw_data(int hx_touch_info_size,
int RawDataLen, int mul_num, int self_num, uint8_t *buf,
uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data)
{
int RawDataLen_word;
int index = 0;
int temp1, temp2, i;
if (buf[hx_touch_info_size] == 0x3A &&
buf[hx_touch_info_size + 1] == 0xA3 &&
buf[hx_touch_info_size + 2] > 0 &&
buf[hx_touch_info_size + 3] == diag_cmd + 5) {
RawDataLen_word = RawDataLen / 2;
index = (buf[hx_touch_info_size + 2] - 1) * RawDataLen_word;
/*I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n",
index, buf[56], buf[57], buf[58], buf[59], mul_num, self_num);*/
for (i = 0; i < RawDataLen_word; i++) {
temp1 = index + i;
if (temp1 < mul_num) { /*mutual*/
/*4: RawData Header, 1:HSB */
mutual_data[index + i]
= buf[i*2 + hx_touch_info_size + 4 + 1]
* 256
+ buf[i * 2 + hx_touch_info_size + 4];
} else { /*self*/
temp1 = i + index;
temp2 = self_num + mul_num;
if (temp1 >= temp2)
break;
/*4: RawData Header*/
self_data[i + index - mul_num]
= buf[i * 2 + hx_touch_info_size + 4];
self_data[i + index - mul_num + 1]
= buf[i * 2 + hx_touch_info_size + 4 + 1];
}
}
} else {
I("[HIMAX TP MSG]%s: header format is wrong!\n", __func__);
I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n",
index, buf[56], buf[57], buf[58], buf[59],
mul_num, self_num);
}
}