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 | |
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>
-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 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) { |
diff --git a/include/linux/mfd/wm8350/comparator.h b/include/linux/mfd/wm8350/comparator.h index 053788649452..54bc5d0fd502 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 9490ec175d5a..cc190055b9c4 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 */ |