aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2008-11-07 19:10:21 -0500
committerSamuel Ortiz <samuel@sortiz.org>2009-01-04 06:17:38 -0500
commit67488526349d043372d141c054f4dc6313780b3c (patch)
tree22db1f6609edd7945fb000b4a9c48e86aadf3dfb /drivers/mfd
parent0c8a601678960fbcc1c1185a283d6d107575810b (diff)
mfd: Add AUXADC support for WM8350
The auxiliary ADC in the WM8350 is shared between several subdevices so access to it needs to be arbitrated by the core driver. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Samuel Ortiz <sameo@openedhand.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/wm8350-core.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c
index c013afde260d..60439bd3984d 100644
--- a/drivers/mfd/wm8350-core.c
+++ b/drivers/mfd/wm8350-core.c
@@ -63,7 +63,6 @@
63 */ 63 */
64static DEFINE_MUTEX(io_mutex); 64static DEFINE_MUTEX(io_mutex);
65static DEFINE_MUTEX(reg_lock_mutex); 65static DEFINE_MUTEX(reg_lock_mutex);
66static 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}
1083EXPORT_SYMBOL_GPL(wm8350_unmask_irq); 1082EXPORT_SYMBOL_GPL(wm8350_unmask_irq);
1084 1083
1084int 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}
1131EXPORT_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) {