extres/regulator: Properly refcount gpio regulators

regnode::enable_cnt is generally used to refcount regulator nodes. For
GPIOs, the refcount was done on the gpio_entry since more than one regulator
can share a GPIO.

GPIO regulators were not taking part in the node refcount, since they had
their own mechanism. This caused some fallout after manu started disabling
everybody's unused regulators in r331989.

Refcount it.

Glanced over by:	manu
This commit is contained in:
Kyle Evans 2018-06-14 20:37:25 +00:00
parent 61a835e403
commit cba506f2c1
3 changed files with 20 additions and 0 deletions

View File

@ -507,6 +507,20 @@ struct regnode_std_param *regnode_get_stdparam(struct regnode *regnode)
return (&regnode->std_param); return (&regnode->std_param);
} }
void
regnode_enable_cnt_inc(struct regnode *regnode)
{
regnode->enable_cnt++;
}
void
regnode_enable_cnt_dec(struct regnode *regnode)
{
regnode->enable_cnt--;
}
void regnode_topo_unlock(void) void regnode_topo_unlock(void)
{ {

View File

@ -106,6 +106,8 @@ int regnode_get_flags(struct regnode *regnode);
void *regnode_get_softc(struct regnode *regnode); void *regnode_get_softc(struct regnode *regnode);
device_t regnode_get_device(struct regnode *regnode); device_t regnode_get_device(struct regnode *regnode);
struct regnode_std_param *regnode_get_stdparam(struct regnode *regnode); struct regnode_std_param *regnode_get_stdparam(struct regnode *regnode);
void regnode_enable_cnt_inc(struct regnode *regnode);
void regnode_enable_cnt_dec(struct regnode *regnode);
void regnode_topo_unlock(void); void regnode_topo_unlock(void);
void regnode_topo_xlock(void); void regnode_topo_xlock(void);
void regnode_topo_slock(void); void regnode_topo_slock(void);

View File

@ -156,6 +156,8 @@ regnode_fixed_init(struct regnode *regnode)
if (sc->gpio_open_drain) if (sc->gpio_open_drain)
flags |= GPIO_PIN_OPENDRAIN; flags |= GPIO_PIN_OPENDRAIN;
enable = sc->param->boot_on || sc->param->always_on; enable = sc->param->boot_on || sc->param->always_on;
if (enable)
regnode_enable_cnt_inc(regnode);
if (!sc->param->enable_active_high) if (!sc->param->enable_active_high)
enable = !enable; enable = !enable;
rv = GPIO_PIN_SET(pin->dev, pin->pin, enable); rv = GPIO_PIN_SET(pin->dev, pin->pin, enable);
@ -194,12 +196,14 @@ regnode_fixed_enable(struct regnode *regnode, bool enable, int *udelay)
return (0); return (0);
pin = &sc->gpio_entry->gpio_pin; pin = &sc->gpio_entry->gpio_pin;
if (enable) { if (enable) {
regnode_enable_cnt_inc(regnode);
sc->gpio_entry->enable_cnt++; sc->gpio_entry->enable_cnt++;
if (sc->gpio_entry->enable_cnt > 1) if (sc->gpio_entry->enable_cnt > 1)
return (0); return (0);
} else { } else {
KASSERT(sc->gpio_entry->enable_cnt > 0, KASSERT(sc->gpio_entry->enable_cnt > 0,
("Invalid enable count")); ("Invalid enable count"));
regnode_enable_cnt_dec(regnode);
sc->gpio_entry->enable_cnt--; sc->gpio_entry->enable_cnt--;
if (sc->gpio_entry->enable_cnt >= 1) if (sc->gpio_entry->enable_cnt >= 1)
return (0); return (0);