主题 : tiny4412外设寄存器地址定义位置 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 101173
精华: 0
发帖: 13
金钱: 65 两
威望: 13 点
综合积分: 26 分
注册时间: 2014-03-04
最后登录: 2014-04-20
楼主  发表于: 2014-04-05 18:57

 tiny4412外设寄存器地址定义位置

tiny4412开发板外设寄存器地址,如ADC设备控制寄存器的地址是定义在哪个文件呢?
*無鈳取玳
级别: 论坛版主
UID: 27
精华: 12
发帖: 5398
金钱: 40120 两
威望: 17929 点
综合积分: 11036 分
注册时间: 2008-01-16
最后登录: 2014-11-22
1楼  发表于: 2014-04-05 22:06

 回 楼主(liyun422828) 的帖子

对于ADC,参考arch/arm/plat-samsung/devs.c里下面部分的代码。可以看到,ADC寄存器的起始地址是由SAMSUNG_PA_ADC这个宏定义的。
复制代码
  1. #if defined(CONFIG_SAMSUNG_DEV_ADC)
  2. static struct resource s3c_adc_resource[] = {
  3.         [0] = DEFINE_RES_MEM(SAMSUNG_PA_ADC, SZ_256),
  4. #ifdef IRQ_TC
  5.         [1] = DEFINE_RES_IRQ(IRQ_TC),
  6. #endif
  7.         [2] = DEFINE_RES_IRQ_NAMED(IRQ_ADC, "samsung-adc"),
  8. };
  9. struct platform_device s3c_device_adc = {
  10.         .name           = "samsung-adc",
  11.         .id             = -1,
  12.         .num_resources  = ARRAY_SIZE(s3c_adc_resource),
  13.         .resource       = s3c_adc_resource,
  14. };
"If you have an apple and I have an apple and we exchange apples, then you and I will
still each have one apple. But if you have an idea and I have an idea and we exchange
these ideas, then each of us will have two ideas."
级别: 新手上路
UID: 101173
精华: 0
发帖: 13
金钱: 65 两
威望: 13 点
综合积分: 26 分
注册时间: 2014-03-04
最后登录: 2014-04-20
2楼  发表于: 2014-04-09 22:15
多谢1楼的回答,还是存在一些疑问。adc转换结果是通过中断读取的,即Adc.c (位于linux-3.5\arch\arm\plat-samsung)的s3c_adc_irq函数。该函数data0 = readl(adc->regs + S3C2410_ADCDAT0);语句使用adc->regs + S3C2410_ADCDAT0获取地址,那么adc->regs在哪里获取地址的呢?怎么和SAMSUNG_PA_ADC发生联系的啊?

static irqreturn_t s3c_adc_irq(int irq, void *pw)
{
    struct adc_device *adc = pw;
    struct s3c_adc_client *client;
    enum s3c_cpu_type cpu = platform_get_device_id(adc->pdev)->driver_data;
    unsigned data0;
    unsigned data1 = 0;

    /* Need lock before accessing adc->cur; also keep for ->client
     * access since that's accessed elsewhere in adc_read() / adc_start()
     */
    spin_lock(&adc->lock);

    client = adc->cur;
    if (!client) {
        dev_warn(&adc->pdev->dev, "%s: no adc pending\n", __func__);
        spin_unlock(&adc->lock);
        goto exit;
    }

    data0 = readl(adc->regs + S3C2410_ADCDAT0);
    if (cpu == TYPE_ADCV4) {
        adc_dbg(adc, "read %d: 0x%04x\n", client->nr_samples, data0);
    } else {
        data1 = readl(adc->regs + S3C2410_ADCDAT1);
        adc_dbg(adc, "read %d: 0x%04x, 0x%04x\n", client->nr_samples,
            data0, data1);
    }

    client->nr_samples--;

    if (cpu == TYPE_ADCV1 || cpu == TYPE_ADCV11) {
        data0 &= 0x3ff;
        data1 &= 0x3ff;
    } else {
        /* S3C2416/S3C64XX/S5P ADC resolution is 12-bit */
        data0 &= 0xfff;
        data1 &= 0xfff;
    }

    if (client->convert_cb)
        (client->convert_cb)(client, data0, data1, &client->nr_samples);

    if (client->nr_samples > 0) {
        /* fire another conversion for this */

        client->select_cb(client, 1);
        s3c_adc_convert(adc);
    } else {
        client->select_cb(client, 0);
        adc->cur = NULL;
        s3c_adc_try(adc);
    }
    spin_unlock(&adc->lock);

exit:
    if (cpu == TYPE_ADCV2 || cpu == TYPE_ADCV3 || cpu == TYPE_ADCV4) {
        /* Clear ADC interrupt */
        writel(0, adc->regs + S3C64XX_ADCCLRINT);
    }
    return IRQ_HANDLED;
}
级别: 新手上路
UID: 101173
精华: 0
发帖: 13
金钱: 65 两
威望: 13 点
综合积分: 26 分
注册时间: 2014-03-04
最后登录: 2014-04-20
3楼  发表于: 2014-04-09 22:38
1楼回复的S3C24XX_PA_ADC地址是s3c2440开发板 中ADC的地址,并不是tiny4412中adc寄存器的地址
#ifdef CONFIG_PLAT_S3C24XX
static struct resource s3c_adc_resource[] = {
    [0] = DEFINE_RES_MEM(S3C24XX_PA_ADC, S3C24XX_SZ_ADC),
    [1] = DEFINE_RES_IRQ(IRQ_TC),
    [2] = DEFINE_RES_IRQ_NAMED(IRQ_ADC, "samsung-adc"),
};

在Mach-tiny4412.c (linux-3.5\arch\arm\mach-exynos)    文件中定义了平台设备,但是没有资源定义,糊涂了。
static struct platform_device tiny4412_device_adc = {
    .name            = "tiny4412_adc",
    .id                = -1,
    .num_resources    = 0,
};
*無鈳取玳
级别: 论坛版主
UID: 27
精华: 12
发帖: 5398
金钱: 40120 两
威望: 17929 点
综合积分: 11036 分
注册时间: 2008-01-16
最后登录: 2014-11-22
4楼  发表于: 2014-04-10 21:58

 回 3楼(liyun422828) 的帖子

注意arch/arm/plat-samsung/devs.c里的条件编译,对于tiny4412来说,CONFIG_PLAT_S3C24XX是没有定义的,定义的是CONFIG_SAMSUNG_DEV_ADC。所以,和s3c_device_adc匹配resource的是下面红色部分的代码。

/* ADC */

#ifdef CONFIG_PLAT_S3C24XX
static struct resource s3c_adc_resource[] = {
        [0] = DEFINE_RES_MEM(S3C24XX_PA_ADC, S3C24XX_SZ_ADC),
        [1] = DEFINE_RES_IRQ(IRQ_TC),
        [2] = DEFINE_RES_IRQ_NAMED(IRQ_ADC, "samsung-adc"),
};

struct platform_device s3c_device_adc = {
        .name           = "s3c24xx-adc",
        .id             = -1,
        .num_resources  = ARRAY_SIZE(s3c_adc_resource),
        .resource       = s3c_adc_resource,
};
#endif /* CONFIG_PLAT_S3C24XX */

#if defined(CONFIG_SAMSUNG_DEV_ADC)
static struct resource s3c_adc_resource[] = {
        [0] = DEFINE_RES_MEM(SAMSUNG_PA_ADC, SZ_256),
#ifdef IRQ_TC
        [1] = DEFINE_RES_IRQ(IRQ_TC),
#endif
        [2] = DEFINE_RES_IRQ_NAMED(IRQ_ADC, "samsung-adc"),
};


struct platform_device s3c_device_adc = {
        .name           = "samsung-adc",
        .id             = -1,
        .num_resources  = ARRAY_SIZE(s3c_adc_resource),
        .resource       = s3c_adc_resource,
};

void __init s3c_adc_set_platdata(struct s3c_adc_platdata *pd)
{
        s3c_set_platdata(pd, sizeof(struct s3c_adc_platdata),
                        &s3c_device_adc);
}
#endif /* CONFIG_SAMSUNG_DEV_ADC */

其中,SAMSUNG_PA_ADC定义在arch/arm/mach-exynos/include/mach/map.h中:
复制代码
  1. #if defined(CONFIG_SOC_EXYNOS4412)
  2. #define SAMSUNG_PA_ADC                  EXYNOS4412_PA_ADC
  3. #else
  4. #define SAMSUNG_PA_ADC                  EXYNOS4210_PA_ADC

对于tiny4412来说,用的是EXYNOS4412_PA_ADC

至于tiny4412_adc, 这个是友善之臂自己写的一个基于s3c_adc驱动之上的“客户”驱动,把应用程序对于ADC的访问转到ADC的Channnel 0并通过s3c_adc驱动访问硬件。它的源代码在drivers/char/tiny4412_adc.c
"If you have an apple and I have an apple and we exchange apples, then you and I will
still each have one apple. But if you have an idea and I have an idea and we exchange
these ideas, then each of us will have two ideas."
级别: 新手上路
UID: 101173
精华: 0
发帖: 13
金钱: 65 两
威望: 13 点
综合积分: 26 分
注册时间: 2014-03-04
最后登录: 2014-04-20
5楼  发表于: 2014-04-14 20:12
楼上正解,非常感谢。本人还有个问题想请教。
问题一:arch/arm/plat-samsung/devs.c定义设备设备名称是"samsung-adc"
struct platform_device s3c_device_adc = {
        .name           = "samsung-adc",
        .id             = -1,
        .num_resources  = ARRAY_SIZE(s3c_adc_resource),
        .resource       = s3c_adc_resource,
};
然而drivers/char/tiny4412_adc.c驱动文件中定义的设备名称是"tiny4412_adc",这两个名称不一样,设备和驱动能匹配吗?

问题二:exynos_adc_probe()函数中调用s3c_adc驱动中的s3c_adc_register()函数时,Adc.c (linux-3.5\arch\arm\plat-samsung)文件中的s3c_adc_probe()函数是否会调用呢,怎么开始被调用呢,这个过渡过程还是没明白。

static int __devinit exynos_adc_probe(struct platform_device *dev)
{
    int ret;

    mutex_init(&adcdev.lock);

    /* Register with the core ADC driver. */
    adcdev.client = s3c_adc_register(dev, NULL, NULL, 0);
    if (IS_ERR(adcdev.client)) {
        printk("tiny4412_adc: cannot register adc\n");
        ret = PTR_ERR(adcdev.client);
        goto err_mem;
    }

    ret = misc_register(&misc);

    printk(DEVICE_NAME"\tinitialized\n");

err_mem:
    return ret;
}
*無鈳取玳
级别: 论坛版主
UID: 27
精华: 12
发帖: 5398
金钱: 40120 两
威望: 17929 点
综合积分: 11036 分
注册时间: 2008-01-16
最后登录: 2014-11-22
6楼  发表于: 2014-04-14 21:23
然而drivers/char/tiny4412_adc.c驱动文件中定义的设备名称是"tiny4412_adc",这两个名称不一样,设备和驱动能匹配吗?

注意这里实际上有上下两层驱动,和“s3c_device_adc”匹配的驱动是底层的真正的ADC的驱动,源代码在arch/arm/plat-samsung/adc.c;
上层的"drivers/char/tiny4412_adc.c"这个驱动是和mach-tiny4412.c里的“tiny4412_device_adc”这个设备匹配的。它们之间的关系参考我在前面回复中的描述。

问题二:exynos_adc_probe()函数中调用s3c_adc驱动中的s3c_adc_register()函数时,Adc.c (linux-3.5\arch\arm\plat-samsung)文件中的s3c_adc_probe()函数是否会调用呢,怎么开始被调用呢,这个过渡过程还是没明白。

会被调用到。你可以认为adc.c里定义的函数就是和printf()一样的库函数,和应用程序源代码(这里是tiny4412_adc.c)链接在一起,供运行时调用。
"If you have an apple and I have an apple and we exchange apples, then you and I will
still each have one apple. But if you have an idea and I have an idea and we exchange
these ideas, then each of us will have two ideas."
级别: 新手上路
UID: 101173
精华: 0
发帖: 13
金钱: 65 两
威望: 13 点
综合积分: 26 分
注册时间: 2014-03-04
最后登录: 2014-04-20
7楼  发表于: 2014-04-15 11:53
编写一个应用程序测试tiny4412开发板自带的adc驱动,一直显示如下信息,得不到输出结果,这个可能是什么问题呢?
[root@chipcore /mnt]# ./test_tiny4412_adc
[  123.645000] s3c-adc samsung-adc-v4: s3c_adc_read: ec91b080 is timed out
[  127.145000] s3c-adc samsung-adc-v4: s3c_adc_read: ec91b080 is timed out
[  130.645000] s3c-adc samsung-adc-v4: s3c_adc_read: ec91b080 is timed out
[  134.145000] s3c-adc samsung-adc-v4: s3c_adc_read: ec91b080 is timed out
[  137.645000] s3c-adc samsung-adc-v4: s3c_adc_read: ec91b080 is timed out
[  141.145000] s3c-adc samsung-adc-v4: s3c_adc_read: ec91b080 is timed out
[  144.645000] s3c-adc samsung-adc-v4: s3c_adc_read: ec91b080 is timed out
[  148.145000] s3c-adc samsung-adc-v4: s3c_adc_read: ec91b080 is timed out
[  151.645000] s3c-adc samsung-adc-v4: s3c_adc_read: ec91b080 is timed out
[  155.145000] s3c-adc samsung-adc-v4: s3c_adc_read: ec91b080 is timed out
[  158.645000] s3c-adc samsung-adc-v4: s3c_adc_read: ec91b080 is timed out

发现在调用adc.c文件中s3c_adc_read 函数时出错了
ret = s3c_get_result(client);

    if (ret < 0) {
        s3c_adc_stop(client);
        dev_warn(&adc_dev->pdev->dev, "%s: %p is timed out\n",
                        __func__, client);
        ret = -ETIMEDOUT;
    }
*無鈳取玳
级别: 论坛版主
UID: 27
精华: 12
发帖: 5398
金钱: 40120 两
威望: 17929 点
综合积分: 11036 分
注册时间: 2008-01-16
最后登录: 2014-11-22
8楼  发表于: 2014-04-15 12:28

 回 7楼(liyun422828) 的帖子

建议你另外发一个帖子讨论这个问题。另外,最好能把你的测试程序源代码附上方便别人帮你验证。
"If you have an apple and I have an apple and we exchange apples, then you and I will
still each have one apple. But if you have an idea and I have an idea and we exchange
these ideas, then each of us will have two ideas."
级别: 新手上路
UID: 101173
精华: 0
发帖: 13
金钱: 65 两
威望: 13 点
综合积分: 26 分
注册时间: 2014-03-04
最后登录: 2014-04-20
9楼  发表于: 2014-04-15 15:35
tiny4412测试程序代码如下:
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc,char* argv[])
{
        int fd;
        float fVal;
        int ret;
        unsigned int iVal;
        int cmd;


        fd = open("/dev/adc",O_RDWR);
        if(fd<0)
        {
                perror("open /dev/adc error:");
        }
        cmd = 0xc000fa01;
        //ioctl(fd,cmd);
        while(1)
        {
                ret = read(fd,&iVal,sizeof(iVal));
                printf("Voltage is: %d  or  %f",iVal,(float)(iVal*1.8/1024));  
                sleep(3);
        }
        close(fd);
        printf("/dev/adc closed! \n");
        return 0;
}
另外用开发板自带的# adc-test命令,也会出现同样的现象
[root@chipcore /mnt]# adc-test
press Ctrl-C to stop
[14980.715000] s3c-adc samsung-adc-v4: s3c_adc_read: ec91b080 is timed out
ADC Value: -110
[14981.715000] s3c-adc samsung-adc-v4: s3c_adc_read: ec91b080 is timed out
ADC Value: -110
[14982.715000] s3c-adc samsung-adc-v4: s3c_adc_read: ec91b080 is timed out
ADC Value: -110
[14983.715000] s3c-adc samsung-adc-v4: s3c_adc_read: ec91b080 is timed out
ADC Value: -110
[14984.715000] s3c-adc samsung-adc-v4: s3c_adc_read: ec91b080 is timed out
ADC Value: -110