#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/list.h>
+#include <linux/slab.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/interrupt.h>
* action is required.
*/
+enum s3c_cpu_type {
+ TYPE_S3C24XX,
+ TYPE_S3C64XX
+};
+
struct s3c_adc_client {
struct platform_device *pdev;
struct list_head pend;
{
struct adc_device *adc = pw;
struct s3c_adc_client *client = adc->cur;
+ enum s3c_cpu_type cpu = platform_get_device_id(adc->pdev)->driver_data;
unsigned long flags;
unsigned data0, data1;
if (!client) {
dev_warn(&adc->pdev->dev, "%s: no adc pending\n", __func__);
- return IRQ_HANDLED;
+ goto exit;
}
data0 = readl(adc->regs + S3C2410_ADCDAT0);
client->nr_samples--;
+ if (cpu == TYPE_S3C64XX) {
+ /* S3C64XX ADC resolution is 12-bit */
+ data0 &= 0xfff;
+ data1 &= 0xfff;
+ } else {
+ data0 &= 0x3ff;
+ data1 &= 0x3ff;
+ }
+
if (client->convert_cb)
- (client->convert_cb)(client, data0 & 0x3ff, data1 & 0x3ff,
- &client->nr_samples);
+ (client->convert_cb)(client, data0, data1, &client->nr_samples);
if (client->nr_samples > 0) {
/* fire another conversion for this */
local_irq_restore(flags);
}
+exit:
+ if (cpu == TYPE_S3C64XX) {
+ /* Clear ADC interrupt */
+ writel(0, adc->regs + S3C64XX_ADCCLRINT);
+ }
return IRQ_HANDLED;
}
struct adc_device *adc;
struct resource *regs;
int ret;
+ unsigned tmp;
adc = kzalloc(sizeof(struct adc_device), GFP_KERNEL);
if (adc == NULL) {
clk_enable(adc->clk);
- writel(adc->prescale | S3C2410_ADCCON_PRSCEN,
- adc->regs + S3C2410_ADCCON);
+ tmp = adc->prescale | S3C2410_ADCCON_PRSCEN;
+ if (platform_get_device_id(pdev)->driver_data == TYPE_S3C64XX) {
+ /* Enable 12-bit ADC resolution */
+ tmp |= S3C64XX_ADCCON_RESSEL;
+ }
+ writel(tmp, adc->regs + S3C2410_ADCCON);
dev_info(dev, "attached adc driver\n");
con |= S3C2410_ADCCON_STDBM;
writel(con, adc->regs + S3C2410_ADCCON);
+ disable_irq(adc->irq);
clk_disable(adc->clk);
return 0;
struct adc_device *adc = platform_get_drvdata(pdev);
clk_enable(adc->clk);
+ enable_irq(adc->irq);
writel(adc->prescale | S3C2410_ADCCON_PRSCEN,
adc->regs + S3C2410_ADCCON);
#define s3c_adc_resume NULL
#endif
+static struct platform_device_id s3c_adc_driver_ids[] = {
+ {
+ .name = "s3c24xx-adc",
+ .driver_data = TYPE_S3C24XX,
+ }, {
+ .name = "s3c64xx-adc",
+ .driver_data = TYPE_S3C64XX,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(platform, s3c_adc_driver_ids);
+
static struct platform_driver s3c_adc_driver = {
+ .id_table = s3c_adc_driver_ids,
.driver = {
- .name = "s3c24xx-adc",
+ .name = "s3c-adc",
.owner = THIS_MODULE,
},
.probe = s3c_adc_probe,