2020-11-20 16:17:35

by Jacopo Mondi

[permalink] [raw]
Subject: [PATCH 0/2] media: max9271: Fix GPIO handling

While working on RDACM21 camera integration I found the GPIO handling
code in the max9271 library driver had a few bugs, that went un-noticed
when the library has been used to upstream RDACM20 as the GPIO lines are
not explicitly enabled.

Fix the GPIO handling code in the max9271 library driver and make rdacm20
a little more robust by enabling the GPIO1 line explicitly.

Tested on H3 Salvator-X with MAXIM GMLS expansion board.

Thanks
j

Jacopo Mondi (2):
media: max9271: Fix GPIO enable/disable
media: rdacm20: Enable GPIO1 explicitly

drivers/media/i2c/max9271.c | 8 ++++----
drivers/media/i2c/rdacm20.c | 13 +++++++++++--
2 files changed, 15 insertions(+), 6 deletions(-)

--
2.29.1


2020-11-20 16:18:06

by Jacopo Mondi

[permalink] [raw]
Subject: [PATCH 1/2] media: max9271: Fix GPIO enable/disable

Fix GPIO enable/disable operations which wrongly read the 0x0f register
to obtain the current mask of the enabled lines instead of using
the correct 0x0e register.

Also fix access to bit 0 of the register which is marked as reserved.

Fixes: 34009bffc1c6 ("media: i2c: Add RDACM20 driver")
Signed-off-by: Jacopo Mondi <[email protected]>
---
drivers/media/i2c/max9271.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/media/i2c/max9271.c b/drivers/media/i2c/max9271.c
index 0f6f7a092a46..c247db569bab 100644
--- a/drivers/media/i2c/max9271.c
+++ b/drivers/media/i2c/max9271.c
@@ -223,12 +223,12 @@ int max9271_enable_gpios(struct max9271_device *dev, u8 gpio_mask)
{
int ret;

- ret = max9271_read(dev, 0x0f);
+ ret = max9271_read(dev, 0x0e);
if (ret < 0)
return 0;

/* BIT(0) reserved: GPO is always enabled. */
- ret |= gpio_mask | BIT(0);
+ ret |= (gpio_mask & ~BIT(0));
ret = max9271_write(dev, 0x0e, ret);
if (ret < 0) {
dev_err(&dev->client->dev, "Failed to enable gpio (%d)\n", ret);
@@ -245,12 +245,12 @@ int max9271_disable_gpios(struct max9271_device *dev, u8 gpio_mask)
{
int ret;

- ret = max9271_read(dev, 0x0f);
+ ret = max9271_read(dev, 0x0e);
if (ret < 0)
return 0;

/* BIT(0) reserved: GPO cannot be disabled */
- ret &= (~gpio_mask | BIT(0));
+ ret &= ~(gpio_mask | BIT(0));
ret = max9271_write(dev, 0x0e, ret);
if (ret < 0) {
dev_err(&dev->client->dev, "Failed to disable gpio (%d)\n", ret);
--
2.29.1

2020-11-20 16:19:56

by Jacopo Mondi

[permalink] [raw]
Subject: [PATCH 2/2] media: rdacm20: Enable GPIO1 explicitly

The MAX9271 GPIO1 line that controls the sensor reset is by default
enabled after a serializer chip reset.

As rdacm20 does not go through an explicit serializer reset, make sure
GPIO1 is enabled to make the camera module driver more robust.

Fixes: 34009bffc1c6 ("media: i2c: Add RDACM20 driver")
Signed-off-by: Jacopo Mondi <[email protected]>
---
drivers/media/i2c/rdacm20.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/media/i2c/rdacm20.c b/drivers/media/i2c/rdacm20.c
index 1ed928c4ca70..16bcb764b0e0 100644
--- a/drivers/media/i2c/rdacm20.c
+++ b/drivers/media/i2c/rdacm20.c
@@ -487,9 +487,18 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
* Reset the sensor by cycling the OV10635 reset signal connected to the
* MAX9271 GPIO1 and verify communication with the OV10635.
*/
- max9271_clear_gpios(dev->serializer, MAX9271_GPIO1OUT);
+ ret = max9271_enable_gpios(dev->serializer, MAX9271_GPIO1OUT);
+ if (ret)
+ return ret;
+
+ ret = max9271_clear_gpios(dev->serializer, MAX9271_GPIO1OUT);
+ if (ret)
+ return ret;
usleep_range(10000, 15000);
- max9271_set_gpios(dev->serializer, MAX9271_GPIO1OUT);
+
+ ret = max9271_set_gpios(dev->serializer, MAX9271_GPIO1OUT);
+ if (ret)
+ return ret;
usleep_range(10000, 15000);

again:
--
2.29.1

2020-11-20 19:17:19

by Geert Uytterhoeven

[permalink] [raw]
Subject: Re: [PATCH 1/2] media: max9271: Fix GPIO enable/disable

On Fri, Nov 20, 2020 at 5:15 PM Jacopo Mondi <[email protected]> wrote:
> Fix GPIO enable/disable operations which wrongly read the 0x0f register
> to obtain the current mask of the enabled lines instead of using
> the correct 0x0e register.
>
> Also fix access to bit 0 of the register which is marked as reserved.
>
> Fixes: 34009bffc1c6 ("media: i2c: Add RDACM20 driver")
> Signed-off-by: Jacopo Mondi <[email protected]>

Reviewed-by: Geert Uytterhoeven <[email protected]>

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected]

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

2020-11-23 14:17:36

by Kieran Bingham

[permalink] [raw]
Subject: Re: [PATCH 1/2] media: max9271: Fix GPIO enable/disable

Hi Jacopo,

On 20/11/2020 16:15, Jacopo Mondi wrote:
> Fix GPIO enable/disable operations which wrongly read the 0x0f register
> to obtain the current mask of the enabled lines instead of using
> the correct 0x0e register.
>
> Also fix access to bit 0 of the register which is marked as reserved.
>
> Fixes: 34009bffc1c6 ("media: i2c: Add RDACM20 driver")
> Signed-off-by: Jacopo Mondi <[email protected]>

Took me a few reads of this and the datasheet to be sure :S

But now I am :-D

Reviewed-by: Kieran Bingham <[email protected]>

> ---
> drivers/media/i2c/max9271.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/media/i2c/max9271.c b/drivers/media/i2c/max9271.c
> index 0f6f7a092a46..c247db569bab 100644
> --- a/drivers/media/i2c/max9271.c
> +++ b/drivers/media/i2c/max9271.c
> @@ -223,12 +223,12 @@ int max9271_enable_gpios(struct max9271_device *dev, u8 gpio_mask)
> {
> int ret;
>
> - ret = max9271_read(dev, 0x0f);
> + ret = max9271_read(dev, 0x0e);
> if (ret < 0)
> return 0;
>
> /* BIT(0) reserved: GPO is always enabled. */
> - ret |= gpio_mask | BIT(0);
> + ret |= (gpio_mask & ~BIT(0));
> ret = max9271_write(dev, 0x0e, ret);
> if (ret < 0) {
> dev_err(&dev->client->dev, "Failed to enable gpio (%d)\n", ret);
> @@ -245,12 +245,12 @@ int max9271_disable_gpios(struct max9271_device *dev, u8 gpio_mask)
> {
> int ret;
>
> - ret = max9271_read(dev, 0x0f);
> + ret = max9271_read(dev, 0x0e);
> if (ret < 0)
> return 0;
>
> /* BIT(0) reserved: GPO cannot be disabled */
> - ret &= (~gpio_mask | BIT(0));
> + ret &= ~(gpio_mask | BIT(0));
> ret = max9271_write(dev, 0x0e, ret);
> if (ret < 0) {
> dev_err(&dev->client->dev, "Failed to disable gpio (%d)\n", ret);
>

2020-11-23 16:04:29

by Sergei Shtylyov

[permalink] [raw]
Subject: Re: [PATCH 1/2] media: max9271: Fix GPIO enable/disable

On 11/20/20 7:15 PM, Jacopo Mondi wrote:

> Fix GPIO enable/disable operations which wrongly read the 0x0f register
> to obtain the current mask of the enabled lines instead of using
> the correct 0x0e register.
>
> Also fix access to bit 0 of the register which is marked as reserved.
>
> Fixes: 34009bffc1c6 ("media: i2c: Add RDACM20 driver")
> Signed-off-by: Jacopo Mondi <[email protected]>
> ---
> drivers/media/i2c/max9271.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/media/i2c/max9271.c b/drivers/media/i2c/max9271.c
> index 0f6f7a092a46..c247db569bab 100644
> --- a/drivers/media/i2c/max9271.c
> +++ b/drivers/media/i2c/max9271.c
> @@ -223,12 +223,12 @@ int max9271_enable_gpios(struct max9271_device *dev, u8 gpio_mask)
> {
> int ret;
>
> - ret = max9271_read(dev, 0x0f);
> + ret = max9271_read(dev, 0x0e);
> if (ret < 0)
> return 0;
>
> /* BIT(0) reserved: GPO is always enabled. */
> - ret |= gpio_mask | BIT(0);
> + ret |= (gpio_mask & ~BIT(0));

() hardly needed here, = and <op>= have very low prio...

[...]

MBR, Sergei

2020-11-24 02:48:06

by Kieran Bingham

[permalink] [raw]
Subject: Re: [PATCH 2/2] media: rdacm20: Enable GPIO1 explicitly

Hi Jacopo,

On 20/11/2020 16:15, Jacopo Mondi wrote:
> The MAX9271 GPIO1 line that controls the sensor reset is by default
> enabled after a serializer chip reset.
>
> As rdacm20 does not go through an explicit serializer reset, make sure
> GPIO1 is enabled to make the camera module driver more robust.
>
> Fixes: 34009bffc1c6 ("media: i2c: Add RDACM20 driver")
> Signed-off-by: Jacopo Mondi <[email protected]>

Looks helpful to ensure a GPIO is enabled before toggling ;-)

Reading the datasheet, GPIO1EN defaults to enabled, so I assume this was
already working - however I think being explicit is a good thing anyway.

Reviewed-by: Kieran Bingham <[email protected]>


> ---
> drivers/media/i2c/rdacm20.c | 13 +++++++++++--
> 1 file changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/media/i2c/rdacm20.c b/drivers/media/i2c/rdacm20.c
> index 1ed928c4ca70..16bcb764b0e0 100644
> --- a/drivers/media/i2c/rdacm20.c
> +++ b/drivers/media/i2c/rdacm20.c
> @@ -487,9 +487,18 @@ static int rdacm20_initialize(struct rdacm20_device *dev)
> * Reset the sensor by cycling the OV10635 reset signal connected to the
> * MAX9271 GPIO1 and verify communication with the OV10635.
> */
> - max9271_clear_gpios(dev->serializer, MAX9271_GPIO1OUT);
> + ret = max9271_enable_gpios(dev->serializer, MAX9271_GPIO1OUT);
> + if (ret)
> + return ret;
> +
> + ret = max9271_clear_gpios(dev->serializer, MAX9271_GPIO1OUT);
> + if (ret)
> + return ret;
> usleep_range(10000, 15000);
> - max9271_set_gpios(dev->serializer, MAX9271_GPIO1OUT);
> +
> + ret = max9271_set_gpios(dev->serializer, MAX9271_GPIO1OUT);
> + if (ret)
> + return ret;
> usleep_range(10000, 15000);
>
> again:
> --
> 2.29.1
>