diff options
Diffstat (limited to 'drivers/hwmon/ast_adc.c')
-rw-r--r-- | drivers/hwmon/ast_adc.c | 83 |
1 files changed, 69 insertions, 14 deletions
diff --git a/drivers/hwmon/ast_adc.c b/drivers/hwmon/ast_adc.c index 0969e398a8c8..3f95dc6f0f06 100644 --- a/drivers/hwmon/ast_adc.c +++ b/drivers/hwmon/ast_adc.c @@ -42,7 +42,7 @@ #include <plat/ast-scu.h> -#define REST_DESIGN 0 +#define REST_DESIGN 5 struct adc_vcc_ref_data { int v2; @@ -50,7 +50,7 @@ struct adc_vcc_ref_data { int r2; }; -static struct adc_vcc_ref_data adc_vcc_ref[5] = { +static struct adc_vcc_ref_data adc_vcc_ref[6] = { [0] = { .v2 = 0, .r1 = 5600, @@ -76,8 +76,20 @@ static struct adc_vcc_ref_data adc_vcc_ref[5] = { .r1 = 56000, .r2 = 1000, }, + [5] = { + .v2 = 0, + .r1 = 1000, + .r2 = 1000, + }, }; +/* Divisors for voltage sense; right now adc5 & adc6 divide by 2 */ + +static int adc_divisor[] = { 1, 1, 1, 1, + 1, 2, 2, 1, + 1, 1, 1, 1, + 1, 1, 1, 1}; + struct ast_adc_data { struct device *hwmon_dev; void __iomem *reg_base; /* virtual */ @@ -388,6 +400,22 @@ ast_set_adc_en(struct ast_adc_data *ast_adc, u8 adc_ch, u8 enable) } +/* NAME sysfs */ +static ssize_t +show_name(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + return sprintf(buf, "ast_adc\n"); +} +static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, show_name, NULL, 0, 0); +static struct attribute *name_attributes[] = { + &sensor_dev_attr_name.dev_attr.attr, + NULL +}; +static const struct attribute_group name_attribute_groups = { + .attrs = name_attributes, +}; + /* attr ADC sysfs 0~max adc channel * 0 - show/store channel enable * 1 - show value @@ -399,12 +427,31 @@ ast_set_adc_en(struct ast_adc_data *ast_adc, u8 adc_ch, u8 enable) * 7 - show/store hystersis low */ +static u32 +ast_get_voltage(int idx) { + u16 tmp; + u32 voltage, tmp1, tmp2, tmp3; + tmp = ast_get_adc_value(ast_adc, idx); + // Voltage Sense Method + tmp1 = (adc_vcc_ref[REST_DESIGN].r1 + adc_vcc_ref[REST_DESIGN].r2) * tmp * 25 * 10; + tmp2 = adc_vcc_ref[REST_DESIGN].r2 * 1024 ; + tmp3 = (adc_vcc_ref[REST_DESIGN].r1 * adc_vcc_ref[REST_DESIGN].v2) / adc_vcc_ref[REST_DESIGN].r2; + // printk("tmp3 = %d \n",tmp3); + voltage = (tmp1/tmp2) - tmp3; + + // Higher voltage inputs require a divisor + + if (adc_divisor[idx]) + voltage /= adc_divisor[idx]; + + return voltage; +} + static ssize_t ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf) { struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr); - u16 tmp; - u32 voltage,tmp1, tmp2,tmp3; + u32 voltage; //sensor_attr->index : pwm_ch# //sensor_attr->nr : attr# @@ -414,15 +461,7 @@ ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf) return sprintf(sysfsbuf, "%d : %s\n", ast_get_adc_en(ast_adc,sensor_attr->index),ast_get_adc_en(ast_adc,sensor_attr->index) ? "Enable":"Disable"); break; case 1: //value - tmp = ast_get_adc_value(ast_adc, sensor_attr->index); - //Voltage Sense Method - tmp1 = (adc_vcc_ref[REST_DESIGN].r1 + adc_vcc_ref[REST_DESIGN].r2) * tmp * 25 * 10; - tmp2 = adc_vcc_ref[REST_DESIGN].r2 * 1023 ; - - tmp3 = (adc_vcc_ref[REST_DESIGN].r1 * adc_vcc_ref[REST_DESIGN].v2) / adc_vcc_ref[REST_DESIGN].r2; - // printk("tmp3 = %d \n",tmp3); - voltage = (tmp1/tmp2) - tmp3; - + voltage = ast_get_voltage(sensor_attr->index); return sprintf(sysfsbuf, "%d.%d (V)\n",voltage/100, voltage%100); break; case 2: //alarm @@ -443,6 +482,9 @@ ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf) case 7: //hystersis lower return sprintf(sysfsbuf, "%d \n", ast_get_adc_hyster_lower(ast_adc,sensor_attr->index)); break; + case 8: + voltage = ast_get_voltage(sensor_attr->index); + return sprintf(sysfsbuf, "%d\n",voltage * 10); default: return -EINVAL; @@ -504,6 +546,7 @@ ast_store_adc(struct device *dev, struct device_attribute *attr, const char *sys * 5 - show/store hystersis enable * 6 - show/store hystersis upper * 7 - show/store hystersis low +* 8 - show value as 1000s, expected by lm-sensors */ #define sysfs_adc_ch(index) \ @@ -531,6 +574,9 @@ static SENSOR_DEVICE_ATTR_2(adc##index##_hyster_upper, S_IRUGO | S_IWUSR, \ static SENSOR_DEVICE_ATTR_2(adc##index##_hyster_lower, S_IRUGO | S_IWUSR, \ ast_show_adc, ast_store_adc, 7, index); \ \ +static SENSOR_DEVICE_ATTR_2(in##index##_input, S_IRUGO | S_IWUSR, \ + ast_show_adc, NULL, 8, index); \ +\ static struct attribute *adc##index##_attributes[] = { \ &sensor_dev_attr_adc##index##_en.dev_attr.attr, \ &sensor_dev_attr_adc##index##_value.dev_attr.attr, \ @@ -540,6 +586,7 @@ static struct attribute *adc##index##_attributes[] = { \ &sensor_dev_attr_adc##index##_hyster_en.dev_attr.attr, \ &sensor_dev_attr_adc##index##_hyster_upper.dev_attr.attr, \ &sensor_dev_attr_adc##index##_hyster_lower.dev_attr.attr, \ + &sensor_dev_attr_in##index##_input.dev_attr.attr, \ NULL \ }; @@ -637,10 +684,14 @@ ast_adc_probe(struct platform_device *pdev) goto out_region; } + err = sysfs_create_group(&pdev->dev.kobj, &name_attribute_groups); + if (err) + goto out_region; + for(i=0; i<MAX_CH_NO; i++) { err = sysfs_create_group(&pdev->dev.kobj, &adc_attribute_groups[i]); if (err) - goto out_region; + goto out_sysfs00; } ast_adc_ctrl_init(); @@ -652,6 +703,8 @@ ast_adc_probe(struct platform_device *pdev) //out_irq: // free_irq(ast_adc->irq, NULL); +out_sysfs00: + sysfs_remove_group(&pdev->dev.kobj, &name_attribute_groups); out_region: release_mem_region(res->start, res->end - res->start + 1); out_mem: @@ -674,6 +727,8 @@ ast_adc_remove(struct platform_device *pdev) for(i=0; i<5; i++) sysfs_remove_group(&pdev->dev.kobj, &adc_attribute_groups[i]); + sysfs_remove_group(&pdev->dev.kobj, &name_attribute_groups); + platform_set_drvdata(pdev, NULL); // free_irq(ast_adc->irq, ast_adc); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |