Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci-2.6.23
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-2.6.23
Commits
f7d41d35
Commit
f7d41d35
authored
Oct 16, 2006
by
Kevin Hilman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "ARM: DaVinci: I2C driver cleanup"
This reverts commit
9d9a2a50
.
parent
02c19243
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
355 additions
and
276 deletions
+355
-276
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Kconfig
+3
-9
drivers/i2c/busses/Makefile
drivers/i2c/busses/Makefile
+1
-1
drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-davinci.c
+195
-266
drivers/i2c/busses/i2c-davinci.h
drivers/i2c/busses/i2c-davinci.h
+156
-0
No files found.
drivers/i2c/busses/Kconfig
View file @
f7d41d35
...
...
@@ -84,15 +84,6 @@ config I2C_AU1550
This driver can also be built as a module. If so, the module
will be called i2c-au1550.
config I2C_DAVINCI
tristate "Davinci I2C driver"
depends on I2C && ARCH_DAVINCI
help
If you say yes to this option, support will be included for the
I2C interface on the Texas Instruments DaVinci DM644x family of
processors. Like DM6442 and DM6443.
For details please see http://www.ti.com/davinci
config I2C_ELEKTOR
tristate "Elektor ISA card"
depends on I2C && ISA && BROKEN_ON_SMP
...
...
@@ -554,5 +545,8 @@ config I2C_OMAP
Support for TI OMAP I2C driver. Say yes if you want to use the OMAP
I2C interface.
config I2C_DAVINCI
tristate "Davinci i2c driver"
depends on I2C && ARCH_DAVINCI
endmenu
drivers/i2c/busses/Makefile
View file @
f7d41d35
...
...
@@ -9,7 +9,6 @@ obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o
obj-$(CONFIG_I2C_AMD756_S4882)
+=
i2c-amd756-s4882.o
obj-$(CONFIG_I2C_AMD8111)
+=
i2c-amd8111.o
obj-$(CONFIG_I2C_AU1550)
+=
i2c-au1550.o
obj-$(CONFIG_I2C_DAVINCI)
+=
i2c-davinci.o
obj-$(CONFIG_I2C_ELEKTOR)
+=
i2c-elektor.o
obj-$(CONFIG_I2C_HYDRA)
+=
i2c-hydra.o
obj-$(CONFIG_I2C_I801)
+=
i2c-i801.o
...
...
@@ -45,6 +44,7 @@ obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o
obj-$(CONFIG_SCx200_ACB)
+=
scx200_acb.o
obj-$(CONFIG_SCx200_I2C)
+=
scx200_i2c.o
obj-$(CONFIG_I2C_OMAP)
+=
i2c-omap.o
obj-$(CONFIG_I2C_DAVINCI)
+=
i2c-davinci.o
ifeq
($(CONFIG_I2C_DEBUG_BUS),y)
EXTRA_CFLAGS
+=
-DDEBUG
...
...
drivers/i2c/busses/i2c-davinci.c
View file @
f7d41d35
/*
*
TI DAVINCI I2C adapter driver.
*
linux/drivers/i2c/i2c-davinci.c
*
*
Copyright (C) 2006 Texas Instruments.
*
TI DAVINCI I2C unified algorith+adapter driver
*
*
Updated by Vinod & Sudhakar Feb 2005
*
Copyright (C) 2006 Texas Instruments.
*
* ----------------------------------------------------------------------------
*
...
...
@@ -17,122 +17,69 @@
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
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.
* ----------------------------------------------------------------------------
Modifications:
ver. 1.0: Feb 2005, Vinod/Sudhakar
-
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/version.h>
#include <linux/i2c.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <
linux/err
.h>
#include <
asm/arch/hardware
.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <linux/moduleparam.h>
#include <linux/err.h>
#include <linux/proc_fs.h>
#include <linux/sysctl.h>
#include <linux/wait.h>
#include <asm/arch/irqs.h>
#include "i2c-davinci.h"
MODULE_AUTHOR
(
"Texas Instruments India"
);
MODULE_DESCRIPTION
(
"TI DaVinci I2C bus adapter"
);
MODULE_LICENSE
(
"GPL"
);
static
int
bus_freq
;
module_param
(
bus_freq
,
int
,
0
);
MODULE_PARM_DESC
(
bus_freq
,
"Set I2C bus frequency in KHz: 100 (Standard Mode) or 400 (Fast Mode)"
);
/* ----- global defines ----------------------------------------------- */
static
const
char
driver_name
[]
=
"i2c_davinci"
;
#define DAVINCI_I2C_TIMEOUT (1*HZ)
#define I2C_DAVINCI_INTR_ALL (DAVINCI_I2C_IMR_AAS | \
DAVINCI_I2C_IMR_SCD | \
/*DAVINCI_I2C_IMR_XRDY | */
\
/*DAVINCI_I2C_IMR_RRDY | */
\
/*DAVINCI_I2C_IMR_ARDY | */
\
DAVINCI_I2C_IMR_NACK | \
DAVINCI_I2C_IMR_AL)
#define DAVINCI_I2C_OAR_REG 0x00
#define DAVINCI_I2C_IMR_REG 0x04
#define DAVINCI_I2C_STR_REG 0x08
#define DAVINCI_I2C_CLKL_REG 0x0c
#define DAVINCI_I2C_CLKH_REG 0x10
#define DAVINCI_I2C_CNT_REG 0x14
#define DAVINCI_I2C_DRR_REG 0x18
#define DAVINCI_I2C_SAR_REG 0x1c
#define DAVINCI_I2C_DXR_REG 0x20
#define DAVINCI_I2C_MDR_REG 0x24
#define DAVINCI_I2C_IVR_REG 0x28
#define DAVINCI_I2C_EMDR_REG 0x2c
#define DAVINCI_I2C_PSC_REG 0x30
#define DAVINCI_I2C_IVR_AAS (0x07)
#define DAVINCI_I2C_IVR_SCD (0x06)
#define DAVINCI_I2C_IVR_XRDY (0x05)
#define DAVINCI_I2C_IVR_RDR (0x04)
#define DAVINCI_I2C_IVR_ARDY (0x03)
#define DAVINCI_I2C_IVR_NACK (0x02)
#define DAVINCI_I2C_IVR_AL (0x01)
#define DAVINCI_I2C_STR_BB (1 << 12)
#define DAVINCI_I2C_STR_RSFULL (1 << 11)
#define DAVINCI_I2C_STR_SCD (1 << 5)
#define DAVINCI_I2C_STR_ARDY (1 << 2)
#define DAVINCI_I2C_STR_NACK (1 << 1)
#define DAVINCI_I2C_STR_AL (1 << 0)
#define DAVINCI_I2C_MDR_STT (1 << 13)
#define DAVINCI_I2C_MDR_STP (1 << 11)
#define DAVINCI_I2C_MDR_MST (1 << 10)
#define DAVINCI_I2C_MDR_TRX (1 << 9)
#define DAVINCI_I2C_MDR_XA (1 << 8)
#define DAVINCI_I2C_MDR_IRS (1 << 5)
#define DAVINCI_I2C_IMR_AL (1 << 0)
#define DAVINCI_I2C_IMR_NACK (1 << 1)
#define DAVINCI_I2C_IMR_RRDY (1 << 3)
#define DAVINCI_I2C_IMR_XRDY (1 << 4)
#define DAVINCI_I2C_IMR_SCD (1 << 5)
#define DAVINCI_I2C_IMR_AAS (1 << 6)
#define MOD_REG_BIT(val, mask, set) do { \
if (set) \
val |= mask; \
else \
val &= ~mask; \
} while(0)
#define MAX_MESSAGES 65536
/* max number of messages */
#define I2C_DAVINCI_INTR_ALL (DAVINCI_I2C_ICIMR_AAS_MASK | \
DAVINCI_I2C_ICIMR_SCD_MASK | \
/*DAVINCI_I2C_ICIMR_ICXRDY_MASK | */
\
/*DAVINCI_I2C_ICIMR_ICRRDY_MASK | */
\
/*DAVINCI_I2C_ICIMR_ARDY_MASK | */
\
DAVINCI_I2C_ICIMR_NACK_MASK | \
DAVINCI_I2C_ICIMR_AL_MASK)
/* Following are the default values for the module parameters */
static
int
bus_freq
=
20
;
/* Fast Mode = 400 KHz, Standard Mode = 100 KHz */
struct
davinci_i2c_dev
{
struct
device
*
dev
;
void
__iomem
*
base
;
struct
completion
cmd_complete
;
struct
clk
*
clk
;
int
cmd_err
;
u8
*
buf
;
size_t
buf_len
;
int
irq
;
struct
i2c_adapter
adapter
;
};
static
inline
void
davinci_i2c_write_reg
(
struct
davinci_i2c_dev
*
i2c_dev
,
int
reg
,
u16
val
)
{
__raw_writew
(
val
,
i2c_dev
->
base
+
reg
);
}
static
inline
u16
davinci_i2c_read_reg
(
struct
davinci_i2c_dev
*
i2c_dev
,
int
reg
)
{
return
__raw_readw
(
i2c_dev
->
base
+
reg
);
}
static
int
own_addr
=
0xa
;
/* Randomly assigned own address */
/* Instance of the private I2C device structure */
static
struct
i2c_davinci_device
i2c_davinci_dev
;
/*
* This functions configures I2C and brings I2C out of reset.
...
...
@@ -140,56 +87,53 @@ static inline u16 davinci_i2c_read_reg(struct davinci_i2c_dev *i2c_dev, int reg)
* also gets called if I2C encounetrs any errors. Clock calculation portion
* of this function has been taken from some other driver.
*/
static
int
i2c_davinci_
init
(
struct
davinci_i2c_dev
*
dev
)
static
int
i2c_davinci_
reset
(
struct
i2c_davinci_device
*
dev
)
{
u16
psc
;
u32
clk
,
clkh
,
clkl
;
u32
clk
;
u32
input_clock
=
clk_get_rate
(
dev
->
clk
);
u16
w
;
/* put I2C into reset */
w
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_MDR_REG
);
MOD_REG_BIT
(
w
,
DAVINCI_I2C_MDR_IRS
,
0
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_MDR_REG
,
w
);
dev
->
regs
->
icmdr
&=
~
DAVINCI_I2C_ICMDR_IRS_MASK
;
/* NOTE: I2C Clock divider programming info
* As per I2C specs the following formulas provide prescalar
* and low/high divider values
* input clk --> PSC Div -----------> ICCL/H Div --> output clock
* module clk
*
* output clk = module clk / (PSC + 1) [ (ICCL + d) + (ICCH + d) ]
*
* Thus,
* (ICCL + ICCH) = clk = (input clk / ((psc +1) * output clk)) - 2d;
*
* where if PSC == 0, d = 7,
* if PSC == 1, d = 6
* if PSC > 1 , d = 5
*/
* As per I2C specs the following formulas provide prescalar
* and low/high divider values
*
* input clk --> PSC Div -----------> ICCL/H Div --> output clock
* module clk
*
* output clk = module clk / (PSC + 1) [ (ICCL + d) + (ICCH + d) ]
*
* Thus,
* (ICCL + ICCH) = clk = (input clk / ((psc +1) * output clk)) - 2d;
*
* where if PSC == 0, d = 7,
* if PSC == 1, d = 6
* if PSC > 1 , d = 5
*/
psc
=
26
;
/* To get 1MHz clock */
clk
=
((
input_clock
/
(
psc
+
1
))
/
(
bus_freq
*
1000
))
-
10
;
clkh
=
(
27
*
clk
)
/
100
;
clkl
=
clk
-
clkh
;
clk
=
((
input_clock
/
(
psc
+
1
))
/
(
bus_freq
*
1000
))
-
10
;
d
avinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_PSC_REG
,
psc
)
;
d
avinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_CLKH_REG
,
clkh
);
d
avinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_CLKL_REG
,
clkl
);
d
ev
->
regs
->
icpsc
=
psc
;
d
ev
->
regs
->
icclkh
=
(
27
*
clk
)
/
100
;
/* duty cycle should be 27% */
d
ev
->
regs
->
icclkl
=
(
clk
-
dev
->
regs
->
icclkh
);
dev_dbg
(
dev
->
dev
,
"CLK = %d
\n
"
,
clk
);
dev_dbg
(
dev
->
dev
,
"PSC = %d
\n
"
,
d
avinci_i2c_read_reg
(
DAVINCI_I2C_PSC_REG
)
);
dev_dbg
(
dev
->
dev
,
"CLKL = %d
\n
"
,
d
avinci_i2c_read_reg
(
DAVINCI_I2C_CLKL_REG
)
);
dev_dbg
(
dev
->
dev
,
"CLKH = %d
\n
"
,
d
avinci_i2c_read_reg
(
DAVINCI_I2C_CLKH_REG
)
);
dev_dbg
(
dev
->
dev
,
"PSC = %d
\n
"
,
d
ev
->
regs
->
icpsc
);
dev_dbg
(
dev
->
dev
,
"CLKL = %d
\n
"
,
d
ev
->
regs
->
icclkl
);
dev_dbg
(
dev
->
dev
,
"CLKH = %d
\n
"
,
d
ev
->
regs
->
icclkh
);
/* Take the I2C module out of reset: */
w
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_MDR_REG
);
MOD_REG_BIT
(
w
,
DAVINCI_I2C_MDR_IRS
,
1
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_MDR_REG
,
w
);
/* Set Own Address: */
dev
->
regs
->
icoar
=
own_addr
;
/* Enable interrupts */
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_IMR_REG
,
I2C_DAVINCI_INTR_ALL
);
dev
->
regs
->
icimr
=
I2C_DAVINCI_INTR_ALL
;
/* Take the I2C module out of reset: */
dev
->
regs
->
icmdr
|=
DAVINCI_I2C_ICMDR_IRS_MASK
;
return
0
;
}
...
...
@@ -197,13 +141,12 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
/*
* Waiting on Bus Busy
*/
static
int
i2c_davinci_wait_for_bb
(
struct
davinci_i2c_dev
*
dev
,
char
allow_sleep
)
static
int
i2c_davinci_wait_for_bb
(
char
allow_sleep
)
{
unsigned
long
timeout
;
timeout
=
jiffies
+
DAVINCI_I2C_TIMEOUT
;
while
((
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_STR_REG
))
&
DAVINCI_I2C_STR_BB
)
{
while
((
i2c_davinci_dev
.
regs
->
icstr
)
&
DAVINCI_I2C_ICSTR_BB_MASK
)
{
if
(
time_after
(
jiffies
,
timeout
))
{
return
-
ETIMEDOUT
;
}
...
...
@@ -221,57 +164,61 @@ static int i2c_davinci_wait_for_bb(struct davinci_i2c_dev *dev, char allow_sleep
static
int
i2c_davinci_xfer_msg
(
struct
i2c_adapter
*
adap
,
struct
i2c_msg
*
msg
,
int
stop
)
{
struct
davinci_i2c_dev
*
dev
=
i2c_get_adapdata
(
adap
);
struct
i2c_davinci_device
*
dev
=
i2c_get_adapdata
(
adap
);
u8
zero_byte
=
0
;
u32
flag
=
0
,
stat
=
0
,
cnt
=
2000
;
u16
w
;
int
r
;
if
(
msg
->
len
==
0
)
return
-
EINVAL
;
/* Introduce a 20musec delay. Required for Davinci EVM */
while
(
cnt
--
);
/* set the slave address */
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_SAR_REG
,
msg
->
addr
);
dev
->
buf
=
msg
->
buf
;
dev
->
buf_len
=
msg
->
len
;
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_CNT_REG
,
dev
->
buf_len
);
dev
->
regs
->
icsar
=
msg
->
addr
;
/* Sigh, seems we can't do zero length transactions. Thus, we
* can't probe for devices w/o actually sending/receiving at least
* a single byte. So we'll set count to 1 for the zero length
* transaction case and hope we don't cause grief for some
* arbitrary device due to random byte write/read during
* probes.
*/
if
(
msg
->
len
==
0
)
{
dev
->
buf
=
&
zero_byte
;
dev
->
buf_len
=
1
;
}
else
{
dev
->
buf
=
msg
->
buf
;
dev
->
buf_len
=
msg
->
len
;
}
dev
->
regs
->
iccnt
=
dev
->
buf_len
;
init_completion
(
&
dev
->
cmd_complete
);
dev
->
cmd_err
=
0
;
/* Clear any pending interrupts by reading the IVR */
stat
=
d
avinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_IVR_REG
)
;
stat
=
d
ev
->
regs
->
icivr
;
/* Take I2C out of reset, configure it as master and set the
* start bit */
flag
=
DAVINCI_I2C_MDR_IRS
|
DAVINCI_I2C_MDR_MST
|
DAVINCI_I2C_MDR_STT
;
flag
=
DAVINCI_I2C_ICMDR_IRS_MASK
|
DAVINCI_I2C_ICMDR_MST_MASK
|
DAVINCI_I2C_ICMDR_STT_MASK
;
/* if the slave address is ten bit address, enable XA bit */
if
(
msg
->
flags
&
I2C_M_TEN
)
flag
|=
DAVINCI_I2C_
MDR_XA
;
flag
|=
DAVINCI_I2C_
ICMDR_XA_MASK
;
if
(
!
(
msg
->
flags
&
I2C_M_RD
))
flag
|=
DAVINCI_I2C_
MDR_TRX
;
flag
|=
DAVINCI_I2C_
ICMDR_TRX_MASK
;
if
(
stop
)
flag
|=
DAVINCI_I2C_
MDR_STP
;
flag
|=
DAVINCI_I2C_
ICMDR_STP_MASK
;
/* write the data into mode register */
d
avinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_MDR_REG
,
flag
)
;
d
ev
->
regs
->
icmdr
=
flag
;
/* Enable receive and transmit interrupts */
if
(
msg
->
flags
&
I2C_M_RD
)
{
w
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_IMR_REG
);
MOD_REG_BIT
(
w
,
DAVINCI_I2C_IMR_RRDY
,
1
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_IMR_REG
,
w
);
}
else
{
w
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_IMR_REG
);
MOD_REG_BIT
(
w
,
DAVINCI_I2C_IMR_XRDY
,
1
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_IMR_REG
,
w
);
}
if
(
msg
->
flags
&
I2C_M_RD
)
dev
->
regs
->
icimr
|=
DAVINCI_I2C_ICIMR_ICRRDY_MASK
;
else
dev
->
regs
->
icimr
|=
DAVINCI_I2C_ICIMR_ICXRDY_MASK
;
r
=
wait_for_completion_interruptible_timeout
(
&
dev
->
cmd_complete
,
DAVINCI_I2C_TIMEOUT
);
...
...
@@ -280,56 +227,67 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
return
r
;
if
(
r
==
0
)
{
dev_err
(
dev
->
dev
,
"controller timed out
\n
"
);
i2c_davinci_
ini
t
(
dev
);
i2c_davinci_
rese
t
(
dev
);
return
-
ETIMEDOUT
;
}
/* no error */
if
(
likely
(
!
dev
->
cmd_err
)
)
if
(
!
dev
->
cmd_err
)
return
msg
->
len
;
/* We have an error */
if
(
dev
->
cmd_err
&
DAVINCI_I2C_STR_AL
||
dev
->
cmd_err
&
DAVINCI_I2C_STR_RSFULL
)
{
i2c_davinci_init
(
dev
);
return
-
EIO
;
}
if
(
dev
->
cmd_err
&
DAVINCI_I2C_STR_NACK
)
{
if
(
dev
->
cmd_err
&
DAVINCI_I2C_ICSTR_NACK_MASK
)
{
if
(
msg
->
flags
&
I2C_M_IGNORE_NAK
)
return
msg
->
len
;
if
(
stop
)
{
w
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_MDR_REG
);
MOD_REG_BIT
(
w
,
DAVINCI_I2C_MDR_STP
,
1
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_MDR_REG
,
w
);
}
if
(
stop
)
dev
->
regs
->
icmdr
|=
DAVINCI_I2C_ICMDR_STP_MASK
;
return
-
EREMOTEIO
;
}
if
(
dev
->
cmd_err
&
DAVINCI_I2C_ICSTR_AL_MASK
||
dev
->
cmd_err
&
DAVINCI_I2C_ICSTR_RSFULL_MASK
)
{
i2c_davinci_reset
(
dev
);
return
-
EIO
;
}
return
msg
->
len
;
}
/*
* Prepare controller for a transaction and call i2c_davinci_xfer_msg
*/
static
int
i2c_davinci_xfer
(
struct
i2c_adapter
*
adap
,
struct
i2c_msg
msgs
[],
int
num
)
{
struct
davinci_i2c_dev
*
dev
=
i2c_get_adapdata
(
adap
);
int
i
;
struct
i2c_davinci_device
*
dev
=
i2c_get_adapdata
(
adap
);
int
count
;
int
ret
=
0
;
char
retries
=
adap
->
retries
;
char
retries
=
5
;
dev_dbg
(
dev
->
dev
,
"%s: msgs: %d
\n
"
,
__FUNCTION__
,
num
);
if
((
ret
=
i2c_davinci_wait_for_bb
(
dev
,
1
))
<
0
)
{
if
(
num
<
1
||
num
>
MAX_MESSAGES
)
return
-
EINVAL
;
/* Check for valid parameters in messages */
for
(
count
=
0
;
count
<
num
;
count
++
)
if
(
msgs
[
count
].
buf
==
NULL
)
return
-
EINVAL
;
if
((
ret
=
i2c_davinci_wait_for_bb
(
1
))
<
0
)
{
dev_warn
(
dev
->
dev
,
"timeout waiting for bus ready"
);
return
ret
;
}
for
(
i
=
0
;
i
<
num
;
i
++
)
{
for
(
count
=
0
;
count
<
num
;
count
++
)
{
dev_dbg
(
dev
->
dev
,
"%s: %d, addr: 0x%04x, len: %d, flags: 0x%x
\n
"
,
__FUNCTION__
,
count
,
msgs
[
count
].
addr
,
msgs
[
count
].
len
,
msgs
[
count
].
flags
);
do
{
ret
=
i2c_davinci_xfer_msg
(
adap
,
&
msgs
[
i
],
(
i
==
(
num
-
1
)));
ret
=
i2c_davinci_xfer_msg
(
adap
,
&
msgs
[
count
],
(
count
==
(
num
-
1
)));
if
(
ret
<
0
)
{
dev_dbg
(
dev
->
dev
,
"Retrying ...
\n
"
);
...
...
@@ -339,32 +297,34 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
break
;
}
while
(
retries
);
dev_dbg
(
dev
->
dev
,
"%s:%d ret: %d
\n
"
,
dev_dbg
(
dev
->
dev
,
"%s:%d ret: %d
\n
"
,
__FUNCTION__
,
__LINE__
,
ret
);
if
(
ret
!=
msgs
[
i
].
len
)
if
(
ret
!=
msgs
[
count
].
len
)
break
;
}
if
(
ret
>=
0
&&
num
>
1
)
ret
=
num
;
dev_dbg
(
dev
->
dev
,
"%s:%d ret: %d
\n
"
,
__FUNCTION__
,
__LINE__
,
ret
);
dev_dbg
(
dev
->
dev
,
"%s:%d ret: %d
\n
"
,
__FUNCTION__
,
__LINE__
,
ret
);
return
ret
;
}
static
u32
i2c_davinci_func
(
struct
i2c_adapter
*
adap
)
{
return
I2C_FUNC_I2C
|
(
I2C_FUNC_SMBUS_EMUL
&
~
I2C_FUNC_SMBUS_QUICK
)
;
return
I2C_FUNC_I2C
|
I2C_FUNC_SMBUS_EMUL
;
}
/*
* This function marks a transaction as complete.
*/
static
inline
void
i2c_davinci_complete_cmd
(
struct
davinci_i2c_dev
*
dev
)
static
inline
void
i2c_davinci_complete_cmd
(
struct
i2c_davinci_device
*
dev
)
{
complete
(
&
dev
->
cmd_complete
);
wake_up
(
&
dev
->
cmd_wait
);
}
/*
...
...
@@ -374,99 +334,80 @@ static inline void i2c_davinci_complete_cmd(struct davinci_i2c_dev *dev)
static
irqreturn_t
i2c_davinci_isr
(
int
this_irq
,
void
*
dev_id
,
struct
pt_regs
*
reg
)
{
struct
davinci_i2c_dev
*
dev
=
dev_id
;
struct
i2c_davinci_device
*
dev
=
dev_id
;
u32
stat
;
int
count
=
0
;
u16
w
;
while
((
stat
=
d
avinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_IVR_REG
)
)
!=
0
)
{
while
((
stat
=
d
ev
->
regs
->
icivr
)
!=
0
)
{
dev_dbg
(
dev
->
dev
,
"%s: stat=0x%x
\n
"
,
__FUNCTION__
,
stat
);
if
(
count
++
==
100
)
{
dev_warn
(
dev
->
dev
,
"Too much work in one IRQ
\n
"
);
break
;
}
switch
(
stat
)
{
case
DAVINCI_I2C_I
VR
_AL
:
dev
->
cmd_err
|=
DAVINCI_I2C_
STR_AL
;
case
DAVINCI_I2C_I
CIVR_INTCODE
_AL
:
dev
->
cmd_err
|=
DAVINCI_I2C_
ICSTR_AL_MASK
;
i2c_davinci_complete_cmd
(
dev
);
break
;
case
DAVINCI_I2C_I
VR
_NACK
:
dev
->
cmd_err
|=
DAVINCI_I2C_
STR_NAC
K
;
case
DAVINCI_I2C_I
CIVR_INTCODE
_NACK
:
dev
->
cmd_err
|=
DAVINCI_I2C_
ICSTR_NACK_MAS
K
;
i2c_davinci_complete_cmd
(
dev
);
break
;
case
DAVINCI_I2C_IVR_ARDY
:
w
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_STR_REG
);
MOD_REG_BIT
(
w
,
DAVINCI_I2C_STR_ARDY
,
1
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_STR_REG
,
w
);
case
DAVINCI_I2C_ICIVR_INTCODE_RAR
:
dev
->
regs
->
icstr
|=
DAVINCI_I2C_ICSTR_ARDY_MASK
;
break
;
case
DAVINCI_I2C_I
VR
_RDR
:
case
DAVINCI_I2C_I
CIVR_INTCODE
_RDR
:
if
(
dev
->
buf_len
)
{
*
dev
->
buf
++
=
d
avinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_DRR_REG
)
;
*
dev
->
buf
++
=
d
ev
->
regs
->
icdrr
;
dev
->
buf_len
--
;
if
(
dev
->
buf_len
)
{
continue
;
}
else
{
w
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_STR_REG
);
MOD_REG_BIT
(
w
,
DAVINCI_I2C_IMR_RRDY
,
0
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_STR_REG
,
w
);
dev
->
regs
->
icimr
&=
~
DAVINCI_I2C_ICIMR_ICRRDY_MASK
;
}
}
else
{
dev_err
(
dev
->
dev
,
"RDR IRQ while no"
"data requested
\n
"
);
}
break
;
case
DAVINCI_I2C_I
VR_XRDY
:
case
DAVINCI_I2C_I
CIVR_INTCODE_TDR
:
if
(
dev
->
buf_len
)
{
d
avinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_DXR_REG
,
*
dev
->
buf
++
)
;
d
ev
->
regs
->
icdxr
=
*
dev
->
buf
++
;
dev
->
buf_len
--
;
if
(
dev
->
buf_len
)
continue
;
else
{
w
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_IMR_REG
);
MOD_REG_BIT
(
w
,
DAVINCI_I2C_IMR_XRDY
,
0
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_IMR_REG
,
w
);
dev
->
regs
->
icimr
&=
~
DAVINCI_I2C_ICIMR_ICXRDY_MASK
;
}
}
else
{
dev_err
(
dev
->
dev
,
"TDR IRQ while no data to"
"send
\n
"
);
}
break
;
case
DAVINCI_I2C_IVR_SCD
:
w
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_STR_REG
);
MOD_REG_BIT
(
w
,
DAVINCI_I2C_STR_SCD
,
1
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_STR_REG
,
w
);
case
DAVINCI_I2C_ICIVR_INTCODE_SCD
:
dev
->
regs
->
icstr
|=
DAVINCI_I2C_ICSTR_SCD_MASK
;
i2c_davinci_complete_cmd
(
dev
);
break
;
case
DAVINCI_I2C_I
VR
_AAS
:
case
DAVINCI_I2C_I
CIVR_INTCODE
_AAS
:
dev_warn
(
dev
->
dev
,
"Address as slave interrupt"
);
break
;
default:
break
;
}
/* switch */
}
/* while */
return
count
?
IRQ_HANDLED
:
IRQ_NONE
;
}
/* switch */
}
/* while */
return
IRQ_HANDLED
;
}
static
struct
i2c_algorithm
i2c_davinci_algo
=
{
.
master_xfer
=
i2c_davinci_xfer
,
.
functionality
=
i2c_davinci_func
,
.
master_xfer
=
i2c_davinci_xfer
,
.
functionality
=
i2c_davinci_func
,
};
static
int
davinci_i2c_probe
(
struct
platform_device
*
pdev
)
{
struct
davinci_i2c_dev
*
dev
;
struct
i2c_davinci_device
*
dev
=
&
i2c_davinci_
dev
;
struct
i2c_adapter
*
adap
;
struct
resource
*
mem
,
*
irq
,
*
ioarea
;
struct
resource
*
mem
,
*
irq
;
int
r
;
/* NOTE: driver uses the static register mapping */
...
...
@@ -475,44 +416,38 @@ davinci_i2c_probe(struct platform_device *pdev)
dev_err
(
&
pdev
->
dev
,
"no mem resource?
\n
"
);
return
-
ENODEV
;
}
irq
=
platform_get_resource
(
pdev
,
IORESOURCE_IRQ
,
0
);
if
(
!
irq
)
{
dev_err
(
&
pdev
->
dev
,
"no irq resource?
\n
"
);
return
-
ENODEV
;
}
ioarea
=
request_mem_region
(
mem
->
start
,
(
mem
->
end
-
mem
->
start
)
+
1
,
pdev
->
name
);
if
(
!
ioarea
)
{
r
=
(
int
)
request_mem_region
(
mem
->
start
,
(
mem
->
end
-
mem
->
start
)
+
1
,
driver_
name
);
if
(
!
r
)
{
dev_err
(
&
pdev
->
dev
,
"I2C region already claimed
\n
"
);
return
-
EBUSY
;
}
dev
=
kzalloc
(
sizeof
(
struct
davinci_i2c_dev
),
GFP_KERNEL
);
if
(
!
dev
)
{
r
=
-
ENOMEM
;
goto
err_release_region
;
}
memset
(
dev
,
0
,
sizeof
(
struct
i2c_davinci_device
));
init_waitqueue_head
(
&
dev
->
cmd_wait
);
dev
->
dev
=
&
pdev
->
dev
;
dev
->
irq
=
irq
->
start
;
platform_set_drvdata
(
pdev
,
dev
);
dev
->
clk
=
clk_get
(
&
pdev
->
dev
,
"I2CCLK"
);
if
(
IS_ERR
(
dev
->
clk
))
{
r
=
-
ENODEV
;
goto
err_free_mem
;
}
dev
->
clk
=
clk_get
(
&
pdev
->
dev
,
"I2CCLK"
);
if
(
IS_ERR
(
dev
->
clk
))
return
-
1
;
clk_enable
(
dev
->
clk
);
dev
->
base
=
(
void
__iomem
*
)
IO_ADDRESS
(
mem
->
start
);
i2c_davinci_init
(
dev
);
dev
->
regs
=
(
davinci_i2cregsovly
)
mem
->
start
;
i2c_davinci_reset
(
dev
);
dev
->
irq
=
irq
->
start
;
platform_set_drvdata
(
pdev
,
dev
);
r
=
request_irq
(
dev
->
irq
,
i2c_davinci_isr
,
0
,
pdev
->
name
,
dev
);
r
=
request_irq
(
dev
->
irq
,
i2c_davinci_isr
,
0
,
driver_
name
,
dev
);
if
(
r
)
{
dev_err
(
&
pdev
->
dev
,
"failure requesting irq %i
\n
"
,
dev
->
irq
);
goto
err
_unuse_clocks
;
goto
do
_unuse_clocks
;
}
adap
=
&
dev
->
adapter
;
...
...
@@ -522,8 +457,8 @@ davinci_i2c_probe(struct platform_device *pdev)
strncpy
(
adap
->
name
,
"DaVinci I2C adapter"
,
sizeof
(
adap
->
name
));
adap
->
algo
=
&
i2c_davinci_algo
;
adap
->
dev
.
parent
=
&
pdev
->
dev
;
/* FIXME */
adap
->
client_register
=
NULL
;
adap
->
client_unregister
=
NULL
;
adap
->
timeout
=
1
;
adap
->
retries
=
1
;
...
...
@@ -531,20 +466,17 @@ davinci_i2c_probe(struct platform_device *pdev)
r
=
i2c_add_adapter
(
adap
);
if
(
r
)
{
dev_err
(
&
pdev
->
dev
,
"failure adding adapter
\n
"
);
goto
err
_free_irq
;
goto
do
_free_irq
;
}
return
0
;
err
_free_irq:
do
_free_irq:
free_irq
(
dev
->
irq
,
dev
);
err
_unuse_clocks:
do
_unuse_clocks:
clk_disable
(
dev
->
clk
);
clk_put
(
dev
->
clk
);
dev
->
clk
=
NULL
;
err_free_mem:
kfree
(
dev
);
err_release_region:
release_mem_region
(
mem
->
start
,
(
mem
->
end
-
mem
->
start
)
+
1
);
return
r
;
...
...
@@ -553,17 +485,15 @@ err_release_region:
static
int
davinci_i2c_remove
(
struct
platform_device
*
pdev
)
{
struct
davinci_i2c_dev
*
dev
=
platform_get_drvdata
(
pdev
);
struct
i2c_davinci_device
*
dev
=
platform_get_drvdata
(
pdev
);
struct
resource
*
mem
;
platform_set_drvdata
(
pdev
,
NULL
);
clk_disable
(
dev
->
clk
);
clk_disable
(
dev
->
clk
);
clk_put
(
dev
->
clk
);
dev
->
clk
=
NULL
;
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_MDR_REG
,
0
)
;
free_irq
(
IRQ_I2C
,
dev
);
i2c_davinci_dev
.
regs
->
icmdr
=
0
;
free_irq
(
IRQ_I2C
,
&
i2c_davinci_
dev
);
i2c_del_adapter
(
&
dev
->
adapter
);
mem
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
...
...
@@ -574,9 +504,8 @@ davinci_i2c_remove(struct platform_device *pdev)
static
struct
platform_driver
davinci_i2c_driver
=
{
.
probe
=
davinci_i2c_probe
,
.
remove
=
davinci_i2c_remove
,
.
driver
=
{
.
name
=
"i2c_davinci"
,
.
owner
=
THIS_MODULE
,
.
driver
=
{
.
name
=
(
char
*
)
driver_name
,
},
};
...
...
drivers/i2c/busses/i2c-davinci.h
0 → 100644
View file @
f7d41d35
/*
* linux/drivers/i2c/busses/davinci/i2c_davinci.h
*
* Copyright (C) 2006 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
* ----------------------------------------------------------------------------
Modifications:
ver. 1.0: Feb 2005, Vinod/Sudhakar
-
*
*/
#define DAVINCI_I2C_ICOAR_OADDR_MASK (0x03FFu)
#define DAVINCI_I2C_ICIMR_AAS_MASK (0x0040u)
#define DAVINCI_I2C_ICIMR_SCD_MASK (0x0020u)
#define DAVINCI_I2C_ICIMR_ICXRDY_MASK (0x0010u)
#define DAVINCI_I2C_ICIMR_ICRRDY_MASK (0x0008u)
#define DAVINCI_I2C_ICIMR_ARDY_MASK (0x0004u)
#define DAVINCI_I2C_ICIMR_NACK_MASK (0x0002u)
#define DAVINCI_I2C_ICIMR_AL_MASK (0x0001u)
#define DAVINCI_I2C_ICSTR_SDIR_MASK (0x4000u)
#define DAVINCI_I2C_ICSTR_NACKSNT_MASK (0x2000u)
#define DAVINCI_I2C_ICSTR_BB_MASK (0x1000u)
#define DAVINCI_I2C_ICSTR_RSFULL_MASK (0x0800u)
#define DAVINCI_I2C_ICSTR_XSMT_MASK (0x0400u)
#define DAVINCI_I2C_ICSTR_AAS_MASK (0x0200u)
#define DAVINCI_I2C_ICSTR_AD0_MASK (0x0100u)
#define DAVINCI_I2C_ICSTR_SCD_MASK (0x0020u)
#define DAVINCI_I2C_ICSTR_ICXRDY_MASK (0x0010u)
#define DAVINCI_I2C_ICSTR_ICRRDY_MASK (0x0008u)
#define DAVINCI_I2C_ICSTR_ARDY_MASK (0x0004u)
#define DAVINCI_I2C_ICSTR_NACK_MASK (0x0002u)
#define DAVINCI_I2C_ICSTR_AL_MASK (0x0001u)
#define DAVINCI_I2C_ICCLKL_ICCL_MASK (0xFFFFu)
#define DAVINCI_I2C_ICCLKH_ICCH_MASK (0xFFFFu)
#define DAVINCI_I2C_ICCNT_ICDC_MASK (0xFFFFu)
#define DAVINCI_I2C_ICDRR_D_MASK (0x00FFu)
#define DAVINCI_I2C_ICSAR_SADDR_MASK (0x03FFu)
#define DAVINCI_I2C_ICDXR_D_MASK (0x00FFu)
#define DAVINCI_I2C_ICMDR_NACKMOD_MASK (0x8000u)
#define DAVINCI_I2C_ICMDR_FREE_MASK (0x4000u)
#define DAVINCI_I2C_ICMDR_STT_MASK (0x2000u)
#define DAVINCI_I2C_ICMDR_STP_MASK (0x0800u)
#define DAVINCI_I2C_ICMDR_MST_MASK (0x0400u)
#define DAVINCI_I2C_ICMDR_TRX_MASK (0x0200u)
#define DAVINCI_I2C_ICMDR_XA_MASK (0x0100u)
#define DAVINCI_I2C_ICMDR_RM_MASK (0x0080u)
#define DAVINCI_I2C_ICMDR_DLB_MASK (0x0040u)
#define DAVINCI_I2C_ICMDR_IRS_MASK (0x0020u)
#define DAVINCI_I2C_ICMDR_STB_MASK (0x0010u)
#define DAVINCI_I2C_ICMDR_FDF_MASK (0x0008u)
#define DAVINCI_I2C_ICMDR_BC_MASK (0x0007u)
#define DAVINCI_I2C_ICIVR_TESTMD_MASK (0x0F00u)
#define DAVINCI_I2C_ICIVR_INTCODE_MASK (0x0007u)
#define DAVINCI_I2C_ICIVR_INTCODE_NONE (0x0000u)
#define DAVINCI_I2C_ICIVR_INTCODE_AL (0x0001u)
#define DAVINCI_I2C_ICIVR_INTCODE_NACK (0x0002u)
#define DAVINCI_I2C_ICIVR_INTCODE_RAR (0x0003u)
#define DAVINCI_I2C_ICIVR_INTCODE_RDR (0x0004u)
#define DAVINCI_I2C_ICIVR_INTCODE_TDR (0x0005u)
#define DAVINCI_I2C_ICIVR_INTCODE_SCD (0x0006u)
#define DAVINCI_I2C_ICIVR_INTCODE_AAS (0x0007u)
#define DAVINCI_I2C_ICEMDR_BCM_MASK (0x0001u)
#define DAVINCI_I2C_ICPSC_IPSC_MASK (0x00FFu)
#define DAVINCI_I2C_ICPID1_CLASS_MASK (0xFF00u)
#define DAVINCI_I2C_ICPID1_REVISION_MASK (0x00FFu)
#define DAVINCI_I2C_ICPID2_TYPE_MASK (0x00FFu)
#define DAVINCI_I2C_ICPFUNC_PFUNC_MASK (0x00000001u)
#define DAVINCI_I2C_ICPDIR_PDIR1_MASK (0x00000002u)
#define DAVINCI_I2C_ICPDIR_PDIR0_MASK (0x00000001u)
#define DAVINCI_I2C_ICPDIN_PDIN1_MASK (0x00000002u)
#define DAVINCI_I2C_ICPDIN_PDIN0_MASK (0x00000001u)
#define DAVINCI_I2C_ICPDOUT_PDOUT1_MASK (0x00000002u)
#define DAVINCI_I2C_ICPDOUT_PDOUT0_MASK (0x00000001u)
#define DAVINCI_I2C_ICPDSET_PDSET1_MASK (0x00000002u)
#define DAVINCI_I2C_ICPDSET_PDSET0_MASK (0x00000001u)
#define DAVINCI_I2C_ICPDCLR_PDCLR1_MASK (0x00000002u)
#define DAVINCI_I2C_ICPDCLR_PDCLR0_MASK (0x00000001u)
/**************************************************************************\
* Register Overlay Structure
\**************************************************************************/
typedef
struct
{
u16
icoar
;
u8
rsvd0
[
2
];
u16
icimr
;
u8
rsvd1
[
2
];
u16
icstr
;
u8
rsvd2
[
2
];
u16
icclkl
;
u8
rsvd3
[
2
];
u16
icclkh
;
u8
rsvd4
[
2
];
u16
iccnt
;
u8
rsvd5
[
2
];
u16
icdrr
;
u8
rsvd6
[
2
];
u16
icsar
;
u8
rsvd7
[
2
];
u16
icdxr
;
u8
rsvd8
[
2
];
u16
icmdr
;
u8
rsvd9
[
2
];
u16
icivr
;
u8
rsvd10
[
2
];
u16
icemdr
;
u8
rsvd11
[
2
];
u16
icpsc
;
u8
rsvd12
[
2
];
u16
icpid1
;
u8
rsvd13
[
2
];
u16
icpid2
;
u8
rsvd14
[
14
];
u32
ipcfunc
;
u32
icpdir
;
u32
icpdin
;
u32
icpdout
;
u32
icpdset
;
u32
icpdclr
;
}
davinci_i2cregs
;
/**************************************************************************\
* Overlay structure typedef definition
\**************************************************************************/
typedef
volatile
davinci_i2cregs
*
davinci_i2cregsovly
;
struct
i2c_davinci_device
{
int
cmd_err
;
struct
completion
cmd_complete
;
wait_queue_head_t
cmd_wait
;
u8
*
buf
;
size_t
buf_len
;
davinci_i2cregsovly
regs
;
int
irq
;
struct
i2c_adapter
adapter
;
struct
clk
*
clk
;
struct
device
*
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