Issue controlling MAX7301 GPIO Expander via SPI using Arduino Uno R3
It may just be that your writeGPIO function throws away its arguments, and will only ever write a value of 0x01 to address 0x04. Using the arguments to the function should fix this:

void writeGPIO(byte address, byte data)
{
    address &amp;= ~0x80; // ensure bit 15 is cleared
    digitalWrite(SSEL_GPIO, LOW);
    SPI.transfer(address); // use the address argument
    SPI.transfer(data);    // use the data argument
    digitalWrite(SSEL_GPIO, HIGH);
}


However, it also appears that the MAX7301's 4-wire protocol may not necessarily be as compatible with SPI as expected. Usually, data is clocked in and out of the shift registers at the same time. The timing diagram on page 8 shows that data is clocked in to the device on DIN on the rising edge of SCLK (SPI mode 0 or 2), but that data is clocked out from the device on DOUT on the falling edge of SCLK (SPI mode 1 or 3). You might have better luck with a software SPI given this difference. I have provided a simple delay-based implementation of this below, although I don't have access to an Arduino, so I haven't tested it.

//this function takes the place of SPI.transfer
byte transferMax7301Byte(byte data_out)
{
    byte current_bit, result;
    result = 0;
    //must clock each bit
    for(current_bit = 0; current_bit &lt; 8; current_bit++)
    {
        //SCLK falling edge, MAX7301 changes output
        digitalWrite(SCLK_GPIO, LOW);
        //shift data from DOUT pin read into result
        result = (result &lt;&lt; 1) | digitalRead(DOUT_GPIO);
        //9600 baud is about 104 microseconds per pulse
        //so wait half of that time between edges
        delayMicroseconds(52);
        //SCLK rising edge, Arduino changes output
        digitalWrite(SCLK_GPIO, HIGH);
        //shift data out of data_out onto DIN pin
        digitalWrite(DIN_GPIO, data_out &amp; 0x80);
        data_out &lt;&lt;= 1;
        //wait the other half of the 104 microseconds
        delayMicroseconds(52);
    }
    //last falling edge of SCLK
    digitalWrite(SCLK_GPIO, LOW);
    //read last bit from DOUT pin
    result = (result &lt;&lt; 1) | digitalRead(DOUT_GPIO);
    return result;
}

void writeGPIO(byte address, byte data)
{ 
    address &amp;= ~0x80; // ensure bit 15 is cleared
    digitalWrite(SSEL_GPIO, LOW);

    transferMax7301Byte(address);
    transferMax7301Byte(data);

    digitalWrite(SSEL_GPIO, HIGH);
}

byte readGPIO(byte address)
{
    byte result;

    // Ensure that the D15 bit is set
    address |= 0x80;

    digitalWrite(SSEL_GPIO, LOW);

    // D15 to D8 contain R/W bit and register address
    transferMax7301Byte(address);
    // D7 to D0 discarded
    transferMax7301Byte(NOP);

    digitalWrite(SSEL_GPIO, HIGH);
    // Allow a few ns for MAX7301 register to fill up
    digitalWrite(SSEL_GPIO, LOW);

    // No useful data in MSByte
    transferMax7301Byte(NOP);
    // Results from register should be in LSbyte
    result |= transferMax7301Byte(NOP);

    digitalWrite(SSEL_GPIO, HIGH);

    return(result);
}