diff options
-rw-r--r-- | Documentation/ABI/testing/sysfs-devices-platform-ab5500-core-adc | 20 | ||||
-rw-r--r-- | drivers/mfd/ab5500-gpadc.c | 41 | ||||
-rw-r--r-- | include/linux/mfd/abx500/ab5500-gpadc.h | 1 |
3 files changed, 62 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-platform-ab5500-core-adc b/Documentation/ABI/testing/sysfs-devices-platform-ab5500-core-adc new file mode 100644 index 00000000000..fcfc0ed26fb --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-platform-ab5500-core-adc @@ -0,0 +1,20 @@ +What: /sys/devices/platform/ab5500-core.0/ab5500-adc.0/adc0volt +Date: Nov 2011 +KernelVersion: 3.0 +Contact: Shreshtha Kumar SAHU <shreshthakumar.sahu@stericsson.com> +Description: The adc0volt attribute allows the userspace to read the + voltage of the device connected to the General Purpose + Analog to Digital Converter (GPADC) channel-0. Voltage + conversion from analog to digital happens only when this + attribute is read. GPADC block is present in AB5500 chip + and has input voltage range of 0-1.8 volt for GPADC Ch-0. + It provides result of the converted voltage in 10 bits. + Other GPADC channels attributes may appear in this path + later. For minimum and maximum input voltage range for + each channel please refer to the ST-Ericssons AB5500 + datasheet. An example usage of GPADC can be an ALS device + connected to the channel and user space adapts the + LCD backlight brightness based on ambient light value + read from the attribute. +Users: HAL. + diff --git a/drivers/mfd/ab5500-gpadc.c b/drivers/mfd/ab5500-gpadc.c index 6756d3cf37a..51d1fa9049a 100644 --- a/drivers/mfd/ab5500-gpadc.c +++ b/drivers/mfd/ab5500-gpadc.c @@ -67,6 +67,7 @@ #define GPADC_MANUAL_ADOUT1_MASK 0xC0 #define GPADC_MANUAL_ADOUT0_ON 0x10 #define GPADC_MANUAL_ADOUT1_ON 0x40 +#define MUX_SCALE_GPADC0_MASK 0x08 #define MUX_SCALE_VBAT_MASK 0x02 #define MUX_SCALE_45 0x02 #define MUX_SCALE_BDATA_MASK 0x01 @@ -74,6 +75,8 @@ #define MUX_SCALE_BDATA18 0x01 #define MUX_SCALE_ACCDET2_MASK 0x01 #define MUX_SCALE_ACCDET3_MASK 0x02 +#define GPADC0_SCALE_VOL27 0x00 +#define GPADC0_SCALE_VOL18 0x01 #define ACCDET2_SCALE_VOL27 0x00 #define ACCDET3_SCALE_VOL27 0x00 #define TRIGX_FREQ_MASK 0x07 @@ -98,6 +101,8 @@ #define CTRL_INDEX 0x01 /* GPADC constants from AB5500 spec */ +#define GPADC0_MIN 0 +#define GPADC0_MAX 1800 #define BTEMP_MIN 0 #define BTEMP_MAX 1800 #define BDATA_MIN 0 @@ -229,6 +234,7 @@ struct adc_data { } struct adc_data adc_tab[] = { + ADC_DATA(GPADC0_V, 0x00, GPADC0_MIN, GPADC0_MAX, 0), ADC_DATA(BTEMP_BALL, 0x0D, BTEMP_MIN, BTEMP_MAX, ADOUT0), ADC_DATA(BAT_CTRL, 0x0D, BDATA_MIN, BDATA_MAX, 0), ADC_DATA(MAIN_BAT_V, 0x0C, VBAT_MIN, VBAT_MAX, 0), @@ -270,6 +276,7 @@ static int ab5500_gpadc_ad_to_voltage(struct ab5500_gpadc *gpadc, int res; switch (in) { + case GPADC0_V: case PCB_TEMP: case BTEMP_BALL: case MAIN_BAT_V: @@ -367,6 +374,15 @@ int ab5500_gpadc_convert(struct ab5500_gpadc *gpadc, u8 input) goto out; } break; + case GPADC0_V: + ret = abx500_mask_and_set_register_interruptible(gpadc->dev, + AB5500_BANK_ADC, AB5500_GPADC_MANUAL_MODE_CTRL, + MUX_SCALE_GPADC0_MASK, GPADC0_SCALE_VOL18); + if (ret < 0) { + dev_err(gpadc->dev, "gpadc: fail to set gpadc0\n"); + goto out; + } + break; case ACC_DETECT2: ret = abx500_mask_and_set_register_interruptible(gpadc->dev, AB5500_BANK_ADC, AB5500_GPADC_MANUAL_MODE_CTRL2, @@ -775,6 +791,19 @@ out: } EXPORT_SYMBOL(ab5500_gpadc_convert_auto); +/* sysfs interface for GPADC0 */ +static ssize_t ab5500_gpadc0_get(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int voltage; + struct ab5500_gpadc *gpadc = dev_get_drvdata(dev); + + voltage = ab5500_gpadc_convert(gpadc, GPADC0_V); + + return sprintf(buf, "%d\n", voltage); +} +static DEVICE_ATTR(adc0volt, 0644, ab5500_gpadc0_get, NULL); + static void ab5500_gpadc_trigx_work(struct ab5500_gpadc *gp, int trig) { unsigned long flags; @@ -1114,9 +1143,19 @@ static int __devinit ab5500_gpadc_probe(struct platform_device *pdev) dev_err(gpadc->dev, "gpadc: configuration failed\n"); goto free_wq; } + + ret = device_create_file(gpadc->dev, &dev_attr_adc0volt); + if (ret < 0) { + dev_err(gpadc->dev, "File device creation failed: %d\n", ret); + ret = -ENODEV; + goto fail_sysfs; + } list_add_tail(&gpadc->node, &ab5500_gpadc_list); + platform_set_drvdata(pdev, gpadc); + return 0; +fail_sysfs: free_wq: destroy_workqueue(gpadc->gpadc_wq); fail_irq: @@ -1134,6 +1173,8 @@ static int __devexit ab5500_gpadc_remove(struct platform_device *pdev) int i, irq; struct ab5500_gpadc *gpadc = platform_get_drvdata(pdev); + device_remove_file(gpadc->dev, &dev_attr_adc0volt); + /* remove this gpadc entry from the list */ list_del(&gpadc->node); /* Disable interrupts */ diff --git a/include/linux/mfd/abx500/ab5500-gpadc.h b/include/linux/mfd/abx500/ab5500-gpadc.h index 3282b44114e..67dc3cc9034 100644 --- a/include/linux/mfd/abx500/ab5500-gpadc.h +++ b/include/linux/mfd/abx500/ab5500-gpadc.h @@ -33,6 +33,7 @@ #define MAIN_BAT_V_TXON_TRIG_MIN 13 /* VBAT with TX off only min trigger */ #define MAIN_BAT_V_TRIG_MIN 14 +#define GPADC0_V 15 /* * Frequency of auto adc conversion |