diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2008-11-07 19:10:21 -0500 |
---|---|---|
committer | Samuel Ortiz <samuel@sortiz.org> | 2009-01-04 06:17:38 -0500 |
commit | 67488526349d043372d141c054f4dc6313780b3c (patch) | |
tree | 22db1f6609edd7945fb000b4a9c48e86aadf3dfb /drivers/mfd | |
parent | 0c8a601678960fbcc1c1185a283d6d107575810b (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.c | 51 |
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 | */ |
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) { |