aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2009-08-14 10:23:15 -0400
committerBen Dooks <ben-linux@fluff.org>2009-08-14 10:23:15 -0400
commit63c949ea1dcf5d46789f13d8e9c21bb8aeb605cb (patch)
treeca8e063aed16c0a5e5f51557861dbbad77da8bbb /arch
parent9b71de49b030ad8fd4d13d38571b5c42dc9ed8dd (diff)
parentbff78650a2b0ed42b8fb134b6a9b387e00027d67 (diff)
Merge branch 'next-s3c-hwmon' into next-s3c
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c32
-rw-r--r--arch/arm/plat-s3c/include/plat/adc.h8
-rw-r--r--arch/arm/plat-s3c/include/plat/devs.h2
-rw-r--r--arch/arm/plat-s3c/include/plat/hwmon.h41
-rw-r--r--arch/arm/plat-s3c24xx/adc.c64
-rw-r--r--arch/arm/plat-s3c24xx/devs.c2
6 files changed, 135 insertions, 14 deletions
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index ce3baba2cd7f..06670bb89cab 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -45,6 +45,7 @@
45#include <mach/regs-mem.h> 45#include <mach/regs-mem.h>
46#include <mach/regs-lcd.h> 46#include <mach/regs-lcd.h>
47 47
48#include <plat/hwmon.h>
48#include <plat/nand.h> 49#include <plat/nand.h>
49#include <plat/iic.h> 50#include <plat/iic.h>
50#include <mach/fb.h> 51#include <mach/fb.h>
@@ -547,7 +548,35 @@ static struct i2c_board_info bast_i2c_devs[] __initdata = {
547 }, 548 },
548}; 549};
549 550
551static struct s3c_hwmon_pdata bast_hwmon_info = {
552 /* LCD contrast (0-6.6V) */
553 .in[0] = &(struct s3c_hwmon_chcfg) {
554 .name = "lcd-contrast",
555 .mult = 3300,
556 .div = 512,
557 },
558 /* LED current feedback */
559 .in[1] = &(struct s3c_hwmon_chcfg) {
560 .name = "led-feedback",
561 .mult = 3300,
562 .div = 1024,
563 },
564 /* LCD feedback (0-6.6V) */
565 .in[2] = &(struct s3c_hwmon_chcfg) {
566 .name = "lcd-feedback",
567 .mult = 3300,
568 .div = 512,
569 },
570 /* Vcore (1.8-2.0V), Vref 3.3V */
571 .in[3] = &(struct s3c_hwmon_chcfg) {
572 .name = "vcore",
573 .mult = 3300,
574 .div = 1024,
575 },
576};
577
550/* Standard BAST devices */ 578/* Standard BAST devices */
579// cat /sys/devices/platform/s3c24xx-adc/s3c-hwmon/in_0
551 580
552static struct platform_device *bast_devices[] __initdata = { 581static struct platform_device *bast_devices[] __initdata = {
553 &s3c_device_usb, 582 &s3c_device_usb,
@@ -556,6 +585,8 @@ static struct platform_device *bast_devices[] __initdata = {
556 &s3c_device_i2c0, 585 &s3c_device_i2c0,
557 &s3c_device_rtc, 586 &s3c_device_rtc,
558 &s3c_device_nand, 587 &s3c_device_nand,
588 &s3c_device_adc,
589 &s3c_device_hwmon,
559 &bast_device_dm9k, 590 &bast_device_dm9k,
560 &bast_device_asix, 591 &bast_device_asix,
561 &bast_device_axpp, 592 &bast_device_axpp,
@@ -588,6 +619,7 @@ static void __init bast_map_io(void)
588 s3c24xx_register_clocks(bast_clocks, ARRAY_SIZE(bast_clocks)); 619 s3c24xx_register_clocks(bast_clocks, ARRAY_SIZE(bast_clocks));
589 620
590 s3c_device_nand.dev.platform_data = &bast_nand_info; 621 s3c_device_nand.dev.platform_data = &bast_nand_info;
622 s3c_device_hwmon.dev.platform_data = &bast_hwmon_info;
591 623
592 s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc)); 624 s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
593 s3c24xx_init_clocks(0); 625 s3c24xx_init_clocks(0);
diff --git a/arch/arm/plat-s3c/include/plat/adc.h b/arch/arm/plat-s3c/include/plat/adc.h
index d847bd476b6c..5f3b1cd53b90 100644
--- a/arch/arm/plat-s3c/include/plat/adc.h
+++ b/arch/arm/plat-s3c/include/plat/adc.h
@@ -19,10 +19,14 @@ struct s3c_adc_client;
19extern int s3c_adc_start(struct s3c_adc_client *client, 19extern int s3c_adc_start(struct s3c_adc_client *client,
20 unsigned int channel, unsigned int nr_samples); 20 unsigned int channel, unsigned int nr_samples);
21 21
22extern int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch);
23
22extern struct s3c_adc_client * 24extern struct s3c_adc_client *
23 s3c_adc_register(struct platform_device *pdev, 25 s3c_adc_register(struct platform_device *pdev,
24 void (*select)(unsigned selected), 26 void (*select)(struct s3c_adc_client *client,
25 void (*conv)(unsigned d0, unsigned d1, 27 unsigned selected),
28 void (*conv)(struct s3c_adc_client *client,
29 unsigned d0, unsigned d1,
26 unsigned *samples_left), 30 unsigned *samples_left),
27 unsigned int is_ts); 31 unsigned int is_ts);
28 32
diff --git a/arch/arm/plat-s3c/include/plat/devs.h b/arch/arm/plat-s3c/include/plat/devs.h
index 2e170827e0b0..1989ca1bb2b1 100644
--- a/arch/arm/plat-s3c/include/plat/devs.h
+++ b/arch/arm/plat-s3c/include/plat/devs.h
@@ -46,6 +46,8 @@ extern struct platform_device s3c_device_hsmmc2;
46extern struct platform_device s3c_device_spi0; 46extern struct platform_device s3c_device_spi0;
47extern struct platform_device s3c_device_spi1; 47extern struct platform_device s3c_device_spi1;
48 48
49extern struct platform_device s3c_device_hwmon;
50
49extern struct platform_device s3c_device_nand; 51extern struct platform_device s3c_device_nand;
50 52
51extern struct platform_device s3c_device_usbgadget; 53extern struct platform_device s3c_device_usbgadget;
diff --git a/arch/arm/plat-s3c/include/plat/hwmon.h b/arch/arm/plat-s3c/include/plat/hwmon.h
new file mode 100644
index 000000000000..1ba88ea0aa31
--- /dev/null
+++ b/arch/arm/plat-s3c/include/plat/hwmon.h
@@ -0,0 +1,41 @@
1/* linux/arch/arm/plat-s3c/include/plat/hwmon.h
2 *
3 * Copyright 2005 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 * http://armlinux.simtec.co.uk/
6 *
7 * S3C - HWMon interface for ADC
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12*/
13
14#ifndef __ASM_ARCH_ADC_HWMON_H
15#define __ASM_ARCH_ADC_HWMON_H __FILE__
16
17/**
18 * s3c_hwmon_chcfg - channel configuration
19 * @name: The name to give this channel.
20 * @mult: Multiply the ADC value read by this.
21 * @div: Divide the value from the ADC by this.
22 *
23 * The value read from the ADC is converted to a value that
24 * hwmon expects (mV) by result = (value_read * @mult) / @div.
25 */
26struct s3c_hwmon_chcfg {
27 const char *name;
28 unsigned int mult;
29 unsigned int div;
30};
31
32/**
33 * s3c_hwmon_pdata - HWMON platform data
34 * @in: One configuration for each possible channel used.
35 */
36struct s3c_hwmon_pdata {
37 struct s3c_hwmon_chcfg *in[8];
38};
39
40#endif /* __ASM_ARCH_ADC_HWMON_H */
41
diff --git a/arch/arm/plat-s3c24xx/adc.c b/arch/arm/plat-s3c24xx/adc.c
index ee1baf11ad9e..11117a7ba911 100644
--- a/arch/arm/plat-s3c24xx/adc.c
+++ b/arch/arm/plat-s3c24xx/adc.c
@@ -39,13 +39,16 @@
39struct s3c_adc_client { 39struct s3c_adc_client {
40 struct platform_device *pdev; 40 struct platform_device *pdev;
41 struct list_head pend; 41 struct list_head pend;
42 wait_queue_head_t *wait;
42 43
43 unsigned int nr_samples; 44 unsigned int nr_samples;
45 int result;
44 unsigned char is_ts; 46 unsigned char is_ts;
45 unsigned char channel; 47 unsigned char channel;
46 48
47 void (*select_cb)(unsigned selected); 49 void (*select_cb)(struct s3c_adc_client *c, unsigned selected);
48 void (*convert_cb)(unsigned val1, unsigned val2, 50 void (*convert_cb)(struct s3c_adc_client *c,
51 unsigned val1, unsigned val2,
49 unsigned *samples_left); 52 unsigned *samples_left);
50}; 53};
51 54
@@ -81,7 +84,7 @@ static inline void s3c_adc_select(struct adc_device *adc,
81{ 84{
82 unsigned con = readl(adc->regs + S3C2410_ADCCON); 85 unsigned con = readl(adc->regs + S3C2410_ADCCON);
83 86
84 client->select_cb(1); 87 client->select_cb(client, 1);
85 88
86 con &= ~S3C2410_ADCCON_MUXMASK; 89 con &= ~S3C2410_ADCCON_MUXMASK;
87 con &= ~S3C2410_ADCCON_STDBM; 90 con &= ~S3C2410_ADCCON_STDBM;
@@ -153,25 +156,61 @@ int s3c_adc_start(struct s3c_adc_client *client,
153} 156}
154EXPORT_SYMBOL_GPL(s3c_adc_start); 157EXPORT_SYMBOL_GPL(s3c_adc_start);
155 158
156static void s3c_adc_default_select(unsigned select) 159static void s3c_convert_done(struct s3c_adc_client *client,
160 unsigned v, unsigned u, unsigned *left)
161{
162 client->result = v;
163 wake_up(client->wait);
164}
165
166int s3c_adc_read(struct s3c_adc_client *client, unsigned int ch)
167{
168 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
169 int ret;
170
171 client->convert_cb = s3c_convert_done;
172 client->wait = &wake;
173 client->result = -1;
174
175 ret = s3c_adc_start(client, ch, 1);
176 if (ret < 0)
177 goto err;
178
179 ret = wait_event_timeout(wake, client->result >= 0, HZ / 2);
180 if (client->result < 0) {
181 ret = -ETIMEDOUT;
182 goto err;
183 }
184
185 client->convert_cb = NULL;
186 return client->result;
187
188err:
189 return ret;
190}
191EXPORT_SYMBOL_GPL(s3c_adc_convert);
192
193static void s3c_adc_default_select(struct s3c_adc_client *client,
194 unsigned select)
157{ 195{
158} 196}
159 197
160struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev, 198struct s3c_adc_client *s3c_adc_register(struct platform_device *pdev,
161 void (*select)(unsigned int selected), 199 void (*select)(struct s3c_adc_client *client,
162 void (*conv)(unsigned d0, unsigned d1, 200 unsigned int selected),
201 void (*conv)(struct s3c_adc_client *client,
202 unsigned d0, unsigned d1,
163 unsigned *samples_left), 203 unsigned *samples_left),
164 unsigned int is_ts) 204 unsigned int is_ts)
165{ 205{
166 struct s3c_adc_client *client; 206 struct s3c_adc_client *client;
167 207
168 WARN_ON(!pdev); 208 WARN_ON(!pdev);
169 WARN_ON(!conv);
170 209
171 if (!select) 210 if (!select)
172 select = s3c_adc_default_select; 211 select = s3c_adc_default_select;
173 212
174 if (!conv || !pdev) 213 if (!pdev)
175 return ERR_PTR(-EINVAL); 214 return ERR_PTR(-EINVAL);
176 215
177 client = kzalloc(sizeof(struct s3c_adc_client), GFP_KERNEL); 216 client = kzalloc(sizeof(struct s3c_adc_client), GFP_KERNEL);
@@ -230,16 +269,19 @@ static irqreturn_t s3c_adc_irq(int irq, void *pw)
230 adc_dbg(adc, "read %d: 0x%04x, 0x%04x\n", client->nr_samples, data0, data1); 269 adc_dbg(adc, "read %d: 0x%04x, 0x%04x\n", client->nr_samples, data0, data1);
231 270
232 client->nr_samples--; 271 client->nr_samples--;
233 (client->convert_cb)(data0 & 0x3ff, data1 & 0x3ff, &client->nr_samples); 272
273 if (client->convert_cb)
274 (client->convert_cb)(client, data0 & 0x3ff, data1 & 0x3ff,
275 &client->nr_samples);
234 276
235 if (client->nr_samples > 0) { 277 if (client->nr_samples > 0) {
236 /* fire another conversion for this */ 278 /* fire another conversion for this */
237 279
238 client->select_cb(1); 280 client->select_cb(client, 1);
239 s3c_adc_convert(adc); 281 s3c_adc_convert(adc);
240 } else { 282 } else {
241 local_irq_save(flags); 283 local_irq_save(flags);
242 (client->select_cb)(0); 284 (client->select_cb)(client, 0);
243 adc->cur = NULL; 285 adc->cur = NULL;
244 286
245 s3c_adc_try(adc); 287 s3c_adc_try(adc);
diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c
index 4eb378c89a39..3489019b5374 100644
--- a/arch/arm/plat-s3c24xx/devs.c
+++ b/arch/arm/plat-s3c24xx/devs.c
@@ -348,7 +348,7 @@ struct platform_device s3c_device_adc = {
348/* HWMON */ 348/* HWMON */
349 349
350struct platform_device s3c_device_hwmon = { 350struct platform_device s3c_device_hwmon = {
351 .name = "s3c24xx-hwmon", 351 .name = "s3c-hwmon",
352 .id = -1, 352 .id = -1,
353 .dev.parent = &s3c_device_adc.dev, 353 .dev.parent = &s3c_device_adc.dev,
354}; 354};