Merge branch 'develop-3.0' of ssh://10.10.10.29/rk/kernel into develop-3.0

This commit is contained in:
lintao
2013-09-04 11:34:44 +08:00
21 changed files with 5898 additions and 10 deletions

View File

@@ -79,6 +79,10 @@
#include "../../../drivers/staging/android/timed_gpio.h"
#endif
#if defined(CONFIG_BOARD_ID)
#include <linux/board-id.h>
#endif
#if defined(CONFIG_MT6620)
#include <linux/gps.h>
#endif
@@ -2323,6 +2327,193 @@ static void rk30_pm_power_off(void)
while (1);
}
#if defined(CONFIG_BOARD_ID)
static int board_id_init(void)
{
return 0;
}
static int board_id_deinit(void)
{
return 0;
}
#if defined(CONFIG_BOARD_ID_FLASH)
static struct valid_invalid_name __initdata valid_device_name[] = {
{"rk-fb"},
{"mali400_ump"},
{"rk30-lcdc"},
{"ion-rockchip"},
{"a10_tp_syn"},
//pmic
{"act8846"},
{"wm8326"},
{"tps65910"},
/*angle*/
{"angle_kxtik"},
{"angle_lis3dh"},
{"angle_mma7660"},
/*gsensor*/
{"gsensor"},
{"gs_mma8452"},
{"gs_kxtik"},
{"gs_kxtj9"},
{"gs_lis3dh"},
{"gs_mma7660"},
{"gs_mxc6225"},
/*compass*/
{"compass"},
{"ak8975"},
{"ak8963"},
{"ak09911"},
{"mmc314x"},
/*gyroscope*/
{"gyro"},
{"l3g4200d_gryo"},
{"l3g20d_gryo"},
{"k3g"},
/*light sensor*/
{"lightsensor"},
{"light_cm3217"},
{"light_cm3232"},
{"light_al3006"},
{"ls_stk3171"},
{"ls_isl29023"},
{"ls_ap321xx"},
{"ls_photoresistor"},
{"ls_us5152"},
/*proximity sensor*/
{"psensor"},
{"proximity_al3006"},
{"ps_stk3171"},
{"ps_ap321xx"},
/*temperature*/
{"temperature"},
{"tmp_ms5607"},
/*pressure*/
{"pressure"},
{"pr_ms5607"},
{"rk610_ctl"},
{"rk-lid"},
{"rt3261"},
};
static struct valid_invalid_name __initdata invalid_device_name[5] = {
{"st480"},
{"rk1000_i2c_codec"},
{"rk1000_control"},
{"leds-lm3642"},
{"leds-lm2759"},
};
static struct board_device_table __initdata device_table[] = {
//don't move
{.addr = (int *)valid_device_name, .size = ARRAY_SIZE(valid_device_name), .type = BOARD_DEVICE_TYPE_VALID},
{.addr = (int *)invalid_device_name, .size = ARRAY_SIZE(invalid_device_name), .type = BOARD_DEVICE_TYPE_INVALID},
#if defined(CONFIG_I2C0_RK30)
{.addr = (int *)i2c0_info, .size = ARRAY_SIZE(i2c0_info), .type = BOARD_DEVICE_TYPE_I2C, .bus = BUS_NUM_I2C_0},
#endif
#if defined(CONFIG_I2C1_RK30)
{.addr = (int *)i2c1_info, .size = ARRAY_SIZE(i2c1_info), .type = BOARD_DEVICE_TYPE_I2C, .bus = BUS_NUM_I2C_1},
#endif
#if defined(CONFIG_I2C2_RK30)
{.addr = (int *)i2c2_info, .size = ARRAY_SIZE(i2c2_info), .type = BOARD_DEVICE_TYPE_I2C, .bus = BUS_NUM_I2C_2},
#endif
#if defined(CONFIG_I2C3_RK30)
{.addr = (int *)i2c3_info, .size = ARRAY_SIZE(i2c3_info), .type = BOARD_DEVICE_TYPE_I2C, .bus = BUS_NUM_I2C_3},
#endif
#if defined(CONFIG_I2C4_RK30)
{.addr = (int *)i2c4_info, .size = ARRAY_SIZE(i2c4_info), .type = BOARD_DEVICE_TYPE_I2C, .bus = BUS_NUM_I2C_4},
#endif
#if defined(CONFIG_I2C_GPIO_RK30)
{.addr = (int *)i2c_gpio_info, .size = ARRAY_SIZE(i2c_gpio_info), .type = BOARD_DEVICE_TYPE_I2C, .bus = BUS_NUM_I2C_GPIO},
#endif
{.addr = (int *)board_spi_devices, .size = ARRAY_SIZE(board_spi_devices), .type = BOARD_DEVICE_TYPE_SPI},
{.addr = (int *)devices, .size = ARRAY_SIZE(devices), .type = BOARD_DEVICE_TYPE_PLATFORM},
};
#endif
#if defined(CONFIG_BOARD_ID_HW)
static int board_id_hw_init_paramter(int id)
{
if(id < 0)
return -1;
switch(id)
{
case BOARD_ID_DS763:
//to do
break;
case BOARD_ID_AIO_BAT:
//to do
break;
default:
break;
}
return 0;
}
#endif
static struct board_id_platform_data board_id_info = {
.init_platform_hw = board_id_init,
.exit_platform_hw = board_id_deinit,
#if defined(CONFIG_BOARD_ID_FLASH)
//board_id_flash
.device_table_size = ARRAY_SIZE(device_table),
#endif
#if defined(CONFIG_BOARD_ID_HW)
//or board_id_hw
.gpio_pin = {RK30_PIN0_PC4,RK30_PIN0_PC5,RK30_PIN0_PC6,RK30_PIN0_PC7},
.num_gpio = 4,
.init_parameter = board_id_hw_init_paramter,
#endif
};
static struct platform_device device_board_id = {
#if defined(CONFIG_BOARD_ID_FLASH)
.name = "board_id",
#elif defined(CONFIG_BOARD_ID_HW)
.name = "board_id_hw",
#endif
.id = -1,
.dev = {
.platform_data = &board_id_info,
},
};
static struct platform_device *devices_id[] __initdata = {
&device_board_id,
};
#endif
static void __init machine_rk30_board_init(void)
{
//avs_init();
@@ -2333,11 +2524,25 @@ static void __init machine_rk30_board_init(void)
gpio_direction_output(POWER_ON_PIN, GPIO_HIGH);
#if defined(CONFIG_BOARD_ID)
#if defined(CONFIG_BOARD_ID_FLASH)
board_id_info.device_table = device_table;
platform_add_devices(devices_id, ARRAY_SIZE(devices_id));
rk_platform_add_display_devices();
#elif defined(CONFIG_BOARD_ID_HW)
rk30_i2c_register_board_info();
spi_register_board_info(board_spi_devices, ARRAY_SIZE(board_spi_devices));
platform_add_devices(devices, ARRAY_SIZE(devices));
rk_platform_add_display_devices();
platform_add_devices(devices_id, ARRAY_SIZE(devices_id));
#endif
#else
rk30_i2c_register_board_info();
spi_register_board_info(board_spi_devices, ARRAY_SIZE(board_spi_devices));
platform_add_devices(devices, ARRAY_SIZE(devices));
rk_platform_add_display_devices();
#endif
board_usb_detect_init(RK30_PIN0_PA7);
#if defined(CONFIG_WIFI_CONTROL_FUNC)

View File

@@ -123,6 +123,7 @@ config RK_CLOCK_PROC
depends on PROC_FS
source arch/arm/plat-rk/rk_pm_tests/Kconfig
source arch/arm/plat-rk/bid/Kconfig
if !ARCH_RK29
menu "Support for RK power manage"

View File

@@ -19,3 +19,4 @@ obj-$(CONFIG_DVFS) += dvfs.o
obj-y += pwm.o
obj-$(CONFIG_RK_TIMER) += rk_timer.o
obj-$(CONFIG_RK_PM_TESTS) += rk_pm_tests/
obj-$(CONFIG_BOARD_ID) += bid/

19
arch/arm/plat-rk/bid/Kconfig Executable file
View File

@@ -0,0 +1,19 @@
menuconfig BOARD_ID
bool "board id support for OneImage solution"
default n
choice
depends on BOARD_ID
prompt "board id type"
config BOARD_ID_FLASH
bool "board id save in flash"
config BOARD_ID_AUTO_XML
bool "auto print cust.xml"
depends on BOARD_ID_FLASH
config BOARD_ID_HW
bool "board id get from hardware such as gpios"
endchoice

5
arch/arm/plat-rk/bid/Makefile Executable file
View File

@@ -0,0 +1,5 @@
# rockchip board id select devices
obj-$(CONFIG_BOARD_ID) += board-id.o
obj-$(CONFIG_BOARD_ID_FLASH) += board-id-flash.o
obj-$(CONFIG_BOARD_ID_HW) += board-id-hw.o

View File

@@ -0,0 +1,870 @@
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/miscdevice.h>
#include <linux/circ_buf.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <mach/iomux.h>
#include <mach/gpio.h>
#include <asm/gpio.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/wakelock.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/file.h>
#include <linux/mm.h>
#include <linux/list.h>
#include <linux/debugfs.h>
#include <linux/mempolicy.h>
#include <linux/sched.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/cacheflush.h>
#include <linux/fb.h>
#include <plat/ipp.h>
#include <linux/board-id.h>
extern struct board_id_private_data *g_board_id;
#if defined(CONFIG_BOARD_ID_AUTO_XML)
#define MAX_BUF_LEN 200
static ssize_t board_id_proc_write(struct file *file, const char __user *buffer,
size_t count, loff_t *data)
{
char c;
int rc;
int i = 0, num = 0, j = 0;
struct board_id_private_data *board_id = g_board_id;
char buf[MAX_BUF_LEN];
struct device_id_name *device_id_name_start = board_id->tp_id_name;
struct area_id_name *area_id_name_start = board_id->area_area_id_name;
int max_id = TP_ID_NUMS + LCD_ID_NUMS + KEY_ID_NUMS + CODEC_ID_NUMS + WIFI_ID_NUMS + BT_ID_NUMS + GPS_ID_NUMS + FM_ID_NUMS + MODEM_ID_NUMS + DDR_ID_NUMS + FLASH_ID_NUMS + HDMI_ID_NUMS
+ BATTERY_ID_NUMS + CHARGE_ID_NUMS + BACKLIGHT_ID_NUMS + HEADSET_ID_NUMS + MICPHONE_ID_NUMS + SPEAKER_ID_NUMS + VIBRATOR_ID_NUMS + TV_ID_NUMS
+ ECHIP_ID_NUMS + HUB_ID_NUMS + TPAD_ID_NUMS + PMIC_ID_NUMS + REGULATOR_ID_NUMS + RTC_ID_NUMS + CAMERA_FRONT_ID_NUMS + CAMERA_BACK_ID_NUMS + ANGLE_ID_NUMS + ACCEL_ID_NUMS
+ COMPASS_ID_NUMS + GYRO_ID_NUMS + LIGHT_ID_NUMS + PROXIMITY_ID_NUMS + TEMPERATURE_ID_NUMS + PRESSURE_ID_NUMS;
rc = get_user(c, buffer);
if (rc)
{
atomic_set(&board_id->flags.debug_flag, 0);
return rc;
}
num = c - '0';
printk("%s command list:debug close:0,debug enable:1, create /data/board-id-data.txt :2, create /data/board-id-cust.xml:3, create /data/board-id-device.xml :4\n",__func__);
switch(num)
{
case 0:
case 1:
if(board_id)
atomic_set(&board_id->flags.debug_flag, num);
break;
case 2:
printk("%s:create /data/board-id-data.txt file\n",__func__);
if(!board_id->board_id_data_filp)
board_id->board_id_data_filp = filp_open("/data/board-id-data.txt",O_CREAT|O_TRUNC|O_RDWR,0);
if (board_id->board_id_data_filp)
{
board_id->board_id_data_fs = get_fs();
set_fs(get_ds());
}
memset(buf, 0, MAX_BUF_LEN);
for(i=0; i<max_id; i++)
{
if(device_id_name_start->type && *device_id_name_start->dev_name)
{
snprintf(buf, MAX_BUF_LEN, "type=%d,id=%d,name=%s:%s,%d", device_id_name_start->type, device_id_name_start->id, device_id_name_start->dev_name, device_id_name_start->description, device_id_name_start->device_id);
buf[MAX_BUF_LEN-1] = '\n';
board_id->board_id_data_filp->f_op->write(board_id->board_id_data_filp, buf, MAX_BUF_LEN, &board_id->board_id_data_filp->f_pos);
}
memset(buf,0,MAX_BUF_LEN);
device_id_name_start++;
}
memset(buf, '\n', MAX_BUF_LEN);
board_id->board_id_data_filp->f_op->write(board_id->board_id_data_filp, buf, 3, &board_id->board_id_data_filp->f_pos);
device_id_name_start = board_id->device_selected;
memset(buf, 0, MAX_BUF_LEN);
for(i=0; i<DEVICE_NUM_TYPES; i++)
{
if(device_id_name_start->type && *device_id_name_start->dev_name)
{
snprintf(buf, MAX_BUF_LEN, "device_selected: type=%d,id=%d,name=%s:%s,%d", device_id_name_start->type, device_id_name_start->id, device_id_name_start->dev_name, device_id_name_start->description, device_id_name_start->device_id);
buf[MAX_BUF_LEN-1] = '\n';
board_id->board_id_data_filp->f_op->write(board_id->board_id_data_filp, buf, MAX_BUF_LEN, &board_id->board_id_data_filp->f_pos);
}
memset(buf, 0, MAX_BUF_LEN);
device_id_name_start++;
}
memset(buf, '\n', MAX_BUF_LEN);
board_id->board_id_data_filp->f_op->write(board_id->board_id_data_filp, buf, 3, &board_id->board_id_data_filp->f_pos);
area_id_name_start = board_id->area_area_id_name;
memset(buf, 0, MAX_BUF_LEN);
for(i=AREA_ID_NULL; i<AREA_ID_NUMS+1; i++)
{
if(area_id_name_start->type && (strlen(area_id_name_start->locale_language) > 0))
{
if(i == AREA_ID_NUMS)
snprintf(buf, MAX_BUF_LEN, "area_selected: type=%d,id=%d,name=%s_%s", area_id_name_start->type, area_id_name_start->id, area_id_name_start->locale_language, area_id_name_start->locale_region);
else
snprintf(buf, MAX_BUF_LEN, "type=%d,id=%d,name=%s_%s", area_id_name_start->type, area_id_name_start->id, area_id_name_start->locale_language, area_id_name_start->locale_region);
buf[MAX_BUF_LEN-1] = '\n';
board_id->board_id_data_filp->f_op->write(board_id->board_id_data_filp, buf, MAX_BUF_LEN, &board_id->board_id_data_filp->f_pos);
}
memset(buf, 0, MAX_BUF_LEN);
area_id_name_start++;
}
break;
case 3:
if(!board_id->board_id_area_filp)
board_id->board_id_area_filp = filp_open("/data/board-id-cust.xml",O_CREAT|O_TRUNC|O_RDWR,0);
if (board_id->board_id_area_filp)
{
board_id->board_id_area_fs = get_fs();
set_fs(get_ds());
}
board_id->board_id_area_filp->f_op->write(board_id->board_id_area_filp, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n", 40, &board_id->board_id_area_filp->f_pos);
board_id->board_id_area_filp->f_op->write(board_id->board_id_area_filp, "<cust>\n", 7, &board_id->board_id_area_filp->f_pos);
area_id_name_start = board_id->area_area_id_name;
memset(buf, 0, MAX_BUF_LEN);
for(i=AREA_ID_NULL; i<AREA_ID_NUMS; i++)
{
if(area_id_name_start->type && (strlen(area_id_name_start->locale_language) > 0) && (strlen(area_id_name_start->locale_region) > 0))
{
memset(buf, 0, MAX_BUF_LEN);
snprintf(buf, MAX_BUF_LEN, "\t<if tid=\"%d\" bid=\"%d\" area=\"%s\">\n",area_id_name_start->type, area_id_name_start->id, area_id_name_start->country_area);
board_id->board_id_area_filp->f_op->write(board_id->board_id_area_filp, buf, MAX_BUF_LEN, &board_id->board_id_area_filp->f_pos);
memset(buf, 0, MAX_BUF_LEN);
snprintf(buf, MAX_BUF_LEN, "\t\t<set name=\"persist.sys.language\" value=\"%s\"/>\n\t\t<set name=\"persist.sys.country\" value=\"%s\"/>\n\t\t<set name=\"persist.sys.timezone\" value=\"%s\"/>\n", area_id_name_start->locale_language, area_id_name_start->locale_region, area_id_name_start->timezone);
board_id->board_id_area_filp->f_op->write(board_id->board_id_area_filp, buf, MAX_BUF_LEN, &board_id->board_id_area_filp->f_pos);
memset(buf, 0, MAX_BUF_LEN);
snprintf(buf, MAX_BUF_LEN, "\t\t<set name=\"ro.product.locale.language\" value=\"%s\"/>\n\t\t<set name=\"ro.product.locale.region\" value=\"%s\"/>\n", area_id_name_start->locale_language, area_id_name_start->locale_region);
board_id->board_id_area_filp->f_op->write(board_id->board_id_area_filp, buf, MAX_BUF_LEN, &board_id->board_id_area_filp->f_pos);
//memset(buf, 0, MAX_BUF_LEN);
//snprintf(buf, MAX_BUF_LEN, "\t\t<cp src=\"cust/app/area.apk\" des=\"system/app/area.apk\" mode=\"0644\"/>\n \t\t<rm src=\"system/app/area.apk\" />\n");
//board_id->board_id_area_filp->f_op->write(board_id->board_id_area_filp, buf, MAX_BUF_LEN, &board_id->board_id_area_filp->f_pos);
for(j=0; j<GMS_ID_NUMS; j++)
{
if(xml_config[i].gms_flag[j])
{
memset(buf, 0, MAX_BUF_LEN);
snprintf(buf, MAX_BUF_LEN, "\t\t<rm src=\"cust/app/%s\" des=\"system/app/%s\" mode=\"0644\"/>\n", gms_name[j].gms_name, gms_name[j].gms_name);
board_id->board_id_area_filp->f_op->write(board_id->board_id_area_filp, buf, MAX_BUF_LEN, &board_id->board_id_area_filp->f_pos);
}
}
//</if>
memset(buf, 0, MAX_BUF_LEN);
snprintf(buf, MAX_BUF_LEN, "\t</if>\n");
board_id->board_id_area_filp->f_op->write(board_id->board_id_area_filp, buf, MAX_BUF_LEN, &board_id->board_id_area_filp->f_pos);
}
memset(buf, 0, MAX_BUF_LEN);
if(i < AREA_ID_NUMS)
area_id_name_start++;
}
memset(buf, 0, MAX_BUF_LEN);
snprintf(buf, MAX_BUF_LEN, "\t<if area=\"!China\" language=\"!zh\" local=\"!CN\">\n");
board_id->board_id_area_filp->f_op->write(board_id->board_id_area_filp, buf, MAX_BUF_LEN, &board_id->board_id_area_filp->f_pos);
memset(buf, 0, MAX_BUF_LEN);
snprintf(buf, MAX_BUF_LEN, "\t\t<cp src=\"cust/app/area.apk\" des=\"system/app/area.apk\" mode=\"0644\"/>\n \t\t<rm src=\"system/app/area.apk\" />\n\t</if>\n");
board_id->board_id_area_filp->f_op->write(board_id->board_id_area_filp, buf, MAX_BUF_LEN, &board_id->board_id_area_filp->f_pos);
board_id->board_id_area_filp->f_op->write(board_id->board_id_area_filp, "</cust>\n", 8, &board_id->board_id_area_filp->f_pos);
printk("%s:/data/board-id-cust.xml file\n",__func__);
break;
case 4:
if(!board_id->board_id_device_filp)
board_id->board_id_device_filp = filp_open("/data/board-id-device.xml",O_CREAT|O_TRUNC|O_RDWR,0);
if (board_id->board_id_device_filp)
{
board_id->board_id_device_fs = get_fs();
set_fs(get_ds());
}
board_id->board_id_device_filp->f_op->write(board_id->board_id_device_filp, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n", 40, &board_id->board_id_device_filp->f_pos);
board_id->board_id_device_filp->f_op->write(board_id->board_id_device_filp, "<device>\n", 9, &board_id->board_id_device_filp->f_pos);
device_id_name_start = board_id->tp_id_name;
memset(buf, 0, MAX_BUF_LEN);
for(i=DEVICE_TYPE_TP; i<DEVICE_NUM_TYPES; i++)
{
device_id_name_start = board_id->device_start_addr[i];
device_id_name_start = board_id->tp_id_name;
for(j=0; j<max_id; j++)
{
if((device_id_name_start->type == i) && (strlen(device_id_name_start->dev_name) > 0))
{
memset(buf, 0, MAX_BUF_LEN);
snprintf(buf, MAX_BUF_LEN, "\t<if tid=\"%d\" bid=\"%d\" type=\"%s\" dev=\"%s\" desc=\"%s\">\n", device_id_name_start->type, device_id_name_start->id, device_id_name_start->type_name, device_id_name_start->dev_name, device_id_name_start->description);
board_id->board_id_device_filp->f_op->write(board_id->board_id_device_filp, buf, MAX_BUF_LEN, &board_id->board_id_device_filp->f_pos);
if(DEVICE_TYPE_KEY == device_id_name_start->type)
{
memset(buf, 0, MAX_BUF_LEN); //added by luodh
snprintf(buf, MAX_BUF_LEN, "\t\t<set name=\"ro.product.locale.keylayout\" value=\"%s\"/>\n", device_id_name_start->dev_name);
board_id->board_id_device_filp->f_op->write(board_id->board_id_device_filp, buf, MAX_BUF_LEN, &board_id->board_id_device_filp->f_pos);
}
memset(buf, 0, MAX_BUF_LEN);
snprintf(buf, MAX_BUF_LEN, "\t\t<cp src=\"cust/so/type.dev.so\" des=\"system/lib/hw/type.dev.so\" mode=\"0644\"/>\n \t\t<rm src=\"system/lib/hw/type.dev.so\"/>\n");
board_id->board_id_device_filp->f_op->write(board_id->board_id_device_filp, buf, MAX_BUF_LEN, &board_id->board_id_device_filp->f_pos);
memset(buf, 0, MAX_BUF_LEN);
snprintf(buf, MAX_BUF_LEN, "\t</if>\n");
board_id->board_id_device_filp->f_op->write(board_id->board_id_device_filp, buf, MAX_BUF_LEN, &board_id->board_id_device_filp->f_pos);
memset(buf, 0, MAX_BUF_LEN);
//printk("%s:type=%d,id=%d\n",__func__,device_id_name_start->type, device_id_name_start->id);
}
device_id_name_start++;
}
memset(buf, 0, MAX_BUF_LEN);
}
//board_id->board_id_device_filp->f_op->write(board_id->board_id_device_filp, "\t</type>\n", 9, &board_id->board_id_device_filp->f_pos);
board_id->board_id_device_filp->f_op->write(board_id->board_id_device_filp, "</device>\n", 10, &board_id->board_id_device_filp->f_pos);
printk("%s:/data/board-id-device.xml file\n",__func__);
break;
default:
break;
}
printk("%s %d\n", __func__, __LINE__);
return count;
}
static const struct file_operations board_id_proc_fops = {
.owner = THIS_MODULE,
.write = board_id_proc_write,
};
#endif
static int board_id_open(struct inode *inode, struct file *file)
{
struct board_id_private_data *board_id = g_board_id;
return 0;
}
static int board_id_release(struct inode *inode, struct file *file)
{
struct board_id_private_data *board_id = g_board_id;
return 0;
}
static struct device_id_name device_selected[DEVICE_NUM_TYPES];
static long board_id_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct board_id_private_data *board_id = g_board_id;
void __user *argp = (void __user *)arg;
struct area_id_name area_select = board_id->area_select;
struct operator_id_name operator_select = board_id->operator_select;
struct reserve_id_name reserve_select = board_id->reserve_select;
struct device_id_name device_selected_temp, device_selected_last_temp;
struct area_id_name language_last_select;
struct operator_id_name operator_last_select;
struct reserve_id_name reserve_last_select;
int result = 0;
int i = 0;
switch(cmd)
{
case BOARD_ID_IOCTL_READ_AREA_ID:
mutex_lock(&board_id->operation_mutex);
if(copy_to_user(argp, &area_select, sizeof(struct area_id_name)))
{
printk("%s:fail to copy area_id_name to user\n",__func__);
mutex_unlock(&board_id->operation_mutex);
return -EFAULT;
}
DBG_ID("%s:BOARD_ID_IOCTL_READ_LANGUAGE_ID:%s_%s\n",__func__,area_select.locale_language,area_select.locale_region);
mutex_unlock(&board_id->operation_mutex);
break;
case BOARD_ID_IOCTL_READ_OPERATOR_ID:
mutex_lock(&board_id->operation_mutex);
if(copy_to_user(argp, &operator_select, sizeof(struct operator_id_name)))
{
printk("%s:fail to copy operator_id_name to user\n",__func__);
mutex_unlock(&board_id->operation_mutex);
return -EFAULT;
}
DBG_ID("%s:BOARD_ID_IOCTL_READ_operator_ID:%s_%s\n",__func__,operator_select.operator_name,operator_select.locale_region);
mutex_unlock(&board_id->operation_mutex);
break;
case BOARD_ID_IOCTL_READ_RESERVE_ID:
mutex_lock(&board_id->operation_mutex);
if(copy_to_user(argp, &reserve_select, sizeof(struct reserve_id_name)))
{
printk("%s:fail to copy reserve_id_name to user\n",__func__);
mutex_unlock(&board_id->operation_mutex);
return -EFAULT;
}
DBG_ID("%s:BOARD_ID_IOCTL_READ_RESERVE_ID:%s,%s\n",__func__,reserve_select.reserve_name, reserve_select.locale_region);
mutex_unlock(&board_id->operation_mutex);
break;
case BOARD_ID_IOCTL_READ_STATUS:
mutex_lock(&board_id->operation_mutex);
if(copy_to_user(argp, &board_id->vendor_data[DEVICE_TYPE_STATUS], sizeof(board_id->vendor_data[DEVICE_TYPE_STATUS])))
{
printk("%s:line=%d:fail to copy vendor_data to user\n",__func__,__LINE__);
mutex_unlock(&board_id->operation_mutex);
return -EFAULT;
}
mutex_unlock(&board_id->operation_mutex);
DBG_ID("%s:BOARD_ID_IOCTL_READ_STATUS=0x%x\n",__func__,board_id->vendor_data[DEVICE_TYPE_STATUS]);
break;
case BOARD_ID_IOCTL_READ_VENDOR_DATA:
mutex_lock(&board_id->operation_mutex);
DBG_ID("%s:BOARD_ID_IOCTL_READ_VENDOR_DATA:\n",__func__);
if(copy_to_user(argp, board_id->vendor_data, sizeof(board_id->vendor_data)))
{
printk("%s:line=%d:fail to copy vendor_data to user\n",__func__,__LINE__);
mutex_unlock(&board_id->operation_mutex);
return -EFAULT;
}
mutex_unlock(&board_id->operation_mutex);
break;
}
mutex_lock(&board_id->operation_mutex);
switch(cmd)
{
case BOARD_ID_IOCTL_READ_TP_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_TP];
break;
case BOARD_ID_IOCTL_READ_LCD_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_LCD];
break;
case BOARD_ID_IOCTL_READ_KEY_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_KEY];
break;
case BOARD_ID_IOCTL_READ_CODEC_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_CODEC];
break;
case BOARD_ID_IOCTL_READ_WIFI_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_WIFI];
break;
case BOARD_ID_IOCTL_READ_BT_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_BT];
break;
case BOARD_ID_IOCTL_READ_GPS_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_GPS];
break;
case BOARD_ID_IOCTL_READ_FM_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_FM];
break;
case BOARD_ID_IOCTL_READ_MODEM_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_MODEM];
break;
case BOARD_ID_IOCTL_READ_DDR_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_DDR];
break;
case BOARD_ID_IOCTL_READ_FLASH_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_FLASH];
break;
case BOARD_ID_IOCTL_READ_HDMI_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_HDMI];
break;
case BOARD_ID_IOCTL_READ_BATTERY_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_BATTERY];
break;
case BOARD_ID_IOCTL_READ_CHARGE_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_CHARGE];
break;
case BOARD_ID_IOCTL_READ_BACKLIGHT_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_BACKLIGHT];
break;
case BOARD_ID_IOCTL_READ_HEADSET_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_HEADSET];
break;
case BOARD_ID_IOCTL_READ_MICPHONE_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_MICPHONE];
break;
case BOARD_ID_IOCTL_READ_SPEAKER_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_SPEAKER];
break;
case BOARD_ID_IOCTL_READ_VIBRATOR_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_VIBRATOR];
break;
case BOARD_ID_IOCTL_READ_TV_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_TV];
break;
case BOARD_ID_IOCTL_READ_ECHIP_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_ECHIP];
break;
case BOARD_ID_IOCTL_READ_HUB_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_HUB];
break;
case BOARD_ID_IOCTL_READ_TPAD_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_TPAD];
break;
case BOARD_ID_IOCTL_READ_PMIC_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_PMIC];
break;
case BOARD_ID_IOCTL_READ_REGULATOR_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_REGULATOR];
break;
case BOARD_ID_IOCTL_READ_RTC_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_RTC];
break;
case BOARD_ID_IOCTL_READ_CAMERA_FRONT_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_CAMERA_FRONT];
break;
case BOARD_ID_IOCTL_READ_CAMERA_BACK_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_CAMERA_BACK];
break;
case BOARD_ID_IOCTL_READ_SENSOR_ANGLE_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_ANGLE];
break;
case BOARD_ID_IOCTL_READ_SENSOR_ACCEL_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_ACCEL];
break;
case BOARD_ID_IOCTL_READ_SENSOR_COMPASS_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_COMPASS];
break;
case BOARD_ID_IOCTL_READ_SENSOR_GYRO_ID :
device_selected_temp = board_id->device_selected[DEVICE_TYPE_GYRO];
break;
case BOARD_ID_IOCTL_READ_SENSOR_LIGHT_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_LIGHT];
break;
case BOARD_ID_IOCTL_READ_SENSOR_PROXIMITY_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_PROXIMITY];
break;
case BOARD_ID_IOCTL_READ_SENSOR_TEMPERATURE_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_TEMPERATURE];
break;
case BOARD_ID_IOCTL_READ_SENSOR_PRESSURE_ID:
device_selected_temp = board_id->device_selected[DEVICE_TYPE_PRESSURE];
break;
case BOARD_ID_IOCTL_WRITE_TP_ID:
case BOARD_ID_IOCTL_WRITE_LCD_ID:
case BOARD_ID_IOCTL_WRITE_KEY_ID:
case BOARD_ID_IOCTL_WRITE_CODEC_ID:
case BOARD_ID_IOCTL_WRITE_WIFI_ID:
case BOARD_ID_IOCTL_WRITE_BT_ID:
case BOARD_ID_IOCTL_WRITE_GPS_ID:
case BOARD_ID_IOCTL_WRITE_FM_ID:
case BOARD_ID_IOCTL_WRITE_MODEM_ID:
case BOARD_ID_IOCTL_WRITE_DDR_ID:
case BOARD_ID_IOCTL_WRITE_FLASH_ID:
case BOARD_ID_IOCTL_WRITE_HDMI_ID:
case BOARD_ID_IOCTL_WRITE_BATTERY_ID:
case BOARD_ID_IOCTL_WRITE_CHARGE_ID:
case BOARD_ID_IOCTL_WRITE_BACKLIGHT_ID:
case BOARD_ID_IOCTL_WRITE_HEADSET_ID:
case BOARD_ID_IOCTL_WRITE_MICPHONE_ID:
case BOARD_ID_IOCTL_WRITE_SPEAKER_ID:
case BOARD_ID_IOCTL_WRITE_VIBRATOR_ID:
case BOARD_ID_IOCTL_WRITE_TV_ID:
case BOARD_ID_IOCTL_WRITE_ECHIP_ID:
case BOARD_ID_IOCTL_WRITE_HUB_ID:
case BOARD_ID_IOCTL_WRITE_PMIC_ID:
case BOARD_ID_IOCTL_WRITE_REGULATOR_ID:
case BOARD_ID_IOCTL_WRITE_RTC_ID:
case BOARD_ID_IOCTL_WRITE_CAMERA_FRONT_ID:
case BOARD_ID_IOCTL_WRITE_CAMERA_BACK_ID:
case BOARD_ID_IOCTL_WRITE_SENSOR_ANGLE_ID:
case BOARD_ID_IOCTL_WRITE_SENSOR_ACCEL_ID:
case BOARD_ID_IOCTL_WRITE_SENSOR_COMPASS_ID:
case BOARD_ID_IOCTL_WRITE_SENSOR_GYRO_ID:
case BOARD_ID_IOCTL_WRITE_SENSOR_LIGHT_ID:
case BOARD_ID_IOCTL_WRITE_SENSOR_PROXIMITY_ID:
case BOARD_ID_IOCTL_WRITE_SENSOR_TEMPERATURE_ID:
case BOARD_ID_IOCTL_READ_DEVICE_NAME_BY_ID:
if(copy_from_user(&device_selected_temp, argp, sizeof(struct device_id_name)))
{
printk("%s:line=%d:fail to copy device_id_name from user\n",__func__, __LINE__);
mutex_unlock(&board_id->operation_mutex);
return -EFAULT;
}
DBG_ID("%s:write: type=%d,id=%d,name=%s\n",__func__, (int)device_selected_temp.type, (int)device_selected_temp.id, device_selected_temp.dev_name);
break;
}
switch(cmd)
{
case BOARD_ID_IOCTL_READ_TP_ID:
case BOARD_ID_IOCTL_READ_LCD_ID:
case BOARD_ID_IOCTL_READ_KEY_ID:
case BOARD_ID_IOCTL_READ_CODEC_ID:
case BOARD_ID_IOCTL_READ_WIFI_ID:
case BOARD_ID_IOCTL_READ_BT_ID:
case BOARD_ID_IOCTL_READ_GPS_ID:
case BOARD_ID_IOCTL_READ_FM_ID:
case BOARD_ID_IOCTL_READ_MODEM_ID:
case BOARD_ID_IOCTL_READ_DDR_ID:
case BOARD_ID_IOCTL_READ_FLASH_ID:
case BOARD_ID_IOCTL_READ_HDMI_ID:
case BOARD_ID_IOCTL_READ_BATTERY_ID:
case BOARD_ID_IOCTL_READ_CHARGE_ID:
case BOARD_ID_IOCTL_READ_BACKLIGHT_ID:
case BOARD_ID_IOCTL_READ_HEADSET_ID:
case BOARD_ID_IOCTL_READ_MICPHONE_ID:
case BOARD_ID_IOCTL_READ_SPEAKER_ID:
case BOARD_ID_IOCTL_READ_VIBRATOR_ID:
case BOARD_ID_IOCTL_READ_TV_ID:
case BOARD_ID_IOCTL_READ_ECHIP_ID:
case BOARD_ID_IOCTL_READ_HUB_ID:
case BOARD_ID_IOCTL_READ_PMIC_ID:
case BOARD_ID_IOCTL_READ_REGULATOR_ID:
case BOARD_ID_IOCTL_READ_RTC_ID:
case BOARD_ID_IOCTL_READ_CAMERA_FRONT_ID:
case BOARD_ID_IOCTL_READ_CAMERA_BACK_ID:
case BOARD_ID_IOCTL_READ_SENSOR_ANGLE_ID:
case BOARD_ID_IOCTL_READ_SENSOR_ACCEL_ID:
case BOARD_ID_IOCTL_READ_SENSOR_COMPASS_ID:
case BOARD_ID_IOCTL_READ_SENSOR_GYRO_ID :
case BOARD_ID_IOCTL_READ_SENSOR_LIGHT_ID:
case BOARD_ID_IOCTL_READ_SENSOR_PROXIMITY_ID:
case BOARD_ID_IOCTL_READ_SENSOR_TEMPERATURE_ID:
case BOARD_ID_IOCTL_READ_SENSOR_PRESSURE_ID:
if(copy_to_user(argp, &device_selected_temp, sizeof(struct device_id_name)))
{
printk("%s:line=%d:fail to copy device_selected_temp.dev_name=%s to user\n",__func__,__LINE__,device_selected_temp.dev_name);
mutex_unlock(&board_id->operation_mutex);
return -EFAULT;
}
DBG_ID("%s:read: type=%d,id=%d,name=%s\n",__func__, (int)device_selected_temp.type, (int)device_selected_temp.id, device_selected_temp.dev_name);
break;
case BOARD_ID_IOCTL_WRITE_TP_ID:
board_id->device_selected[DEVICE_TYPE_TP] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_LCD_ID:
board_id->device_selected[DEVICE_TYPE_LCD] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_KEY_ID:
board_id->device_selected[DEVICE_TYPE_KEY] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_CODEC_ID:
board_id->device_selected[DEVICE_TYPE_CODEC] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_WIFI_ID:
board_id->device_selected[DEVICE_TYPE_WIFI] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_BT_ID:
board_id->device_selected[DEVICE_TYPE_BT] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_GPS_ID:
board_id->device_selected[DEVICE_TYPE_GPS] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_FM_ID:
board_id->device_selected[DEVICE_TYPE_FM] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_MODEM_ID:
board_id->device_selected[DEVICE_TYPE_MODEM] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_DDR_ID:
board_id->device_selected[DEVICE_TYPE_DDR] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_FLASH_ID:
board_id->device_selected[DEVICE_TYPE_FLASH] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_HDMI_ID:
board_id->device_selected[DEVICE_TYPE_HDMI] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_BATTERY_ID:
board_id->device_selected[DEVICE_TYPE_BATTERY] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_CHARGE_ID:
board_id->device_selected[DEVICE_TYPE_CHARGE] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_BACKLIGHT_ID:
board_id->device_selected[DEVICE_TYPE_BACKLIGHT] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_HEADSET_ID:
board_id->device_selected[DEVICE_TYPE_HEADSET] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_MICPHONE_ID:
board_id->device_selected[DEVICE_TYPE_MICPHONE] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_SPEAKER_ID:
board_id->device_selected[DEVICE_TYPE_SPEAKER] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_VIBRATOR_ID:
board_id->device_selected[DEVICE_TYPE_VIBRATOR] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_TV_ID:
board_id->device_selected[DEVICE_TYPE_TV] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_ECHIP_ID:
board_id->device_selected[DEVICE_TYPE_ECHIP] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_HUB_ID:
board_id->device_selected[DEVICE_TYPE_HUB] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_TPAD_ID:
board_id->device_selected[DEVICE_TYPE_TPAD] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_PMIC_ID:
board_id->device_selected[DEVICE_TYPE_PMIC] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_REGULATOR_ID:
board_id->device_selected[DEVICE_TYPE_REGULATOR] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_RTC_ID:
board_id->device_selected[DEVICE_TYPE_RTC] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_CAMERA_FRONT_ID:
board_id->device_selected[DEVICE_TYPE_CAMERA_FRONT] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_CAMERA_BACK_ID:
board_id->device_selected[DEVICE_TYPE_CAMERA_BACK] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_SENSOR_ANGLE_ID:
board_id->device_selected[DEVICE_TYPE_ANGLE] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_SENSOR_ACCEL_ID:
board_id->device_selected[DEVICE_TYPE_ACCEL] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_SENSOR_COMPASS_ID:
board_id->device_selected[DEVICE_TYPE_COMPASS] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_SENSOR_GYRO_ID:
board_id->device_selected[DEVICE_TYPE_GYRO] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_SENSOR_LIGHT_ID:
board_id->device_selected[DEVICE_TYPE_LIGHT] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_SENSOR_PROXIMITY_ID:
board_id->device_selected[DEVICE_TYPE_PROXIMITY] = device_selected_temp;
break;
case BOARD_ID_IOCTL_WRITE_SENSOR_TEMPERATURE_ID:
board_id->device_selected[DEVICE_TYPE_TEMPERATURE] = device_selected_temp;
break;
}
mutex_unlock(&board_id->operation_mutex);
switch(cmd)
{
case BOARD_ID_IOCTL_READ_DEVICE_NAME_BY_ID:
mutex_lock(&board_id->operation_mutex);
if(&board_id->device_start_addr[(unsigned)device_selected_temp.type][(unsigned)device_selected_temp.id])
memcpy(&device_selected_last_temp, &board_id->device_start_addr[(unsigned)device_selected_temp.type][(unsigned)device_selected_temp.id], sizeof(struct device_id_name));
else
{
printk("%s:fail to find device,type=%d,id=%d\n",__func__, device_selected_temp.type, device_selected_temp.id);
mutex_unlock(&board_id->operation_mutex);
return -1;
}
if(copy_to_user(argp, &device_selected_last_temp, sizeof(struct device_id_name)))
{
printk("%s:line=%d:fail to copy device_selected_last_temp.dev_name=%s to user\n",__func__,__LINE__,device_selected_last_temp.dev_name);
mutex_unlock(&board_id->operation_mutex);
return -EFAULT;
}
DBG_ID("%s:read: type=%d,id=%d,name=%s\n",__func__, (int)device_selected_last_temp.type, (int)device_selected_last_temp.id, device_selected_last_temp.dev_name);
mutex_unlock(&board_id->operation_mutex);
break;
case BOARD_ID_IOCTL_READ_AREA_NAME_BY_ID:
mutex_lock(&board_id->operation_mutex);
if(copy_from_user(&language_last_select, argp, sizeof(struct area_id_name)))
{
printk("%s:line=%d:fail to copy area_id_name from user\n",__func__, __LINE__);
mutex_unlock(&board_id->operation_mutex);
return -EFAULT;
}
if(copy_to_user(argp, &board_id->area_area_id_name[language_last_select.id], sizeof(struct area_id_name)))
{
printk("%s:fail to copy area_id_name to user\n",__func__);
mutex_unlock(&board_id->operation_mutex);
return -EFAULT;
}
mutex_unlock(&board_id->operation_mutex);
DBG_ID("%s:BOARD_ID_IOCTL_READ_LANGUAGE_NAME_BY_ID:%s_%s\n",__func__,language_last_select.locale_language,language_last_select.locale_region);
break;
case BOARD_ID_IOCTL_READ_OPERATOR_NAME_BY_ID:
mutex_lock(&board_id->operation_mutex);
if(copy_from_user(&operator_last_select, argp, sizeof(struct operator_id_name)))
{
printk("%s:line=%d:fail to copy operator_id_name from user\n",__func__, __LINE__);
mutex_unlock(&board_id->operation_mutex);
return -EFAULT;
}
for(i=OPERATOR_ID_20000_NO_OPERATOR; i<OPERATOR_ID_NUMS; i++)
{
if(operator_last_select.id == board_id->area_operator_id_name[i].id)
{
if(copy_to_user(argp, &board_id->area_operator_id_name[i], sizeof(struct operator_id_name)))
{
printk("%s:fail to copy operator_id_name to user\n",__func__);
mutex_unlock(&board_id->operation_mutex);
return -EFAULT;
}
}
}
mutex_unlock(&board_id->operation_mutex);
DBG_ID("%s:BOARD_ID_IOCTL_READ_OPERATOR_NAME_BY_ID:%s_%s\n",__func__,operator_last_select.operator_name,operator_last_select.locale_region);
break;
case BOARD_ID_IOCTL_READ_RESERVE_NAME_BY_ID:
mutex_lock(&board_id->operation_mutex);
if(copy_from_user(&reserve_last_select, argp, sizeof(struct reserve_id_name)))
{
printk("%s:line=%d:fail to copy reserve_id_name from user\n",__func__, __LINE__);
mutex_unlock(&board_id->operation_mutex);
return -EFAULT;
}
if(copy_to_user(argp, &board_id->area_reserve_id_name[reserve_last_select.id], sizeof(struct reserve_id_name)))
{
printk("%s:fail to copy reserve_id_name to user\n",__func__);
mutex_unlock(&board_id->operation_mutex);
return -EFAULT;
}
mutex_unlock(&board_id->operation_mutex);
DBG_ID("%s:BOARD_ID_IOCTL_READ_RESERVE_NAME_BY_ID:%s_%s\n",__func__,reserve_last_select.reserve_name, reserve_last_select.locale_region);
break;
}
DBG_ID("%s:cmd=%d\n",__func__,cmd);
return 0;
}
static int __init board_id_init(void)
{
int result ;
struct proc_dir_entry *board_id_proc_entry;
struct board_id_private_data *board_id = g_board_id;
if(!board_id)
return -1;
board_id->id_fops.owner = THIS_MODULE;
board_id->id_fops.open = board_id_open;
board_id->id_fops.release = board_id_release;
board_id->id_fops.unlocked_ioctl = board_id_ioctl;
board_id->id_miscdev.minor = MISC_DYNAMIC_MINOR;
board_id->id_miscdev.name = "board_id_misc";
board_id->id_miscdev.fops = &board_id->id_fops;
result = misc_register(&board_id->id_miscdev);
if(result < 0) {
printk("%s:misc_register err,ret=%d\n",__func__,result);
return result;
}
#if defined(CONFIG_BOARD_ID_AUTO_XML)
board_id_proc_entry = proc_create("driver/board_id_dbg", 0660, NULL, &board_id_proc_fops);
#endif
board_id->board_id_data_filp = NULL;
board_id->board_id_area_filp = NULL;
board_id->board_id_device_filp = NULL;
printk("%s:\n",__func__);
return 0;
}
static void __exit board_id_exit(void)
{
struct board_id_private_data *board_id = g_board_id;
if(!board_id)
return ;
misc_deregister(&board_id->id_miscdev);
set_fs(board_id->board_id_data_fs);
filp_close(board_id->board_id_data_filp, NULL);
set_fs(board_id->board_id_area_fs);
filp_close(board_id->board_id_area_filp, NULL);
set_fs(board_id->board_id_device_fs);
filp_close(board_id->board_id_device_filp, NULL);
}
subsys_initcall_sync(board_id_init);
module_exit(board_id_exit);
MODULE_AUTHOR("ROCKCHIP Corporation:lw@rock-chips.com");
MODULE_DESCRIPTION("rockchip board id misc interface for vendor");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,163 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/skbuff.h>
#include <mach/board.h>
#include <mach/io.h>
#include <mach/gpio.h>
#include <mach/iomux.h>
#include <linux/board-id.h>
#if 0
#define DBG(x...) printk(x)
#else
#define DBG(x...)
#endif
extern void kernel_restart(char *cmd);
struct board_id_hw_private_data {
struct mutex id_mutex;
int last_value[16];
int board_id;
struct board_id_platform_data *pdata;
};
static struct board_id_hw_private_data *g_id;
enum board_id_hw get_board_id_hw(void)
{
struct board_id_hw_private_data *id = g_id;
DBG("%s:id:0x%x\n",__func__,id->board_id);
return id->board_id;
}
EXPORT_SYMBOL(get_board_id_hw);
static int _get_board_id_hw(struct board_id_hw_private_data *id)
{
int result = 0;
int value1 = 0, value2 = 0, value3 = 0;
int i = 0, j = 0;
id->board_id = -1;
for(i=0; i<id->pdata->num_gpio; i++)
{
gpio_request(id->pdata->gpio_pin[i],"gpio_board_id");
gpio_direction_input(id->pdata->gpio_pin[i]);
gpio_pull_updown(id->pdata->gpio_pin[i], PullDisable);
for(j=0; j<1000; j++)
{
value1 = gpio_get_value(id->pdata->gpio_pin[i]);
if(value1 < 0)
continue;
mdelay(1);
value2 = gpio_get_value(id->pdata->gpio_pin[i]);
if(value2 < 0)
continue;
mdelay(1);
value3 = gpio_get_value(id->pdata->gpio_pin[i]);
if(value3 < 0)
continue;
if((value1 == value2) && (value2 == value3))
break;
}
if(j >= 1000)
{
printk("%s:hareware error,gpio level changed always!\n",__func__);
kernel_restart(NULL);
}
result = (value1 << i) | result;
DBG("%s:gpio:%d,value:%d\n",__func__,id->pdata->gpio_pin[i],value1);
}
id->board_id = result;
DBG("%s:num=%d,id=0x%x\n",__func__,id->pdata->num_gpio, id->board_id);
return result;
}
static int __devinit board_id_hw_probe(struct platform_device *pdev)
{
struct board_id_platform_data *pdata = pdev->dev.platform_data;
struct board_id_hw_private_data *id = NULL;
int result = 0;
if(!pdata)
return -ENOMEM;
id = kzalloc(sizeof(struct board_id_hw_private_data), GFP_KERNEL);
if (id == NULL) {
dev_err(&pdev->dev, "Unable to allocate private data\n");
return -ENOMEM;
}
id->pdata = pdata;
if(pdata->init_platform_hw)
pdata->init_platform_hw();
result = _get_board_id_hw(id);
if(pdata->init_parameter)
pdata->init_parameter(id->board_id);
if(pdata->exit_platform_hw)
pdata->exit_platform_hw();
platform_set_drvdata(pdev, id);
g_id = id;
printk("%s:board id :0x%x\n",__func__,result);
return 0;
}
static int __devexit board_id_hw_remove(struct platform_device *pdev)
{
//struct board_id_platform_data *pdata = pdev->dev.platform_data;
struct board_id_hw_private_data *id = platform_get_drvdata(pdev);
kfree(id);
return 0;
}
static struct platform_driver board_id_hw_driver = {
.probe = board_id_hw_probe,
.remove = __devexit_p(board_id_hw_remove),
.driver = {
.name = "board_id_hw",
.owner = THIS_MODULE,
},
};
static int __init board_id_hw_init(void)
{
return platform_driver_register(&board_id_hw_driver);
}
static void __exit board_id_hw_exit(void)
{
platform_driver_unregister(&board_id_hw_driver);
}
arch_initcall_sync(board_id_hw_init);
module_exit(board_id_hw_exit);
MODULE_AUTHOR("ROCKCHIP Corporation:lw@rock-chips.com");
MODULE_DESCRIPTION("Interface for get board id");
MODULE_LICENSE("GPL");

1184
arch/arm/plat-rk/bid/board-id.c Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -232,8 +232,11 @@ struct sensor_platform_data {
struct board_id_platform_data {
int gpio_pin[32];
int num_gpio;
int (*init_platform_hw)(void);
char *board_id_buf;
int (*init_platform_hw)(void);
int (*exit_platform_hw)(void);
struct board_device_table *device_table;
int device_table_size;
int (*init_parameter)(int id);
};

View File

@@ -5,10 +5,10 @@
comment "handle all sensors"
menuconfig SENSOR_DEVICE
tristate "handle gsensor,compass,gyroscope,lsensor psensor etc"
tristate "handle angle,accel,compass,gyroscope,lsensor psensor etc"
if SENSOR_DEVICE
source "drivers/input/sensors/angle/Kconfig"
source "drivers/input/sensors/accel/Kconfig"
source "drivers/input/sensors/compass/Kconfig"
source "drivers/input/sensors/gyro/Kconfig"

View File

@@ -1,4 +1,5 @@
# sensor drivers
obj-$(CONFIG_ANGLE_DEVICE) += angle/
obj-$(CONFIG_GSENSOR_DEVICE) += accel/
obj-$(CONFIG_COMPASS_DEVICE) += compass/
obj-$(CONFIG_GYROSCOPE_DEVICE) += gyro/

View File

@@ -0,0 +1,26 @@
#
# gsensor drivers configuration
#
menuconfig ANGLE_DEVICE
bool "angle device support"
help
Enable this to be able to choose the drivers for controlling the
g_sensor on some platforms, for example on PDAs.
if ANGLE_DEVICE
config ANGLE_KXTIK
bool "angle kxtik"
help
To have support for your specific gsesnor you will have to
select the proper drivers which depend on this option.
config ANGLE_LIS3DH
bool "angle lis3dh"
help
To have support for your specific gsesnor you will have to
select the proper drivers which depend on this option.
endif

View File

@@ -0,0 +1,2 @@
obj-$(CONFIG_ANGLE_KXTIK) += angle_kxtik.o
obj-$(CONFIG_ANGLE_LIS3DH) += angle_lis3dh.o

View File

@@ -0,0 +1,394 @@
/* drivers/input/sensors/access/angle_kxtik.c
*
* Copyright (C) 2012-2015 ROCKCHIP.
* Author: luowei <lw@rock-chips.com>
*
* 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 <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/irq.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/workqueue.h>
#include <linux/freezer.h>
#include <mach/gpio.h>
#include <mach/board.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
#include <linux/sensor-dev.h>
#define KXTIK_DEVID_1004 0x05 //chip id
#define KXTIK_DEVID_J9_1005 0x07 //chip id
#define KXTIK_DEVID_J2_1009 0x09 //chip id
#define KXTIK_DEVID_1013 0x11 //chip id
#define KXTIK_RANGE 2000000
#define KXTIK_XOUT_HPF_L (0x00) /* 0000 0000 */
#define KXTIK_XOUT_HPF_H (0x01) /* 0000 0001 */
#define KXTIK_YOUT_HPF_L (0x02) /* 0000 0010 */
#define KXTIK_YOUT_HPF_H (0x03) /* 0000 0011 */
#define KXTIK_ZOUT_HPF_L (0x04) /* 0001 0100 */
#define KXTIK_ZOUT_HPF_H (0x05) /* 0001 0101 */
#define KXTIK_XOUT_L (0x06) /* 0000 0110 */
#define KXTIK_XOUT_H (0x07) /* 0000 0111 */
#define KXTIK_YOUT_L (0x08) /* 0000 1000 */
#define KXTIK_YOUT_H (0x09) /* 0000 1001 */
#define KXTIK_ZOUT_L (0x0A) /* 0001 1010 */
#define KXTIK_ZOUT_H (0x0B) /* 0001 1011 */
#define KXTIK_ST_RESP (0x0C) /* 0000 1100 */
#define KXTIK_WHO_AM_I (0x0F) /* 0000 1111 */
#define KXTIK_TILT_POS_CUR (0x10) /* 0001 0000 */
#define KXTIK_TILT_POS_PRE (0x11) /* 0001 0001 */
#define KXTIK_INT_SRC_REG1 (0x15) /* 0001 0101 */
#define KXTIK_INT_SRC_REG2 (0x16) /* 0001 0110 */
#define KXTIK_STATUS_REG (0x18) /* 0001 1000 */
#define KXTIK_INT_REL (0x1A) /* 0001 1010 */
#define KXTIK_CTRL_REG1 (0x1B) /* 0001 1011 */
#define KXTIK_CTRL_REG2 (0x1C) /* 0001 1100 */
#define KXTIK_CTRL_REG3 (0x1D) /* 0001 1101 */
#define KXTIK_INT_CTRL_REG1 (0x1E) /* 0001 1110 */
#define KXTIK_INT_CTRL_REG2 (0x1F) /* 0001 1111 */
#define KXTIK_INT_CTRL_REG3 (0x20) /* 0010 0000 */
#define KXTIK_DATA_CTRL_REG (0x21) /* 0010 0001 */
#define KXTIK_TILT_TIMER (0x28) /* 0010 1000 */
#define KXTIK_WUF_TIMER (0x29) /* 0010 1001 */
#define KXTIK_TDT_TIMER (0x2B) /* 0010 1011 */
#define KXTIK_TDT_H_THRESH (0x2C) /* 0010 1100 */
#define KXTIK_TDT_L_THRESH (0x2D) /* 0010 1101 */
#define KXTIK_TDT_TAP_TIMER (0x2E) /* 0010 1110 */
#define KXTIK_TDT_TOTAL_TIMER (0x2F) /* 0010 1111 */
#define KXTIK_TDT_LATENCY_TIMER (0x30) /* 0011 0000 */
#define KXTIK_TDT_WINDOW_TIMER (0x31) /* 0011 0001 */
#define KXTIK_WUF_THRESH (0x5A) /* 0101 1010 */
#define KXTIK_TILT_ANGLE (0x5C) /* 0101 1100 */
#define KXTIK_HYST_SET (0x5F) /* 0101 1111 */
/* CONTROL REGISTER 1 BITS */
#define KXTIK_DISABLE 0x7F
#define KXTIK_ENABLE (1 << 7)
#define KXTIK_DRDYE (1 << 5)
/* INPUT_ABS CONSTANTS */
#define FUZZ 3
#define FLAT 3
/* RESUME STATE INDICES */
#define RES_DATA_CTRL 0
#define RES_CTRL_REG1 1
#define RES_INT_CTRL1 2
#define RESUME_ENTRIES 3
/* CTRL_REG1: set resolution, g-range, data ready enable */
/* Output resolution: 8-bit valid or 12-bit valid */
#define KXTIK_RES_8BIT 0
#define KXTIK_RES_12BIT (1 << 6)
/* Output g-range: +/-2g, 4g, or 8g */
#define KXTIK_G_2G 0
#define KXTIK_G_4G (1 << 3)
#define KXTIK_G_8G (1 << 4)
/* DATA_CTRL_REG: controls the output data rate of the part */
#define KXTIK_ODR12_5F 0
#define KXTIK_ODR25F 1
#define KXTIK_ODR50F 2
#define KXTIK_ODR100F 3
#define KXTIK_ODR200F 4
#define KXTIK_ODR400F 5
#define KXTIK_ODR800F 6
/* kxtik */
#define KXTIK_PRECISION 12
#define KXTIK_BOUNDARY (0x1 << (KXTIK_PRECISION - 1))
#define KXTIK_GRAVITY_STEP KXTIK_RANGE / KXTIK_BOUNDARY
/****************operate according to sensor chip:start************/
static int sensor_active(struct i2c_client *client, int enable, int rate)
{
struct sensor_private_data *sensor =
(struct sensor_private_data *) i2c_get_clientdata(client);
int result = 0;
int status = 0;
sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
//register setting according to chip datasheet
if(enable)
{
status = KXTIK_ENABLE; //kxtik
sensor->ops->ctrl_data |= status;
}
else
{
status = ~KXTIK_ENABLE; //kxtik
sensor->ops->ctrl_data &= status;
}
DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
if(result)
printk("%s:fail to active sensor\n",__func__);
return result;
}
static int sensor_init(struct i2c_client *client)
{
struct sensor_private_data *sensor =
(struct sensor_private_data *) i2c_get_clientdata(client);
int result = 0;
int i = 0;
unsigned char id_reg = KXTIK_WHO_AM_I;
unsigned char id_data = 0;
unsigned char ctrl_data_save = 0;
result = sensor->ops->active(client,0,0);
if(result)
{
printk("%s:line=%d,error\n",__func__,__LINE__);
return result;
}
sensor->status_cur = SENSOR_OFF;
for(i=0; i<3; i++)
{
result = sensor_rx_data(client, &id_reg, 1);
id_data = id_reg;
if(!result)
break;
}
if(result)
{
printk("%s:fail to read id,result=%d\n",__func__, result);
return result;
}
sensor->devid = id_data;
result = sensor_write_reg(client, KXTIK_DATA_CTRL_REG, KXTIK_ODR400F);
if(result)
{
printk("%s:line=%d,error\n",__func__,__LINE__);
return result;
}
if(sensor->pdata->irq_enable) //open interrupt
{
/*
BIT 4 IEA sets the polarity of the physical interrupt pin (7)
IEA = 0 <20> polarity of the physical interrupt pin (7) is active low
IEA = 1 <20> polarity of the physical interrupt pin (7) is active high
BIT 3 IEL sets the response of the physical interrupt pin (7)
IEL = 0 <20> the physical interrupt pin (7) latches until it is cleared by reading INT_REL
IEL = 1 <20> the physical interrupt pin (7) will transmit one pulse with a period of 0.03 - 0.05ms
*/
if (id_data == KXTIK_DEVID_1004)
result = sensor_write_reg(client, KXTIK_INT_CTRL_REG1, 0x34);//enable int,active high,need read INT_REL
else
result = sensor_write_reg(client, KXTIK_INT_CTRL_REG1, 0x28);//enable int,active high,need read INT_REL
if(result)
{
printk("%s:line=%d,error\n",__func__,__LINE__);
return result;
}
}
ctrl_data_save = sensor_read_reg(client, sensor->ops->ctrl_reg);
DBG("%s: ctrl_data_save = 0x%x\n", __func__, ctrl_data_save);
sensor->ops->ctrl_data = (KXTIK_RES_12BIT | KXTIK_G_2G);
if(sensor->pdata->irq_enable)
{
sensor->ops->ctrl_data &= ~KXTIK_ENABLE;
sensor->ops->ctrl_data |= KXTIK_DRDYE;
}
DBG("%s: first write sensor->ops->ctrl_data = 0x%x\n", __func__, sensor->ops->ctrl_data);
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
if(result)
{
printk("%s:line=%d,error\n",__func__,__LINE__);
return result;
}
if(ctrl_data_save & 0x80)
sensor->ops->ctrl_data |= KXTIK_ENABLE;
else
sensor->ops->ctrl_data &= ~KXTIK_ENABLE;
DBG("%s: second write sensor->ops->ctrl_data = 0x%x\n", __func__, sensor->ops->ctrl_data);
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
if(result)
{
printk("%s:line=%d,error\n",__func__,__LINE__);
return result;
}
DBG("%s:%s id=0x%x\n",__func__,sensor->ops->name, id_data);
return result;
}
static int sensor_convert_data(struct i2c_client *client, char high_byte, char low_byte)
{
s64 result;
struct sensor_private_data *sensor =
(struct sensor_private_data *) i2c_get_clientdata(client);
//int precision = sensor->ops->precision;
switch (sensor->devid) {
case KXTIK_DEVID_1004:
case KXTIK_DEVID_1013:
case KXTIK_DEVID_J9_1005:
case KXTIK_DEVID_J2_1009:
result = (((int)high_byte << 8) | ((int)low_byte ))>>4;
if (result < KXTIK_BOUNDARY)
result = result* KXTIK_GRAVITY_STEP;
else
result = ~( ((~result & (0x7fff>>(16-KXTIK_PRECISION)) ) + 1)
* KXTIK_GRAVITY_STEP) + 1;
break;
default:
printk(KERN_ERR "%s: devid wasn't set correctly\n",__func__);
return -EFAULT;
}
return (int)result;
}
static int angle_report_value(struct i2c_client *client, struct sensor_axis *axis)
{
struct sensor_private_data *sensor =
(struct sensor_private_data *) i2c_get_clientdata(client);
/* Report acceleration sensor information */
input_report_abs(sensor->input_dev, ABS_X, axis->x);
input_report_abs(sensor->input_dev, ABS_Y, axis->y);
input_report_abs(sensor->input_dev, ABS_Z, axis->z);
input_sync(sensor->input_dev);
DBG("Gsensor x==%d y==%d z==%d\n",axis->x,axis->y,axis->z);
return 0;
}
#define GSENSOR_MIN 10
static int sensor_report_value(struct i2c_client *client)
{
struct sensor_private_data *sensor =
(struct sensor_private_data *) i2c_get_clientdata(client);
struct sensor_platform_data *pdata = sensor->pdata;
int ret = 0;
int x,y,z;
struct sensor_axis axis;
char buffer[6] = {0};
char value = 0;
if(sensor->ops->read_len < 6) //sensor->ops->read_len = 6
{
printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);
return -1;
}
memset(buffer, 0, 6);
/* Data bytes from hardware xL, xH, yL, yH, zL, zH */
do {
*buffer = sensor->ops->read_reg;
ret = sensor_rx_data(client, buffer, sensor->ops->read_len);
if (ret < 0)
return ret;
} while (0);
//this angle need 6 bytes buffer
x = sensor_convert_data(sensor->client, buffer[1], buffer[0]); //buffer[1]:high bit
y = sensor_convert_data(sensor->client, buffer[3], buffer[2]);
z = sensor_convert_data(sensor->client, buffer[5], buffer[4]);
axis.x = (pdata->orientation[0])*x + (pdata->orientation[1])*y + (pdata->orientation[2])*z;
axis.y = (pdata->orientation[3])*x + (pdata->orientation[4])*y + (pdata->orientation[5])*z;
axis.z = (pdata->orientation[6])*x + (pdata->orientation[7])*y + (pdata->orientation[8])*z;
DBG( "%s: axis = %d %d %d \n", __func__, axis.x, axis.y, axis.z);
//Report event only while value is changed to save some power
if((abs(sensor->axis.x - axis.x) > GSENSOR_MIN) || (abs(sensor->axis.y - axis.y) > GSENSOR_MIN) || (abs(sensor->axis.z - axis.z) > GSENSOR_MIN))
{
angle_report_value(client, &axis);
/* <20><><EFBFBD><EFBFBD><EFBFBD>ػ<EFBFBD><D8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. */
mutex_lock(&(sensor->data_mutex) );
sensor->axis = axis;
mutex_unlock(&(sensor->data_mutex) );
}
if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0)) //read sensor intterupt status register
{
value = sensor_read_reg(client, sensor->ops->int_status_reg);
DBG("%s:sensor int status :0x%x\n",__func__,value);
}
return ret;
}
struct sensor_operate angle_kxtik_ops = {
.name = "angle_kxtik",
.type = SENSOR_TYPE_ANGLE, //sensor type and it should be correct
.id_i2c = ANGLE_ID_KXTIK, //i2c id number
.read_reg = KXTIK_XOUT_L, //read data
.read_len = 6, //data length
.id_reg = SENSOR_UNKNOW_DATA, //read device id from this register
.id_data = SENSOR_UNKNOW_DATA,
.precision = KXTIK_PRECISION, //12 bits
.ctrl_reg = KXTIK_CTRL_REG1, //enable or disable
.int_status_reg = KXTIK_INT_REL, //intterupt status register
.range = {-KXTIK_RANGE,KXTIK_RANGE}, //range
.trig = IRQF_TRIGGER_LOW|IRQF_ONESHOT,
.active = sensor_active,
.init = sensor_init,
.report = sensor_report_value,
};
/****************operate according to sensor chip:end************/
//function name should not be changed
static struct sensor_operate *angle_get_ops(void)
{
return &angle_kxtik_ops;
}
static int __init angle_kxtik_init(void)
{
struct sensor_operate *ops = angle_get_ops();
int result = 0;
int type = ops->type;
result = sensor_register_slave(type, NULL, NULL, angle_get_ops);
printk("%s\n",__func__);
return result;
}
static void __exit angle_kxtik_exit(void)
{
struct sensor_operate *ops = angle_get_ops();
int type = ops->type;
sensor_unregister_slave(type, NULL, NULL, angle_get_ops);
}
module_init(angle_kxtik_init);
module_exit(angle_kxtik_exit);

View File

@@ -0,0 +1,336 @@
/* drivers/input/sensors/access/kxtik.c
*
* Copyright (C) 2012-2015 ROCKCHIP.
* Author: luowei <lw@rock-chips.com>
*
* 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 <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/irq.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/workqueue.h>
#include <linux/freezer.h>
#include <mach/gpio.h>
#include <mach/board.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
#endif
#include <linux/sensor-dev.h>
#define LIS3DH_INT_COUNT (0x0E)
#define LIS3DH_WHO_AM_I (0x0F)
/* full scale setting - register & mask */
#define LIS3DH_TEMP_CFG_REG (0x1F)
#define LIS3DH_CTRL_REG1 (0x20)
#define LIS3DH_CTRL_REG2 (0x21)
#define LIS3DH_CTRL_REG3 (0x22)
#define LIS3DH_CTRL_REG4 (0x23)
#define LIS3DH_CTRL_REG5 (0x24)
#define LIS3DH_CTRL_REG6 (0x25)
#define LIS3DH_REFERENCE (0x26)
#define LIS3DH_STATUS_REG (0x27)
#define LIS3DH_OUT_X_L (0x28)
#define LIS3DH_OUT_X_H (0x29)
#define LIS3DH_OUT_Y_L (0x2a)
#define LIS3DH_OUT_Y_H (0x2b)
#define LIS3DH_OUT_Z_L (0x2c)
#define LIS3DH_OUT_Z_H (0x2d)
#define LIS3DH_FIFO_CTRL_REG (0x2E)
#define LIS3DH_INT1_CFG (0x30)
#define LIS3DH_INT1_SRC (0x31)
#define LIS3DH_INT1_THS (0x32)
#define LIS3DH_INT1_DURATION (0x33)
#define LIS3DH_DEVID (0x33) //chip id
#define LIS3DH_ACC_DISABLE (0x08)
#define LIS3DH_RANGE 2000000
/* LIS3DH */
#define LIS3DH_PRECISION 16
#define LIS3DH_BOUNDARY (0x1 << (LIS3DH_PRECISION - 1))
#define LIS3DH_GRAVITY_STEP (LIS3DH_RANGE / LIS3DH_BOUNDARY)
#define ODR1 0x10 /* 1Hz output data rate */
#define ODR10 0x20 /* 10Hz output data rate */
#define ODR25 0x30 /* 25Hz output data rate */
#define ODR50 0x40 /* 50Hz output data rate */
#define ODR100 0x50 /* 100Hz output data rate */
#define ODR200 0x60 /* 200Hz output data rate */
#define ODR400 0x70 /* 400Hz output data rate */
#define ODR1250 0x90 /* 1250Hz output data rate */
struct sensor_reg_data {
char reg;
char data;
};
/****************operate according to sensor chip:start************/
static int sensor_active(struct i2c_client *client, int enable, int rate)
{
struct sensor_private_data *sensor =
(struct sensor_private_data *) i2c_get_clientdata(client);
int result = 0;
int status = 0;
sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
sensor->ops->ctrl_data |= ODR100; //100HZ,if 0 then power down
//register setting according to chip datasheet
if(!enable)
{
status = LIS3DH_ACC_DISABLE; //lis3dh
sensor->ops->ctrl_data |= status;
}
else
{
status = ~LIS3DH_ACC_DISABLE; //lis3dh
sensor->ops->ctrl_data &= status;
}
DBG("%s:reg=0x%x,reg_ctrl=0x%x,enable=%d\n",__func__,sensor->ops->ctrl_reg, sensor->ops->ctrl_data, enable);
result = sensor_write_reg(client, sensor->ops->ctrl_reg, sensor->ops->ctrl_data);
if(result)
printk("%s:fail to active sensor\n",__func__);
return result;
}
static int sensor_init(struct i2c_client *client)
{
struct sensor_private_data *sensor =
(struct sensor_private_data *) i2c_get_clientdata(client);
int result = 0;
int i;
struct sensor_reg_data reg_data[] =
{
{LIS3DH_CTRL_REG2,0X00},
{LIS3DH_CTRL_REG4,0x08}, //High resolution output mode: 1, Normal mode
{LIS3DH_CTRL_REG6,0x40},
{LIS3DH_TEMP_CFG_REG,0x00}, //
{LIS3DH_FIFO_CTRL_REG,0x00}, //
{LIS3DH_INT1_CFG,0xFF}, //6 direction position recognition
{LIS3DH_INT1_THS,0x7F}, //Interrupt 1 threshold
{LIS3DH_INT1_DURATION,0x7F}, //Duration value 0x00->ox7f
};
result = sensor->ops->active(client,0,0);
if(result)
{
printk("%s:line=%d,error\n",__func__,__LINE__);
return result;
}
sensor->status_cur = SENSOR_OFF;
for(i=0;i<(sizeof(reg_data)/sizeof(struct sensor_reg_data));i++)
{
result = sensor_write_reg(client, reg_data[i].reg, reg_data[i].data);
if(result)
{
printk("%s:line=%d,i=%d,error\n",__func__,__LINE__,i);
return result;
}
}
if(sensor->pdata->irq_enable)
{
result = sensor_write_reg(client, LIS3DH_CTRL_REG3, 0x40);//I1_AOI1 =1 if motion
if(result)
{
printk("%s:line=%d,error\n",__func__,__LINE__);
return result;
}
result = sensor_write_reg(client, LIS3DH_CTRL_REG5, 0x08);
if(result)
{
printk("%s:line=%d,error\n",__func__,__LINE__);
return result;
}
}
return result;
}
static int sensor_convert_data(struct i2c_client *client, char high_byte, char low_byte)
{
s64 result;
struct sensor_private_data *sensor =
(struct sensor_private_data *) i2c_get_clientdata(client);
//int precision = sensor->ops->precision;
switch (sensor->devid) {
case LIS3DH_DEVID:
result = ((int)high_byte << 8) | (int)low_byte;
if (result < LIS3DH_BOUNDARY)
result = result* LIS3DH_GRAVITY_STEP;
else
result = ~( ((~result & (0x7fff>>(16-LIS3DH_PRECISION)) ) + 1)
* LIS3DH_GRAVITY_STEP) + 1;
break;
default:
printk(KERN_ERR "%s: devid wasn't set correctly\n",__func__);
return -EFAULT;
}
return (int)result;
}
static int angle_report_value(struct i2c_client *client, struct sensor_axis *axis)
{
struct sensor_private_data *sensor =
(struct sensor_private_data *) i2c_get_clientdata(client);
/* Report acceleration sensor information */
input_report_abs(sensor->input_dev, ABS_X, axis->x);
input_report_abs(sensor->input_dev, ABS_Y, axis->y);
input_report_abs(sensor->input_dev, ABS_Z, axis->z);
input_sync(sensor->input_dev);
DBG("Gsensor x==%d y==%d z==%d\n",axis->x,axis->y,axis->z);
return 0;
}
#define GSENSOR_MIN 10
static int sensor_report_value(struct i2c_client *client)
{
struct sensor_private_data *sensor =
(struct sensor_private_data *) i2c_get_clientdata(client);
struct sensor_platform_data *pdata = sensor->pdata;
int ret = 0;
int x,y,z;
struct sensor_axis axis;
char buffer[6] = {0};
char value = 0;
if(sensor->ops->read_len < 6) //sensor->ops->read_len = 6
{
printk("%s:lenth is error,len=%d\n",__func__,sensor->ops->read_len);
return -1;
}
memset(buffer, 0, 6);
value = sensor_read_reg(client, LIS3DH_STATUS_REG);
if((value & 0x0f) == 0)
{
printk("%s:line=%d,value=0x%x,data is not ready\n",__func__,__LINE__,value);
return -1;
}
/* Data bytes from hardware xL, xH, yL, yH, zL, zH */
do {
*buffer = sensor->ops->read_reg;
ret = sensor_rx_data(client, buffer, sensor->ops->read_len);
if (ret < 0)
return ret;
} while (0);
//this angle need 6 bytes buffer
x = sensor_convert_data(sensor->client, buffer[1], buffer[0]); //buffer[1]:high bit
y = sensor_convert_data(sensor->client, buffer[3], buffer[2]);
z = sensor_convert_data(sensor->client, buffer[5], buffer[4]);
axis.x = (pdata->orientation[0])*x + (pdata->orientation[1])*y + (pdata->orientation[2])*z;
axis.y = (pdata->orientation[3])*x + (pdata->orientation[4])*y + (pdata->orientation[5])*z;
axis.z = (pdata->orientation[6])*x + (pdata->orientation[7])*y + (pdata->orientation[8])*z;
DBG( "%s: axis = %d %d %d \n", __func__, axis.x, axis.y, axis.z);
//Report event only while value is changed to save some power
if((abs(sensor->axis.x - axis.x) > GSENSOR_MIN) || (abs(sensor->axis.y - axis.y) > GSENSOR_MIN) || (abs(sensor->axis.z - axis.z) > GSENSOR_MIN))
{
angle_report_value(client, &axis);
/* <20><><EFBFBD><EFBFBD><EFBFBD>ػ<EFBFBD><D8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. */
mutex_lock(&(sensor->data_mutex) );
sensor->axis = axis;
mutex_unlock(&(sensor->data_mutex) );
}
if((sensor->pdata->irq_enable)&& (sensor->ops->int_status_reg >= 0)) //read sensor intterupt status register
{
value = sensor_read_reg(client, sensor->ops->int_status_reg);
DBG("%s:sensor int status :0x%x\n",__func__,value);
}
return ret;
}
struct sensor_operate angle_lis3dh_ops = {
.name = "angle_lis3dh",
.type = SENSOR_TYPE_ANGLE, //sensor type and it should be correct
.id_i2c = ANGLE_ID_LIS3DH, //i2c id number
.read_reg = (LIS3DH_OUT_X_L | 0x80), //read data
.read_len = 6, //data length
.id_reg = LIS3DH_WHO_AM_I, //read device id from this register
.id_data = LIS3DH_DEVID, //device id
.precision = LIS3DH_PRECISION, //12 bits
.ctrl_reg = LIS3DH_CTRL_REG1, //enable or disable
.int_status_reg = LIS3DH_INT1_SRC, //intterupt status register
.range = {-LIS3DH_RANGE,LIS3DH_RANGE}, //range
.trig = (IRQF_TRIGGER_LOW|IRQF_ONESHOT),
.active = sensor_active,
.init = sensor_init,
.report = sensor_report_value,
};
/****************operate according to sensor chip:end************/
//function name should not be changed
static struct sensor_operate *angle_get_ops(void)
{
return &angle_lis3dh_ops;
}
static int __init angle_lis3dh_init(void)
{
struct sensor_operate *ops = angle_get_ops();
int result = 0;
int type = ops->type;
result = sensor_register_slave(type, NULL, NULL, angle_get_ops);
return result;
}
static void __exit angle_lis3dh_exit(void)
{
struct sensor_operate *ops = angle_get_ops();
int type = ops->type;
sensor_unregister_slave(type, NULL, NULL, angle_get_ops);
}
module_init(angle_lis3dh_init);
module_exit(angle_lis3dh_exit);

View File

@@ -40,9 +40,10 @@
sensor-dev.c v1.1 add pressure and temperature support 2013-2-27
sensor-dev.c v1.2 add akm8963 support 2013-3-10
sensor-dev.c v1.3 add sensor debug support 2013-3-15
sensor-dev.c v1.4 add angle calculation support between two gsensors 2013-09-01
*/
#define SENSOR_VERSION_AND_TIME "sensor-dev.c v1.3 add sensor debug support 2013-3-15"
#define SENSOR_VERSION_AND_TIME "sensor-dev.c v1.4 add angle calculation support between two gsensors 2013-09-01"
struct sensor_private_data *g_sensor[SENSOR_NUM_TYPES];
@@ -67,9 +68,9 @@ static ssize_t sensor_proc_write(struct file *file, const char __user *buffer,
num = c - '0';
printk("%s command list:close:%d, accel:%d, compass:%d, gyro:%d, light:%d, psensor:%d, temp:%d, pressure:%d,total:%d,num=%d\n",__func__,
printk("%s command list:close:%d,angle:%d accel:%d, compass:%d, gyro:%d, light:%d, psensor:%d, temp:%d, pressure:%d,total:%d,num=%d\n",__func__,
SENSOR_TYPE_NULL, SENSOR_TYPE_ACCEL,SENSOR_TYPE_COMPASS,SENSOR_TYPE_GYROSCOPE,SENSOR_TYPE_LIGHT,SENSOR_TYPE_PROXIMITY,
SENSOR_TYPE_NULL, SENSOR_TYPE_ANGLE, SENSOR_TYPE_ACCEL,SENSOR_TYPE_COMPASS,SENSOR_TYPE_GYROSCOPE,SENSOR_TYPE_LIGHT,SENSOR_TYPE_PROXIMITY,
SENSOR_TYPE_TEMPERATURE,SENSOR_TYPE_PRESSURE,SENSOR_NUM_TYPES,num);
@@ -347,7 +348,7 @@ static int sensor_irq_init(struct i2c_client *client)
goto error;
}
client->irq = irq;
if((sensor->pdata->type == SENSOR_TYPE_GYROSCOPE) || (sensor->pdata->type == SENSOR_TYPE_ACCEL))
if((sensor->pdata->type == SENSOR_TYPE_GYROSCOPE) || (sensor->pdata->type == SENSOR_TYPE_ACCEL) || (sensor->pdata->type == SENSOR_TYPE_ANGLE))
disable_irq_nosync(client->irq);//disable irq
if(((sensor->pdata->type == SENSOR_TYPE_LIGHT) || (sensor->pdata->type == SENSOR_TYPE_PROXIMITY))&& (!(sensor->ops->trig & IRQF_SHARED)))
disable_irq_nosync(client->irq);//disable irq
@@ -389,6 +390,154 @@ static void sensor_resume(struct early_suspend *h)
}
#endif
static int angle_dev_open(struct inode *inode, struct file *file)
{
//struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_ACCEL];
//struct i2c_client *client = sensor->client;
int result = 0;
return result;
}
static int angle_dev_release(struct inode *inode, struct file *file)
{
//struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_ANGLE];
//struct i2c_client *client = sensor->client;
int result = 0;
return result;
}
/* ioctl - I/O control */
static long angle_dev_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_ANGLE];
struct i2c_client *client = sensor->client;
void __user *argp = (void __user *)arg;
struct sensor_axis axis = {0};
char rate;
int result = 0;
switch (cmd) {
case GSENSOR_IOCTL_APP_SET_RATE:
if (copy_from_user(&rate, argp, sizeof(rate)))
{
result = -EFAULT;
goto error;
}
break;
default:
break;
}
switch (cmd) {
case GSENSOR_IOCTL_START:
DBG("%s:GSENSOR_IOCTL_START start,status=%d\n", __func__,sensor->status_cur);
mutex_lock(&sensor->operation_mutex);
if(++sensor->start_count == 1)
{
if(sensor->status_cur == SENSOR_OFF)
{
atomic_set(&(sensor->data_ready), 0);
if ( (result = sensor->ops->active(client, 1, 0) ) < 0 ) {
mutex_unlock(&sensor->operation_mutex);
printk("%s:fail to active sensor,ret=%d\n",__func__,result);
goto error;
}
if(sensor->pdata->irq_enable)
{
DBG("%s:enable irq,irq=%d\n",__func__,client->irq);
enable_irq(client->irq); //enable irq
}
else
{
PREPARE_DELAYED_WORK(&sensor->delaywork, sensor_delaywork_func);
schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));
}
sensor->status_cur = SENSOR_ON;
}
}
mutex_unlock(&sensor->operation_mutex);
DBG("%s:GSENSOR_IOCTL_START OK\n", __func__);
break;
case GSENSOR_IOCTL_CLOSE:
DBG("%s:GSENSOR_IOCTL_CLOSE start,status=%d\n", __func__,sensor->status_cur);
mutex_lock(&sensor->operation_mutex);
if(--sensor->start_count == 0)
{
if(sensor->status_cur == SENSOR_ON)
{
atomic_set(&(sensor->data_ready), 0);
if ( (result = sensor->ops->active(client, 0, 0) ) < 0 ) {
mutex_unlock(&sensor->operation_mutex);
goto error;
}
if(sensor->pdata->irq_enable)
{
DBG("%s:disable irq,irq=%d\n",__func__,client->irq);
disable_irq_nosync(client->irq);//disable irq
}
else
cancel_delayed_work_sync(&sensor->delaywork);
sensor->status_cur = SENSOR_OFF;
}
DBG("%s:GSENSOR_IOCTL_CLOSE OK\n", __func__);
}
mutex_unlock(&sensor->operation_mutex);
break;
case GSENSOR_IOCTL_APP_SET_RATE:
DBG("%s:GSENSOR_IOCTL_APP_SET_RATE start\n", __func__);
mutex_lock(&sensor->operation_mutex);
result = sensor_reset_rate(client, rate);
if (result < 0){
mutex_unlock(&sensor->operation_mutex);
goto error;
}
sensor->status_cur = SENSOR_ON;
mutex_unlock(&sensor->operation_mutex);
DBG("%s:GSENSOR_IOCTL_APP_SET_RATE OK\n", __func__);
break;
case GSENSOR_IOCTL_GETDATA:
mutex_lock(&sensor->data_mutex);
memcpy(&axis, &sensor->axis, sizeof(sensor->axis)); //get data from buffer
mutex_unlock(&sensor->data_mutex);
break;
default:
result = -ENOTTY;
goto error;
}
switch (cmd) {
case GSENSOR_IOCTL_GETDATA:
if ( copy_to_user(argp, &axis, sizeof(axis) ) ) {
printk("failed to copy sense data to user space.");
result = -EFAULT;
goto error;
}
DBG("%s:GSENSOR_IOCTL_GETDATA OK\n", __func__);
break;
default:
break;
}
error:
return result;
}
static int gsensor_dev_open(struct inode *inode, struct file *file)
{
//struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_ACCEL];
@@ -1279,6 +1428,26 @@ static int sensor_misc_device_register(struct sensor_private_data *sensor, int t
switch(type)
{
case SENSOR_TYPE_ANGLE:
if(!sensor->ops->misc_dev)
{
sensor->fops.owner = THIS_MODULE;
sensor->fops.unlocked_ioctl = angle_dev_ioctl;
sensor->fops.open = angle_dev_open;
sensor->fops.release = angle_dev_release;
sensor->miscdev.minor = MISC_DYNAMIC_MINOR;
sensor->miscdev.name = "angle";
sensor->miscdev.fops = &sensor->fops;
}
else
{
memcpy(&sensor->miscdev, sensor->ops->misc_dev, sizeof(*sensor->ops->misc_dev));
}
break;
case SENSOR_TYPE_ACCEL:
if(!sensor->ops->misc_dev)
{
@@ -1572,6 +1741,17 @@ int sensor_probe(struct i2c_client *client, const struct i2c_device_id *devid)
switch(type)
{
case SENSOR_TYPE_ANGLE:
sensor->input_dev->name = "angle";
set_bit(EV_ABS, sensor->input_dev->evbit);
/* x-axis acceleration */
input_set_abs_params(sensor->input_dev, ABS_X, sensor->ops->range[0], sensor->ops->range[1], 0, 0); //2g full scale range
/* y-axis acceleration */
input_set_abs_params(sensor->input_dev, ABS_Y, sensor->ops->range[0], sensor->ops->range[1], 0, 0); //2g full scale range
/* z-axis acceleration */
input_set_abs_params(sensor->input_dev, ABS_Z, sensor->ops->range[0], sensor->ops->range[1], 0, 0); //2g full scale range
break;
case SENSOR_TYPE_ACCEL:
sensor->input_dev->name = "gsensor";
set_bit(EV_ABS, sensor->input_dev->evbit);
@@ -1740,6 +1920,9 @@ static int sensor_remove(struct i2c_client *client)
}
static const struct i2c_device_id sensor_id[] = {
/*angle*/
{"angle_kxtik", ANGLE_ID_KXTIK},
{"angle_lis3dh", ANGLE_ID_LIS3DH},
/*gsensor*/
{"gsensor", ACCEL_ID_ALL},
{"gs_mma8452", ACCEL_ID_MMA845X},

View File

@@ -278,6 +278,25 @@ char GetSNSectorInfo(char * pbuf)
return 0;
}
char GetSNSectorInfoBeforeNandInit(char * pbuf)
{
char * sn_addr = ioremap(0x10501600,0x200);
memcpy(pbuf,sn_addr,0x200);
iounmap(sn_addr);
//print_hex_dump(KERN_WARNING, "sn:", DUMP_PREFIX_NONE, 16,1, sn_addr, 0x200, 0);
return 0;
}
char GetVendor0InfoBeforeNandInit(char * pbuf)
{
char * sn_addr = ioremap(0x10501400,0x200);
memcpy(pbuf,sn_addr + 8,504);
iounmap(sn_addr);
//print_hex_dump(KERN_WARNING, "sn:", DUMP_PREFIX_NONE, 16,1, sn_addr, 0x200, 0);
return 0;
}
char GetChipSectorInfo(char * pbuf)
{
if(gpNandInfo->GetChipSectorInfo)

18
include/linux/board-id-hw.h Executable file
View File

@@ -0,0 +1,18 @@
enum board_id_hw{
BOARD_ID_INVALID = -1,
BOARD_ID_DS763 = 0,
BOARD_ID_C8002,
BOARD_ID_C8003,
BOARD_ID_C1014,
BOARD_ID_C7018,
BOARD_ID_TA7CP01,
BOARD_ID_TA9CP01,
BOARD_ID_TA0CP01,
BOARD_ID_AIO_BAT,
BOARD_ID_AIO_NOBAT,
BOARD_ID_NUM,
};

1018
include/linux/board-id-operator.h Executable file

File diff suppressed because it is too large Load Diff

1435
include/linux/board-id.h Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -25,7 +25,8 @@
#define SENSOR_UNKNOW_DATA -1
enum sensor_type {
SENSOR_TYPE_NULL,
SENSOR_TYPE_NULL,
SENSOR_TYPE_ANGLE,
SENSOR_TYPE_ACCEL,
SENSOR_TYPE_COMPASS,
SENSOR_TYPE_GYROSCOPE,
@@ -38,7 +39,11 @@ enum sensor_type {
enum sensor_id {
ID_INVALID = 0,
ANGLE_ID_ALL,
ANGLE_ID_KXTIK,
ANGLE_ID_LIS3DH,
ACCEL_ID_ALL,
ACCEL_ID_LIS331,
ACCEL_ID_LSM303DLX,