int twl6040_power(struct twl6040 *twl6040, int on) { int ret = 0; mutex_lock(&twl6040->mutex); if (on) { /* already powered-up */ if (twl6040->power_count++) goto out; if (gpio_is_valid(twl6040->audpwron)) { /* use automatic power-up sequence */ ret = twl6040_power_up_automatic(twl6040); if (ret) { twl6040->power_count = 0; goto out; } } else { /* use manual power-up sequence */ ret = twl6040_power_up_manual(twl6040); if (ret) { twl6040->power_count = 0; goto out; } } /* Default PLL configuration after power up */ twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL; twl6040->sysclk = 19200000; twl6040->mclk = 32768; } else { /* already powered-down */ if (!twl6040->power_count) { dev_err(twl6040->dev, "device is already powered-off\n"); ret = -EPERM; goto out; } if (--twl6040->power_count) goto out; if (gpio_is_valid(twl6040->audpwron)) { /* use AUDPWRON line */ gpio_set_value(twl6040->audpwron, 0); /* power-down sequence latency */ usleep_range(500, 700); } else { /* use manual power-down sequence */ twl6040_power_down_manual(twl6040); } twl6040->sysclk = 0; twl6040->mclk = 0; } out: mutex_unlock(&twl6040->mutex); return ret; }
int twl6040_power(struct twl6040 *twl6040, int on) { int ret = 0; mutex_lock(&twl6040->mutex); if (on) { /* already powered-up */ if (twl6040->power_count++) goto out; ret = clk_prepare_enable(twl6040->clk32k); if (ret) { twl6040->power_count = 0; goto out; } /* Allow writes to the chip */ regcache_cache_only(twl6040->regmap, false); if (gpio_is_valid(twl6040->audpwron)) { /* use automatic power-up sequence */ ret = twl6040_power_up_automatic(twl6040); if (ret) { clk_disable_unprepare(twl6040->clk32k); twl6040->power_count = 0; goto out; } } else { /* use manual power-up sequence */ ret = twl6040_power_up_manual(twl6040); if (ret) { clk_disable_unprepare(twl6040->clk32k); twl6040->power_count = 0; goto out; } } /* * Register access can produce errors after power-up unless we * wait at least 8ms based on measurements on duovero. */ usleep_range(10000, 12000); /* Sync with the HW */ ret = regcache_sync(twl6040->regmap); if (ret) { dev_err(twl6040->dev, "Failed to sync with the HW: %i\n", ret); goto out; } /* Default PLL configuration after power up */ twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL; twl6040->sysclk_rate = 19200000; } else { /* already powered-down */ if (!twl6040->power_count) { dev_err(twl6040->dev, "device is already powered-off\n"); ret = -EPERM; goto out; } if (--twl6040->power_count) goto out; if (gpio_is_valid(twl6040->audpwron)) { /* use AUDPWRON line */ gpio_set_value(twl6040->audpwron, 0); /* power-down sequence latency */ usleep_range(500, 700); } else { /* use manual power-down sequence */ twl6040_power_down_manual(twl6040); } /* Set regmap to cache only and mark it as dirty */ regcache_cache_only(twl6040->regmap, true); regcache_mark_dirty(twl6040->regmap); twl6040->sysclk_rate = 0; if (twl6040->pll == TWL6040_SYSCLK_SEL_HPPLL) { clk_disable_unprepare(twl6040->mclk); twl6040->mclk_rate = 0; } clk_disable_unprepare(twl6040->clk32k); } out: mutex_unlock(&twl6040->mutex); return ret; }
int twl6040_power(struct twl6040 *twl6040, int on) { int ret = 0; mutex_lock(&twl6040->mutex); if (on) { /* already powered-up */ if (twl6040->power_count++) goto out; clk_prepare_enable(twl6040->clk32k); /* Allow writes to the chip */ regcache_cache_only(twl6040->regmap, false); if (gpio_is_valid(twl6040->audpwron)) { /* use automatic power-up sequence */ ret = twl6040_power_up_automatic(twl6040); if (ret) { twl6040->power_count = 0; goto out; } } else { /* use manual power-up sequence */ ret = twl6040_power_up_manual(twl6040); if (ret) { twl6040->power_count = 0; goto out; } } /* Sync with the HW */ regcache_sync(twl6040->regmap); /* Default PLL configuration after power up */ twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL; twl6040->sysclk = 19200000; twl6040->mclk = 32768; } else { /* already powered-down */ if (!twl6040->power_count) { dev_err(twl6040->dev, "device is already powered-off\n"); ret = -EPERM; goto out; } if (--twl6040->power_count) goto out; if (gpio_is_valid(twl6040->audpwron)) { /* use AUDPWRON line */ gpio_set_value(twl6040->audpwron, 0); /* power-down sequence latency */ usleep_range(500, 700); } else { /* use manual power-down sequence */ twl6040_power_down_manual(twl6040); } /* Set regmap to cache only and mark it as dirty */ regcache_cache_only(twl6040->regmap, true); regcache_mark_dirty(twl6040->regmap); twl6040->sysclk = 0; twl6040->mclk = 0; clk_disable_unprepare(twl6040->clk32k); } out: mutex_unlock(&twl6040->mutex); return ret; }