| Bryan Huntsman | 3f2bc4d | 2011-08-16 17:27:22 -0700 | [diff] [blame] | 1 | #ifndef __MSM_ADC_H | 
|  | 2 | #define __MSM_ADC_H | 
|  | 3 |  | 
|  | 4 | #include <linux/sched.h> | 
|  | 5 |  | 
|  | 6 | #define MSM_ADC_MAX_CHAN_STR 64 | 
|  | 7 |  | 
|  | 8 | /* must be <= to the max buffer size in the modem implementation */ | 
|  | 9 | #define MSM_ADC_DEV_MAX_INFLIGHT 9 | 
|  | 10 |  | 
|  | 11 | #define MSM_ADC_IOCTL_CODE		0x90 | 
|  | 12 |  | 
|  | 13 | struct msm_adc_conversion { | 
|  | 14 | /* hwmon channel number - this is not equivalent to the DAL chan */ | 
|  | 15 | uint32_t chan; | 
|  | 16 | /* returned result in ms */ | 
|  | 17 | int result; | 
|  | 18 | }; | 
|  | 19 |  | 
|  | 20 | struct adc_chan_result { | 
|  | 21 | /* The channel number of the requesting/requested conversion */ | 
|  | 22 | uint32_t chan; | 
|  | 23 | /* The pre-calibrated digital output of a given ADC relative to the | 
|  | 24 | ADC reference */ | 
|  | 25 | int32_t adc_code; | 
|  | 26 | /* in units specific for a given ADC; most ADC uses reference voltage | 
|  | 27 | *  but some ADC uses reference current.  This measurement here is | 
|  | 28 | *  a number relative to a reference of a given ADC */ | 
|  | 29 | int64_t measurement; | 
|  | 30 | /* The data meaningful for each individual channel whether it is | 
|  | 31 | * voltage, current, temperature, etc. */ | 
|  | 32 | int64_t physical; | 
|  | 33 | }; | 
|  | 34 |  | 
|  | 35 | /* | 
|  | 36 | * Issue a blocking adc conversion request. Once the call returns, the data | 
|  | 37 | * can be found in the 'physical' field of adc_chan_result. This call will | 
|  | 38 | * return ENODATA if there is an invalid result returned by the modem driver. | 
|  | 39 | */ | 
|  | 40 | #define MSM_ADC_REQUEST			_IOWR(MSM_ADC_IOCTL_CODE, 1,	\ | 
|  | 41 | struct adc_chan_result) | 
|  | 42 |  | 
|  | 43 | /* | 
|  | 44 | * Issue a non-blocking adc conversion request. The results from this | 
|  | 45 | * request can be obtained by calling AIO_READ once the transfer is | 
|  | 46 | * completed. To verify completion, the blocking call AIO_POLL can be used. | 
|  | 47 | * If there are no slot resources, this call will return an error with errno | 
|  | 48 | * set to EWOULDBLOCK. | 
|  | 49 | */ | 
|  | 50 | #define MSM_ADC_AIO_REQUEST		_IOWR(MSM_ADC_IOCTL_CODE, 2,	\ | 
|  | 51 | struct adc_chan_result) | 
|  | 52 |  | 
|  | 53 | /* | 
|  | 54 | * Same non-blocking semantics as AIO_REQUEST, except this call will block | 
|  | 55 | * if there are no available slot resources. This call can fail with errno | 
|  | 56 | * set to EDEADLK if there are no resources and the file descriptor in question | 
|  | 57 | * has outstanding conversion requests already. This is done so the client | 
|  | 58 | * does not block on resources that can only be freed by reading the results -- | 
|  | 59 | * effectively deadlocking the system. In this case, the client must read | 
|  | 60 | * pending results before proceeding to free up resources. | 
|  | 61 | */ | 
|  | 62 | #define MSM_ADC_AIO_REQUEST_BLOCK_RES	_IOWR(MSM_ADC_IOCTL_CODE, 3,	\ | 
|  | 63 | struct adc_chan_result) | 
|  | 64 |  | 
|  | 65 | /* | 
|  | 66 | * Returns the number of pending results that are associated with a particular | 
|  | 67 | * file descriptor. If there are no pending results, this call will block until | 
|  | 68 | * there is at least one. If there are no requests queued at all on this file | 
|  | 69 | * descriptor, this call will fail with EDEADLK. This is to prevent deadlock in | 
|  | 70 | * a single-threaded scenario where POLL would never return. | 
|  | 71 | */ | 
|  | 72 | #define MSM_ADC_AIO_POLL		_IOR(MSM_ADC_IOCTL_CODE, 4,	\ | 
|  | 73 | uint32_t) | 
|  | 74 |  | 
|  | 75 | #define MSM_ADC_FLUID_INIT	_IOR(MSM_ADC_IOCTL_CODE, 5,	\ | 
|  | 76 | uint32_t) | 
|  | 77 |  | 
|  | 78 | #define MSM_ADC_FLUID_DEINIT	_IOR(MSM_ADC_IOCTL_CODE, 6,	\ | 
|  | 79 | uint32_t) | 
|  | 80 |  | 
|  | 81 | struct msm_adc_aio_result { | 
|  | 82 | uint32_t chan; | 
|  | 83 | int result; | 
|  | 84 | }; | 
|  | 85 |  | 
|  | 86 | /* | 
|  | 87 | * Read the results from an AIO / non-blocking conversion request. AIO_POLL | 
|  | 88 | * should be used before using this command to verify how many pending requests | 
|  | 89 | * are available for the file descriptor. This call will fail with errno set to | 
|  | 90 | * ENOMSG if there are no pending messages to be read at the time of the call. | 
|  | 91 | * The call will return ENODATA if there is an invalid result returned by the | 
|  | 92 | * modem driver. | 
|  | 93 | */ | 
|  | 94 | #define MSM_ADC_AIO_READ		_IOR(MSM_ADC_IOCTL_CODE, 5,	\ | 
|  | 95 | struct adc_chan_result) | 
|  | 96 |  | 
|  | 97 | struct msm_adc_lookup { | 
|  | 98 | /* channel name (input) */ | 
|  | 99 | char name[MSM_ADC_MAX_CHAN_STR]; | 
|  | 100 | /* local channel index (output) */ | 
|  | 101 | uint32_t chan_idx; | 
|  | 102 | }; | 
|  | 103 |  | 
|  | 104 | /* | 
|  | 105 | * Look up a channel name and get back an index that can be used | 
|  | 106 | * as a parameter to the conversion request commands. | 
|  | 107 | */ | 
|  | 108 | #define MSM_ADC_LOOKUP			_IOWR(MSM_ADC_IOCTL_CODE, 6,	\ | 
|  | 109 | struct msm_adc_lookup) | 
|  | 110 |  | 
|  | 111 |  | 
|  | 112 | #ifdef __KERNEL__ | 
|  | 113 | #define MSM_ADC_MAX_NUM_DEVS		3 | 
|  | 114 |  | 
|  | 115 | enum { | 
|  | 116 | ADC_CONFIG_TYPE1, | 
|  | 117 | ADC_CONFIG_TYPE2, | 
|  | 118 | ADC_CONFIG_NONE = 0xffffffff | 
|  | 119 | }; | 
|  | 120 |  | 
|  | 121 | enum { | 
|  | 122 | ADC_CALIB_CONFIG_TYPE1, | 
|  | 123 | ADC_CALIB_CONFIG_TYPE2, | 
|  | 124 | ADC_CALIB_CONFIG_TYPE3, | 
|  | 125 | ADC_CALIB_CONFIG_TYPE4, | 
|  | 126 | ADC_CALIB_CONFIG_TYPE5, | 
|  | 127 | ADC_CALIB_CONFIG_TYPE6, | 
|  | 128 | ADC_CALIB_CONFIG_TYPE7, | 
|  | 129 | ADC_CALIB_CONFIG_NONE = 0xffffffff | 
|  | 130 | }; | 
|  | 131 |  | 
|  | 132 | enum { | 
|  | 133 | /* CHAN_PATH_TYPEn is specific for each ADC driver | 
|  | 134 | and can be used however way it wants*/ | 
|  | 135 | CHAN_PATH_TYPE1, | 
|  | 136 | CHAN_PATH_TYPE2, | 
|  | 137 | CHAN_PATH_TYPE3, | 
|  | 138 | CHAN_PATH_TYPE4, | 
|  | 139 | CHAN_PATH_TYPE5, | 
|  | 140 | CHAN_PATH_TYPE6, | 
|  | 141 | CHAN_PATH_TYPE7, | 
|  | 142 | CHAN_PATH_TYPE8, | 
|  | 143 | CHAN_PATH_TYPE9, | 
|  | 144 | CHAN_PATH_TYPE10, | 
|  | 145 | CHAN_PATH_TYPE11, | 
|  | 146 | CHAN_PATH_TYPE12, | 
|  | 147 | CHAN_PATH_TYPE13, | 
|  | 148 | CHAN_PATH_TYPE14, | 
|  | 149 | CHAN_PATH_TYPE15, | 
|  | 150 | CHAN_PATH_TYPE16, | 
|  | 151 | /* A given channel connects directly to the ADC */ | 
|  | 152 | CHAN_PATH_TYPE_NONE = 0xffffffff | 
|  | 153 | }; | 
|  | 154 |  | 
|  | 155 | #define CHANNEL_ADC_BATT_ID     0 | 
|  | 156 | #define CHANNEL_ADC_BATT_THERM  1 | 
|  | 157 | #define CHANNEL_ADC_BATT_AMON   2 | 
|  | 158 | #define CHANNEL_ADC_VBATT       3 | 
|  | 159 | #define CHANNEL_ADC_VCOIN       4 | 
|  | 160 | #define CHANNEL_ADC_VCHG        5 | 
|  | 161 | #define CHANNEL_ADC_CHG_MONITOR 6 | 
|  | 162 | #define CHANNEL_ADC_VPH_PWR     7 | 
|  | 163 | #define CHANNEL_ADC_USB_VBUS    8 | 
|  | 164 | #define CHANNEL_ADC_DIE_TEMP    9 | 
|  | 165 | #define CHANNEL_ADC_DIE_TEMP_4K 0xa | 
|  | 166 | #define CHANNEL_ADC_XOTHERM     0xb | 
|  | 167 | #define CHANNEL_ADC_XOTHERM_4K  0xc | 
|  | 168 | #define CHANNEL_ADC_HDSET       0xd | 
|  | 169 | #define CHANNEL_ADC_MSM_THERM	0xe | 
|  | 170 | #define CHANNEL_ADC_625_REF	0xf | 
|  | 171 | #define CHANNEL_ADC_1250_REF	0x10 | 
|  | 172 | #define CHANNEL_ADC_325_REF	0x11 | 
|  | 173 | #define CHANNEL_ADC_FSM_THERM	0x12 | 
|  | 174 | #define CHANNEL_ADC_PA_THERM	0x13 | 
|  | 175 |  | 
|  | 176 | enum { | 
|  | 177 | CALIB_STARTED, | 
|  | 178 | CALIB_NOT_REQUIRED = 0xffffffff, | 
|  | 179 | }; | 
|  | 180 |  | 
|  | 181 | struct linear_graph { | 
|  | 182 | int32_t offset; | 
|  | 183 | int32_t dy; /* Slope numerator */ | 
|  | 184 | int32_t dx; /* Slope denominator */ | 
|  | 185 | }; | 
|  | 186 |  | 
|  | 187 | struct adc_map_pt { | 
|  | 188 | int32_t x; | 
|  | 189 | int32_t y; | 
|  | 190 | }; | 
|  | 191 |  | 
|  | 192 | struct adc_properties { | 
|  | 193 | uint32_t adc_reference; /* milli-voltage for this adc */ | 
|  | 194 | uint32_t bitresolution; | 
|  | 195 | bool bipolar; | 
|  | 196 | uint32_t conversiontime; | 
|  | 197 | }; | 
|  | 198 |  | 
|  | 199 | struct chan_properties { | 
|  | 200 | uint32_t gain_numerator; | 
|  | 201 | uint32_t gain_denominator; | 
|  | 202 | struct linear_graph *adc_graph; | 
|  | 203 | /* this maybe the same as adc_properties.ConversionTime | 
|  | 204 | if channel does not change the adc properties */ | 
|  | 205 | uint32_t chan_conv_time; | 
|  | 206 | }; | 
|  | 207 |  | 
|  | 208 | struct msm_adc_channels { | 
|  | 209 | char *name; | 
|  | 210 | uint32_t channel_name; | 
|  | 211 | uint32_t adc_dev_instance; | 
|  | 212 | struct adc_access_fn *adc_access_fn; | 
|  | 213 | uint32_t chan_path_type; | 
|  | 214 | uint32_t adc_config_type; | 
|  | 215 | uint32_t adc_calib_type; | 
|  | 216 | int32_t (*chan_processor)(int32_t, const struct adc_properties *, | 
|  | 217 | const struct chan_properties *, struct adc_chan_result *); | 
|  | 218 |  | 
|  | 219 | }; | 
|  | 220 |  | 
|  | 221 | struct msm_adc_platform_data { | 
|  | 222 | struct msm_adc_channels *channel; | 
|  | 223 | uint32_t num_chan_supported; | 
|  | 224 | uint32_t num_adc; | 
|  | 225 | uint32_t chan_per_adc; | 
|  | 226 | char **dev_names; | 
|  | 227 | uint32_t target_hw; | 
|  | 228 | uint32_t gpio_config; | 
|  | 229 | u32 (*adc_gpio_enable) (int); | 
|  | 230 | u32 (*adc_gpio_disable) (int); | 
|  | 231 | u32 (*adc_fluid_enable) (void); | 
|  | 232 | u32 (*adc_fluid_disable) (void); | 
|  | 233 | }; | 
|  | 234 |  | 
|  | 235 | enum hw_type { | 
|  | 236 | MSM_7x30, | 
|  | 237 | MSM_8x60, | 
|  | 238 | FSM_9xxx, | 
| Siddartha Mohanadoss | bc2103f | 2012-03-20 11:41:48 -0700 | [diff] [blame] | 239 | MSM_8x25, | 
| Bryan Huntsman | 3f2bc4d | 2011-08-16 17:27:22 -0700 | [diff] [blame] | 240 | }; | 
|  | 241 |  | 
|  | 242 | enum epm_gpio_config { | 
|  | 243 | MPROC_CONFIG, | 
|  | 244 | APROC_CONFIG | 
|  | 245 | }; | 
|  | 246 |  | 
|  | 247 | enum adc_request { | 
|  | 248 | START_OF_CONV, | 
|  | 249 | END_OF_CONV, | 
|  | 250 | START_OF_CALIBRATION, | 
|  | 251 | END_OF_CALIBRATION, | 
|  | 252 | }; | 
|  | 253 |  | 
|  | 254 | struct adc_dev_spec { | 
|  | 255 | uint32_t			hwmon_dev_idx; | 
|  | 256 | struct dal_dev_spec { | 
|  | 257 | uint32_t		dev_idx; | 
|  | 258 | uint32_t		chan_idx; | 
|  | 259 | } dal; | 
|  | 260 | }; | 
|  | 261 |  | 
|  | 262 | struct dal_conv_request { | 
|  | 263 | struct dal_dev_spec		target; | 
|  | 264 | void				*cb_h; | 
|  | 265 | }; | 
|  | 266 |  | 
|  | 267 | struct dal_adc_result { | 
|  | 268 | uint32_t			status; | 
|  | 269 | uint32_t			token; | 
|  | 270 | uint32_t			dev_idx; | 
|  | 271 | uint32_t			chan_idx; | 
|  | 272 | int				physical; | 
|  | 273 | uint32_t			percent; | 
|  | 274 | uint32_t			microvolts; | 
|  | 275 | uint32_t			reserved; | 
|  | 276 | }; | 
|  | 277 |  | 
|  | 278 | struct dal_conv_slot { | 
|  | 279 | void				*cb_h; | 
|  | 280 | struct dal_adc_result		result; | 
|  | 281 | struct completion		comp; | 
|  | 282 | struct list_head		list; | 
|  | 283 | uint32_t			idx; | 
|  | 284 | uint32_t			chan_idx; | 
|  | 285 | bool				blocking; | 
|  | 286 | struct msm_client_data		*client; | 
|  | 287 | }; | 
|  | 288 |  | 
|  | 289 | struct dal_translation { | 
|  | 290 | uint32_t			dal_dev_idx; | 
|  | 291 | uint32_t			hwmon_dev_idx; | 
|  | 292 | uint32_t			hwmon_start; | 
|  | 293 | uint32_t			hwmon_end; | 
|  | 294 | }; | 
|  | 295 |  | 
|  | 296 | struct msm_client_data { | 
|  | 297 | struct list_head		complete_list; | 
|  | 298 | bool				online; | 
|  | 299 | int32_t				adc_chan; | 
|  | 300 | uint32_t			num_complete; | 
|  | 301 | uint32_t			num_outstanding; | 
|  | 302 | wait_queue_head_t		data_wait; | 
|  | 303 | wait_queue_head_t		outst_wait; | 
|  | 304 | struct mutex lock; | 
|  | 305 | }; | 
|  | 306 |  | 
|  | 307 | struct adc_conv_slot { | 
|  | 308 | void				*cb_h; | 
|  | 309 | union { | 
|  | 310 | struct adc_chan_result		result; | 
|  | 311 | struct dal_adc_result		dal_result; | 
|  | 312 | } conv; | 
|  | 313 | struct completion		comp; | 
|  | 314 | struct completion		*compk; | 
|  | 315 | struct list_head		list; | 
|  | 316 | uint32_t			idx; | 
|  | 317 | enum adc_request		adc_request; | 
|  | 318 | bool				blocking; | 
|  | 319 | struct msm_client_data		*client; | 
|  | 320 | struct work_struct		work; | 
|  | 321 | struct chan_properties		chan_properties; | 
|  | 322 | uint32_t			chan_path; | 
|  | 323 | uint32_t			chan_adc_config; | 
|  | 324 | uint32_t			chan_adc_calib; | 
|  | 325 | }; | 
|  | 326 |  | 
|  | 327 | struct adc_access_fn { | 
|  | 328 | int32_t (*adc_select_chan_and_start_conv)(uint32_t, | 
|  | 329 | struct adc_conv_slot*); | 
|  | 330 | int32_t (*adc_read_adc_code)(uint32_t dev_instance, int32_t *data); | 
|  | 331 | struct adc_properties *(*adc_get_properties)(uint32_t dev_instance); | 
|  | 332 | void (*adc_slot_request)(uint32_t dev_instance, | 
|  | 333 | struct adc_conv_slot **); | 
|  | 334 | void (*adc_restore_slot)(uint32_t dev_instance, | 
|  | 335 | struct adc_conv_slot *slot); | 
|  | 336 | int32_t (*adc_calibrate)(uint32_t dev_instance, struct adc_conv_slot*, | 
|  | 337 | int *); | 
|  | 338 | }; | 
|  | 339 |  | 
|  | 340 | void msm_adc_wq_work(struct work_struct *work); | 
|  | 341 | void msm_adc_conv_cb(void *context, u32 param, void *evt_buf, u32 len); | 
| Amir Samuelov | 9f9ece3 | 2011-09-17 23:23:25 +0300 | [diff] [blame] | 342 | #ifdef CONFIG_SENSORS_MSM_ADC | 
| Bryan Huntsman | 3f2bc4d | 2011-08-16 17:27:22 -0700 | [diff] [blame] | 343 | int32_t adc_channel_open(uint32_t channel, void **h); | 
|  | 344 | int32_t adc_channel_close(void *h); | 
|  | 345 | int32_t adc_channel_request_conv(void *h, struct completion *conv_complete_evt); | 
|  | 346 | int32_t adc_channel_read_result(void *h, struct adc_chan_result *chan_result); | 
| Amir Samuelov | 9f9ece3 | 2011-09-17 23:23:25 +0300 | [diff] [blame] | 347 | #else | 
| Siddartha Mohanadoss | bc2103f | 2012-03-20 11:41:48 -0700 | [diff] [blame] | 348 | static inline int32_t adc_channel_open(uint32_t channel, void **h) | 
| Amir Samuelov | 9f9ece3 | 2011-09-17 23:23:25 +0300 | [diff] [blame] | 349 | { | 
|  | 350 | pr_err("%s.not supported.\n", __func__); | 
|  | 351 | return -ENODEV; | 
|  | 352 | } | 
| Siddartha Mohanadoss | bc2103f | 2012-03-20 11:41:48 -0700 | [diff] [blame] | 353 | static inline int32_t adc_channel_close(void *h) | 
| Amir Samuelov | 9f9ece3 | 2011-09-17 23:23:25 +0300 | [diff] [blame] | 354 | { | 
|  | 355 | pr_err("%s.not supported.\n", __func__); | 
|  | 356 | return -ENODEV; | 
|  | 357 | } | 
| Siddartha Mohanadoss | bc2103f | 2012-03-20 11:41:48 -0700 | [diff] [blame] | 358 | static inline int32_t | 
| Anirudh Ghayal | c201933 | 2011-11-12 06:29:10 +0530 | [diff] [blame] | 359 | adc_channel_request_conv(void *h, struct completion *conv_complete_evt) | 
| Amir Samuelov | 9f9ece3 | 2011-09-17 23:23:25 +0300 | [diff] [blame] | 360 | { | 
|  | 361 | pr_err("%s.not supported.\n", __func__); | 
|  | 362 | return -ENODEV; | 
|  | 363 | } | 
| Siddartha Mohanadoss | bc2103f | 2012-03-20 11:41:48 -0700 | [diff] [blame] | 364 | static inline int32_t | 
| Anirudh Ghayal | c201933 | 2011-11-12 06:29:10 +0530 | [diff] [blame] | 365 | adc_channel_read_result(void *h, struct adc_chan_result *chan_result) | 
| Amir Samuelov | 9f9ece3 | 2011-09-17 23:23:25 +0300 | [diff] [blame] | 366 | { | 
|  | 367 | pr_err("%s.not supported.\n", __func__); | 
|  | 368 | return -ENODEV; | 
|  | 369 | } | 
| Amir Samuelov | 9f9ece3 | 2011-09-17 23:23:25 +0300 | [diff] [blame] | 370 | #endif /* CONFIG_SENSORS_MSM_ADC */ | 
| Bryan Huntsman | 3f2bc4d | 2011-08-16 17:27:22 -0700 | [diff] [blame] | 371 | #endif | 
|  | 372 | #endif /* __MSM_ADC_H */ |