input: sensor: add cm36283 devicetree support

Add Capella cm36283 ambient light/proximity sensor devicetree support
to make it compatible with the current Linux kernel structure.

Change-Id: I23d7916480d1924b4a0a8121b2a587993a1d4b61
Signed-off-by: Oliver Wang <mengmeng@codeaurora.org>
This commit is contained in:
Oliver Wang 2013-08-23 13:42:10 +08:00 committed by Stephen Boyd
parent 574a33be22
commit e63fc3c340
4 changed files with 152 additions and 7 deletions

View file

@ -0,0 +1,40 @@
Capella cm36283 L/P sensor
Required properties:
- compatible : Should be "capella,cm36283".
- reg : i2c slave address of the device.
- interrupt-parent : Parent of interrupt.
- interrupts : L/P sample interrupt to indicate new data ready.
- vdd-supply : Power supply needed to power up the device.
- vio-supply : IO power supply needed for IO and I2C.
- capella,interrupt-gpio : The gpio pin for the interrupt.
- capella,levels : The adc value for light sensor to trigger different light level.
- capella,ps_close_thd_set : The threshold adc value for proximity sensor to trigger close interrupt.
- capella,ps_away_thd_set: The threshold adc value for proximity sensor to trigger away interrupt.
- capella,ls_cmd : The initial value to configure cm36283 ALS_CONF register.
- capella,ps_conf1_val : The initial value to configure cm36283 PS_CONF1 register.
- capella,ps_conf3_val : The initial value to configure cm36283 PS_CONF3 register.
Optional properties:
- capella,use-polling : Property to specify if using polling instead of interrupt for adc value report.
Example:
capella@60 {
compatible = "capella,cm36283";
reg = <0x60>;
interrupt-parent = <&msmgpio>;
interrupts = <80 0x2>;
vdd-supply = <&pm8110_l19>;
vio-supply = <&pm8110_l14>;
capella,use-polling;
capella,interrupt-gpio = <80>;
capella,levels = <0x0A 0xA0 0xE1 0x140 0x280 0x500 0xA28 0x16A8 0x1F40 0x2800>;
capella,ps_close_thd_set = <0xa>;
capella,ps_away_thd_set = <0x5>;
capella,ls_cmd = <0x44>; /* PS_IT=160ms, INT_PERS=2*/
capella,ps_conf1_val = <0x0006>; /*CM36283_PS_ITB_1_2 | CM36283_PS_DR_1_40| CM36283_PS_IT_1T | CM36283_PS_PERS_2 | CM36283_PS_RES_1*/
capella,ps_conf3_val = <0x3010>; /* CM36283_PS_MS_NORMAL | CM36283_PS_PROL_255 | CM36283_PS_SMART_PERS_ENABLE, */
};

View file

@ -13,6 +13,7 @@ arm ARM Ltd.
atmel Atmel Corporation
bosch Bosch Sensortec GmbH
brcm Broadcom Corporation
capella Capella Microsystems, Inc.
cavium Cavium, Inc.
chrp Common Hardware Reference Platform
cirrus Cirrus Logic, Inc.

View file

@ -2,7 +2,9 @@
*
* Copyright (C) 2012 Capella Microsystems Inc.
* Author: Frank Hsieh <pengyueh@gmail.com>
*
*
* Copyright (c) 2013, The Linux Foundation. All rights reserved.
*
* 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.
@ -32,6 +34,7 @@
#include <linux/wakelock.h>
#include <linux/jiffies.h>
#include <linux/cm36283.h>
#include <linux/of_gpio.h>
#include <asm/uaccess.h>
#include <asm/mach-types.h>
@ -1274,6 +1277,78 @@ static void cm36283_late_resume(struct early_suspend *h)
}
#endif
static int cm36283_parse_dt(struct device *dev,
struct cm36283_platform_data *pdata)
{
struct device_node *np = dev->of_node;
u32 levels[CM36283_LEVELS_SIZE], i;
u32 temp_val;
int rc;
rc = of_get_named_gpio_flags(np, "capella,interrupt-gpio",
0, NULL);
if (rc < 0) {
dev_err(dev, "Unable to read interrupt pin number\n");
return rc;
} else {
pdata->intr = rc;
}
rc = of_property_read_u32_array(np, "capella,levels", levels,
CM36283_LEVELS_SIZE);
if (rc) {
dev_err(dev, "Unable to read levels data\n");
return rc;
} else {
for (i = 0; i < CM36283_LEVELS_SIZE; i++)
pdata->levels[i] = levels[i];
}
rc = of_property_read_u32(np, "capella,ps_close_thd_set", &temp_val);
if (rc) {
dev_err(dev, "Unable to read ps_close_thd_set\n");
return rc;
} else {
pdata->ps_close_thd_set = (u8)temp_val;
}
rc = of_property_read_u32(np, "capella,ps_away_thd_set", &temp_val);
if (rc) {
dev_err(dev, "Unable to read ps_away_thd_set\n");
return rc;
} else {
pdata->ps_away_thd_set = (u8)temp_val;
}
rc = of_property_read_u32(np, "capella,ls_cmd", &temp_val);
if (rc) {
dev_err(dev, "Unable to read ls_cmd\n");
return rc;
} else {
pdata->ls_cmd = (u16)temp_val;
}
rc = of_property_read_u32(np, "capella,ps_conf1_val", &temp_val);
if (rc) {
dev_err(dev, "Unable to read ps_conf1_val\n");
return rc;
} else {
pdata->ps_conf1_val = (u16)temp_val;
}
rc = of_property_read_u32(np, "capella,ps_conf3_val", &temp_val);
if (rc) {
dev_err(dev, "Unable to read ps_conf3_val\n");
return rc;
} else {
pdata->ps_conf3_val = (u16)temp_val;
}
pdata->polling = of_property_read_bool(np, "capella,use-polling");
return 0;
}
static int cm36283_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@ -1291,12 +1366,29 @@ static int cm36283_probe(struct i2c_client *client,
/*D("[CM36283] %s: client->irq = %d\n", __func__, client->irq);*/
lpi->i2c_client = client;
pdata = client->dev.platform_data;
if (!pdata) {
pr_err("[PS][CM36283 error]%s: Assign platform_data error!!\n",
__func__);
ret = -EBUSY;
goto err_platform_data_null;
if (client->dev.of_node) {
pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
dev_err(&client->dev, "Failed to allocate memory for pdata\n");
ret = -ENOMEM;
goto err_platform_data_null;
}
ret = cm36283_parse_dt(&client->dev, pdata);
pdata->slave_addr = client->addr;
if (ret) {
dev_err(&client->dev, "Failed to get pdata from device tree\n");
goto err_parse_dt;
}
} else {
pdata = client->dev.platform_data;
if (!pdata) {
dev_err(&client->dev, "%s: Assign platform_data error!!\n",
__func__);
ret = -EBUSY;
goto err_platform_data_null;
}
}
lpi->irq = client->irq;
@ -1502,6 +1594,9 @@ err_lightsensor_setup:
mutex_destroy(&als_enable_mutex);
mutex_destroy(&als_disable_mutex);
mutex_destroy(&als_get_adc_mutex);
err_parse_dt:
if (client->dev.of_node && (pdata != NULL))
devm_kfree(&client->dev, pdata);
err_platform_data_null:
kfree(lpi);
return ret;
@ -1769,6 +1864,11 @@ static const struct i2c_device_id cm36283_i2c_id[] = {
{}
};
static struct of_device_id cm36283_match_table[] = {
{ .compatible = "capella,cm36283",},
{ },
};
static struct i2c_driver cm36283_driver = {
.id_table = cm36283_i2c_id,
.probe = cm36283_probe,
@ -1776,6 +1876,7 @@ static struct i2c_driver cm36283_driver = {
.name = CM36283_I2C_NAME,
.owner = THIS_MODULE,
.pm = &cm36283_pm,
.of_match_table = cm36283_match_table,
},
};

View file

@ -120,6 +120,8 @@
extern unsigned int ps_kparam1;
extern unsigned int ps_kparam2;
#define CM36283_LEVELS_SIZE 10
struct cm36283_platform_data {
int intr;
uint16_t levels[10];
@ -131,6 +133,7 @@ struct cm36283_platform_data {
uint16_t ls_cmd;
uint16_t ps_conf1_val;
uint16_t ps_conf3_val;
bool polling;
};
#endif