Exemple #1
0
static int smsi2c_ts_enable(void *context) {
#define  TS_CLK 4000000 //6000000
//#define  TS_CONTROL_ENABLE

	struct SmsTsEnable_S TsEnableMsg = {{MSG_SMS_ENBALE_TS_INTERFACE_REQ, 
					0, 
					11,
					sizeof(struct SmsTsEnable_S),
					0},
					TS_CLK,//24000000,
					TSI_PARALLEL_ON_HIF, //TSI_PARALLEL_ON_HIF, TSI_SERIAL_ON_SDIO, //wood, ++--, @20140917
					TSI_SIGNALS_ACTIVE_HIGH,//TSI_SIGNALS_ACTIVE_LOW,
					0,//0,
					TSI_SIG_OUT_FALL_EDGE,
					TSI_BIT7_IS_MSB,
#ifdef TS_CONTROL_ENABLE
					1,
#else
					0,
#endif
					TSI_TRANSPARENT,//TSI_ENCAPSULATED,
					21};//21
	struct smsi2c_device *smsdev = (struct smsi2c_device *)context;
	
	if (!smsdev)
	{
		sms_err("smsi2c_ts_enable smsdev NULL!!\n");
		return -ENODEV;
	}
	return smsi2c_sendrequest(context, &TsEnableMsg, sizeof(TsEnableMsg));
	//return i2c_master_normal_send(smsdev->client, &TsEnableMsg, sizeof(TsEnableMsg), I2C_SCL_TATE); //using 400KHz clk

}
Exemple #2
0
// allocate and init i2c dev descriptor
// update i2c client params
// 
static int smsi2c_probe(void)
{
	int ret;

	struct smsi2c_device *smsdev;
	struct smsdevice_params_t params;
	struct SmsMsgHdr_S smsmsg;
	struct SmsMsgData2Args_S setIntMsg = {{MSG_SMS_SPI_INT_LINE_SET_REQ, 
				0, 
				11,
				sizeof(struct SmsMsgData2Args_S),
				0},
				{0xff,
				20}};

	    struct i2c_board_info smsi2c_info = {
		I2C_BOARD_INFO("smsi2c", sms_i2c_addr),
	    };
	
	smsdev = kzalloc(sizeof(struct smsi2c_device), GFP_KERNEL);
	if (!smsdev)
	{
		sms_err("Cannot allocate memory for I2C device driver.\n");
		return -ENOMEM;
	}
		
	g_smsi2c_device = smsdev;
	sms_debug ("Memory allocated");
	smsdev->adap = i2c_get_adapter(host_i2c_ctrl);
	if (!smsdev->adap) {
		sms_err("Cannot get adapter #%d.\n", host_i2c_ctrl);
		ret = -ENODEV;
		goto failed_allocate_adapter;
	}
	sms_debug ("Got the adapter");

	smsi2c_info.platform_data = smsdev;

	smsdev->client = i2c_new_device(smsdev->adap, &smsi2c_info);

	if (!smsdev->client) {
		sms_err("Cannot register I2C device with addr 0x%x.\n", sms_i2c_addr);
		 ret = -ENODEV;
		 goto failed_allocate_device;
	}
	sms_debug ("Got the device");


	ret = gpio_request(host_i2c_intr_pin, "sms_gpio");
	if (ret) {
		sms_err("failed to get sms_gpio\n");
		 goto failed_allocate_gpio;
	}	
	gpio_direction_input(host_i2c_intr_pin);
	gpio_export(host_i2c_intr_pin, 0);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
	irq_set_irq_type(gpio_to_irq(host_i2c_intr_pin), IRQ_TYPE_EDGE_FALLING);	
#else
	set_irq_type(gpio_to_irq(host_i2c_intr_pin), IRQ_TYPE_EDGE_FALLING);	
#endif
	/*register irq*/
	ret = request_irq( gpio_to_irq(host_i2c_intr_pin), (irq_handler_t)smsi2c_interrupt,
		 IRQF_TRIGGER_RISING, "SMSI2C", smsdev);
	if (ret < 0) {
		sms_err("failed to allocate interrupt for SMS\n");
		ret = -ENODEV;
		goto failed_allocate_interrupt;
	}	

	if (device_int_line != 0xFFFFFFFF)
	{ /* Device is not using the default interrupt pin*/

		sms_debug("Device is not using the default int pin, need to set the interrupt pin to %d", device_int_line);
		setIntMsg.msgData[1] = device_int_line;
		ret = smsi2c_sendrequest(smsdev, &setIntMsg, sizeof(setIntMsg));
		msleep(50);
	}

	init_completion(&smsdev->version_ex_done);
	smsdev->wait_for_version_resp = 1;
	SMS_INIT_MSG(&smsmsg, MSG_SMS_GET_VERSION_EX_REQ,
		     sizeof(struct SmsMsgHdr_S));
	smsi2c_sendrequest(smsdev, &smsmsg, sizeof(smsmsg));
	/*Wait for response*/
	ret = wait_for_completion_timeout(&smsdev->version_ex_done, msecs_to_jiffies(500));
	if (ret > 0)
	{ /*Got version. device is in*/
		sms_debug("Found and identified the I2C device");
	}
	else
	{ /* No response recieved*/
		sms_err("No response to get version command");
		ret = -ETIME;
		goto failed_registering_coredev;
	}


	memset(&params, 0, sizeof(struct smsdevice_params_t));

	params.device = (struct device *)&smsdev->client->adapter->dev;
#ifdef SMS_RK_TS
	params.buffer_size = MAX_I2C_BUF_SIZE;
	params.num_buffers = MAX_I2C_BUF_NUMBER;
	params.require_node_buffer = 1;
#else
	params.buffer_size = 0x400;
	params.num_buffers = 20;
#endif
	params.context = smsdev;

	snprintf(params.devpath, sizeof(params.devpath),
		 "i2c\\%s", "smsi2c");

	params.sendrequest_handler  = smsi2c_sendrequest;
	params.loadfirmware_handler = smsi2c_loadfirmware_handler;
	switch(smsdev->chip_model)
	{
		case 0: params.device_type = 0; break;
		case 0x1002:
		case 0x1102:
		case 0x1004: params.device_type = SMS_NOVA_B0; break;
		case 0x1182: params.device_type = SMS_VENICE; break;
		case 0x1530: params.device_type = SMS_DENVER_1530; break;
		case 0x2130: params.device_type = SMS_PELE; break;
		case 0x2160: params.device_type = SMS_DENVER_2160; break;
		case 0x2180: params.device_type = SMS_MING; break;
		case 0x2230: params.device_type = SMS_RIO; break;
		case 0x3130: params.device_type = SMS_ZICO; break;
		case 0x3180: params.device_type = SMS_QING; break;
		case 0x3230: params.device_type = SMS_SANTOS; break;
		case 0x4470: 
			if (smsdev->chip_metal >= 2)
				params.device_type = SMS_SIENA_A2; 
			else
				params.device_type = SMS_SIENA; 
			break;

		default: params.device_type = 0; break;
	}

	/* Use SMS_DEVICE_FAMILY2 for firmware download over SMS MSGs
	   SMS_DEVICE_FAMILY1 for backdoor I2C firmware download */
	params.flags |= SMS_DEVICE_FAMILY2;
	
	/* Device protocol completion events */

	ret = smscore_register_device(&params, &smsdev->coredev);
	if (ret < 0)
        {
	        printk(KERN_INFO "smscore_register_device error\n");
		goto failed_registering_coredev;
        }

	ret = smscore_start_device(smsdev->coredev);
	if (ret < 0)
        {
		printk(KERN_INFO "smscore_start_device error\n");
		goto failed_device_start;
        }

	return 0;
failed_device_start:
	smscore_unregister_device(smsdev->coredev);
failed_registering_coredev:
	free_irq(gpio_to_irq(host_i2c_intr_pin), smsdev);
failed_allocate_interrupt:
	gpio_free(host_i2c_intr_pin);
failed_allocate_gpio:
	i2c_unregister_device(smsdev->client);
failed_allocate_device:
	i2c_put_adapter(smsdev->adap);
failed_allocate_adapter:
	g_smsi2c_device = NULL;
	kfree(smsdev);

	return ret;
}
Exemple #3
0
static int smsi2c_loadfirmware_handler(void *context, void* p_data, u32 fw_size)
{
	int ret;
	u8* fw_data = (u8*)p_data + 12;
	u32* fw_hdr = p_data;
	u32 actual_crc, dummy_crc,i;
	u32 chunk_size;
	u32 dummy_hdr[3];
	u32 fw_addr, fw_len, dnl_offset;
	struct smsi2c_device *smsdev = (struct smsi2c_device *)context;
	u16 flags_bak = smsdev->client->flags;
	
	struct SmsMsgHdr_S BackdoorMsg = {
		MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ, 0, HIF_TASK,
			sizeof(struct SmsMsgHdr_S), 0};
	
	fw_addr = fw_hdr[2];
	fw_len = fw_hdr[1];

	/*The full CRC is for debug and printing, the function doesnt use this*/
	sms_debug("crc=0x%x, len=0x%x, addr=0x%x", fw_hdr[0], fw_len, fw_addr);
	actual_crc=0;
	for (i = 0; i < fw_len+8 ; i++)
	{
		actual_crc ^= ((u8*)p_data)[4+i];
	}
	sms_debug("actual calculated crc=0x%x", actual_crc);
	

	sms_debug("Sending the firmware content in chunks of no more than %dKB.\n", MAX_CHUNK_SIZE/1024);
	dnl_offset = fw_addr + fw_len;
	smsdev->client->flags |= I2C_M_IGNORE_NAK;
	while (fw_len)
	{
		sms_debug("Sending backdoor command.\n");
		ret = smsi2c_sendrequest(context, &BackdoorMsg, sizeof(BackdoorMsg));
		if (ret < 0)
		{
			sms_err ("failed sending backdoor command");
			return ret;
		}

		msleep(30);
		chunk_size = min((int)fw_len, MAX_CHUNK_SIZE);

		dnl_offset -= chunk_size;
		fw_len -= chunk_size;
		dummy_hdr[1] = chunk_size;
		dummy_hdr[2] = dnl_offset;

		dummy_crc=0;
		for (i = 0; i < 8 ; i++)
		{
			dummy_crc ^= ((u8*)dummy_hdr)[4+i];
		}
		for (i = 0; i < chunk_size ; i++)
		{
			dummy_crc ^= ((u8*)(fw_data+fw_len))[i];
		}
		sms_debug("download chunk size %d at offset 0x%x, act crc is 0x%x.\n", chunk_size, dnl_offset, dummy_crc);
		if (dnl_offset == fw_addr)
		{ /* Only for the last chunk send the correct CRC*/
			dummy_hdr[0] = dummy_crc;
		}
		else
		{/* for all but last chunk, make sure crc is wrong*/
			dummy_hdr[0] = dummy_crc^0x55;
		}
		/*send header of current chunk*/
		ret = smsi2c_sendrequest(context, (u8*)dummy_hdr, 12);
		if (ret < 0)
		{
			sms_err ("failed sending fw header");
			return ret;
		}
		msleep(20);
		/*send the data of current chunk*/
		ret = smsi2c_sendrequest(context, 
						(u8*)(fw_data+fw_len), 
						chunk_size);
		if (ret < 0)
		{
			sms_err ("failed sending fw data");
			return ret;
		}
		msleep(30);
	}
	sms_debug("FW download complete.\n");
	smsdev->client->flags = flags_bak;
	//msleep(400);
	smsi2c_ts_enable(context);

	return 0;
}
static int smsi2c_loadfirmware_handler(void *context, void* p_data, u32 fw_size)
{
	int ret;
	u8* fw_buf = (u8*)p_data;
	
	struct SmsMsgHdr_S BackdoorMsg = {
		MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ, 0, HIF_TASK,
			sizeof(struct SmsMsgHdr_S), 0};
	
	struct SmsTsEnable_S TsEnableMsg = {{MSG_SMS_ENBALE_TS_INTERFACE_REQ, 
					0, 
					11,
					sizeof(struct SmsTsEnable_S),
					0},
					15000000,
					TSI_SERIAL_ON_SDIO,
					TSI_SIGNALS_ACTIVE_LOW,
					0,
					TSI_SIG_OUT_FALL_EDGE,
					TSI_BIT0_IS_MSB,
					0,
					TSI_ENCAPSULATED,
					21};
	
	u32 sizeToCalc;
	u8* ptr;
    u32 checkSum;
    u32 i;
	
	u32* pFirstHeader = (u32*)fw_buf;
    	u32 SecondHeader[3];
	
	if (fw_size > 60*1024)
	{
		/* Send last part */
		SecondHeader[0] = 0xffffffff;        /* Impossible checksum */
		SecondHeader[1] = pFirstHeader[1] - 2*MAX_CHUNK_SIZE; /* Length of second chunk */
		SecondHeader[2] = pFirstHeader[2] + 2*MAX_CHUNK_SIZE; /* Address of second chunk */
		
		ret = smsi2c_sendrequest(context, &BackdoorMsg, sizeof(BackdoorMsg));
		msleep(50);

		ret = smsi2c_sendrequest(context, (u8*)(SecondHeader), 12);
		msleep(50);
		
		ret = smsi2c_sendrequest(context, 
						(u8*)(fw_buf+12+2*MAX_CHUNK_SIZE), 
						pFirstHeader[1] - 2*MAX_CHUNK_SIZE);
		msleep(50);
		
		/* Send middle part */
		SecondHeader[0] = 0xffffffff;             
		SecondHeader[1] = MAX_CHUNK_SIZE;         
		SecondHeader[2] = pFirstHeader[2] + MAX_CHUNK_SIZE;         
		
		ret = smsi2c_sendrequest(context, &BackdoorMsg, sizeof(BackdoorMsg));
		msleep(50);

		ret = smsi2c_sendrequest(context, (u8*)(SecondHeader), 12);
		msleep(50);
		
		ret = smsi2c_sendrequest(context, 
							(u8*)(fw_buf+12+MAX_CHUNK_SIZE), 
							MAX_CHUNK_SIZE);
		msleep(50);
		
		/* Send first part
		   Fix checksum */
		pFirstHeader[1] = MAX_CHUNK_SIZE;
		sizeToCalc = pFirstHeader[1] + 8;
		ptr = fw_buf + 4;

		checkSum = 0;

		for (i = 0; i < sizeToCalc; i++)
		{
			  checkSum ^= *(ptr + i);
		}

		pFirstHeader[0] = checkSum;                     

		ret = smsi2c_sendrequest(context, &BackdoorMsg, sizeof(BackdoorMsg));
		msleep(50);

		ret = smsi2c_sendrequest(context, (u8*)(pFirstHeader), 12);
		msleep(50);
		
		ret = smsi2c_sendrequest(context, 
								(u8*)(fw_buf+12),
								MAX_CHUNK_SIZE);
	}
	else
	{
		ret = smsi2c_sendrequest(context, (u8*)(fw_buf), 12);
		msleep(20);
			
		ret = smsi2c_sendrequest(context, (u8*)(fw_buf+12), fw_size-12);
	}
	
	msleep(20);
						
	ret = smsi2c_sendrequest(context, &TsEnableMsg, sizeof(TsEnableMsg));
	
	return 0;
}