From 5affb607720d734ca572b8a77c5c7d62d3042b6f Mon Sep 17 00:00:00 2001 From: Gregory Bean Date: Thu, 9 Sep 2010 16:38:02 -0700 Subject: gpio: sx150x: correct and refine reset-on-probe behavior Replace the arbitrary software-reset call from the device-probe method, because: - It is defective. To work correctly, it should be two byte writes, not a single word write. As it stands, it does nothing. - Some devices with sx150x expanders installed have their NRESET pins ganged on the same line, so resetting one causes the others to reset - not a nice thing to do arbitrarily! - The probe, usually taking place at boot, implies a recent hard-reset, so a software reset at this point is just a waste of energy anyway. Therefore, make it optional, defaulting to off, as this will match the common case of probing at powerup and also matches the current broken no-op behavior. Signed-off-by: Gregory Bean Reviewed-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/gpio/sx150x.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/sx150x.c b/drivers/gpio/sx150x.c index b42f42c..823559a 100644 --- a/drivers/gpio/sx150x.c +++ b/drivers/gpio/sx150x.c @@ -459,17 +459,33 @@ static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg) return err; } -static int sx150x_init_hw(struct sx150x_chip *chip, - struct sx150x_platform_data *pdata) +static int sx150x_reset(struct sx150x_chip *chip) { - int err = 0; + int err; - err = i2c_smbus_write_word_data(chip->client, + err = i2c_smbus_write_byte_data(chip->client, chip->dev_cfg->reg_reset, - 0x3412); + 0x12); if (err < 0) return err; + err = i2c_smbus_write_byte_data(chip->client, + chip->dev_cfg->reg_reset, + 0x34); + return err; +} + +static int sx150x_init_hw(struct sx150x_chip *chip, + struct sx150x_platform_data *pdata) +{ + int err = 0; + + if (pdata->reset_during_probe) { + err = sx150x_reset(chip); + if (err < 0) + return err; + } + err = sx150x_i2c_write(chip->client, chip->dev_cfg->reg_misc, 0x01); -- cgit v1.1 From f0a7a98d1d400e2a5fd9a63ed56d30d30f2864cb Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 13 Sep 2010 13:04:02 +0100 Subject: ARM: 6373/1: tc35892-gpio: add setup/remove callbacks For board-specific initialization. Cc: Samuel Ortiz Cc: linux-kernel@vger.kernel.org Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Russell King --- drivers/gpio/tc35892-gpio.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/tc35892-gpio.c b/drivers/gpio/tc35892-gpio.c index 1be6288..7e10c93 100644 --- a/drivers/gpio/tc35892-gpio.c +++ b/drivers/gpio/tc35892-gpio.c @@ -322,6 +322,9 @@ static int __devinit tc35892_gpio_probe(struct platform_device *pdev) goto out_freeirq; } + if (pdata->setup) + pdata->setup(tc35892, tc35892_gpio->chip.base); + platform_set_drvdata(pdev, tc35892_gpio); return 0; @@ -338,9 +341,14 @@ out_free: static int __devexit tc35892_gpio_remove(struct platform_device *pdev) { struct tc35892_gpio *tc35892_gpio = platform_get_drvdata(pdev); + struct tc35892 *tc35892 = tc35892_gpio->tc35892; + struct tc35892_gpio_platform_data *pdata = tc35892->pdata->gpio; int irq = platform_get_irq(pdev, 0); int ret; + if (pdata->remove) + pdata->remove(tc35892, tc35892_gpio->chip.base); + ret = gpiochip_remove(&tc35892_gpio->chip); if (ret < 0) { dev_err(tc35892_gpio->dev, -- cgit v1.1