diff options
| -rw-r--r-- | drivers/mfd/wm8350-core.c | 51 | ||||
| -rw-r--r-- | include/linux/mfd/wm8350/comparator.h | 8 | ||||
| -rw-r--r-- | include/linux/mfd/wm8350/core.h | 2 |
3 files changed, 60 insertions, 1 deletions
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index c013afde260..60439bd3984 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c | |||
| @@ -63,7 +63,6 @@ | |||
| 63 | */ | 63 | */ |
| 64 | static DEFINE_MUTEX(io_mutex); | 64 | static DEFINE_MUTEX(io_mutex); |
| 65 | static DEFINE_MUTEX(reg_lock_mutex); | 65 | static DEFINE_MUTEX(reg_lock_mutex); |
| 66 | static DEFINE_MUTEX(auxadc_mutex); | ||
| 67 | 66 | ||
| 68 | /* Perform a physical read from the device. | 67 | /* Perform a physical read from the device. |
| 69 | */ | 68 | */ |
| @@ -1082,6 +1081,55 @@ int wm8350_unmask_irq(struct wm8350 *wm8350, int irq) | |||
| 1082 | } | 1081 | } |
| 1083 | EXPORT_SYMBOL_GPL(wm8350_unmask_irq); | 1082 | EXPORT_SYMBOL_GPL(wm8350_unmask_irq); |
| 1084 | 1083 | ||
| 1084 | int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) | ||
| 1085 | { | ||
| 1086 | u16 reg, result = 0; | ||
| 1087 | int tries = 5; | ||
| 1088 | |||
| 1089 | if (channel < WM8350_AUXADC_AUX1 || channel > WM8350_AUXADC_TEMP) | ||
| 1090 | return -EINVAL; | ||
| 1091 | if (channel >= WM8350_AUXADC_USB && channel <= WM8350_AUXADC_TEMP | ||
| 1092 | && (scale != 0 || vref != 0)) | ||
| 1093 | return -EINVAL; | ||
| 1094 | |||
| 1095 | mutex_lock(&wm8350->auxadc_mutex); | ||
| 1096 | |||
| 1097 | /* Turn on the ADC */ | ||
| 1098 | reg = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5); | ||
| 1099 | wm8350_reg_write(wm8350, WM8350_POWER_MGMT_5, reg | WM8350_AUXADC_ENA); | ||
| 1100 | |||
| 1101 | if (scale || vref) { | ||
| 1102 | reg = scale << 13; | ||
| 1103 | reg |= vref << 12; | ||
| 1104 | wm8350_reg_write(wm8350, WM8350_AUX1_READBACK + channel, reg); | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1); | ||
| 1108 | reg |= 1 << channel | WM8350_AUXADC_POLL; | ||
| 1109 | wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg); | ||
| 1110 | |||
| 1111 | do { | ||
| 1112 | schedule_timeout_interruptible(1); | ||
| 1113 | reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1); | ||
| 1114 | } while (tries-- && (reg & WM8350_AUXADC_POLL)); | ||
| 1115 | |||
| 1116 | if (!tries) | ||
| 1117 | dev_err(wm8350->dev, "adc chn %d read timeout\n", channel); | ||
| 1118 | else | ||
| 1119 | result = wm8350_reg_read(wm8350, | ||
| 1120 | WM8350_AUX1_READBACK + channel); | ||
| 1121 | |||
| 1122 | /* Turn off the ADC */ | ||
| 1123 | reg = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5); | ||
| 1124 | wm8350_reg_write(wm8350, WM8350_POWER_MGMT_5, | ||
| 1125 | reg & ~WM8350_AUXADC_ENA); | ||
| 1126 | |||
| 1127 | mutex_unlock(&wm8350->auxadc_mutex); | ||
| 1128 | |||
| 1129 | return result & WM8350_AUXADC_DATA1_MASK; | ||
| 1130 | } | ||
| 1131 | EXPORT_SYMBOL_GPL(wm8350_read_auxadc); | ||
| 1132 | |||
| 1085 | /* | 1133 | /* |
| 1086 | * Cache is always host endian. | 1134 | * Cache is always host endian. |
| 1087 | */ | 1135 | */ |
| @@ -1239,6 +1287,7 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, | |||
| 1239 | } | 1287 | } |
| 1240 | } | 1288 | } |
| 1241 | 1289 | ||
| 1290 | mutex_init(&wm8350->auxadc_mutex); | ||
| 1242 | mutex_init(&wm8350->irq_mutex); | 1291 | mutex_init(&wm8350->irq_mutex); |
| 1243 | INIT_WORK(&wm8350->irq_work, wm8350_irq_worker); | 1292 | INIT_WORK(&wm8350->irq_work, wm8350_irq_worker); |
| 1244 | if (irq) { | 1293 | if (irq) { |
diff --git a/include/linux/mfd/wm8350/comparator.h b/include/linux/mfd/wm8350/comparator.h index 05378864945..54bc5d0fd50 100644 --- a/include/linux/mfd/wm8350/comparator.h +++ b/include/linux/mfd/wm8350/comparator.h | |||
| @@ -164,4 +164,12 @@ | |||
| 164 | #define WM8350_AUXADC_BATT 6 | 164 | #define WM8350_AUXADC_BATT 6 |
| 165 | #define WM8350_AUXADC_TEMP 7 | 165 | #define WM8350_AUXADC_TEMP 7 |
| 166 | 166 | ||
| 167 | struct wm8350; | ||
| 168 | |||
| 169 | /* | ||
| 170 | * AUX ADC Readback | ||
| 171 | */ | ||
| 172 | int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, | ||
| 173 | int vref); | ||
| 174 | |||
| 167 | #endif | 175 | #endif |
diff --git a/include/linux/mfd/wm8350/core.h b/include/linux/mfd/wm8350/core.h index 9490ec175d5..cc190055b9c 100644 --- a/include/linux/mfd/wm8350/core.h +++ b/include/linux/mfd/wm8350/core.h | |||
| @@ -573,6 +573,8 @@ struct wm8350 { | |||
| 573 | void *src); | 573 | void *src); |
| 574 | u16 *reg_cache; | 574 | u16 *reg_cache; |
| 575 | 575 | ||
| 576 | struct mutex auxadc_mutex; | ||
| 577 | |||
| 576 | /* Interrupt handling */ | 578 | /* Interrupt handling */ |
| 577 | struct work_struct irq_work; | 579 | struct work_struct irq_work; |
| 578 | struct mutex irq_mutex; /* IRQ table mutex */ | 580 | struct mutex irq_mutex; /* IRQ table mutex */ |
