193ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu/* 20c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig * Driver for the ADC on Freescale Semiconductor MC13783 and MC13892 PMICs. 393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu * 493ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. 593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu * Copyright (C) 2009 Sascha Hauer, Pengutronix 693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu * 793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu * This program is free software; you can redistribute it and/or 893ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu * modify it under the terms of the GNU General Public License 993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu * as published by the Free Software Foundation; either version 2 1093ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu * of the License, or (at your option) any later version. 1193ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu * This program is distributed in the hope that it will be useful, 1293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu * but WITHOUT ANY WARRANTY; without even the implied warranty of 1393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1493ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu * GNU General Public License for more details. 1593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu * 1693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu * You should have received a copy of the GNU General Public License along with 1793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu * this program; if not, write to the Free Software Foundation, Inc., 51 1893ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 1993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu */ 2093ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 210c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig#include <linux/mfd/mc13xxx.h> 2293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu#include <linux/platform_device.h> 2393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu#include <linux/hwmon-sysfs.h> 2493ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu#include <linux/kernel.h> 2593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu#include <linux/module.h> 2693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu#include <linux/hwmon.h> 275a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 2893ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu#include <linux/init.h> 2993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu#include <linux/err.h> 3093ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 310c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig#define DRIVER_NAME "mc13783-adc" 320c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig 330c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig/* platform device id driver data */ 340c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig#define MC13783_ADC_16CHANS 1 350c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig#define MC13783_ADC_BPDIV2 2 3693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 3793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustruct mc13783_adc_priv { 38613c27ab98dd2242bd9d62b0ab00b440bdf3259fUwe Kleine-König struct mc13xxx *mc13xxx; 3993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu struct device *hwmon_dev; 400c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig char name[10]; 4193ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu}; 4293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 4393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic ssize_t mc13783_adc_show_name(struct device *dev, struct device_attribute 4493ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu *devattr, char *buf) 4593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu{ 460c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig struct mc13783_adc_priv *priv = dev_get_drvdata(dev); 470c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig 480c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig return sprintf(buf, "%s\n", priv->name); 4993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu} 5093ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 5193ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic int mc13783_adc_read(struct device *dev, 5293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu struct device_attribute *devattr, unsigned int *val) 5393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu{ 540c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig struct mc13783_adc_priv *priv = dev_get_drvdata(dev); 5593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 5693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu unsigned int channel = attr->index; 5793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu unsigned int sample[4]; 5893ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu int ret; 5993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 60613c27ab98dd2242bd9d62b0ab00b440bdf3259fUwe Kleine-König ret = mc13xxx_adc_do_conversion(priv->mc13xxx, 61613c27ab98dd2242bd9d62b0ab00b440bdf3259fUwe Kleine-König MC13XXX_ADC_MODE_MULT_CHAN, 621039d762d03b573de4d46603c8583051c6d79094Michael Thalmeier channel, 0, 0, sample); 6393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu if (ret) 6493ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu return ret; 6593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 6693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu channel &= 0x7; 6793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 6893ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu *val = (sample[channel % 4] >> (channel > 3 ? 14 : 2)) & 0x3ff; 6993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 7093ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu return 0; 7193ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu} 7293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 7393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic ssize_t mc13783_adc_read_bp(struct device *dev, 7493ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu struct device_attribute *devattr, char *buf) 7593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu{ 7693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu unsigned val; 770c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig struct platform_device *pdev = to_platform_device(dev); 780c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig kernel_ulong_t driver_data = platform_get_device_id(pdev)->driver_data; 7993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu int ret = mc13783_adc_read(dev, devattr, &val); 8093ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 8193ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu if (ret) 8293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu return ret; 8393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 840c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig if (driver_data & MC13783_ADC_BPDIV2) 850c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig val = DIV_ROUND_CLOSEST(val * 9, 2); 860c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig else 870c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig /* 880c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig * BP (channel 2) reports with offset 2.4V to the actual value 890c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig * to fit the input range of the ADC. unit = 2.25mV = 9/4 mV. 900c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig */ 910c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig val = DIV_ROUND_CLOSEST(val * 9, 4) + 2400; 9293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 9393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu return sprintf(buf, "%u\n", val); 9493ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu} 9593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 9693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic ssize_t mc13783_adc_read_gp(struct device *dev, 9793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu struct device_attribute *devattr, char *buf) 9893ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu{ 9993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu unsigned val; 10093ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu int ret = mc13783_adc_read(dev, devattr, &val); 10193ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 10293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu if (ret) 10393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu return ret; 10493ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 10593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu /* 10693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu * input range is [0, 2.3V], val has 10 bits, so each bit 10793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu * is worth 9/4 mV. 10893ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu */ 10993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu val = DIV_ROUND_CLOSEST(val * 9, 4); 11093ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 11193ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu return sprintf(buf, "%u\n", val); 11293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu} 11393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 11493ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic DEVICE_ATTR(name, S_IRUGO, mc13783_adc_show_name, NULL); 11593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, mc13783_adc_read_bp, NULL, 2); 11693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, mc13783_adc_read_gp, NULL, 5); 11793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, mc13783_adc_read_gp, NULL, 6); 11893ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, mc13783_adc_read_gp, NULL, 7); 11993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, mc13783_adc_read_gp, NULL, 8); 12093ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, mc13783_adc_read_gp, NULL, 9); 12193ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, mc13783_adc_read_gp, NULL, 10); 12293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, mc13783_adc_read_gp, NULL, 11); 12393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, mc13783_adc_read_gp, NULL, 12); 12493ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, mc13783_adc_read_gp, NULL, 13); 12593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, mc13783_adc_read_gp, NULL, 14); 12693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, mc13783_adc_read_gp, NULL, 15); 12793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 1280c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenigstatic struct attribute *mc13783_attr_base[] = { 12993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu &dev_attr_name.attr, 13093ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu &sensor_dev_attr_in2_input.dev_attr.attr, 13193ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu &sensor_dev_attr_in5_input.dev_attr.attr, 13293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu &sensor_dev_attr_in6_input.dev_attr.attr, 13393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu &sensor_dev_attr_in7_input.dev_attr.attr, 1340c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig NULL 1350c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig}; 1360c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig 1370c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenigstatic const struct attribute_group mc13783_group_base = { 1380c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig .attrs = mc13783_attr_base, 1390c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig}; 1400c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig 1410c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig/* these are only used if MC13783_ADC_16CHANS is provided in driver data */ 1420c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenigstatic struct attribute *mc13783_attr_16chans[] = { 14393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu &sensor_dev_attr_in8_input.dev_attr.attr, 14493ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu &sensor_dev_attr_in9_input.dev_attr.attr, 14593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu &sensor_dev_attr_in10_input.dev_attr.attr, 14693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu &sensor_dev_attr_in11_input.dev_attr.attr, 14793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu NULL 14893ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu}; 14993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 1500c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenigstatic const struct attribute_group mc13783_group_16chans = { 1510c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig .attrs = mc13783_attr_16chans, 15293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu}; 15393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 15493ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu/* last four channels may be occupied by the touchscreen */ 15593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic struct attribute *mc13783_attr_ts[] = { 15693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu &sensor_dev_attr_in12_input.dev_attr.attr, 15793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu &sensor_dev_attr_in13_input.dev_attr.attr, 15893ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu &sensor_dev_attr_in14_input.dev_attr.attr, 15993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu &sensor_dev_attr_in15_input.dev_attr.attr, 16093ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu NULL 16193ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu}; 16293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 16393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic const struct attribute_group mc13783_group_ts = { 16493ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu .attrs = mc13783_attr_ts, 16593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu}; 16693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 167eaf06ee22594ac90cdd0279483b06c1db1667e01Uwe Kleine-Königstatic int mc13783_adc_use_touchscreen(struct platform_device *pdev) 168eaf06ee22594ac90cdd0279483b06c1db1667e01Uwe Kleine-König{ 169eaf06ee22594ac90cdd0279483b06c1db1667e01Uwe Kleine-König struct mc13783_adc_priv *priv = platform_get_drvdata(pdev); 170613c27ab98dd2242bd9d62b0ab00b440bdf3259fUwe Kleine-König unsigned flags = mc13xxx_get_flags(priv->mc13xxx); 171eaf06ee22594ac90cdd0279483b06c1db1667e01Uwe Kleine-König 172613c27ab98dd2242bd9d62b0ab00b440bdf3259fUwe Kleine-König return flags & MC13XXX_USE_TOUCHSCREEN; 173eaf06ee22594ac90cdd0279483b06c1db1667e01Uwe Kleine-König} 174eaf06ee22594ac90cdd0279483b06c1db1667e01Uwe Kleine-König 17593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic int __init mc13783_adc_probe(struct platform_device *pdev) 17693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu{ 17793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu struct mc13783_adc_priv *priv; 17893ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu int ret; 1790c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig const struct platform_device_id *id = platform_get_device_id(pdev); 1800c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig char *dash; 18193ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 18293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu priv = kzalloc(sizeof(*priv), GFP_KERNEL); 18393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu if (!priv) 18493ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu return -ENOMEM; 18593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 186613c27ab98dd2242bd9d62b0ab00b440bdf3259fUwe Kleine-König priv->mc13xxx = dev_get_drvdata(pdev->dev.parent); 1870c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig snprintf(priv->name, ARRAY_SIZE(priv->name), "%s", id->name); 1880c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig dash = strchr(priv->name, '-'); 1890c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig if (dash) 1900c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig *dash = '\0'; 19193ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 19293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu platform_set_drvdata(pdev, priv); 19393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 19493ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu /* Register sysfs hooks */ 1950c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group_base); 19693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu if (ret) 1970c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig goto out_err_create_base; 1980c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig 1990c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig if (id->driver_data & MC13783_ADC_16CHANS) { 2000c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig ret = sysfs_create_group(&pdev->dev.kobj, 2010c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig &mc13783_group_16chans); 2020c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig if (ret) 2030c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig goto out_err_create_16chans; 2040c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig } 20593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 206eaf06ee22594ac90cdd0279483b06c1db1667e01Uwe Kleine-König if (!mc13783_adc_use_touchscreen(pdev)) { 20793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group_ts); 20893ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu if (ret) 2090c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig goto out_err_create_ts; 210eaf06ee22594ac90cdd0279483b06c1db1667e01Uwe Kleine-König } 21193ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 21293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu priv->hwmon_dev = hwmon_device_register(&pdev->dev); 21393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu if (IS_ERR(priv->hwmon_dev)) { 21493ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu ret = PTR_ERR(priv->hwmon_dev); 21593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu dev_err(&pdev->dev, 21693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu "hwmon_device_register failed with %d.\n", ret); 21793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu goto out_err_register; 21893ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu } 21993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 22093ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu return 0; 22193ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 22293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fuout_err_register: 22393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 224eaf06ee22594ac90cdd0279483b06c1db1667e01Uwe Kleine-König if (!mc13783_adc_use_touchscreen(pdev)) 22593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts); 2260c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenigout_err_create_ts: 22793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 2280c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig if (id->driver_data & MC13783_ADC_16CHANS) 2290c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_16chans); 2300c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenigout_err_create_16chans: 2310c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig 2320c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_base); 2330c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenigout_err_create_base: 23493ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 23593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu platform_set_drvdata(pdev, NULL); 23693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu kfree(priv); 23793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 23893ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu return ret; 23993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu} 24093ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 24193ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic int __devexit mc13783_adc_remove(struct platform_device *pdev) 24293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu{ 24393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu struct mc13783_adc_priv *priv = platform_get_drvdata(pdev); 2440c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig kernel_ulong_t driver_data = platform_get_device_id(pdev)->driver_data; 24593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 24693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu hwmon_device_unregister(priv->hwmon_dev); 24793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 248eaf06ee22594ac90cdd0279483b06c1db1667e01Uwe Kleine-König if (!mc13783_adc_use_touchscreen(pdev)) 24993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts); 25093ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 2510c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig if (driver_data & MC13783_ADC_16CHANS) 2520c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_16chans); 2530c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig 2540c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_base); 25593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 25693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu platform_set_drvdata(pdev, NULL); 25793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu kfree(priv); 25893ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 25993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu return 0; 26093ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu} 26193ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 2620c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenigstatic const struct platform_device_id mc13783_adc_idtable[] = { 2630c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig { 2640c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig .name = "mc13783-adc", 2650c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig .driver_data = MC13783_ADC_16CHANS, 2660c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig }, { 2670c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig .name = "mc13892-adc", 2680c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig .driver_data = MC13783_ADC_BPDIV2, 2690c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig }, { 2700c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig /* sentinel */ 2710c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig } 2720c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig}; 2730c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-KoenigMODULE_DEVICE_TABLE(platform, mc13783_adc_idtable); 2740c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig 27593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic struct platform_driver mc13783_adc_driver = { 276cb88200490d723048994753ed59dc0abddc51e77Frans Meulenbroeks .remove = __devexit_p(mc13783_adc_remove), 27793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu .driver = { 27893ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu .owner = THIS_MODULE, 2790c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig .name = DRIVER_NAME, 28093ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu }, 2810c2732152a5813a870d0b96f0844f4dfe1436519Uwe Kleine-Koenig .id_table = mc13783_adc_idtable, 28293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu}; 28393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 28493ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic int __init mc13783_adc_init(void) 28593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu{ 28693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu return platform_driver_probe(&mc13783_adc_driver, mc13783_adc_probe); 28793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu} 28893ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 28993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fustatic void __exit mc13783_adc_exit(void) 29093ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu{ 29193ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu platform_driver_unregister(&mc13783_adc_driver); 29293ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu} 29393ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 29493ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fumodule_init(mc13783_adc_init); 29593ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fumodule_exit(mc13783_adc_exit); 29693ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao Fu 29793ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao FuMODULE_DESCRIPTION("MC13783 ADC driver"); 29893ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao FuMODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>"); 29993ee0a75f6e4b2c7ec20fd8f4ace87f88ba785b9Luotao FuMODULE_LICENSE("GPL"); 300