Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c fixes from Wolfram Sang: "i2c has a bugfix and documentation improvements for you" * 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: Documentation: i2c: mention ACPI method for instantiating devices Documentation: i2c: describe devicetree method for instantiating devices i2c: mv64xxx: refactor message start to ensure proper initialization
This commit is contained in:
@@ -8,8 +8,8 @@ reason, the kernel code must instantiate I2C devices explicitly. There are
|
|||||||
several ways to achieve this, depending on the context and requirements.
|
several ways to achieve this, depending on the context and requirements.
|
||||||
|
|
||||||
|
|
||||||
Method 1: Declare the I2C devices by bus number
|
Method 1a: Declare the I2C devices by bus number
|
||||||
-----------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
This method is appropriate when the I2C bus is a system bus as is the case
|
This method is appropriate when the I2C bus is a system bus as is the case
|
||||||
for many embedded systems. On such systems, each I2C bus has a number
|
for many embedded systems. On such systems, each I2C bus has a number
|
||||||
@@ -51,6 +51,43 @@ The devices will be automatically unbound and destroyed when the I2C bus
|
|||||||
they sit on goes away (if ever.)
|
they sit on goes away (if ever.)
|
||||||
|
|
||||||
|
|
||||||
|
Method 1b: Declare the I2C devices via devicetree
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
This method has the same implications as method 1a. The declaration of I2C
|
||||||
|
devices is here done via devicetree as subnodes of the master controller.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
i2c1: i2c@400a0000 {
|
||||||
|
/* ... master properties skipped ... */
|
||||||
|
clock-frequency = <100000>;
|
||||||
|
|
||||||
|
flash@50 {
|
||||||
|
compatible = "atmel,24c256";
|
||||||
|
reg = <0x50>;
|
||||||
|
};
|
||||||
|
|
||||||
|
pca9532: gpio@60 {
|
||||||
|
compatible = "nxp,pca9532";
|
||||||
|
gpio-controller;
|
||||||
|
#gpio-cells = <2>;
|
||||||
|
reg = <0x60>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Here, two devices are attached to the bus using a speed of 100kHz. For
|
||||||
|
additional properties which might be needed to set up the device, please refer
|
||||||
|
to its devicetree documentation in Documentation/devicetree/bindings/.
|
||||||
|
|
||||||
|
|
||||||
|
Method 1c: Declare the I2C devices via ACPI
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
ACPI can also describe I2C devices. There is special documentation for this
|
||||||
|
which is currently located at Documentation/acpi/enumeration.txt.
|
||||||
|
|
||||||
|
|
||||||
Method 2: Instantiate the devices explicitly
|
Method 2: Instantiate the devices explicitly
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
|
@@ -97,7 +97,6 @@ enum {
|
|||||||
enum {
|
enum {
|
||||||
MV64XXX_I2C_ACTION_INVALID,
|
MV64XXX_I2C_ACTION_INVALID,
|
||||||
MV64XXX_I2C_ACTION_CONTINUE,
|
MV64XXX_I2C_ACTION_CONTINUE,
|
||||||
MV64XXX_I2C_ACTION_OFFLOAD_SEND_START,
|
|
||||||
MV64XXX_I2C_ACTION_SEND_START,
|
MV64XXX_I2C_ACTION_SEND_START,
|
||||||
MV64XXX_I2C_ACTION_SEND_RESTART,
|
MV64XXX_I2C_ACTION_SEND_RESTART,
|
||||||
MV64XXX_I2C_ACTION_OFFLOAD_RESTART,
|
MV64XXX_I2C_ACTION_OFFLOAD_RESTART,
|
||||||
@@ -204,6 +203,9 @@ static int mv64xxx_i2c_offload_msg(struct mv64xxx_i2c_data *drv_data)
|
|||||||
unsigned long ctrl_reg;
|
unsigned long ctrl_reg;
|
||||||
struct i2c_msg *msg = drv_data->msgs;
|
struct i2c_msg *msg = drv_data->msgs;
|
||||||
|
|
||||||
|
if (!drv_data->offload_enabled)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
drv_data->msg = msg;
|
drv_data->msg = msg;
|
||||||
drv_data->byte_posn = 0;
|
drv_data->byte_posn = 0;
|
||||||
drv_data->bytes_left = msg->len;
|
drv_data->bytes_left = msg->len;
|
||||||
@@ -433,8 +435,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
|
|||||||
|
|
||||||
drv_data->msgs++;
|
drv_data->msgs++;
|
||||||
drv_data->num_msgs--;
|
drv_data->num_msgs--;
|
||||||
if (!(drv_data->offload_enabled &&
|
if (mv64xxx_i2c_offload_msg(drv_data) < 0) {
|
||||||
mv64xxx_i2c_offload_msg(drv_data))) {
|
|
||||||
drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START;
|
drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START;
|
||||||
writel(drv_data->cntl_bits,
|
writel(drv_data->cntl_bits,
|
||||||
drv_data->reg_base + drv_data->reg_offsets.control);
|
drv_data->reg_base + drv_data->reg_offsets.control);
|
||||||
@@ -458,15 +459,14 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
|
|||||||
drv_data->reg_base + drv_data->reg_offsets.control);
|
drv_data->reg_base + drv_data->reg_offsets.control);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MV64XXX_I2C_ACTION_OFFLOAD_SEND_START:
|
|
||||||
if (!mv64xxx_i2c_offload_msg(drv_data))
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
drv_data->action = MV64XXX_I2C_ACTION_SEND_START;
|
|
||||||
/* FALLTHRU */
|
|
||||||
case MV64XXX_I2C_ACTION_SEND_START:
|
case MV64XXX_I2C_ACTION_SEND_START:
|
||||||
writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START,
|
/* Can we offload this msg ? */
|
||||||
drv_data->reg_base + drv_data->reg_offsets.control);
|
if (mv64xxx_i2c_offload_msg(drv_data) < 0) {
|
||||||
|
/* No, switch to standard path */
|
||||||
|
mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs);
|
||||||
|
writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START,
|
||||||
|
drv_data->reg_base + drv_data->reg_offsets.control);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MV64XXX_I2C_ACTION_SEND_ADDR_1:
|
case MV64XXX_I2C_ACTION_SEND_ADDR_1:
|
||||||
@@ -625,15 +625,10 @@ mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg,
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&drv_data->lock, flags);
|
spin_lock_irqsave(&drv_data->lock, flags);
|
||||||
if (drv_data->offload_enabled) {
|
|
||||||
drv_data->action = MV64XXX_I2C_ACTION_OFFLOAD_SEND_START;
|
|
||||||
drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND;
|
|
||||||
} else {
|
|
||||||
mv64xxx_i2c_prepare_for_io(drv_data, msg);
|
|
||||||
|
|
||||||
drv_data->action = MV64XXX_I2C_ACTION_SEND_START;
|
drv_data->action = MV64XXX_I2C_ACTION_SEND_START;
|
||||||
drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND;
|
drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND;
|
||||||
}
|
|
||||||
drv_data->send_stop = is_last;
|
drv_data->send_stop = is_last;
|
||||||
drv_data->block = 1;
|
drv_data->block = 1;
|
||||||
mv64xxx_i2c_do_action(drv_data);
|
mv64xxx_i2c_do_action(drv_data);
|
||||||
|
Reference in New Issue
Block a user