diff mbox

[v1,2/3] gpio: Add support for TPS68470 GPIOs

Message ID 1496750118-5570-3-git-send-email-rajmohan.mani@intel.com
State New
Headers show

Commit Message

Mani, Rajmohan June 6, 2017, 11:55 a.m. UTC
This patch adds support for TPS68470 GPIOs.
There are 7 GPIOs and a few sensor related GPIOs.
These GPIOs can be requested and configured as
appropriate.

Signed-off-by: Rajmohan Mani <rajmohan.mani@intel.com>
---
 drivers/gpio/Kconfig         |  10 +++
 drivers/gpio/Makefile        |   1 +
 drivers/gpio/gpio-tps68470.c | 185 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 196 insertions(+)
 create mode 100644 drivers/gpio/gpio-tps68470.c

Comments

Andy Shevchenko June 6, 2017, 2:15 p.m. UTC | #1
On Tue, Jun 6, 2017 at 2:55 PM, Rajmohan Mani <rajmohan.mani@intel.com> wrote:
> This patch adds support for TPS68470 GPIOs.
> There are 7 GPIOs and a few sensor related GPIOs.
> These GPIOs can be requested and configured as
> appropriate.

Besides my below comments, just put it here that I recommended earlier
to provide 2 GPIO chips (one per bank of GPIOs).
It's up to Linus to decide since you didn't follow the recommendation.

> +#include <linux/gpio.h>
> +#include <linux/gpio/machine.h>

These shouldn't be in the driver.
Instead use
#include <linux/gpio/driver.h>

> +#include <linux/mfd/tps68470.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>

> +       if (offset >= TPS68470_N_REGULAR_GPIO) {
> +               offset -= TPS68470_N_REGULAR_GPIO;
> +               reg = TPS68470_REG_SGPO;
> +       }

Two GPIO chips makes this gone.

> +struct gpiod_lookup_table gpios_table = {
> +       .dev_id = NULL,
> +       .table = {
> +                 GPIO_LOOKUP("tps68470-gpio", 0, "gpio.0", GPIO_ACTIVE_HIGH),
> +                 GPIO_LOOKUP("tps68470-gpio", 1, "gpio.1", GPIO_ACTIVE_HIGH),
> +                 GPIO_LOOKUP("tps68470-gpio", 2, "gpio.2", GPIO_ACTIVE_HIGH),
> +                 GPIO_LOOKUP("tps68470-gpio", 3, "gpio.3", GPIO_ACTIVE_HIGH),
> +                 GPIO_LOOKUP("tps68470-gpio", 4, "gpio.4", GPIO_ACTIVE_HIGH),
> +                 GPIO_LOOKUP("tps68470-gpio", 5, "gpio.5", GPIO_ACTIVE_HIGH),
> +                 GPIO_LOOKUP("tps68470-gpio", 6, "gpio.6", GPIO_ACTIVE_HIGH),
> +                 GPIO_LOOKUP("tps68470-gpio", 7, "s_enable", GPIO_ACTIVE_HIGH),
> +                 GPIO_LOOKUP("tps68470-gpio", 8, "s_idle", GPIO_ACTIVE_HIGH),
> +                 GPIO_LOOKUP("tps68470-gpio", 9, "s_resetn", GPIO_ACTIVE_HIGH),
> +                 {},
> +       },
> +};

This doesn't belong to the driver.

> +static int tps68470_gpio_probe(struct platform_device *pdev)
> +{
> +       struct tps68470 *tps68470 = dev_get_drvdata(pdev->dev.parent);
> +       struct tps68470_gpio_data *tps68470_gpio;

> +       int i, ret;

unsingned int i;

> +       ret = gpiochip_add(&tps68470_gpio->gc);

devm_ ?

> +       gpiod_add_lookup_table(&gpios_table);

Doesn't belong to the driver either.
I suppose it's a part of MFD (patch 1)

> +       /*
> +        * Initialize all the GPIOs to 0, just to make sure all
> +        * GPIOs start with known default values. This protects against
> +        * any GPIOs getting set with a value of 1, after TPS68470 reset

So, this is hardware bug. Right? Or misconfiguration of the chip we may avoid?

> +        */
> +       for (i = 0; i < tps68470_gpio->gc.ngpio; i++)
> +               tps68470_gpio_set(&tps68470_gpio->gc, i, 0);
> +
> +       return ret;
> +}

> +
> +static int tps68470_gpio_remove(struct platform_device *pdev)
> +{
> +       struct tps68470_gpio_data *tps68470_gpio = platform_get_drvdata(pdev);
> +
> +       gpiod_remove_lookup_table(&gpios_table);
> +       gpiochip_remove(&tps68470_gpio->gc);
> +
> +       return 0;
> +}

Should gone after devm_ in use.
Linus Walleij June 9, 2017, 11:15 a.m. UTC | #2
On Tue, Jun 6, 2017 at 1:55 PM, Rajmohan Mani <rajmohan.mani@intel.com> wrote:

> This patch adds support for TPS68470 GPIOs.
> There are 7 GPIOs and a few sensor related GPIOs.
> These GPIOs can be requested and configured as
> appropriate.
>
> Signed-off-by: Rajmohan Mani <rajmohan.mani@intel.com>

Same comments as Andy already sent, plus:

> +static inline struct tps68470_gpio_data *to_gpio_data(struct gpio_chip *gpiochp)
> +{
> +       return container_of(gpiochp, struct tps68470_gpio_data, gc);
> +}

Please use the data pointe inside gpio_chip.

struct tps68470_gpio_data *foo = gpiochip_get_data(gc);

> +       ret = tps68470_reg_read(tps, reg, &val);
(...)
> +       tps68470_update_bits(tps, reg, BIT(offset), value ? BIT(offset) : 0);
(...)
> +       return tps68470_update_bits(tps, TPS68470_GPIO_CTL_REG_A(offset),
> +                                TPS68470_GPIO_MODE_MASK,
> +                                TPS68470_GPIO_MODE_OUT_CMOS);
(...)
> +       return tps68470_update_bits(tps, TPS68470_GPIO_CTL_REG_A(offset),
> +                                  TPS68470_GPIO_MODE_MASK, 0x00);

This looks like a reimplementation of regmap. Is it not possible
to create a regmap in the MFD driver and pass that around instead?

> +struct gpiod_lookup_table gpios_table = {
> +       .dev_id = NULL,
> +       .table = {
> +                 GPIO_LOOKUP("tps68470-gpio", 0, "gpio.0", GPIO_ACTIVE_HIGH),
> +                 GPIO_LOOKUP("tps68470-gpio", 1, "gpio.1", GPIO_ACTIVE_HIGH),
> +                 GPIO_LOOKUP("tps68470-gpio", 2, "gpio.2", GPIO_ACTIVE_HIGH),
> +                 GPIO_LOOKUP("tps68470-gpio", 3, "gpio.3", GPIO_ACTIVE_HIGH),
> +                 GPIO_LOOKUP("tps68470-gpio", 4, "gpio.4", GPIO_ACTIVE_HIGH),
> +                 GPIO_LOOKUP("tps68470-gpio", 5, "gpio.5", GPIO_ACTIVE_HIGH),
> +                 GPIO_LOOKUP("tps68470-gpio", 6, "gpio.6", GPIO_ACTIVE_HIGH),
> +                 GPIO_LOOKUP("tps68470-gpio", 7, "s_enable", GPIO_ACTIVE_HIGH),
> +                 GPIO_LOOKUP("tps68470-gpio", 8, "s_idle", GPIO_ACTIVE_HIGH),
> +                 GPIO_LOOKUP("tps68470-gpio", 9, "s_resetn", GPIO_ACTIVE_HIGH),
> +                 {},
> +       },
> +};

Hm that's why you include <linux/gpio/machine.h> I guess.

This warrants a big comment above it explaining why this is done like
that and what the use is inside any system with this chip mounted.

> +       tps68470_gpio->gc.label = "tps68470-gpio";
> +       tps68470_gpio->gc.owner = THIS_MODULE;
> +       tps68470_gpio->gc.direction_input = tps68470_gpio_input;
> +       tps68470_gpio->gc.direction_output = tps68470_gpio_output;

Please implement .get_direction()

> +       tps68470_gpio->gc.get = tps68470_gpio_get;
> +       tps68470_gpio->gc.set = tps68470_gpio_set;
> +       tps68470_gpio->gc.can_sleep = true;
> +       tps68470_gpio->gc.ngpio = TPS68470_N_GPIO;
> +       tps68470_gpio->gc.base = -1;
> +       tps68470_gpio->gc.parent = &pdev->dev;

Consider assigning the .names() array some sensible line names.

> +static int tps68470_gpio_remove(struct platform_device *pdev)
> +{
> +       struct tps68470_gpio_data *tps68470_gpio = platform_get_drvdata(pdev);
> +
> +       gpiod_remove_lookup_table(&gpios_table);
> +       gpiochip_remove(&tps68470_gpio->gc);

You can't use devm_gpiochip_add()?

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mani, Rajmohan June 11, 2017, 3:49 a.m. UTC | #3
Hi Andy,

Thanks for the reviews and patience.

> 

> On Tue, Jun 6, 2017 at 2:55 PM, Rajmohan Mani <rajmohan.mani@intel.com>

> wrote:

> > This patch adds support for TPS68470 GPIOs.

> > There are 7 GPIOs and a few sensor related GPIOs.

> > These GPIOs can be requested and configured as appropriate.

> 

> Besides my below comments, just put it here that I recommended earlier to

> provide 2 GPIO chips (one per bank of GPIOs).

> It's up to Linus to decide since you didn't follow the recommendation.

> 


Ack.
Did you mean to add this in Kconfig or this source file?

Here's some more details on these GPIOs.
Each of these 7 GPIOs has 2 registers to control the mode, level, drive strength, polarity, hysteresis control among other things. Also there are GPDI and GPDO registers to control the input and output values of these 7 GPIOs. These GPIOs are numbered 0 through 6.
The remaining 3 GPIOs are more of special purpose GPIOs that are output only, with one register to control all of their output values and drive strengths. These GPIOs are named with a special purpose (ENABLE, IDLE and RESET of the sensor).

> > +#include <linux/gpio.h>

> > +#include <linux/gpio/machine.h>

> 

> These shouldn't be in the driver.

> Instead use

> #include <linux/gpio/driver.h>

> 


Ack

> > +#include <linux/mfd/tps68470.h>

> > +#include <linux/module.h>

> > +#include <linux/platform_device.h>

> 

> > +       if (offset >= TPS68470_N_REGULAR_GPIO) {

> > +               offset -= TPS68470_N_REGULAR_GPIO;

> > +               reg = TPS68470_REG_SGPO;

> > +       }

> 

> Two GPIO chips makes this gone.

> 


Ack.
On a closer look, creating two GPIO chips makes things clearer. 
But, this comes at the cost of a new set of gpio_get/set, 
gpio_output/input functions for the new GPIO chip. This results in 
new code for the second GPIO chip, which is pretty much 
going to be the copy of first GPIO chip, except for initializing 
the "reg" variable with GPDO or SGPO register. If we decide to 
reuse the existing code of the first GPIO chip for the new/second 
GPIO chip, we would still need to add a check, which would be 
effectively the same as the existing code, with the only advantage 
of not having to initialize the "offset" variable (which holds the 
GPIO offset). Given the above, it seems ok to retain the existing 
model of a single chip with the adjustments for offset, reg 
variables per the GPIO offset, to keep the whole picture simple.

> > +struct gpiod_lookup_table gpios_table = {

> > +       .dev_id = NULL,

> > +       .table = {

> > +                 GPIO_LOOKUP("tps68470-gpio", 0, "gpio.0", GPIO_ACTIVE_HIGH),

> > +                 GPIO_LOOKUP("tps68470-gpio", 1, "gpio.1", GPIO_ACTIVE_HIGH),

> > +                 GPIO_LOOKUP("tps68470-gpio", 2, "gpio.2", GPIO_ACTIVE_HIGH),

> > +                 GPIO_LOOKUP("tps68470-gpio", 3, "gpio.3", GPIO_ACTIVE_HIGH),

> > +                 GPIO_LOOKUP("tps68470-gpio", 4, "gpio.4", GPIO_ACTIVE_HIGH),

> > +                 GPIO_LOOKUP("tps68470-gpio", 5, "gpio.5", GPIO_ACTIVE_HIGH),

> > +                 GPIO_LOOKUP("tps68470-gpio", 6, "gpio.6", GPIO_ACTIVE_HIGH),

> > +                 GPIO_LOOKUP("tps68470-gpio", 7, "s_enable",

> GPIO_ACTIVE_HIGH),

> > +                 GPIO_LOOKUP("tps68470-gpio", 8, "s_idle", GPIO_ACTIVE_HIGH),

> > +                 GPIO_LOOKUP("tps68470-gpio", 9, "s_resetn",

> GPIO_ACTIVE_HIGH),

> > +                 {},

> > +       },

> > +};

> 

> This doesn't belong to the driver.

> 


Ack
I have moved this code to the MFD driver

> > +static int tps68470_gpio_probe(struct platform_device *pdev) {

> > +       struct tps68470 *tps68470 = dev_get_drvdata(pdev->dev.parent);

> > +       struct tps68470_gpio_data *tps68470_gpio;

> 

> > +       int i, ret;

> 

> unsingned int i;

> 

> > +       ret = gpiochip_add(&tps68470_gpio->gc);

> 

> devm_ ?

> 


Ack

> > +       gpiod_add_lookup_table(&gpios_table);

> 

> Doesn't belong to the driver either.

> I suppose it's a part of MFD (patch 1)

> 


Ack

> > +       /*

> > +        * Initialize all the GPIOs to 0, just to make sure all

> > +        * GPIOs start with known default values. This protects against

> > +        * any GPIOs getting set with a value of 1, after TPS68470

> > + reset

> 

> So, this is hardware bug. Right? Or misconfiguration of the chip we may avoid?

> 


The tps68470 PMIC upon reset, does not have the "power on reset" values.
We just initialize the GPIOs with their known default values.

> > +        */

> > +       for (i = 0; i < tps68470_gpio->gc.ngpio; i++)

> > +               tps68470_gpio_set(&tps68470_gpio->gc, i, 0);

> > +

> > +       return ret;

> > +}

> 

> > +

> > +static int tps68470_gpio_remove(struct platform_device *pdev) {

> > +       struct tps68470_gpio_data *tps68470_gpio =

> > +platform_get_drvdata(pdev);

> > +

> > +       gpiod_remove_lookup_table(&gpios_table);

> > +       gpiochip_remove(&tps68470_gpio->gc);

> > +

> > +       return 0;

> > +}

> 

> Should gone after devm_ in use.

> 


Ack
Mani, Rajmohan June 11, 2017, 5:04 a.m. UTC | #4
SGkgTGludXMsDQoNClRoYW5rcyBmb3IgdGhlIHJldmlld3MuDQoNCj4gLS0tLS1PcmlnaW5hbCBN
ZXNzYWdlLS0tLS0NCj4gRnJvbTogTGludXMgV2FsbGVpaiBbbWFpbHRvOmxpbnVzLndhbGxlaWpA
bGluYXJvLm9yZ10NCj4gU2VudDogRnJpZGF5LCBKdW5lIDA5LCAyMDE3IDQ6MTUgQU0NCj4gVG86
IE1hbmksIFJham1vaGFuIDxyYWptb2hhbi5tYW5pQGludGVsLmNvbT4NCj4gQ2M6IGxpbnV4LWtl
cm5lbEB2Z2VyLmtlcm5lbC5vcmc7IGxpbnV4LWdwaW9Admdlci5rZXJuZWwub3JnOyBBQ1BJIERl
dmVsDQo+IE1hbGluZyBMaXN0IDxsaW51eC1hY3BpQHZnZXIua2VybmVsLm9yZz47IExlZSBKb25l
cyA8bGVlLmpvbmVzQGxpbmFyby5vcmc+Ow0KPiBBbGV4YW5kcmUgQ291cmJvdCA8Z251cm91QGdt
YWlsLmNvbT47IFJhZmFlbCBKLiBXeXNvY2tpDQo+IDxyandAcmp3eXNvY2tpLm5ldD47IExlbiBC
cm93biA8bGVuYkBrZXJuZWwub3JnPg0KPiBTdWJqZWN0OiBSZTogW1BBVENIIHYxIDIvM10gZ3Bp
bzogQWRkIHN1cHBvcnQgZm9yIFRQUzY4NDcwIEdQSU9zDQo+IA0KPiBPbiBUdWUsIEp1biA2LCAy
MDE3IGF0IDE6NTUgUE0sIFJham1vaGFuIE1hbmkgPHJham1vaGFuLm1hbmlAaW50ZWwuY29tPg0K
PiB3cm90ZToNCj4gDQo+ID4gVGhpcyBwYXRjaCBhZGRzIHN1cHBvcnQgZm9yIFRQUzY4NDcwIEdQ
SU9zLg0KPiA+IFRoZXJlIGFyZSA3IEdQSU9zIGFuZCBhIGZldyBzZW5zb3IgcmVsYXRlZCBHUElP
cy4NCj4gPiBUaGVzZSBHUElPcyBjYW4gYmUgcmVxdWVzdGVkIGFuZCBjb25maWd1cmVkIGFzIGFw
cHJvcHJpYXRlLg0KPiA+DQo+ID4gU2lnbmVkLW9mZi1ieTogUmFqbW9oYW4gTWFuaSA8cmFqbW9o
YW4ubWFuaUBpbnRlbC5jb20+DQo+IA0KPiBTYW1lIGNvbW1lbnRzIGFzIEFuZHkgYWxyZWFkeSBz
ZW50LCBwbHVzOg0KPiANCj4gPiArc3RhdGljIGlubGluZSBzdHJ1Y3QgdHBzNjg0NzBfZ3Bpb19k
YXRhICp0b19ncGlvX2RhdGEoc3RydWN0DQo+ID4gK2dwaW9fY2hpcCAqZ3Bpb2NocCkgew0KPiA+
ICsgICAgICAgcmV0dXJuIGNvbnRhaW5lcl9vZihncGlvY2hwLCBzdHJ1Y3QgdHBzNjg0NzBfZ3Bp
b19kYXRhLCBnYyk7IH0NCj4gDQo+IFBsZWFzZSB1c2UgdGhlIGRhdGEgcG9pbnRlIGluc2lkZSBn
cGlvX2NoaXAuDQo+IA0KDQpUaGlzIGlzIG5vdCBjbGVhciB0byBtZS4NClRoZSBkcml2ZXIgYWxy
ZWFkeSBnZXRzIHRoZSBkYXRhIHBvaW50ZXIgaW5zaWRlIGdwaW9fY2hpcCAod2hpY2ggaXMgZ3Bp
b2NocCkNCklzIHRoZSBuYW1lIGdwaW9jaHAgbWlzbGVhZGluZz8gDQpJIGhhZCB0byBnZXQgcmlk
IG9mICJpIiBpbiBncGlvY2hpcCwgdG8gbWVldCA4MCBjaGFyIGxpbWl0Lg0KDQo+IHN0cnVjdCB0
cHM2ODQ3MF9ncGlvX2RhdGEgKmZvbyA9IGdwaW9jaGlwX2dldF9kYXRhKGdjKTsNCj4gDQo+ID4g
KyAgICAgICByZXQgPSB0cHM2ODQ3MF9yZWdfcmVhZCh0cHMsIHJlZywgJnZhbCk7DQo+ICguLi4p
DQo+ID4gKyAgICAgICB0cHM2ODQ3MF91cGRhdGVfYml0cyh0cHMsIHJlZywgQklUKG9mZnNldCks
IHZhbHVlID8NCj4gPiArIEJJVChvZmZzZXQpIDogMCk7DQo+ICguLi4pDQo+ID4gKyAgICAgICBy
ZXR1cm4gdHBzNjg0NzBfdXBkYXRlX2JpdHModHBzLCBUUFM2ODQ3MF9HUElPX0NUTF9SRUdfQShv
ZmZzZXQpLA0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRQUzY4NDcwX0dQ
SU9fTU9ERV9NQVNLLA0KPiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRQUzY4
NDcwX0dQSU9fTU9ERV9PVVRfQ01PUyk7DQo+ICguLi4pDQo+ID4gKyAgICAgICByZXR1cm4gdHBz
Njg0NzBfdXBkYXRlX2JpdHModHBzLCBUUFM2ODQ3MF9HUElPX0NUTF9SRUdfQShvZmZzZXQpLA0K
PiA+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFBTNjg0NzBfR1BJT19NT0RF
X01BU0ssIDB4MDApOw0KPiANCj4gVGhpcyBsb29rcyBsaWtlIGEgcmVpbXBsZW1lbnRhdGlvbiBv
ZiByZWdtYXAuIElzIGl0IG5vdCBwb3NzaWJsZSB0byBjcmVhdGUgYQ0KPiByZWdtYXAgaW4gdGhl
IE1GRCBkcml2ZXIgYW5kIHBhc3MgdGhhdCBhcm91bmQgaW5zdGVhZD8NCj4gDQoNCkFjaw0KV2ls
bCBiZSBhZGRyZXNzZWQgaW4gdjIgb2YgdGhpcyBwYXRjaCBzZXJpZXMuDQoNCj4gPiArc3RydWN0
IGdwaW9kX2xvb2t1cF90YWJsZSBncGlvc190YWJsZSA9IHsNCj4gPiArICAgICAgIC5kZXZfaWQg
PSBOVUxMLA0KPiA+ICsgICAgICAgLnRhYmxlID0gew0KPiA+ICsgICAgICAgICAgICAgICAgIEdQ
SU9fTE9PS1VQKCJ0cHM2ODQ3MC1ncGlvIiwgMCwgImdwaW8uMCIsIEdQSU9fQUNUSVZFX0hJR0gp
LA0KPiA+ICsgICAgICAgICAgICAgICAgIEdQSU9fTE9PS1VQKCJ0cHM2ODQ3MC1ncGlvIiwgMSwg
ImdwaW8uMSIsIEdQSU9fQUNUSVZFX0hJR0gpLA0KPiA+ICsgICAgICAgICAgICAgICAgIEdQSU9f
TE9PS1VQKCJ0cHM2ODQ3MC1ncGlvIiwgMiwgImdwaW8uMiIsIEdQSU9fQUNUSVZFX0hJR0gpLA0K
PiA+ICsgICAgICAgICAgICAgICAgIEdQSU9fTE9PS1VQKCJ0cHM2ODQ3MC1ncGlvIiwgMywgImdw
aW8uMyIsIEdQSU9fQUNUSVZFX0hJR0gpLA0KPiA+ICsgICAgICAgICAgICAgICAgIEdQSU9fTE9P
S1VQKCJ0cHM2ODQ3MC1ncGlvIiwgNCwgImdwaW8uNCIsIEdQSU9fQUNUSVZFX0hJR0gpLA0KPiA+
ICsgICAgICAgICAgICAgICAgIEdQSU9fTE9PS1VQKCJ0cHM2ODQ3MC1ncGlvIiwgNSwgImdwaW8u
NSIsIEdQSU9fQUNUSVZFX0hJR0gpLA0KPiA+ICsgICAgICAgICAgICAgICAgIEdQSU9fTE9PS1VQ
KCJ0cHM2ODQ3MC1ncGlvIiwgNiwgImdwaW8uNiIsIEdQSU9fQUNUSVZFX0hJR0gpLA0KPiA+ICsg
ICAgICAgICAgICAgICAgIEdQSU9fTE9PS1VQKCJ0cHM2ODQ3MC1ncGlvIiwgNywgInNfZW5hYmxl
IiwNCj4gR1BJT19BQ1RJVkVfSElHSCksDQo+ID4gKyAgICAgICAgICAgICAgICAgR1BJT19MT09L
VVAoInRwczY4NDcwLWdwaW8iLCA4LCAic19pZGxlIiwgR1BJT19BQ1RJVkVfSElHSCksDQo+ID4g
KyAgICAgICAgICAgICAgICAgR1BJT19MT09LVVAoInRwczY4NDcwLWdwaW8iLCA5LCAic19yZXNl
dG4iLA0KPiBHUElPX0FDVElWRV9ISUdIKSwNCj4gPiArICAgICAgICAgICAgICAgICB7fSwNCj4g
PiArICAgICAgIH0sDQo+ID4gK307DQo+IA0KPiBIbSB0aGF0J3Mgd2h5IHlvdSBpbmNsdWRlIDxs
aW51eC9ncGlvL21hY2hpbmUuaD4gSSBndWVzcy4NCj4gDQoNCkFjaw0KDQo+IFRoaXMgd2FycmFu
dHMgYSBiaWcgY29tbWVudCBhYm92ZSBpdCBleHBsYWluaW5nIHdoeSB0aGlzIGlzIGRvbmUgbGlr
ZSB0aGF0IGFuZA0KPiB3aGF0IHRoZSB1c2UgaXMgaW5zaWRlIGFueSBzeXN0ZW0gd2l0aCB0aGlz
IGNoaXAgbW91bnRlZC4NCj4gDQoNCkFjaw0KSSBoYXZlIGFkZGVkIGNvbW1lbnRzIGluIHRoZSBN
RkQgZHJpdmVyLCBpbnNpZGUgd2hpY2ggdGhlIGxvb2t1cCB0YWJsZSBoYXMgbW92ZWQuDQoNCj4g
PiArICAgICAgIHRwczY4NDcwX2dwaW8tPmdjLmxhYmVsID0gInRwczY4NDcwLWdwaW8iOw0KPiA+
ICsgICAgICAgdHBzNjg0NzBfZ3Bpby0+Z2Mub3duZXIgPSBUSElTX01PRFVMRTsNCj4gPiArICAg
ICAgIHRwczY4NDcwX2dwaW8tPmdjLmRpcmVjdGlvbl9pbnB1dCA9IHRwczY4NDcwX2dwaW9faW5w
dXQ7DQo+ID4gKyAgICAgICB0cHM2ODQ3MF9ncGlvLT5nYy5kaXJlY3Rpb25fb3V0cHV0ID0gdHBz
Njg0NzBfZ3Bpb19vdXRwdXQ7DQo+IA0KPiBQbGVhc2UgaW1wbGVtZW50IC5nZXRfZGlyZWN0aW9u
KCkNCj4gDQoNCkFjaw0KDQo+ID4gKyAgICAgICB0cHM2ODQ3MF9ncGlvLT5nYy5nZXQgPSB0cHM2
ODQ3MF9ncGlvX2dldDsNCj4gPiArICAgICAgIHRwczY4NDcwX2dwaW8tPmdjLnNldCA9IHRwczY4
NDcwX2dwaW9fc2V0Ow0KPiA+ICsgICAgICAgdHBzNjg0NzBfZ3Bpby0+Z2MuY2FuX3NsZWVwID0g
dHJ1ZTsNCj4gPiArICAgICAgIHRwczY4NDcwX2dwaW8tPmdjLm5ncGlvID0gVFBTNjg0NzBfTl9H
UElPOw0KPiA+ICsgICAgICAgdHBzNjg0NzBfZ3Bpby0+Z2MuYmFzZSA9IC0xOw0KPiA+ICsgICAg
ICAgdHBzNjg0NzBfZ3Bpby0+Z2MucGFyZW50ID0gJnBkZXYtPmRldjsNCj4gDQo+IENvbnNpZGVy
IGFzc2lnbmluZyB0aGUgLm5hbWVzKCkgYXJyYXkgc29tZSBzZW5zaWJsZSBsaW5lIG5hbWVzLg0K
PiANCg0KQWNrDQoNCj4gPiArc3RhdGljIGludCB0cHM2ODQ3MF9ncGlvX3JlbW92ZShzdHJ1Y3Qg
cGxhdGZvcm1fZGV2aWNlICpwZGV2KSB7DQo+ID4gKyAgICAgICBzdHJ1Y3QgdHBzNjg0NzBfZ3Bp
b19kYXRhICp0cHM2ODQ3MF9ncGlvID0NCj4gPiArcGxhdGZvcm1fZ2V0X2RydmRhdGEocGRldik7
DQo+ID4gKw0KPiA+ICsgICAgICAgZ3Bpb2RfcmVtb3ZlX2xvb2t1cF90YWJsZSgmZ3Bpb3NfdGFi
bGUpOw0KPiA+ICsgICAgICAgZ3Bpb2NoaXBfcmVtb3ZlKCZ0cHM2ODQ3MF9ncGlvLT5nYyk7DQo+
IA0KPiBZb3UgY2FuJ3QgdXNlIGRldm1fZ3Bpb2NoaXBfYWRkKCk/DQo+IA0KDQpPcmlnaW5hbGx5
IEkgY291bGRuJ3QsIGJlY2F1c2UgdGhlIGRyaXZlciBjYW4gbm90IHJlbW92ZSB0aGUgbG9va3Vw
IHRhYmxlIHVwb24gZXhpdC9yZW1vdmFsLiBJIG1vdmVkIHRoaXMgY29kZSBpbnNpZGUgdGhlIE1G
RCBkcml2ZXIsIHdoaWNoIGlzIG1vZGlmaWVkIHRvIHVzZSAuc2h1dGRvd24oKSB0byByZW1vdmUg
dGhlIGxvb2t1cCB0YWJsZSwgc28gaXQgY2FuIHVzZSBkZXZfbWZkXyogY2FsbC4NCg0K
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sakari Ailus June 11, 2017, 11:30 a.m. UTC | #5
Hi Rajmohan and Andy,

On Sun, Jun 11, 2017 at 03:49:18AM +0000, Mani, Rajmohan wrote:
> Hi Andy,
> 
> Thanks for the reviews and patience.
> 
> > 
> > On Tue, Jun 6, 2017 at 2:55 PM, Rajmohan Mani <rajmohan.mani@intel.com>
> > wrote:
> > > This patch adds support for TPS68470 GPIOs.
> > > There are 7 GPIOs and a few sensor related GPIOs.
> > > These GPIOs can be requested and configured as appropriate.
> > 
> > Besides my below comments, just put it here that I recommended earlier to
> > provide 2 GPIO chips (one per bank of GPIOs).
> > It's up to Linus to decide since you didn't follow the recommendation.
> > 
> 
> Ack.
> Did you mean to add this in Kconfig or this source file?
> 
> Here's some more details on these GPIOs.
> Each of these 7 GPIOs has 2 registers to control the mode, level, drive strength, polarity, hysteresis control among other things. Also there are GPDI and GPDO registers to control the input and output values of these 7 GPIOs. These GPIOs are numbered 0 through 6.
> The remaining 3 GPIOs are more of special purpose GPIOs that are output only, with one register to control all of their output values and drive strengths. These GPIOs are named with a special purpose (ENABLE, IDLE and RESET of the sensor).
> 
> > > +#include <linux/gpio.h>
> > > +#include <linux/gpio/machine.h>
> > 
> > These shouldn't be in the driver.
> > Instead use
> > #include <linux/gpio/driver.h>
> > 
> 
> Ack
> 
> > > +#include <linux/mfd/tps68470.h>
> > > +#include <linux/module.h>
> > > +#include <linux/platform_device.h>
> > 
> > > +       if (offset >= TPS68470_N_REGULAR_GPIO) {
> > > +               offset -= TPS68470_N_REGULAR_GPIO;
> > > +               reg = TPS68470_REG_SGPO;
> > > +       }
> > 
> > Two GPIO chips makes this gone.

Again, I'm not really worried about this driver, but the ACPI tables. How
does the difference show there?

The outputs (s_enable, s_idle and s_resetn) are not numbered in the
documentation. There grouped, though, but the order in that grouping varies.

> > > +struct gpiod_lookup_table gpios_table = {
> > > +       .dev_id = NULL,
> > > +       .table = {
> > > +                 GPIO_LOOKUP("tps68470-gpio", 0, "gpio.0", GPIO_ACTIVE_HIGH),
> > > +                 GPIO_LOOKUP("tps68470-gpio", 1, "gpio.1", GPIO_ACTIVE_HIGH),
> > > +                 GPIO_LOOKUP("tps68470-gpio", 2, "gpio.2", GPIO_ACTIVE_HIGH),
> > > +                 GPIO_LOOKUP("tps68470-gpio", 3, "gpio.3", GPIO_ACTIVE_HIGH),
> > > +                 GPIO_LOOKUP("tps68470-gpio", 4, "gpio.4", GPIO_ACTIVE_HIGH),
> > > +                 GPIO_LOOKUP("tps68470-gpio", 5, "gpio.5", GPIO_ACTIVE_HIGH),
> > > +                 GPIO_LOOKUP("tps68470-gpio", 6, "gpio.6", GPIO_ACTIVE_HIGH),
> > > +                 GPIO_LOOKUP("tps68470-gpio", 7, "s_enable",
> > GPIO_ACTIVE_HIGH),
> > > +                 GPIO_LOOKUP("tps68470-gpio", 8, "s_idle", GPIO_ACTIVE_HIGH),
> > > +                 GPIO_LOOKUP("tps68470-gpio", 9, "s_resetn",
> > GPIO_ACTIVE_HIGH),
> > > +                 {},
> > > +       },
> > > +};
> > 
> > This doesn't belong to the driver.
> > 
> 
> Ack
> I have moved this code to the MFD driver

This information should come from the ACPI tables, it should not be present
in drivers. Why do you need it?

> > > +       /*
> > > +        * Initialize all the GPIOs to 0, just to make sure all
> > > +        * GPIOs start with known default values. This protects against
> > > +        * any GPIOs getting set with a value of 1, after TPS68470
> > > + reset
> > 
> > So, this is hardware bug. Right? Or misconfiguration of the chip we may avoid?
> > 
> 
> The tps68470 PMIC upon reset, does not have the "power on reset" values.
> We just initialize the GPIOs with their known default values.

If that was the case, I bet you could expect interesting behaviour from the
hardware connected to these pins.

For what it's worth, the chip documentation states that the reset value for
the SGPO and GPDO registers is zero, as well as that GPIOs are configured as
input and the reset value of the s_* outputs is low.

In other words, I don't think that explicitly setting the values to zero has
an effect.
Andy Shevchenko June 11, 2017, 1:40 p.m. UTC | #6
On Sun, Jun 11, 2017 at 2:30 PM, Sakari Ailus <sakari.ailus@iki.fi> wrote:
> On Sun, Jun 11, 2017 at 03:49:18AM +0000, Mani, Rajmohan wrote:
>> > On Tue, Jun 6, 2017 at 2:55 PM, Rajmohan Mani <rajmohan.mani@intel.com>
>> > wrote:

>> > Besides my below comments, just put it here that I recommended earlier to
>> > provide 2 GPIO chips (one per bank of GPIOs).
>> > It's up to Linus to decide since you didn't follow the recommendation.

>> Did you mean to add this in Kconfig or this source file?
>>
>> Here's some more details on these GPIOs.
>> Each of these 7 GPIOs has 2 registers to control the mode, level, drive strength, polarity, hysteresis control among other things. Also there are GPDI and GPDO registers to control the input and output values of these 7 GPIOs. These GPIOs are numbered 0 through 6.
>> The remaining 3 GPIOs are more of special purpose GPIOs that are output only, with one register to control all of their output values and drive strengths. These GPIOs are named with a special purpose (ENABLE, IDLE and RESET of the sensor).

>> > > +#include <linux/mfd/tps68470.h>
>> > > +#include <linux/module.h>
>> > > +#include <linux/platform_device.h>
>> >
>> > > +       if (offset >= TPS68470_N_REGULAR_GPIO) {
>> > > +               offset -= TPS68470_N_REGULAR_GPIO;
>> > > +               reg = TPS68470_REG_SGPO;
>> > > +       }
>> >
>> > Two GPIO chips makes this gone.
>
> Again, I'm not really worried about this driver, but the ACPI tables. How
> does the difference show there?

Same way. You will have common numbering over the chip [0, 9]. It will
be just an abstraction inside the driver.

> The outputs (s_enable, s_idle and s_resetn) are not numbered in the
> documentation. There grouped, though, but the order in that grouping varies.

I don't get this. You are telling that the property of "always output"
can be assigned to any 3 out of 10?
Above states the opposite, so, it's clear to me that abstraction of 2
GPIO chips over 1 can be utilized here.

>> > > +struct gpiod_lookup_table gpios_table = {
>> > > +       .dev_id = NULL,
>> > > +       .table = {
>> > > +                 GPIO_LOOKUP("tps68470-gpio", 0, "gpio.0", GPIO_ACTIVE_HIGH),
>> > > +                 GPIO_LOOKUP("tps68470-gpio", 1, "gpio.1", GPIO_ACTIVE_HIGH),
>> > > +                 GPIO_LOOKUP("tps68470-gpio", 2, "gpio.2", GPIO_ACTIVE_HIGH),
>> > > +                 GPIO_LOOKUP("tps68470-gpio", 3, "gpio.3", GPIO_ACTIVE_HIGH),
>> > > +                 GPIO_LOOKUP("tps68470-gpio", 4, "gpio.4", GPIO_ACTIVE_HIGH),
>> > > +                 GPIO_LOOKUP("tps68470-gpio", 5, "gpio.5", GPIO_ACTIVE_HIGH),
>> > > +                 GPIO_LOOKUP("tps68470-gpio", 6, "gpio.6", GPIO_ACTIVE_HIGH),
>> > > +                 GPIO_LOOKUP("tps68470-gpio", 7, "s_enable",
>> > GPIO_ACTIVE_HIGH),
>> > > +                 GPIO_LOOKUP("tps68470-gpio", 8, "s_idle", GPIO_ACTIVE_HIGH),
>> > > +                 GPIO_LOOKUP("tps68470-gpio", 9, "s_resetn",
>> > GPIO_ACTIVE_HIGH),
>> > > +                 {},
>> > > +       },
>> > > +};
>> >
>> > This doesn't belong to the driver.

>> I have moved this code to the MFD driver
>
> This information should come from the ACPI tables, it should not be present
> in drivers. Why do you need it?

+1 (asked same in review of new version)

>> > > +       /*
>> > > +        * Initialize all the GPIOs to 0, just to make sure all
>> > > +        * GPIOs start with known default values. This protects against
>> > > +        * any GPIOs getting set with a value of 1, after TPS68470
>> > > + reset
>> >
>> > So, this is hardware bug. Right? Or misconfiguration of the chip we may avoid?

>> The tps68470 PMIC upon reset, does not have the "power on reset" values.
>> We just initialize the GPIOs with their known default values.
>
> If that was the case, I bet you could expect interesting behaviour from the
> hardware connected to these pins.

+1. I don't believe the hardware / firmware doesn't care about clear
and always predictable state.

> For what it's worth, the chip documentation states that the reset value for
> the SGPO and GPDO registers is zero, as well as that GPIOs are configured as
> input and the reset value of the s_* outputs is low.
>
> In other words, I don't think that explicitly setting the values to zero has
> an effect.
Sakari Ailus June 11, 2017, 4:50 p.m. UTC | #7
Hi Andy,

On Sun, Jun 11, 2017 at 04:40:16PM +0300, Andy Shevchenko wrote:
> On Sun, Jun 11, 2017 at 2:30 PM, Sakari Ailus <sakari.ailus@iki.fi> wrote:
> > On Sun, Jun 11, 2017 at 03:49:18AM +0000, Mani, Rajmohan wrote:
> >> > On Tue, Jun 6, 2017 at 2:55 PM, Rajmohan Mani <rajmohan.mani@intel.com>
> >> > wrote:
> 
> >> > Besides my below comments, just put it here that I recommended earlier to
> >> > provide 2 GPIO chips (one per bank of GPIOs).
> >> > It's up to Linus to decide since you didn't follow the recommendation.
> 
> >> Did you mean to add this in Kconfig or this source file?
> >>
> >> Here's some more details on these GPIOs.
> >> Each of these 7 GPIOs has 2 registers to control the mode, level, drive strength, polarity, hysteresis control among other things. Also there are GPDI and GPDO registers to control the input and output values of these 7 GPIOs. These GPIOs are numbered 0 through 6.
> >> The remaining 3 GPIOs are more of special purpose GPIOs that are output only, with one register to control all of their output values and drive strengths. These GPIOs are named with a special purpose (ENABLE, IDLE and RESET of the sensor).
> 
> >> > > +#include <linux/mfd/tps68470.h>
> >> > > +#include <linux/module.h>
> >> > > +#include <linux/platform_device.h>
> >> >
> >> > > +       if (offset >= TPS68470_N_REGULAR_GPIO) {
> >> > > +               offset -= TPS68470_N_REGULAR_GPIO;
> >> > > +               reg = TPS68470_REG_SGPO;
> >> > > +       }
> >> >
> >> > Two GPIO chips makes this gone.
> >
> > Again, I'm not really worried about this driver, but the ACPI tables. How
> > does the difference show there?
> 
> Same way. You will have common numbering over the chip [0, 9]. It will
> be just an abstraction inside the driver.

Oh, in that case that should be a non-issue.

> 
> > The outputs (s_enable, s_idle and s_resetn) are not numbered in the
> > documentation. There grouped, though, but the order in that grouping varies.
> 
> I don't get this. You are telling that the property of "always output"
> can be assigned to any 3 out of 10?

No, I'm telling you that the three (s_enable, s_idle and s_resetn) cannot be
configured as inputs --- instead they're always outputs. That's how the
hardware is implemented.

> Above states the opposite, so, it's clear to me that abstraction of 2
> GPIO chips over 1 can be utilized here.

Sounds fine to me, taken that this does not add complications to ACPI
tables.
Andy Shevchenko June 11, 2017, 7:43 p.m. UTC | #8
On Sun, Jun 11, 2017 at 7:50 PM, Sakari Ailus <sakari.ailus@iki.fi> wrote:
> On Sun, Jun 11, 2017 at 04:40:16PM +0300, Andy Shevchenko wrote:
>> On Sun, Jun 11, 2017 at 2:30 PM, Sakari Ailus <sakari.ailus@iki.fi> wrote:

>> > Again, I'm not really worried about this driver, but the ACPI tables. How
>> > does the difference show there?
>>
>> Same way. You will have common numbering over the chip [0, 9]. It will
>> be just an abstraction inside the driver.
>
> Oh, in that case that should be a non-issue.

>> Above states the opposite, so, it's clear to me that abstraction of 2
>> GPIO chips over 1 can be utilized here.
>
> Sounds fine to me, taken that this does not add complications to ACPI
> tables.

They just need to share the same ACPI_HANDLE (it might require to do
this in generic way in gpiolib) and have a continuous numbering (easy
to achieve with carefully chosen bases).
Mani, Rajmohan June 12, 2017, 12:18 a.m. UTC | #9
Hi Linus,

> Subject: Re: [PATCH v1 2/3] gpio: Add support for TPS68470 GPIOs


> > +static inline struct tps68470_gpio_data *to_gpio_data(struct

> > +gpio_chip *gpiochp) {

> > +       return container_of(gpiochp, struct tps68470_gpio_data, gc); }

> 

> Please use the data pointe inside gpio_chip.

> 


My bad. I completely missed the following line. Will fix it v3.

> struct tps68470_gpio_data *foo = gpiochip_get_data(gc);

>
Mani, Rajmohan June 12, 2017, 9:17 a.m. UTC | #10
Hi Andy, Sakari,

> Subject: Re: [PATCH v1 2/3] gpio: Add support for TPS68470 GPIOs

> 

> On Sun, Jun 11, 2017 at 7:50 PM, Sakari Ailus <sakari.ailus@iki.fi> wrote:

> > On Sun, Jun 11, 2017 at 04:40:16PM +0300, Andy Shevchenko wrote:

> >> On Sun, Jun 11, 2017 at 2:30 PM, Sakari Ailus <sakari.ailus@iki.fi> wrote:

> 

> >> > Again, I'm not really worried about this driver, but the ACPI

> >> > tables. How does the difference show there?

> >>

> >> Same way. You will have common numbering over the chip [0, 9]. It

> >> will be just an abstraction inside the driver.

> >

> > Oh, in that case that should be a non-issue.

> 

> >> Above states the opposite, so, it's clear to me that abstraction of 2

> >> GPIO chips over 1 can be utilized here.

> >

> > Sounds fine to me, taken that this does not add complications to ACPI

> > tables.

> 

> They just need to share the same ACPI_HANDLE (it might require to do this in

> generic way in gpiolib) and have a continuous numbering (easy to achieve with

> carefully chosen bases).

> 


Few clarifications...

Are you implying new kernel changes are needed in gpiolib to accommodate 2 GPIO chips?
Does it need changes in platform firmware or is it expected to work just with the gpiolib changes that you described above?

Thanks
Raj
Andy Shevchenko June 12, 2017, 9:29 a.m. UTC | #11
On Mon, Jun 12, 2017 at 12:17 PM, Mani, Rajmohan
<rajmohan.mani@intel.com> wrote:
>> Subject: Re: [PATCH v1 2/3] gpio: Add support for TPS68470 GPIOs
>> On Sun, Jun 11, 2017 at 7:50 PM, Sakari Ailus <sakari.ailus@iki.fi> wrote:
>> > On Sun, Jun 11, 2017 at 04:40:16PM +0300, Andy Shevchenko wrote:
>> >> On Sun, Jun 11, 2017 at 2:30 PM, Sakari Ailus <sakari.ailus@iki.fi> wrote:

>> >> > Again, I'm not really worried about this driver, but the ACPI
>> >> > tables. How does the difference show there?
>> >>
>> >> Same way. You will have common numbering over the chip [0, 9]. It
>> >> will be just an abstraction inside the driver.

>> > Sounds fine to me, taken that this does not add complications to ACPI
>> > tables.
>>
>> They just need to share the same ACPI_HANDLE (it might require to do this in
>> generic way in gpiolib) and have a continuous numbering (easy to achieve with
>> carefully chosen bases).

> Few clarifications...
>
> Are you implying new kernel changes are needed in gpiolib to accommodate 2 GPIO chips?

Might be needed. It should be investigated first.
In any case it would be somelike oneliner.

> Does it need changes in platform firmware or is it expected to work just with the gpiolib changes that you described above?

No firmware changes are implied.
Mani, Rajmohan June 12, 2017, 9:51 a.m. UTC | #12
Hi Sakari,

> Subject: Re: [PATCH v1 2/3] gpio: Add support for TPS68470 GPIOs
> 
> Hi Rajmohan and Andy,
> 
> On Sun, Jun 11, 2017 at 03:49:18AM +0000, Mani, Rajmohan wrote:
> > Hi Andy,
> >
> > Thanks for the reviews and patience.
> >
> > >
> > > On Tue, Jun 6, 2017 at 2:55 PM, Rajmohan Mani
> > > <rajmohan.mani@intel.com>
> > > wrote:
> > > > This patch adds support for TPS68470 GPIOs.
> > > > There are 7 GPIOs and a few sensor related GPIOs.
> > > > These GPIOs can be requested and configured as appropriate.
> > >
> > > Besides my below comments, just put it here that I recommended
> > > earlier to provide 2 GPIO chips (one per bank of GPIOs).
> > > It's up to Linus to decide since you didn't follow the recommendation.
> > >
> >
> > Ack.
> > Did you mean to add this in Kconfig or this source file?
> >
> > Here's some more details on these GPIOs.
> > Each of these 7 GPIOs has 2 registers to control the mode, level, drive
> strength, polarity, hysteresis control among other things. Also there are GPDI
> and GPDO registers to control the input and output values of these 7 GPIOs.
> These GPIOs are numbered 0 through 6.
> > The remaining 3 GPIOs are more of special purpose GPIOs that are output
> only, with one register to control all of their output values and drive strengths.
> These GPIOs are named with a special purpose (ENABLE, IDLE and RESET of the
> sensor).
> >
> > > > +#include <linux/gpio.h>
> > > > +#include <linux/gpio/machine.h>
> > >
> > > These shouldn't be in the driver.
> > > Instead use
> > > #include <linux/gpio/driver.h>
> > >
> >
> > Ack
> >
> > > > +#include <linux/mfd/tps68470.h>
> > > > +#include <linux/module.h>
> > > > +#include <linux/platform_device.h>
> > >
> > > > +       if (offset >= TPS68470_N_REGULAR_GPIO) {
> > > > +               offset -= TPS68470_N_REGULAR_GPIO;
> > > > +               reg = TPS68470_REG_SGPO;
> > > > +       }
> > >
> > > Two GPIO chips makes this gone.
> 
> Again, I'm not really worried about this driver, but the ACPI tables. How does
> the difference show there?
> 
> The outputs (s_enable, s_idle and s_resetn) are not numbered in the
> documentation. There grouped, though, but the order in that grouping varies.
> 
> > > > +struct gpiod_lookup_table gpios_table = {
> > > > +       .dev_id = NULL,
> > > > +       .table = {
> > > > +                 GPIO_LOOKUP("tps68470-gpio", 0, "gpio.0",
> GPIO_ACTIVE_HIGH),
> > > > +                 GPIO_LOOKUP("tps68470-gpio", 1, "gpio.1",
> GPIO_ACTIVE_HIGH),
> > > > +                 GPIO_LOOKUP("tps68470-gpio", 2, "gpio.2",
> GPIO_ACTIVE_HIGH),
> > > > +                 GPIO_LOOKUP("tps68470-gpio", 3, "gpio.3",
> GPIO_ACTIVE_HIGH),
> > > > +                 GPIO_LOOKUP("tps68470-gpio", 4, "gpio.4",
> GPIO_ACTIVE_HIGH),
> > > > +                 GPIO_LOOKUP("tps68470-gpio", 5, "gpio.5",
> GPIO_ACTIVE_HIGH),
> > > > +                 GPIO_LOOKUP("tps68470-gpio", 6, "gpio.6",
> GPIO_ACTIVE_HIGH),
> > > > +                 GPIO_LOOKUP("tps68470-gpio", 7, "s_enable",
> > > GPIO_ACTIVE_HIGH),
> > > > +                 GPIO_LOOKUP("tps68470-gpio", 8, "s_idle",
> GPIO_ACTIVE_HIGH),
> > > > +                 GPIO_LOOKUP("tps68470-gpio", 9, "s_resetn",
> > > GPIO_ACTIVE_HIGH),
> > > > +                 {},
> > > > +       },
> > > > +};
> > >
> > > This doesn't belong to the driver.
> > >
> >
> > Ack
> > I have moved this code to the MFD driver
> 
> This information should come from the ACPI tables, it should not be present in
> drivers. Why do you need it?
> 

I have removed the GPIO lookup table code for now.

> > > > +       /*
> > > > +        * Initialize all the GPIOs to 0, just to make sure all
> > > > +        * GPIOs start with known default values. This protects against
> > > > +        * any GPIOs getting set with a value of 1, after TPS68470
> > > > + reset
> > >
> > > So, this is hardware bug. Right? Or misconfiguration of the chip we may
> avoid?
> > >
> >
> > The tps68470 PMIC upon reset, does not have the "power on reset" values.
> > We just initialize the GPIOs with their known default values.
> 
> If that was the case, I bet you could expect interesting behaviour from the
> hardware connected to these pins.
> 
> For what it's worth, the chip documentation states that the reset value for the
> SGPO and GPDO registers is zero, as well as that GPIOs are configured as input
> and the reset value of the s_* outputs is low.
> 
> In other words, I don't think that explicitly setting the values to zero has an
> effect.
>

For now, I have removed this code that sets the GPIOs to zeros. If there are enough findings / reasons, this code may come back.
--
To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 23ca51e..ed34f9b 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1041,6 +1041,16 @@  config GPIO_TPS65912
 	help
 	  This driver supports TPS65912 gpio chip
 
+config GPIO_TPS68470
+	bool "TPS68470 GPIO"
+	depends on MFD_TPS68470
+	help
+	  Select this option to enable GPIO driver for the TPS68470
+	  chip family.
+	  There are 7 GPIOs and few sensor related GPIOs supported
+	  by the TPS68470. These GPIOs can be requested and
+	  configured as appropriate, with this driver.
+
 config GPIO_TWL4030
 	tristate "TWL4030, TWL5030, and TPS659x0 GPIOs"
 	depends on TWL4030_CORE
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 68b9627..a2659cb 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -120,6 +120,7 @@  obj-$(CONFIG_GPIO_TPS65218)	+= gpio-tps65218.o
 obj-$(CONFIG_GPIO_TPS6586X)	+= gpio-tps6586x.o
 obj-$(CONFIG_GPIO_TPS65910)	+= gpio-tps65910.o
 obj-$(CONFIG_GPIO_TPS65912)	+= gpio-tps65912.o
+obj-$(CONFIG_GPIO_TPS68470)	+= gpio-tps68470.o
 obj-$(CONFIG_GPIO_TS4800)	+= gpio-ts4800.o
 obj-$(CONFIG_GPIO_TS4900)	+= gpio-ts4900.o
 obj-$(CONFIG_GPIO_TS5500)	+= gpio-ts5500.o
diff --git a/drivers/gpio/gpio-tps68470.c b/drivers/gpio/gpio-tps68470.c
new file mode 100644
index 0000000..b599a66
--- /dev/null
+++ b/drivers/gpio/gpio-tps68470.c
@@ -0,0 +1,185 @@ 
+/*
+ * GPIO driver for TPS68470 PMIC
+ *
+ * Copyright (C) 2017 Intel Corporation
+ * Authors:
+ * Antti Laakso <antti.laakso@intel.com>
+ * Tianshu Qiu <tian.shu.qiu@intel.com>
+ * Jian Xu Zheng <jian.xu.zheng@intel.com>
+ * Yuning Pu <yuning.pu@intel.com>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/gpio.h>
+#include <linux/gpio/machine.h>
+#include <linux/mfd/tps68470.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#define TPS68470_N_LOGIC_OUTPUT	3
+#define TPS68470_N_REGULAR_GPIO	7
+#define TPS68470_N_GPIO	(TPS68470_N_LOGIC_OUTPUT + TPS68470_N_REGULAR_GPIO)
+
+struct tps68470_gpio_data {
+	struct tps68470 *tps68470;
+	struct gpio_chip gc;
+};
+
+static inline struct tps68470_gpio_data *to_gpio_data(struct gpio_chip *gpiochp)
+{
+	return container_of(gpiochp, struct tps68470_gpio_data, gc);
+}
+
+static int tps68470_gpio_get(struct gpio_chip *gc, unsigned int offset)
+{
+	struct tps68470_gpio_data *tps68470_gpio = to_gpio_data(gc);
+	struct tps68470 *tps = tps68470_gpio->tps68470;
+	unsigned int reg = TPS68470_REG_GPDO;
+	int val, ret;
+
+	if (offset >= TPS68470_N_REGULAR_GPIO) {
+		offset -= TPS68470_N_REGULAR_GPIO;
+		reg = TPS68470_REG_SGPO;
+	}
+
+	ret = tps68470_reg_read(tps, reg, &val);
+	if (ret) {
+		dev_err(tps->dev, "reg 0x%x read failed\n", TPS68470_REG_SGPO);
+		return ret;
+	}
+	return !!(val & BIT(offset));
+}
+
+static void tps68470_gpio_set(struct gpio_chip *gc, unsigned int offset,
+				int value)
+{
+	struct tps68470_gpio_data *tps68470_gpio = to_gpio_data(gc);
+	struct tps68470 *tps = tps68470_gpio->tps68470;
+	unsigned int reg = TPS68470_REG_GPDO;
+
+	if (offset >= TPS68470_N_REGULAR_GPIO) {
+		reg = TPS68470_REG_SGPO;
+		offset -= TPS68470_N_REGULAR_GPIO;
+	}
+
+	tps68470_update_bits(tps, reg, BIT(offset), value ? BIT(offset) : 0);
+}
+
+static int tps68470_gpio_output(struct gpio_chip *gc, unsigned int offset,
+				int value)
+{
+	struct tps68470_gpio_data *tps68470_gpio = to_gpio_data(gc);
+	struct tps68470 *tps = tps68470_gpio->tps68470;
+
+	/* rest are always outputs */
+	if (offset >= TPS68470_N_REGULAR_GPIO)
+		return 0;
+
+	/* Set the initial value */
+	tps68470_gpio_set(gc, offset, value);
+
+	return tps68470_update_bits(tps, TPS68470_GPIO_CTL_REG_A(offset),
+				 TPS68470_GPIO_MODE_MASK,
+				 TPS68470_GPIO_MODE_OUT_CMOS);
+}
+
+static int tps68470_gpio_input(struct gpio_chip *gc, unsigned int offset)
+{
+	struct tps68470_gpio_data *tps68470_gpio = to_gpio_data(gc);
+	struct tps68470 *tps = tps68470_gpio->tps68470;
+
+	/* rest are always outputs */
+	if (offset >= TPS68470_N_REGULAR_GPIO)
+		return -EINVAL;
+
+	return tps68470_update_bits(tps, TPS68470_GPIO_CTL_REG_A(offset),
+				   TPS68470_GPIO_MODE_MASK, 0x00);
+}
+
+struct gpiod_lookup_table gpios_table = {
+	.dev_id = NULL,
+	.table = {
+		  GPIO_LOOKUP("tps68470-gpio", 0, "gpio.0", GPIO_ACTIVE_HIGH),
+		  GPIO_LOOKUP("tps68470-gpio", 1, "gpio.1", GPIO_ACTIVE_HIGH),
+		  GPIO_LOOKUP("tps68470-gpio", 2, "gpio.2", GPIO_ACTIVE_HIGH),
+		  GPIO_LOOKUP("tps68470-gpio", 3, "gpio.3", GPIO_ACTIVE_HIGH),
+		  GPIO_LOOKUP("tps68470-gpio", 4, "gpio.4", GPIO_ACTIVE_HIGH),
+		  GPIO_LOOKUP("tps68470-gpio", 5, "gpio.5", GPIO_ACTIVE_HIGH),
+		  GPIO_LOOKUP("tps68470-gpio", 6, "gpio.6", GPIO_ACTIVE_HIGH),
+		  GPIO_LOOKUP("tps68470-gpio", 7, "s_enable", GPIO_ACTIVE_HIGH),
+		  GPIO_LOOKUP("tps68470-gpio", 8, "s_idle", GPIO_ACTIVE_HIGH),
+		  GPIO_LOOKUP("tps68470-gpio", 9, "s_resetn", GPIO_ACTIVE_HIGH),
+		  {},
+	},
+};
+
+static int tps68470_gpio_probe(struct platform_device *pdev)
+{
+	struct tps68470 *tps68470 = dev_get_drvdata(pdev->dev.parent);
+	struct tps68470_gpio_data *tps68470_gpio;
+	int i, ret;
+
+	tps68470_gpio = devm_kzalloc(&pdev->dev, sizeof(*tps68470_gpio),
+				     GFP_KERNEL);
+	if (!tps68470_gpio)
+		return -ENOMEM;
+
+	tps68470_gpio->tps68470 = tps68470;
+	tps68470_gpio->gc.label = "tps68470-gpio";
+	tps68470_gpio->gc.owner = THIS_MODULE;
+	tps68470_gpio->gc.direction_input = tps68470_gpio_input;
+	tps68470_gpio->gc.direction_output = tps68470_gpio_output;
+	tps68470_gpio->gc.get = tps68470_gpio_get;
+	tps68470_gpio->gc.set = tps68470_gpio_set;
+	tps68470_gpio->gc.can_sleep = true;
+	tps68470_gpio->gc.ngpio = TPS68470_N_GPIO;
+	tps68470_gpio->gc.base = -1;
+	tps68470_gpio->gc.parent = &pdev->dev;
+
+	ret = gpiochip_add(&tps68470_gpio->gc);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to register gpio_chip: %d\n", ret);
+		return ret;
+	}
+
+	gpiod_add_lookup_table(&gpios_table);
+
+	platform_set_drvdata(pdev, tps68470_gpio);
+
+	/*
+	 * Initialize all the GPIOs to 0, just to make sure all
+	 * GPIOs start with known default values. This protects against
+	 * any GPIOs getting set with a value of 1, after TPS68470 reset
+	 */
+	for (i = 0; i < tps68470_gpio->gc.ngpio; i++)
+		tps68470_gpio_set(&tps68470_gpio->gc, i, 0);
+
+	return ret;
+}
+
+static int tps68470_gpio_remove(struct platform_device *pdev)
+{
+	struct tps68470_gpio_data *tps68470_gpio = platform_get_drvdata(pdev);
+
+	gpiod_remove_lookup_table(&gpios_table);
+	gpiochip_remove(&tps68470_gpio->gc);
+
+	return 0;
+}
+
+static struct platform_driver tps68470_gpio_driver = {
+	.driver = {
+		   .name = "tps68470-gpio",
+	},
+	.probe = tps68470_gpio_probe,
+	.remove = tps68470_gpio_remove,
+};
+
+builtin_platform_driver(tps68470_gpio_driver)