Problems configuring Device Tree and GPIO for PCA9538 GPIO expander

I'm developing with an NRF52832, using NCS v2.6.1/Zephyr 3.5.99

My custom hardware has three NXP PCA9538 GPIO expanders on it, to allow me to control various address and enable pins on some other devices, plus a few status LEDs.

I seem to be having issues getting my setup to correctly talk to and configure the GPIO outputs on any of the PCA9538's.

This is how I have them set up in my .dts file for my custom board:

&i2c0 {
    status = "okay";
    compatible = "nordic,nrf-twim";
    pinctrl-0 = <&i2c0_ct_default>;
    pinctrl-1 = <&i2c0_ct_sleep>;
    pinctrl-names = "default", "sleep";

    pca9538_70: pca9538@70 {
        compatible = "nxp,pca95xx";
        reg = <0x70>;
        gpio-controller;
        #gpio-cells = <2>;
        ngpios = <8>;
	    status = "okay";

		addrenpins {
			compatible = "gpio-leds";

			enai: gpio_out_enai {
				gpios = <&pca9538_70 0 GPIO_ACTIVE_LOW>;
				label = "Enable Input A Device";
			};

			enao: gpio_out_enao {
				gpios = <&pca9538_70 1 GPIO_ACTIVE_LOW>;
				label = "Enable Output A Device";
			};

			enbi: gpio_out_enbi {
				gpios = <&pca9538_70 2 GPIO_ACTIVE_LOW>;
				label = "Enable Input B Device";
			};

			enbo: gpio_out_enbo {
				gpios = <&pca9538_70 3 GPIO_ACTIVE_LOW>;
				label = "Enable Output B Device";
			};

			enci: gpio_out_enci {
				gpios = <&pca9538_70 4 GPIO_ACTIVE_LOW>;
				label = "Enable Input C Device";
			};

			enco: gpio_out_enco {
				gpios = <&pca9538_70 5 GPIO_ACTIVE_LOW>;
				label = "Enable Output C Device";
			};

			endi: gpio_out_endi {
				gpios = <&pca9538_70 6 GPIO_ACTIVE_LOW>;
				label = "Enable Input D Device";
			};

			endo: gpio_out_endo {
				gpios = <&pca9538_70 7 GPIO_ACTIVE_LOW>;
				label = "Enable Output D Device";
			};

		};
    };

   pca9538_72: pca9538@72 {
        compatible = "nxp,pca95xx";
        reg = <0x72>;
        gpio-controller;
        #gpio-cells = <2>;
        ngpios = <8>;
	    status = "okay";

		ledpins {
			compatible = "gpio-leds";

			testactive: gpio_out_testactive {
				gpios = <&pca9538_72 0 GPIO_ACTIVE_LOW>;
				label = "Test is active";
			};

			testpass: gpio_out_testpass {
				gpios = <&pca9538_72 1 GPIO_ACTIVE_LOW>;
				label = "Test has passed";
			};

			testfail: gpio_out_testfail {
				gpios = <&pca9538_72 2 GPIO_ACTIVE_LOW>;
				label = "Test has failed";
			};
		};
    };

   pca9538_73: pca9538@73 {
        compatible = "nxp,pca95xx";
        reg = <0x73>;
        gpio-controller;
        #gpio-cells = <2>;
        ngpios = <8>;
	    status = "okay";
    };
};

Note that <&i2c0_ct_default> and <&i2c0_ct_sleep>; are set up in my .dtsi file as follows:

i2c0_ct_default: i2c0_default {
		group1 {
			psels = <NRF_PSEL(TWIM_SDA, 0, 26)>,
				<NRF_PSEL(TWIM_SCL, 0, 27)>;
		};
	};

	i2c0_ct_sleep: i2c0_sleep {
		group1 {
			psels = <NRF_PSEL(TWIM_SDA, 0, 26)>,
				<NRF_PSEL(TWIM_SCL, 0, 27)>;
			low-power-enable;
		};
	};

I then have a buch of alias in my overlay file referencing all the gpio:

aliases {
	testactive = &testactive;
	testpass = &testpass;
	testfail = &testfail;
    enai = &enai;
    enbi = &enbi;
    enci = &enci;
    endi = &endi;
    enao = &enao;
    enbo = &enbo;
    enco = &enco;
    endo = &endo;
    };

Then, in my firmware, when I set up the gpio that I want to use on my expanders, I do this:

static const struct gpio_dt_spec enable_a_in = GPIO_DT_SPEC_GET(DT_ALIAS(enai), gpios);
static const struct gpio_dt_spec enable_b_in = GPIO_DT_SPEC_GET(DT_ALIAS(enbi), gpios);
static const struct gpio_dt_spec enable_c_in = GPIO_DT_SPEC_GET(DT_ALIAS(enci), gpios);
static const struct gpio_dt_spec enable_d_in = GPIO_DT_SPEC_GET(DT_ALIAS(endi), gpios);

static const struct gpio_dt_spec enable_a_out = GPIO_DT_SPEC_GET(DT_ALIAS(enao), gpios);
static const struct gpio_dt_spec enable_b_out = GPIO_DT_SPEC_GET(DT_ALIAS(enbo), gpios);
static const struct gpio_dt_spec enable_c_out = GPIO_DT_SPEC_GET(DT_ALIAS(enco), gpios);
static const struct gpio_dt_spec enable_d_out = GPIO_DT_SPEC_GET(DT_ALIAS(endo), gpios);

static const struct gpio_dt_spec test_active_led = GPIO_DT_SPEC_GET(DT_ALIAS(testactive), gpios);
static const struct gpio_dt_spec test_pass_led = GPIO_DT_SPEC_GET(DT_ALIAS(testpass), gpios);
static const struct gpio_dt_spec test_fail_led = GPIO_DT_SPEC_GET(DT_ALIAS(testfail), gpios);

And then I attempt to configure them as outputs, and set them to a starting value like this:

    CHECK_ERR(gpio_pin_configure_dt(&enable_a_in, GPIO_OUTPUT));
    CHECK_ERR(gpio_pin_configure_dt(&enable_b_in, GPIO_OUTPUT));
    CHECK_ERR(gpio_pin_configure_dt(&enable_c_in, GPIO_OUTPUT));
    CHECK_ERR(gpio_pin_configure_dt(&enable_d_in, GPIO_OUTPUT));
    CHECK_ERR(gpio_pin_configure_dt(&enable_a_out, GPIO_OUTPUT));
    CHECK_ERR(gpio_pin_configure_dt(&enable_b_out, GPIO_OUTPUT));
    CHECK_ERR(gpio_pin_configure_dt(&enable_c_out, GPIO_OUTPUT));
    CHECK_ERR(gpio_pin_configure_dt(&enable_d_out, GPIO_OUTPUT));

    CHECK_ERR(gpio_pin_set_dt(&enable_a_in, GPIO_INACTIVE));
    CHECK_ERR(gpio_pin_set_dt(&enable_b_in, GPIO_INACTIVE));
    CHECK_ERR(gpio_pin_set_dt(&enable_c_in, GPIO_INACTIVE));
    CHECK_ERR(gpio_pin_set_dt(&enable_d_in, GPIO_INACTIVE));
    CHECK_ERR(gpio_pin_set_dt(&enable_a_out, GPIO_INACTIVE));
    CHECK_ERR(gpio_pin_set_dt(&enable_b_out, GPIO_INACTIVE));
    CHECK_ERR(gpio_pin_set_dt(&enable_c_out, GPIO_INACTIVE));
    CHECK_ERR(gpio_pin_set_dt(&enable_d_out, GPIO_INACTIVE));

Note that CHECK_ERR() is a custom #define that just checks the return value and sends out some LOG info to the console if its < 0.

I seem to be having issues at the point that I call something like 

  CHECK_ERR(gpio_pin_configure_dt(&enable_a_in, GPIO_OUTPUT));
for any of the GPIO on my PCA9538, and I can't work out what the issue is.  I'm getting error -5.
I've got these settings in my proj.conf file:
CONFIG_GPIO=y
CONFIG_I2C=y
CONFIG_GPIO_PCA95XX=y
I've not used a GPIO expander IC before, but have certainly done plenty of stuff with the I2C on the nRF52832 on custom boards without issue.  I don't believe its an I2C issue, but that I am doing something wrong with the way I have my device tree set up, or the way I am trying to access the GPIO.
Can anyone help me fault find what I'm doing wrong?
Cheers,
Mike
Related