-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
video: mb862xx: add support for controller's I2C bus adapter
Add adapter driver for I2C adapter in Coral-P(A)/Lime GDCs. So we can easily access devices on controller's I2C bus using i2c-dev interface. Signed-off-by: Anatolij Gustschin <agust@denx.de>
- Loading branch information
Anatolij Gustschin
committed
May 24, 2011
1 parent
12ed0c4
commit f8a6b1f
Showing
6 changed files
with
224 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
/* | ||
* Coral-P(A)/Lime I2C adapter driver | ||
* | ||
* (C) 2011 DENX Software Engineering, Anatolij Gustschin <agust@denx.de> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
* | ||
*/ | ||
|
||
#include <linux/fb.h> | ||
#include <linux/i2c.h> | ||
#include <linux/io.h> | ||
|
||
#include "mb862xxfb.h" | ||
#include "mb862xx_reg.h" | ||
|
||
static int mb862xx_i2c_wait_event(struct i2c_adapter *adap) | ||
{ | ||
struct mb862xxfb_par *par = adap->algo_data; | ||
u32 reg; | ||
|
||
do { | ||
udelay(1); | ||
reg = inreg(i2c, GC_I2C_BCR); | ||
if (reg & (I2C_INT | I2C_BER)) | ||
break; | ||
} while (1); | ||
|
||
return (reg & I2C_BER) ? 0 : 1; | ||
} | ||
|
||
static int mb862xx_i2c_do_address(struct i2c_adapter *adap, int addr) | ||
{ | ||
struct mb862xxfb_par *par = adap->algo_data; | ||
|
||
outreg(i2c, GC_I2C_DAR, addr); | ||
outreg(i2c, GC_I2C_CCR, I2C_CLOCK_AND_ENABLE); | ||
outreg(i2c, GC_I2C_BCR, par->i2c_rs ? I2C_REPEATED_START : I2C_START); | ||
if (!mb862xx_i2c_wait_event(adap)) | ||
return -EIO; | ||
par->i2c_rs = !(inreg(i2c, GC_I2C_BSR) & I2C_LRB); | ||
return par->i2c_rs; | ||
} | ||
|
||
static int mb862xx_i2c_write_byte(struct i2c_adapter *adap, u8 byte) | ||
{ | ||
struct mb862xxfb_par *par = adap->algo_data; | ||
|
||
outreg(i2c, GC_I2C_DAR, byte); | ||
outreg(i2c, GC_I2C_BCR, I2C_START); | ||
if (!mb862xx_i2c_wait_event(adap)) | ||
return -EIO; | ||
return !(inreg(i2c, GC_I2C_BSR) & I2C_LRB); | ||
} | ||
|
||
static int mb862xx_i2c_read_byte(struct i2c_adapter *adap, u8 *byte, int last) | ||
{ | ||
struct mb862xxfb_par *par = adap->algo_data; | ||
|
||
outreg(i2c, GC_I2C_BCR, I2C_START | (last ? 0 : I2C_ACK)); | ||
if (!mb862xx_i2c_wait_event(adap)) | ||
return 0; | ||
*byte = inreg(i2c, GC_I2C_DAR); | ||
return 1; | ||
} | ||
|
||
void mb862xx_i2c_stop(struct i2c_adapter *adap) | ||
{ | ||
struct mb862xxfb_par *par = adap->algo_data; | ||
|
||
outreg(i2c, GC_I2C_BCR, I2C_STOP); | ||
outreg(i2c, GC_I2C_CCR, I2C_DISABLE); | ||
par->i2c_rs = 0; | ||
} | ||
|
||
static int mb862xx_i2c_read(struct i2c_adapter *adap, struct i2c_msg *m) | ||
{ | ||
int i, ret = 0; | ||
int last = m->len - 1; | ||
|
||
for (i = 0; i < m->len; i++) { | ||
if (!mb862xx_i2c_read_byte(adap, &m->buf[i], i == last)) { | ||
ret = -EIO; | ||
break; | ||
} | ||
} | ||
return ret; | ||
} | ||
|
||
static int mb862xx_i2c_write(struct i2c_adapter *adap, struct i2c_msg *m) | ||
{ | ||
int i, ret = 0; | ||
|
||
for (i = 0; i < m->len; i++) { | ||
if (!mb862xx_i2c_write_byte(adap, m->buf[i])) { | ||
ret = -EIO; | ||
break; | ||
} | ||
} | ||
return ret; | ||
} | ||
|
||
static int mb862xx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, | ||
int num) | ||
{ | ||
struct mb862xxfb_par *par = adap->algo_data; | ||
struct i2c_msg *m; | ||
int addr; | ||
int i = 0, err = 0; | ||
|
||
dev_dbg(par->dev, "%s: %d msgs\n", __func__, num); | ||
|
||
for (i = 0; i < num; i++) { | ||
m = &msgs[i]; | ||
if (!m->len) { | ||
dev_dbg(par->dev, "%s: null msgs\n", __func__); | ||
continue; | ||
} | ||
addr = m->addr; | ||
if (m->flags & I2C_M_RD) | ||
addr |= 1; | ||
|
||
err = mb862xx_i2c_do_address(adap, addr); | ||
if (err < 0) | ||
break; | ||
if (m->flags & I2C_M_RD) | ||
err = mb862xx_i2c_read(adap, m); | ||
else | ||
err = mb862xx_i2c_write(adap, m); | ||
} | ||
|
||
if (i) | ||
mb862xx_i2c_stop(adap); | ||
|
||
return (err < 0) ? err : i; | ||
} | ||
|
||
static u32 mb862xx_func(struct i2c_adapter *adap) | ||
{ | ||
return I2C_FUNC_SMBUS_BYTE_DATA; | ||
} | ||
|
||
static const struct i2c_algorithm mb862xx_algo = { | ||
.master_xfer = mb862xx_xfer, | ||
.functionality = mb862xx_func, | ||
}; | ||
|
||
static struct i2c_adapter mb862xx_i2c_adapter = { | ||
.name = "MB862xx I2C adapter", | ||
.algo = &mb862xx_algo, | ||
.owner = THIS_MODULE, | ||
}; | ||
|
||
int mb862xx_i2c_init(struct mb862xxfb_par *par) | ||
{ | ||
int ret; | ||
|
||
mb862xx_i2c_adapter.algo_data = par; | ||
par->adap = &mb862xx_i2c_adapter; | ||
|
||
ret = i2c_add_adapter(par->adap); | ||
if (ret < 0) { | ||
dev_err(par->dev, "failed to add %s\n", | ||
mb862xx_i2c_adapter.name); | ||
} | ||
return ret; | ||
} | ||
|
||
void mb862xx_i2c_exit(struct mb862xxfb_par *par) | ||
{ | ||
if (par->adap) { | ||
i2c_del_adapter(par->adap); | ||
par->adap = NULL; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters