Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
38310772
Commit
38310772
authored
Apr 26, 2007
by
Tony Lindgren
Browse files
Options
Browse Files
Download
Plain Diff
Merge omap-drivers
parents
74adb813
a043909d
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
255 additions
and
154 deletions
+255
-154
drivers/char/watchdog/omap_wdt.c
drivers/char/watchdog/omap_wdt.c
+156
-96
drivers/char/watchdog/omap_wdt.h
drivers/char/watchdog/omap_wdt.h
+9
-19
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-omap.c
+90
-39
No files found.
drivers/char/watchdog/omap_wdt.c
View file @
38310772
...
...
@@ -50,49 +50,61 @@
#include "omap_wdt.h"
static
struct
platform_device
*
omap_wdt_dev
;
static
unsigned
timer_margin
;
module_param
(
timer_margin
,
uint
,
0
);
MODULE_PARM_DESC
(
timer_margin
,
"initial watchdog timeout (in seconds)"
);
static
int
omap_wdt_users
;
static
struct
clk
*
armwdt_ck
=
NULL
;
static
struct
clk
*
mpu_wdt_ick
=
NULL
;
static
struct
clk
*
mpu_wdt_fck
=
NULL
;
static
unsigned
int
wdt_trgr_pattern
=
0x1234
;
struct
omap_wdt_dev
{
void
__iomem
*
base
;
/* physical */
struct
device
*
dev
;
int
omap_wdt_users
;
struct
clk
*
armwdt_ck
;
struct
clk
*
mpu_wdt_ick
;
struct
clk
*
mpu_wdt_fck
;
struct
resource
*
mem
;
struct
miscdevice
omap_wdt_miscdev
;
};
static
void
omap_wdt_ping
(
void
)
static
void
omap_wdt_ping
(
struct
omap_wdt_dev
*
wdev
)
{
void
__iomem
*
base
=
wdev
->
base
;
/* wait for posted write to complete */
while
((
omap_readl
(
OMAP_WATCHDOG_WPS
))
&
0x08
)
while
((
omap_readl
(
base
+
OMAP_WATCHDOG_WPS
))
&
0x08
)
cpu_relax
();
wdt_trgr_pattern
=
~
wdt_trgr_pattern
;
omap_writel
(
wdt_trgr_pattern
,
(
OMAP_WATCHDOG_TGR
));
omap_writel
(
wdt_trgr_pattern
,
(
base
+
OMAP_WATCHDOG_TGR
));
/* wait for posted write to complete */
while
((
omap_readl
(
OMAP_WATCHDOG_WPS
))
&
0x08
)
while
((
omap_readl
(
base
+
OMAP_WATCHDOG_WPS
))
&
0x08
)
cpu_relax
();
/* reloaded WCRR from WLDR */
}
static
void
omap_wdt_enable
(
void
)
static
void
omap_wdt_enable
(
struct
omap_wdt_dev
*
wdev
)
{
void
__iomem
*
base
;
base
=
wdev
->
base
;
/* Sequence to enable the watchdog */
omap_writel
(
0xBBBB
,
OMAP_WATCHDOG_SPR
);
while
((
omap_readl
(
OMAP_WATCHDOG_WPS
))
&
0x10
)
omap_writel
(
0xBBBB
,
base
+
OMAP_WATCHDOG_SPR
);
while
((
omap_readl
(
base
+
OMAP_WATCHDOG_WPS
))
&
0x10
)
cpu_relax
();
omap_writel
(
0x4444
,
OMAP_WATCHDOG_SPR
);
while
((
omap_readl
(
OMAP_WATCHDOG_WPS
))
&
0x10
)
omap_writel
(
0x4444
,
base
+
OMAP_WATCHDOG_SPR
);
while
((
omap_readl
(
base
+
OMAP_WATCHDOG_WPS
))
&
0x10
)
cpu_relax
();
}
static
void
omap_wdt_disable
(
void
)
static
void
omap_wdt_disable
(
struct
omap_wdt_dev
*
wdev
)
{
void
__iomem
*
base
;
base
=
wdev
->
base
;
/* sequence required to disable watchdog */
omap_writel
(
0xAAAA
,
OMAP_WATCHDOG_SPR
);
/* TIMER_MODE */
while
(
omap_readl
(
OMAP_WATCHDOG_WPS
)
&
0x10
)
omap_writel
(
0xAAAA
,
base
+
OMAP_WATCHDOG_SPR
);
/* TIMER_MODE */
while
(
omap_readl
(
base
+
OMAP_WATCHDOG_WPS
)
&
0x10
)
cpu_relax
();
omap_writel
(
0x5555
,
OMAP_WATCHDOG_SPR
);
/* TIMER_MODE */
while
(
omap_readl
(
OMAP_WATCHDOG_WPS
)
&
0x10
)
omap_writel
(
0x5555
,
base
+
OMAP_WATCHDOG_SPR
);
/* TIMER_MODE */
while
(
omap_readl
(
base
+
OMAP_WATCHDOG_WPS
)
&
0x10
)
cpu_relax
();
}
...
...
@@ -105,15 +117,17 @@ static void omap_wdt_adjust_timeout(unsigned new_timeout)
timer_margin
=
new_timeout
;
}
static
void
omap_wdt_set_timeout
(
void
)
static
void
omap_wdt_set_timeout
(
struct
omap_wdt_dev
*
wdev
)
{
u32
pre_margin
=
GET_WLDR_VAL
(
timer_margin
);
void
__iomem
*
base
;
base
=
wdev
->
base
;
/* just count up at 32 KHz */
while
(
omap_readl
(
OMAP_WATCHDOG_WPS
)
&
0x04
)
while
(
omap_readl
(
base
+
OMAP_WATCHDOG_WPS
)
&
0x04
)
cpu_relax
();
omap_writel
(
pre_margin
,
OMAP_WATCHDOG_LDR
);
while
(
omap_readl
(
OMAP_WATCHDOG_WPS
)
&
0x04
)
omap_writel
(
pre_margin
,
base
+
OMAP_WATCHDOG_LDR
);
while
(
omap_readl
(
base
+
OMAP_WATCHDOG_WPS
)
&
0x04
)
cpu_relax
();
}
...
...
@@ -123,55 +137,65 @@ static void omap_wdt_set_timeout(void)
static
int
omap_wdt_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
if
(
test_and_set_bit
(
1
,
(
unsigned
long
*
)
&
omap_wdt_users
))
struct
omap_wdt_dev
*
wdev
;
void
__iomem
*
base
;
wdev
=
platform_get_drvdata
(
omap_wdt_dev
);
base
=
wdev
->
base
;
if
(
test_and_set_bit
(
1
,
(
unsigned
long
*
)
&
(
wdev
->
omap_wdt_users
)))
return
-
EBUSY
;
if
(
cpu_is_omap16xx
())
clk_enable
(
armwdt_ck
);
/* Enable the clock */
clk_enable
(
wdev
->
armwdt_ck
);
/* Enable the clock */
if
(
cpu_is_omap24xx
())
{
clk_enable
(
mpu_wdt_ick
);
/* Enable the interface clock */
clk_enable
(
mpu_wdt_fck
);
/* Enable the functional clock */
clk_enable
(
wdev
->
mpu_wdt_ick
);
/* Enable the interface clock */
clk_enable
(
wdev
->
mpu_wdt_fck
);
/* Enable the functional clock */
}
/* initialize prescaler */
while
(
omap_readl
(
OMAP_WATCHDOG_WPS
)
&
0x01
)
while
(
omap_readl
(
base
+
OMAP_WATCHDOG_WPS
)
&
0x01
)
cpu_relax
();
omap_writel
((
1
<<
5
)
|
(
PTV
<<
2
),
OMAP_WATCHDOG_CNTRL
);
while
(
omap_readl
(
OMAP_WATCHDOG_WPS
)
&
0x01
)
omap_writel
((
1
<<
5
)
|
(
PTV
<<
2
),
base
+
OMAP_WATCHDOG_CNTRL
);
while
(
omap_readl
(
base
+
OMAP_WATCHDOG_WPS
)
&
0x01
)
cpu_relax
();
omap_wdt_set_timeout
();
omap_wdt_enable
();
file
->
private_data
=
(
void
*
)
wdev
;
omap_wdt_set_timeout
(
wdev
);
omap_wdt_enable
(
wdev
);
return
0
;
}
static
int
omap_wdt_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
omap_wdt_dev
*
wdev
;
wdev
=
file
->
private_data
;
/*
* Shut off the timer unless NOWAYOUT is defined.
*/
#ifndef CONFIG_WATCHDOG_NOWAYOUT
omap_wdt_disable
();
omap_wdt_disable
(
wdev
);
if
(
cpu_is_omap16xx
())
{
clk_disable
(
armwdt_ck
);
/* Disable the clock */
clk_put
(
armwdt_ck
);
armwdt_ck
=
NULL
;
clk_disable
(
wdev
->
armwdt_ck
);
/* Disable the clock */
clk_put
(
wdev
->
armwdt_ck
);
wdev
->
armwdt_ck
=
NULL
;
}
if
(
cpu_is_omap24xx
())
{
clk_disable
(
mpu_wdt_ick
);
/* Disable the clock */
clk_disable
(
mpu_wdt_fck
);
/* Disable the clock */
clk_put
(
mpu_wdt_ick
);
clk_put
(
mpu_wdt_fck
);
mpu_wdt_ick
=
NULL
;
mpu_wdt_fck
=
NULL
;
clk_disable
(
wdev
->
mpu_wdt_ick
);
/* Disable the clock */
clk_disable
(
wdev
->
mpu_wdt_fck
);
/* Disable the clock */
clk_put
(
wdev
->
mpu_wdt_ick
);
clk_put
(
wdev
->
mpu_wdt_fck
);
wdev
->
mpu_wdt_ick
=
NULL
;
wdev
->
mpu_wdt_fck
=
NULL
;
}
#else
printk
(
KERN_CRIT
"omap_wdt: Unexpected close, not stopping!
\n
"
);
#endif
omap_wdt_users
=
0
;
wdev
->
omap_wdt_users
=
0
;
return
0
;
}
...
...
@@ -179,9 +203,11 @@ static ssize_t
omap_wdt_write
(
struct
file
*
file
,
const
char
__user
*
data
,
size_t
len
,
loff_t
*
ppos
)
{
struct
omap_wdt_dev
*
wdev
;
wdev
=
file
->
private_data
;
/* Refresh LOAD_TIME. */
if
(
len
)
omap_wdt_ping
();
omap_wdt_ping
(
wdev
);
return
len
;
}
...
...
@@ -189,12 +215,14 @@ static int
omap_wdt_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
omap_wdt_dev
*
wdev
;
int
new_margin
;
static
struct
watchdog_info
ident
=
{
.
identity
=
"OMAP Watchdog"
,
.
options
=
WDIOF_SETTIMEOUT
,
.
firmware_version
=
0
,
};
wdev
=
file
->
private_data
;
switch
(
cmd
)
{
default:
...
...
@@ -212,22 +240,23 @@ omap_wdt_ioctl(struct inode *inode, struct file *file,
return
put_user
(
omap_prcm_get_reset_sources
(),
(
int
__user
*
)
arg
);
case
WDIOC_KEEPALIVE
:
omap_wdt_ping
();
omap_wdt_ping
(
wdev
);
return
0
;
case
WDIOC_SETTIMEOUT
:
if
(
get_user
(
new_margin
,
(
int
__user
*
)
arg
))
return
-
EFAULT
;
omap_wdt_adjust_timeout
(
new_margin
);
omap_wdt_disable
();
omap_wdt_set_timeout
();
omap_wdt_enable
();
omap_wdt_disable
(
wdev
);
omap_wdt_set_timeout
(
wdev
);
omap_wdt_enable
(
wdev
);
omap_wdt_ping
();
omap_wdt_ping
(
wdev
);
/* Fall */
case
WDIOC_GETTIMEOUT
:
return
put_user
(
timer_margin
,
(
int
__user
*
)
arg
);
}
return
0
;
}
static
const
struct
file_operations
omap_wdt_fops
=
{
...
...
@@ -238,96 +267,123 @@ static const struct file_operations omap_wdt_fops = {
.
release
=
omap_wdt_release
,
};
static
struct
miscdevice
omap_wdt_miscdev
=
{
.
minor
=
WATCHDOG_MINOR
,
.
name
=
"watchdog"
,
.
fops
=
&
omap_wdt_fops
};
static
int
__init
omap_wdt_probe
(
struct
platform_device
*
pdev
)
{
struct
resource
*
res
,
*
mem
;
int
ret
;
struct
omap_wdt_dev
*
wdev
;
/* reserve static register mappings */
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
if
(
!
res
)
return
-
ENOENT
;
if
(
omap_wdt_dev
)
return
-
EBUSY
;
mem
=
request_mem_region
(
res
->
start
,
res
->
end
-
res
->
start
+
1
,
pdev
->
name
);
if
(
mem
==
NULL
)
return
-
EBUSY
;
platform_set_drvdata
(
pdev
,
mem
);
omap_wdt_users
=
0
;
wdev
=
kzalloc
(
sizeof
(
struct
omap_wdt_dev
),
GFP_KERNEL
);
if
(
!
wdev
)
{
ret
=
-
ENOMEM
;
goto
fail
;
}
wdev
->
omap_wdt_users
=
0
;
wdev
->
mem
=
mem
;
if
(
cpu_is_omap16xx
())
{
armwdt_ck
=
clk_get
(
&
pdev
->
dev
,
"armwdt_ck"
);
if
(
IS_ERR
(
armwdt_ck
))
{
ret
=
PTR_ERR
(
armwdt_ck
);
armwdt_ck
=
NULL
;
wdev
->
armwdt_ck
=
clk_get
(
&
pdev
->
dev
,
"armwdt_ck"
);
if
(
IS_ERR
(
wdev
->
armwdt_ck
))
{
ret
=
PTR_ERR
(
wdev
->
armwdt_ck
);
wdev
->
armwdt_ck
=
NULL
;
goto
fail
;
}
}
if
(
cpu_is_omap24xx
())
{
mpu_wdt_ick
=
clk_get
(
&
pdev
->
dev
,
"mpu_wdt_ick"
);
if
(
IS_ERR
(
mpu_wdt_ick
))
{
ret
=
PTR_ERR
(
mpu_wdt_ick
);
mpu_wdt_ick
=
NULL
;
wdev
->
mpu_wdt_ick
=
clk_get
(
&
pdev
->
dev
,
"mpu_wdt_ick"
);
if
(
IS_ERR
(
wdev
->
mpu_wdt_ick
))
{
ret
=
PTR_ERR
(
wdev
->
mpu_wdt_ick
);
wdev
->
mpu_wdt_ick
=
NULL
;
goto
fail
;
}
mpu_wdt_fck
=
clk_get
(
&
pdev
->
dev
,
"mpu_wdt_fck"
);
if
(
IS_ERR
(
mpu_wdt_fck
))
{
ret
=
PTR_ERR
(
mpu_wdt_fck
);
mpu_wdt_fck
=
NULL
;
wdev
->
mpu_wdt_fck
=
clk_get
(
&
pdev
->
dev
,
"mpu_wdt_fck"
);
if
(
IS_ERR
(
wdev
->
mpu_wdt_fck
))
{
ret
=
PTR_ERR
(
wdev
->
mpu_wdt_fck
);
wdev
->
mpu_wdt_fck
=
NULL
;
goto
fail
;
}
}
wdev
->
base
=
(
void
__iomem
*
)
(
mem
->
start
);
platform_set_drvdata
(
pdev
,
wdev
);
omap_wdt_disable
();
omap_wdt_disable
(
wdev
);
omap_wdt_adjust_timeout
(
timer_margin
);
omap_wdt_miscdev
.
parent
=
&
pdev
->
dev
;
ret
=
misc_register
(
&
omap_wdt_miscdev
);
wdev
->
omap_wdt_miscdev
.
parent
=
&
pdev
->
dev
;
wdev
->
omap_wdt_miscdev
.
minor
=
WATCHDOG_MINOR
;
wdev
->
omap_wdt_miscdev
.
name
=
"watchdog"
;
wdev
->
omap_wdt_miscdev
.
fops
=
&
omap_wdt_fops
;
ret
=
misc_register
(
&
(
wdev
->
omap_wdt_miscdev
));
if
(
ret
)
goto
fail
;
pr_info
(
"OMAP Watchdog Timer: initial timeout %d sec
\n
"
,
timer_margin
);
pr_info
(
"OMAP Watchdog Timer Rev 0x%02x: initial timeout %d sec
\n
"
,
omap_readl
(
wdev
->
base
+
OMAP_WATCHDOG_REV
)
&
0xFF
,
timer_margin
);
/* autogate OCP interface clock */
omap_writel
(
0x01
,
OMAP_WATCHDOG_SYS_CONFIG
);
omap_writel
(
0x01
,
wdev
->
base
+
OMAP_WATCHDOG_SYS_CONFIG
);
omap_wdt_dev
=
pdev
;
return
0
;
fail:
if
(
armwdt_ck
)
clk_put
(
armwdt_ck
);
if
(
mpu_wdt_ick
)
clk_put
(
mpu_wdt_ick
);
if
(
mpu_wdt_fck
)
clk_put
(
mpu_wdt_fck
);
if
(
wdev
)
{
platform_set_drvdata
(
pdev
,
NULL
);
if
(
wdev
->
armwdt_ck
)
clk_put
(
wdev
->
armwdt_ck
);
if
(
wdev
->
mpu_wdt_ick
)
clk_put
(
wdev
->
mpu_wdt_ick
);
if
(
wdev
->
mpu_wdt_fck
)
clk_put
(
wdev
->
mpu_wdt_fck
);
kfree
(
wdev
);
}
if
(
mem
)
{
release_resource
(
mem
);
}
return
ret
;
}
static
void
omap_wdt_shutdown
(
struct
platform_device
*
pdev
)
{
omap_wdt_disable
();
struct
omap_wdt_dev
*
wdev
;
wdev
=
platform_get_drvdata
(
pdev
);
omap_wdt_disable
(
wdev
);
}
static
int
omap_wdt_remove
(
struct
platform_device
*
pdev
)
{
struct
resource
*
mem
=
platform_get_drvdata
(
pdev
);
misc_deregister
(
&
omap_wdt_miscdev
);
release_resource
(
mem
);
if
(
armwdt_ck
)
clk_put
(
armwdt_ck
);
if
(
mpu_wdt_ick
)
clk_put
(
mpu_wdt_ick
);
if
(
mpu_wdt_fck
)
clk_put
(
mpu_wdt_fck
);
struct
omap_wdt_dev
*
wdev
;
wdev
=
platform_get_drvdata
(
pdev
);
misc_deregister
(
&
(
wdev
->
omap_wdt_miscdev
));
release_resource
(
wdev
->
mem
);
platform_set_drvdata
(
pdev
,
NULL
);
if
(
wdev
->
armwdt_ck
)
clk_put
(
wdev
->
armwdt_ck
);
if
(
wdev
->
mpu_wdt_ick
)
clk_put
(
wdev
->
mpu_wdt_ick
);
if
(
wdev
->
mpu_wdt_fck
)
clk_put
(
wdev
->
mpu_wdt_fck
);
kfree
(
wdev
);
omap_wdt_dev
=
NULL
;
return
0
;
}
...
...
@@ -341,16 +397,20 @@ static int omap_wdt_remove(struct platform_device *pdev)
static
int
omap_wdt_suspend
(
struct
platform_device
*
pdev
,
pm_message_t
state
)
{
if
(
omap_wdt_users
)
omap_wdt_disable
();
struct
omap_wdt_dev
*
wdev
;
wdev
=
platform_get_drvdata
(
pdev
);
if
(
wdev
->
omap_wdt_users
)
omap_wdt_disable
(
wdev
);
return
0
;
}
static
int
omap_wdt_resume
(
struct
platform_device
*
pdev
)
{
if
(
omap_wdt_users
)
{
omap_wdt_enable
();
omap_wdt_ping
();
struct
omap_wdt_dev
*
wdev
;
wdev
=
platform_get_drvdata
(
pdev
);
if
(
wdev
->
omap_wdt_users
)
{
omap_wdt_enable
(
wdev
);
omap_wdt_ping
(
wdev
);
}
return
0
;
}
...
...
drivers/char/watchdog/omap_wdt.h
View file @
38310772
...
...
@@ -30,25 +30,15 @@
#ifndef _OMAP_WATCHDOG_H
#define _OMAP_WATCHDOG_H
#define OMAP1610_WATCHDOG_BASE 0xfffeb000
#define OMAP2420_WATCHDOG_BASE 0x48022000
/*WDT Timer 2 */
#ifdef CONFIG_ARCH_OMAP24XX
#define OMAP_WATCHDOG_BASE OMAP2420_WATCHDOG_BASE
#else
#define OMAP_WATCHDOG_BASE OMAP1610_WATCHDOG_BASE
#define RM_RSTST_WKUP 0
#endif
#define OMAP_WATCHDOG_REV (OMAP_WATCHDOG_BASE + 0x00)
#define OMAP_WATCHDOG_SYS_CONFIG (OMAP_WATCHDOG_BASE + 0x10)
#define OMAP_WATCHDOG_STATUS (OMAP_WATCHDOG_BASE + 0x14)
#define OMAP_WATCHDOG_CNTRL (OMAP_WATCHDOG_BASE + 0x24)
#define OMAP_WATCHDOG_CRR (OMAP_WATCHDOG_BASE + 0x28)
#define OMAP_WATCHDOG_LDR (OMAP_WATCHDOG_BASE + 0x2c)
#define OMAP_WATCHDOG_TGR (OMAP_WATCHDOG_BASE + 0x30)
#define OMAP_WATCHDOG_WPS (OMAP_WATCHDOG_BASE + 0x34)
#define OMAP_WATCHDOG_SPR (OMAP_WATCHDOG_BASE + 0x48)
#define OMAP_WATCHDOG_REV (0x00)
#define OMAP_WATCHDOG_SYS_CONFIG (0x10)
#define OMAP_WATCHDOG_STATUS (0x14)
#define OMAP_WATCHDOG_CNTRL (0x24)
#define OMAP_WATCHDOG_CRR (0x28)
#define OMAP_WATCHDOG_LDR (0x2c)
#define OMAP_WATCHDOG_TGR (0x30)
#define OMAP_WATCHDOG_WPS (0x34)
#define OMAP_WATCHDOG_SPR (0x48)
/* Using the prescaler, the OMAP watchdog could go for many
* months before firing. These limits work without scaling,
...
...
drivers/i2c/busses/i2c-omap.c
View file @
38310772
...
...
@@ -2,13 +2,15 @@
* TI OMAP I2C master mode driver
*
* Copyright (C) 2003 MontaVista Software, Inc.
* Copyright (C) 2004 Texas Instruments.
*
* Updated to work with multiple I2C interfaces on 24xx by
* Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
* Copyright (C) 2005 Nokia Corporation
* Copyright (C) 2004 - 2007 Texas Instruments.
*
* Cleaned up by Juha Yrjl <juha.yrjola@nokia.com>
* Originally written by MontaVista Software, Inc.
* Additional contributions by:
* Tony Lindgren <tony@atomide.com>
* Imre Deak <imre.deak@nokia.com>
* Juha Yrjl <juha.yrjola@nokia.com>
* Syed Khasim <x0khasim@ti.com>
*
* 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
...
...
@@ -87,6 +89,7 @@
/* I2C Configuration Register (OMAP_I2C_CON): */
#define OMAP_I2C_CON_EN (1 << 15)
/* I2C module enable */
#define OMAP_I2C_CON_BE (1 << 14)
/* Big endian mode */
#define OMAP_I2C_CON_OPMODE (1 << 12)
/* High Speed support */
#define OMAP_I2C_CON_STB (1 << 11)
/* Start byte mode (master) */
#define OMAP_I2C_CON_MST (1 << 10)
/* Master/slave mode */
#define OMAP_I2C_CON_TRX (1 << 9)
/* TX/RX mode (master only) */
...
...
@@ -95,6 +98,10 @@
#define OMAP_I2C_CON_STP (1 << 1)
/* Stop cond (master only) */
#define OMAP_I2C_CON_STT (1 << 0)
/* Start condition (master) */
/* I2C SCL time value when Master */
#define OMAP_I2C_SCLL_HSSCLL 8
#define OMAP_I2C_SCLH_HSSCLH 8
/* I2C System Test Register (OMAP_I2C_SYSTEST): */
#ifdef DEBUG
#define OMAP_I2C_SYSTEST_ST_EN (1 << 15)
/* System test enable */
...
...
@@ -113,12 +120,6 @@
/* I2C System Configuration Register (OMAP_I2C_SYSC): */
#define OMAP_I2C_SYSC_SRST (1 << 1)
/* Soft Reset */
/* REVISIT: Use platform_data instead of module parameters */
/* Fast Mode = 400 kHz, Standard = 100 kHz */
static
int
clock
=
100
;
/* Default: 100 kHz */
module_param
(
clock
,
int
,
0
);
MODULE_PARM_DESC
(
clock
,
"Set I2C clock in kHz: 400=fast mode (default == 100)"
);
struct
omap_i2c_dev
{
struct
device
*
dev
;
void
__iomem
*
base
;
/* virtual */
...
...
@@ -127,6 +128,7 @@ struct omap_i2c_dev {
struct
clk
*
fclk
;
/* Functional clock */
struct
completion
cmd_complete
;
struct
resource
*
ioarea
;
u32
speed
;
/* Speed of bus in Khz */
u16
cmd_err
;
u8
*
buf
;
size_t
buf_len
;
...
...
@@ -154,7 +156,18 @@ static int omap_i2c_get_clocks(struct omap_i2c_dev *dev)
return
-
ENODEV
;
}
}
/* For I2C operations on 2430 we need 96Mhz clock */
if
(
cpu_is_omap2430
())
{
dev
->
fclk
=
clk_get
(
dev
->
dev
,
"i2chs_fck"
);
if
(
IS_ERR
(
dev
->
fclk
))
{
if
(
dev
->
iclk
!=
NULL
)
{
clk_put
(
dev
->
iclk
);
dev
->
iclk
=
NULL
;
}
dev
->
fclk
=
NULL
;
return
-
ENODEV
;
}
}
else
{
dev
->
fclk
=
clk_get
(
dev
->
dev
,
"i2c_fck"
);
if
(
IS_ERR
(
dev
->
fclk
))
{
if
(
dev
->
iclk
!=
NULL
)
{
...
...
@@ -164,7 +177,7 @@ static int omap_i2c_get_clocks(struct omap_i2c_dev *dev)
dev
->
fclk
=
NULL
;
return
-
ENODEV
;
}
}
return
0
;
}
...
...
@@ -194,9 +207,11 @@ static void omap_i2c_disable_clocks(struct omap_i2c_dev *dev)
static
int
omap_i2c_init
(
struct
omap_i2c_dev
*
dev
)
{
u16
psc
=
0
;
u16
psc
=
0
,
scll
=
0
,
sclh
=
0
;
u16
fsscll
=
0
,
fssclh
=
0
,
hsscll
=
0
,
hssclh
=
0
;
unsigned
long
fclk_rate
=
12000000
;
unsigned
long
timeout
;
unsigned
long
internal_clk
=
0
;
if
(
!
dev
->
rev1
)
{
omap_i2c_write_reg
(
dev
,
OMAP_I2C_SYSC_REG
,
OMAP_I2C_SYSC_SRST
);
...
...
@@ -239,18 +254,47 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
psc
=
fclk_rate
/
12000000
;
}
/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
omap_i2c_write_reg
(
dev
,
OMAP_I2C_PSC_REG
,
psc
);
if
(
cpu_is_omap2430
())
{
/* HSI2C controller internal clk rate should be 19.2 Mhz */
internal_clk
=
19200
;
fclk_rate
=
clk_get_rate
(
dev
->
fclk
)
/
1000
;
/* Compute prescaler divisor */
psc
=
fclk_rate
/
internal_clk
;
psc
=
psc
-
1
;
/* If configured for High Speed */
if
(
dev
->
speed
>
400
)
{
/* For first phase of HS mode */
fsscll
=
internal_clk
/
(
400
*
2
)
-
6
;
fssclh
=
internal_clk
/
(
400
*
2
)
-
6
;
/* For second phase of HS mode */
hsscll
=
fclk_rate
/
(
dev
->
speed
*
2
)
-
6
;
hssclh
=
fclk_rate
/
(
dev
->
speed
*
2
)
-
6
;
}
else
{
/* To handle F/S modes */
fsscll
=
internal_clk
/
(
dev
->
speed
*
2
)
-
6
;
fssclh
=
internal_clk
/
(
dev
->
speed
*
2
)
-
6
;
}
scll
=
(
hsscll
<<
OMAP_I2C_SCLL_HSSCLL
)
|
fsscll
;
sclh
=
(
hssclh
<<
OMAP_I2C_SCLH_HSSCLH
)
|
fssclh
;
}
else
{
/* Program desired operating rate */
fclk_rate
/=
(
psc
+
1
)
*
1000
;
if
(
psc
>
2
)
psc
=
2
;
scll
=
fclk_rate
/
(
dev
->
speed
*
2
)
-
7
+
psc
;
sclh
=
fclk_rate
/
(
dev
->
speed
*
2
)
-
7
+
psc
;
}
/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
omap_i2c_write_reg
(
dev
,
OMAP_I2C_PSC_REG
,
psc
);
omap_i2c_write_reg
(
dev
,
OMAP_I2C_SCLL_REG
,
fclk_rate
/
(
clock
*
2
)
-
7
+
psc
);
omap_i2c_write_reg
(
dev
,
OMAP_I2C_SCLH_REG
,
fclk_rate
/
(
clock
*
2
)
-
7
+
psc
);
/* SCL low and high time values */
omap_i2c_write_reg
(
dev
,
OMAP_I2C_SCLL_REG
,
scll
);
omap_i2c_write_reg
(
dev
,
OMAP_I2C_SCLH_REG
,
sclh
);
/* Take the I2C module out of reset: */
omap_i2c_write_reg
(
dev
,
OMAP_I2C_CON_REG
,
OMAP_I2C_CON_EN
);
...
...
@@ -335,6 +379,11 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
dev
->
cmd_err
=
0
;
w
=
OMAP_I2C_CON_EN
|
OMAP_I2C_CON_MST
|
OMAP_I2C_CON_STT
;
/* High speed configuration */
if
(
dev
->
speed
>
400
)
w
|=
OMAP_I2C_CON_OPMODE
;
if
(
msg
->
flags
&
I2C_M_TEN
)
w
|=
OMAP_I2C_CON_XA
;
if
(
!
(
msg
->
flags
&
I2C_M_RD
))
...
...
@@ -581,6 +630,7 @@ omap_i2c_probe(struct platform_device *pdev)
struct
i2c_adapter
*
adap
;
struct
resource
*
mem
,
*
irq
,
*
ioarea
;
int
r
;
u32
*
speed
=
NULL
;
/* NOTE: driver uses the static register mapping */
mem
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
...
...
@@ -601,17 +651,18 @@ omap_i2c_probe(struct platform_device *pdev)
return
-
EBUSY
;
}
if
(
clock
>
200
)
clock
=
400
;
/* Fast mode */
else
clock
=
100
;
/* Standard mode */
dev
=
kzalloc
(
sizeof
(
struct
omap_i2c_dev
),
GFP_KERNEL
);
if
(
!
dev
)
{
r
=
-
ENOMEM
;
goto
err_release_region
;
}
if
(
pdev
->
dev
.
platform_data
!=
NULL
)
speed
=
(
u32
*
)
pdev
->
dev
.
platform_data
;
else
*
speed
=
100
;
/* Defualt speed */
dev
->
speed
=
*
speed
;
dev
->
dev
=
&
pdev
->
dev
;
dev
->
irq
=
irq
->
start
;
dev
->
base
=
(
void
__iomem
*
)
IO_ADDRESS
(
mem
->
start
);
...
...
@@ -637,7 +688,7 @@ omap_i2c_probe(struct platform_device *pdev)
}
r
=
omap_i2c_read_reg
(
dev
,
OMAP_I2C_REV_REG
)
&
0xff
;
dev_info
(
dev
->
dev
,
"bus %d rev%d.%d at %d kHz
\n
"
,
pdev
->
id
,
r
>>
4
,
r
&
0xf
,
clock
);
pdev
->
id
,
r
>>
4
,
r
&
0xf
,
dev
->
speed
);
adap
=
&
dev
->
adapter
;
i2c_set_adapdata
(
adap
,
dev
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment