[PATCH v3 4/4] iio: accel: mma8452: Allow open drain interrupt pin configuration
Esben Haabendal <[email protected]>
| Newsgroups | org.kernel.vger.linux-iio,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
When sharing interrupt line with other chips, the interrupt pin most likely needs to be configured in open-drain mode instead of push-pull. The PP_OD bit in CTRL_REG3 is set when open-drain mode is configured, allowing sharing the interrupt line with other devices (with same interrupt polarity). The IRQF_SHARED flag is added to request_threaded_irq() flags, indicating that the interrupt line can be shared with other devices. Signed-off-by: Esben Haabendal <[email protected]> --- drivers/iio/accel/mma8452.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index 723ca3d9cb96..fa0915530f95 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -81,6 +81,8 @@ #define MMA8452_CTRL_REG2_RST BIT(6) #define MMA8452_CTRL_REG2_MODS_SHIFT 3 #define MMA8452_CTRL_REG2_MODS_MASK 0x1b +#define MMA8452_CTRL_REG3 0x2c +#define MMA8452_CTRL_REG3_PP_OD BIT(0) #define MMA8452_CTRL_REG4 0x2d #define MMA8452_CTRL_REG5 0x2e #define MMA8452_OFF_X 0x2f @@ -119,6 +121,7 @@ struct mma8452_data { int sleep_val; u8 ctrl_reg1; u8 data_cfg; + bool open_drain; }; /** @@ -647,6 +650,22 @@ static int mma8452_set_power_mode(struct mma8452_data *data, u8 mode) return mma8452_change_config(data, MMA8452_CTRL_REG2, reg); } +static int mma8452_set_interrupt_pin_mode(struct mma8452_data *data) +{ + int reg; + + reg = i2c_smbus_read_byte_data(data->client, MMA8452_CTRL_REG3); + if (reg < 0) + return reg; + + if (data->open_drain) + reg |= MMA8452_CTRL_REG3_PP_OD; + else + reg &= ~MMA8452_CTRL_REG3_PP_OD; + + return i2c_smbus_write_byte_data(data->client, MMA8452_CTRL_REG3, reg); +} + /* returns >0 if in freefall mode, 0 if not or <0 if an error occurred */ static int mma8452_freefall_mode_enabled(struct mma8452_data *data) { @@ -1667,6 +1686,11 @@ static int mma8452_probe(struct i2c_client *client) goto disable_regulators; } + data->open_drain = device_property_read_bool(&client->dev, "drive-open-drain"); + ret = mma8452_set_interrupt_pin_mode(data); + if (ret) + goto trigger_cleanup; + data->ctrl_reg1 = MMA8452_CTRL_ACTIVE | (MMA8452_CTRL_DR_DEFAULT << MMA8452_CTRL_DR_SHIFT); @@ -1688,7 +1712,7 @@ static int mma8452_probe(struct i2c_client *client) irq_flags = irq_get_trigger_type(client->irq); if (irq_flags == IRQ_TYPE_NONE) irq_flags = IRQF_TRIGGER_LOW; - irq_flags |= IRQF_ONESHOT; + irq_flags |= IRQF_ONESHOT | IRQF_SHARED; ret = request_threaded_irq(client->irq, NULL, mma8452_interrupt, irq_flags, client->name, indio_dev); if (ret) @@ -1806,6 +1830,10 @@ static int mma8452_runtime_resume(struct device *dev) return ret; } + ret = mma8452_set_interrupt_pin_mode(data); + if (ret) + goto runtime_resume_failed; + ret = mma8452_active(data); if (ret < 0) goto runtime_resume_failed; -- 2.55.0