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
e7db443b
Commit
e7db443b
authored
May 24, 2010
by
Kevin Hilman
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'davinci-i2c' into davinci-reset
parents
042f6a50
96642b3d
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
251 additions
and
63 deletions
+251
-63
drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-davinci.c
+251
-63
No files found.
drivers/i2c/busses/i2c-davinci.c
View file @
e7db443b
...
@@ -36,14 +36,16 @@
...
@@ -36,14 +36,16 @@
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/cpufreq.h>
#include <linux/gpio.h>
#include <mach/hardware.h>
#include <mach/hardware.h>
#include <mach/i2c.h>
#include <mach/i2c.h>
/* ----- global defines ----------------------------------------------- */
/* ----- global defines ----------------------------------------------- */
#define DAVINCI_I2C_TIMEOUT (1*HZ)
#define DAVINCI_I2C_TIMEOUT (1*HZ)
#define DAVINCI_I2C_MAX_TRIES 2
#define I2C_DAVINCI_INTR_ALL (DAVINCI_I2C_IMR_AAS | \
#define I2C_DAVINCI_INTR_ALL (DAVINCI_I2C_IMR_AAS | \
DAVINCI_I2C_IMR_SCD | \
DAVINCI_I2C_IMR_SCD | \
DAVINCI_I2C_IMR_ARDY | \
DAVINCI_I2C_IMR_ARDY | \
...
@@ -72,37 +74,29 @@
...
@@ -72,37 +74,29 @@
#define DAVINCI_I2C_IVR_NACK 0x02
#define DAVINCI_I2C_IVR_NACK 0x02
#define DAVINCI_I2C_IVR_AL 0x01
#define DAVINCI_I2C_IVR_AL 0x01
#define DAVINCI_I2C_STR_BB (1 << 12)
#define DAVINCI_I2C_STR_BB BIT(12)
#define DAVINCI_I2C_STR_RSFULL (1 << 11)
#define DAVINCI_I2C_STR_RSFULL BIT(11)
#define DAVINCI_I2C_STR_SCD (1 << 5)
#define DAVINCI_I2C_STR_SCD BIT(5)
#define DAVINCI_I2C_STR_ARDY (1 << 2)
#define DAVINCI_I2C_STR_ARDY BIT(2)
#define DAVINCI_I2C_STR_NACK (1 << 1)
#define DAVINCI_I2C_STR_NACK BIT(1)
#define DAVINCI_I2C_STR_AL (1 << 0)
#define DAVINCI_I2C_STR_AL BIT(0)
#define DAVINCI_I2C_MDR_NACK (1 << 15)
#define DAVINCI_I2C_MDR_NACK BIT(15)
#define DAVINCI_I2C_MDR_STT (1 << 13)
#define DAVINCI_I2C_MDR_STT BIT(13)
#define DAVINCI_I2C_MDR_STP (1 << 11)
#define DAVINCI_I2C_MDR_STP BIT(11)
#define DAVINCI_I2C_MDR_MST (1 << 10)
#define DAVINCI_I2C_MDR_MST BIT(10)
#define DAVINCI_I2C_MDR_TRX (1 << 9)
#define DAVINCI_I2C_MDR_TRX BIT(9)
#define DAVINCI_I2C_MDR_XA (1 << 8)
#define DAVINCI_I2C_MDR_XA BIT(8)
#define DAVINCI_I2C_MDR_RM (1 << 7)
#define DAVINCI_I2C_MDR_RM BIT(7)
#define DAVINCI_I2C_MDR_IRS (1 << 5)
#define DAVINCI_I2C_MDR_IRS BIT(5)
#define DAVINCI_I2C_IMR_AAS (1 << 6)
#define DAVINCI_I2C_IMR_AAS BIT(6)
#define DAVINCI_I2C_IMR_SCD (1 << 5)
#define DAVINCI_I2C_IMR_SCD BIT(5)
#define DAVINCI_I2C_IMR_XRDY (1 << 4)
#define DAVINCI_I2C_IMR_XRDY BIT(4)
#define DAVINCI_I2C_IMR_RRDY (1 << 3)
#define DAVINCI_I2C_IMR_RRDY BIT(3)
#define DAVINCI_I2C_IMR_ARDY (1 << 2)
#define DAVINCI_I2C_IMR_ARDY BIT(2)
#define DAVINCI_I2C_IMR_NACK (1 << 1)
#define DAVINCI_I2C_IMR_NACK BIT(1)
#define DAVINCI_I2C_IMR_AL (1 << 0)
#define DAVINCI_I2C_IMR_AL BIT(0)
#define MOD_REG_BIT(val, mask, set) do { \
if (set) { \
val |= mask; \
} else { \
val &= ~mask; \
} \
} while (0)
struct
davinci_i2c_dev
{
struct
davinci_i2c_dev
{
struct
device
*
dev
;
struct
device
*
dev
;
...
@@ -113,8 +107,13 @@ struct davinci_i2c_dev {
...
@@ -113,8 +107,13 @@ struct davinci_i2c_dev {
u8
*
buf
;
u8
*
buf
;
size_t
buf_len
;
size_t
buf_len
;
int
irq
;
int
irq
;
int
stop
;
u8
terminate
;
u8
terminate
;
struct
i2c_adapter
adapter
;
struct
i2c_adapter
adapter
;
#ifdef CONFIG_CPU_FREQ
struct
completion
xfr_complete
;
struct
notifier_block
freq_transition
;
#endif
};
};
/* default platform data to use if not supplied in the platform_device */
/* default platform data to use if not supplied in the platform_device */
...
@@ -134,12 +133,59 @@ static inline u16 davinci_i2c_read_reg(struct davinci_i2c_dev *i2c_dev, int reg)
...
@@ -134,12 +133,59 @@ static inline u16 davinci_i2c_read_reg(struct davinci_i2c_dev *i2c_dev, int reg)
return
__raw_readw
(
i2c_dev
->
base
+
reg
);
return
__raw_readw
(
i2c_dev
->
base
+
reg
);
}
}
/*
/* Generate a pulse on the i2c clock pin. */
* This functions configures I2C and brings I2C out of reset.
static
void
generic_i2c_clock_pulse
(
unsigned
int
scl_pin
)
* This function is called during I2C init function. This function
{
* also gets called if I2C encounters any errors.
u16
i
;
if
(
scl_pin
)
{
/* Send high and low on the SCL line */
for
(
i
=
0
;
i
<
9
;
i
++
)
{
gpio_set_value
(
scl_pin
,
0
);
udelay
(
20
);
gpio_set_value
(
scl_pin
,
1
);
udelay
(
20
);
}
}
}
/* This routine does i2c bus recovery as specified in the
* i2c protocol Rev. 03 section 3.16 titled "Bus clear"
*/
*/
static
int
i2c_davinci_init
(
struct
davinci_i2c_dev
*
dev
)
static
void
i2c_recover_bus
(
struct
davinci_i2c_dev
*
dev
)
{
u32
flag
=
0
;
struct
davinci_i2c_platform_data
*
pdata
=
dev
->
dev
->
platform_data
;
dev_err
(
dev
->
dev
,
"initiating i2c bus recovery
\n
"
);
/* Send NACK to the slave */
flag
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_MDR_REG
);
flag
|=
DAVINCI_I2C_MDR_NACK
;
/* write the data into mode register */
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_MDR_REG
,
flag
);
if
(
pdata
)
generic_i2c_clock_pulse
(
pdata
->
scl_pin
);
/* Send STOP */
flag
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_MDR_REG
);
flag
|=
DAVINCI_I2C_MDR_STP
;
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_MDR_REG
,
flag
);
}
static
inline
void
davinci_i2c_reset_ctrl
(
struct
davinci_i2c_dev
*
i2c_dev
,
int
val
)
{
u16
w
;
w
=
davinci_i2c_read_reg
(
i2c_dev
,
DAVINCI_I2C_MDR_REG
);
if
(
!
val
)
/* put I2C into reset */
w
&=
~
DAVINCI_I2C_MDR_IRS
;
else
/* take I2C out of reset */
w
|=
DAVINCI_I2C_MDR_IRS
;
davinci_i2c_write_reg
(
i2c_dev
,
DAVINCI_I2C_MDR_REG
,
w
);
}
static
void
i2c_davinci_calc_clk_dividers
(
struct
davinci_i2c_dev
*
dev
)
{
{
struct
davinci_i2c_platform_data
*
pdata
=
dev
->
dev
->
platform_data
;
struct
davinci_i2c_platform_data
*
pdata
=
dev
->
dev
->
platform_data
;
u16
psc
;
u16
psc
;
...
@@ -148,15 +194,6 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
...
@@ -148,15 +194,6 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
u32
clkh
;
u32
clkh
;
u32
clkl
;
u32
clkl
;
u32
input_clock
=
clk_get_rate
(
dev
->
clk
);
u32
input_clock
=
clk_get_rate
(
dev
->
clk
);
u16
w
;
if
(
!
pdata
)
pdata
=
&
davinci_i2c_platform_data_default
;
/* 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
);
/* NOTE: I2C Clock divider programming info
/* NOTE: I2C Clock divider programming info
* As per I2C specs the following formulas provide prescaler
* As per I2C specs the following formulas provide prescaler
...
@@ -188,12 +225,32 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
...
@@ -188,12 +225,32 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_CLKH_REG
,
clkh
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_CLKH_REG
,
clkh
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_CLKL_REG
,
clkl
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_CLKL_REG
,
clkl
);
dev_dbg
(
dev
->
dev
,
"input_clock = %d, CLK = %d
\n
"
,
input_clock
,
clk
);
}
/*
* This function configures I2C and brings I2C out of reset.
* This function is called during I2C init function. This function
* also gets called if I2C encounters any errors.
*/
static
int
i2c_davinci_init
(
struct
davinci_i2c_dev
*
dev
)
{
struct
davinci_i2c_platform_data
*
pdata
=
dev
->
dev
->
platform_data
;
if
(
!
pdata
)
pdata
=
&
davinci_i2c_platform_data_default
;
/* put I2C into reset */
davinci_i2c_reset_ctrl
(
dev
,
0
);
/* compute clock dividers */
i2c_davinci_calc_clk_dividers
(
dev
);
/* Respond at reserved "SMBus Host" slave address" (and zero);
/* Respond at reserved "SMBus Host" slave address" (and zero);
* we seem to have no option to not respond...
* we seem to have no option to not respond...
*/
*/
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_OAR_REG
,
0x08
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_OAR_REG
,
0x08
);
dev_dbg
(
dev
->
dev
,
"input_clock = %d, CLK = %d
\n
"
,
input_clock
,
clk
);
dev_dbg
(
dev
->
dev
,
"PSC = %d
\n
"
,
dev_dbg
(
dev
->
dev
,
"PSC = %d
\n
"
,
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_PSC_REG
));
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_PSC_REG
));
dev_dbg
(
dev
->
dev
,
"CLKL = %d
\n
"
,
dev_dbg
(
dev
->
dev
,
"CLKL = %d
\n
"
,
...
@@ -204,9 +261,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
...
@@ -204,9 +261,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
pdata
->
bus_freq
,
pdata
->
bus_delay
);
pdata
->
bus_freq
,
pdata
->
bus_delay
);
/* Take the I2C module out of reset: */
/* Take the I2C module out of reset: */
w
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_MDR_REG
);
davinci_i2c_reset_ctrl
(
dev
,
1
);
MOD_REG_BIT
(
w
,
DAVINCI_I2C_MDR_IRS
,
1
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_MDR_REG
,
w
);
/* Enable interrupts */
/* Enable interrupts */
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_IMR_REG
,
I2C_DAVINCI_INTR_ALL
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_IMR_REG
,
I2C_DAVINCI_INTR_ALL
);
...
@@ -221,14 +276,22 @@ static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev,
...
@@ -221,14 +276,22 @@ static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev,
char
allow_sleep
)
char
allow_sleep
)
{
{
unsigned
long
timeout
;
unsigned
long
timeout
;
static
u16
to_cnt
;
timeout
=
jiffies
+
dev
->
adapter
.
timeout
;
timeout
=
jiffies
+
dev
->
adapter
.
timeout
;
while
(
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_STR_REG
)
while
(
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_STR_REG
)
&
DAVINCI_I2C_STR_BB
)
{
&
DAVINCI_I2C_STR_BB
)
{
if
(
to_cnt
<=
DAVINCI_I2C_MAX_TRIES
)
{
if
(
time_after
(
jiffies
,
timeout
))
{
if
(
time_after
(
jiffies
,
timeout
))
{
dev_warn
(
dev
->
dev
,
dev_warn
(
dev
->
dev
,
"timeout waiting for bus ready
\n
"
);
"timeout waiting for bus ready
\n
"
);
to_cnt
++
;
return
-
ETIMEDOUT
;
return
-
ETIMEDOUT
;
}
else
{
to_cnt
=
0
;
i2c_recover_bus
(
dev
);
i2c_davinci_init
(
dev
);
}
}
}
if
(
allow_sleep
)
if
(
allow_sleep
)
schedule_timeout
(
1
);
schedule_timeout
(
1
);
...
@@ -250,9 +313,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
...
@@ -250,9 +313,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
u16
w
;
u16
w
;
int
r
;
int
r
;
if
(
msg
->
len
==
0
)
return
-
EINVAL
;
if
(
!
pdata
)
if
(
!
pdata
)
pdata
=
&
davinci_i2c_platform_data_default
;
pdata
=
&
davinci_i2c_platform_data_default
;
/* Introduce a delay, required for some boards (e.g Davinci EVM) */
/* Introduce a delay, required for some boards (e.g Davinci EVM) */
...
@@ -264,6 +324,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
...
@@ -264,6 +324,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
dev
->
buf
=
msg
->
buf
;
dev
->
buf
=
msg
->
buf
;
dev
->
buf_len
=
msg
->
len
;
dev
->
buf_len
=
msg
->
len
;
dev
->
stop
=
stop
;
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_CNT_REG
,
dev
->
buf_len
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_CNT_REG
,
dev
->
buf_len
);
...
@@ -281,23 +342,40 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
...
@@ -281,23 +342,40 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
flag
|=
DAVINCI_I2C_MDR_TRX
;
flag
|=
DAVINCI_I2C_MDR_TRX
;
if
(
stop
)
if
(
stop
)
flag
|=
DAVINCI_I2C_MDR_STP
;
flag
|=
DAVINCI_I2C_MDR_STP
;
if
(
msg
->
len
==
0
)
{
flag
|=
DAVINCI_I2C_MDR_RM
;
flag
&=
~
DAVINCI_I2C_MDR_STP
;
}
/* Enable receive or transmit interrupts */
/* Enable receive or transmit interrupts */
w
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_IMR_REG
);
w
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_IMR_REG
);
if
(
msg
->
flags
&
I2C_M_RD
)
if
(
msg
->
flags
&
I2C_M_RD
)
MOD_REG_BIT
(
w
,
DAVINCI_I2C_IMR_RRDY
,
1
)
;
w
|=
DAVINCI_I2C_IMR_RRDY
;
else
else
MOD_REG_BIT
(
w
,
DAVINCI_I2C_IMR_XRDY
,
1
)
;
w
|=
DAVINCI_I2C_IMR_XRDY
;
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_IMR_REG
,
w
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_IMR_REG
,
w
);
dev
->
terminate
=
0
;
dev
->
terminate
=
0
;
/* write the data into mode register */
/* write the data into mode register */
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_MDR_REG
,
flag
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_MDR_REG
,
flag
);
/*
* First byte should be set here, not after interrupt,
* because transmit-data-ready interrupt can come before
* NACK-interrupt during sending of previous message and
* ICDXR may have wrong data
*/
if
((
!
(
msg
->
flags
&
I2C_M_RD
))
&&
dev
->
buf_len
)
{
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_DXR_REG
,
*
dev
->
buf
++
);
dev
->
buf_len
--
;
}
r
=
wait_for_completion_interruptible_timeout
(
&
dev
->
cmd_complete
,
r
=
wait_for_completion_interruptible_timeout
(
&
dev
->
cmd_complete
,
dev
->
adapter
.
timeout
);
dev
->
adapter
.
timeout
);
if
(
r
==
0
)
{
if
(
r
==
0
)
{
dev_err
(
dev
->
dev
,
"controller timed out
\n
"
);
dev_err
(
dev
->
dev
,
"controller timed out
\n
"
);
i2c_recover_bus
(
dev
);
i2c_davinci_init
(
dev
);
i2c_davinci_init
(
dev
);
dev
->
buf_len
=
0
;
dev
->
buf_len
=
0
;
return
-
ETIMEDOUT
;
return
-
ETIMEDOUT
;
...
@@ -334,7 +412,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
...
@@ -334,7 +412,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
return
msg
->
len
;
return
msg
->
len
;
if
(
stop
)
{
if
(
stop
)
{
w
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_MDR_REG
);
w
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_MDR_REG
);
MOD_REG_BIT
(
w
,
DAVINCI_I2C_MDR_STP
,
1
)
;
w
|=
DAVINCI_I2C_MDR_STP
;
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_MDR_REG
,
w
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_MDR_REG
,
w
);
}
}
return
-
EREMOTEIO
;
return
-
EREMOTEIO
;
...
@@ -367,12 +445,17 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
...
@@ -367,12 +445,17 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
}
}
#ifdef CONFIG_CPU_FREQ
complete
(
&
dev
->
xfr_complete
);
#endif
return
num
;
return
num
;
}
}
static
u32
i2c_davinci_func
(
struct
i2c_adapter
*
adap
)
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
;
}
}
static
void
terminate_read
(
struct
davinci_i2c_dev
*
dev
)
static
void
terminate_read
(
struct
davinci_i2c_dev
*
dev
)
...
@@ -431,6 +514,14 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
...
@@ -431,6 +514,14 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
case
DAVINCI_I2C_IVR_ARDY
:
case
DAVINCI_I2C_IVR_ARDY
:
davinci_i2c_write_reg
(
dev
,
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_STR_REG
,
DAVINCI_I2C_STR_ARDY
);
DAVINCI_I2C_STR_REG
,
DAVINCI_I2C_STR_ARDY
);
if
(((
dev
->
buf_len
==
0
)
&&
(
dev
->
stop
!=
0
))
||
(
dev
->
cmd_err
&
DAVINCI_I2C_STR_NACK
))
{
w
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_MDR_REG
);
w
|=
DAVINCI_I2C_MDR_STP
;
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_MDR_REG
,
w
);
}
complete
(
&
dev
->
cmd_complete
);
complete
(
&
dev
->
cmd_complete
);
break
;
break
;
...
@@ -462,7 +553,7 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
...
@@ -462,7 +553,7 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
w
=
davinci_i2c_read_reg
(
dev
,
w
=
davinci_i2c_read_reg
(
dev
,
DAVINCI_I2C_IMR_REG
);
DAVINCI_I2C_IMR_REG
);
MOD_REG_BIT
(
w
,
DAVINCI_I2C_IMR_XRDY
,
0
)
;
w
&=
~
DAVINCI_I2C_IMR_XRDY
;
davinci_i2c_write_reg
(
dev
,
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_IMR_REG
,
DAVINCI_I2C_IMR_REG
,
w
);
w
);
...
@@ -491,6 +582,48 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
...
@@ -491,6 +582,48 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
return
count
?
IRQ_HANDLED
:
IRQ_NONE
;
return
count
?
IRQ_HANDLED
:
IRQ_NONE
;
}
}
#ifdef CONFIG_CPU_FREQ
static
int
i2c_davinci_cpufreq_transition
(
struct
notifier_block
*
nb
,
unsigned
long
val
,
void
*
data
)
{
struct
davinci_i2c_dev
*
dev
;
dev
=
container_of
(
nb
,
struct
davinci_i2c_dev
,
freq_transition
);
if
(
val
==
CPUFREQ_PRECHANGE
)
{
wait_for_completion
(
&
dev
->
xfr_complete
);
davinci_i2c_reset_ctrl
(
dev
,
0
);
}
else
if
(
val
==
CPUFREQ_POSTCHANGE
)
{
i2c_davinci_calc_clk_dividers
(
dev
);
davinci_i2c_reset_ctrl
(
dev
,
1
);
}
return
0
;
}
static
inline
int
i2c_davinci_cpufreq_register
(
struct
davinci_i2c_dev
*
dev
)
{
dev
->
freq_transition
.
notifier_call
=
i2c_davinci_cpufreq_transition
;
return
cpufreq_register_notifier
(
&
dev
->
freq_transition
,
CPUFREQ_TRANSITION_NOTIFIER
);
}
static
inline
void
i2c_davinci_cpufreq_deregister
(
struct
davinci_i2c_dev
*
dev
)
{
cpufreq_unregister_notifier
(
&
dev
->
freq_transition
,
CPUFREQ_TRANSITION_NOTIFIER
);
}
#else
static
inline
int
i2c_davinci_cpufreq_register
(
struct
davinci_i2c_dev
*
dev
)
{
return
0
;
}
static
inline
void
i2c_davinci_cpufreq_deregister
(
struct
davinci_i2c_dev
*
dev
)
{
}
#endif
static
struct
i2c_algorithm
i2c_davinci_algo
=
{
static
struct
i2c_algorithm
i2c_davinci_algo
=
{
.
master_xfer
=
i2c_davinci_xfer
,
.
master_xfer
=
i2c_davinci_xfer
,
.
functionality
=
i2c_davinci_func
,
.
functionality
=
i2c_davinci_func
,
...
@@ -530,6 +663,9 @@ static int davinci_i2c_probe(struct platform_device *pdev)
...
@@ -530,6 +663,9 @@ static int davinci_i2c_probe(struct platform_device *pdev)
}
}
init_completion
(
&
dev
->
cmd_complete
);
init_completion
(
&
dev
->
cmd_complete
);
#ifdef CONFIG_CPU_FREQ
init_completion
(
&
dev
->
xfr_complete
);
#endif
dev
->
dev
=
get_device
(
&
pdev
->
dev
);
dev
->
dev
=
get_device
(
&
pdev
->
dev
);
dev
->
irq
=
irq
->
start
;
dev
->
irq
=
irq
->
start
;
platform_set_drvdata
(
pdev
,
dev
);
platform_set_drvdata
(
pdev
,
dev
);
...
@@ -541,7 +677,12 @@ static int davinci_i2c_probe(struct platform_device *pdev)
...
@@ -541,7 +677,12 @@ static int davinci_i2c_probe(struct platform_device *pdev)
}
}
clk_enable
(
dev
->
clk
);
clk_enable
(
dev
->
clk
);
dev
->
base
=
(
void
__iomem
*
)
IO_ADDRESS
(
mem
->
start
);
dev
->
base
=
ioremap
(
mem
->
start
,
resource_size
(
mem
));
if
(
!
dev
->
base
)
{
r
=
-
EBUSY
;
goto
err_mem_ioremap
;
}
i2c_davinci_init
(
dev
);
i2c_davinci_init
(
dev
);
r
=
request_irq
(
dev
->
irq
,
i2c_davinci_isr
,
0
,
pdev
->
name
,
dev
);
r
=
request_irq
(
dev
->
irq
,
i2c_davinci_isr
,
0
,
pdev
->
name
,
dev
);
...
@@ -550,6 +691,12 @@ static int davinci_i2c_probe(struct platform_device *pdev)
...
@@ -550,6 +691,12 @@ static int davinci_i2c_probe(struct platform_device *pdev)
goto
err_unuse_clocks
;
goto
err_unuse_clocks
;
}
}
r
=
i2c_davinci_cpufreq_register
(
dev
);
if
(
r
)
{
dev_err
(
&
pdev
->
dev
,
"failed to register cpufreq
\n
"
);
goto
err_free_irq
;
}
adap
=
&
dev
->
adapter
;
adap
=
&
dev
->
adapter
;
i2c_set_adapdata
(
adap
,
dev
);
i2c_set_adapdata
(
adap
,
dev
);
adap
->
owner
=
THIS_MODULE
;
adap
->
owner
=
THIS_MODULE
;
...
@@ -571,6 +718,8 @@ static int davinci_i2c_probe(struct platform_device *pdev)
...
@@ -571,6 +718,8 @@ static int davinci_i2c_probe(struct platform_device *pdev)
err_free_irq:
err_free_irq:
free_irq
(
dev
->
irq
,
dev
);
free_irq
(
dev
->
irq
,
dev
);
err_unuse_clocks:
err_unuse_clocks:
iounmap
(
dev
->
base
);
err_mem_ioremap:
clk_disable
(
dev
->
clk
);
clk_disable
(
dev
->
clk
);
clk_put
(
dev
->
clk
);
clk_put
(
dev
->
clk
);
dev
->
clk
=
NULL
;
dev
->
clk
=
NULL
;
...
@@ -589,6 +738,8 @@ static int davinci_i2c_remove(struct platform_device *pdev)
...
@@ -589,6 +738,8 @@ static int davinci_i2c_remove(struct platform_device *pdev)
struct
davinci_i2c_dev
*
dev
=
platform_get_drvdata
(
pdev
);
struct
davinci_i2c_dev
*
dev
=
platform_get_drvdata
(
pdev
);
struct
resource
*
mem
;
struct
resource
*
mem
;
i2c_davinci_cpufreq_deregister
(
dev
);
platform_set_drvdata
(
pdev
,
NULL
);
platform_set_drvdata
(
pdev
,
NULL
);
i2c_del_adapter
(
&
dev
->
adapter
);
i2c_del_adapter
(
&
dev
->
adapter
);
put_device
(
&
pdev
->
dev
);
put_device
(
&
pdev
->
dev
);
...
@@ -599,6 +750,7 @@ static int davinci_i2c_remove(struct platform_device *pdev)
...
@@ -599,6 +750,7 @@ static int davinci_i2c_remove(struct platform_device *pdev)
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_MDR_REG
,
0
);
davinci_i2c_write_reg
(
dev
,
DAVINCI_I2C_MDR_REG
,
0
);
free_irq
(
IRQ_I2C
,
dev
);
free_irq
(
IRQ_I2C
,
dev
);
iounmap
(
dev
->
base
);
kfree
(
dev
);
kfree
(
dev
);
mem
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
mem
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
...
@@ -606,6 +758,41 @@ static int davinci_i2c_remove(struct platform_device *pdev)
...
@@ -606,6 +758,41 @@ static int davinci_i2c_remove(struct platform_device *pdev)
return
0
;
return
0
;
}
}
#ifdef CONFIG_PM
static
int
davinci_i2c_suspend
(
struct
device
*
dev
)
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
davinci_i2c_dev
*
i2c_dev
=
platform_get_drvdata
(
pdev
);
/* put I2C into reset */
davinci_i2c_reset_ctrl
(
i2c_dev
,
0
);
clk_disable
(
i2c_dev
->
clk
);
return
0
;
}
static
int
davinci_i2c_resume
(
struct
device
*
dev
)
{
struct
platform_device
*
pdev
=
to_platform_device
(
dev
);
struct
davinci_i2c_dev
*
i2c_dev
=
platform_get_drvdata
(
pdev
);
clk_enable
(
i2c_dev
->
clk
);
/* take I2C out of reset */
davinci_i2c_reset_ctrl
(
i2c_dev
,
1
);
return
0
;
}
static
const
struct
dev_pm_ops
davinci_i2c_pm
=
{
.
suspend
=
davinci_i2c_suspend
,
.
resume
=
davinci_i2c_resume
,
};
#define davinci_i2c_pm_ops (&davinci_i2c_pm)
#else
#define davinci_i2c_pm_ops NULL
#endif
/* work with hotplug and coldplug */
/* work with hotplug and coldplug */
MODULE_ALIAS
(
"platform:i2c_davinci"
);
MODULE_ALIAS
(
"platform:i2c_davinci"
);
...
@@ -615,6 +802,7 @@ static struct platform_driver davinci_i2c_driver = {
...
@@ -615,6 +802,7 @@ static struct platform_driver davinci_i2c_driver = {
.
driver
=
{
.
driver
=
{
.
name
=
"i2c_davinci"
,
.
name
=
"i2c_davinci"
,
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
.
pm
=
davinci_i2c_pm_ops
,
},
},
};
};
...
...
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