안녕하세요!

보드 사양

smdk2440 레퍼런스

커널: 2.6.30.9 포팅

사용 클럭

399MHz, 133MHz, 66MHz를 사용합니다.

LCD : 800*480

 

 

Falinux 2440 에서 s3c2410-ts.c 파일을 참조하여

제 개발 보드에 이식을 하였습니다.

클럭 발생부분은

제가 falinux2440과 제 보드를 비교하였으나 동일하게 발생을 하였습니다.

하지만

x(low value = 0~50) => 950 ~ 1023 값이 나옵니다.

그이후부터는 계속 Max(1023)이 나오고요

좀더 자세하게 설명을 드리면

 

0~10~20~30~~~~~~512~~~~~~1000~~~1023

이렇게 나와야 하는데

950~1000~1023~~~~~~~1023~~~~~~~~1023

이렇게 나옵니다.

 

처음부터 Max값의 90% 를 가지고 시작하기때문에

 

조금만 지나도 금방 MAX값에 도달하여 의미 없는 값이 나옵니다.

아래 제 보드에 설정한 값을 명기 하였습니다.

한달가까이 이부분을 검토하고 있으나 변화가 없습니다.

원인이 뭔지 아시는 분은 답변을 부탁드립니다.

추가적으로

delay 부분과 presc 부분에 대한 이해가 부족합니다.

몇번을 읽어서 사실적인 내용은 이해가 가나 보드에 어떻게

적용을 하는지에 대해서 이해가 가질 않습니다.

혹시 아시는분 설명 부탁드립니다.

보드 셋팅값

===================================================

// TouchScreen Setup
static struct s3c2410_ts_mach_info falinux_s24xx_ts_cfg = {
.delay = 10000,
.presc = 49,
.oversampling_shift = 2,
};

====================================================

/* Touchscreen */
struct platform_device s3c_device_ts = {
.name = "s3c2410-ts",
.id = -1,
};
EXPORT_SYMBOL(s3c_device_ts);

static struct s3c2410_ts_mach_info s3c2410ts_info;

void __init set_s3c2410ts_info(struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
{
memcpy(&s3c2410ts_info,hard_s3c2410ts_info,sizeof(struct s3c2410_ts_mach_info));
s3c_device_ts.dev.platform_data = &s3c2410ts_info;
}
EXPORT_SYMBOL(set_s3c2410ts_info);

========================================================

ts.c

-------

/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
* iPAQ H1940 touchscreen support
*
* ChangeLog
*
* 2004-09-05: Herbert P철tzl <herbert@13thfloor.at>
* - added clock (de-)allocation code
*
* 2005-03-06: Arnaud Patard <arnaud.patard@rtp-net.org>
* - h1940_ -> s3c2410 (this driver is now also used on the n30
* machines :P)
* - Debug messages are now enabled with the config option
* TOUCHSCREEN_S3C2410_DEBUG
* - Changed the way the value are read
* - Input subsystem should now work
* - Use ioremap and readl/writel
*
* 2005-03-23: Arnaud Patard <arnaud.patard@rtp-net.org>
* - Make use of some undocumented features of the touchscreen
* controller
*
*/

#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <asm/irq.h>

#include <asm/arch/regs-adc.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/ts.h>

/* For ts.dev.id.version */
#define S3C2410TSVERSION 0x0101

#define WAIT4INT(x) (((x)<<8) | \
S3C2410_ADCTSC_YM_SEN | \
S3C2410_ADCTSC_YP_SEN | \
S3C2410_ADCTSC_XP_SEN | \
S3C2410_ADCTSC_XY_PST(3))

#define AUTOPST (S3C2410_ADCTSC_YM_SEN | \
S3C2410_ADCTSC_YP_SEN | \
S3C2410_ADCTSC_XP_SEN | \
S3C2410_ADCTSC_AUTO_PST | \
S3C2410_ADCTSC_XY_PST(0))

#define DEBUG_LVL KERN_DEBUG

MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
MODULE_DESCRIPTION("s3c2410 touchscreen driver");
MODULE_LICENSE("GPL");

/*
* Definitions & global arrays.
*/


static char *s3c2410ts_name = "s3c2410 TouchScreen";

/*
* Per-touchscreen data.
*/

struct s3c2410ts {
struct input_dev *dev;
long xp;
long yp;
int count;
int shift;
};

static struct s3c2410ts ts;
static void __iomem *base_addr;

static inline void s3c2410_ts_connect(void)
{
#ifdef CONFIG_CPU_S3C2410
s3c2410_gpio_cfgpin(S3C2410_GPG12, S3C2410_GPG12_XMON);
s3c2410_gpio_cfgpin(S3C2410_GPG13, S3C2410_GPG13_nXPON);
s3c2410_gpio_cfgpin(S3C2410_GPG14, S3C2410_GPG14_YMON);
s3c2410_gpio_cfgpin(S3C2410_GPG15, S3C2410_GPG15_nYPON);
#endif
}

static void touch_timer_fire(unsigned long data)
{
unsigned long data0;
unsigned long data1;
int updown;

data0 = readl(base_addr+S3C2410_ADCDAT0);
data1 = readl(base_addr+S3C2410_ADCDAT1);

updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));

if (updown) { // down
if (ts.count != 0) {
ts.xp >>= ts.shift;
ts.yp >>= ts.shift;

#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
{
struct timeval tv;
do_gettimeofday(&tv);
printk(DEBUG_LVL "T: %06d, X: %03ld, Y: %03ld\n", (int)tv.tv_usec, ts.xp, ts.yp);
}
#endif

input_report_abs(ts.dev, ABS_X, ts.xp);
input_report_abs(ts.dev, ABS_Y, ts.yp);

input_report_key(ts.dev, BTN_TOUCH, 1);
input_report_abs(ts.dev, ABS_PRESSURE, 1);
input_sync(ts.dev);
}

ts.xp = 0;
ts.yp = 0;
ts.count = 0;

writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
} else { // up
ts.count = 0;

input_report_key(ts.dev, BTN_TOUCH, 0);
input_report_abs(ts.dev, ABS_PRESSURE, 0);
input_sync(ts.dev);

writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
}
}

static struct timer_list touch_timer =
TIMER_INITIALIZER(touch_timer_fire, 0, 0);

static irqreturn_t stylus_updown(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long data0;
unsigned long data1;
int updown;

data0 = readl(base_addr+S3C2410_ADCDAT0);
data1 = readl(base_addr+S3C2410_ADCDAT1);

updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));

/* TODO we should never get an interrupt with updown set while
* the timer is running, but maybe we ought to verify that the
* timer isn't running anyways. */

if (updown)
touch_timer_fire(0);

return IRQ_HANDLED;
}


static irqreturn_t stylus_action(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned long data0;
unsigned long data1;

data0 = readl(base_addr+S3C2410_ADCDAT0);
data1 = readl(base_addr+S3C2410_ADCDAT1);

ts.xp += data0 & S3C2410_ADCDAT0_XPDATA_MASK;
ts.yp += data1 & S3C2410_ADCDAT1_YPDATA_MASK;
ts.count++;

if (ts.count < (1<<ts.shift)) {
writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, base_addr+S3C2410_ADCTSC);
writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START, base_addr+S3C2410_ADCCON);
} else {
mod_timer(&touch_timer, jiffies+1);
writel(WAIT4INT(1), base_addr+S3C2410_ADCTSC);
}

return IRQ_HANDLED;
}

static struct clk *adc_clock;

/*
* The functions for inserting/removing us as a module.
*/
static int __init s3c2410ts_probe(struct platform_device *pdev)
{
struct s3c2410_ts_mach_info *info;
struct input_dev *input_dev;

info = ( struct s3c2410_ts_mach_info *)pdev->dev.platform_data;

if (!info)
{
printk(KERN_ERR "Hm... too bad : no platform data for ts\n");
return -EINVAL;
}

#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
printk(DEBUG_LVL "Entering s3c2410ts_init\n");
#endif

adc_clock = clk_get(NULL, "adc");
if (!adc_clock) {
printk(KERN_ERR "failed to get adc clock source\n");
return -ENOENT;
}
clk_enable(adc_clock);

#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
printk(DEBUG_LVL "got and enabled clock\n");
#endif

base_addr=ioremap(S3C2410_PA_ADC,0x20);
if (base_addr == NULL) {
printk(KERN_ERR "Failed to remap register block\n");
return -ENOMEM;
}


/* Configure GPIOs */
s3c2410_ts_connect();

if ((info->presc&0xff) > 0)
writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(info->presc&0xFF),\
base_addr+S3C2410_ADCCON);
else
writel(0,base_addr+S3C2410_ADCCON);


/* Initialise registers */
if ((info->delay&0xffff) > 0)
writel(info->delay & 0xffff, base_addr+S3C2410_ADCDLY);

writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);

/* Initialise input stuff */
memset(&ts, 0, sizeof(struct s3c2410ts));
input_dev = input_allocate_device();

if (!input_dev) {
printk(KERN_ERR "Unable to allocate the input device !!\n");
return -ENOMEM;
}

ts.dev = input_dev;
ts.dev->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS);
ts.dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
input_set_abs_params(ts.dev, ABS_X, 0, 0x3FF, 0, 0);
input_set_abs_params(ts.dev, ABS_Y, 0, 0x3FF, 0, 0);
input_set_abs_params(ts.dev, ABS_PRESSURE, 0, 1, 0, 0);

ts.dev->private = &ts;
ts.dev->name = s3c2410ts_name;
ts.dev->id.bustype = BUS_RS232;
ts.dev->id.vendor = 0xDEAD;
ts.dev->id.product = 0xBEEF;
ts.dev->id.version = S3C2410TSVERSION;

ts.shift = info->oversampling_shift;

/* Get irqs */
if (request_irq(IRQ_ADC, stylus_action, SA_SAMPLE_RANDOM,
"s3c2410_action", ts.dev)) {
printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_ADC !\n");
iounmap(base_addr);
return -EIO;
}
if (request_irq(IRQ_TC, stylus_updown, SA_SAMPLE_RANDOM,
"s3c2410_action", ts.dev)) {
printk(KERN_ERR "s3c2410_ts.c: Could not allocate ts IRQ_TC !\n");
iounmap(base_addr);
return -EIO;
}

printk(KERN_INFO "%s successfully loaded\n", s3c2410ts_name);

/* All went ok, so register to the input system */
input_register_device(ts.dev);

return 0;
}

static int s3c2410ts_remove(struct platform_device *pdev)
{
disable_irq(IRQ_ADC);
disable_irq(IRQ_TC);
free_irq(IRQ_TC,ts.dev);
free_irq(IRQ_ADC,ts.dev);

if (adc_clock) {
clk_disable(adc_clock);
clk_put(adc_clock);
adc_clock = NULL;
}

input_unregister_device(ts.dev);
iounmap(base_addr);

return 0;
}

static struct platform_driver s3c2410ts_driver = {
.driver = {
.name = "s3c2410-ts",
.owner = THIS_MODULE,
},
.probe = s3c2410ts_probe,
.remove = s3c2410ts_remove,
};


static int __init s3c2410ts_init(void)
{
return platform_driver_register(&s3c2410ts_driver);
}

static void __exit s3c2410ts_exit(void)
{
platform_driver_unregister(&s3c2410ts_driver);
}

module_init(s3c2410ts_init);
module_exit(s3c2410ts_exit);
============================================================