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
4da40921
Commit
4da40921
authored
Jan 15, 2006
by
Juha Yrjola
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ARM: OMAP: Clean up the I2C driver
parent
0dad9642
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
282 additions
and
433 deletions
+282
-433
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-omap.c
+282
-319
drivers/i2c/busses/i2c-omap.h
drivers/i2c/busses/i2c-omap.h
+0
-114
No files found.
drivers/i2c/busses/i2c-omap.c
View file @
4da40921
...
@@ -10,13 +10,15 @@
...
@@ -10,13 +10,15 @@
* Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
* Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
* Copyright (C) 2005 Nokia Corporation
* Copyright (C) 2005 Nokia Corporation
*
*
* Cleaned up by Juha Yrjl <juha.yrjola@nokia.com>
*
* ----------------------------------------------------------------------------
* ----------------------------------------------------------------------------
* This file was highly leveraged from i2c-elektor.c:
* This file was highly leveraged from i2c-elektor.c:
*
*
* Copyright 1995-97 Simon G. Vogl
* Copyright 1995-97 Simon G. Vogl
* 1998-99 Hans Berglund
* 1998-99 Hans Berglund
*
*
* With some changes from Kysti M
�
kki <kmalkki@cc.hut.fi> and even
* With some changes from Kysti M
l
kki <kmalkki@cc.hut.fi> and even
* Frodo Looijaard <frodol@dds.nl>
* Frodo Looijaard <frodol@dds.nl>
*
*
* This program is free software; you can redistribute it and/or modify
* This program is free software; you can redistribute it and/or modify
...
@@ -34,11 +36,14 @@
...
@@ -34,11 +36,14 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
*/
// #define DEBUG
#include <linux/module.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
#include <linux/completion.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/io.h>
...
@@ -48,37 +53,34 @@
...
@@ -48,37 +53,34 @@
static
const
char
driver_name
[]
=
"i2c_omap"
;
static
const
char
driver_name
[]
=
"i2c_omap"
;
#define MODULE_NAME "OMAP I2C"
#define MODULE_NAME "OMAP I2C"
#define OMAP_I2C_TIMEOUT (1*HZ)
/* timeout waiting for an I2C transaction */
#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(500))
/* timeout waiting for the controller to respond */
#define pr_err(format, arg...) \
printk(KERN_ERR MODULE_NAME " ERROR: " format "\n", ## arg )
#define DEFAULT_OWN 1
/* default own I2C address */
#define DEFAULT_OWN 1
/* default own I2C address */
#define MAX_MESSAGES 65536
/* max number of messages */
#define MAX_MESSAGES 65536
/* max number of messages */
#define OMAP_I2C_REV 0x00
#define OMAP_I2C_REV
_REG
0x00
#define OMAP_I2C_IE 0x04
#define OMAP_I2C_IE
_REG
0x04
#define OMAP_I2C_STAT 0x08
#define OMAP_I2C_STAT
_REG
0x08
#define OMAP_I2C_IV 0x0c
#define OMAP_I2C_IV
_REG
0x0c
#define OMAP_I2C_SYSS 0x10
#define OMAP_I2C_SYSS
_REG
0x10
#define OMAP_I2C_BUF 0x14
#define OMAP_I2C_BUF
_REG
0x14
#define OMAP_I2C_CNT 0x18
#define OMAP_I2C_CNT
_REG
0x18
#define OMAP_I2C_DATA 0x1c
#define OMAP_I2C_DATA
_REG
0x1c
#define OMAP_I2C_SYSC 0x20
#define OMAP_I2C_SYSC
_REG
0x20
#define OMAP_I2C_CON 0x24
#define OMAP_I2C_CON
_REG
0x24
#define OMAP_I2C_OA 0x28
#define OMAP_I2C_OA
_REG
0x28
#define OMAP_I2C_SA 0x2c
#define OMAP_I2C_SA
_REG
0x2c
#define OMAP_I2C_PSC 0x30
#define OMAP_I2C_PSC
_REG
0x30
#define OMAP_I2C_SCLL 0x34
#define OMAP_I2C_SCLL
_REG
0x34
#define OMAP_I2C_SCLH 0x38
#define OMAP_I2C_SCLH
_REG
0x38
#define OMAP_I2C_SYSTEST 0x3c
#define OMAP_I2C_SYSTEST
_REG
0x3c
/* I2C Interrupt Enable Register (OMAP_I2C_IE): */
/* I2C Interrupt Enable Register (OMAP_I2C_IE): */
#define OMAP_I2C_IE_XRDY
_IE
(1 << 4)
/* TX data ready int enable */
#define OMAP_I2C_IE_XRDY (1 << 4)
/* TX data ready int enable */
#define OMAP_I2C_IE_RRDY
_IE
(1 << 3)
/* RX data ready int enable */
#define OMAP_I2C_IE_RRDY (1 << 3)
/* RX data ready int enable */
#define OMAP_I2C_IE_ARDY
_IE
(1 << 2)
/* Access ready int enable */
#define OMAP_I2C_IE_ARDY (1 << 2)
/* Access ready int enable */
#define OMAP_I2C_IE_NACK
_IE
(1 << 1)
/* No ack interrupt enable */
#define OMAP_I2C_IE_NACK (1 << 1)
/* No ack interrupt enable */
#define OMAP_I2C_IE_AL
_IE
(1 << 0)
/* Arbitration lost int ena */
#define OMAP_I2C_IE_AL
(1 << 0)
/* Arbitration lost int ena */
/* I2C Status Register (OMAP_I2C_STAT): */
/* I2C Status Register (OMAP_I2C_STAT): */
#define OMAP_I2C_STAT_SBD (1 << 15)
/* Single byte data */
#define OMAP_I2C_STAT_SBD (1 << 15)
/* Single byte data */
...
@@ -99,7 +101,6 @@ static const char driver_name[] = "i2c_omap";
...
@@ -99,7 +101,6 @@ static const char driver_name[] = "i2c_omap";
/* I2C Configuration Register (OMAP_I2C_CON): */
/* I2C Configuration Register (OMAP_I2C_CON): */
#define OMAP_I2C_CON_EN (1 << 15)
/* I2C module enable */
#define OMAP_I2C_CON_EN (1 << 15)
/* I2C module enable */
#define OMAP_I2C_CON_RST (0 << 15)
/* I2C module reset */
#define OMAP_I2C_CON_BE (1 << 14)
/* Big endian mode */
#define OMAP_I2C_CON_BE (1 << 14)
/* Big endian mode */
#define OMAP_I2C_CON_STB (1 << 11)
/* Start byte mode (master) */
#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_MST (1 << 10)
/* Master/slave mode */
...
@@ -125,45 +126,14 @@ static const char driver_name[] = "i2c_omap";
...
@@ -125,45 +126,14 @@ static const char driver_name[] = "i2c_omap";
/* I2C System Configuration Register (OMAP_I2C_SYSC): */
/* I2C System Configuration Register (OMAP_I2C_SYSC): */
#define OMAP_I2C_SYSC_SRST (1 << 1)
/* Soft Reset */
#define OMAP_I2C_SYSC_SRST (1 << 1)
/* Soft Reset */
/* ------- debugging ---------------------------------------------------*/
/* REVISIT: Use platform_data instead of module parameters */
#define I2C_OMAP_DEBUG
#ifdef I2c_OMAP_DEBUG
static
int
i2c_debug
;
module_param
(
i2c_debug
,
int
,
0
);
MODULE_PARM_DESC
(
i2c_debug
,
"debug level - 0 off; 1 normal; 2,3 more verbose; "
"9 omap-protocol"
);
#define DEB(level, format, arg...) do { \
if (i2c_debug >= level) \
printk(KERN_DEBUG MODULE_NAME " DEBUG: " format "\n", ## arg); \
} while(0)
#define DEB0(format, arg...) DEB(0, format, arg)
#define DEB1(format, arg...) DEB(1, format, arg)
#define DEB2(format, arg...) DEB(2, format, arg)
#define DEB3(format, arg...) DEB(3, format, arg)
#define DEB9(format, arg...) DEB(9, format, arg)
#else
#define DEB0(fmt, args...)
#define DEB1(fmt, args...)
#define DEB2(fmt, args...)
#define DEB3(fmt, args...)
#define DEB9(fmt, args...)
#endif
static
int
clock
=
100
;
/* Default: Fast Mode = 400 KHz, Standard = 100 KHz */
static
int
clock
=
100
;
/* Default: Fast Mode = 400 KHz, Standard = 100 KHz */
module_param
(
clock
,
int
,
0
);
module_param
(
clock
,
int
,
0
);
MODULE_PARM_DESC
(
clock
,
"Set I2C clock in
K
Hz: 100 or 400 (Fast Mode)"
);
MODULE_PARM_DESC
(
clock
,
"Set I2C clock in
k
Hz: 100 or 400 (Fast Mode)"
);
static
int
own
;
static
int
own
;
module_param
(
own
,
int
,
0
);
module_param
(
own
,
int
,
0
);
MODULE_PARM_DESC
(
own
,
"Address of OMAP
i2c
master (0 for default == 1)"
);
MODULE_PARM_DESC
(
own
,
"Address of OMAP
I2C
master (0 for default == 1)"
);
struct
omap_i2c_dev
{
struct
omap_i2c_dev
{
struct
device
*
dev
;
struct
device
*
dev
;
...
@@ -171,40 +141,88 @@ struct omap_i2c_dev {
...
@@ -171,40 +141,88 @@ struct omap_i2c_dev {
int
irq
;
int
irq
;
struct
clk
*
iclk
;
/* Interface clock */
struct
clk
*
iclk
;
/* Interface clock */
struct
clk
*
fclk
;
/* Functional clock */
struct
clk
*
fclk
;
/* Functional clock */
int
cmd_complete
,
cmd_err
;
struct
completion
cmd_complete
;
wait_queue_head_t
cmd_wait
;
u16
cmd_err
;
u8
*
buf
;
u8
*
buf
;
size_t
buf_len
;
size_t
buf_len
;
struct
i2c_adapter
adapter
;
struct
i2c_adapter
adapter
;
int
rev1
;
unsigned
rev1
:
1
;
u8
own_address
;
};
};
static
void
inline
omap_i2c_write
(
struct
omap_i2c_dev
*
i2c_dev
,
static
inline
void
omap_i2c_write_reg
(
struct
omap_i2c_dev
*
i2c_dev
,
int
val
,
int
reg
)
int
reg
,
u16
val
)
{
{
__raw_writew
(
val
,
i2c_dev
->
base
+
reg
);
__raw_writew
(
val
,
i2c_dev
->
base
+
reg
);
}
}
static
in
t
inline
omap_i2c_read
(
struct
omap_i2c_dev
*
i2c_dev
,
int
reg
)
static
in
line
u16
omap_i2c_read_reg
(
struct
omap_i2c_dev
*
i2c_dev
,
int
reg
)
{
{
return
__raw_readw
(
i2c_dev
->
base
+
reg
);
return
__raw_readw
(
i2c_dev
->
base
+
reg
);
}
}
static
void
omap_i2c_reset
(
struct
omap_i2c_dev
*
omap_i2c_dev
)
#ifdef CONFIG_ARCH_OMAP24XX
static
int
omap_i2c_get_clocks
(
struct
omap_i2c_dev
*
dev
,
int
bus
)
{
{
unsigned
long
timeout
;
if
(
!
cpu_is_omap24xx
())
u16
psc
=
0
;
return
0
;
unsigned
long
fclk_rate
;
/* Soft reset, hard reset needed only for rev1 */
dev
->
iclk
=
clk_get
(
NULL
,
if
(
!
omap_i2c_dev
->
rev1
)
bus
==
1
?
"i2c1_ick"
:
"i2c2_ick"
);
omap_i2c_write
(
omap_i2c_dev
,
OMAP_I2C_SYSC_SRST
,
OMAP_I2C_SYSC
);
if
(
IS_ERR
(
dev
->
iclk
))
{
else
return
-
ENODEV
;
omap_i2c_write
(
omap_i2c_dev
,
OMAP_I2C_CON_RST
,
OMAP_I2C_CON
);
}
dev
->
fclk
=
clk_get
(
NULL
,
bus
==
1
?
"i2c1_fck"
:
"i2c2_fck"
);
if
(
IS_ERR
(
dev
->
fclk
))
{
clk_put
(
dev
->
fclk
);
return
-
ENODEV
;
}
return
0
;
}
static
void
omap_i2c_put_clocks
(
struct
omap_i2c_dev
*
dev
)
{
clk_put
(
dev
->
fclk
);
clk_put
(
dev
->
iclk
);
}
static
void
omap_i2c_enable_clocks
(
struct
omap_i2c_dev
*
dev
)
{
clk_enable
(
dev
->
iclk
);
clk_enable
(
dev
->
fclk
);
}
static
void
omap_i2c_disable_clocks
(
struct
omap_i2c_dev
*
dev
)
{
clk_disable
(
dev
->
iclk
);
clk_disable
(
dev
->
fclk
);
}
fclk_rate
=
12000000
;
#else
#define omap_i2c_get_clocks(x, y) 0
#define omap_i2c_enable_clocks(x, y) do {} while (0)
#define omap_i2c_disable_clocks(x, y) do {} while (0)
#define omap_i2c_put_clocks(x) do {} while (0)
#endif
static
void
omap_i2c_reset
(
struct
omap_i2c_dev
*
dev
)
{
u16
psc
;
unsigned
long
fclk_rate
;
if
(
!
dev
->
rev1
)
{
omap_i2c_write_reg
(
dev
,
OMAP_I2C_SYSC_REG
,
OMAP_I2C_SYSC_SRST
);
/* For some reason we need to set the EN bit before the
* reset done bit gets set. */
omap_i2c_write_reg
(
dev
,
OMAP_I2C_CON_REG
,
OMAP_I2C_CON_EN
);
while
(
!
(
omap_i2c_read_reg
(
dev
,
OMAP_I2C_SYSS_REG
)
&
0x01
));
}
omap_i2c_write_reg
(
dev
,
OMAP_I2C_CON_REG
,
0
);
if
(
!
cpu_is_omap24xx
())
{
if
(
cpu_class_is_omap1
())
{
struct
clk
*
armxor_ck
;
struct
clk
*
armxor_ck
;
unsigned
long
armxor_rate
;
unsigned
long
armxor_rate
;
...
@@ -219,64 +237,55 @@ static void omap_i2c_reset(struct omap_i2c_dev *omap_i2c_dev)
...
@@ -219,64 +237,55 @@ static void omap_i2c_reset(struct omap_i2c_dev *omap_i2c_dev)
if
(
armxor_rate
>
16000000
)
if
(
armxor_rate
>
16000000
)
psc
=
(
armxor_rate
+
8000000
)
/
12000000
;
psc
=
(
armxor_rate
+
8000000
)
/
12000000
;
else
psc
=
0
;
fclk_rate
=
armxor_rate
;
fclk_rate
=
armxor_rate
;
}
else
if
(
cpu_class_is_omap2
())
{
fclk_rate
=
12000000
;
psc
=
0
;
}
}
/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
omap_i2c_write
(
omap_i2c_dev
,
psc
,
OMAP_I2C_PSC
);
omap_i2c_write
_reg
(
dev
,
OMAP_I2C_PSC_REG
,
psc
);
/* Program desired operating rate */
/* Program desired operating rate */
fclk_rate
/=
(
psc
+
1
)
*
1000
;
fclk_rate
/=
(
psc
+
1
)
*
1000
;
if
(
psc
>
2
)
if
(
psc
>
2
)
psc
=
2
;
psc
=
2
;
omap_i2c_write
(
omap_i2c_dev
,
fclk_rate
/
(
clock
*
2
)
-
7
+
psc
,
OMAP_I2C_SCLL
);
omap_i2c_write
(
omap_i2c_dev
,
fclk_rate
/
(
clock
*
2
)
-
7
+
psc
,
OMAP_I2C_SCLH
);
/* Set Own Address: */
omap_i2c_write_reg
(
dev
,
OMAP_I2C_SCLL_REG
,
omap_i2c_write
(
omap_i2c_dev
,
own
,
OMAP_I2C_OA
);
fclk_rate
/
(
clock
*
2
)
-
7
+
psc
);
omap_i2c_write_reg
(
dev
,
OMAP_I2C_SCLH_REG
,
fclk_rate
/
(
clock
*
2
)
-
7
+
psc
);
/* Enable interrupts */
/* Set Own Address: */
omap_i2c_write
(
omap_i2c_dev
,
omap_i2c_write_reg
(
dev
,
OMAP_I2C_OA_REG
,
dev
->
own_address
);
(
OMAP_I2C_IE_XRDY_IE
|
OMAP_I2C_IE_RRDY_IE
|
OMAP_I2C_IE_ARDY_IE
|
OMAP_I2C_IE_NACK_IE
|
OMAP_I2C_IE_AL_IE
),
OMAP_I2C_IE
);
/* Take the I2C module out of reset: */
/* Take the I2C module out of reset: */
omap_i2c_write
(
omap_i2c_dev
,
OMAP_I2C_CON_EN
,
OMAP_I2C_CON
);
omap_i2c_write_reg
(
dev
,
OMAP_I2C_CON_REG
,
OMAP_I2C_CON_EN
);
if
(
!
omap_i2c_dev
->
rev1
){
/* Enable interrupts */
timeout
=
jiffies
+
OMAP_I2C_TIMEOUT
;
omap_i2c_write_reg
(
dev
,
OMAP_I2C_IE_REG
,
while
(
!
(
omap_i2c_read
(
omap_i2c_dev
,
OMAP_I2C_SYSS
)
&
(
OMAP_I2C_IE_XRDY
|
OMAP_I2C_IE_RRDY
|
OMAP_I2C_SYSS_RDONE
))
{
OMAP_I2C_IE_ARDY
|
OMAP_I2C_IE_NACK
|
if
(
time_after
(
jiffies
,
timeout
))
{
OMAP_I2C_IE_AL
));
pr_err
(
"timeout waiting for I2C reset"
);
break
;
}
msleep
(
1
);
}
}
}
}
/*
/*
* Waiting on Bus Busy
* Waiting on Bus Busy
*/
*/
static
int
static
int
omap_i2c_wait_for_bb
(
struct
omap_i2c_dev
*
dev
)
omap_i2c_wait_for_bb
(
struct
omap_i2c_dev
*
omap_i2c_dev
,
char
allow_sleep
)
{
{
unsigned
long
timeout
;
unsigned
long
timeout
;
timeout
=
jiffies
+
OMAP_I2C_TIMEOUT
;
timeout
=
jiffies
+
OMAP_I2C_TIMEOUT
;
while
(
omap_i2c_read
(
omap_i2c_dev
,
OMAP_I2C_STAT
)
&
OMAP_I2C_STAT_BB
)
{
while
(
omap_i2c_read
_reg
(
dev
,
OMAP_I2C_STAT_REG
)
&
OMAP_I2C_STAT_BB
)
{
if
(
time_after
(
jiffies
,
timeout
))
{
if
(
time_after
(
jiffies
,
timeout
))
{
printk
(
KERN_WARNING
"timeout waiting for bus ready
\n
"
);
dev_warn
(
dev
->
dev
,
"timeout waiting for bus ready
\n
"
);
return
-
ETIMEDOUT
;
return
-
ETIMEDOUT
;
}
}
if
(
allow_sleep
)
msleep
(
1
);
msleep
(
1
);
}
}
return
0
;
return
0
;
...
@@ -285,18 +294,18 @@ omap_i2c_wait_for_bb(struct omap_i2c_dev *omap_i2c_dev, char allow_sleep)
...
@@ -285,18 +294,18 @@ omap_i2c_wait_for_bb(struct omap_i2c_dev *omap_i2c_dev, char allow_sleep)
/*
/*
* Low level master read/write transaction.
* Low level master read/write transaction.
*/
*/
static
int
static
int
omap_i2c_xfer_msg
(
struct
i2c_adapter
*
adap
,
omap_i2c_xfer_msg
(
struct
i2c_adapter
*
adap
,
struct
i2c_msg
*
msg
,
int
stop
)
struct
i2c_msg
*
msg
,
int
stop
)
{
{
struct
omap_i2c_dev
*
omap_i2c_dev
=
i2c_get_adapdata
(
adap
);
struct
omap_i2c_dev
*
dev
=
i2c_get_adapdata
(
adap
);
u8
zero_byte
=
0
;
int
r
;
int
r
;
u16
w
;
u16
w
;
u8
zero_byte
=
0
;
DEB2
(
"addr: 0x%04x, len: %d, flags: 0x%x, stop: %d
\n
"
,
dev_dbg
(
dev
->
dev
,
"addr: 0x%04x, len: %d, flags: 0x%x, stop: %d
\n
"
,
msg
->
addr
,
msg
->
len
,
msg
->
flags
,
stop
);
msg
->
addr
,
msg
->
len
,
msg
->
flags
,
stop
);
omap_i2c_write
(
omap_i2c_dev
,
msg
->
addr
,
OMAP_I2C_SA
);
omap_i2c_write
_reg
(
dev
,
OMAP_I2C_SA_REG
,
msg
->
addr
);
/* Sigh, seems we can't do zero length transactions. Thus, we
/* Sigh, seems we can't do zero length transactions. Thus, we
* can't probe for devices w/o actually sending/receiving at least
* can't probe for devices w/o actually sending/receiving at least
...
@@ -305,16 +314,19 @@ omap_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
...
@@ -305,16 +314,19 @@ omap_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
* arbitrary device due to random byte write/read during
* arbitrary device due to random byte write/read during
* probes.
* probes.
*/
*/
/* REVISIT: Could the STB bit of I2C_CON be used with probing? */
if
(
msg
->
len
==
0
)
{
if
(
msg
->
len
==
0
)
{
omap_i2c_
dev
->
buf
=
&
zero_byte
;
dev
->
buf
=
&
zero_byte
;
omap_i2c_
dev
->
buf_len
=
1
;
dev
->
buf_len
=
1
;
}
else
{
}
else
{
omap_i2c_
dev
->
buf
=
msg
->
buf
;
dev
->
buf
=
msg
->
buf
;
omap_i2c_
dev
->
buf_len
=
msg
->
len
;
dev
->
buf_len
=
msg
->
len
;
}
}
omap_i2c_write
(
omap_i2c_dev
,
omap_i2c_dev
->
buf_len
,
OMAP_I2C_CNT
);
omap_i2c_write_reg
(
dev
,
OMAP_I2C_CNT_REG
,
dev
->
buf_len
);
omap_i2c_dev
->
cmd_complete
=
0
;
omap_i2c_dev
->
cmd_err
=
0
;
init_completion
(
&
dev
->
cmd_complete
);
dev
->
cmd_err
=
0
;
w
=
OMAP_I2C_CON_EN
|
OMAP_I2C_CON_MST
|
OMAP_I2C_CON_STT
;
w
=
OMAP_I2C_CON_EN
|
OMAP_I2C_CON_MST
|
OMAP_I2C_CON_STT
;
if
(
msg
->
flags
&
I2C_M_TEN
)
if
(
msg
->
flags
&
I2C_M_TEN
)
w
|=
OMAP_I2C_CON_XA
;
w
|=
OMAP_I2C_CON_XA
;
...
@@ -322,41 +334,42 @@ omap_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
...
@@ -322,41 +334,42 @@ omap_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
w
|=
OMAP_I2C_CON_TRX
;
w
|=
OMAP_I2C_CON_TRX
;
if
(
stop
)
if
(
stop
)
w
|=
OMAP_I2C_CON_STP
;
w
|=
OMAP_I2C_CON_STP
;
omap_i2c_write
(
omap_i2c_dev
,
w
,
OMAP_I2C_CON
);
omap_i2c_write_reg
(
dev
,
OMAP_I2C_CON_REG
,
w
);
r
=
wait_event_interruptible_timeout
(
omap_i2c_dev
->
cmd_wait
,
omap_i2c_dev
->
cmd_complete
,
OMAP_I2C_TIMEOUT
);
omap_i2c_dev
->
buf_len
=
0
;
r
=
wait_for_completion_interruptible_timeout
(
&
dev
->
cmd_complete
,
OMAP_I2C_TIMEOUT
);
dev
->
buf_len
=
0
;
if
(
r
<
0
)
if
(
r
<
0
)
return
r
;
return
r
;
if
(
!
omap_i2c_dev
->
cmd_complete
)
{
if
(
r
==
0
)
{
omap_i2c_reset
(
omap_i2c_dev
);
dev_err
(
dev
->
dev
,
"controller timed out
\n
"
);
omap_i2c_reset
(
dev
);
return
-
ETIMEDOUT
;
return
-
ETIMEDOUT
;
}
}
if
(
!
omap_i2c_dev
->
cmd_err
)
return
msg
->
len
;
if
(
likely
(
!
dev
->
cmd_err
))
return
0
;
/* We have an error */
/* We have an error */
if
(
omap_i2c_
dev
->
cmd_err
&
OMAP_I2C_STAT_NACK
)
{
if
(
dev
->
cmd_err
&
OMAP_I2C_STAT_NACK
)
{
if
(
msg
->
flags
&
I2C_M_IGNORE_NAK
)
if
(
msg
->
flags
&
I2C_M_IGNORE_NAK
)
return
msg
->
len
;
return
0
;
if
(
stop
)
if
(
stop
)
{
omap_i2c_write
(
omap_i2c_dev
,
u16
w
;
omap_i2c_read
(
omap_i2c_dev
,
OMAP_I2C_CON
)
|
OMAP_I2C_CON_STP
,
w
=
omap_i2c_read_reg
(
dev
,
OMAP_I2C_CON_REG
);
OMAP_I2C_CON
);
w
|=
OMAP_I2C_CON_STP
;
omap_i2c_write_reg
(
dev
,
OMAP_I2C_CON_REG
,
w
);
}
return
-
EREMOTEIO
;
return
-
EREMOTEIO
;
}
}
if
((
OMAP_I2C_STAT_AL
|
OMAP_I2C_STAT_ROVR
|
OMAP_I2C_STAT_XUDF
)
if
(
dev
->
cmd_err
&
(
OMAP_I2C_STAT_AL
|
OMAP_I2C_STAT_ROVR
|
&
omap_i2c_dev
->
cmd_err
)
{
OMAP_I2C_STAT_XUDF
))
omap_i2c_reset
(
omap_i2c_dev
);
omap_i2c_reset
(
dev
);
return
-
EIO
;
return
-
EIO
;
}
return
msg
->
len
;
}
}
/*
/*
* Prepare controller for a transaction and call omap_i2c_xfer_msg
* Prepare controller for a transaction and call omap_i2c_xfer_msg
* to do the work during IRQ processing.
* to do the work during IRQ processing.
...
@@ -364,12 +377,10 @@ omap_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
...
@@ -364,12 +377,10 @@ omap_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
static
int
static
int
omap_i2c_xfer
(
struct
i2c_adapter
*
adap
,
struct
i2c_msg
msgs
[],
int
num
)
omap_i2c_xfer
(
struct
i2c_adapter
*
adap
,
struct
i2c_msg
msgs
[],
int
num
)
{
{
struct
omap_i2c_dev
*
omap_i2c_
dev
=
i2c_get_adapdata
(
adap
);
struct
omap_i2c_dev
*
dev
=
i2c_get_adapdata
(
adap
);
int
i
;
int
i
;
int
r
=
0
;
int
r
=
0
;
DEB1
(
"msgs: %d
\n
"
,
num
);
if
(
num
<
1
||
num
>
MAX_MESSAGES
)
if
(
num
<
1
||
num
>
MAX_MESSAGES
)
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -378,28 +389,24 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
...
@@ -378,28 +389,24 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
if
(
msgs
[
i
].
buf
==
NULL
)
if
(
msgs
[
i
].
buf
==
NULL
)
return
-
EINVAL
;
return
-
EINVAL
;
// REVISIT: initialize and use adap->retries
omap_i2c_enable_clocks
(
dev
);
if
((
r
=
omap_i2c_wait_for_bb
(
omap_i2c_dev
,
1
))
<
0
)
/* REVISIT: initialize and use adap->retries */
return
r
;
if
((
r
=
omap_i2c_wait_for_bb
(
dev
))
<
0
)
goto
out
;
for
(
i
=
0
;
i
<
num
;
i
++
)
{
for
(
i
=
0
;
i
<
num
;
i
++
)
{
DEB2
(
"msg: %d, addr: 0x%04x, len: %d, flags: 0x%x
\n
"
,
dev_dbg
(
dev
->
dev
,
"msg: %d, addr: 0x%04x, len: %d, flags: 0x%x
\n
"
,
i
,
msgs
[
i
].
addr
,
msgs
[
i
].
len
,
msgs
[
i
].
flags
);
i
,
msgs
[
i
].
addr
,
msgs
[
i
].
len
,
msgs
[
i
].
flags
);
r
=
omap_i2c_xfer_msg
(
adap
,
&
msgs
[
i
],
(
i
==
(
num
-
1
)));
r
=
omap_i2c_xfer_msg
(
adap
,
&
msgs
[
i
],
(
i
==
(
num
-
1
)));
if
(
r
!=
0
)
DEB2
(
"r: %d
\n
"
,
r
);
if
(
r
!=
msgs
[
i
].
len
)
break
;
break
;
}
}
if
(
r
>
=
0
&&
num
>
1
)
if
(
r
=
=
0
&&
num
>
1
)
r
=
num
;
r
=
num
;
out:
DEB2
(
"r: %d
\n
"
,
r
);
omap_i2c_disable_clocks
(
dev
);
return
r
;
return
r
;
}
}
...
@@ -410,109 +417,112 @@ omap_i2c_func(struct i2c_adapter *adap)
...
@@ -410,109 +417,112 @@ omap_i2c_func(struct i2c_adapter *adap)
}
}
static
inline
void
static
inline
void
omap_i2c_complete_cmd
(
struct
omap_i2c_dev
*
dev
)
omap_i2c_complete_cmd
(
struct
omap_i2c_dev
*
dev
,
u16
err
)
{
dev
->
cmd_err
|=
err
;
complete
(
&
dev
->
cmd_complete
);
}
static
inline
void
omap_i2c_ack_stat
(
struct
omap_i2c_dev
*
dev
,
u16
stat
)
{
{
dev
->
cmd_complete
=
1
;
omap_i2c_write_reg
(
dev
,
OMAP_I2C_STAT_REG
,
stat
);
wake_up
(
&
dev
->
cmd_wait
);
}
}
static
irqreturn_t
static
irqreturn_t
omap_i2c_isr
(
int
this_irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
omap_i2c_isr
(
int
this_irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
{
struct
omap_i2c_dev
*
omap_i2c_
dev
=
dev_id
;
struct
omap_i2c_dev
*
dev
=
dev_id
;
u16
bits
;
u16
bits
;
u16
stat
,
w
;
u16
stat
,
w
;
int
count
=
0
;
int
count
=
0
;
u16
iv_read
;
u16
iv_read
;
bits
=
omap_i2c_read
(
omap_i2c_dev
,
OMAP_I2C_IE
);
bits
=
omap_i2c_read
_reg
(
dev
,
OMAP_I2C_IE_REG
);
while
((
stat
=
omap_i2c_read
(
omap_i2c_dev
,
OMAP_I2C_STAT
))
&
bits
)
{
while
((
stat
=
(
omap_i2c_read_reg
(
dev
,
OMAP_I2C_STAT_REG
)
))
&
bits
)
{
dev_dbg
(
dev
->
dev
,
"IRQ (ISR = 0x%04x)
\n
"
,
stat
);
if
(
count
++
==
100
)
{
if
(
count
++
==
100
)
{
printk
(
KERN_WARNING
"Too much work in one IRQ
\n
"
);
dev_warn
(
dev
->
dev
,
"Too much work in one IRQ
\n
"
);
break
;
break
;
}
}
omap_i2c_write
(
omap_i2c_dev
,
stat
,
OMAP_I2C_STAT
);
omap_i2c_write_reg
(
dev
,
OMAP_I2C_STAT_REG
,
stat
);
if
(
stat
&
OMAP_I2C_STAT_ARDY
)
{
if
(
stat
&
OMAP_I2C_STAT_ARDY
)
{
omap_i2c_complete_cmd
(
omap_i2c_dev
);
omap_i2c_complete_cmd
(
dev
,
0
);
omap_i2c_write
(
omap_i2c_dev
,
OMAP_I2C_STAT_ARDY
,
if
(
dev
->
rev1
)
OMAP_I2C_STAT
);
iv_read
=
omap_i2c_read_reg
(
dev
,
OMAP_I2C_IV_REG
);
if
(
omap_i2c_dev
->
rev1
)
iv_read
=
omap_i2c_read
(
omap_i2c_dev
,
OMAP_I2C_IV
);
continue
;
continue
;
}
}
if
(
stat
&
OMAP_I2C_STAT_RRDY
)
{
if
(
stat
&
OMAP_I2C_STAT_RRDY
)
{
w
=
omap_i2c_read
(
omap_i2c_dev
,
OMAP_I2C_DATA
);
w
=
omap_i2c_read
_reg
(
dev
,
OMAP_I2C_DATA_REG
);
if
(
omap_i2c_
dev
->
buf_len
)
{
if
(
dev
->
buf_len
)
{
*
omap_i2c_
dev
->
buf
++
=
w
;
*
dev
->
buf
++
=
w
;
omap_i2c_
dev
->
buf_len
--
;
dev
->
buf_len
--
;
if
(
omap_i2c_
dev
->
buf_len
)
{
if
(
dev
->
buf_len
)
{
*
omap_i2c_
dev
->
buf
++
=
w
>>
8
;
*
dev
->
buf
++
=
w
>>
8
;
omap_i2c_
dev
->
buf_len
--
;
dev
->
buf_len
--
;
}
}
if
(
omap_i2c_dev
->
rev1
&&
if
(
dev
->
rev1
&&
!
dev
->
buf_len
)
!
omap_i2c_dev
->
buf_len
)
omap_i2c_complete_cmd
(
dev
,
0
);
omap_i2c_complete_cmd
(
omap_i2c_dev
);
}
else
}
else
pr_err
(
"RRDY IRQ while no data requested"
);
dev_err
(
dev
->
dev
,
"RRDY IRQ while no data requested
\n
"
);
omap_i2c_write
(
omap_i2c_dev
,
OMAP_I2C_STAT_RRDY
,
omap_i2c_ack_stat
(
dev
,
OMAP_I2C_STAT_RRDY
);
OMAP_I2C_STAT
);
if
(
dev
->
rev1
)
if
(
omap_i2c_dev
->
rev1
)
iv_read
=
omap_i2c_read_reg
(
dev
,
OMAP_I2C_IV_REG
);
iv_read
=
omap_i2c_read
(
omap_i2c_dev
,
OMAP_I2C_IV
);
continue
;
continue
;
}
}
if
(
stat
&
OMAP_I2C_STAT_XRDY
)
{
if
(
stat
&
OMAP_I2C_STAT_XRDY
)
{
int
bail_out
=
0
;
w
=
0
;
w
=
0
;
if
(
omap_i2c_
dev
->
buf_len
)
{
if
(
dev
->
buf_len
)
{
w
=
*
omap_i2c_
dev
->
buf
++
;
w
=
*
dev
->
buf
++
;
omap_i2c_
dev
->
buf_len
--
;
dev
->
buf_len
--
;
if
(
omap_i2c_
dev
->
buf_len
)
{
if
(
dev
->
buf_len
)
{
w
|=
*
omap_i2c_
dev
->
buf
++
<<
8
;
w
|=
*
dev
->
buf
++
<<
8
;
omap_i2c_
dev
->
buf_len
--
;
dev
->
buf_len
--
;
}
}
}
else
{
}
else
pr_err
(
"XRDY IRQ while no data to send"
);
dev_err
(
dev
->
dev
,
"XRDY IRQ while no data to send
\n
"
);
/* FIXME: shouldn't we bail out here? */
#if 0
if (!(stat & OMAP_I2C_STAT_BB)) {
dev_warn(dev->dev, "XRDY while bus not busy\n");
bail_out = 1;
}
}
omap_i2c_write
(
omap_i2c_dev
,
w
,
OMAP_I2C_DATA
);
#endif
/* We have to make sure the XRDY bit is reset */
omap_i2c_write_reg
(
dev
,
OMAP_I2C_DATA_REG
,
w
);
omap_i2c_write
(
omap_i2c_dev
,
OMAP_I2C_STAT_XRDY
,
omap_i2c_ack_stat
(
dev
,
OMAP_I2C_STAT_XRDY
);
OMAP_I2C_STAT
);
if
(
dev
->
rev1
)
{
if
(
omap_i2c_dev
->
rev1
)
{
iv_read
=
omap_i2c_read_reg
(
dev
,
OMAP_I2C_IV_REG
);
iv_read
=
omap_i2c_read
(
omap_i2c_dev
,
if
(
!
dev
->
buf_len
)
OMAP_I2C_IV
);
omap_i2c_complete_cmd
(
dev
,
0
);
if
(
!
omap_i2c_dev
->
buf_len
)
omap_i2c_complete_cmd
(
omap_i2c_dev
);
}
}
if
(
bail_out
)
omap_i2c_complete_cmd
(
dev
,
1
<<
15
);
continue
;
continue
;
}
}
if
(
stat
&
OMAP_I2C_STAT_ROVR
)
{
if
(
stat
&
OMAP_I2C_STAT_ROVR
)
{
pr_err
(
"Receive overrun
\n
"
);
dev_err
(
dev
->
dev
,
"Receive overrun
\n
"
);
omap_i2c_
dev
->
cmd_err
|=
OMAP_I2C_STAT_ROVR
;
dev
->
cmd_err
|=
OMAP_I2C_STAT_ROVR
;
}
}
if
(
stat
&
OMAP_I2C_STAT_XUDF
)
{
if
(
stat
&
OMAP_I2C_STAT_XUDF
)
{
pr_err
(
"Transmit overflow
\n
"
);
dev_err
(
dev
->
dev
,
"Transmit overflow
\n
"
);
omap_i2c_
dev
->
cmd_err
|=
OMAP_I2C_STAT_XUDF
;
dev
->
cmd_err
|=
OMAP_I2C_STAT_XUDF
;
}
}
if
(
stat
&
OMAP_I2C_STAT_NACK
)
{
if
(
stat
&
OMAP_I2C_STAT_NACK
)
{
omap_i2c_dev
->
cmd_err
|=
OMAP_I2C_STAT_NACK
;
omap_i2c_complete_cmd
(
dev
,
OMAP_I2C_STAT_NACK
);
omap_i2c_complete_cmd
(
omap_i2c_dev
);
omap_i2c_write_reg
(
dev
,
OMAP_I2C_CON_REG
,
OMAP_I2C_CON_STP
);
omap_i2c_write
(
omap_i2c_dev
,
OMAP_I2C_CON_STP
,
OMAP_I2C_CON
);
}
}
if
(
stat
&
OMAP_I2C_STAT_AL
)
{
if
(
stat
&
OMAP_I2C_STAT_AL
)
{
pr_err
(
"Arbitration lost
\n
"
);
dev_err
(
dev
->
dev
,
"Arbitration lost
\n
"
);
omap_i2c_dev
->
cmd_err
|=
OMAP_I2C_STAT_AL
;
omap_i2c_complete_cmd
(
dev
,
OMAP_I2C_STAT_AL
);
omap_i2c_complete_cmd
(
omap_i2c_dev
);
}
}
if
(
omap_i2c_dev
->
rev1
)
if
(
dev
->
rev1
)
iv_read
=
omap_i2c_read
(
omap_i2c_dev
,
OMAP_I2C_IV
);
iv_read
=
omap_i2c_read_reg
(
dev
,
OMAP_I2C_IV_REG
);
}
}
return
IRQ_HANDLED
;
return
count
?
IRQ_HANDLED
:
IRQ_NONE
;
}
}
static
struct
i2c_algorithm
omap_i2c_algo
=
{
static
struct
i2c_algorithm
omap_i2c_algo
=
{
...
@@ -520,60 +530,10 @@ static struct i2c_algorithm omap_i2c_algo = {
...
@@ -520,60 +530,10 @@ static struct i2c_algorithm omap_i2c_algo = {
.
functionality
=
omap_i2c_func
,
.
functionality
=
omap_i2c_func
,
};
};
#ifdef CONFIG_ARCH_OMAP24XX
static
int
omap_i2c_24xx_get_clocks
(
struct
omap_i2c_dev
*
omap_i2c_dev
,
int
bus
)
{
if
(
!
cpu_is_omap24xx
())
return
0
;
omap_i2c_dev
->
iclk
=
clk_get
(
NULL
,
bus
==
1
?
"i2c1_ick"
:
"i2c2_ick"
);
if
(
IS_ERR
(
omap_i2c_dev
->
iclk
))
{
return
-
ENODEV
;
}
omap_i2c_dev
->
fclk
=
clk_get
(
NULL
,
bus
==
1
?
"i2c1_fck"
:
"i2c2_fck"
);
if
(
IS_ERR
(
omap_i2c_dev
->
fclk
))
{
clk_put
(
omap_i2c_dev
->
fclk
);
return
-
ENODEV
;
}
return
0
;
}
static
void
omap_i2c_24xx_put_clocks
(
struct
omap_i2c_dev
*
omap_i2c_dev
)
{
if
(
cpu_is_omap24xx
())
{
clk_put
(
omap_i2c_dev
->
fclk
);
clk_put
(
omap_i2c_dev
->
iclk
);
}
}
static
void
omap_i2c_24xx_enable_clocks
(
struct
omap_i2c_dev
*
omap_i2c_dev
,
int
enable
)
{
if
(
cpu_is_omap24xx
())
{
if
(
enable
)
{
clk_enable
(
omap_i2c_dev
->
iclk
);
clk_enable
(
omap_i2c_dev
->
fclk
);
}
else
{
clk_disable
(
omap_i2c_dev
->
iclk
);
clk_disable
(
omap_i2c_dev
->
fclk
);
}
}
}
#else
#define omap_i2c_24xx_get_clocks(x, y) 0
#define omap_i2c_24xx_enable_clocks(x, y) do {} while (0)
#define omap_i2c_24xx_put_clocks(x) do {} while (0)
#endif
static
int
static
int
omap_i2c_probe
(
struct
platform_device
*
pdev
)
omap_i2c_probe
(
struct
platform_device
*
pdev
)
{
{
struct
omap_i2c_dev
*
omap_i2c_
dev
;
struct
omap_i2c_dev
*
dev
;
struct
i2c_adapter
*
adap
;
struct
i2c_adapter
*
adap
;
struct
resource
*
mem
,
*
irq
;
struct
resource
*
mem
,
*
irq
;
int
r
;
int
r
;
...
@@ -581,19 +541,19 @@ omap_i2c_probe(struct platform_device *pdev)
...
@@ -581,19 +541,19 @@ omap_i2c_probe(struct platform_device *pdev)
/* NOTE: driver uses the static register mapping */
/* NOTE: driver uses the static register mapping */
mem
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
mem
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
if
(
!
mem
)
{
if
(
!
mem
)
{
pr_err
(
"%s: no mem resource?
\n
"
,
driver_name
);
dev_err
(
&
pdev
->
dev
,
"no mem resource?
\n
"
);
return
-
ENODEV
;
return
-
ENODEV
;
}
}
irq
=
platform_get_resource
(
pdev
,
IORESOURCE_IRQ
,
0
);
irq
=
platform_get_resource
(
pdev
,
IORESOURCE_IRQ
,
0
);
if
(
!
irq
)
{
if
(
!
irq
)
{
pr_err
(
"%s: no irq resource?
\n
"
,
driver_name
);
dev_err
(
&
pdev
->
dev
,
"no irq resource?
\n
"
);
return
-
ENODEV
;
return
-
ENODEV
;
}
}
r
=
(
int
)
request_mem_region
(
mem
->
start
,
(
mem
->
end
-
mem
->
start
)
+
1
,
r
=
(
int
)
request_mem_region
(
mem
->
start
,
(
mem
->
end
-
mem
->
start
)
+
1
,
driver_name
);
driver_name
);
if
(
!
r
)
{
if
(
!
r
)
{
pr_err
(
"%s: I2C region already claimed
\n
"
,
driver_name
);
dev_err
(
&
pdev
->
dev
,
"I2C region already claimed
\n
"
);
return
-
EBUSY
;
return
-
EBUSY
;
}
}
...
@@ -602,69 +562,73 @@ omap_i2c_probe(struct platform_device *pdev)
...
@@ -602,69 +562,73 @@ omap_i2c_probe(struct platform_device *pdev)
else
else
clock
=
100
;
/* Standard mode */
clock
=
100
;
/* Standard mode */
if
(
own
<
1
||
own
>
0x7f
)
dev
=
kzalloc
(
sizeof
(
struct
omap_i2c_dev
),
GFP_KERNEL
);
own
=
DEFAULT_OWN
;
if
(
!
dev
)
{
omap_i2c_dev
=
kzalloc
(
sizeof
(
struct
omap_i2c_dev
),
GFP_KERNEL
);
if
(
!
omap_i2c_dev
)
{
r
=
-
ENOMEM
;
r
=
-
ENOMEM
;
goto
do_release_region
;
goto
do_release_region
;
}
}
omap_i2c_dev
->
dev
=
&
pdev
->
dev
;
/* FIXME: Get own address from platform_data */
omap_i2c_dev
->
irq
=
irq
->
start
;
if
(
own
>=
1
&&
own
<
0x7f
)
omap_i2c_dev
->
base
=
(
void
__iomem
*
)
IO_ADDRESS
(
mem
->
start
)
;
dev
->
own_address
=
own
;
platform_set_drvdata
(
pdev
,
omap_i2c_dev
);
else
init_waitqueue_head
(
&
omap_i2c_dev
->
cmd_wait
)
;
own
=
DEFAULT_OWN
;
if
((
r
=
omap_i2c_24xx_get_clocks
(
omap_i2c_dev
,
pdev
->
id
))
!=
0
)
dev
->
dev
=
&
pdev
->
dev
;
dev
->
irq
=
irq
->
start
;
dev
->
base
=
(
void
__iomem
*
)
IO_ADDRESS
(
mem
->
start
);
platform_set_drvdata
(
pdev
,
dev
);
if
((
r
=
omap_i2c_get_clocks
(
dev
,
pdev
->
id
))
!=
0
)
goto
do_free_mem
;
goto
do_free_mem
;
omap_i2c_
24xx_enable_clocks
(
omap_i2c_dev
,
1
);
omap_i2c_
enable_clocks
(
dev
);
#ifdef CONFIG_ARCH_OMAP15XX
#ifdef CONFIG_ARCH_OMAP15XX
omap_i2c_dev
->
rev1
=
omap_i2c_read
(
omap_i2c_dev
,
OMAP_I2C_REV
)
<
0x20
;
dev
->
rev1
=
omap_i2c_read_reg
(
dev
,
OMAP_I2C_REV_REG
)
<
0x20
;
#endif
#endif
/* reset ASAP, clearing any IRQs */
/* reset ASAP, clearing any IRQs */
omap_i2c_reset
(
omap_i2c_
dev
);
omap_i2c_reset
(
dev
);
r
=
request_irq
(
omap_i2c_
dev
->
irq
,
omap_i2c_isr
,
0
,
r
=
request_irq
(
dev
->
irq
,
omap_i2c_isr
,
0
,
driver_name
,
omap_i2c_
dev
);
driver_name
,
dev
);
if
(
r
)
{
if
(
r
)
{
pr_err
(
"%s: failure requesting irq %i
\n
"
,
dev_err
(
dev
->
dev
,
"failure requesting irq %i
\n
"
,
dev
->
irq
);
driver_name
,
omap_i2c_dev
->
irq
);
goto
do_unuse_clocks
;
goto
do_unuse_clocks
;
}
}
r
=
omap_i2c_read
(
omap_i2c_dev
,
OMAP_I2C_REV
)
&
0xff
;
r
=
omap_i2c_read
_reg
(
dev
,
OMAP_I2C_REV_REG
)
&
0xff
;
pr_info
(
"%s: bus %d rev%d.%d at %d KHz
\n
"
,
driver_name
,
dev_info
(
dev
->
dev
,
"bus %d rev%d.%d at %d kHz
\n
"
,
pdev
->
id
-
1
,
r
>>
4
,
r
&
0xf
,
clock
);
pdev
->
id
-
1
,
r
>>
4
,
r
&
0xf
,
clock
);
adap
=
&
omap_i2c_
dev
->
adapter
;
adap
=
&
dev
->
adapter
;
i2c_set_adapdata
(
adap
,
omap_i2c_
dev
);
i2c_set_adapdata
(
adap
,
dev
);
adap
->
owner
=
THIS_MODULE
;
adap
->
owner
=
THIS_MODULE
;
adap
->
class
=
I2C_CLASS_HWMON
;
adap
->
class
=
I2C_CLASS_HWMON
;
strncpy
(
adap
->
name
,
"OMAP I2C adapter"
,
sizeof
(
adap
->
name
));
strncpy
(
adap
->
name
,
"OMAP I2C adapter"
,
sizeof
(
adap
->
name
));
adap
->
algo
=
&
omap_i2c_algo
;
adap
->
algo
=
&
omap_i2c_algo
;
adap
->
dev
.
parent
=
&
pdev
->
dev
;
adap
->
dev
.
parent
=
&
pdev
->
dev
;
/* i2c device drivers may be active on return from add_adapter() */
/* i2c device drivers may be active on return from add_adapter() */
r
=
i2c_add_adapter
(
adap
);
r
=
i2c_add_adapter
(
adap
);
if
(
r
)
{
if
(
r
)
{
pr_err
(
"%s: failure adding adapter
\n
"
,
driver_name
);
dev_err
(
dev
->
dev
,
"failure adding adapter
\n
"
);
goto
do_free_irq
;
goto
do_free_irq
;
}
}
omap_i2c_disable_clocks
(
dev
);
return
0
;
return
0
;
do_free_irq:
do_free_irq:
free_irq
(
omap_i2c_dev
->
irq
,
omap_i2c_
dev
);
free_irq
(
dev
->
irq
,
dev
);
do_unuse_clocks:
do_unuse_clocks:
omap_i2c_
24xx_enable_clocks
(
omap_i2c_dev
,
0
);
omap_i2c_
enable_clocks
(
dev
);
omap_i2c_
24xx_put_clocks
(
omap_i2c_
dev
);
omap_i2c_
put_clocks
(
dev
);
do_free_mem:
do_free_mem:
kfree
(
omap_i2c_
dev
);
kfree
(
dev
);
do_release_region:
do_release_region:
omap_i2c_write
(
omap_i2c_dev
,
0
,
OMAP_I2C_CON
);
omap_i2c_write
_reg
(
dev
,
OMAP_I2C_CON_REG
,
0
);
release_mem_region
(
mem
->
start
,
(
mem
->
end
-
mem
->
start
)
+
1
);
release_mem_region
(
mem
->
start
,
(
mem
->
end
-
mem
->
start
)
+
1
);
return
r
;
return
r
;
...
@@ -673,15 +637,14 @@ do_release_region:
...
@@ -673,15 +637,14 @@ do_release_region:
static
int
static
int
omap_i2c_remove
(
struct
platform_device
*
pdev
)
omap_i2c_remove
(
struct
platform_device
*
pdev
)
{
{
struct
omap_i2c_dev
*
omap_i2c_
dev
=
platform_get_drvdata
(
pdev
);
struct
omap_i2c_dev
*
dev
=
platform_get_drvdata
(
pdev
);
struct
resource
*
mem
;
struct
resource
*
mem
;
omap_i2c_write
(
omap_i2c_dev
,
0
,
OMAP_I2C_CON
);
free_irq
(
dev
->
irq
,
dev
);
i2c_del_adapter
(
&
omap_i2c_dev
->
adapter
);
i2c_del_adapter
(
&
dev
->
adapter
);
free_irq
(
omap_i2c_dev
->
irq
,
omap_i2c_dev
);
omap_i2c_write_reg
(
dev
,
OMAP_I2C_CON_REG
,
0
);
omap_i2c_24xx_enable_clocks
(
omap_i2c_dev
,
0
);
omap_i2c_put_clocks
(
dev
);
omap_i2c_24xx_put_clocks
(
omap_i2c_dev
);
kfree
(
dev
);
kfree
(
omap_i2c_dev
);
mem
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
mem
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
release_mem_region
(
mem
->
start
,
(
mem
->
end
-
mem
->
start
)
+
1
);
release_mem_region
(
mem
->
start
,
(
mem
->
end
-
mem
->
start
)
+
1
);
return
0
;
return
0
;
...
@@ -695,7 +658,7 @@ static struct platform_driver omap_i2c_driver = {
...
@@ -695,7 +658,7 @@ static struct platform_driver omap_i2c_driver = {
},
},
};
};
/*
i2c
may be needed to bring up other drivers */
/*
I2C
may be needed to bring up other drivers */
static
int
__init
static
int
__init
omap_i2c_init_driver
(
void
)
omap_i2c_init_driver
(
void
)
{
{
...
...
drivers/i2c/busses/i2c-omap.h
deleted
100644 → 0
View file @
0dad9642
/*
* linux/drivers/i2c/i2c-omap1610.h
*
* BRIEF MODULE DESCRIPTION
* OMAP I2C register definitions
*
* Copyright (C) 2004 Texas Instruments.
*
* 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
* HISTORY:
*
* 20040824: Thiago Radicchi <trr@dcc.ufmg.br> DCC-UFMG / iNdT
* Removed some ifdefs which broke compilation for some platforms.
* Added new defintion for interrupt vector.
*/
/* I2C Registers: */
#define OMAP_I2C_BASE IO_ADDRESS(0xfffb3800)
#define OMAP_I2C_IOSIZE (0x40)
#define OMAP_I2C_REV (OMAP_I2C_BASE + 0x00)
#define OMAP_I2C_IE (OMAP_I2C_BASE + 0x04)
#define OMAP_I2C_STAT (OMAP_I2C_BASE + 0x08)
#define OMAP_I2C_IV (OMAP_I2C_BASE + 0x0c)
#define OMAP_I2C_SYSS (OMAP_I2C_BASE + 0x10)
#define OMAP_I2C_BUF (OMAP_I2C_BASE + 0x14)
#define OMAP_I2C_CNT (OMAP_I2C_BASE + 0x18)
#define OMAP_I2C_DATA (OMAP_I2C_BASE + 0x1c)
#define OMAP_I2C_SYSC (OMAP_I2C_BASE + 0x20)
#define OMAP_I2C_CON (OMAP_I2C_BASE + 0x24)
#define OMAP_I2C_OA (OMAP_I2C_BASE + 0x28)
#define OMAP_I2C_SA (OMAP_I2C_BASE + 0x2c)
#define OMAP_I2C_PSC (OMAP_I2C_BASE + 0x30)
#define OMAP_I2C_SCLL (OMAP_I2C_BASE + 0x34)
#define OMAP_I2C_SCLH (OMAP_I2C_BASE + 0x38)
#define OMAP_I2C_SYSTEST (OMAP_I2C_BASE + 0x3c)
/* I2C Interrupt Enable Register (OMAP_I2C_IE): */
#define OMAP_I2C_IE_XRDY_IE (1 << 4)
/* Transmit data ready interrupt enable */
#define OMAP_I2C_IE_RRDY_IE (1 << 3)
/* Receive data ready interrupt enable */
#define OMAP_I2C_IE_ARDY_IE (1 << 2)
/* Register access ready interrupt enable */
#define OMAP_I2C_IE_NACK_IE (1 << 1)
/* No acknowledgment interrupt enable */
#define OMAP_I2C_IE_AL_IE (1 << 0)
/* Arbitration lost interrupt enable */
/* I2C Status Register (OMAP_I2C_STAT): */
#define OMAP_I2C_STAT_SBD (1 << 15)
/* Single byte data */
#define OMAP_I2C_STAT_BB (1 << 12)
/* Bus busy */
#define OMAP_I2C_STAT_ROVR (1 << 11)
/* Receive overrun */
#define OMAP_I2C_STAT_XUDF (1 << 10)
/* Transmit underflow */
#define OMAP_I2C_STAT_AAS (1 << 9)
/* Address as slave */
#define OMAP_I2C_STAT_AD0 (1 << 8)
/* Address zero */
#define OMAP_I2C_STAT_XRDY (1 << 4)
/* Transmit data ready */
#define OMAP_I2C_STAT_RRDY (1 << 3)
/* Receive data ready */
#define OMAP_I2C_STAT_ARDY (1 << 2)
/* Register access ready */
#define OMAP_I2C_STAT_NACK (1 << 1)
/* No acknowledgment interrupt enable */
#define OMAP_I2C_STAT_AL (1 << 0)
/* Arbitration lost interrupt enable */
/* I2C Buffer Configuration Register (OMAP_I2C_BUF): */
#define OMAP_I2C_BUF_RDMA_EN (1 << 15)
/* Receive DMA channel enable */
#define OMAP_I2C_BUF_XDMA_EN (1 << 7)
/* Transmit DMA channel enable */
/* I2C Configuration Register (OMAP_I2C_CON): */
#define OMAP_I2C_CON_EN (1 << 15)
/* I2C module enable */
#define OMAP_I2C_CON_RST (0 << 15)
/* I2C module reset */
#define OMAP_I2C_CON_BE (1 << 14)
/* Big endian mode */
#define OMAP_I2C_CON_STB (1 << 11)
/* Start byte mode (master mode only) */
#define OMAP_I2C_CON_MST (1 << 10)
/* Master/slave mode */
#define OMAP_I2C_CON_TRX (1 << 9)
/* Transmitter/receiver mode (master mode only) */
#define OMAP_I2C_CON_XA (1 << 8)
/* Expand address */
#define OMAP_I2C_CON_RM (1 << 2)
/* Repeat mode (master mode only) */
#define OMAP_I2C_CON_STP (1 << 1)
/* Stop condition (master mode only) */
#define OMAP_I2C_CON_STT (1 << 0)
/* Start condition (master mode only) */
/* I2C System Test Register (OMAP_I2C_SYSTEST): */
#define OMAP_I2C_SYSTEST_ST_EN (1 << 15)
/* System test enable */
#define OMAP_I2C_SYSTEST_FREE (1 << 14)
/* Free running mode (on breakpoint) */
#define OMAP_I2C_SYSTEST_TMODE_MASK (3 << 12)
/* Test mode select */
#define OMAP_I2C_SYSTEST_TMODE_SHIFT (12)
/* Test mode select */
#define OMAP_I2C_SYSTEST_SCL_I (1 << 3)
/* SCL line sense input value */
#define OMAP_I2C_SYSTEST_SCL_O (1 << 2)
/* SCL line drive output value */
#define OMAP_I2C_SYSTEST_SDA_I (1 << 1)
/* SDA line sense input value */
#define OMAP_I2C_SYSTEST_SDA_O (1 << 0)
/* SDA line drive output value */
/* I2C System Status register (OMAP_I2C_SYSS): */
#define OMAP_I2C_SYSS_RDONE 1
/* Reset Done */
/* I2C System Configuration Register (OMAP_I2C_SYSC): */
#define OMAP_I2C_SYSC_SRST (1 << 1)
/* Soft Reset */
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