[PATCH 1/2] ASoC: da7219: Reset codec gracefully, if still active
Currently the reset code in i2c_probe only resets the AAD part of the device and not the entire codec. This patch updates the driver to resolve this and ensures that if the codec is still active from a previous boot then the audio paths are powered down prior to reset. Signed-off-by: Adam Thomson --- sound/soc/codecs/da7219.c | 30 +++--- sound/soc/codecs/da7219.h | 5 + 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 9d08c11..eecb6d6 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -1925,7 +1925,8 @@ static int da7219_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct da7219_priv *da7219; - int ret; + unsigned int system_active, system_status; + int i, ret; da7219 = devm_kzalloc(&i2c->dev, sizeof(struct da7219_priv), GFP_KERNEL); @@ -1941,14 +1942,37 @@ static int da7219_i2c_probe(struct i2c_client *i2c, return ret; } - /* Software reset codec. */ + regcache_cache_bypass(da7219->regmap, true); + + /* Disable audio paths if still active from previous start */ + regmap_read(da7219->regmap, DA7219_SYSTEM_ACTIVE, &system_active); + if (system_active) { + regmap_write(da7219->regmap, DA7219_GAIN_RAMP_CTRL, +DA7219_GAIN_RAMP_RATE_NOMINAL); + regmap_write(da7219->regmap, DA7219_SYSTEM_MODES_INPUT, 0x00); + regmap_write(da7219->regmap, DA7219_SYSTEM_MODES_OUTPUT, 0x01); + + for (i = 0; i < DA7219_SYS_STAT_CHECK_RETRIES; ++i) { + regmap_read(da7219->regmap, DA7219_SYSTEM_STATUS, + &system_status); + if (!system_status) + break; + + msleep(DA7219_SYS_STAT_CHECK_DELAY); + } + } + + /* Soft reset codec */ regmap_write_bits(da7219->regmap, DA7219_ACCDET_CONFIG_1, DA7219_ACCDET_EN_MASK, 0); regmap_write_bits(da7219->regmap, DA7219_CIF_CTRL, - DA7219_CIF_REG_SOFT_RESET_MASK, 0); + DA7219_CIF_REG_SOFT_RESET_MASK, + DA7219_CIF_REG_SOFT_RESET_MASK); regmap_write_bits(da7219->regmap, DA7219_SYSTEM_ACTIVE, DA7219_SYSTEM_ACTIVE_MASK, 0); + regcache_cache_bypass(da7219->regmap, false); + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_da7219, &da7219_dai, 1); if (ret < 0) { diff --git a/sound/soc/codecs/da7219.h b/sound/soc/codecs/da7219.h index 545576d..f1b3ad8 100644 --- a/sound/soc/codecs/da7219.h +++ b/sound/soc/codecs/da7219.h @@ -578,6 +578,7 @@ #define DA7219_GAIN_RAMP_RATE_SHIFT0 #define DA7219_GAIN_RAMP_RATE_MASK (0x3 << 0) #define DA7219_GAIN_RAMP_RATE_X8 (0x0 << 0) +#define DA7219_GAIN_RAMP_RATE_NOMINAL (0x1 << 0) #define DA7219_GAIN_RAMP_RATE_MAX 4 /* DA7219_PC_COUNT = 0x94 */ @@ -772,6 +773,10 @@ /* SRM */ #define DA7219_SRM_CHECK_RETRIES 8 +/* System Controller */ +#define DA7219_SYS_STAT_CHECK_RETRIES 6 +#define DA7219_SYS_STAT_CHECK_DELAY50 + enum da7219_clk_src { DA7219_CLKSRC_MCLK = 0, DA7219_CLKSRC_MCLK_SQR, -- 1.9.3
[PATCH 0/2] ASoC: da7219: Codec soft reset and AAD improvements
This patch set makes the following updates to the driver code: 1) Ensures codec is properly reset at startup, and if previously active then disable audio paths prior to reset. 2) Disables AAD in suspend, if device is not a wake-up source. Changes are based on top of latest code introduced under the following commits: ASoC: da7219: software reset codec at probe ASoC: da7219: Support HP detect procedure when MCLK not present Adam Thomson (2): ASoC: da7219: Reset codec gracefully, if still active ASoC: da7219: Disable AAD if codec is not a wake-up source include/sound/da7219.h| 2 ++ sound/soc/codecs/da7219-aad.c | 56 sound/soc/codecs/da7219-aad.h | 5 sound/soc/codecs/da7219.c | 60 +++ sound/soc/codecs/da7219.h | 6 + 5 files changed, 113 insertions(+), 16 deletions(-) -- 1.9.3
[PATCH 2/2] ASoC: da7219: Disable AAD if codec is not a wake-up source
Currently if AAD is enabled in the device, during system suspend the feature remains, regardless of whether the codec is a wake-up source or not. This means some additional power is being used which is unnecessary, and can causes issues with some platforms' IRQ handlers where state changes during system suspend aren't captured. This patch updates the driver to disable AAD during suspend, if we're not a wake-up source, and then re-enables this on resume. Signed-off-by: Adam Thomson --- include/sound/da7219.h| 2 ++ sound/soc/codecs/da7219-aad.c | 56 +++ sound/soc/codecs/da7219-aad.h | 5 sound/soc/codecs/da7219.c | 30 +-- sound/soc/codecs/da7219.h | 1 + 5 files changed, 81 insertions(+), 13 deletions(-) diff --git a/include/sound/da7219.h b/include/sound/da7219.h index 02876ac..409ef139 100644 --- a/include/sound/da7219.h +++ b/include/sound/da7219.h @@ -34,6 +34,8 @@ enum da7219_mic_amp_in_sel { struct da7219_aad_pdata; struct da7219_pdata { + bool wakeup_source; + /* Mic */ enum da7219_micbias_voltage micbias_lvl; enum da7219_mic_amp_in_sel mic_amp_in_sel; diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index fc27dab..2b8914d 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c @@ -797,6 +797,62 @@ static void da7219_aad_handle_pdata(struct snd_soc_codec *codec) /* + * Suspend/Resume + */ + +void da7219_aad_suspend(struct snd_soc_codec *codec) +{ + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); + struct da7219_aad_priv *da7219_aad = da7219->aad; + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + u8 micbias_ctrl; + + if (da7219_aad->jack) { + /* Disable jack detection during suspend */ + snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, + DA7219_ACCDET_EN_MASK, 0); + + /* +* If we have a 4-pole jack inserted, then micbias will be +* enabled. We can disable micbias here, and keep a note to +* re-enable it on resume. If jack removal occurred during +* suspend then this will be dealt with through the IRQ handler. +*/ + if (da7219_aad->jack_inserted) { + micbias_ctrl = snd_soc_read(codec, DA7219_MICBIAS_CTRL); + if (micbias_ctrl & DA7219_MICBIAS1_EN_MASK) { + snd_soc_dapm_disable_pin(dapm, "Mic Bias"); + snd_soc_dapm_sync(dapm); + da7219_aad->micbias_resume_enable = true; + } + } + } +} + +void da7219_aad_resume(struct snd_soc_codec *codec) +{ + struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); + struct da7219_aad_priv *da7219_aad = da7219->aad; + struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); + + if (da7219_aad->jack) { + /* Re-enable micbias if previously enabled for 4-pole jack */ + if (da7219_aad->jack_inserted && + da7219_aad->micbias_resume_enable) { + snd_soc_dapm_force_enable_pin(dapm, "Mic Bias"); + snd_soc_dapm_sync(dapm); + da7219_aad->micbias_resume_enable = false; + } + + /* Re-enable jack detection */ + snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, + DA7219_ACCDET_EN_MASK, + DA7219_ACCDET_EN_MASK); + } +} + + +/* * Init/Exit */ diff --git a/sound/soc/codecs/da7219-aad.h b/sound/soc/codecs/da7219-aad.h index a34be48..117a3d7 100644 --- a/sound/soc/codecs/da7219-aad.h +++ b/sound/soc/codecs/da7219-aad.h @@ -201,12 +201,17 @@ struct da7219_aad_priv { struct work_struct hptest_work; struct snd_soc_jack *jack; + bool micbias_resume_enable; bool jack_inserted; }; /* AAD control */ void da7219_aad_jack_det(struct snd_soc_codec *codec, struct snd_soc_jack *jack); +/* Suspend/Resume */ +void da7219_aad_suspend(struct snd_soc_codec *codec); +void da7219_aad_resume(struct snd_soc_codec *codec); + /* Init/Exit */ int da7219_aad_init(struct snd_soc_codec *codec); void da7219_aad_exit(struct snd_soc_codec *codec); diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index eecb6d6..65f7e98 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -1482,6 +1482,8 @@ static struct da7219_pdata *da7219_fw_to_pdata(struct snd_soc_codec *codec) if (!pdata) return NULL; + pdata->wakeup_source = device_property_read_bool(dev, "wakeup-source
[PATCH] ASoC: da7219: Make more efficient use of MCLK within driver
Currently, if the driver has control of MCLK then it remains enabled as long as the codec is in STANDBY or above. The MCLK is only really required in STANDBY when a 3-pole jack is inserted and the HP detect procedure is required to run. This patch updates the code to enable/disable the MCLK when moving between the STANDBY and PREPARE bias level, and when a 3-pole jack is inserted and HP detection is required, thus saving power at all other times. Signed-off-by: Adam Thomson --- sound/soc/codecs/da7219-aad.c | 18 +- sound/soc/codecs/da7219.c | 18 +++--- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index f0057cd..4e369a1 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -115,12 +116,23 @@ static void da7219_aad_hptest_work(struct work_struct *work) u16 tonegen_freq_hptest; u8 accdet_cfg8; - int report = 0; + int report = 0, ret = 0; /* Lock DAPM and any Kcontrols that are affected by this test */ snd_soc_dapm_mutex_lock(dapm); mutex_lock(&da7219->lock); + /* Ensure MCLK is available for HP test procedure */ + if (da7219->mclk) { + ret = clk_prepare_enable(da7219->mclk); + if (ret) { + dev_err(codec->dev, "Failed to enable mclk - %d\n", ret); + mutex_unlock(&da7219->lock); + snd_soc_dapm_mutex_unlock(dapm); + return; + } + } + /* Bypass cache so it saves current settings */ regcache_cache_bypass(da7219->regmap, true); @@ -250,6 +262,10 @@ static void da7219_aad_hptest_work(struct work_struct *work) snd_soc_update_bits(codec, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK, DA7219_HP_R_AMP_OE_MASK); + /* Remove MCLK, if previously enabled */ + if (da7219->mclk) + clk_disable_unprepare(da7219->mclk); + mutex_unlock(&da7219->lock); snd_soc_dapm_mutex_unlock(dapm); diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 50ea943..737e914 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -1508,11 +1508,10 @@ static int da7219_set_bias_level(struct snd_soc_codec *codec, switch (level) { case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: break; - case SND_SOC_BIAS_STANDBY: - if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { - /* MCLK */ + case SND_SOC_BIAS_PREPARE: + /* Enable MCLK for transition to ON state */ + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) { if (da7219->mclk) { ret = clk_prepare_enable(da7219->mclk); if (ret) { @@ -1521,11 +1520,19 @@ static int da7219_set_bias_level(struct snd_soc_codec *codec, return ret; } } + } + break; + case SND_SOC_BIAS_STANDBY: + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { /* Master bias */ snd_soc_update_bits(codec, DA7219_REFERENCES, DA7219_BIAS_EN_MASK, DA7219_BIAS_EN_MASK); + } else { + /* Remove MCLK */ + if (da7219->mclk) + clk_disable_unprepare(da7219->mclk); } break; case SND_SOC_BIAS_OFF: @@ -1534,9 +1541,6 @@ static int da7219_set_bias_level(struct snd_soc_codec *codec, snd_soc_update_bits(codec, DA7219_REFERENCES, DA7219_BIAS_EN_MASK, 0); - /* MCLK */ - if (da7219->mclk) - clk_disable_unprepare(da7219->mclk); break; } -- 1.9.3
[PATCH 2/4] ASoC: da7213: Improve driver efficiency with regards to MCLK usage
Currently MCLK remains enabled during bias STANDBY state, and this is not necessary. This patch updates the code to handle enabling and disabling of MCLK, if provided, when moving between STANDBY and PREPARE states, therefore saving power when no active streams present. Signed-off-by: Adam Thomson --- sound/soc/codecs/da7213.c | 20 +++- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index bcf1834..7701f4e 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -1454,11 +1454,10 @@ static int da7213_set_bias_level(struct snd_soc_codec *codec, switch (level) { case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: break; - case SND_SOC_BIAS_STANDBY: - if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { - /* MCLK */ + case SND_SOC_BIAS_PREPARE: + /* Enable MCLK for transition to ON state */ + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) { if (da7213->mclk) { ret = clk_prepare_enable(da7213->mclk); if (ret) { @@ -1467,21 +1466,24 @@ static int da7213_set_bias_level(struct snd_soc_codec *codec, return ret; } } - + } + break; + case SND_SOC_BIAS_STANDBY: + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { /* Enable VMID reference & master bias */ snd_soc_update_bits(codec, DA7213_REFERENCES, DA7213_VMID_EN | DA7213_BIAS_EN, DA7213_VMID_EN | DA7213_BIAS_EN); + } else { + /* Remove MCLK */ + if (da7213->mclk) + clk_disable_unprepare(da7213->mclk); } break; case SND_SOC_BIAS_OFF: /* Disable VMID reference & master bias */ snd_soc_update_bits(codec, DA7213_REFERENCES, DA7213_VMID_EN | DA7213_BIAS_EN, 0); - - /* MCLK */ - if (da7213->mclk) - clk_disable_unprepare(da7213->mclk); break; } return 0; -- 1.9.3
RE: [alsa-devel] [PATCH 3/4] ASoC: da7213: Refactor sysclk(), pll() functions to improve handling
On 08 August 2016 08:43, Peter Meerwald-Stadler wrote: > > Currently the handling of the PLL in the driver is a little clunky, > > and not ideal for all modes. This patch updates the code to make it > > cleaner and more sensible for the various PLL states. > > > > Key items of note are: > > - MCLK squaring is now handled directly as part of the sysclk() > >function, removing the need for a private flag to set this feature. > > - All PLL modes are defined as an enum, and are handled as a case > >statement in pll() function to clean up configuration. This also > >removes any need for a private flag for SRM. > > - For 32KHz mode, checks are made on codec master mode and correct > >MCLK rates, to avoid incorrect usage of PLL for this operation. > > - For 32KHz mode, SRM flag now correctly enabled and fout set to > >sensible value to achieve appropriate PLL dividers. > > thanks, looks good > Tested-by: Peter Meerwald-Stadler > > nitpick: add extra newline at the end of > if (da7213->mclk_rate == 32768) block > Thanks. Glad the patch set has resolved issues you were seeing. Patches have been pulled by Mark.
[PATCH 0/2] ASoC: da7218: Small clocking related updates for driver
This patch set contains two updates relating to clocking. The first removes the 32KHz PLL feature as this is no longer supported, and the second provides MCLK effciency improvements to avoid unnecessary MCLK enabling. Changes are based on v4.8-rc1 Linux kernel. Adam Thomson (2): ASoC: da7218: Remove 32KHz PLL mode from driver ASoC: da7218: Improve driver efficiency with regards to MCLK usage sound/soc/codecs/da7218.c | 34 +++--- sound/soc/codecs/da7218.h | 2 -- 2 files changed, 15 insertions(+), 21 deletions(-) -- 1.9.3
[PATCH 2/2] ASoC: da7218: Improve driver efficiency with regards to MCLK usage
Currently MCLK remains enabled during bias STANDBY state, and this is not necessary. This patch updates the code to handle enabling and disabling of MCLK, if provided, when moving between STANDBY and PREPARE states, therefore saving power when no active streams present. Signed-off-by: Adam Thomson --- sound/soc/codecs/da7218.c | 22 -- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c index f443519..e7f3e4c 100644 --- a/sound/soc/codecs/da7218.c +++ b/sound/soc/codecs/da7218.c @@ -2583,20 +2583,22 @@ static int da7218_set_bias_level(struct snd_soc_codec *codec, switch (level) { case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: break; - case SND_SOC_BIAS_STANDBY: - if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { - /* MCLK */ + case SND_SOC_BIAS_PREPARE: + /* Enable MCLK for transition to ON state */ + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_STANDBY) { if (da7218->mclk) { ret = clk_prepare_enable(da7218->mclk); if (ret) { - dev_err(codec->dev, - "Failed to enable mclk\n"); + dev_err(codec->dev, "Failed to enable mclk\n"); return ret; } } + } + break; + case SND_SOC_BIAS_STANDBY: + if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { /* Master bias */ snd_soc_update_bits(codec, DA7218_REFERENCES, DA7218_BIAS_EN_MASK, @@ -2606,6 +2608,10 @@ static int da7218_set_bias_level(struct snd_soc_codec *codec, snd_soc_update_bits(codec, DA7218_LDO_CTRL, DA7218_LDO_EN_MASK, DA7218_LDO_EN_MASK); + } else { + /* Remove MCLK */ + if (da7218->mclk) + clk_disable_unprepare(da7218->mclk); } break; case SND_SOC_BIAS_OFF: @@ -2619,10 +2625,6 @@ static int da7218_set_bias_level(struct snd_soc_codec *codec, snd_soc_update_bits(codec, DA7218_REFERENCES, DA7218_BIAS_EN_MASK, 0); } - - /* MCLK */ - if (da7218->mclk) - clk_disable_unprepare(da7218->mclk); break; } -- 1.9.3
[PATCH 1/2] ASoC: da7218: Remove 32KHz PLL mode from driver
Functionality has been removed in latest silicon variants. This patch removes the feature from the driver to align. Signed-off-by: Adam Thomson --- sound/soc/codecs/da7218.c | 12 +++- sound/soc/codecs/da7218.h | 2 -- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c index 99ce23e..f443519 100644 --- a/sound/soc/codecs/da7218.c +++ b/sound/soc/codecs/da7218.c @@ -1819,7 +1819,7 @@ static int da7218_set_dai_sysclk(struct snd_soc_dai *codec_dai, if (da7218->mclk_rate == freq) return 0; - if (((freq < 200) && (freq != 32768)) || (freq > 5400)) { + if ((freq < 200) || (freq > 5400)) { dev_err(codec_dai->dev, "Unsupported MCLK value %d\n", freq); return -EINVAL; @@ -1866,11 +1866,8 @@ static int da7218_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, u32 freq_ref; u64 frac_div; - /* Verify 32KHz, 2MHz - 54MHz MCLK provided, and set input divider */ - if (da7218->mclk_rate == 32768) { - indiv_bits = DA7218_PLL_INDIV_9_TO_18_MHZ; - indiv = DA7218_PLL_INDIV_9_TO_18_MHZ_VAL; - } else if (da7218->mclk_rate < 200) { + /* Verify 2MHz - 54MHz MCLK provided, and set input divider */ + if (da7218->mclk_rate < 200) { dev_err(codec->dev, "PLL input clock %d below valid range\n", da7218->mclk_rate); return -EINVAL; @@ -1911,9 +1908,6 @@ static int da7218_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, case DA7218_SYSCLK_PLL_SRM: pll_ctrl |= DA7218_PLL_MODE_SRM; break; - case DA7218_SYSCLK_PLL_32KHZ: - pll_ctrl |= DA7218_PLL_MODE_32KHZ; - break; default: dev_err(codec->dev, "Invalid PLL config\n"); return -EINVAL; diff --git a/sound/soc/codecs/da7218.h b/sound/soc/codecs/da7218.h index 477cd37..4f7ec21 100644 --- a/sound/soc/codecs/da7218.h +++ b/sound/soc/codecs/da7218.h @@ -888,7 +888,6 @@ #define DA7218_PLL_MODE_BYPASS (0x0 << 6) #define DA7218_PLL_MODE_NORMAL (0x1 << 6) #define DA7218_PLL_MODE_SRM(0x2 << 6) -#define DA7218_PLL_MODE_32KHZ (0x3 << 6) /* DA7218_PLL_FRAC_TOP = 0x92 */ #define DA7218_PLL_FBDIV_FRAC_TOP_SHIFT0 @@ -1371,7 +1370,6 @@ enum da7218_sys_clk { DA7218_SYSCLK_MCLK = 0, DA7218_SYSCLK_PLL, DA7218_SYSCLK_PLL_SRM, - DA7218_SYSCLK_PLL_32KHZ }; enum da7218_dev_id { -- 1.9.3
[RFC PATCH 5/7] power: supply: Add type for USB PD PPS chargers
This adds a type to represent USB PPS chargers as defined in the USB Power Delivery Specification Revision 3.0 V1.1 Signed-off-by: Adam Thomson --- drivers/power/supply/power_supply_sysfs.c | 2 +- include/linux/power_supply.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c index 5204f11..efd2469 100644 --- a/drivers/power/supply/power_supply_sysfs.c +++ b/drivers/power/supply/power_supply_sysfs.c @@ -43,7 +43,7 @@ static const char * const power_supply_type_text[] = { "Unknown", "Battery", "UPS", "Mains", "USB", "USB_DCP", "USB_CDP", "USB_ACA", "USB_C", - "USB_PD", "USB_PD_DRP", "BrickID" + "USB_PD", "USB_PD_DRP", "USB_PD_PPS", "BrickID" }; static const char * const power_supply_status_text[] = { diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 79e90b3..3a79c75 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -167,6 +167,7 @@ enum power_supply_type { POWER_SUPPLY_TYPE_USB_TYPE_C, /* Type C Port */ POWER_SUPPLY_TYPE_USB_PD, /* Power Delivery Port */ POWER_SUPPLY_TYPE_USB_PD_DRP, /* PD Dual Role Port */ + POWER_SUPPLY_TYPE_USB_PD_PPS, /* PD Programmable Power Supply */ POWER_SUPPLY_TYPE_APPLE_BRICK_ID, /* Apple Charging Method */ }; -- 1.9.1
[RFC PATCH 6/7] typec: tcpm: Represent source supply through power_supply class
This commit adds a power_supply class instance to represent a PD source's voltage and current properties. This provides an interface for reading these properties from user-space or other drivers. For PPS enabled Sources, this also provides write access to set the current and voltage and allows for swapping between standard PDO and PPS APDO. As this represents a superset of the information provided in the fusb302 driver, the power_supply instance in that code is removed as part of this change, so reverting the commit titled 'typec: tcpm: Represent source supply through power_supply class' Signed-off-by: Adam Thomson --- drivers/usb/typec/Kconfig | 1 + drivers/usb/typec/fusb302/Kconfig | 2 +- drivers/usb/typec/fusb302/fusb302.c | 63 +- drivers/usb/typec/tcpm.c| 225 +++- 4 files changed, 228 insertions(+), 63 deletions(-) diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig index 465d7da..b9cd806 100644 --- a/drivers/usb/typec/Kconfig +++ b/drivers/usb/typec/Kconfig @@ -8,6 +8,7 @@ config TYPEC_TCPM tristate "USB Type-C Port Controller Manager" depends on USB select TYPEC + select POWER_SUPPLY help The Type-C Port Controller Manager provides a USB PD and USB Type-C state machine for use with Type-C Port Controllers. diff --git a/drivers/usb/typec/fusb302/Kconfig b/drivers/usb/typec/fusb302/Kconfig index 48a4f2f..fce099f 100644 --- a/drivers/usb/typec/fusb302/Kconfig +++ b/drivers/usb/typec/fusb302/Kconfig @@ -1,6 +1,6 @@ config TYPEC_FUSB302 tristate "Fairchild FUSB302 Type-C chip driver" - depends on I2C && POWER_SUPPLY + depends on I2C help The Fairchild FUSB302 Type-C chip driver that works with Type-C Port Controller Manager to provide USB PD and USB diff --git a/drivers/usb/typec/fusb302/fusb302.c b/drivers/usb/typec/fusb302/fusb302.c index e790b67..8e68cb2 100644 --- a/drivers/usb/typec/fusb302/fusb302.c +++ b/drivers/usb/typec/fusb302/fusb302.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -109,11 +108,6 @@ struct fusb302_chip { /* lock for sharing chip states */ struct mutex lock; - /* psy + psy status */ - struct power_supply *psy; - u32 current_limit; - u32 supply_voltage; - /* chip status */ enum toggling_mode toggling_mode; enum src_current_status src_current_status; @@ -882,13 +876,11 @@ static int tcpm_set_vbus(struct tcpc_dev *dev, bool on, bool charge) chip->vbus_on = on; fusb302_log(chip, "vbus := %s", on ? "On" : "Off"); } - if (chip->charge_on == charge) { + if (chip->charge_on == charge) fusb302_log(chip, "charge is already %s", charge ? "On" : "Off"); - } else { + else chip->charge_on = charge; - power_supply_changed(chip->psy); - } done: mutex_unlock(&chip->lock); @@ -904,11 +896,6 @@ static int tcpm_set_current_limit(struct tcpc_dev *dev, u32 max_ma, u32 mv) fusb302_log(chip, "current limit: %d ma, %d mv (not implemented)", max_ma, mv); - chip->supply_voltage = mv; - chip->current_limit = max_ma; - - power_supply_changed(chip->psy); - return 0; } @@ -1694,43 +1681,6 @@ static irqreturn_t fusb302_irq_intn(int irq, void *dev_id) return IRQ_HANDLED; } -static int fusb302_psy_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct fusb302_chip *chip = power_supply_get_drvdata(psy); - - switch (psp) { - case POWER_SUPPLY_PROP_ONLINE: - val->intval = chip->charge_on; - break; - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = chip->supply_voltage * 1000; /* mV -> µV */ - break; - case POWER_SUPPLY_PROP_CURRENT_MAX: - val->intval = chip->current_limit * 1000; /* mA -> µA */ - break; - default: - return -ENODATA; - } - - return 0; -} - -static enum power_supply_property fusb302_psy_properties[] = { - POWER_SUPPLY_PROP_ONLINE, - POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_CURRENT_MAX, -}; - -static const struct power_supply_desc fusb302_psy_desc = { - .name = "fusb302-typec-source", - .type = POWER_SUPPLY_TYPE_USB_TYPE_C, - .properties = fusb302_psy_properties, - .num_properties = ARRAY_SIZE(fusb302_psy_properties), - .get
[RFC PATCH 4/7] typec: tcpm: Add core support for sink side PPS
This commit adds code to handle requesting of PPS APDOs. Switching between standard PDOs and APDOs, and re-requesting an APDO to modify operating voltage/current will be triggered by an external call into TCPM. Signed-off-by: Adam Thomson --- drivers/usb/typec/tcpm.c | 441 +-- include/linux/usb/tcpm.h | 2 +- 2 files changed, 429 insertions(+), 14 deletions(-) diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index 8483d3e..c4045cc 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -56,6 +56,7 @@ S(SNK_DISCOVERY_DEBOUNCE_DONE), \ S(SNK_WAIT_CAPABILITIES), \ S(SNK_NEGOTIATE_CAPABILITIES), \ + S(SNK_NEGOTIATE_PPS_CAPABILITIES), \ S(SNK_TRANSITION_SINK), \ S(SNK_TRANSITION_SINK_VBUS),\ S(SNK_READY), \ @@ -175,6 +176,16 @@ struct pd_mode_data { struct typec_altmode_desc altmode_desc[SVID_DISCOVERY_MAX]; }; +struct pd_pps_data { + u16 min_volt; + u16 max_volt; + u16 max_curr; + u16 out_volt; + u16 op_curr; + bool supported; + bool active; +}; + struct tcpm_port { struct device *dev; @@ -268,6 +279,7 @@ struct tcpm_port { unsigned int max_snk_ma; unsigned int max_snk_mw; unsigned int operating_snk_mw; + bool update_sink_caps; /* Requested current / voltage */ u32 current_limit; @@ -284,8 +296,13 @@ struct tcpm_port { /* VDO to retry if UFP responder replied busy */ u32 vdo_retry; - /* Alternate mode data */ + /* PPS */ + struct pd_pps_data pps_data; + struct completion pps_complete; + bool pps_pending; + int pps_status; + /* Alternate mode data */ struct pd_mode_data mode_data; struct typec_altmode *partner_altmode[SVID_DISCOVERY_MAX]; struct typec_altmode *port_altmode[SVID_DISCOVERY_MAX]; @@ -503,6 +520,13 @@ static void tcpm_log_source_caps(struct tcpm_port *port) pdo_max_voltage(pdo), pdo_max_power(pdo)); break; + case PDO_TYPE_APDO: + scnprintf(msg, sizeof(msg), + "%u-%u mV, %u mA", + pdo_apdo_min_voltage(pdo), + pdo_apdo_max_voltage(pdo), + pdo_apdo_max_current(pdo)); + break; default: strcpy(msg, "undefined"); break; @@ -1259,6 +1283,10 @@ static void vdm_state_machine_work(struct work_struct *work) /* * PD (data, control) command handling functions */ + +static int tcpm_pd_send_control(struct tcpm_port *port, + enum pd_ctrl_msg_type type); + static void tcpm_pd_data_request(struct tcpm_port *port, const struct pd_message *msg) { @@ -1323,6 +1351,15 @@ static void tcpm_pd_data_request(struct tcpm_port *port, } } +static void tcpm_pps_complete(struct tcpm_port *port, int result) +{ + if (port->pps_pending) { + port->pps_status = result; + port->pps_pending = false; + complete(&port->pps_complete); + } +} + static void tcpm_pd_ctrl_request(struct tcpm_port *port, const struct pd_message *msg) { @@ -1399,6 +1436,11 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, next_state = SNK_WAIT_CAPABILITIES; tcpm_set_state(port, next_state, 0); break; + case SNK_NEGOTIATE_PPS_CAPABILITIES: + port->pps_status = (type == PD_CTRL_WAIT ? + -EAGAIN : -EOPNOTSUPP); + tcpm_set_state(port, SNK_READY, 0); + break; case DR_SWAP_SEND: port->swap_status = (type == PD_CTRL_WAIT ? -EAGAIN : -EOPNOTSUPP); @@ -1421,6 +1463,13 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, case PD_CTRL_ACCEPT: switch (port->state) { case SNK_NEGOTIATE_CAPABILITIES: + port->pps_data.active = false; + tcpm_set_state(port, SNK_TRANSITION_SINK, 0); + break; + case SNK_NEGOTIATE_PPS_CAPABILITIES: + port->pps_data.active = true; + port->pps_data.out_volt = port->supply_voltage; + port->pps_data.op_curr = port->current_limit; tcpm_set_state(port, SNK_TRANSITIO
[RFC PATCH 7/7] typec: tcpm: Add support for sink PPS related messages
This commit adds sink side support for Get_Status, Status, Get_PPS_Status and PPS_Status handling. As there's the potential for a partner to respond with Not_Supported handling of this message is also added. Sending of Not_Supported is added is added to handle messages received but not yet handled. Signed-off-by: Adam Thomson --- drivers/usb/typec/tcpm.c | 152 --- 1 file changed, 143 insertions(+), 9 deletions(-) diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index bf3c93a..d12304e 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -28,7 +28,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -122,6 +124,11 @@ S(SNK_TRYWAIT_VBUS),\ S(BIST_RX), \ \ + S(GET_STATUS_SEND), \ + S(GET_STATUS_SEND_TIMEOUT), \ + S(GET_PPS_STATUS_SEND), \ + S(GET_PPS_STATUS_SEND_TIMEOUT), \ + \ S(ERROR_RECOVERY), \ S(PORT_RESET), \ S(PORT_RESET_WAIT_OFF) @@ -152,6 +159,7 @@ enum pd_msg_request { PD_MSG_NONE = 0, PD_MSG_CTRL_REJECT, PD_MSG_CTRL_WAIT, + PD_MSG_CTRL_NOT_SUPP, PD_MSG_DATA_SINK_CAP, PD_MSG_DATA_SOURCE_CAP, }; @@ -1288,10 +1296,42 @@ static void vdm_state_machine_work(struct work_struct *work) /* * PD (data, control) command handling functions */ +static inline enum tcpm_state ready_state(struct tcpm_port *port) +{ + if (port->pwr_role == TYPEC_SOURCE) + return SRC_READY; + else + return SNK_READY; +} static int tcpm_pd_send_control(struct tcpm_port *port, enum pd_ctrl_msg_type type); +static void tcpm_handle_alert(struct tcpm_port *port, const __le32 *payload, + int cnt) +{ + u32 p0 = le32_to_cpu(payload[0]); + unsigned int type = ado_type(p0); + + if (!type) { + tcpm_log(port, "Alert message received with no type"); + return; + } + + /* Just handling non-battery alerts for now */ + if (!(type & ADO_TYPE_BATT_STATUS_CHANGE)) { + switch (port->state) { + case SRC_READY: + case SNK_READY: + tcpm_set_state(port, GET_STATUS_SEND, 0); + break; + default: + tcpm_queue_message(port, PD_MSG_CTRL_WAIT); + break; + } + } +} + static void tcpm_pd_data_request(struct tcpm_port *port, const struct pd_message *msg) { @@ -1350,6 +1390,14 @@ static void tcpm_pd_data_request(struct tcpm_port *port, tcpm_set_state(port, BIST_RX, 0); } break; + case PD_DATA_ALERT: + tcpm_handle_alert(port, msg->payload, cnt); + break; + case PD_DATA_BATT_STATUS: + case PD_DATA_GET_COUNTRY_INFO: + tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP); + /* Currently unsupported */ + break; default: tcpm_log(port, "Unhandled data message type %#x", type); break; @@ -1432,6 +1480,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, break; case PD_CTRL_REJECT: case PD_CTRL_WAIT: + case PD_CTRL_NOT_SUPP: switch (port->state) { case SNK_NEGOTIATE_CAPABILITIES: /* USB PD specification, Figure 8-43 */ @@ -1548,12 +1597,84 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, break; } break; + case PD_CTRL_GET_SOURCE_CAP_EXT: + case PD_CTRL_GET_STATUS: + case PD_CTRL_FR_SWAP: + case PD_CTRL_GET_PPS_STATUS: + case PD_CTRL_GET_COUNTRY_CODES: + /* Currently not supported */ + tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP); + break; default: tcpm_log(port, "Unhandled ctrl message type %#x", type); break; } } +static void tcpm_pd_ext_msg_request(struct tcpm_port *port, + const struct pd_message *msg) +{ + enum pd_ext_msg_type type = pd_header_type_le(msg->header); + unsigned int data_size = pd_ext_header_data_size_le(msg->ext_msg.header); + u8 *data; + + if (!(msg->ext_msg.header && PD_EXT_HDR_CHUNKED)) { + tcpm_log(port, "Unchunked extended messages unsupported"); + return; + } + +
[RFC PATCH 1/7] typec: tcpm: Add PD Rev 3.0 definitions to PD header
This commit adds definitions for PD Rev 3.0 messages, including APDO PPS and extended message support for TCPM. Signed-off-by: Adam Thomson --- include/linux/usb/pd.h | 162 + 1 file changed, 151 insertions(+), 11 deletions(-) diff --git a/include/linux/usb/pd.h b/include/linux/usb/pd.h index e00051c..77c6cd6 100644 --- a/include/linux/usb/pd.h +++ b/include/linux/usb/pd.h @@ -35,6 +35,13 @@ enum pd_ctrl_msg_type { PD_CTRL_WAIT = 12, PD_CTRL_SOFT_RESET = 13, /* 14-15 Reserved */ + PD_CTRL_NOT_SUPP = 16, + PD_CTRL_GET_SOURCE_CAP_EXT = 17, + PD_CTRL_GET_STATUS = 18, + PD_CTRL_FR_SWAP = 19, + PD_CTRL_GET_PPS_STATUS = 20, + PD_CTRL_GET_COUNTRY_CODES = 21, + /* 22-31 Reserved */ }; enum pd_data_msg_type { @@ -43,13 +50,38 @@ enum pd_data_msg_type { PD_DATA_REQUEST = 2, PD_DATA_BIST = 3, PD_DATA_SINK_CAP = 4, - /* 5-14 Reserved */ + PD_DATA_BATT_STATUS = 5, + PD_DATA_ALERT = 6, + PD_DATA_GET_COUNTRY_INFO = 7, + /* 8-14 Reserved */ PD_DATA_VENDOR_DEF = 15, + /* 16-31 Reserved */ +}; + +enum pd_ext_msg_type { + /* 0 Reserved */ + PD_EXT_SOURCE_CAP_EXT = 1, + PD_EXT_STATUS = 2, + PD_EXT_GET_BATT_CAP = 3, + PD_EXT_GET_BATT_STATUS = 4, + PD_EXT_BATT_CAP = 5, + PD_EXT_GET_MANUFACTURER_INFO = 6, + PD_EXT_MANUFACTURER_INFO = 7, + PD_EXT_SECURITY_REQUEST = 8, + PD_EXT_SECURITY_RESPONSE = 9, + PD_EXT_FW_UPDATE_REQUEST = 10, + PD_EXT_FW_UPDATE_RESPONSE = 11, + PD_EXT_PPS_STATUS = 12, + PD_EXT_COUNTRY_INFO = 13, + PD_EXT_COUNTRY_CODES = 14, + /* 15-31 Reserved */ }; #define PD_REV10 0x0 #define PD_REV20 0x1 +#define PD_REV30 0x2 +#define PD_HEADER_EXT_HDR BIT(15) #define PD_HEADER_CNT_SHIFT12 #define PD_HEADER_CNT_MASK 0x7 #define PD_HEADER_ID_SHIFT 9 @@ -59,18 +91,19 @@ enum pd_data_msg_type { #define PD_HEADER_REV_MASK 0x3 #define PD_HEADER_DATA_ROLEBIT(5) #define PD_HEADER_TYPE_SHIFT 0 -#define PD_HEADER_TYPE_MASK0xf +#define PD_HEADER_TYPE_MASK0x1f -#define PD_HEADER(type, pwr, data, id, cnt)\ +#define PD_HEADER(type, pwr, data, id, cnt, ext_hdr) \ type) & PD_HEADER_TYPE_MASK) << PD_HEADER_TYPE_SHIFT) | \ ((pwr) == TYPEC_SOURCE ? PD_HEADER_PWR_ROLE : 0) | \ ((data) == TYPEC_HOST ? PD_HEADER_DATA_ROLE : 0) | \ -(PD_REV20 << PD_HEADER_REV_SHIFT) |\ +(PD_REV30 << PD_HEADER_REV_SHIFT) |\ (((id) & PD_HEADER_ID_MASK) << PD_HEADER_ID_SHIFT) | \ -(((cnt) & PD_HEADER_CNT_MASK) << PD_HEADER_CNT_SHIFT)) +(((cnt) & PD_HEADER_CNT_MASK) << PD_HEADER_CNT_SHIFT) |\ +((ext_hdr) ? PD_HEADER_EXT_HDR : 0)) #define PD_HEADER_LE(type, pwr, data, id, cnt) \ - cpu_to_le16(PD_HEADER((type), (pwr), (data), (id), (cnt))) + cpu_to_le16(PD_HEADER((type), (pwr), (data), (id), (cnt), (0))) static inline unsigned int pd_header_cnt(u16 header) { @@ -102,16 +135,66 @@ static inline unsigned int pd_header_msgid_le(__le16 header) return pd_header_msgid(le16_to_cpu(header)); } +#define PD_EXT_HDR_CHUNKED BIT(15) +#define PD_EXT_HDR_CHUNK_NUM_SHIFT 11 +#define PD_EXT_HDR_CHUNK_NUM_MASK 0xf +#define PD_EXT_HDR_REQ_CHUNK BIT(10) +#define PD_EXT_HDR_DATA_SIZE_SHIFT 0 +#define PD_EXT_HDR_DATA_SIZE_MASK 0x1ff + +#define PD_EXT_HDR(data_size, req_chunk, chunk_num, chunked) \ + data_size) & PD_EXT_HDR_DATA_SIZE_MASK) << PD_EXT_HDR_DATA_SIZE_SHIFT) |\ +((req_chunk) ? PD_EXT_HDR_REQ_CHUNK : 0) | \ +(((chunk_num) & PD_EXT_HDR_CHUNK_NUM_MASK) << PD_EXT_HDR_CHUNK_NUM_SHIFT) |\ +((chunked) ? PD_EXT_HDR_CHUNKED : 0)) + +#define PD_EXT_HDR_LE(data_size, req_chunk, chunk_num, chunked) \ + cpu_to_le16(PD_EXT_HDR((data_size), (req_chunk), (chunk_num), (chunked))) + +static inline unsigned int pd_ext_header_chunk_num(u16 ext_header) +{ + return (ext_header >> PD_EXT_HDR_CHUNK_NUM_SHIFT) & + PD_EXT_HDR_CHUNK_NUM_MASK; +} + +static inline unsigned int pd_ext_header_data_size(u16 ext_header) +{ + return (ext_header >> PD_EXT_HDR_DATA_SIZE_SHIFT) & + PD_EXT_HDR_DATA_SIZE_MASK; +} + +static inline unsigned int pd_ext_header_data_size_le(__le16 ext_header) +{ + return pd_ext_header_data_size(le16_to_cpu(ext_header)); +} + #define PD_MAX_PAYLOAD 7 +#define PD_EXT_MAX_LEGACY_DATA 26 +#define PD_EXT_MAX_CHUNK_DATA 26 +#define PD_EXT_MAX_DATA260 /** - * struct pd_messa
[RFC PATCH 2/7] typec: tcpm: Add ADO header for Alert message handling
This commit adds a header providing definitions for handling Alert messages. Currently the header only focuses on handling incoming alerts. Signed-off-by: Adam Thomson --- include/linux/usb/pd_ado.h | 49 ++ 1 file changed, 49 insertions(+) create mode 100644 include/linux/usb/pd_ado.h diff --git a/include/linux/usb/pd_ado.h b/include/linux/usb/pd_ado.h new file mode 100644 index 000..edcbcfa --- /dev/null +++ b/include/linux/usb/pd_ado.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017 Dialog Semiconductor + * + * Author: Adam Thomson + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __LINUX_USB_PD_ADO_H +#define __LINUX_USB_PD_ADO_H + +/* ADO : Alert Data Object */ +#define ADO_TYPE_SHIFT 24 +#define ADO_TYPE_MASK 0xff +#define ADO_FIXED_BATT_SHIFT 20 +#define ADO_FIXED_BATT_MASK0xf +#define ADO_HOT_SWAP_BATT_SHIFT16 +#define ADO_HOT_SWAP_BATT_MASK 0xf + +#define ADO_TYPE_BATT_STATUS_CHANGEBIT(1) +#define ADO_TYPE_OCP BIT(2) +#define ADO_TYPE_OTP BIT(3) +#define ADO_TYPE_OP_COND_CHANGEBIT(4) +#define ADO_TYPE_SRC_INPUT_CHANGE BIT(5) +#define ADO_TYPE_OVP BIT(6) + +static inline unsigned int ado_type(u32 ado) +{ + return (ado >> ADO_TYPE_SHIFT) & ADO_TYPE_MASK; +} + +static inline unsigned int ado_fixed_batt(u32 ado) +{ + return (ado >> ADO_FIXED_BATT_SHIFT) & ADO_FIXED_BATT_MASK; +} + +static inline unsigned int ado_hot_swap_batt(u32 ado) +{ + return (ado >> ADO_HOT_SWAP_BATT_SHIFT) & ADO_HOT_SWAP_BATT_MASK; +} +#endif /* __LINUX_USB_PD_ADO_H */ -- 1.9.1
[RFC PATCH 0/7] typec: tcpm: Add sink side support for PPS
This patch set adds sink side support for the PPS feature introduced in the USB PD 3.0 specification. The source PPS supply is represented using the Power Supply framework to provide access and control APIs for dealing with it's operating voltage and current, and switching between a standard PDO and PPS APDO operation. During standard PDO operation the voltage and current is read-only, but for APDO PPS these are writable as well to allow for control. It should be noted that the keepalive for PPS is not handled within TCPM. The expectation is that the external user will be required to ensure re-requests occur regularly to ensure PPS remains and the source does not hard reset. So with all of that covered, please feel free to rip this apart as you see fit. Note: Code changes are based on linux-next tag 'next-20171017' to pick up the move out of staging of TCPM related code. Adam Thomson (7): typec: tcpm: Add PD Rev 3.0 definitions to PD header typec: tcpm: Add ADO header for Alert message handling typec: tcpm: Add SDB header for Status message handling typec: tcpm: Add core support for sink side PPS power: supply: Add type for USB PD PPS chargers typec: tcpm: Represent source supply through power_supply class typec: tcpm: Add support for sink PPS related messages drivers/power/supply/power_supply_sysfs.c | 2 +- drivers/usb/typec/Kconfig | 1 + drivers/usb/typec/fusb302/Kconfig | 2 +- drivers/usb/typec/fusb302/fusb302.c | 63 +-- drivers/usb/typec/tcpm.c | 816 +- include/linux/power_supply.h | 1 + include/linux/usb/pd.h| 162 +- include/linux/usb/pd_ado.h| 49 ++ include/linux/usb/pd_ext_sdb.h| 40 ++ include/linux/usb/tcpm.h | 2 +- 10 files changed, 1041 insertions(+), 97 deletions(-) create mode 100644 include/linux/usb/pd_ado.h create mode 100644 include/linux/usb/pd_ext_sdb.h -- 1.9.1
[RFC PATCH 3/7] typec: tcpm: Add SDB header for Status message handling
This commit adds a header providing definitions for handling Status messages. Currently the header only focuses on handling incoming Status messages. Signed-off-by: Adam Thomson --- include/linux/usb/pd_ext_sdb.h | 40 1 file changed, 40 insertions(+) create mode 100644 include/linux/usb/pd_ext_sdb.h diff --git a/include/linux/usb/pd_ext_sdb.h b/include/linux/usb/pd_ext_sdb.h new file mode 100644 index 000..6d6da31 --- /dev/null +++ b/include/linux/usb/pd_ext_sdb.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017 Dialog Semiconductor + * + * Author: Adam Thomson + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __LINUX_USB_PD_EXT_SDB_H +#define __LINUX_USB_PD_EXT_SDB_H + +/* SDB : Status Data Block */ +enum pd_ext_sdb_fields { + EXT_SDB_INTERNAL_TEMP = 0, + EXT_SDB_PRESENT_INPUT, + EXT_SDB_PRESENT_BATT_INPUT, + EXT_SDB_EVENT_FLAGS, + EXT_SDB_TEMP_STATUS, + EXT_SDB_DATA_SIZE, +}; + +/* Event Flags */ +#define EXT_SDB_EVENT_OCP BIT(1) +#define EXT_SDB_EVENT_OTP BIT(2) +#define EXT_SDB_EVENT_OVP BIT(3) +#define EXT_SDB_EVENT_CF_CV_MODE BIT(4) + +#define EXT_SDB_PPS_EVENTS (EXT_SDB_EVENT_OCP |\ +EXT_SDB_EVENT_OTP |\ +EXT_SDB_EVENT_OVP) + +#endif /* __LINUX_USB_PD_EXT_SDB_H */ -- 1.9.1
RE: [RFC PATCH 2/7] typec: tcpm: Add ADO header for Alert message handling
On 01 November 2017 17:20, Greg Kroah-Hartman wrote: > On Wed, Nov 01, 2017 at 05:03:10PM +0000, Adam Thomson wrote: > > This commit adds a header providing definitions for handling Alert > > messages. Currently the header only focuses on handling incoming > > alerts. > > > > Signed-off-by: Adam Thomson > > --- > > include/linux/usb/pd_ado.h | 49 > ++ > > 1 file changed, 49 insertions(+) > > create mode 100644 include/linux/usb/pd_ado.h > > > > diff --git a/include/linux/usb/pd_ado.h b/include/linux/usb/pd_ado.h > > new file mode 100644 > > index 000..edcbcfa > > --- /dev/null > > +++ b/include/linux/usb/pd_ado.h > > @@ -0,0 +1,49 @@ > > +/* > > + * Copyright (c) 2017 Dialog Semiconductor > > + * > > + * Author: Adam Thomson > > + * > > + * 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; either version 2 of the License, or > > + * (at your option) any later version. > > I have to ask, do you _really_ mean "any later version"? Many thanks for the prompt comments. So this is the same copyright header applied for the other PD related code (bit of a copy and paste to follow existing tcpm practice), and have tended to use this header for other driver development as well. Within the context of the Linux kernel I believe this should be fine and will resolve to GPLv2, and should someone use the code elsewhere then they can choose a later GPL license, not that I suspect many would. Do you see any problems here as am happy to be corrected? :) > > > + * > > + * This program is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + */ > > + > > +#ifndef __LINUX_USB_PD_ADO_H > > +#define __LINUX_USB_PD_ADO_H > > + > > +/* ADO : Alert Data Object */ > > +#define ADO_TYPE_SHIFT 24 > > +#define ADO_TYPE_MASK 0xff > > +#define ADO_FIXED_BATT_SHIFT 20 > > +#define ADO_FIXED_BATT_MASK0xf > > +#define ADO_HOT_SWAP_BATT_SHIFT16 > > +#define ADO_HOT_SWAP_BATT_MASK 0xf > > USB_ prefixes perhaps? Again here I was following the existing TCPM approach, but if it's a problem then I can update this. > > > + > > +#define ADO_TYPE_BATT_STATUS_CHANGEBIT(1) > > +#define ADO_TYPE_OCP BIT(2) > > +#define ADO_TYPE_OTP BIT(3) > > +#define ADO_TYPE_OP_COND_CHANGEBIT(4) > > +#define ADO_TYPE_SRC_INPUT_CHANGE BIT(5) > > +#define ADO_TYPE_OVP BIT(6) > > + > > +static inline unsigned int ado_type(u32 ado) > > +{ > > + return (ado >> ADO_TYPE_SHIFT) & ADO_TYPE_MASK; > > +} > > usb_ prefix for this and the other inline functions as well? Same comment here.
RE: [RFC PATCH 3/7] typec: tcpm: Add SDB header for Status message handling
On 01 November 2017 17:21, Greg Kroah-Hartman wrote: > On Wed, Nov 01, 2017 at 05:03:11PM +0000, Adam Thomson wrote: > > This commit adds a header providing definitions for handling > > Status messages. Currently the header only focuses on handling > > incoming Status messages. > > > > Signed-off-by: Adam Thomson > > --- > > include/linux/usb/pd_ext_sdb.h | 40 > > > 1 file changed, 40 insertions(+) > > create mode 100644 include/linux/usb/pd_ext_sdb.h > > > > diff --git a/include/linux/usb/pd_ext_sdb.h b/include/linux/usb/pd_ext_sdb.h > > new file mode 100644 > > index 000..6d6da31 > > --- /dev/null > > +++ b/include/linux/usb/pd_ext_sdb.h > > @@ -0,0 +1,40 @@ > > +/* > > + * Copyright (c) 2017 Dialog Semiconductor > > + * > > + * Author: Adam Thomson > > + * > > + * 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; either version 2 of the License, or > > + * (at your option) any later version. > > Same license question here. > > > > + * > > + * This program is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + */ > > + > > +#ifndef __LINUX_USB_PD_EXT_SDB_H > > +#define __LINUX_USB_PD_EXT_SDB_H > > No need for __LINUX_ right? As for patch 2, was following existing TCPM code but can remove the LINUX part if that's preferred.
RE: [RFC PATCH 1/7] typec: tcpm: Add PD Rev 3.0 definitions to PD header
On 01 November 2017 20:09, Jack Pham wrote: > Hi Adam, > > On Wed, Nov 01, 2017 at 05:03:09PM +0000, Adam Thomson wrote: > > This commit adds definitions for PD Rev 3.0 messages, including > > APDO PPS and extended message support for TCPM. > > > > Signed-off-by: Adam Thomson > > --- > > include/linux/usb/pd.h | 162 > + > > 1 file changed, 151 insertions(+), 11 deletions(-) > > > > diff --git a/include/linux/usb/pd.h b/include/linux/usb/pd.h > > index e00051c..77c6cd6 100644 > > --- a/include/linux/usb/pd.h > > +++ b/include/linux/usb/pd.h > > > > > #define PD_REV10 0x0 > > #define PD_REV20 0x1 > > +#define PD_REV30 0x2 > > > > +#define PD_HEADER_EXT_HDR BIT(15) > > #define PD_HEADER_CNT_SHIFT12 > > #define PD_HEADER_CNT_MASK 0x7 > > #define PD_HEADER_ID_SHIFT 9 > > @@ -59,18 +91,19 @@ enum pd_data_msg_type { > > #define PD_HEADER_REV_MASK 0x3 > > #define PD_HEADER_DATA_ROLEBIT(5) > > #define PD_HEADER_TYPE_SHIFT 0 > > -#define PD_HEADER_TYPE_MASK0xf > > +#define PD_HEADER_TYPE_MASK0x1f > > > > -#define PD_HEADER(type, pwr, data, id, cnt) > > \ > > +#define PD_HEADER(type, pwr, data, id, cnt, ext_hdr) > > \ > > type) & PD_HEADER_TYPE_MASK) << PD_HEADER_TYPE_SHIFT) | \ > > ((pwr) == TYPEC_SOURCE ? PD_HEADER_PWR_ROLE : 0) | \ > > ((data) == TYPEC_HOST ? PD_HEADER_DATA_ROLE : 0) | \ > > -(PD_REV20 << PD_HEADER_REV_SHIFT) |\ > > +(PD_REV30 << PD_HEADER_REV_SHIFT) |\ > > You are making a hardcoded change for the Spec Rev field of every > outgoing message to be 3.0. However, this needs to be flexible in order > to support backwards compatibility when communicating with a 2.0 peer. > The revision "negotiation" would need to be done at the time the first > Request is sent such that both source & sink settle on the highest > supported revision of both. (PD 3.0 spec section 6.2.1.1.5) Thanks for the prompt comments. Much appreciated. This is a fair point. The existing code was hard coded to Rev 2.0 but this should really be based on capabilities of both sides, if we're truly following the spec. Will take a look at this and try to address the problem. > > > (((id) & PD_HEADER_ID_MASK) << PD_HEADER_ID_SHIFT) | \ > > -(((cnt) & PD_HEADER_CNT_MASK) << PD_HEADER_CNT_SHIFT)) > > +(((cnt) & PD_HEADER_CNT_MASK) << PD_HEADER_CNT_SHIFT) |\ > > +((ext_hdr) ? PD_HEADER_EXT_HDR : 0)) > > > > #define PD_HEADER_LE(type, pwr, data, id, cnt) \ > > - cpu_to_le16(PD_HEADER((type), (pwr), (data), (id), (cnt))) > > + cpu_to_le16(PD_HEADER((type), (pwr), (data), (id), (cnt), (0))) > > > > static inline unsigned int pd_header_cnt(u16 header) > > { > > @@ -102,16 +135,66 @@ static inline unsigned int pd_header_msgid_le(__le16 > header) > > return pd_header_msgid(le16_to_cpu(header)); > > } > > > > +#define PD_EXT_HDR_CHUNKED BIT(15) > > +#define PD_EXT_HDR_CHUNK_NUM_SHIFT 11 > > +#define PD_EXT_HDR_CHUNK_NUM_MASK 0xf > > +#define PD_EXT_HDR_REQ_CHUNK BIT(10) > > +#define PD_EXT_HDR_DATA_SIZE_SHIFT 0 > > +#define PD_EXT_HDR_DATA_SIZE_MASK 0x1ff > > + > > +#define PD_EXT_HDR(data_size, req_chunk, chunk_num, chunked) > \ > > + data_size) & PD_EXT_HDR_DATA_SIZE_MASK) << > PD_EXT_HDR_DATA_SIZE_SHIFT) | \ > > +((req_chunk) ? PD_EXT_HDR_REQ_CHUNK : 0) | > \ > > +(((chunk_num) & PD_EXT_HDR_CHUNK_NUM_MASK) << > PD_EXT_HDR_CHUNK_NUM_SHIFT) | \ > > +((chunked) ? PD_EXT_HDR_CHUNKED : 0)) > > + > > +#define PD_EXT_HDR_LE(data_size, req_chunk, chunk_num, chunked) \ > > + cpu_to_le16(PD_EXT_HDR((data_size), (req_chunk), (chunk_num), > (chunked))) > > + > > +static inline unsigned int pd_ext_header_chunk_num(u16 ext_header) > > +{ > > + return (ext_header >> PD_EXT_HDR_CHUNK_NUM_SHIFT) & > > + PD_EXT_HDR_CHUNK_NUM_MASK; > > +} > > + > > +static inline unsigned int pd_ext_header_data_size(u16 ext_header) > > +{ > > + return (ext_header >> PD_EXT_HDR_DATA_SIZE_SHIFT) & > > + PD_EXT_HDR_DATA_SIZE_MASK; > > +} > > + > > +static inline unsigned int pd_ext_header_data_size_le(__le16 ext_header) > > +{ > &g
RE: [RFC PATCH 2/7] typec: tcpm: Add ADO header for Alert message handling
On 02 November 2017 16:49, Greg Kroah-Hartman wrote: > On Thu, Nov 02, 2017 at 11:40:12AM +0000, Adam Thomson wrote: > > On 01 November 2017 17:20, Greg Kroah-Hartman wrote: > > > > > On Wed, Nov 01, 2017 at 05:03:10PM +, Adam Thomson wrote: > > > > This commit adds a header providing definitions for handling Alert > > > > messages. Currently the header only focuses on handling incoming > > > > alerts. > > > > > > > > Signed-off-by: Adam Thomson > > > > --- > > > > include/linux/usb/pd_ado.h | 49 > > > ++ > > > > 1 file changed, 49 insertions(+) > > > > create mode 100644 include/linux/usb/pd_ado.h > > > > > > > > diff --git a/include/linux/usb/pd_ado.h b/include/linux/usb/pd_ado.h > > > > new file mode 100644 > > > > index 000..edcbcfa > > > > --- /dev/null > > > > +++ b/include/linux/usb/pd_ado.h > > > > @@ -0,0 +1,49 @@ > > > > +/* > > > > + * Copyright (c) 2017 Dialog Semiconductor > > > > + * > > > > + * Author: Adam Thomson > > > > + * > > > > + * 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; either version 2 of the License, or > > > > + * (at your option) any later version. > > > > > > I have to ask, do you _really_ mean "any later version"? > > > > Many thanks for the prompt comments. > > > > So this is the same copyright header applied for the other PD related code > > (bit of a copy and paste to follow existing tcpm practice), and have tended > > to > > use this header for other driver development as well. Within the context of > > the > > Linux kernel I believe this should be fine and will resolve to GPLv2, and > > should > > someone use the code elsewhere then they can choose a later GPL license, not > > that I suspect many would. Do you see any problems here as am happy to be > > corrected? :) > > Please consult your lawyers as to what license you should use for new > kernel code. Never just blindly copy/paste without knowing what you are > supposed to be doing :) Yes, our legal department are aware of the use of this header, from previous driver submissions, and have no problems. I certainly wouldn't have applied this otherwise, but completely understand why you raised this :) > > > > + * > > > > + * This program is distributed in the hope that it will be useful, > > > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > > > + * GNU General Public License for more details. > > > > + */ > > > > + > > > > +#ifndef __LINUX_USB_PD_ADO_H > > > > +#define __LINUX_USB_PD_ADO_H > > > > + > > > > +/* ADO : Alert Data Object */ > > > > +#define ADO_TYPE_SHIFT 24 > > > > +#define ADO_TYPE_MASK 0xff > > > > +#define ADO_FIXED_BATT_SHIFT 20 > > > > +#define ADO_FIXED_BATT_MASK0xf > > > > +#define ADO_HOT_SWAP_BATT_SHIFT16 > > > > +#define ADO_HOT_SWAP_BATT_MASK 0xf > > > > > > USB_ prefixes perhaps? > > > > Again here I was following the existing TCPM approach, but if it's a problem > > then I can update this. > > What does TCPM use here? I missed those defines... For example, include/linux/usb/pd_bdo.h uses defines such as: #define BDO_MODE_TRANSMIT (1 << 28) and include/linux/usb/pd.h has defines such as: #define PDO_FIXED_DUAL_ROLE BIT(29) > > > > > + > > > > +#define ADO_TYPE_BATT_STATUS_CHANGEBIT(1) > > > > +#define ADO_TYPE_OCP BIT(2) > > > > +#define ADO_TYPE_OTP BIT(3) > > > > +#define ADO_TYPE_OP_COND_CHANGEBIT(4) > > > > +#define ADO_TYPE_SRC_INPUT_CHANGE BIT(5) > > > > +#define ADO_TYPE_OVP BIT(6) > > > > + > > > > +static inline unsigned int ado_type(u32 ado) > > > > +{ > > > > + return (ado >> ADO_TYPE_SHIFT) & ADO_TYPE_MASK; > > > > +} > > > > > > usb_ prefix for this and the other inline functions as well? > > > > Same comment here. > > But it would make more sense, right? I'm happy with that. Actually I'd probably opt for 'usb_pd_' if I was going that route as it's PD specific information. Would that be reasonable?
[RFC PATCH v2 0/7] typec: tcpm: Add sink side support for PPS
This patch set adds sink side support for the PPS feature introduced in the USB PD 3.0 specification. The source PPS supply is represented using the Power Supply framework to provide access and control APIs for dealing with it's operating voltage and current, and switching between a standard PDO and PPS APDO operation. During standard PDO operation the voltage and current is read-only, but for APDO PPS these are writable as well to allow for control. It should be noted that the keepalive for PPS is not handled within TCPM. The expectation is that the external user will be required to ensure re-requests occur regularly to ensure PPS remains and the source does not hard reset. Changes in v2: - Use USB_PD and usb_pd prefixes for macros and inline functions in headers. - Negotiate spec revision of PD headers during initial contract agreement. - New headers now use SPDX tags for referencing correct license. NOTE: Code changes are based on linux-next tag 'next-20171114' to pick up the move out of staging of TCPM related code. Adam Thomson (7): typec: tcpm: Add PD Rev 3.0 definitions to PD header typec: tcpm: Add ADO header for Alert message handling typec: tcpm: Add SDB header for Status message handling typec: tcpm: Add core support for sink side PPS power: supply: Add type for USB PD PPS chargers typec: tcpm: Represent source supply through power_supply class typec: tcpm: Add support for sink PPS related messages drivers/power/supply/power_supply_sysfs.c | 2 +- drivers/usb/typec/Kconfig | 1 + drivers/usb/typec/fusb302/Kconfig | 2 +- drivers/usb/typec/fusb302/fusb302.c | 63 +-- drivers/usb/typec/tcpm.c | 851 +- include/linux/power_supply.h | 1 + include/linux/usb/pd.h| 174 +- include/linux/usb/pd_ado.h| 42 ++ include/linux/usb/pd_ext_sdb.h| 31 ++ include/linux/usb/tcpm.h | 2 +- 10 files changed, 1071 insertions(+), 98 deletions(-) create mode 100644 include/linux/usb/pd_ado.h create mode 100644 include/linux/usb/pd_ext_sdb.h -- 1.9.1
[RFC PATCH v2 2/7] typec: tcpm: Add ADO header for Alert message handling
This commit adds a header providing definitions for handling Alert messages. Currently the header only focuses on handling incoming alerts. Signed-off-by: Adam Thomson --- include/linux/usb/pd_ado.h | 42 ++ 1 file changed, 42 insertions(+) create mode 100644 include/linux/usb/pd_ado.h diff --git a/include/linux/usb/pd_ado.h b/include/linux/usb/pd_ado.h new file mode 100644 index 000..9aa1cf3 --- /dev/null +++ b/include/linux/usb/pd_ado.h @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2017 Dialog Semiconductor + * + * Author: Adam Thomson + */ + +#ifndef __LINUX_USB_PD_ADO_H +#define __LINUX_USB_PD_ADO_H + +/* ADO : Alert Data Object */ +#define USB_PD_ADO_TYPE_SHIFT 24 +#define USB_PD_ADO_TYPE_MASK 0xff +#define USB_PD_ADO_FIXED_BATT_SHIFT20 +#define USB_PD_ADO_FIXED_BATT_MASK 0xf +#define USB_PD_ADO_HOT_SWAP_BATT_SHIFT 16 +#define USB_PD_ADO_HOT_SWAP_BATT_MASK 0xf + +#define USB_PD_ADO_TYPE_BATT_STATUS_CHANGE BIT(1) +#define USB_PD_ADO_TYPE_OCPBIT(2) +#define USB_PD_ADO_TYPE_OTPBIT(3) +#define USB_PD_ADO_TYPE_OP_COND_CHANGE BIT(4) +#define USB_PD_ADO_TYPE_SRC_INPUT_CHANGE BIT(5) +#define USB_PD_ADO_TYPE_OVPBIT(6) + +static inline unsigned int usb_pd_ado_type(u32 ado) +{ + return (ado >> USB_PD_ADO_TYPE_SHIFT) & USB_PD_ADO_TYPE_MASK; +} + +static inline unsigned int usb_pd_ado_fixed_batt(u32 ado) +{ + return (ado >> USB_PD_ADO_FIXED_BATT_SHIFT) & + USB_PD_ADO_FIXED_BATT_MASK; +} + +static inline unsigned int usb_pd_ado_hot_swap_batt(u32 ado) +{ + return (ado >> USB_PD_ADO_HOT_SWAP_BATT_SHIFT) & + USB_PD_ADO_HOT_SWAP_BATT_MASK; +} +#endif /* __LINUX_USB_PD_ADO_H */ -- 1.9.1
[RFC PATCH v2 3/7] typec: tcpm: Add SDB header for Status message handling
This commit adds a header providing definitions for handling Status messages. Currently the header only focuses on handling incoming Status messages. Signed-off-by: Adam Thomson --- include/linux/usb/pd_ext_sdb.h | 31 +++ 1 file changed, 31 insertions(+) create mode 100644 include/linux/usb/pd_ext_sdb.h diff --git a/include/linux/usb/pd_ext_sdb.h b/include/linux/usb/pd_ext_sdb.h new file mode 100644 index 000..0eb83ce --- /dev/null +++ b/include/linux/usb/pd_ext_sdb.h @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2017 Dialog Semiconductor + * + * Author: Adam Thomson + */ + +#ifndef __LINUX_USB_PD_EXT_SDB_H +#define __LINUX_USB_PD_EXT_SDB_H + +/* SDB : Status Data Block */ +enum usb_pd_ext_sdb_fields { + USB_PD_EXT_SDB_INTERNAL_TEMP = 0, + USB_PD_EXT_SDB_PRESENT_INPUT, + USB_PD_EXT_SDB_PRESENT_BATT_INPUT, + USB_PD_EXT_SDB_EVENT_FLAGS, + USB_PD_EXT_SDB_TEMP_STATUS, + USB_PD_EXT_SDB_DATA_SIZE, +}; + +/* Event Flags */ +#define USB_PD_EXT_SDB_EVENT_OCP BIT(1) +#define USB_PD_EXT_SDB_EVENT_OTP BIT(2) +#define USB_PD_EXT_SDB_EVENT_OVP BIT(3) +#define USB_PD_EXT_SDB_EVENT_CF_CV_MODEBIT(4) + +#define USB_PD_EXT_SDB_PPS_EVENTS (USB_PD_EXT_SDB_EVENT_OCP | \ +USB_PD_EXT_SDB_EVENT_OTP | \ +USB_PD_EXT_SDB_EVENT_OVP) + +#endif /* __LINUX_USB_PD_EXT_SDB_H */ -- 1.9.1
[RFC PATCH v2 5/7] power: supply: Add type for USB PD PPS chargers
This adds a type to represent USB PPS chargers as defined in the USB Power Delivery Specification Revision 3.0 V1.1 Signed-off-by: Adam Thomson Reviewed-by: Sebastian Reichel --- drivers/power/supply/power_supply_sysfs.c | 2 +- include/linux/power_supply.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c index 5204f11..efd2469 100644 --- a/drivers/power/supply/power_supply_sysfs.c +++ b/drivers/power/supply/power_supply_sysfs.c @@ -43,7 +43,7 @@ static const char * const power_supply_type_text[] = { "Unknown", "Battery", "UPS", "Mains", "USB", "USB_DCP", "USB_CDP", "USB_ACA", "USB_C", - "USB_PD", "USB_PD_DRP", "BrickID" + "USB_PD", "USB_PD_DRP", "USB_PD_PPS", "BrickID" }; static const char * const power_supply_status_text[] = { diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 79e90b3..3a79c75 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -167,6 +167,7 @@ enum power_supply_type { POWER_SUPPLY_TYPE_USB_TYPE_C, /* Type C Port */ POWER_SUPPLY_TYPE_USB_PD, /* Power Delivery Port */ POWER_SUPPLY_TYPE_USB_PD_DRP, /* PD Dual Role Port */ + POWER_SUPPLY_TYPE_USB_PD_PPS, /* PD Programmable Power Supply */ POWER_SUPPLY_TYPE_APPLE_BRICK_ID, /* Apple Charging Method */ }; -- 1.9.1
[RFC PATCH v2 7/7] typec: tcpm: Add support for sink PPS related messages
This commit adds sink side support for Get_Status, Status, Get_PPS_Status and PPS_Status handling. As there's the potential for a partner to respond with Not_Supported handling of this message is also added. Sending of Not_Supported is added is added to handle messages received but not yet handled. Signed-off-by: Adam Thomson --- drivers/usb/typec/tcpm.c | 152 --- 1 file changed, 143 insertions(+), 9 deletions(-) diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index 7c26c3d..8db49ab 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -19,7 +19,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -113,6 +115,11 @@ S(SNK_TRYWAIT_VBUS),\ S(BIST_RX), \ \ + S(GET_STATUS_SEND), \ + S(GET_STATUS_SEND_TIMEOUT), \ + S(GET_PPS_STATUS_SEND), \ + S(GET_PPS_STATUS_SEND_TIMEOUT), \ + \ S(ERROR_RECOVERY), \ S(PORT_RESET), \ S(PORT_RESET_WAIT_OFF) @@ -143,6 +150,7 @@ enum pd_msg_request { PD_MSG_NONE = 0, PD_MSG_CTRL_REJECT, PD_MSG_CTRL_WAIT, + PD_MSG_CTRL_NOT_SUPP, PD_MSG_DATA_SINK_CAP, PD_MSG_DATA_SOURCE_CAP, }; @@ -1285,10 +1293,42 @@ static void vdm_state_machine_work(struct work_struct *work) /* * PD (data, control) command handling functions */ +static inline enum tcpm_state ready_state(struct tcpm_port *port) +{ + if (port->pwr_role == TYPEC_SOURCE) + return SRC_READY; + else + return SNK_READY; +} static int tcpm_pd_send_control(struct tcpm_port *port, enum pd_ctrl_msg_type type); +static void tcpm_handle_alert(struct tcpm_port *port, const __le32 *payload, + int cnt) +{ + u32 p0 = le32_to_cpu(payload[0]); + unsigned int type = usb_pd_ado_type(p0); + + if (!type) { + tcpm_log(port, "Alert message received with no type"); + return; + } + + /* Just handling non-battery alerts for now */ + if (!(type & USB_PD_ADO_TYPE_BATT_STATUS_CHANGE)) { + switch (port->state) { + case SRC_READY: + case SNK_READY: + tcpm_set_state(port, GET_STATUS_SEND, 0); + break; + default: + tcpm_queue_message(port, PD_MSG_CTRL_WAIT); + break; + } + } +} + static void tcpm_pd_data_request(struct tcpm_port *port, const struct pd_message *msg) { @@ -1371,6 +1411,14 @@ static void tcpm_pd_data_request(struct tcpm_port *port, tcpm_set_state(port, BIST_RX, 0); } break; + case PD_DATA_ALERT: + tcpm_handle_alert(port, msg->payload, cnt); + break; + case PD_DATA_BATT_STATUS: + case PD_DATA_GET_COUNTRY_INFO: + /* Currently unsupported */ + tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP); + break; default: tcpm_log(port, "Unhandled data message type %#x", type); break; @@ -1453,6 +1501,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, break; case PD_CTRL_REJECT: case PD_CTRL_WAIT: + case PD_CTRL_NOT_SUPP: switch (port->state) { case SNK_NEGOTIATE_CAPABILITIES: /* USB PD specification, Figure 8-43 */ @@ -1569,12 +1618,84 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, break; } break; + case PD_CTRL_GET_SOURCE_CAP_EXT: + case PD_CTRL_GET_STATUS: + case PD_CTRL_FR_SWAP: + case PD_CTRL_GET_PPS_STATUS: + case PD_CTRL_GET_COUNTRY_CODES: + /* Currently not supported */ + tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP); + break; default: tcpm_log(port, "Unhandled ctrl message type %#x", type); break; } } +static void tcpm_pd_ext_msg_request(struct tcpm_port *port, + const struct pd_message *msg) +{ + enum pd_ext_msg_type type = pd_header_type_le(msg->header); + unsigned int data_size = pd_ext_header_data_size_le(msg->ext_msg.header); + u8 *data; + + if (!(msg->ext_msg.header && PD_EXT_HDR_CHUNKED)) { + tcpm_log(port, "Unchunked extended messages unsupported"); +
[RFC PATCH v2 6/7] typec: tcpm: Represent source supply through power_supply class
This commit adds a power_supply class instance to represent a PD source's voltage and current properties. This provides an interface for reading these properties from user-space or other drivers. For PPS enabled Sources, this also provides write access to set the current and voltage and allows for swapping between standard PDO and PPS APDO. As this represents a superset of the information provided in the fusb302 driver, the power_supply instance in that code is removed as part of this change, so reverting the commit titled 'typec: tcpm: Represent source supply through power_supply class' Signed-off-by: Adam Thomson --- drivers/usb/typec/Kconfig | 1 + drivers/usb/typec/fusb302/Kconfig | 2 +- drivers/usb/typec/fusb302/fusb302.c | 63 +- drivers/usb/typec/tcpm.c| 225 +++- 4 files changed, 228 insertions(+), 63 deletions(-) diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig index 465d7da..b9cd806 100644 --- a/drivers/usb/typec/Kconfig +++ b/drivers/usb/typec/Kconfig @@ -8,6 +8,7 @@ config TYPEC_TCPM tristate "USB Type-C Port Controller Manager" depends on USB select TYPEC + select POWER_SUPPLY help The Type-C Port Controller Manager provides a USB PD and USB Type-C state machine for use with Type-C Port Controllers. diff --git a/drivers/usb/typec/fusb302/Kconfig b/drivers/usb/typec/fusb302/Kconfig index 48a4f2f..fce099f 100644 --- a/drivers/usb/typec/fusb302/Kconfig +++ b/drivers/usb/typec/fusb302/Kconfig @@ -1,6 +1,6 @@ config TYPEC_FUSB302 tristate "Fairchild FUSB302 Type-C chip driver" - depends on I2C && POWER_SUPPLY + depends on I2C help The Fairchild FUSB302 Type-C chip driver that works with Type-C Port Controller Manager to provide USB PD and USB diff --git a/drivers/usb/typec/fusb302/fusb302.c b/drivers/usb/typec/fusb302/fusb302.c index 72cb060..21bd075 100644 --- a/drivers/usb/typec/fusb302/fusb302.c +++ b/drivers/usb/typec/fusb302/fusb302.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -100,11 +99,6 @@ struct fusb302_chip { /* lock for sharing chip states */ struct mutex lock; - /* psy + psy status */ - struct power_supply *psy; - u32 current_limit; - u32 supply_voltage; - /* chip status */ enum toggling_mode toggling_mode; enum src_current_status src_current_status; @@ -873,13 +867,11 @@ static int tcpm_set_vbus(struct tcpc_dev *dev, bool on, bool charge) chip->vbus_on = on; fusb302_log(chip, "vbus := %s", on ? "On" : "Off"); } - if (chip->charge_on == charge) { + if (chip->charge_on == charge) fusb302_log(chip, "charge is already %s", charge ? "On" : "Off"); - } else { + else chip->charge_on = charge; - power_supply_changed(chip->psy); - } done: mutex_unlock(&chip->lock); @@ -895,11 +887,6 @@ static int tcpm_set_current_limit(struct tcpc_dev *dev, u32 max_ma, u32 mv) fusb302_log(chip, "current limit: %d ma, %d mv (not implemented)", max_ma, mv); - chip->supply_voltage = mv; - chip->current_limit = max_ma; - - power_supply_changed(chip->psy); - return 0; } @@ -1685,43 +1672,6 @@ static irqreturn_t fusb302_irq_intn(int irq, void *dev_id) return IRQ_HANDLED; } -static int fusb302_psy_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct fusb302_chip *chip = power_supply_get_drvdata(psy); - - switch (psp) { - case POWER_SUPPLY_PROP_ONLINE: - val->intval = chip->charge_on; - break; - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = chip->supply_voltage * 1000; /* mV -> µV */ - break; - case POWER_SUPPLY_PROP_CURRENT_MAX: - val->intval = chip->current_limit * 1000; /* mA -> µA */ - break; - default: - return -ENODATA; - } - - return 0; -} - -static enum power_supply_property fusb302_psy_properties[] = { - POWER_SUPPLY_PROP_ONLINE, - POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_CURRENT_MAX, -}; - -static const struct power_supply_desc fusb302_psy_desc = { - .name = "fusb302-typec-source", - .type = POWER_SUPPLY_TYPE_USB_TYPE_C, - .properties = fusb302_psy_properties, - .num_properties = ARRAY_SIZE(fusb302_psy_properties), - .get
[RFC PATCH v2 1/7] typec: tcpm: Add PD Rev 3.0 definitions to PD header
This commit adds definitions for PD Rev 3.0 messages, including APDO PPS and extended message support for TCPM. Signed-off-by: Adam Thomson --- include/linux/usb/pd.h | 174 + 1 file changed, 162 insertions(+), 12 deletions(-) diff --git a/include/linux/usb/pd.h b/include/linux/usb/pd.h index e00051c..8c9ac80 100644 --- a/include/linux/usb/pd.h +++ b/include/linux/usb/pd.h @@ -35,6 +35,13 @@ enum pd_ctrl_msg_type { PD_CTRL_WAIT = 12, PD_CTRL_SOFT_RESET = 13, /* 14-15 Reserved */ + PD_CTRL_NOT_SUPP = 16, + PD_CTRL_GET_SOURCE_CAP_EXT = 17, + PD_CTRL_GET_STATUS = 18, + PD_CTRL_FR_SWAP = 19, + PD_CTRL_GET_PPS_STATUS = 20, + PD_CTRL_GET_COUNTRY_CODES = 21, + /* 22-31 Reserved */ }; enum pd_data_msg_type { @@ -43,13 +50,39 @@ enum pd_data_msg_type { PD_DATA_REQUEST = 2, PD_DATA_BIST = 3, PD_DATA_SINK_CAP = 4, - /* 5-14 Reserved */ + PD_DATA_BATT_STATUS = 5, + PD_DATA_ALERT = 6, + PD_DATA_GET_COUNTRY_INFO = 7, + /* 8-14 Reserved */ PD_DATA_VENDOR_DEF = 15, + /* 16-31 Reserved */ +}; + +enum pd_ext_msg_type { + /* 0 Reserved */ + PD_EXT_SOURCE_CAP_EXT = 1, + PD_EXT_STATUS = 2, + PD_EXT_GET_BATT_CAP = 3, + PD_EXT_GET_BATT_STATUS = 4, + PD_EXT_BATT_CAP = 5, + PD_EXT_GET_MANUFACTURER_INFO = 6, + PD_EXT_MANUFACTURER_INFO = 7, + PD_EXT_SECURITY_REQUEST = 8, + PD_EXT_SECURITY_RESPONSE = 9, + PD_EXT_FW_UPDATE_REQUEST = 10, + PD_EXT_FW_UPDATE_RESPONSE = 11, + PD_EXT_PPS_STATUS = 12, + PD_EXT_COUNTRY_INFO = 13, + PD_EXT_COUNTRY_CODES = 14, + /* 15-31 Reserved */ }; #define PD_REV10 0x0 #define PD_REV20 0x1 +#define PD_REV30 0x2 +#define PD_MAX_REV PD_REV30 +#define PD_HEADER_EXT_HDR BIT(15) #define PD_HEADER_CNT_SHIFT12 #define PD_HEADER_CNT_MASK 0x7 #define PD_HEADER_ID_SHIFT 9 @@ -59,18 +92,19 @@ enum pd_data_msg_type { #define PD_HEADER_REV_MASK 0x3 #define PD_HEADER_DATA_ROLEBIT(5) #define PD_HEADER_TYPE_SHIFT 0 -#define PD_HEADER_TYPE_MASK0xf +#define PD_HEADER_TYPE_MASK0x1f -#define PD_HEADER(type, pwr, data, id, cnt)\ +#define PD_HEADER(type, pwr, data, rev, id, cnt, ext_hdr) \ type) & PD_HEADER_TYPE_MASK) << PD_HEADER_TYPE_SHIFT) | \ ((pwr) == TYPEC_SOURCE ? PD_HEADER_PWR_ROLE : 0) | \ ((data) == TYPEC_HOST ? PD_HEADER_DATA_ROLE : 0) | \ -(PD_REV20 << PD_HEADER_REV_SHIFT) |\ +(rev << PD_HEADER_REV_SHIFT) | \ (((id) & PD_HEADER_ID_MASK) << PD_HEADER_ID_SHIFT) | \ -(((cnt) & PD_HEADER_CNT_MASK) << PD_HEADER_CNT_SHIFT)) +(((cnt) & PD_HEADER_CNT_MASK) << PD_HEADER_CNT_SHIFT) |\ +((ext_hdr) ? PD_HEADER_EXT_HDR : 0)) -#define PD_HEADER_LE(type, pwr, data, id, cnt) \ - cpu_to_le16(PD_HEADER((type), (pwr), (data), (id), (cnt))) +#define PD_HEADER_LE(type, pwr, data, rev, id, cnt) \ + cpu_to_le16(PD_HEADER((type), (pwr), (data), (rev), (id), (cnt), (0))) static inline unsigned int pd_header_cnt(u16 header) { @@ -102,16 +136,75 @@ static inline unsigned int pd_header_msgid_le(__le16 header) return pd_header_msgid(le16_to_cpu(header)); } +static inline unsigned int pd_header_rev(u16 header) +{ + return (header >> PD_HEADER_REV_SHIFT) & PD_HEADER_REV_MASK; +} + +static inline unsigned int pd_header_rev_le(__le16 header) +{ + return pd_header_rev(le16_to_cpu(header)); +} + +#define PD_EXT_HDR_CHUNKED BIT(15) +#define PD_EXT_HDR_CHUNK_NUM_SHIFT 11 +#define PD_EXT_HDR_CHUNK_NUM_MASK 0xf +#define PD_EXT_HDR_REQ_CHUNK BIT(10) +#define PD_EXT_HDR_DATA_SIZE_SHIFT 0 +#define PD_EXT_HDR_DATA_SIZE_MASK 0x1ff + +#define PD_EXT_HDR(data_size, req_chunk, chunk_num, chunked) \ + data_size) & PD_EXT_HDR_DATA_SIZE_MASK) << PD_EXT_HDR_DATA_SIZE_SHIFT) |\ +((req_chunk) ? PD_EXT_HDR_REQ_CHUNK : 0) | \ +(((chunk_num) & PD_EXT_HDR_CHUNK_NUM_MASK) << PD_EXT_HDR_CHUNK_NUM_SHIFT) |\ +((chunked) ? PD_EXT_HDR_CHUNKED : 0)) + +#define PD_EXT_HDR_LE(data_size, req_chunk, chunk_num, chunked) \ + cpu_to_le16(PD_EXT_HDR((data_size), (req_chunk), (chunk_num), (chunked))) + +static inline unsigned int pd_ext_header_chunk_num(u16 ext_header) +{ + return (ext_header >> PD_EXT_HDR_CHUNK_NUM_SHIFT) & + PD_EXT_HDR_CHUNK_NUM_MASK; +} + +static inline unsigned int pd_ext_header_data_size(u16 ext_header) +{ + return (ext_header >> PD_EXT_HDR_DATA_SIZE_SHIFT) & +
[RFC PATCH v2 4/7] typec: tcpm: Add core support for sink side PPS
This commit adds code to handle requesting of PPS APDOs. Switching between standard PDOs and APDOs, and re-requesting an APDO to modify operating voltage/current will be triggered by an external call into TCPM. Signed-off-by: Adam Thomson --- drivers/usb/typec/tcpm.c | 476 +-- include/linux/usb/tcpm.h | 2 +- 2 files changed, 464 insertions(+), 14 deletions(-) diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index c166fc7..78983e1 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -47,6 +47,7 @@ S(SNK_DISCOVERY_DEBOUNCE_DONE), \ S(SNK_WAIT_CAPABILITIES), \ S(SNK_NEGOTIATE_CAPABILITIES), \ + S(SNK_NEGOTIATE_PPS_CAPABILITIES), \ S(SNK_TRANSITION_SINK), \ S(SNK_TRANSITION_SINK_VBUS),\ S(SNK_READY), \ @@ -166,6 +167,16 @@ struct pd_mode_data { struct typec_altmode_desc altmode_desc[SVID_DISCOVERY_MAX]; }; +struct pd_pps_data { + u16 min_volt; + u16 max_volt; + u16 max_curr; + u16 out_volt; + u16 op_curr; + bool supported; + bool active; +}; + struct tcpm_port { struct device *dev; @@ -233,6 +244,7 @@ struct tcpm_port { struct completion swap_complete; int swap_status; + unsigned int negotiated_rev; unsigned int message_id; unsigned int caps_count; unsigned int hard_reset_count; @@ -259,6 +271,7 @@ struct tcpm_port { unsigned int max_snk_ma; unsigned int max_snk_mw; unsigned int operating_snk_mw; + bool update_sink_caps; /* Requested current / voltage */ u32 current_limit; @@ -275,8 +288,13 @@ struct tcpm_port { /* VDO to retry if UFP responder replied busy */ u32 vdo_retry; - /* Alternate mode data */ + /* PPS */ + struct pd_pps_data pps_data; + struct completion pps_complete; + bool pps_pending; + int pps_status; + /* Alternate mode data */ struct pd_mode_data mode_data; struct typec_altmode *partner_altmode[SVID_DISCOVERY_MAX]; struct typec_altmode *port_altmode[SVID_DISCOVERY_MAX]; @@ -494,6 +512,13 @@ static void tcpm_log_source_caps(struct tcpm_port *port) pdo_max_voltage(pdo), pdo_max_power(pdo)); break; + case PDO_TYPE_APDO: + scnprintf(msg, sizeof(msg), + "%u-%u mV, %u mA", + pdo_apdo_min_voltage(pdo), + pdo_apdo_max_voltage(pdo), + pdo_apdo_max_current(pdo)); + break; default: strcpy(msg, "undefined"); break; @@ -788,11 +813,13 @@ static int tcpm_pd_send_source_caps(struct tcpm_port *port) msg.header = PD_HEADER_LE(PD_CTRL_REJECT, port->pwr_role, port->data_role, + port->negotiated_rev, port->message_id, 0); } else { msg.header = PD_HEADER_LE(PD_DATA_SOURCE_CAP, port->pwr_role, port->data_role, + port->negotiated_rev, port->message_id, port->nr_src_pdo); } @@ -813,11 +840,13 @@ static int tcpm_pd_send_sink_caps(struct tcpm_port *port) msg.header = PD_HEADER_LE(PD_CTRL_REJECT, port->pwr_role, port->data_role, + port->negotiated_rev, port->message_id, 0); } else { msg.header = PD_HEADER_LE(PD_DATA_SINK_CAP, port->pwr_role, port->data_role, + port->negotiated_rev, port->message_id, port->nr_snk_pdo); } @@ -1184,6 +1213,7 @@ static void vdm_run_state_machine(struct tcpm_port *port) msg.header = PD_HEADER_LE(PD_DATA_VENDOR_DEF, port->pwr_role, port->data_role, + port->negotiated_rev, por
RE: [PATCH 1/2] ASoC: da7218: fix fix child-node lookup
On 13 November 2017 11:13, Johan Hovold wrote: > Fix child-node lookup during probe, which ended up searching the whole > device tree depth-first starting at the parent rather than just matching > on its children. > > To make things worse, the parent codec node was also prematurely freed. > > Fixes: 4d50934abd22 ("ASoC: da7218: Add da7218 codec driver") > Cc: stable # 4.5 > Cc: Adam Thomson > Signed-off-by: Johan Hovold Acked-by: Adam Thomson > --- > sound/soc/codecs/da7218.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c > index b2d42ec1dcd9..56564ce90cb6 100644 > --- a/sound/soc/codecs/da7218.c > +++ b/sound/soc/codecs/da7218.c > @@ -2520,7 +2520,7 @@ static struct da7218_pdata *da7218_of_to_pdata(struct > snd_soc_codec *codec) > } > > if (da7218->dev_id == DA7218_DEV_ID) { > - hpldet_np = of_find_node_by_name(np, "da7218_hpldet"); > + hpldet_np = of_get_child_by_name(np, "da7218_hpldet"); > if (!hpldet_np) > return pdata; > > -- > 2.15.0
[PATCH 1/1] ASoC: da7219: Improve error handling for regulator supplies
Currently if bulk_enable() of supplies fails, the code still goes on to try and put the device into active state, and set expected IO voltage of the device. This doesn't really make sense so code now returns on bulk_enable() failure, with an error message. Also, to help with debug, failure to get supplies also provides an error message. Signed-off-by: Adam Thomson --- This patch is based on changes introduced under patch: 'ASoC: codecs: Add da7219 codec driver' (Commit 6d817c0e9fd7536be76690bfdee88e8a81c16f7d, kernel/git/broonie/sound.git) sound/soc/codecs/da7219.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 76f8fc2..c86a833 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -1554,8 +1554,10 @@ static int da7219_handle_supplies(struct snd_soc_codec *codec) ret = devm_regulator_bulk_get(codec->dev, DA7219_NUM_SUPPLIES, da7219->supplies); - if (ret) + if (ret) { + dev_err(codec->dev, "Failed to get supplies"); return ret; + } /* Determine VDDIO voltage provided */ vddio = da7219->supplies[DA7219_SUPPLY_VDDIO].consumer; @@ -1567,6 +1569,10 @@ static int da7219_handle_supplies(struct snd_soc_codec *codec) /* Enable main supplies */ ret = regulator_bulk_enable(DA7219_NUM_SUPPLIES, da7219->supplies); + if (ret) { + dev_err(codec->dev, "Failed to enable supplies"); + return ret; + } /* Ensure device in active mode */ snd_soc_write(codec, DA7219_SYSTEM_ACTIVE, DA7219_SYSTEM_ACTIVE_MASK); @@ -1574,7 +1580,7 @@ static int da7219_handle_supplies(struct snd_soc_codec *codec) /* Update IO voltage level range */ snd_soc_write(codec, DA7219_IO_CTRL, io_voltage_lvl); - return ret; + return 0; } static void da7219_handle_pdata(struct snd_soc_codec *codec) -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 0/2] ASoC: da7213: Add DT support for codec
This patch set adds DT support to the codec driver, and supporting bindings documentation. Patch set is based against v4.3-rc4 Adam Thomson (2): ASoC: da7213: Add DT support to codec driver ASoC: da7213: Add bindings documentation for codec driver Documentation/devicetree/bindings/sound/da7213.txt | 41 + sound/soc/codecs/da7213.c | 181 +++-- sound/soc/codecs/da7213.h | 8 +- 3 files changed, 212 insertions(+), 18 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/da7213.txt -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/2] ASoC: da7213: Add bindings documentation for codec driver
Signed-off-by: Adam Thomson --- Documentation/devicetree/bindings/sound/da7213.txt | 41 ++ 1 file changed, 41 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/da7213.txt diff --git a/Documentation/devicetree/bindings/sound/da7213.txt b/Documentation/devicetree/bindings/sound/da7213.txt new file mode 100644 index 000..7280e82 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/da7213.txt @@ -0,0 +1,41 @@ +Dialog Semiconductor DA7213 Audio Codec bindings + +== + +Required properties: +- compatible : Should be "dlg,da7213" +- reg: Specifies the I2C slave address + +Optional properties: +- clocks : phandle and clock specifier for codec MCLK. +- clock-names : Clock name string for 'clocks' attribute, should be "mclk". + +- dlg,micbias1-lvl : Voltage (mV) for Mic Bias 1 + [<1600>, <2200>, <2500>, <3000>] +- dlg,micbias2-lvl : Voltage (mV) for Mic Bias 2 + [<1600>, <2200>, <2500>, <3000>] +- dlg,dmic-data-sel : DMIC channel select based on clock edge. + ["lrise_rfall", "lfall_rrise"] +- dlg,dmic-samplephase : When to sample audio from DMIC. + ["on_clkedge", "between_clkedge"] +- dlg,dmic-clkrate : DMIC clock frequency (MHz). + [<150>, <300>] + +== + +Example: + + codec_i2c: da7213@1a { + compatible = "dlg,da7213"; + reg = <0x1a>; + + clocks = <&clks 201>; + clock-names = "mclk"; + + dlg,micbias1-lvl = <2500>; + dlg,micbias2-lvl = <2500>; + + dlg,dmic-data-sel = "lrise_rfall"; + dlg,dmic-samplephase = "between_clkedge"; + dlg,dmic-clkrate = <300>; + }; -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/2] ASoC: da7213: Add DT support to codec driver
This patch adds support for DT bindings in the codec driver. As part of this support, the mclk data can now be provided and used to control the mclk during codec operation. Signed-off-by: Adam Thomson --- sound/soc/codecs/da7213.c | 181 ++ sound/soc/codecs/da7213.h | 8 +- 2 files changed, 171 insertions(+), 18 deletions(-) diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index a9c86ef..c654044 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -12,6 +12,7 @@ * option) any later version. */ +#include #include #include #include @@ -1222,23 +1223,44 @@ static int da7213_set_dai_sysclk(struct snd_soc_dai *codec_dai, { struct snd_soc_codec *codec = codec_dai->codec; struct da7213_priv *da7213 = snd_soc_codec_get_drvdata(codec); + int ret = 0; + + if ((da7213->clk_src == clk_id) && (da7213->mclk_rate == freq)) + return 0; + + if (((freq < 500) && (freq != 32768)) || (freq > 5400)) { + dev_err(codec_dai->dev, "Unsupported MCLK value %d\n", + freq); + return -EINVAL; + } switch (clk_id) { + case DA7213_CLKSRC_MCLK_SQR: + da7213->mclk_squarer_en = true; + break; case DA7213_CLKSRC_MCLK: - if ((freq == 32768) || - ((freq >= 500) && (freq <= 5400))) { - da7213->mclk_rate = freq; - return 0; - } else { - dev_err(codec_dai->dev, "Unsupported MCLK value %d\n", - freq); - return -EINVAL; - } + da7213->mclk_squarer_en = false; break; default: dev_err(codec_dai->dev, "Unknown clock source %d\n", clk_id); return -EINVAL; } + + da7213->clk_src = clk_id; + + if (da7213->mclk) { + freq = clk_round_rate(da7213->mclk, freq); + ret = clk_set_rate(da7213->mclk, freq); + if (ret) { + dev_err(codec_dai->dev, "Failed to set clock rate %d\n", + freq); + return ret; + } + } + + da7213->mclk_rate = freq; + + return 0; } /* Supported PLL input frequencies are 5MHz - 54MHz. */ @@ -1366,12 +1388,17 @@ static struct snd_soc_dai_driver da7213_dai = { static int da7213_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct da7213_priv *da7213 = snd_soc_codec_get_drvdata(codec); + switch (level) { case SND_SOC_BIAS_ON: case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { + /* MCLK */ + clk_prepare_enable(da7213->mclk); + /* Enable VMID reference & master bias */ snd_soc_update_bits(codec, DA7213_REFERENCES, DA7213_VMID_EN | DA7213_BIAS_EN, @@ -1382,15 +1409,126 @@ static int da7213_set_bias_level(struct snd_soc_codec *codec, /* Disable VMID reference & master bias */ snd_soc_update_bits(codec, DA7213_REFERENCES, DA7213_VMID_EN | DA7213_BIAS_EN, 0); + + /* MCLK */ + clk_disable_unprepare(da7213->mclk); break; } return 0; } +/* DT */ +static const struct of_device_id da7213_of_match[] = { + { .compatible = "dlg,da7213", }, + { } +}; +MODULE_DEVICE_TABLE(of, da7213_of_match); + +static enum da7213_micbias_voltage + da7213_of_micbias_lvl(struct snd_soc_codec *codec, u32 val) +{ + switch (val) { + case 1600: + return DA7213_MICBIAS_1_6V; + case 2200: + return DA7213_MICBIAS_2_2V; + case 2500: + return DA7213_MICBIAS_2_5V; + case 3000: + return DA7213_MICBIAS_3_0V; + default: + dev_warn(codec->dev, "Invalid micbias level\n"); + return DA7213_MICBIAS_2_2V; + } +} + +static enum da7213_dmic_data_sel + da7213_of_dmic_data_sel(struct snd_soc_codec *codec, const char *str) +{ + if (!strcmp(str, "lrise_rfall")) { + return DA7213_DMIC_DATA_LRISE_RFALL; + } else if (!strcmp(str, "lfall_rrise")) { + return DA7213_DMIC_DATA_LFALL_RRISE; + } else { + dev_warn(codec->dev, "Invalid DMIC data select type\n&q
[PATCH v6 0/6] Add support for DA9150 Fuel-Gauge
This patch set adds support for the Dialog DA9150 Fuel-Gauge. In this patch set the following is provided: - MFD Core and DT bindings updates. - Power Supply Fuel-Gauge support and DT bindings documentation. This patch set is baselined against the v4.3-rc4 kernel version. Changes in v6: - Rebase to v4.3-rc4 Changes in v5: - Rebase to v4.2 Changes in v4: - MFD, Power, DT: Update DT compatible & driver name strings for Fuel Gauge, in line with maintainers request. - Power: Update Kconfig and Makefile to use BATTERY_* for config entry instead of FG_*. Also fuel-gauge module now depends on MFD not Charger. - Power: Added helper function to simplify single attribute accesses using QIF interface of fuel-gauge. - Power: Use of devm_* functions for IRQ and power_supply registration. - Power: Added checking of result from platform_get_irq_byname(). Changes in v3: - MFD: Some tidy up of code (gotos, dropped FG header, DEFINE_RES_IRQ_NAMED) - MFD & Power: Drop use of callback function for temperature reading, as requested by Lee Jones. - MFD (DT): Binding doc update to flesh out example text. - MFD (DT): New patch to change MFD binding doc to use relative paths. - MFD: New patch to use DEFINE_RES_IRQ_NAMED for all other IRQ resources. Changes in v2: - Moved temp callback function prototype to be part of power fuel-gauge patch, as requested by Lee Jones. Adam Thomson (6): mfd: da9150: Add support for Fuel-Gauge mfd: da9150: Update DT bindings for Fuel-Gauge support power: Add support for DA9150 Fuel-Gauge power: da9150: Add DT bindings documentation for Fuel-Gauge mfd: da9150: Use relative paths in DT bindings document mfd: da9150: Use DEFINE_RES_IRQ_NAMED() help macro for IRQ resource Documentation/devicetree/bindings/mfd/da9150.txt | 33 +- .../devicetree/bindings/power/da9150-fg.txt| 23 + drivers/mfd/da9150-core.c | 191 +-- drivers/power/Kconfig | 10 + drivers/power/Makefile | 1 + drivers/power/da9150-fg.c | 578 + include/linux/mfd/da9150/core.h| 19 +- 7 files changed, 810 insertions(+), 45 deletions(-) create mode 100644 Documentation/devicetree/bindings/power/da9150-fg.txt create mode 100644 drivers/power/da9150-fg.c -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v6 4/6] power: da9150: Add DT bindings documentation for Fuel-Gauge
Signed-off-by: Adam Thomson Acked-By: Sebastian Reichel --- Changes in v6: - Rebase to v4.3-rc4 Changes in v5: - Rebase to v4.2 Changes in v4: - Update compatible string of fuel-gauge to "dlg,da9150-fuel-gauge". - Changed example node name to "fuel-gauge". Changes in v3: - N/A Changes in v2: - N/A .../devicetree/bindings/power/da9150-fg.txt| 23 ++ 1 file changed, 23 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/da9150-fg.txt diff --git a/Documentation/devicetree/bindings/power/da9150-fg.txt b/Documentation/devicetree/bindings/power/da9150-fg.txt new file mode 100644 index 000..00236fe --- /dev/null +++ b/Documentation/devicetree/bindings/power/da9150-fg.txt @@ -0,0 +1,23 @@ +Dialog Semiconductor DA9150 Fuel-Gauge Power Supply bindings + +Required properties: +- compatible: "dlg,da9150-fuel-gauge" for DA9150 Fuel-Gauge Power Supply + +Optional properties: +- dlg,update-interval: Interval time (milliseconds) between battery level checks. +- dlg,warn-soc-level: Battery discharge level (%) where warning event raised. + [1 - 100] +- dlg,crit-soc-level: Battery discharge level (%) where critical event raised. + This value should be lower than the warning level. + [1 - 100] + + +Example: + + fuel-gauge { + compatible = "dlg,da9150-fuel-gauge"; + + dlg,update-interval = <1>; + dlg,warn-soc-level = /bits/ 8 <15>; + dlg,crit-soc-level = /bits/ 8 <5>; + }; -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v6 5/6] mfd: da9150: Use relative paths in DT bindings document
When referencing other DT bindings documentation, use relative path rather than absolute. Signed-off-by: Adam Thomson Suggested-by: Lee Jones Acked-by: Lee Jones --- Changes in v6: - Rebase to v4.3-rc4 Changes in v5: - Rebase to v4.2 Changes in v4: - N/A Changes in v3: - Initial version. Changes in v2: - N/A Documentation/devicetree/bindings/mfd/da9150.txt | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/da9150.txt b/Documentation/devicetree/bindings/mfd/da9150.txt index 970801d..fd4dca7 100644 --- a/Documentation/devicetree/bindings/mfd/da9150.txt +++ b/Documentation/devicetree/bindings/mfd/da9150.txt @@ -17,13 +17,13 @@ Required properties: the IRQs from da9150 are delivered to. - interrupts: IRQ line info for da9150 chip. - interrupt-controller: da9150 has internal IRQs (own IRQ domain). - (See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt for + (See ../interrupt-controller/interrupts.txt for further information relating to interrupt properties) Sub-devices: -- da9150-gpadc: See Documentation/devicetree/bindings/iio/adc/da9150-gpadc.txt -- da9150-charger: See Documentation/devicetree/bindings/power/da9150-charger.txt -- da9150-fg: See Documentation/devicetree/bindings/power/da9150-fg.txt +- da9150-gpadc: See ../iio/adc/da9150-gpadc.txt +- da9150-charger: See ../power/da9150-charger.txt +- da9150-fg: See ../power/da9150-fg.txt Example: -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v6 1/6] mfd: da9150: Add support for Fuel-Gauge
Signed-off-by: Adam Thomson Acked-by: Lee Jones --- Changes in v6: - Rebase to v4.3-rc4 Changes in v5: - Rebase to v4.2 Changes in v4: - Update compatible string of fuel-gauge to "dlg, da9150-fuel-gauge". Also made similar change to driver name to keep things consistent. Changes in v3: - Use DEFINE_RES_IRQ_NAMED() helper for defining FG IRQ resource. - Unwanted new line & comments removed. - Remove gotos which can be replaced with straight forward return calls. - Add enum for indexing MFD cells list, which is used to assign pdata for FG sub-device. - Remove use of function pointers for QIF related read/write functions as currently only I2C supported, so call I2C functions directly. - Fold fg.h contents into core.h. Changes in v2: - Moved temp callback function prototype to be part of power fuel-gauge patch, as requested by Lee Jones. drivers/mfd/da9150-core.c | 156 ++-- include/linux/mfd/da9150/core.h | 19 - 2 files changed, 167 insertions(+), 8 deletions(-) diff --git a/drivers/mfd/da9150-core.c b/drivers/mfd/da9150-core.c index 94b9bbd..85ca4b5 100644 --- a/drivers/mfd/da9150-core.c +++ b/drivers/mfd/da9150-core.c @@ -23,6 +23,77 @@ #include #include +/* Raw device access, used for QIF */ +static int da9150_i2c_read_device(struct i2c_client *client, u8 addr, int count, + u8 *buf) +{ + struct i2c_msg xfer; + int ret; + + /* +* Read is split into two transfers as device expects STOP/START rather +* than repeated start to carry out this kind of access. +*/ + + /* Write address */ + xfer.addr = client->addr; + xfer.flags = 0; + xfer.len = 1; + xfer.buf = &addr; + + ret = i2c_transfer(client->adapter, &xfer, 1); + if (ret != 1) { + if (ret < 0) + return ret; + else + return -EIO; + } + + /* Read data */ + xfer.addr = client->addr; + xfer.flags = I2C_M_RD; + xfer.len = count; + xfer.buf = buf; + + ret = i2c_transfer(client->adapter, &xfer, 1); + if (ret == 1) + return 0; + else if (ret < 0) + return ret; + else + return -EIO; +} + +static int da9150_i2c_write_device(struct i2c_client *client, u8 addr, + int count, const u8 *buf) +{ + struct i2c_msg xfer; + u8 *reg_data; + int ret; + + reg_data = kzalloc(1 + count, GFP_KERNEL); + if (!reg_data) + return -ENOMEM; + + reg_data[0] = addr; + memcpy(®_data[1], buf, count); + + /* Write address & data */ + xfer.addr = client->addr; + xfer.flags = 0; + xfer.len = 1 + count; + xfer.buf = reg_data; + + ret = i2c_transfer(client->adapter, &xfer, 1); + kfree(reg_data); + if (ret == 1) + return 0; + else if (ret < 0) + return ret; + else + return -EIO; +} + static bool da9150_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { @@ -107,6 +178,28 @@ static const struct regmap_config da9150_regmap_config = { .volatile_reg = da9150_volatile_reg, }; +void da9150_read_qif(struct da9150 *da9150, u8 addr, int count, u8 *buf) +{ + int ret; + + ret = da9150_i2c_read_device(da9150->core_qif, addr, count, buf); + if (ret < 0) + dev_err(da9150->dev, "Failed to read from QIF 0x%x: %d\n", + addr, ret); +} +EXPORT_SYMBOL_GPL(da9150_read_qif); + +void da9150_write_qif(struct da9150 *da9150, u8 addr, int count, const u8 *buf) +{ + int ret; + + ret = da9150_i2c_write_device(da9150->core_qif, addr, count, buf); + if (ret < 0) + dev_err(da9150->dev, "Failed to write to QIF 0x%x: %d\n", + addr, ret); +} +EXPORT_SYMBOL_GPL(da9150_write_qif); + u8 da9150_reg_read(struct da9150 *da9150, u16 reg) { int val, ret; @@ -297,19 +390,35 @@ static struct resource da9150_charger_resources[] = { }, }; +static struct resource da9150_fg_resources[] = { + DEFINE_RES_IRQ_NAMED(DA9150_IRQ_FG, "FG"), +}; + +enum da9150_dev_idx { + DA9150_GPADC_IDX = 0, + DA9150_CHARGER_IDX, + DA9150_FG_IDX, +}; + static struct mfd_cell da9150_devs[] = { - { + [DA9150_GPADC_IDX] = { .name = "da9150-gpadc", .of_compatible = "dlg,da9150-gpadc", .resources = da9150_gpadc_resources, .num_resources = ARRAY_SIZE(da9150_gpadc_resources), }, - { + [DA9150_CHARGER_IDX] = { .name = "da9150-charger", .of_compatible = "
[PATCH v6 3/6] power: Add support for DA9150 Fuel-Gauge
This adds power supply driver support for the Fuel-Gauge part of the DA9150 combined Charger and Fuel-Gauge device. Signed-off-by: Adam Thomson Acked-By: Sebastian Reichel --- Changes in v6: - Rebase to v4.3-rc4 Changes in v5: - Rebase to v4.2 Changes in v4: - Update compatible string of fuel-gauge to "dlg,da9150-fuel-gauge". Also updated driver name string to keep consistency. - Update Kconfig and Makefile to use BATTERY_* for config entry instead of FG_*. Also fuel-gauge module now depends on MFD not Charger. - Added helper function to simplify single attribute accesses using QIF interface of fuel-gauge. - Use of devm_* functions for IRQ and power_supply registration. - Added checking of result from platform_get_irq_byname(). Changes in v3: - Removed use of temp callback function, at request of Lee Jones. - Comment added to clarify limitation of temperature reading functionality that remains. Changes in v2: - Moved temp callback function prototype to be part of power fuel-gauge patch, rather than MFD, as requested by Lee Jones. drivers/power/Kconfig | 10 + drivers/power/Makefile| 1 + drivers/power/da9150-fg.c | 578 ++ 3 files changed, 589 insertions(+) create mode 100644 drivers/power/da9150-fg.c diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index f8758d6..8d53f58 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -204,6 +204,16 @@ config CHARGER_DA9150 This driver can also be built as a module. If so, the module will be called da9150-charger. +config BATTERY_DA9150 + tristate "Dialog Semiconductor DA9150 Fuel Gauge support" + depends on MFD_DA9150 + help + Say Y here to enable support for the Fuel-Gauge unit of the DA9150 + Integrated Charger & Fuel-Gauge IC + + This driver can also be built as a module. If so, the module will be + called da9150-fg. + config AXP288_CHARGER tristate "X-Powers AXP288 Charger" depends on MFD_AXP20X && EXTCON_AXP288 diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 5752ce8..cbdf89d 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o obj-$(CONFIG_BATTERY_DA9052) += da9052-battery.o obj-$(CONFIG_CHARGER_DA9150) += da9150-charger.o +obj-$(CONFIG_BATTERY_DA9150) += da9150-fg.o obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o obj-$(CONFIG_BATTERY_Z2) += z2_battery.o diff --git a/drivers/power/da9150-fg.c b/drivers/power/da9150-fg.c new file mode 100644 index 000..39ebf04 --- /dev/null +++ b/drivers/power/da9150-fg.c @@ -0,0 +1,578 @@ +/* + * DA9150 Fuel-Gauge Driver + * + * Copyright (c) 2015 Dialog Semiconductor + * + * Author: Adam Thomson + * + * 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; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Core2Wire */ +#define DA9150_QIF_READ(0x0 << 7) +#define DA9150_QIF_WRITE (0x1 << 7) +#define DA9150_QIF_CODE_MASK 0x7F + +#define DA9150_QIF_BYTE_SIZE 8 +#define DA9150_QIF_BYTE_MASK 0xFF +#define DA9150_QIF_SHORT_SIZE 2 +#define DA9150_QIF_LONG_SIZE 4 + +/* QIF Codes */ +#define DA9150_QIF_UAVG6 +#define DA9150_QIF_UAVG_SIZE DA9150_QIF_LONG_SIZE +#define DA9150_QIF_IAVG8 +#define DA9150_QIF_IAVG_SIZE DA9150_QIF_LONG_SIZE +#define DA9150_QIF_NTCAVG 12 +#define DA9150_QIF_NTCAVG_SIZE DA9150_QIF_LONG_SIZE +#define DA9150_QIF_SHUNT_VAL 36 +#define DA9150_QIF_SHUNT_VAL_SIZE DA9150_QIF_SHORT_SIZE +#define DA9150_QIF_SD_GAIN 38 +#define DA9150_QIF_SD_GAIN_SIZEDA9150_QIF_LONG_SIZE +#define DA9150_QIF_FCC_MAH 40 +#define DA9150_QIF_FCC_MAH_SIZEDA9150_QIF_SHORT_SIZE +#define DA9150_QIF_SOC_PCT 43 +#define DA9150_QIF_SOC_PCT_SIZEDA9150_QIF_SHORT_SIZE +#define DA9150_QIF_CHARGE_LIMIT44 +#define DA9150_QIF_CHARGE_LIMIT_SIZE DA9150_QIF_SHORT_SIZE +#define DA9150_QIF_DISCHARGE_LIMIT 45 +#define DA9150_QIF_DISCHARGE_LIMIT_SIZEDA9150_QIF_SHORT_SIZE +#define DA9150_QIF_FW_MAIN_VER 118 +#define DA9150_QIF_FW_MAIN_VER_SIZEDA9150_QIF_SHORT_SIZE +#define DA9150_QIF_E_FG_STATUS 126 +#define DA9150_QIF_E_FG_STATUS_SIZEDA9150_QIF_SHORT_SIZE +#define DA9150_QIF_SYNC
[PATCH v6 2/6] mfd: da9150: Update DT bindings for Fuel-Gauge support
Signed-off-by: Adam Thomson Acked-by: Lee Jones --- Changes in v6: - Rebase to v4.3-rc4 Changes in v5: - Rebase to v4.2 Changes in v4: - Update compatible string of fuel-gauge to "da9150-fuel-gauge". - Node name tidy up, relating to maintainer comments on fuel-gauge DT binding doc. - Removed Ack to patch from Lee Jones, as this has now been modified slightly and didn't want to make assumptions of approval. Changes in v3: - Removal of unwanted new-line. - Flesh out example bindings usage. Changes in v2: - N/A Documentation/devicetree/bindings/mfd/da9150.txt | 27 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/da9150.txt b/Documentation/devicetree/bindings/mfd/da9150.txt index d0588ea..970801d 100644 --- a/Documentation/devicetree/bindings/mfd/da9150.txt +++ b/Documentation/devicetree/bindings/mfd/da9150.txt @@ -6,6 +6,7 @@ Device Description -- --- da9150-gpadc : General Purpose ADC da9150-charger : Battery Charger +da9150-fg : Battery Fuel-Gauge == @@ -22,7 +23,7 @@ Required properties: Sub-devices: - da9150-gpadc: See Documentation/devicetree/bindings/iio/adc/da9150-gpadc.txt - da9150-charger: See Documentation/devicetree/bindings/power/da9150-charger.txt - +- da9150-fg: See Documentation/devicetree/bindings/power/da9150-fg.txt Example: @@ -34,10 +35,28 @@ Example: interrupt-controller; gpadc: da9150-gpadc { - ... + compatible = "dlg,da9150-gpadc"; + #io-channel-cells = <1>; + }; + + charger { + compatible = "dlg,da9150-charger"; + + io-channels = <&gpadc 0>, + <&gpadc 2>, + <&gpadc 8>, + <&gpadc 5>; + io-channel-names = "CHAN_IBUS", + "CHAN_VBUS", + "CHAN_TJUNC", + "CHAN_VBAT"; }; - da9150-charger { - ... + fuel-gauge { + compatible = "dlg,da9150-fuel-gauge"; + + dlg,update-interval = <1>; + dlg,warn-soc-level = /bits/ 8 <15>; + dlg,crit-soc-level = /bits/ 8 <5> }; }; -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v6 6/6] mfd: da9150: Use DEFINE_RES_IRQ_NAMED() help macro for IRQ resource
Signed-off-by: Adam Thomson Suggested-by: Lee Jones Acked-by: Lee Jones --- Changes in v6: - Rebase to v4.3-rc4 Changes in v5: - Rebase to v4.2 Changes in v4: - N/A Changes in v3: - Initial version. Changes in v2: - N/A drivers/mfd/da9150-core.c | 35 +-- 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/drivers/mfd/da9150-core.c b/drivers/mfd/da9150-core.c index 85ca4b5..195fdcf 100644 --- a/drivers/mfd/da9150-core.c +++ b/drivers/mfd/da9150-core.c @@ -355,39 +355,14 @@ static const struct regmap_irq_chip da9150_regmap_irq_chip = { }; static struct resource da9150_gpadc_resources[] = { - { - .name = "GPADC", - .start = DA9150_IRQ_GPADC, - .end = DA9150_IRQ_GPADC, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(DA9150_IRQ_GPADC, "GPADC"), }; static struct resource da9150_charger_resources[] = { - { - .name = "CHG_STATUS", - .start = DA9150_IRQ_CHG, - .end = DA9150_IRQ_CHG, - .flags = IORESOURCE_IRQ, - }, - { - .name = "CHG_TJUNC", - .start = DA9150_IRQ_TJUNC, - .end = DA9150_IRQ_TJUNC, - .flags = IORESOURCE_IRQ, - }, - { - .name = "CHG_VFAULT", - .start = DA9150_IRQ_VFAULT, - .end = DA9150_IRQ_VFAULT, - .flags = IORESOURCE_IRQ, - }, - { - .name = "CHG_VBUS", - .start = DA9150_IRQ_VBUS, - .end = DA9150_IRQ_VBUS, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(DA9150_IRQ_CHG, "CHG_STATUS"), + DEFINE_RES_IRQ_NAMED(DA9150_IRQ_TJUNC, "CHG_TJUNC"), + DEFINE_RES_IRQ_NAMED(DA9150_IRQ_VFAULT, "CHG_VFAULT"), + DEFINE_RES_IRQ_NAMED(DA9150_IRQ_VBUS, "CHG_VBUS"), }; static struct resource da9150_fg_resources[] = { -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 0/2] ASoC: da7219: Improve mclk error checking, use of_match_ptr
This patch set contains a couple of small updates/fixes: - Use of of_match_ptr() for assigning match table to driver structure - Only enable/disable mclk if it has been provided to the driver. - Add error checking of clk_prepare_enable. Patch set is based on changes introduced under patch: 'ASoC: da7219: Improve error handling for regulator supplies' (Commit 4e929134eb8271abc9c52c371e056debfea6898b , kernel/git/broonie/sound.git) Adam Thomson (2): ASoC: da7219: Use of_match_ptr() when assigning match table ASoC: da7219: Improve error checking of mclk enable/disable sound/soc/codecs/da7219.c | 15 --- 1 file changed, 12 insertions(+), 3 deletions(-) -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/2] ASoC: da7219: Improve error checking of mclk enable/disable
Should only try to enable/disable the provided mclk, during bias level changes, if it's not NULL. Also return value of clk_prepare_enable() should be checked and dealt with accordingly. Signed-off-by: Adam Thomson --- sound/soc/codecs/da7219.c | 13 +++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index adcc079..abba4b3 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -1494,6 +1494,7 @@ static int da7219_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); + int ret; switch (level) { case SND_SOC_BIAS_ON: @@ -1502,7 +1503,14 @@ static int da7219_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { /* MCLK */ - clk_prepare_enable(da7219->mclk); + if (da7219->mclk) { + ret = clk_prepare_enable(da7219->mclk); + if (ret) { + dev_err(codec->dev, + "Failed to enable mclk\n"); + return ret; + } + } /* Master bias */ snd_soc_update_bits(codec, DA7219_REFERENCES, @@ -1528,7 +1536,8 @@ static int da7219_set_bias_level(struct snd_soc_codec *codec, } /* MCLK */ - clk_disable_unprepare(da7219->mclk); + if (da7219->mclk) + clk_disable_unprepare(da7219->mclk); break; } -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/2] ASoC: da7219: Use of_match_ptr() when assigning match table
Use of_match_ptr() to handle non-DT kernel scenario where match table should be NULL. Signed-off-by: Adam Thomson --- sound/soc/codecs/da7219.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index c86a833..adcc079 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -1932,7 +1932,7 @@ MODULE_DEVICE_TABLE(i2c, da7219_i2c_id); static struct i2c_driver da7219_i2c_driver = { .driver = { .name = "da7219", - .of_match_table = da7219_of_match, + .of_match_table = of_match_ptr(da7219_of_match), }, .probe = da7219_i2c_probe, .remove = da7219_i2c_remove, -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 0/3] ASoC: da7213: Add DT support for codec
This patch set adds DT support to the codec driver, and supporting bindings documentation. Patch set is based against v4.3-rc4 Changes in v2: - Split mclk data support changes into separate patch - Use of_match_ptr() for match table assignment - Only call clk_prepare_enable/disable() if mclk data provided (not NULL). - Add error checking for clk_prepare_enable() usage. Adam Thomson (3): ASoC: da7213: Add DT support to codec driver ASoC: da7213: Add support to handle mclk data provided to driver ASoC: da7213: Add bindings documentation for codec driver Documentation/devicetree/bindings/sound/da7213.txt | 41 + include/sound/da7213.h | 3 - sound/soc/codecs/da7213.c | 190 +++-- sound/soc/codecs/da7213.h | 8 +- 4 files changed, 221 insertions(+), 21 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/da7213.txt -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 3/3] ASoC: da7213: Add bindings documentation for codec driver
Signed-off-by: Adam Thomson --- Documentation/devicetree/bindings/sound/da7213.txt | 41 ++ 1 file changed, 41 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/da7213.txt diff --git a/Documentation/devicetree/bindings/sound/da7213.txt b/Documentation/devicetree/bindings/sound/da7213.txt new file mode 100644 index 000..7280e82 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/da7213.txt @@ -0,0 +1,41 @@ +Dialog Semiconductor DA7213 Audio Codec bindings + +== + +Required properties: +- compatible : Should be "dlg,da7213" +- reg: Specifies the I2C slave address + +Optional properties: +- clocks : phandle and clock specifier for codec MCLK. +- clock-names : Clock name string for 'clocks' attribute, should be "mclk". + +- dlg,micbias1-lvl : Voltage (mV) for Mic Bias 1 + [<1600>, <2200>, <2500>, <3000>] +- dlg,micbias2-lvl : Voltage (mV) for Mic Bias 2 + [<1600>, <2200>, <2500>, <3000>] +- dlg,dmic-data-sel : DMIC channel select based on clock edge. + ["lrise_rfall", "lfall_rrise"] +- dlg,dmic-samplephase : When to sample audio from DMIC. + ["on_clkedge", "between_clkedge"] +- dlg,dmic-clkrate : DMIC clock frequency (MHz). + [<150>, <300>] + +== + +Example: + + codec_i2c: da7213@1a { + compatible = "dlg,da7213"; + reg = <0x1a>; + + clocks = <&clks 201>; + clock-names = "mclk"; + + dlg,micbias1-lvl = <2500>; + dlg,micbias2-lvl = <2500>; + + dlg,dmic-data-sel = "lrise_rfall"; + dlg,dmic-samplephase = "between_clkedge"; + dlg,dmic-clkrate = <300>; + }; -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2 2/3] ASoC: da7213: Add support to handle mclk data provided to driver
Driver now can make use of mclk data, if provided, to set, enable and disable the clock source. As part of this, the choice to enable clock squaring is dealt with as part of dai_sysclk() call rather than as platform data. Signed-off-by: Adam Thomson --- include/sound/da7213.h| 3 --- sound/soc/codecs/da7213.c | 67 +++ sound/soc/codecs/da7213.h | 8 -- 3 files changed, 62 insertions(+), 16 deletions(-) diff --git a/include/sound/da7213.h b/include/sound/da7213.h index 673f5c3..e7eac89 100644 --- a/include/sound/da7213.h +++ b/include/sound/da7213.h @@ -44,9 +44,6 @@ struct da7213_platform_data { enum da7213_dmic_data_sel dmic_data_sel; enum da7213_dmic_samplephase dmic_samplephase; enum da7213_dmic_clk_rate dmic_clk_rate; - - /* MCLK squaring config */ - bool mclk_squaring; }; #endif /* _DA7213_PDATA_H */ diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index ab1486b..7278f93 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -12,6 +12,7 @@ * option) any later version. */ +#include #include #include #include @@ -1222,23 +1223,44 @@ static int da7213_set_dai_sysclk(struct snd_soc_dai *codec_dai, { struct snd_soc_codec *codec = codec_dai->codec; struct da7213_priv *da7213 = snd_soc_codec_get_drvdata(codec); + int ret = 0; + + if ((da7213->clk_src == clk_id) && (da7213->mclk_rate == freq)) + return 0; + + if (((freq < 500) && (freq != 32768)) || (freq > 5400)) { + dev_err(codec_dai->dev, "Unsupported MCLK value %d\n", + freq); + return -EINVAL; + } switch (clk_id) { case DA7213_CLKSRC_MCLK: - if ((freq == 32768) || - ((freq >= 500) && (freq <= 5400))) { - da7213->mclk_rate = freq; - return 0; - } else { - dev_err(codec_dai->dev, "Unsupported MCLK value %d\n", - freq); - return -EINVAL; - } + da7213->mclk_squarer_en = false; + break; + case DA7213_CLKSRC_MCLK_SQR: + da7213->mclk_squarer_en = true; break; default: dev_err(codec_dai->dev, "Unknown clock source %d\n", clk_id); return -EINVAL; } + + da7213->clk_src = clk_id; + + if (da7213->mclk) { + freq = clk_round_rate(da7213->mclk, freq); + ret = clk_set_rate(da7213->mclk, freq); + if (ret) { + dev_err(codec_dai->dev, "Failed to set clock rate %d\n", + freq); + return ret; + } + } + + da7213->mclk_rate = freq; + + return 0; } /* Supported PLL input frequencies are 5MHz - 54MHz. */ @@ -1366,12 +1388,25 @@ static struct snd_soc_dai_driver da7213_dai = { static int da7213_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + struct da7213_priv *da7213 = snd_soc_codec_get_drvdata(codec); + int ret; + switch (level) { case SND_SOC_BIAS_ON: case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) { + /* MCLK */ + if (da7213->mclk) { + ret = clk_prepare_enable(da7213->mclk); + if (ret) { + dev_err(codec->dev, + "Failed to enable mclk\n"); + return ret; + } + } + /* Enable VMID reference & master bias */ snd_soc_update_bits(codec, DA7213_REFERENCES, DA7213_VMID_EN | DA7213_BIAS_EN, @@ -1382,6 +1417,10 @@ static int da7213_set_bias_level(struct snd_soc_codec *codec, /* Disable VMID reference & master bias */ snd_soc_update_bits(codec, DA7213_REFERENCES, DA7213_VMID_EN | DA7213_BIAS_EN, 0); + + /* MCLK */ + if (da7213->mclk) + clk_disable_unprepare(da7213->mclk); break; } return 0; @@ -1618,9 +1657,15 @@ static int da7213_probe(struct snd_soc_codec *codec) DA7213_DMIC_DATA_SEL_MASK | DA7213_DMIC_SAMPLEPHASE_
[PATCH v2 1/3] ASoC: da7213: Add DT support to codec driver
This patch adds support for DT bindings in the codec driver. As part of this support, the mclk data can now be provided and used to control the mclk during codec operation. Signed-off-by: Adam Thomson --- sound/soc/codecs/da7213.c | 123 -- 1 file changed, 118 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index a9c86ef..ab1486b 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -1387,10 +1387,118 @@ static int da7213_set_bias_level(struct snd_soc_codec *codec, return 0; } +/* DT */ +static const struct of_device_id da7213_of_match[] = { + { .compatible = "dlg,da7213", }, + { } +}; +MODULE_DEVICE_TABLE(of, da7213_of_match); + +static enum da7213_micbias_voltage + da7213_of_micbias_lvl(struct snd_soc_codec *codec, u32 val) +{ + switch (val) { + case 1600: + return DA7213_MICBIAS_1_6V; + case 2200: + return DA7213_MICBIAS_2_2V; + case 2500: + return DA7213_MICBIAS_2_5V; + case 3000: + return DA7213_MICBIAS_3_0V; + default: + dev_warn(codec->dev, "Invalid micbias level\n"); + return DA7213_MICBIAS_2_2V; + } +} + +static enum da7213_dmic_data_sel + da7213_of_dmic_data_sel(struct snd_soc_codec *codec, const char *str) +{ + if (!strcmp(str, "lrise_rfall")) { + return DA7213_DMIC_DATA_LRISE_RFALL; + } else if (!strcmp(str, "lfall_rrise")) { + return DA7213_DMIC_DATA_LFALL_RRISE; + } else { + dev_warn(codec->dev, "Invalid DMIC data select type\n"); + return DA7213_DMIC_DATA_LRISE_RFALL; + } +} + +static enum da7213_dmic_samplephase + da7213_of_dmic_samplephase(struct snd_soc_codec *codec, const char *str) +{ + if (!strcmp(str, "on_clkedge")) { + return DA7213_DMIC_SAMPLE_ON_CLKEDGE; + } else if (!strcmp(str, "between_clkedge")) { + return DA7213_DMIC_SAMPLE_BETWEEN_CLKEDGE; + } else { + dev_warn(codec->dev, "Invalid DMIC sample phase\n"); + return DA7213_DMIC_SAMPLE_ON_CLKEDGE; + } +} + +static enum da7213_dmic_clk_rate + da7213_of_dmic_clkrate(struct snd_soc_codec *codec, u32 val) +{ + switch (val) { + case 150: + return DA7213_DMIC_CLK_1_5MHZ; + case 300: + return DA7213_DMIC_CLK_3_0MHZ; + default: + dev_warn(codec->dev, "Invalid DMIC clock rate\n"); + return DA7213_DMIC_CLK_1_5MHZ; + } +} + +static struct da7213_platform_data + *da7213_of_to_pdata(struct snd_soc_codec *codec) +{ + struct device_node *np = codec->dev->of_node; + struct da7213_platform_data *pdata; + const char *of_str; + u32 of_val32; + + pdata = devm_kzalloc(codec->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_warn(codec->dev, "Failed to allocate memory for pdata\n"); + return NULL; + } + + if (of_property_read_u32(np, "dlg,micbias1-lvl", &of_val32) >= 0) + pdata->micbias1_lvl = da7213_of_micbias_lvl(codec, of_val32); + else + pdata->micbias1_lvl = DA7213_MICBIAS_2_2V; + + if (of_property_read_u32(np, "dlg,micbias2-lvl", &of_val32) >= 0) + pdata->micbias2_lvl = da7213_of_micbias_lvl(codec, of_val32); + else + pdata->micbias2_lvl = DA7213_MICBIAS_2_2V; + + if (!of_property_read_string(np, "dlg,dmic-data-sel", &of_str)) + pdata->dmic_data_sel = da7213_of_dmic_data_sel(codec, of_str); + else + pdata->dmic_data_sel = DA7213_DMIC_DATA_LRISE_RFALL; + + if (!of_property_read_string(np, "dlg,dmic-samplephase", &of_str)) + pdata->dmic_samplephase = + da7213_of_dmic_samplephase(codec, of_str); + else + pdata->dmic_samplephase = DA7213_DMIC_SAMPLE_ON_CLKEDGE; + + if (of_property_read_u32(np, "dlg,dmic-clkrate", &of_val32) >= 0) + pdata->dmic_clk_rate = da7213_of_dmic_clkrate(codec, of_val32); + else + pdata->dmic_clk_rate = DA7213_DMIC_CLK_3_0MHZ; + + return pdata; +} + + static int da7213_probe(struct snd_soc_codec *codec) { struct da7213_priv *da7213 = snd_soc_codec_get_drvdata(codec); - struct da7213_platform_data *pdata = da7213->pdata; /* Default to using ALC auto offset calibration mode. */ snd_soc_update_bits(codec, DA7213_ALC_CTRL1, @@ -1450,8 +1558,15 @@ static int da7213_probe(struct snd_soc_codec *codec) snd_soc_update_bits(c
[PATCH v7 5/6] mfd: da9150: Use relative paths in DT bindings document
When referencing other DT bindings documentation, use relative path rather than absolute. Signed-off-by: Adam Thomson Suggested-by: Lee Jones Acked-by: Lee Jones --- Changes in v6: - Rebase to v4.3-rc4 Changes in v5: - Rebase to v4.2 Changes in v3: - Initial version. Documentation/devicetree/bindings/mfd/da9150.txt | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/da9150.txt b/Documentation/devicetree/bindings/mfd/da9150.txt index 970801d..fd4dca7 100644 --- a/Documentation/devicetree/bindings/mfd/da9150.txt +++ b/Documentation/devicetree/bindings/mfd/da9150.txt @@ -17,13 +17,13 @@ Required properties: the IRQs from da9150 are delivered to. - interrupts: IRQ line info for da9150 chip. - interrupt-controller: da9150 has internal IRQs (own IRQ domain). - (See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt for + (See ../interrupt-controller/interrupts.txt for further information relating to interrupt properties) Sub-devices: -- da9150-gpadc: See Documentation/devicetree/bindings/iio/adc/da9150-gpadc.txt -- da9150-charger: See Documentation/devicetree/bindings/power/da9150-charger.txt -- da9150-fg: See Documentation/devicetree/bindings/power/da9150-fg.txt +- da9150-gpadc: See ../iio/adc/da9150-gpadc.txt +- da9150-charger: See ../power/da9150-charger.txt +- da9150-fg: See ../power/da9150-fg.txt Example: -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v7 2/6] mfd: da9150: Update DT bindings for Fuel-Gauge support
Signed-off-by: Adam Thomson Acked-by: Lee Jones --- Changes in v6: - Rebase to v4.3-rc4 Changes in v5: - Rebase to v4.2 Changes in v4: - Update compatible string of fuel-gauge to "da9150-fuel-gauge". - Node name tidy up, relating to maintainer comments on fuel-gauge DT binding doc. - Removed Ack to patch from Lee Jones, as this has now been modified slightly and didn't want to make assumptions of approval. Changes in v3: - Removal of unwanted new-line. - Flesh out example bindings usage. Documentation/devicetree/bindings/mfd/da9150.txt | 27 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/mfd/da9150.txt b/Documentation/devicetree/bindings/mfd/da9150.txt index d0588ea..970801d 100644 --- a/Documentation/devicetree/bindings/mfd/da9150.txt +++ b/Documentation/devicetree/bindings/mfd/da9150.txt @@ -6,6 +6,7 @@ Device Description -- --- da9150-gpadc : General Purpose ADC da9150-charger : Battery Charger +da9150-fg : Battery Fuel-Gauge == @@ -22,7 +23,7 @@ Required properties: Sub-devices: - da9150-gpadc: See Documentation/devicetree/bindings/iio/adc/da9150-gpadc.txt - da9150-charger: See Documentation/devicetree/bindings/power/da9150-charger.txt - +- da9150-fg: See Documentation/devicetree/bindings/power/da9150-fg.txt Example: @@ -34,10 +35,28 @@ Example: interrupt-controller; gpadc: da9150-gpadc { - ... + compatible = "dlg,da9150-gpadc"; + #io-channel-cells = <1>; + }; + + charger { + compatible = "dlg,da9150-charger"; + + io-channels = <&gpadc 0>, + <&gpadc 2>, + <&gpadc 8>, + <&gpadc 5>; + io-channel-names = "CHAN_IBUS", + "CHAN_VBUS", + "CHAN_TJUNC", + "CHAN_VBAT"; }; - da9150-charger { - ... + fuel-gauge { + compatible = "dlg,da9150-fuel-gauge"; + + dlg,update-interval = <1>; + dlg,warn-soc-level = /bits/ 8 <15>; + dlg,crit-soc-level = /bits/ 8 <5> }; }; -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v7 0/6] Add support for DA9150 Fuel-Gauge
This patch set adds support for the Dialog DA9150 Fuel-Gauge. In this patch set the following is provided: - MFD Core and DT bindings updates. - Power Supply Fuel-Gauge support and DT bindings documentation. This patch set is baselined against the v4.3-rc4 kernel version. Changes in v7: - Fix return code handling for platform_get_irq_byname() call in fuel-gauge. Changes in v6: - Rebase to v4.3-rc4 Changes in v5: - Rebase to v4.2 Changes in v4: - MFD, Power, DT: Update DT compatible & driver name strings for Fuel Gauge, in line with maintainers request. - Power: Update Kconfig and Makefile to use BATTERY_* for config entry instead of FG_*. Also fuel-gauge module now depends on MFD not Charger. - Power: Added helper function to simplify single attribute accesses using QIF interface of fuel-gauge. - Power: Use of devm_* functions for IRQ and power_supply registration. - Power: Added checking of result from platform_get_irq_byname(). Changes in v3: - MFD: Some tidy up of code (gotos, dropped FG header, DEFINE_RES_IRQ_NAMED) - MFD & Power: Drop use of callback function for temperature reading, as requested by Lee Jones. - MFD (DT): Binding doc update to flesh out example text. - MFD (DT): New patch to change MFD binding doc to use relative paths. - MFD: New patch to use DEFINE_RES_IRQ_NAMED for all other IRQ resources. Changes in v2: - Moved temp callback function prototype to be part of power fuel-gauge patch, as requested by Lee Jones. Adam Thomson (6): mfd: da9150: Add support for Fuel-Gauge mfd: da9150: Update DT bindings for Fuel-Gauge support power: Add support for DA9150 Fuel-Gauge power: da9150: Add DT bindings documentation for Fuel-Gauge mfd: da9150: Use relative paths in DT bindings document mfd: da9150: Use DEFINE_RES_IRQ_NAMED() help macro for IRQ resource Documentation/devicetree/bindings/mfd/da9150.txt | 33 +- .../devicetree/bindings/power/da9150-fg.txt| 23 + drivers/mfd/da9150-core.c | 191 +-- drivers/power/Kconfig | 10 + drivers/power/Makefile | 1 + drivers/power/da9150-fg.c | 579 + include/linux/mfd/da9150/core.h| 19 +- 7 files changed, 811 insertions(+), 45 deletions(-) create mode 100644 Documentation/devicetree/bindings/power/da9150-fg.txt create mode 100644 drivers/power/da9150-fg.c -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v7 3/6] power: Add support for DA9150 Fuel-Gauge
This adds power supply driver support for the Fuel-Gauge part of the DA9150 combined Charger and Fuel-Gauge device. Signed-off-by: Adam Thomson Acked-by: Sebastian Reichel --- Changes in v7: - Fix return code handling for platform_get_irq_byname() call. Changes in v6: - Rebase to v4.3-rc4 Changes in v5: - Rebase to v4.2 Changes in v4: - Update compatible string of fuel-gauge to "dlg,da9150-fuel-gauge". Also updated driver name string to keep consistency. - Update Kconfig and Makefile to use BATTERY_* for config entry instead of FG_*. Also fuel-gauge module now depends on MFD not Charger. - Added helper function to simplify single attribute accesses using QIF interface of fuel-gauge. - Use of devm_* functions for IRQ and power_supply registration. - Added checking of result from platform_get_irq_byname(). Changes in v3: - Removed use of temp callback function, at request of Lee Jones. - Comment added to clarify limitation of temperature reading functionality that remains. Changes in v2: - Moved temp callback function prototype to be part of power fuel-gauge patch, rather than MFD, as requested by Lee Jones. drivers/power/Kconfig | 10 + drivers/power/Makefile| 1 + drivers/power/da9150-fg.c | 579 ++ 3 files changed, 590 insertions(+) create mode 100644 drivers/power/da9150-fg.c diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index f8758d6..8d53f58 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -204,6 +204,16 @@ config CHARGER_DA9150 This driver can also be built as a module. If so, the module will be called da9150-charger. +config BATTERY_DA9150 + tristate "Dialog Semiconductor DA9150 Fuel Gauge support" + depends on MFD_DA9150 + help + Say Y here to enable support for the Fuel-Gauge unit of the DA9150 + Integrated Charger & Fuel-Gauge IC + + This driver can also be built as a module. If so, the module will be + called da9150-fg. + config AXP288_CHARGER tristate "X-Powers AXP288 Charger" depends on MFD_AXP20X && EXTCON_AXP288 diff --git a/drivers/power/Makefile b/drivers/power/Makefile index 5752ce8..cbdf89d 100644 --- a/drivers/power/Makefile +++ b/drivers/power/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o obj-$(CONFIG_BATTERY_DA9052) += da9052-battery.o obj-$(CONFIG_CHARGER_DA9150) += da9150-charger.o +obj-$(CONFIG_BATTERY_DA9150) += da9150-fg.o obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o obj-$(CONFIG_BATTERY_Z2) += z2_battery.o diff --git a/drivers/power/da9150-fg.c b/drivers/power/da9150-fg.c new file mode 100644 index 000..8b8ce97 --- /dev/null +++ b/drivers/power/da9150-fg.c @@ -0,0 +1,579 @@ +/* + * DA9150 Fuel-Gauge Driver + * + * Copyright (c) 2015 Dialog Semiconductor + * + * Author: Adam Thomson + * + * 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; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Core2Wire */ +#define DA9150_QIF_READ(0x0 << 7) +#define DA9150_QIF_WRITE (0x1 << 7) +#define DA9150_QIF_CODE_MASK 0x7F + +#define DA9150_QIF_BYTE_SIZE 8 +#define DA9150_QIF_BYTE_MASK 0xFF +#define DA9150_QIF_SHORT_SIZE 2 +#define DA9150_QIF_LONG_SIZE 4 + +/* QIF Codes */ +#define DA9150_QIF_UAVG6 +#define DA9150_QIF_UAVG_SIZE DA9150_QIF_LONG_SIZE +#define DA9150_QIF_IAVG8 +#define DA9150_QIF_IAVG_SIZE DA9150_QIF_LONG_SIZE +#define DA9150_QIF_NTCAVG 12 +#define DA9150_QIF_NTCAVG_SIZE DA9150_QIF_LONG_SIZE +#define DA9150_QIF_SHUNT_VAL 36 +#define DA9150_QIF_SHUNT_VAL_SIZE DA9150_QIF_SHORT_SIZE +#define DA9150_QIF_SD_GAIN 38 +#define DA9150_QIF_SD_GAIN_SIZEDA9150_QIF_LONG_SIZE +#define DA9150_QIF_FCC_MAH 40 +#define DA9150_QIF_FCC_MAH_SIZEDA9150_QIF_SHORT_SIZE +#define DA9150_QIF_SOC_PCT 43 +#define DA9150_QIF_SOC_PCT_SIZEDA9150_QIF_SHORT_SIZE +#define DA9150_QIF_CHARGE_LIMIT44 +#define DA9150_QIF_CHARGE_LIMIT_SIZE DA9150_QIF_SHORT_SIZE +#define DA9150_QIF_DISCHARGE_LIMIT 45 +#define DA9150_QIF_DISCHARGE_LIMIT_SIZEDA9150_QIF_SHORT_SIZE +#define DA9150_QIF_FW_MAIN_VER 118 +#define DA9150_QIF_FW_MAIN_VER_SIZEDA9150_QIF_SHORT_SIZE +#define DA9150_QIF_E_FG_STATUS 126 +#define DA9150_QIF_E_FG_STATUS_
[PATCH v7 1/6] mfd: da9150: Add support for Fuel-Gauge
Signed-off-by: Adam Thomson Acked-by: Lee Jones --- Changes in v6: - Rebase to v4.3-rc4 Changes in v5: - Rebase to v4.2 Changes in v4: - Update compatible string of fuel-gauge to "dlg, da9150-fuel-gauge". Also made similar change to driver name to keep things consistent. Changes in v3: - Use DEFINE_RES_IRQ_NAMED() helper for defining FG IRQ resource. - Unwanted new line & comments removed. - Remove gotos which can be replaced with straight forward return calls. - Add enum for indexing MFD cells list, which is used to assign pdata for FG sub-device. - Remove use of function pointers for QIF related read/write functions as currently only I2C supported, so call I2C functions directly. - Fold fg.h contents into core.h. Changes in v2: - Moved temp callback function prototype to be part of power fuel-gauge patch, as requested by Lee Jones. drivers/mfd/da9150-core.c | 156 ++-- include/linux/mfd/da9150/core.h | 19 - 2 files changed, 167 insertions(+), 8 deletions(-) diff --git a/drivers/mfd/da9150-core.c b/drivers/mfd/da9150-core.c index 94b9bbd..85ca4b5 100644 --- a/drivers/mfd/da9150-core.c +++ b/drivers/mfd/da9150-core.c @@ -23,6 +23,77 @@ #include #include +/* Raw device access, used for QIF */ +static int da9150_i2c_read_device(struct i2c_client *client, u8 addr, int count, + u8 *buf) +{ + struct i2c_msg xfer; + int ret; + + /* +* Read is split into two transfers as device expects STOP/START rather +* than repeated start to carry out this kind of access. +*/ + + /* Write address */ + xfer.addr = client->addr; + xfer.flags = 0; + xfer.len = 1; + xfer.buf = &addr; + + ret = i2c_transfer(client->adapter, &xfer, 1); + if (ret != 1) { + if (ret < 0) + return ret; + else + return -EIO; + } + + /* Read data */ + xfer.addr = client->addr; + xfer.flags = I2C_M_RD; + xfer.len = count; + xfer.buf = buf; + + ret = i2c_transfer(client->adapter, &xfer, 1); + if (ret == 1) + return 0; + else if (ret < 0) + return ret; + else + return -EIO; +} + +static int da9150_i2c_write_device(struct i2c_client *client, u8 addr, + int count, const u8 *buf) +{ + struct i2c_msg xfer; + u8 *reg_data; + int ret; + + reg_data = kzalloc(1 + count, GFP_KERNEL); + if (!reg_data) + return -ENOMEM; + + reg_data[0] = addr; + memcpy(®_data[1], buf, count); + + /* Write address & data */ + xfer.addr = client->addr; + xfer.flags = 0; + xfer.len = 1 + count; + xfer.buf = reg_data; + + ret = i2c_transfer(client->adapter, &xfer, 1); + kfree(reg_data); + if (ret == 1) + return 0; + else if (ret < 0) + return ret; + else + return -EIO; +} + static bool da9150_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { @@ -107,6 +178,28 @@ static const struct regmap_config da9150_regmap_config = { .volatile_reg = da9150_volatile_reg, }; +void da9150_read_qif(struct da9150 *da9150, u8 addr, int count, u8 *buf) +{ + int ret; + + ret = da9150_i2c_read_device(da9150->core_qif, addr, count, buf); + if (ret < 0) + dev_err(da9150->dev, "Failed to read from QIF 0x%x: %d\n", + addr, ret); +} +EXPORT_SYMBOL_GPL(da9150_read_qif); + +void da9150_write_qif(struct da9150 *da9150, u8 addr, int count, const u8 *buf) +{ + int ret; + + ret = da9150_i2c_write_device(da9150->core_qif, addr, count, buf); + if (ret < 0) + dev_err(da9150->dev, "Failed to write to QIF 0x%x: %d\n", + addr, ret); +} +EXPORT_SYMBOL_GPL(da9150_write_qif); + u8 da9150_reg_read(struct da9150 *da9150, u16 reg) { int val, ret; @@ -297,19 +390,35 @@ static struct resource da9150_charger_resources[] = { }, }; +static struct resource da9150_fg_resources[] = { + DEFINE_RES_IRQ_NAMED(DA9150_IRQ_FG, "FG"), +}; + +enum da9150_dev_idx { + DA9150_GPADC_IDX = 0, + DA9150_CHARGER_IDX, + DA9150_FG_IDX, +}; + static struct mfd_cell da9150_devs[] = { - { + [DA9150_GPADC_IDX] = { .name = "da9150-gpadc", .of_compatible = "dlg,da9150-gpadc", .resources = da9150_gpadc_resources, .num_resources = ARRAY_SIZE(da9150_gpadc_resources), }, - { + [DA9150_CHARGER_IDX] = { .name = "da9150-charger", .of_compatible = "
[PATCH v7 4/6] power: da9150: Add DT bindings documentation for Fuel-Gauge
Signed-off-by: Adam Thomson Acked-by: Sebastian Reichel --- Changes in v6: - Rebase to v4.3-rc4 Changes in v5: - Rebase to v4.2 Changes in v4: - Update compatible string of fuel-gauge to "dlg,da9150-fuel-gauge". - Changed example node name to "fuel-gauge". .../devicetree/bindings/power/da9150-fg.txt| 23 ++ 1 file changed, 23 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/da9150-fg.txt diff --git a/Documentation/devicetree/bindings/power/da9150-fg.txt b/Documentation/devicetree/bindings/power/da9150-fg.txt new file mode 100644 index 000..00236fe --- /dev/null +++ b/Documentation/devicetree/bindings/power/da9150-fg.txt @@ -0,0 +1,23 @@ +Dialog Semiconductor DA9150 Fuel-Gauge Power Supply bindings + +Required properties: +- compatible: "dlg,da9150-fuel-gauge" for DA9150 Fuel-Gauge Power Supply + +Optional properties: +- dlg,update-interval: Interval time (milliseconds) between battery level checks. +- dlg,warn-soc-level: Battery discharge level (%) where warning event raised. + [1 - 100] +- dlg,crit-soc-level: Battery discharge level (%) where critical event raised. + This value should be lower than the warning level. + [1 - 100] + + +Example: + + fuel-gauge { + compatible = "dlg,da9150-fuel-gauge"; + + dlg,update-interval = <1>; + dlg,warn-soc-level = /bits/ 8 <15>; + dlg,crit-soc-level = /bits/ 8 <5>; + }; -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v7 6/6] mfd: da9150: Use DEFINE_RES_IRQ_NAMED() help macro for IRQ resource
Signed-off-by: Adam Thomson Suggested-by: Lee Jones Acked-by: Lee Jones --- Changes in v6: - Rebase to v4.3-rc4 Changes in v5: - Rebase to v4.2 Changes in v3: - Initial version. drivers/mfd/da9150-core.c | 35 +-- 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/drivers/mfd/da9150-core.c b/drivers/mfd/da9150-core.c index 85ca4b5..195fdcf 100644 --- a/drivers/mfd/da9150-core.c +++ b/drivers/mfd/da9150-core.c @@ -355,39 +355,14 @@ static const struct regmap_irq_chip da9150_regmap_irq_chip = { }; static struct resource da9150_gpadc_resources[] = { - { - .name = "GPADC", - .start = DA9150_IRQ_GPADC, - .end = DA9150_IRQ_GPADC, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(DA9150_IRQ_GPADC, "GPADC"), }; static struct resource da9150_charger_resources[] = { - { - .name = "CHG_STATUS", - .start = DA9150_IRQ_CHG, - .end = DA9150_IRQ_CHG, - .flags = IORESOURCE_IRQ, - }, - { - .name = "CHG_TJUNC", - .start = DA9150_IRQ_TJUNC, - .end = DA9150_IRQ_TJUNC, - .flags = IORESOURCE_IRQ, - }, - { - .name = "CHG_VFAULT", - .start = DA9150_IRQ_VFAULT, - .end = DA9150_IRQ_VFAULT, - .flags = IORESOURCE_IRQ, - }, - { - .name = "CHG_VBUS", - .start = DA9150_IRQ_VBUS, - .end = DA9150_IRQ_VBUS, - .flags = IORESOURCE_IRQ, - }, + DEFINE_RES_IRQ_NAMED(DA9150_IRQ_CHG, "CHG_STATUS"), + DEFINE_RES_IRQ_NAMED(DA9150_IRQ_TJUNC, "CHG_TJUNC"), + DEFINE_RES_IRQ_NAMED(DA9150_IRQ_VFAULT, "CHG_VFAULT"), + DEFINE_RES_IRQ_NAMED(DA9150_IRQ_VBUS, "CHG_VBUS"), }; static struct resource da9150_fg_resources[] = { -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] ASoC: fsl_ssi: Fix checking of dai format for AC97 mode
Current code incorrectly treats dai format for AC97 as bit mask whereas it's actually an integer value. This causes DAI formats other than AC97 (e.g. DSP_B) to trigger AC97 related code, which is incorrect and breaks functionality. This patch fixes the code to correctly compare values to determine AC97 or not. Signed-off-by: Adam Thomson --- sound/soc/fsl/fsl_ssi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index c0b940e..ee47041 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -249,7 +249,8 @@ MODULE_DEVICE_TABLE(of, fsl_ssi_ids); static bool fsl_ssi_is_ac97(struct fsl_ssi_private *ssi_private) { - return !!(ssi_private->dai_fmt & SND_SOC_DAIFMT_AC97); + return (ssi_private->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) == + SND_SOC_DAIFMT_AC97; } static bool fsl_ssi_is_i2s_master(struct fsl_ssi_private *ssi_private) @@ -945,7 +946,7 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev, CCSR_SSI_SCR_TCH_EN); } - if (fmt & SND_SOC_DAIFMT_AC97) + if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_AC97) fsl_ssi_setup_ac97(ssi_private); return 0; -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] ASoC: da7219: Add delays to capture path to remove DC offset noise
On some platforms it has been noted that a pop noise can be witnessed when capturing audio, mainly for first time after a headset jack has been inserted. This is due to a DC offset in the Mic PGA and so to avoid this delays are required when powering up the capture path. This commit rectifies the problem by adding delays post Mic PGA and post Mixin PGA. The post Mic PGA delay is determined based on Mic Bias voltage, and is only applied the first time after a headset jack is inserted. Signed-off-by: Adam Thomson --- sound/soc/codecs/da7219-aad.c | 5 + sound/soc/codecs/da7219.c | 44 +-- sound/soc/codecs/da7219.h | 8 ++-- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index a49ab75..2c7d508 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c @@ -59,6 +59,7 @@ static void da7219_aad_btn_det_work(struct work_struct *work) container_of(work, struct da7219_aad_priv, btn_det_work); struct snd_soc_component *component = da7219_aad->component; struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); + struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); u8 statusa, micbias_ctrl; bool micbias_up = false; int retries = 0; @@ -86,6 +87,8 @@ static void da7219_aad_btn_det_work(struct work_struct *work) if (retries >= DA7219_AAD_MICBIAS_CHK_RETRIES) dev_warn(component->dev, "Mic bias status check timed out"); + da7219->micbias_on_event = true; + /* * Mic bias pulse required to enable mic, must be done before enabling * button detection to prevent erroneous button readings. @@ -439,6 +442,8 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data) snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1, DA7219_BUTTON_CONFIG_MASK, 0); + da7219->micbias_on_event = false; + /* Disable mic bias */ snd_soc_dapm_disable_pin(dapm, "Mic Bias"); snd_soc_dapm_sync(dapm); diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index c0144f2..e46e9f4 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -768,6 +768,30 @@ static int da7219_tonegen_freq_put(struct snd_kcontrol *kcontrol, * DAPM Events */ +static int da7219_mic_pga_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + if (da7219->micbias_on_event) { + /* +* Delay only for first capture after bias enabled to +* avoid possible DC offset related noise. +*/ + da7219->micbias_on_event = false; + msleep(da7219->mic_pga_delay); + } + break; + default: + break; + } + + return 0; +} + static int da7219_dai_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -937,12 +961,12 @@ static int da7219_gain_ramp_event(struct snd_soc_dapm_widget *w, SND_SOC_DAPM_INPUT("MIC"), /* Input PGAs */ - SND_SOC_DAPM_PGA("Mic PGA", DA7219_MIC_1_CTRL, -DA7219_MIC_1_AMP_EN_SHIFT, DA7219_NO_INVERT, -NULL, 0), - SND_SOC_DAPM_PGA("Mixin PGA", DA7219_MIXIN_L_CTRL, -DA7219_MIXIN_L_AMP_EN_SHIFT, DA7219_NO_INVERT, -NULL, 0), + SND_SOC_DAPM_PGA_E("Mic PGA", DA7219_MIC_1_CTRL, + DA7219_MIC_1_AMP_EN_SHIFT, DA7219_NO_INVERT, + NULL, 0, da7219_mic_pga_event, SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_PGA_E("Mixin PGA", DA7219_MIXIN_L_CTRL, + DA7219_MIXIN_L_AMP_EN_SHIFT, DA7219_NO_INVERT, + NULL, 0, da7219_settling_event, SND_SOC_DAPM_POST_PMU), /* Input Filters */ SND_SOC_DAPM_ADC("ADC", NULL, DA7219_ADC_L_CTRL, DA7219_ADC_L_EN_SHIFT, @@ -1847,6 +1871,14 @@ static void da7219_handle_pdata(struct snd_soc_component *component) snd_soc_component_write(component, DA7219_MICBIAS_CTRL, micbias_lvl); + /* +* Calculate delay required to compensate for DC offset in +* Mic PGA, based
RE: [PATCH v2] ASoC: da7219: Allow pdata to specify a VDDIO
On 23 July 2018 00:28, Daniel Kurtz wrote: > Some systems do not have software controllable regulators driving the > DA7219's supplies, nor can they use device tree to create "always-on fixed > regulators" to easily pretend like they do. > > On these systems the call to devm_regulator_bulk_get() just creates > a set of dummy registers. Calling regulator_get_voltage() on a dummy > regulator just returns -EINVAL, in which case the DA7219 is always set up > to use the default VDDIO voltage range of 2.5-3.6V. > > Provide a new device property to let such systems specify a different > VDDIO if needed (e.g., 1.8V). I'm not sure what the general view on this is. In the past it was suggested the regulator framework was the way to go to pass this kind of information, but obviously ACPI platforms don't tend to use it. Mark, what is your feeling on this? Would you be in favour of some kind of fixed voltage regulator representation, similar to the patch for the AMD platform (ASoC: AMD: Add a fix voltage regulator for DA7219 and ADAU7002), albeit tweaked to avoid asynchronous probe() issues, or is this a reasonable route? Personally in my mind, and in an ideal world, I'd prefer just one method for retrieving this data in the codec driver, but that may not be sensible. > > Signed-off-by: Daniel Kurtz > --- > Changes for v2: > - fix to use device_property_read_u32() > > include/sound/da7219.h| 2 ++ > sound/soc/codecs/da7219.c | 19 +-- > 2 files changed, 15 insertions(+), 6 deletions(-) > > diff --git a/include/sound/da7219.h b/include/sound/da7219.h > index 1bfcb16f2d10ab..16ab125ad4adbf 100644 > --- a/include/sound/da7219.h > +++ b/include/sound/da7219.h > @@ -38,6 +38,8 @@ struct da7219_pdata { > > const char *dai_clks_name; > > + u32 vddio; > + > /* Mic */ > enum da7219_micbias_voltage micbias_lvl; > enum da7219_mic_amp_in_sel mic_amp_in_sel; > diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c > index 980a6a8bf56d38..9893920b26f41f 100644 > --- a/sound/soc/codecs/da7219.c > +++ b/sound/soc/codecs/da7219.c > @@ -1634,6 +1634,9 @@ static struct da7219_pdata *da7219_fw_to_pdata(struct > snd_soc_component *compone > else > pdata->mic_amp_in_sel = DA7219_MIC_AMP_IN_SEL_DIFF; > > + if (device_property_read_u32(dev, "dlg,vddio", &of_val32) >= 0) > + pdata->vddio = of_val32; > + > return pdata; > } > > @@ -1717,8 +1720,12 @@ static int da7219_handle_supplies(struct > snd_soc_component *component) > /* Determine VDDIO voltage provided */ > vddio = da7219->supplies[DA7219_SUPPLY_VDDIO].consumer; > ret = regulator_get_voltage(vddio); > + /* If regulator_get_voltage() fails, try to use vddio from pdata. */ > + if (ret < 0 && da7219->pdata) > + ret = da7219->pdata->vddio; > if (ret < 120) > - dev_warn(component->dev, "Invalid VDDIO voltage\n"); > + dev_warn(component->dev, "Invalid VDDIO voltage: %d mV\n", > + ret); > else if (ret < 280) > io_voltage_lvl = DA7219_IO_VOLTAGE_LEVEL_1_2V_2_8V; > > @@ -1872,6 +1879,11 @@ static int da7219_probe(struct snd_soc_component > *component) > mutex_init(&da7219->ctrl_lock); > mutex_init(&da7219->pll_lock); > > + /* Handle DT/ACPI/Platform data */ > + da7219->pdata = dev_get_platdata(component->dev); > + if (!da7219->pdata) > + da7219->pdata = da7219_fw_to_pdata(component); > + > /* Regulator configuration */ > ret = da7219_handle_supplies(component); > if (ret) > @@ -1897,11 +1909,6 @@ static int da7219_probe(struct snd_soc_component > *component) > break; > } > > - /* Handle DT/ACPI/Platform data */ > - da7219->pdata = dev_get_platdata(component->dev); > - if (!da7219->pdata) > - da7219->pdata = da7219_fw_to_pdata(component); > - > da7219_handle_pdata(component); > > /* Check if MCLK provided */ > -- > 2.18.0.233.g985f88cf7e-goog
RE: [PATCH v2] power: supply: da9150-fg: remove VLA usage
On 09 March 2018 18:27, Gustavo A. R. Silva wrote: > In preparation to enabling -Wvla, remove VLA usage and replace it > with fixed-length arrays. > > DA9150_QIF_LONG_SIZE (4 bytes) is the biggest size of an attribute which can > be accessed [1]. > > Fixed as part of the directive to remove all VLAs from > the kernel: https://lkml.org/lkml/2018/3/7/621 > > [1] https://marc.info/?l=kernel-hardening&m=152059600524753&w=2 > > Signed-off-by: Gustavo A. R. Silva Acked-by: Adam Thomson > --- > Changes in v2: > - Use DA9150_QIF_LONG_SIZE instead of DA9150_QIF_BYTE_SIZE as the >maximum size for array 'buf'. Thanks to Adam Thomson for the >feedback on this. > - Update changelog based on Adam's comments. > > drivers/power/supply/da9150-fg.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/power/supply/da9150-fg.c > b/drivers/power/supply/da9150-fg.c > index 8b8ce97..7ea2188 100644 > --- a/drivers/power/supply/da9150-fg.c > +++ b/drivers/power/supply/da9150-fg.c > @@ -92,7 +92,7 @@ struct da9150_fg { > static u32 da9150_fg_read_attr(struct da9150_fg *fg, u8 code, u8 size) > > { > - u8 buf[size]; > + u8 buf[DA9150_QIF_LONG_SIZE]; > u8 read_addr; > u32 res = 0; > int i; > @@ -111,7 +111,7 @@ static void da9150_fg_write_attr(struct da9150_fg *fg, u8 > code, u8 size, >u32 val) > > { > - u8 buf[size]; > + u8 buf[DA9150_QIF_LONG_SIZE]; > u8 write_addr; > int i; > > -- > 2.7.4
RE: [PATCH v4 0/7] typec: tcpm: Add sink side support for PPS
On 09 March 2018 17:34, Greg Kroah-Hartman wrote: > On Tue, Jan 02, 2018 at 03:50:48PM +0000, Adam Thomson wrote: > > This patch set adds sink side support for the PPS feature introduced in the > > USB PD 3.0 specification. > > > > The source PPS supply is represented using the Power Supply framework to > > provide > > access and control APIs for dealing with it's operating voltage and current, > > and switching between a standard PDO and PPS APDO operation. During standard > PDO > > operation the voltage and current is read-only, but for APDO PPS these are > > writable as well to allow for control. > > > > It should be noted that the keepalive for PPS is not handled within TCPM. > > The > > expectation is that the external user will be required to ensure re-requests > > occur regularly to ensure PPS remains and the source does not hard reset. > > I've applied the first 3 patches now. Can you rebase and resend based > on the feedback so far? That's great. Thanks. Need to also rebase based on the patch 'Revert "typec: tcpm: Only request matching pdos"' as this impacts the APDO selection logic. This is on my TODO list and will try and deal with it ASAP, hopefully this week.
RE: [PATCH v7 2/6] Documentation: power: Initial effort to document power_supply ABI
On 26 March 2018 10:57, Greg Kroah-Hartman wrote: > On Fri, Mar 23, 2018 at 10:12:21AM +0000, Adam Thomson wrote: > > This commit adds generic ABI information regarding power_supply > > properties. This is an initial attempt to try and align the usage > > of these properties between drivers. As part of this commit, > > common Battery and USB related properties have been listed. > > > > Signed-off-by: Adam Thomson > > --- > > Documentation/ABI/testing/sysfs-class-power | 443 > > > MAINTAINERS | 1 + > > 2 files changed, 444 insertions(+) > > How was this not documented before? As an FYI, there is some overall documentation under: Documentation/power/power_supply_class.txt However, after discussions with Heikki, it was determined something more detailed would be useful to help clarify usage. > Anyway, any objection to me taking this through the USB tree, as the > typec patches depend on the 3/6 patch here. If so, can I get an ack > from the power supply maintainers? > > thanks, > > greg k-h
[PATCH v5 5/5] typec: tcpm: Add support for sink PPS related messages
This commit adds sink side support for Get_Status, Status, Get_PPS_Status and PPS_Status handling. As there's the potential for a partner to respond with Not_Supported, handling of this message is also added. Sending of Not_Supported is added to handle messagescreceived but not yet handled. Signed-off-by: Adam Thomson Acked-by: Heikki Krogerus --- drivers/usb/typec/tcpm.c | 152 --- 1 file changed, 143 insertions(+), 9 deletions(-) diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index 18ab36f..148db99 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -19,7 +19,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -113,6 +115,11 @@ S(SNK_TRYWAIT_VBUS),\ S(BIST_RX), \ \ + S(GET_STATUS_SEND), \ + S(GET_STATUS_SEND_TIMEOUT), \ + S(GET_PPS_STATUS_SEND), \ + S(GET_PPS_STATUS_SEND_TIMEOUT), \ + \ S(ERROR_RECOVERY), \ S(PORT_RESET), \ S(PORT_RESET_WAIT_OFF) @@ -143,6 +150,7 @@ enum pd_msg_request { PD_MSG_NONE = 0, PD_MSG_CTRL_REJECT, PD_MSG_CTRL_WAIT, + PD_MSG_CTRL_NOT_SUPP, PD_MSG_DATA_SINK_CAP, PD_MSG_DATA_SOURCE_CAP, }; @@ -1398,10 +1406,42 @@ static int tcpm_validate_caps(struct tcpm_port *port, const u32 *pdo, /* * PD (data, control) command handling functions */ +static inline enum tcpm_state ready_state(struct tcpm_port *port) +{ + if (port->pwr_role == TYPEC_SOURCE) + return SRC_READY; + else + return SNK_READY; +} static int tcpm_pd_send_control(struct tcpm_port *port, enum pd_ctrl_msg_type type); +static void tcpm_handle_alert(struct tcpm_port *port, const __le32 *payload, + int cnt) +{ + u32 p0 = le32_to_cpu(payload[0]); + unsigned int type = usb_pd_ado_type(p0); + + if (!type) { + tcpm_log(port, "Alert message received with no type"); + return; + } + + /* Just handling non-battery alerts for now */ + if (!(type & USB_PD_ADO_TYPE_BATT_STATUS_CHANGE)) { + switch (port->state) { + case SRC_READY: + case SNK_READY: + tcpm_set_state(port, GET_STATUS_SEND, 0); + break; + default: + tcpm_queue_message(port, PD_MSG_CTRL_WAIT); + break; + } + } +} + static void tcpm_pd_data_request(struct tcpm_port *port, const struct pd_message *msg) { @@ -1487,6 +1527,14 @@ static void tcpm_pd_data_request(struct tcpm_port *port, tcpm_set_state(port, BIST_RX, 0); } break; + case PD_DATA_ALERT: + tcpm_handle_alert(port, msg->payload, cnt); + break; + case PD_DATA_BATT_STATUS: + case PD_DATA_GET_COUNTRY_INFO: + /* Currently unsupported */ + tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP); + break; default: tcpm_log(port, "Unhandled data message type %#x", type); break; @@ -1569,6 +1617,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, break; case PD_CTRL_REJECT: case PD_CTRL_WAIT: + case PD_CTRL_NOT_SUPP: switch (port->state) { case SNK_NEGOTIATE_CAPABILITIES: /* USB PD specification, Figure 8-43 */ @@ -1688,12 +1737,84 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, break; } break; + case PD_CTRL_GET_SOURCE_CAP_EXT: + case PD_CTRL_GET_STATUS: + case PD_CTRL_FR_SWAP: + case PD_CTRL_GET_PPS_STATUS: + case PD_CTRL_GET_COUNTRY_CODES: + /* Currently not supported */ + tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP); + break; default: tcpm_log(port, "Unhandled ctrl message type %#x", type); break; } } +static void tcpm_pd_ext_msg_request(struct tcpm_port *port, + const struct pd_message *msg) +{ + enum pd_ext_msg_type type = pd_header_type_le(msg->header); + unsigned int data_size = pd_ext_header_data_size_le(msg->ext_msg.header); + u8 *data; + + if (!(msg->ext_msg.header && PD_EXT_HDR_CHUNKED)) { + tcpm_log(port, "Unchunked extended messages
[PATCH v5 2/5] Documentation: power: Initial effort to document power_supply ABI
This commit adds generic ABI information regarding power_supply properties. This is an initial attempt to try and align the usage of these properties between drivers. As part of this commit, common Battery and USB related properties have been listed. Signed-off-by: Adam Thomson --- Documentation/ABI/testing/sysfs-class-power | 443 MAINTAINERS | 1 + 2 files changed, 444 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-class-power b/Documentation/ABI/testing/sysfs-class-power index f85ce9e..e046566 100644 --- a/Documentation/ABI/testing/sysfs-class-power +++ b/Documentation/ABI/testing/sysfs-class-power @@ -1,3 +1,446 @@ += General Properties = + +What: /sys/class/power_supply//manufacturer +Date: May 2007 +Contact: linux...@vger.kernel.org +Description: + Reports the name of the device manufacturer. + + Access: Read + Valid values: Represented as string + +What: /sys/class/power_supply//model_name +Date: May 2007 +Contact: linux...@vger.kernel.org +Description: + Reports the name of the device model. + + Access: Read + Valid values: Represented as string + +What: /sys/class/power_supply//serial_number +Date: January 2008 +Contact: linux...@vger.kernel.org +Description: + Reports the serial number of the device. + + Access: Read + Valid values: Represented as string + +What: /sys/class/power_supply//type +Date: May 2010 +Contact: linux...@vger.kernel.org +Description: + Describes the main type of the supply. + + Access: Read + Valid values: "Battery", "UPS", "Mains", "USB" + += Battery Properties = + +What: /sys/class/power_supply//capacity +Date: May 2007 +Contact: linux...@vger.kernel.org +Description: + Fine grain representation of battery capacity. + Access: Read + Valid values: 0 - 100 (percent) + +What: /sys/class/power_supply//capacity_alert_max +Date: July 2012 +Contact: linux...@vger.kernel.org +Description: + Maximum battery capacity trip-wire value where the supply will + notify user-space of the event. This is normally used for the + battery discharging scenario where user-space needs to know the + battery has dropped to an upper level so it can take + appropriate action (e.g. warning user that battery level is + low). + + Access: Read, Write + Valid values: 0 - 100 (percent) + +What: /sys/class/power_supply//capacity_alert_min +Date: July 2012 +Contact: linux...@vger.kernel.org +Description: + Minimum battery capacity trip-wire value where the supply will + notify user-space of the event. This is normally used for the + battery discharging scenario where user-space needs to know the + battery has dropped to a lower level so it can take + appropriate action (e.g. warning user that battery level is + critically low). + + Access: Read, Write + Valid values: 0 - 100 (percent) + +What: /sys/class/power_supply//capacity_level +Date: June 2009 +Contact: linux...@vger.kernel.org +Description: + Coarse representation of battery capacity. + + Access: Read + Valid values: "Unknown", "Critical", "Low", "Normal", "High", + "Full" + +What: /sys/class/power_supply//current_avg +Date: May 2007 +Contact: linux...@vger.kernel.org +Description: + Reports an average IBAT current reading for the battery, over a + fixed period. Normally devices will provide a fixed interval in + which they average readings to smooth out the reported value. + + Access: Read + Valid values: Represented in microamps + +What: /sys/class/power_supply//current_max +Date: October 2010 +Contact: linux...@vger.kernel.org +Description: + Reports the maximum IBAT current allowed into the battery. + + Access: Read + Valid values: Represented in microamps + +What: /sys/class/power_supply//current_now +Date: May 2007 +Contact: linux...@vger.kernel.org +Description: + Reports an instant, single IBAT current reading for the battery. + This value is not averaged/smoothed. + + Access: Read + Valid values: Represented in microamps +
[PATCH v5 4/5] typec: tcpm: Represent source supply through power_supply
This commit adds a power_supply class instance to represent a PD source's voltage and current properties. This provides an interface for reading these properties from user-space or other drivers. For PPS enabled Sources, this also provides write access to set the current and voltage and allows for swapping between standard PDO and PPS APDO. As this represents a superset of the information provided in the fusb302 driver, the power_supply instance in that code is removed as part of this change, so reverting the commit titled 'typec: tcpm: Represent source supply through power_supply class' Signed-off-by: Adam Thomson --- drivers/usb/typec/Kconfig | 1 + drivers/usb/typec/fusb302/Kconfig | 2 +- drivers/usb/typec/fusb302/fusb302.c | 63 +- drivers/usb/typec/tcpm.c| 242 +++- 4 files changed, 245 insertions(+), 63 deletions(-) diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig index bcb2744..1ef606d 100644 --- a/drivers/usb/typec/Kconfig +++ b/drivers/usb/typec/Kconfig @@ -48,6 +48,7 @@ if TYPEC config TYPEC_TCPM tristate "USB Type-C Port Controller Manager" depends on USB + select POWER_SUPPLY help The Type-C Port Controller Manager provides a USB PD and USB Type-C state machine for use with Type-C Port Controllers. diff --git a/drivers/usb/typec/fusb302/Kconfig b/drivers/usb/typec/fusb302/Kconfig index 48a4f2f..fce099f 100644 --- a/drivers/usb/typec/fusb302/Kconfig +++ b/drivers/usb/typec/fusb302/Kconfig @@ -1,6 +1,6 @@ config TYPEC_FUSB302 tristate "Fairchild FUSB302 Type-C chip driver" - depends on I2C && POWER_SUPPLY + depends on I2C help The Fairchild FUSB302 Type-C chip driver that works with Type-C Port Controller Manager to provide USB PD and USB diff --git a/drivers/usb/typec/fusb302/fusb302.c b/drivers/usb/typec/fusb302/fusb302.c index 06794c0..6a8f279 100644 --- a/drivers/usb/typec/fusb302/fusb302.c +++ b/drivers/usb/typec/fusb302/fusb302.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -99,11 +98,6 @@ struct fusb302_chip { /* lock for sharing chip states */ struct mutex lock; - /* psy + psy status */ - struct power_supply *psy; - u32 current_limit; - u32 supply_voltage; - /* chip status */ enum toggling_mode toggling_mode; enum src_current_status src_current_status; @@ -861,13 +855,11 @@ static int tcpm_set_vbus(struct tcpc_dev *dev, bool on, bool charge) chip->vbus_on = on; fusb302_log(chip, "vbus := %s", on ? "On" : "Off"); } - if (chip->charge_on == charge) { + if (chip->charge_on == charge) fusb302_log(chip, "charge is already %s", charge ? "On" : "Off"); - } else { + else chip->charge_on = charge; - power_supply_changed(chip->psy); - } done: mutex_unlock(&chip->lock); @@ -883,11 +875,6 @@ static int tcpm_set_current_limit(struct tcpc_dev *dev, u32 max_ma, u32 mv) fusb302_log(chip, "current limit: %d ma, %d mv (not implemented)", max_ma, mv); - chip->supply_voltage = mv; - chip->current_limit = max_ma; - - power_supply_changed(chip->psy); - return 0; } @@ -1686,43 +1673,6 @@ static irqreturn_t fusb302_irq_intn(int irq, void *dev_id) return IRQ_HANDLED; } -static int fusb302_psy_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct fusb302_chip *chip = power_supply_get_drvdata(psy); - - switch (psp) { - case POWER_SUPPLY_PROP_ONLINE: - val->intval = chip->charge_on; - break; - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = chip->supply_voltage * 1000; /* mV -> µV */ - break; - case POWER_SUPPLY_PROP_CURRENT_MAX: - val->intval = chip->current_limit * 1000; /* mA -> µA */ - break; - default: - return -ENODATA; - } - - return 0; -} - -static enum power_supply_property fusb302_psy_properties[] = { - POWER_SUPPLY_PROP_ONLINE, - POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_CURRENT_MAX, -}; - -static const struct power_supply_desc fusb302_psy_desc = { - .name = "fusb302-typec-source", - .type = POWER_SUPPLY_TYPE_USB_TYPE_C, - .properties = fusb302_psy_properties, - .num_properties = ARRAY_SIZE(fusb302_psy_properties), - .get_proper
[PATCH v5 0/5] typec: tcpm: Add sink side support for PPS
This patch set adds sink side support for the PPS feature introduced in the USB PD 3.0 specification. The source PPS supply is represented using the Power Supply framework to provide access and control APIs for dealing with it's operating voltage and current, and switching between a standard PDO and PPS APDO operation. During standard PDO operation the voltage and current is read-only, but for APDO PPS these are writable as well to allow for control. It should be noted that the keepalive for PPS is not handled within TCPM. The expectation is that the external user will be required to ensure re-requests occur regularly to ensure PPS remains and the source does not hard reset. Changes in v5: - Rebase on branch with 'Revert "typec: tcpm: Only request matching pdos"' and header changes already included. - Update power_supply registration to make power_supply names unique per port, to avoid errors creating duplicate psy instances. New name uses port dev name as a suffix. - Renamed 'connected_type' psy property to 'usb_type', as requested by maintainer. - Added initial attempt at generic ABI documentation for common psy class properties for Battery and USB type supplies. - Small update to PPS APDO selection code to limit maximum current requested based on sink maximum allowed current. Have left Heikki's 'Acked-by' tag as it's a minor change, but can remove if that's not deemed appropriate. Changes in v4: - For PD 3.0 definitions patch, make it benign with regards to existing TCPM code so build isn't broken if this one patch is applied, as suggested by kbuild robot. Update for dynamic revision is moved to be part of sink side PPS support patch. - Use PTR_ERR_OR_ZERO macro to simplify return of devm_tcpm_psy_register() function, as suggested by kbuild robot. - Make devm_tcpm_psy_register() static as not used outside this file. Changes in v3: - Drop 'RFC' from patch series titles - Rename PPS related defines to be PPS specific rather than generic APDO titles - Update source caps logging to only print PPS APDOs, and for others report as undefined. - Add ABI documentation for tcpm-source-psy sysfs properties - Rebase PDO selection on top of 'typec: tcpm: Only request matching pdos' patch. - Update capabilities validation introduced in 'typec: tcpm: Validate source and sink caps' to support PPS APDOs. - Dropped power_supply 'type' property update for PPS addition - Added 'connected_type' property to power_supply framework, to support supplies which can report multiple connected types (e.g. USB), as discussed with Heikki. Changes in v2: - Use USB_PD and usb_pd prefixes for macros and inline functions in headers. - Negotiate spec revision of PD headers during initial contract agreement. - New headers now use SPDX tags for referencing correct license. NOTE: Code changes based on usb-next (027bd6cafd9a1e3a109b5e5682c85ac84e804a8d) Adam Thomson (5): typec: tcpm: Add core support for sink side PPS Documentation: power: Initial effort to document power_supply ABI power: supply: Add 'usb_type' property and supporting code typec: tcpm: Represent source supply through power_supply typec: tcpm: Add support for sink PPS related messages Documentation/ABI/testing/sysfs-class-power | 455 ++ MAINTAINERS | 1 + drivers/power/supply/power_supply_sysfs.c | 50 ++ drivers/usb/typec/Kconfig | 1 + drivers/usb/typec/fusb302/Kconfig | 2 +- drivers/usb/typec/fusb302/fusb302.c | 63 +- drivers/usb/typec/tcpm.c| 916 +++- include/linux/power_supply.h| 16 + include/linux/usb/pd.h | 4 +- include/linux/usb/tcpm.h| 2 +- 10 files changed, 1422 insertions(+), 88 deletions(-) -- 1.9.1
[PATCH v5 1/5] typec: tcpm: Add core support for sink side PPS
This commit adds code to handle requesting of PPS APDOs. Switching between standard PDOs and APDOs, and re-requesting an APDO to modify operating voltage/current will be triggered by an external call into TCPM. Signed-off-by: Adam Thomson Acked-by: Heikki Krogerus --- drivers/usb/typec/tcpm.c | 524 +-- include/linux/usb/pd.h | 4 +- include/linux/usb/tcpm.h | 2 +- 3 files changed, 513 insertions(+), 17 deletions(-) diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index 4c0fc54..b4cf1ca 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -47,6 +47,7 @@ S(SNK_DISCOVERY_DEBOUNCE_DONE), \ S(SNK_WAIT_CAPABILITIES), \ S(SNK_NEGOTIATE_CAPABILITIES), \ + S(SNK_NEGOTIATE_PPS_CAPABILITIES), \ S(SNK_TRANSITION_SINK), \ S(SNK_TRANSITION_SINK_VBUS),\ S(SNK_READY), \ @@ -166,6 +167,16 @@ struct pd_mode_data { struct typec_altmode_desc altmode_desc[SVID_DISCOVERY_MAX]; }; +struct pd_pps_data { + u32 min_volt; + u32 max_volt; + u32 max_curr; + u32 out_volt; + u32 op_curr; + bool supported; + bool active; +}; + struct tcpm_port { struct device *dev; @@ -233,6 +244,7 @@ struct tcpm_port { struct completion swap_complete; int swap_status; + unsigned int negotiated_rev; unsigned int message_id; unsigned int caps_count; unsigned int hard_reset_count; @@ -259,6 +271,7 @@ struct tcpm_port { unsigned int max_snk_ma; unsigned int max_snk_mw; unsigned int operating_snk_mw; + bool update_sink_caps; /* Requested current / voltage */ u32 current_limit; @@ -275,8 +288,13 @@ struct tcpm_port { /* VDO to retry if UFP responder replied busy */ u32 vdo_retry; - /* Alternate mode data */ + /* PPS */ + struct pd_pps_data pps_data; + struct completion pps_complete; + bool pps_pending; + int pps_status; + /* Alternate mode data */ struct pd_mode_data mode_data; struct typec_altmode *partner_altmode[SVID_DISCOVERY_MAX]; struct typec_altmode *port_altmode[SVID_DISCOVERY_MAX]; @@ -494,6 +512,16 @@ static void tcpm_log_source_caps(struct tcpm_port *port) pdo_max_voltage(pdo), pdo_max_power(pdo)); break; + case PDO_TYPE_APDO: + if (pdo_apdo_type(pdo) == APDO_TYPE_PPS) + scnprintf(msg, sizeof(msg), + "%u-%u mV, %u mA", + pdo_pps_apdo_min_voltage(pdo), + pdo_pps_apdo_max_voltage(pdo), + pdo_pps_apdo_max_current(pdo)); + else + strcpy(msg, "undefined APDO"); + break; default: strcpy(msg, "undefined"); break; @@ -777,11 +805,13 @@ static int tcpm_pd_send_source_caps(struct tcpm_port *port) msg.header = PD_HEADER_LE(PD_CTRL_REJECT, port->pwr_role, port->data_role, + port->negotiated_rev, port->message_id, 0); } else { msg.header = PD_HEADER_LE(PD_DATA_SOURCE_CAP, port->pwr_role, port->data_role, + port->negotiated_rev, port->message_id, port->nr_src_pdo); } @@ -802,11 +832,13 @@ static int tcpm_pd_send_sink_caps(struct tcpm_port *port) msg.header = PD_HEADER_LE(PD_CTRL_REJECT, port->pwr_role, port->data_role, + port->negotiated_rev, port->message_id, 0); } else { msg.header = PD_HEADER_LE(PD_DATA_SINK_CAP, port->pwr_role, port->data_role, + port->negotiated_rev, port->message_id, port->nr_snk_pdo); } @@ -1173,6 +1205,7 @@ static void vdm_run_state_machine(struct tcpm_port *port) msg.header = PD_HE
[PATCH v5 3/5] power: supply: Add 'usb_type' property and supporting code
This commit adds the 'usb_type' property to represent USB supplies which can report a number of different types based on a connection event. Examples of this already exist in drivers whereby the existing 'type' property is updated, based on an event, to represent what was connected (e.g. USB, USB_DCP, USB_ACA, ...). Current implementations however don't show all supported connectable types, so this knowledge has to be exlicitly known for each driver that supports this. The 'usb_type' property is intended to fill this void and show users all possible USB types supported by a driver. The property, when read, shows all available types for the driver, and the one currently chosen is highlighted/bracketed. It is expected that the 'type' property would then just show the top-level type 'USB', and this would be static. Currently the 'usb_type' enum contains all of the USB variant types that exist for the 'type' enum at this time, and in addition has SDP and PPS types. The mirroring is intentional so as to not impact existing usage of the 'type' property. Signed-off-by: Adam Thomson Acked-by: Heikki Krogerus Reviewed-by: Sebastian Reichel --- Documentation/ABI/testing/sysfs-class-power | 12 +++ drivers/power/supply/power_supply_sysfs.c | 50 + include/linux/power_supply.h| 16 + 3 files changed, 78 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-class-power b/Documentation/ABI/testing/sysfs-class-power index e046566..5e23e22 100644 --- a/Documentation/ABI/testing/sysfs-class-power +++ b/Documentation/ABI/testing/sysfs-class-power @@ -409,6 +409,18 @@ Description: Access: Read Valid values: Represented in 1/10 Degrees Celsius +What: /sys/class/power_supply//usb_type +Date: March 2018 +Contact: linux...@vger.kernel.org +Description: + Reports what type of USB connection is currently active for + the supply, for example it can show if USB-PD capable source + is attached. + + Access: Read-Only + Valid values: "Unknown", "SDP", "DCP", "CDP", "ACA", "C", "PD", + "PD_DRP", "PD_PPS", "BrickID" + What: /sys/class/power_supply//voltage_max Date: January 2008 Contact: linux...@vger.kernel.org diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c index 5204f11..b68def4 100644 --- a/drivers/power/supply/power_supply_sysfs.c +++ b/drivers/power/supply/power_supply_sysfs.c @@ -46,6 +46,11 @@ "USB_PD", "USB_PD_DRP", "BrickID" }; +static const char * const power_supply_usb_type_text[] = { + "Unknown", "SDP", "DCP", "CDP", "ACA", "C", + "PD", "PD_DRP", "PD_PPS", "BrickID" +}; + static const char * const power_supply_status_text[] = { "Unknown", "Charging", "Discharging", "Not charging", "Full" }; @@ -73,6 +78,46 @@ "Unknown", "System", "Device" }; +static ssize_t power_supply_show_usb_type(struct device *dev, + enum power_supply_usb_type *usb_types, + ssize_t num_usb_types, + union power_supply_propval *value, + char *buf) +{ + enum power_supply_usb_type usb_type; + ssize_t count = 0; + bool match = false; + int i; + + if ((!usb_types) || (num_usb_types <= 0)) { + dev_warn(dev, "driver has no valid connected types\n"); + return -ENODATA; + } + + for (i = 0; i < num_usb_types; ++i) { + usb_type = usb_types[i]; + + if (value->intval == usb_type) { + count += sprintf(buf + count, "[%s] ", +power_supply_usb_type_text[usb_type]); + match = true; + } else { + count += sprintf(buf + count, "%s ", +power_supply_usb_type_text[usb_type]); + } + } + + if (!match) { + dev_warn(dev, "driver reporting unsupported connected type\n"); + return -EINVAL; + } + + if (count) + buf[count - 1] = '\n'; + + return count; +} + static ssize_t power_supply_show_property(struct device *dev, struc
RE: [PATCH v5 5/5] typec: tcpm: Add support for sink PPS related messages
On 22 March 2018 03:53, Guenter Roeck wrote: > > +static void tcpm_pd_ext_msg_request(struct tcpm_port *port, > > + const struct pd_message *msg) > > +{ > > + enum pd_ext_msg_type type = pd_header_type_le(msg->header); > > + unsigned int data_size = pd_ext_header_data_size_le(msg- > >ext_msg.header); > > + u8 *data; > > + > > + if (!(msg->ext_msg.header && PD_EXT_HDR_CHUNKED)) { > > + tcpm_log(port, "Unchunked extended messages unsupported"); > > + return; > > + } > > + > > + if (data_size > (PD_EXT_MAX_CHUNK_DATA)) { > > + tcpm_log(port, "Chunk handling not yet supported"); > > + return; > > + } > > + > > + data = kzalloc(data_size, GFP_KERNEL); > > + if (!data) { > > + tcpm_log(port, "Failed to allocate memory for ext msg data"); > > + return; > > + } > > + memcpy(data, msg->ext_msg.data, data_size); > > + > > + switch (type) { > > + case PD_EXT_STATUS: > > + /* > > +* If PPS related events raised then get PPS status to clear > > +* (see USB PD 3.0 Spec, 6.5.2.4) > > +*/ > > + if (data[USB_PD_EXT_SDB_EVENT_FLAGS] & > USB_PD_EXT_SDB_PPS_EVENTS) > > This seems to be the only use of 'data'. Can you explain why it is needed > in the first place ? Am I missing something ? Actually it's a fair point. Right now it's not needed so will remove it and directly reference the ext_msg.data array.
RE: [PATCH v5 1/5] typec: tcpm: Add core support for sink side PPS
On 22 March 2018 04:03, Guenter Roeck wrote: > > static enum pdo_err tcpm_caps_err(struct tcpm_port *port, const u32 *pdo, > > @@ -1308,6 +1347,26 @@ static enum pdo_err tcpm_caps_err(struct tcpm_port > *port, const u32 *pdo, > > pdo_min_voltage(pdo[i - 1]))) > > return PDO_ERR_DUPE_PDO; > > break; > > + /* > > +* The Programmable Power Supply APDOs, if present, > > +* shall be sent in Maximum Voltage order; > > +* lowest to highest. > > +*/ > > + case PDO_TYPE_APDO: > > + if (pdo_apdo_type(pdo[i]) != APDO_TYPE_PPS) > > + break; > > + > > + if (pdo_pps_apdo_max_current(pdo[i]) < > > + pdo_pps_apdo_max_current(pdo[i - 1])) > > + return > PDO_ERR_PPS_APDO_NOT_SORTED; > > + else if ((pdo_pps_apdo_min_voltage(pdo[i]) == > > + pdo_pps_apdo_min_voltage(pdo[i - 1])) > && > > +(pdo_pps_apdo_max_voltage(pdo[i]) == > > + pdo_pps_apdo_max_voltage(pdo[i - 1])) > && > > +(pdo_pps_apdo_max_current(pdo[i]) == > > + pdo_pps_apdo_max_current(pdo[i - 1]))) > > Unnecessary ( ) I have to say I think it's neater/clearer with than without but if that's something you really don't like then I'll remove them. > > +static int tcpm_pps_set_op_curr(struct tcpm_port *port, u16 op_curr) > > +{ > > + unsigned int target_mw; > > + int ret = 0; > > + > > Unnecessary initialization. Ok, will remove. > > +static int tcpm_pps_set_out_volt(struct tcpm_port *port, u16 out_volt) > > +{ > > + unsigned int target_mw; > > + int ret = 0; > > + > Unnecessary initialization. Ditto > > + mutex_lock(&port->swap_lock); > > + mutex_lock(&port->lock); > > + > > + if (!port->pps_data.active) { > > + ret = -EOPNOTSUPP; > > + goto port_unlock; > > + } > > + > > + if (port->state != SNK_READY) { > > + ret = -EAGAIN; > > + goto port_unlock; > > + } > > + > > + if ((out_volt < port->pps_data.min_volt) || > > + (out_volt > port->pps_data.max_volt)) { > > Unnecessary ( ) Ok. > > + ret = -EINVAL; > > + goto port_unlock; > > + } > > + > > + target_mw = (port->pps_data.op_curr * out_volt) / 1000; > > + if (target_mw < port->operating_snk_mw) { > > + ret = -EINVAL; > > + goto port_unlock; > > + } > > + > > + reinit_completion(&port->pps_complete); > > + port->pps_data.out_volt = out_volt; > > + port->pps_status = 0; > > + port->pps_pending = true; > > + tcpm_set_state(port, SNK_NEGOTIATE_PPS_CAPABILITIES, 0); > > + mutex_unlock(&port->lock); > > + > > + if (!wait_for_completion_timeout(&port->pps_complete, > > + msecs_to_jiffies(PD_STATE_MACHINE_TIMEOUT))) > > + ret = -ETIMEDOUT; > > + else > > + ret = port->pps_status; > > + > > + goto swap_unlock; > > + > > +port_unlock: > > + mutex_unlock(&port->lock); > > +swap_unlock: > > + mutex_unlock(&port->swap_lock); > > + > > + return ret; > > +} > > + > > +static int tcpm_pps_activate(struct tcpm_port *port, bool activate) > > +{ > > + int ret = 0; > > + > > + mutex_lock(&port->swap_lock); > > + mutex_lock(&port->lock); > > + > > + if (!port->pps_data.supported) { > > + ret = -EOPNOTSUPP; > > + goto port_unlock; > > + } > > + > > + /* Trying to deactivate PPS when already deactivated so just bail */ > > + if ((!port->pps_data.active) && (!activate)) > > Unnecessary ( ) Actually agree on this one :)
RE: [PATCH v5 3/5] power: supply: Add 'usb_type' property and supporting code
On 22 March 2018 04:08, Guenter Roeck wrote: > > +static ssize_t power_supply_show_usb_type(struct device *dev, > > + enum power_supply_usb_type > *usb_types, > > + ssize_t num_usb_types, > > + union power_supply_propval *value, > > + char *buf) > > +{ > > + enum power_supply_usb_type usb_type; > > + ssize_t count = 0; > > + bool match = false; > > + int i; > > + > > + if ((!usb_types) || (num_usb_types <= 0)) { > > Unnecessary ( ) Fine, can remove. > > > + dev_warn(dev, "driver has no valid connected types\n"); > > Are those warnings useful or do they just clog the log ? Either case, if that > happens, > wouldn't it be better to detect the situation during registration and abort ? This is added as an optional property for supply drivers. This will only show up if a supply driver adds the USB_TYPE property to its list, and then someone attempts to access it. Actually there's no current checking for the psy_desc information provided to the register function, so for example if it's NULL then the kernel will dump when it tries to dereference. I'll take a look at this and see if I can add something, including checks on the usb_type property.
RE: [PATCH v5 4/5] typec: tcpm: Represent source supply through power_supply
On 22 March 2018 04:09, Guenter Roeck wrote: > > +static int tcpm_psy_set_prop(struct power_supply *psy, > > +enum power_supply_property psp, > > +const union power_supply_propval *val) > > +{ > > + struct tcpm_port *port = power_supply_get_drvdata(psy); > > + int ret = 0; > > + > > + switch (psp) { > > + case POWER_SUPPLY_PROP_ONLINE: > > + ret = tcpm_psy_set_online(port, val); > > + break; > > + case POWER_SUPPLY_PROP_VOLTAGE_NOW: > > + if ((val->intval < (port->pps_data.min_volt * 1000)) || > > + (val->intval > (port->pps_data.max_volt * 1000))) > > + ret = -EINVAL; > > + else > > + ret = tcpm_pps_set_out_volt(port, (val->intval / 1000)); > > + break; > > + case POWER_SUPPLY_PROP_CURRENT_NOW: > > + if (val->intval > (port->pps_data.max_curr * 1000)) > > + ret = -EINVAL; > > + else > > + ret = tcpm_pps_set_op_curr(port, (val->intval / 1000)); > > I am really not a friend of excessive ( ). Yes, I got that. :) I am of the opinion that they should be used to enforce precedence. This to me is good coding practice and makes it unambiguous for the reader. That's why I use them as above. Do you think the above uses make it harder to understand or more difficult to maintain?
[PATCH v6 6/6] typec: tcpm: Add support for sink PPS related messages
This commit adds sink side support for Get_Status, Status, Get_PPS_Status and PPS_Status handling. As there's the potential for a partner to respond with Not_Supported, handling of this message is also added. Sending of Not_Supported is added to handle messagescreceived but not yet handled. Signed-off-by: Adam Thomson Acked-by: Heikki Krogerus --- drivers/usb/typec/tcpm.c | 143 --- 1 file changed, 134 insertions(+), 9 deletions(-) diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index c859cba..fffe97d 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -19,7 +19,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -113,6 +115,11 @@ S(SNK_TRYWAIT_VBUS),\ S(BIST_RX), \ \ + S(GET_STATUS_SEND), \ + S(GET_STATUS_SEND_TIMEOUT), \ + S(GET_PPS_STATUS_SEND), \ + S(GET_PPS_STATUS_SEND_TIMEOUT), \ + \ S(ERROR_RECOVERY), \ S(PORT_RESET), \ S(PORT_RESET_WAIT_OFF) @@ -143,6 +150,7 @@ enum pd_msg_request { PD_MSG_NONE = 0, PD_MSG_CTRL_REJECT, PD_MSG_CTRL_WAIT, + PD_MSG_CTRL_NOT_SUPP, PD_MSG_DATA_SINK_CAP, PD_MSG_DATA_SOURCE_CAP, }; @@ -1398,10 +1406,42 @@ static int tcpm_validate_caps(struct tcpm_port *port, const u32 *pdo, /* * PD (data, control) command handling functions */ +static inline enum tcpm_state ready_state(struct tcpm_port *port) +{ + if (port->pwr_role == TYPEC_SOURCE) + return SRC_READY; + else + return SNK_READY; +} static int tcpm_pd_send_control(struct tcpm_port *port, enum pd_ctrl_msg_type type); +static void tcpm_handle_alert(struct tcpm_port *port, const __le32 *payload, + int cnt) +{ + u32 p0 = le32_to_cpu(payload[0]); + unsigned int type = usb_pd_ado_type(p0); + + if (!type) { + tcpm_log(port, "Alert message received with no type"); + return; + } + + /* Just handling non-battery alerts for now */ + if (!(type & USB_PD_ADO_TYPE_BATT_STATUS_CHANGE)) { + switch (port->state) { + case SRC_READY: + case SNK_READY: + tcpm_set_state(port, GET_STATUS_SEND, 0); + break; + default: + tcpm_queue_message(port, PD_MSG_CTRL_WAIT); + break; + } + } +} + static void tcpm_pd_data_request(struct tcpm_port *port, const struct pd_message *msg) { @@ -1487,6 +1527,14 @@ static void tcpm_pd_data_request(struct tcpm_port *port, tcpm_set_state(port, BIST_RX, 0); } break; + case PD_DATA_ALERT: + tcpm_handle_alert(port, msg->payload, cnt); + break; + case PD_DATA_BATT_STATUS: + case PD_DATA_GET_COUNTRY_INFO: + /* Currently unsupported */ + tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP); + break; default: tcpm_log(port, "Unhandled data message type %#x", type); break; @@ -1569,6 +1617,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, break; case PD_CTRL_REJECT: case PD_CTRL_WAIT: + case PD_CTRL_NOT_SUPP: switch (port->state) { case SNK_NEGOTIATE_CAPABILITIES: /* USB PD specification, Figure 8-43 */ @@ -1688,12 +1737,75 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, break; } break; + case PD_CTRL_GET_SOURCE_CAP_EXT: + case PD_CTRL_GET_STATUS: + case PD_CTRL_FR_SWAP: + case PD_CTRL_GET_PPS_STATUS: + case PD_CTRL_GET_COUNTRY_CODES: + /* Currently not supported */ + tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP); + break; default: tcpm_log(port, "Unhandled ctrl message type %#x", type); break; } } +static void tcpm_pd_ext_msg_request(struct tcpm_port *port, + const struct pd_message *msg) +{ + enum pd_ext_msg_type type = pd_header_type_le(msg->header); + unsigned int data_size = pd_ext_header_data_size_le(msg->ext_msg.header); + + if (!(msg->ext_msg.header && PD_EXT_HDR_CHUNKED)) { + tcpm_log(port, "Unchunked extended messages unsupported"); +
[PATCH v6 4/6] power: supply: Add 'usb_type' property and supporting code
This commit adds the 'usb_type' property to represent USB supplies which can report a number of different types based on a connection event. Examples of this already exist in drivers whereby the existing 'type' property is updated, based on an event, to represent what was connected (e.g. USB, USB_DCP, USB_ACA, ...). Current implementations however don't show all supported connectable types, so this knowledge has to be exlicitly known for each driver that supports this. The 'usb_type' property is intended to fill this void and show users all possible USB types supported by a driver. The property, when read, shows all available types for the driver, and the one currently chosen is highlighted/bracketed. It is expected that the 'type' property would then just show the top-level type 'USB', and this would be static. Currently the 'usb_type' enum contains all of the USB variant types that exist for the 'type' enum at this time, and in addition has SDP and PPS types. The mirroring is intentional so as to not impact existing usage of the 'type' property. Signed-off-by: Adam Thomson --- Documentation/ABI/testing/sysfs-class-power | 12 drivers/power/supply/power_supply_core.c| 8 - drivers/power/supply/power_supply_sysfs.c | 45 + include/linux/power_supply.h| 16 ++ 4 files changed, 80 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-class-power b/Documentation/ABI/testing/sysfs-class-power index e046566..5e23e22 100644 --- a/Documentation/ABI/testing/sysfs-class-power +++ b/Documentation/ABI/testing/sysfs-class-power @@ -409,6 +409,18 @@ Description: Access: Read Valid values: Represented in 1/10 Degrees Celsius +What: /sys/class/power_supply//usb_type +Date: March 2018 +Contact: linux...@vger.kernel.org +Description: + Reports what type of USB connection is currently active for + the supply, for example it can show if USB-PD capable source + is attached. + + Access: Read-Only + Valid values: "Unknown", "SDP", "DCP", "CDP", "ACA", "C", "PD", + "PD_DRP", "PD_PPS", "BrickID" + What: /sys/class/power_supply//voltage_max Date: January 2008 Contact: linux...@vger.kernel.org diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index 64f6449..dff2bbb 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -843,7 +843,7 @@ static void psy_unregister_cooler(struct power_supply *psy) { struct device *dev; struct power_supply *psy; - int rc; + int i, rc; if (!parent) pr_warn("%s: Expected proper parent device for '%s'\n", @@ -852,6 +852,12 @@ static void psy_unregister_cooler(struct power_supply *psy) if (!desc || !desc->name || !desc->properties || !desc->num_properties) return ERR_PTR(-EINVAL); + for (i = 0; i < desc->num_properties; ++i) { + if ((desc->properties[i] == POWER_SUPPLY_PROP_USB_TYPE) && + (!desc->usb_types || !desc->num_usb_types)) + return ERR_PTR(-EINVAL); + } + psy = kzalloc(sizeof(*psy), GFP_KERNEL); if (!psy) return ERR_PTR(-ENOMEM); diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c index 5204f11..1350068 100644 --- a/drivers/power/supply/power_supply_sysfs.c +++ b/drivers/power/supply/power_supply_sysfs.c @@ -46,6 +46,11 @@ "USB_PD", "USB_PD_DRP", "BrickID" }; +static const char * const power_supply_usb_type_text[] = { + "Unknown", "SDP", "DCP", "CDP", "ACA", "C", + "PD", "PD_DRP", "PD_PPS", "BrickID" +}; + static const char * const power_supply_status_text[] = { "Unknown", "Charging", "Discharging", "Not charging", "Full" }; @@ -73,6 +78,41 @@ "Unknown", "System", "Device" }; +static ssize_t power_supply_show_usb_type(struct device *dev, + enum power_supply_usb_type *usb_types, + ssize_t num_usb_types, + union power_supply_propval *value, + char *buf) +{ + enum power_supply_usb_type usb_type; + ssize_t count = 0;
[PATCH v6 0/6] typec: tcpm: Add sink side support for PPS
This patch set adds sink side support for the PPS feature introduced in the USB PD 3.0 specification. The source PPS supply is represented using the Power Supply framework to provide access and control APIs for dealing with it's operating voltage and current, and switching between a standard PDO and PPS APDO operation. During standard PDO operation the voltage and current is read-only, but for APDO PPS these are writable as well to allow for control. It should be noted that the keepalive for PPS is not handled within TCPM. The expectation is that the external user will be required to ensure re-requests occur regularly to ensure PPS remains and the source does not hard reset. Changes in v6: - Remove unnecessary use of 'data' variable and associated kzalloc/kfree call for extended message handling. - Add patch for error checking psy_desc struct in psy register code. - Add error checking of usb_type property in psy register code. - Cosmetic () and initialisation changes as requested by Guenter. - Removed Acked-by and Reviewed-by on patch 04 as there have been changes to error handling with regards to usb_type, so didn't feel appropriate to keep them. Changes in v5: - Rebase on branch with 'Revert "typec: tcpm: Only request matching pdos"' and header changes already included. - Update power_supply registration to make power_supply names unique per port, to avoid errors creating duplicate psy instances. New name uses port dev name as a suffix. - Renamed 'connected_type' psy property to 'usb_type', as requested by maintainer. - Added initial attempt at generic ABI documentation for common psy class properties for Battery and USB type supplies. - Small update to PPS APDO selection code to limit maximum current requested based on sink maximum allowed current. Have left Heikki's 'Acked-by' tag as it's a minor change, but can remove if that's not deemed appropriate. Changes in v4: - For PD 3.0 definitions patch, make it benign with regards to existing TCPM code so build isn't broken if this one patch is applied, as suggested by kbuild robot. Update for dynamic revision is moved to be part of sink side PPS support patch. - Use PTR_ERR_OR_ZERO macro to simplify return of devm_tcpm_psy_register() function, as suggested by kbuild robot. - Make devm_tcpm_psy_register() static as not used outside this file. Changes in v3: - Drop 'RFC' from patch series titles - Rename PPS related defines to be PPS specific rather than generic APDO titles - Update source caps logging to only print PPS APDOs, and for others report as undefined. - Add ABI documentation for tcpm-source-psy sysfs properties - Rebase PDO selection on top of 'typec: tcpm: Only request matching pdos' patch. - Update capabilities validation introduced in 'typec: tcpm: Validate source and sink caps' to support PPS APDOs. - Dropped power_supply 'type' property update for PPS addition - Added 'connected_type' property to power_supply framework, to support supplies which can report multiple connected types (e.g. USB), as discussed with Heikki. Changes in v2: - Use USB_PD and usb_pd prefixes for macros and inline functions in headers. - Negotiate spec revision of PD headers during initial contract agreement. - New headers now use SPDX tags for referencing correct license. NOTE: Code changes based on usb-next (027bd6cafd9a1e3a109b5e5682c85ac84e804a8d) Adam Thomson (6): typec: tcpm: Add core support for sink side PPS Documentation: power: Initial effort to document power_supply ABI power: supply: Add error checking of psy desc during registration power: supply: Add 'usb_type' property and supporting code typec: tcpm: Represent source supply through power_supply typec: tcpm: Add support for sink PPS related messages Documentation/ABI/testing/sysfs-class-power | 455 ++ MAINTAINERS | 1 + drivers/power/supply/power_supply_core.c| 11 +- drivers/power/supply/power_supply_sysfs.c | 45 ++ drivers/usb/typec/Kconfig | 1 + drivers/usb/typec/fusb302/Kconfig | 2 +- drivers/usb/typec/fusb302/fusb302.c | 63 +- drivers/usb/typec/tcpm.c| 907 +++- include/linux/power_supply.h| 16 + include/linux/usb/pd.h | 4 +- include/linux/usb/tcpm.h| 2 +- 11 files changed, 1418 insertions(+), 89 deletions(-) -- 1.9.1
[PATCH v6 5/6] typec: tcpm: Represent source supply through power_supply
This commit adds a power_supply class instance to represent a PD source's voltage and current properties. This provides an interface for reading these properties from user-space or other drivers. For PPS enabled Sources, this also provides write access to set the current and voltage and allows for swapping between standard PDO and PPS APDO. As this represents a superset of the information provided in the fusb302 driver, the power_supply instance in that code is removed as part of this change, so reverting the commit titled 'typec: tcpm: Represent source supply through power_supply class' Signed-off-by: Adam Thomson --- drivers/usb/typec/Kconfig | 1 + drivers/usb/typec/fusb302/Kconfig | 2 +- drivers/usb/typec/fusb302/fusb302.c | 63 +- drivers/usb/typec/tcpm.c| 242 +++- 4 files changed, 245 insertions(+), 63 deletions(-) diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig index bcb2744..1ef606d 100644 --- a/drivers/usb/typec/Kconfig +++ b/drivers/usb/typec/Kconfig @@ -48,6 +48,7 @@ if TYPEC config TYPEC_TCPM tristate "USB Type-C Port Controller Manager" depends on USB + select POWER_SUPPLY help The Type-C Port Controller Manager provides a USB PD and USB Type-C state machine for use with Type-C Port Controllers. diff --git a/drivers/usb/typec/fusb302/Kconfig b/drivers/usb/typec/fusb302/Kconfig index 48a4f2f..fce099f 100644 --- a/drivers/usb/typec/fusb302/Kconfig +++ b/drivers/usb/typec/fusb302/Kconfig @@ -1,6 +1,6 @@ config TYPEC_FUSB302 tristate "Fairchild FUSB302 Type-C chip driver" - depends on I2C && POWER_SUPPLY + depends on I2C help The Fairchild FUSB302 Type-C chip driver that works with Type-C Port Controller Manager to provide USB PD and USB diff --git a/drivers/usb/typec/fusb302/fusb302.c b/drivers/usb/typec/fusb302/fusb302.c index 06794c0..6a8f279 100644 --- a/drivers/usb/typec/fusb302/fusb302.c +++ b/drivers/usb/typec/fusb302/fusb302.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -99,11 +98,6 @@ struct fusb302_chip { /* lock for sharing chip states */ struct mutex lock; - /* psy + psy status */ - struct power_supply *psy; - u32 current_limit; - u32 supply_voltage; - /* chip status */ enum toggling_mode toggling_mode; enum src_current_status src_current_status; @@ -861,13 +855,11 @@ static int tcpm_set_vbus(struct tcpc_dev *dev, bool on, bool charge) chip->vbus_on = on; fusb302_log(chip, "vbus := %s", on ? "On" : "Off"); } - if (chip->charge_on == charge) { + if (chip->charge_on == charge) fusb302_log(chip, "charge is already %s", charge ? "On" : "Off"); - } else { + else chip->charge_on = charge; - power_supply_changed(chip->psy); - } done: mutex_unlock(&chip->lock); @@ -883,11 +875,6 @@ static int tcpm_set_current_limit(struct tcpc_dev *dev, u32 max_ma, u32 mv) fusb302_log(chip, "current limit: %d ma, %d mv (not implemented)", max_ma, mv); - chip->supply_voltage = mv; - chip->current_limit = max_ma; - - power_supply_changed(chip->psy); - return 0; } @@ -1686,43 +1673,6 @@ static irqreturn_t fusb302_irq_intn(int irq, void *dev_id) return IRQ_HANDLED; } -static int fusb302_psy_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct fusb302_chip *chip = power_supply_get_drvdata(psy); - - switch (psp) { - case POWER_SUPPLY_PROP_ONLINE: - val->intval = chip->charge_on; - break; - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = chip->supply_voltage * 1000; /* mV -> µV */ - break; - case POWER_SUPPLY_PROP_CURRENT_MAX: - val->intval = chip->current_limit * 1000; /* mA -> µA */ - break; - default: - return -ENODATA; - } - - return 0; -} - -static enum power_supply_property fusb302_psy_properties[] = { - POWER_SUPPLY_PROP_ONLINE, - POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_CURRENT_MAX, -}; - -static const struct power_supply_desc fusb302_psy_desc = { - .name = "fusb302-typec-source", - .type = POWER_SUPPLY_TYPE_USB_TYPE_C, - .properties = fusb302_psy_properties, - .num_properties = ARRAY_SIZE(fusb302_psy_properties), - .get_proper
[PATCH v6 3/6] power: supply: Add error checking of psy desc during registration
Currently there's no error checking of this parameter in the registration function and it's blindly added to psy class and subsequently used as is. For example if this is NULL the call to psy_register_thermal() will try to dereference the pointer thus causing a kernel dump. This commit updates the registration code to add some basic checks on the desc pointer validity, name, and presence of properties. Signed-off-by: Adam Thomson --- drivers/power/supply/power_supply_core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index 82f998a..64f6449 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -849,6 +849,9 @@ static void psy_unregister_cooler(struct power_supply *psy) pr_warn("%s: Expected proper parent device for '%s'\n", __func__, desc->name); + if (!desc || !desc->name || !desc->properties || !desc->num_properties) + return ERR_PTR(-EINVAL); + psy = kzalloc(sizeof(*psy), GFP_KERNEL); if (!psy) return ERR_PTR(-ENOMEM); -- 1.9.1
[PATCH v6 1/6] typec: tcpm: Add core support for sink side PPS
This commit adds code to handle requesting of PPS APDOs. Switching between standard PDOs and APDOs, and re-requesting an APDO to modify operating voltage/current will be triggered by an external call into TCPM. Signed-off-by: Adam Thomson Acked-by: Heikki Krogerus --- drivers/usb/typec/tcpm.c | 524 +-- include/linux/usb/pd.h | 4 +- include/linux/usb/tcpm.h | 2 +- 3 files changed, 513 insertions(+), 17 deletions(-) diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index 4c0fc54..5618b3f 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -47,6 +47,7 @@ S(SNK_DISCOVERY_DEBOUNCE_DONE), \ S(SNK_WAIT_CAPABILITIES), \ S(SNK_NEGOTIATE_CAPABILITIES), \ + S(SNK_NEGOTIATE_PPS_CAPABILITIES), \ S(SNK_TRANSITION_SINK), \ S(SNK_TRANSITION_SINK_VBUS),\ S(SNK_READY), \ @@ -166,6 +167,16 @@ struct pd_mode_data { struct typec_altmode_desc altmode_desc[SVID_DISCOVERY_MAX]; }; +struct pd_pps_data { + u32 min_volt; + u32 max_volt; + u32 max_curr; + u32 out_volt; + u32 op_curr; + bool supported; + bool active; +}; + struct tcpm_port { struct device *dev; @@ -233,6 +244,7 @@ struct tcpm_port { struct completion swap_complete; int swap_status; + unsigned int negotiated_rev; unsigned int message_id; unsigned int caps_count; unsigned int hard_reset_count; @@ -259,6 +271,7 @@ struct tcpm_port { unsigned int max_snk_ma; unsigned int max_snk_mw; unsigned int operating_snk_mw; + bool update_sink_caps; /* Requested current / voltage */ u32 current_limit; @@ -275,8 +288,13 @@ struct tcpm_port { /* VDO to retry if UFP responder replied busy */ u32 vdo_retry; - /* Alternate mode data */ + /* PPS */ + struct pd_pps_data pps_data; + struct completion pps_complete; + bool pps_pending; + int pps_status; + /* Alternate mode data */ struct pd_mode_data mode_data; struct typec_altmode *partner_altmode[SVID_DISCOVERY_MAX]; struct typec_altmode *port_altmode[SVID_DISCOVERY_MAX]; @@ -494,6 +512,16 @@ static void tcpm_log_source_caps(struct tcpm_port *port) pdo_max_voltage(pdo), pdo_max_power(pdo)); break; + case PDO_TYPE_APDO: + if (pdo_apdo_type(pdo) == APDO_TYPE_PPS) + scnprintf(msg, sizeof(msg), + "%u-%u mV, %u mA", + pdo_pps_apdo_min_voltage(pdo), + pdo_pps_apdo_max_voltage(pdo), + pdo_pps_apdo_max_current(pdo)); + else + strcpy(msg, "undefined APDO"); + break; default: strcpy(msg, "undefined"); break; @@ -777,11 +805,13 @@ static int tcpm_pd_send_source_caps(struct tcpm_port *port) msg.header = PD_HEADER_LE(PD_CTRL_REJECT, port->pwr_role, port->data_role, + port->negotiated_rev, port->message_id, 0); } else { msg.header = PD_HEADER_LE(PD_DATA_SOURCE_CAP, port->pwr_role, port->data_role, + port->negotiated_rev, port->message_id, port->nr_src_pdo); } @@ -802,11 +832,13 @@ static int tcpm_pd_send_sink_caps(struct tcpm_port *port) msg.header = PD_HEADER_LE(PD_CTRL_REJECT, port->pwr_role, port->data_role, + port->negotiated_rev, port->message_id, 0); } else { msg.header = PD_HEADER_LE(PD_DATA_SINK_CAP, port->pwr_role, port->data_role, + port->negotiated_rev, port->message_id, port->nr_snk_pdo); } @@ -1173,6 +1205,7 @@ static void vdm_run_state_machine(struct tcpm_port *port) msg.header = PD_HE
[PATCH v6 2/6] Documentation: power: Initial effort to document power_supply ABI
This commit adds generic ABI information regarding power_supply properties. This is an initial attempt to try and align the usage of these properties between drivers. As part of this commit, common Battery and USB related properties have been listed. Signed-off-by: Adam Thomson --- Documentation/ABI/testing/sysfs-class-power | 443 MAINTAINERS | 1 + 2 files changed, 444 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-class-power b/Documentation/ABI/testing/sysfs-class-power index f85ce9e..e046566 100644 --- a/Documentation/ABI/testing/sysfs-class-power +++ b/Documentation/ABI/testing/sysfs-class-power @@ -1,3 +1,446 @@ += General Properties = + +What: /sys/class/power_supply//manufacturer +Date: May 2007 +Contact: linux...@vger.kernel.org +Description: + Reports the name of the device manufacturer. + + Access: Read + Valid values: Represented as string + +What: /sys/class/power_supply//model_name +Date: May 2007 +Contact: linux...@vger.kernel.org +Description: + Reports the name of the device model. + + Access: Read + Valid values: Represented as string + +What: /sys/class/power_supply//serial_number +Date: January 2008 +Contact: linux...@vger.kernel.org +Description: + Reports the serial number of the device. + + Access: Read + Valid values: Represented as string + +What: /sys/class/power_supply//type +Date: May 2010 +Contact: linux...@vger.kernel.org +Description: + Describes the main type of the supply. + + Access: Read + Valid values: "Battery", "UPS", "Mains", "USB" + += Battery Properties = + +What: /sys/class/power_supply//capacity +Date: May 2007 +Contact: linux...@vger.kernel.org +Description: + Fine grain representation of battery capacity. + Access: Read + Valid values: 0 - 100 (percent) + +What: /sys/class/power_supply//capacity_alert_max +Date: July 2012 +Contact: linux...@vger.kernel.org +Description: + Maximum battery capacity trip-wire value where the supply will + notify user-space of the event. This is normally used for the + battery discharging scenario where user-space needs to know the + battery has dropped to an upper level so it can take + appropriate action (e.g. warning user that battery level is + low). + + Access: Read, Write + Valid values: 0 - 100 (percent) + +What: /sys/class/power_supply//capacity_alert_min +Date: July 2012 +Contact: linux...@vger.kernel.org +Description: + Minimum battery capacity trip-wire value where the supply will + notify user-space of the event. This is normally used for the + battery discharging scenario where user-space needs to know the + battery has dropped to a lower level so it can take + appropriate action (e.g. warning user that battery level is + critically low). + + Access: Read, Write + Valid values: 0 - 100 (percent) + +What: /sys/class/power_supply//capacity_level +Date: June 2009 +Contact: linux...@vger.kernel.org +Description: + Coarse representation of battery capacity. + + Access: Read + Valid values: "Unknown", "Critical", "Low", "Normal", "High", + "Full" + +What: /sys/class/power_supply//current_avg +Date: May 2007 +Contact: linux...@vger.kernel.org +Description: + Reports an average IBAT current reading for the battery, over a + fixed period. Normally devices will provide a fixed interval in + which they average readings to smooth out the reported value. + + Access: Read + Valid values: Represented in microamps + +What: /sys/class/power_supply//current_max +Date: October 2010 +Contact: linux...@vger.kernel.org +Description: + Reports the maximum IBAT current allowed into the battery. + + Access: Read + Valid values: Represented in microamps + +What: /sys/class/power_supply//current_now +Date: May 2007 +Contact: linux...@vger.kernel.org +Description: + Reports an instant, single IBAT current reading for the battery. + This value is not averaged/smoothed. + + Access: Read + Valid values: Represented in microamps +
[PATCH v7 3/6] power: supply: Add error checking of psy desc during registration
Currently there's no error checking of this parameter in the registration function and it's blindly added to psy class and subsequently used as is. For example if this is NULL the call to psy_register_thermal() will try to dereference the pointer thus causing a kernel dump. This commit updates the registration code to add some basic checks on the desc pointer validity, name, and presence of properties. Signed-off-by: Adam Thomson --- drivers/power/supply/power_supply_core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index 82f998a..64f6449 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -849,6 +849,9 @@ static void psy_unregister_cooler(struct power_supply *psy) pr_warn("%s: Expected proper parent device for '%s'\n", __func__, desc->name); + if (!desc || !desc->name || !desc->properties || !desc->num_properties) + return ERR_PTR(-EINVAL); + psy = kzalloc(sizeof(*psy), GFP_KERNEL); if (!psy) return ERR_PTR(-ENOMEM); -- 1.9.1
[PATCH v7 4/6] power: supply: Add 'usb_type' property and supporting code
This commit adds the 'usb_type' property to represent USB supplies which can report a number of different types based on a connection event. Examples of this already exist in drivers whereby the existing 'type' property is updated, based on an event, to represent what was connected (e.g. USB, USB_DCP, USB_ACA, ...). Current implementations however don't show all supported connectable types, so this knowledge has to be exlicitly known for each driver that supports this. The 'usb_type' property is intended to fill this void and show users all possible USB types supported by a driver. The property, when read, shows all available types for the driver, and the one currently chosen is highlighted/bracketed. It is expected that the 'type' property would then just show the top-level type 'USB', and this would be static. Currently the 'usb_type' enum contains all of the USB variant types that exist for the 'type' enum at this time, and in addition has SDP and PPS types. The mirroring is intentional so as to not impact existing usage of the 'type' property. Signed-off-by: Adam Thomson --- Documentation/ABI/testing/sysfs-class-power | 12 drivers/power/supply/power_supply_core.c| 8 - drivers/power/supply/power_supply_sysfs.c | 45 + include/linux/power_supply.h| 16 ++ 4 files changed, 80 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/sysfs-class-power b/Documentation/ABI/testing/sysfs-class-power index e046566..5e23e22 100644 --- a/Documentation/ABI/testing/sysfs-class-power +++ b/Documentation/ABI/testing/sysfs-class-power @@ -409,6 +409,18 @@ Description: Access: Read Valid values: Represented in 1/10 Degrees Celsius +What: /sys/class/power_supply//usb_type +Date: March 2018 +Contact: linux...@vger.kernel.org +Description: + Reports what type of USB connection is currently active for + the supply, for example it can show if USB-PD capable source + is attached. + + Access: Read-Only + Valid values: "Unknown", "SDP", "DCP", "CDP", "ACA", "C", "PD", + "PD_DRP", "PD_PPS", "BrickID" + What: /sys/class/power_supply//voltage_max Date: January 2008 Contact: linux...@vger.kernel.org diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index 64f6449..dff2bbb 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -843,7 +843,7 @@ static void psy_unregister_cooler(struct power_supply *psy) { struct device *dev; struct power_supply *psy; - int rc; + int i, rc; if (!parent) pr_warn("%s: Expected proper parent device for '%s'\n", @@ -852,6 +852,12 @@ static void psy_unregister_cooler(struct power_supply *psy) if (!desc || !desc->name || !desc->properties || !desc->num_properties) return ERR_PTR(-EINVAL); + for (i = 0; i < desc->num_properties; ++i) { + if ((desc->properties[i] == POWER_SUPPLY_PROP_USB_TYPE) && + (!desc->usb_types || !desc->num_usb_types)) + return ERR_PTR(-EINVAL); + } + psy = kzalloc(sizeof(*psy), GFP_KERNEL); if (!psy) return ERR_PTR(-ENOMEM); diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c index 5204f11..1350068 100644 --- a/drivers/power/supply/power_supply_sysfs.c +++ b/drivers/power/supply/power_supply_sysfs.c @@ -46,6 +46,11 @@ "USB_PD", "USB_PD_DRP", "BrickID" }; +static const char * const power_supply_usb_type_text[] = { + "Unknown", "SDP", "DCP", "CDP", "ACA", "C", + "PD", "PD_DRP", "PD_PPS", "BrickID" +}; + static const char * const power_supply_status_text[] = { "Unknown", "Charging", "Discharging", "Not charging", "Full" }; @@ -73,6 +78,41 @@ "Unknown", "System", "Device" }; +static ssize_t power_supply_show_usb_type(struct device *dev, + enum power_supply_usb_type *usb_types, + ssize_t num_usb_types, + union power_supply_propval *value, + char *buf) +{ + enum power_supply_usb_type usb_type; + ssize_t count = 0;
[PATCH v7 1/6] typec: tcpm: Add core support for sink side PPS
This commit adds code to handle requesting of PPS APDOs. Switching between standard PDOs and APDOs, and re-requesting an APDO to modify operating voltage/current will be triggered by an external call into TCPM. Signed-off-by: Adam Thomson Acked-by: Heikki Krogerus --- drivers/usb/typec/tcpm.c | 517 ++- include/linux/usb/pd.h | 4 +- include/linux/usb/tcpm.h | 1 + 3 files changed, 509 insertions(+), 13 deletions(-) diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index 4c0fc54..1a66c9e 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -47,6 +47,7 @@ S(SNK_DISCOVERY_DEBOUNCE_DONE), \ S(SNK_WAIT_CAPABILITIES), \ S(SNK_NEGOTIATE_CAPABILITIES), \ + S(SNK_NEGOTIATE_PPS_CAPABILITIES), \ S(SNK_TRANSITION_SINK), \ S(SNK_TRANSITION_SINK_VBUS),\ S(SNK_READY), \ @@ -166,6 +167,16 @@ struct pd_mode_data { struct typec_altmode_desc altmode_desc[SVID_DISCOVERY_MAX]; }; +struct pd_pps_data { + u32 min_volt; + u32 max_volt; + u32 max_curr; + u32 out_volt; + u32 op_curr; + bool supported; + bool active; +}; + struct tcpm_port { struct device *dev; @@ -233,6 +244,7 @@ struct tcpm_port { struct completion swap_complete; int swap_status; + unsigned int negotiated_rev; unsigned int message_id; unsigned int caps_count; unsigned int hard_reset_count; @@ -259,6 +271,7 @@ struct tcpm_port { unsigned int max_snk_ma; unsigned int max_snk_mw; unsigned int operating_snk_mw; + bool update_sink_caps; /* Requested current / voltage */ u32 current_limit; @@ -275,8 +288,13 @@ struct tcpm_port { /* VDO to retry if UFP responder replied busy */ u32 vdo_retry; - /* Alternate mode data */ + /* PPS */ + struct pd_pps_data pps_data; + struct completion pps_complete; + bool pps_pending; + int pps_status; + /* Alternate mode data */ struct pd_mode_data mode_data; struct typec_altmode *partner_altmode[SVID_DISCOVERY_MAX]; struct typec_altmode *port_altmode[SVID_DISCOVERY_MAX]; @@ -494,6 +512,16 @@ static void tcpm_log_source_caps(struct tcpm_port *port) pdo_max_voltage(pdo), pdo_max_power(pdo)); break; + case PDO_TYPE_APDO: + if (pdo_apdo_type(pdo) == APDO_TYPE_PPS) + scnprintf(msg, sizeof(msg), + "%u-%u mV, %u mA", + pdo_pps_apdo_min_voltage(pdo), + pdo_pps_apdo_max_voltage(pdo), + pdo_pps_apdo_max_current(pdo)); + else + strcpy(msg, "undefined APDO"); + break; default: strcpy(msg, "undefined"); break; @@ -777,11 +805,13 @@ static int tcpm_pd_send_source_caps(struct tcpm_port *port) msg.header = PD_HEADER_LE(PD_CTRL_REJECT, port->pwr_role, port->data_role, + port->negotiated_rev, port->message_id, 0); } else { msg.header = PD_HEADER_LE(PD_DATA_SOURCE_CAP, port->pwr_role, port->data_role, + port->negotiated_rev, port->message_id, port->nr_src_pdo); } @@ -802,11 +832,13 @@ static int tcpm_pd_send_sink_caps(struct tcpm_port *port) msg.header = PD_HEADER_LE(PD_CTRL_REJECT, port->pwr_role, port->data_role, + port->negotiated_rev, port->message_id, 0); } else { msg.header = PD_HEADER_LE(PD_DATA_SINK_CAP, port->pwr_role, port->data_role, + port->negotiated_rev, port->message_id, port->nr_snk_pdo); } @@ -1173,6 +1205,7 @@ static void vdm_run_state_machine(struct tcpm_port *port) msg.header = PD_HE
[PATCH v7 5/6] typec: tcpm: Represent source supply through power_supply
This commit adds a power_supply class instance to represent a PD source's voltage and current properties. This provides an interface for reading these properties from user-space or other drivers. For PPS enabled Sources, this also provides write access to set the current and voltage and allows for swapping between standard PDO and PPS APDO. As this represents a superset of the information provided in the fusb302 driver, the power_supply instance in that code is removed as part of this change, so reverting the commit titled 'typec: tcpm: Represent source supply through power_supply class' Signed-off-by: Adam Thomson --- drivers/usb/typec/Kconfig | 1 + drivers/usb/typec/fusb302/Kconfig | 2 +- drivers/usb/typec/fusb302/fusb302.c | 63 +- drivers/usb/typec/tcpm.c| 245 +++- 4 files changed, 248 insertions(+), 63 deletions(-) diff --git a/drivers/usb/typec/Kconfig b/drivers/usb/typec/Kconfig index bcb2744..1ef606d 100644 --- a/drivers/usb/typec/Kconfig +++ b/drivers/usb/typec/Kconfig @@ -48,6 +48,7 @@ if TYPEC config TYPEC_TCPM tristate "USB Type-C Port Controller Manager" depends on USB + select POWER_SUPPLY help The Type-C Port Controller Manager provides a USB PD and USB Type-C state machine for use with Type-C Port Controllers. diff --git a/drivers/usb/typec/fusb302/Kconfig b/drivers/usb/typec/fusb302/Kconfig index 48a4f2f..fce099f 100644 --- a/drivers/usb/typec/fusb302/Kconfig +++ b/drivers/usb/typec/fusb302/Kconfig @@ -1,6 +1,6 @@ config TYPEC_FUSB302 tristate "Fairchild FUSB302 Type-C chip driver" - depends on I2C && POWER_SUPPLY + depends on I2C help The Fairchild FUSB302 Type-C chip driver that works with Type-C Port Controller Manager to provide USB PD and USB diff --git a/drivers/usb/typec/fusb302/fusb302.c b/drivers/usb/typec/fusb302/fusb302.c index 06794c0..6a8f279 100644 --- a/drivers/usb/typec/fusb302/fusb302.c +++ b/drivers/usb/typec/fusb302/fusb302.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -99,11 +98,6 @@ struct fusb302_chip { /* lock for sharing chip states */ struct mutex lock; - /* psy + psy status */ - struct power_supply *psy; - u32 current_limit; - u32 supply_voltage; - /* chip status */ enum toggling_mode toggling_mode; enum src_current_status src_current_status; @@ -861,13 +855,11 @@ static int tcpm_set_vbus(struct tcpc_dev *dev, bool on, bool charge) chip->vbus_on = on; fusb302_log(chip, "vbus := %s", on ? "On" : "Off"); } - if (chip->charge_on == charge) { + if (chip->charge_on == charge) fusb302_log(chip, "charge is already %s", charge ? "On" : "Off"); - } else { + else chip->charge_on = charge; - power_supply_changed(chip->psy); - } done: mutex_unlock(&chip->lock); @@ -883,11 +875,6 @@ static int tcpm_set_current_limit(struct tcpc_dev *dev, u32 max_ma, u32 mv) fusb302_log(chip, "current limit: %d ma, %d mv (not implemented)", max_ma, mv); - chip->supply_voltage = mv; - chip->current_limit = max_ma; - - power_supply_changed(chip->psy); - return 0; } @@ -1686,43 +1673,6 @@ static irqreturn_t fusb302_irq_intn(int irq, void *dev_id) return IRQ_HANDLED; } -static int fusb302_psy_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct fusb302_chip *chip = power_supply_get_drvdata(psy); - - switch (psp) { - case POWER_SUPPLY_PROP_ONLINE: - val->intval = chip->charge_on; - break; - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = chip->supply_voltage * 1000; /* mV -> µV */ - break; - case POWER_SUPPLY_PROP_CURRENT_MAX: - val->intval = chip->current_limit * 1000; /* mA -> µA */ - break; - default: - return -ENODATA; - } - - return 0; -} - -static enum power_supply_property fusb302_psy_properties[] = { - POWER_SUPPLY_PROP_ONLINE, - POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_CURRENT_MAX, -}; - -static const struct power_supply_desc fusb302_psy_desc = { - .name = "fusb302-typec-source", - .type = POWER_SUPPLY_TYPE_USB_TYPE_C, - .properties = fusb302_psy_properties, - .num_properties = ARRAY_SIZE(fusb302_psy_properties), - .get_proper
[PATCH v7 6/6] typec: tcpm: Add support for sink PPS related messages
This commit adds sink side support for Get_Status, Status, Get_PPS_Status and PPS_Status handling. As there's the potential for a partner to respond with Not_Supported, handling of this message is also added. Sending of Not_Supported is added to handle messagescreceived but not yet handled. Signed-off-by: Adam Thomson Acked-by: Heikki Krogerus --- drivers/usb/typec/tcpm.c | 143 --- 1 file changed, 134 insertions(+), 9 deletions(-) diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index 57a7d1a..7025a16 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -19,7 +19,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -113,6 +115,11 @@ S(SNK_TRYWAIT_VBUS),\ S(BIST_RX), \ \ + S(GET_STATUS_SEND), \ + S(GET_STATUS_SEND_TIMEOUT), \ + S(GET_PPS_STATUS_SEND), \ + S(GET_PPS_STATUS_SEND_TIMEOUT), \ + \ S(ERROR_RECOVERY), \ S(PORT_RESET), \ S(PORT_RESET_WAIT_OFF) @@ -143,6 +150,7 @@ enum pd_msg_request { PD_MSG_NONE = 0, PD_MSG_CTRL_REJECT, PD_MSG_CTRL_WAIT, + PD_MSG_CTRL_NOT_SUPP, PD_MSG_DATA_SINK_CAP, PD_MSG_DATA_SOURCE_CAP, }; @@ -1398,10 +1406,42 @@ static int tcpm_validate_caps(struct tcpm_port *port, const u32 *pdo, /* * PD (data, control) command handling functions */ +static inline enum tcpm_state ready_state(struct tcpm_port *port) +{ + if (port->pwr_role == TYPEC_SOURCE) + return SRC_READY; + else + return SNK_READY; +} static int tcpm_pd_send_control(struct tcpm_port *port, enum pd_ctrl_msg_type type); +static void tcpm_handle_alert(struct tcpm_port *port, const __le32 *payload, + int cnt) +{ + u32 p0 = le32_to_cpu(payload[0]); + unsigned int type = usb_pd_ado_type(p0); + + if (!type) { + tcpm_log(port, "Alert message received with no type"); + return; + } + + /* Just handling non-battery alerts for now */ + if (!(type & USB_PD_ADO_TYPE_BATT_STATUS_CHANGE)) { + switch (port->state) { + case SRC_READY: + case SNK_READY: + tcpm_set_state(port, GET_STATUS_SEND, 0); + break; + default: + tcpm_queue_message(port, PD_MSG_CTRL_WAIT); + break; + } + } +} + static void tcpm_pd_data_request(struct tcpm_port *port, const struct pd_message *msg) { @@ -1489,6 +1529,14 @@ static void tcpm_pd_data_request(struct tcpm_port *port, tcpm_set_state(port, BIST_RX, 0); } break; + case PD_DATA_ALERT: + tcpm_handle_alert(port, msg->payload, cnt); + break; + case PD_DATA_BATT_STATUS: + case PD_DATA_GET_COUNTRY_INFO: + /* Currently unsupported */ + tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP); + break; default: tcpm_log(port, "Unhandled data message type %#x", type); break; @@ -1571,6 +1619,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, break; case PD_CTRL_REJECT: case PD_CTRL_WAIT: + case PD_CTRL_NOT_SUPP: switch (port->state) { case SNK_NEGOTIATE_CAPABILITIES: /* USB PD specification, Figure 8-43 */ @@ -1690,12 +1739,75 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port, break; } break; + case PD_CTRL_GET_SOURCE_CAP_EXT: + case PD_CTRL_GET_STATUS: + case PD_CTRL_FR_SWAP: + case PD_CTRL_GET_PPS_STATUS: + case PD_CTRL_GET_COUNTRY_CODES: + /* Currently not supported */ + tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP); + break; default: tcpm_log(port, "Unhandled ctrl message type %#x", type); break; } } +static void tcpm_pd_ext_msg_request(struct tcpm_port *port, + const struct pd_message *msg) +{ + enum pd_ext_msg_type type = pd_header_type_le(msg->header); + unsigned int data_size = pd_ext_header_data_size_le(msg->ext_msg.header); + + if (!(msg->ext_msg.header && PD_EXT_HDR_CHUNKED)) { + tcpm_log(port, "Unchunked extended messages unsupported"); +
[PATCH v7 2/6] Documentation: power: Initial effort to document power_supply ABI
This commit adds generic ABI information regarding power_supply properties. This is an initial attempt to try and align the usage of these properties between drivers. As part of this commit, common Battery and USB related properties have been listed. Signed-off-by: Adam Thomson --- Documentation/ABI/testing/sysfs-class-power | 443 MAINTAINERS | 1 + 2 files changed, 444 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-class-power b/Documentation/ABI/testing/sysfs-class-power index f85ce9e..e046566 100644 --- a/Documentation/ABI/testing/sysfs-class-power +++ b/Documentation/ABI/testing/sysfs-class-power @@ -1,3 +1,446 @@ += General Properties = + +What: /sys/class/power_supply//manufacturer +Date: May 2007 +Contact: linux...@vger.kernel.org +Description: + Reports the name of the device manufacturer. + + Access: Read + Valid values: Represented as string + +What: /sys/class/power_supply//model_name +Date: May 2007 +Contact: linux...@vger.kernel.org +Description: + Reports the name of the device model. + + Access: Read + Valid values: Represented as string + +What: /sys/class/power_supply//serial_number +Date: January 2008 +Contact: linux...@vger.kernel.org +Description: + Reports the serial number of the device. + + Access: Read + Valid values: Represented as string + +What: /sys/class/power_supply//type +Date: May 2010 +Contact: linux...@vger.kernel.org +Description: + Describes the main type of the supply. + + Access: Read + Valid values: "Battery", "UPS", "Mains", "USB" + += Battery Properties = + +What: /sys/class/power_supply//capacity +Date: May 2007 +Contact: linux...@vger.kernel.org +Description: + Fine grain representation of battery capacity. + Access: Read + Valid values: 0 - 100 (percent) + +What: /sys/class/power_supply//capacity_alert_max +Date: July 2012 +Contact: linux...@vger.kernel.org +Description: + Maximum battery capacity trip-wire value where the supply will + notify user-space of the event. This is normally used for the + battery discharging scenario where user-space needs to know the + battery has dropped to an upper level so it can take + appropriate action (e.g. warning user that battery level is + low). + + Access: Read, Write + Valid values: 0 - 100 (percent) + +What: /sys/class/power_supply//capacity_alert_min +Date: July 2012 +Contact: linux...@vger.kernel.org +Description: + Minimum battery capacity trip-wire value where the supply will + notify user-space of the event. This is normally used for the + battery discharging scenario where user-space needs to know the + battery has dropped to a lower level so it can take + appropriate action (e.g. warning user that battery level is + critically low). + + Access: Read, Write + Valid values: 0 - 100 (percent) + +What: /sys/class/power_supply//capacity_level +Date: June 2009 +Contact: linux...@vger.kernel.org +Description: + Coarse representation of battery capacity. + + Access: Read + Valid values: "Unknown", "Critical", "Low", "Normal", "High", + "Full" + +What: /sys/class/power_supply//current_avg +Date: May 2007 +Contact: linux...@vger.kernel.org +Description: + Reports an average IBAT current reading for the battery, over a + fixed period. Normally devices will provide a fixed interval in + which they average readings to smooth out the reported value. + + Access: Read + Valid values: Represented in microamps + +What: /sys/class/power_supply//current_max +Date: October 2010 +Contact: linux...@vger.kernel.org +Description: + Reports the maximum IBAT current allowed into the battery. + + Access: Read + Valid values: Represented in microamps + +What: /sys/class/power_supply//current_now +Date: May 2007 +Contact: linux...@vger.kernel.org +Description: + Reports an instant, single IBAT current reading for the battery. + This value is not averaged/smoothed. + + Access: Read + Valid values: Represented in microamps +
[PATCH v7 0/6] typec: tcpm: Add sink side support for PPS
This patch set adds sink side support for the PPS feature introduced in the USB PD 3.0 specification. The source PPS supply is represented using the Power Supply framework to provide access and control APIs for dealing with it's operating voltage and current, and switching between a standard PDO and PPS APDO operation. During standard PDO operation the voltage and current is read-only, but for APDO PPS these are writable as well to allow for control. It should be noted that the keepalive for PPS is not handled within TCPM. The expectation is that the external user will be required to ensure re-requests occur regularly to ensure PPS remains and the source does not hard reset. Changes in v7: - Further tidy up with bracket usage and unwanted initialisation. - Stop using else if statement after break. - Added NULL checking of psy_name after devm_kzalloc(). - Reinstate PD_ROLE_SWAP_TIMEOUT and revert role swap functions to use this. - Add PD_PPS_CTRL_TIMEOUT for PPS related control functions. Changes in v6: - Remove unnecessary use of 'data' variable and associated kzalloc/kfree call for extended message handling. - Add patch for error checking psy_desc struct in psy register code. - Add error checking of usb_type property in psy register code. - Cosmetic () and initialisation changes as requested by Guenter. - Removed Acked-by and Reviewed-by, from Heikki and Sebastian respectively, on patch 04 as there have been changes to error handling with regards to usb_type, so didn't feel appropriate to keep them. Changes in v5: - Rebase on branch with 'Revert "typec: tcpm: Only request matching pdos"' and header changes already included. - Update power_supply registration to make power_supply names unique per port, to avoid errors creating duplicate psy instances. New name uses port dev name as a suffix. - Renamed 'connected_type' psy property to 'usb_type', as requested by maintainer. - Added initial attempt at generic ABI documentation for common psy class properties for Battery and USB type supplies. - Small update to PPS APDO selection code to limit maximum current requested based on sink maximum allowed current. Have left Heikki's 'Acked-by' tag as it's a minor change, but can remove if that's not deemed appropriate. Changes in v4: - For PD 3.0 definitions patch, make it benign with regards to existing TCPM code so build isn't broken if this one patch is applied, as suggested by kbuild robot. Update for dynamic revision is moved to be part of sink side PPS support patch. - Use PTR_ERR_OR_ZERO macro to simplify return of devm_tcpm_psy_register() function, as suggested by kbuild robot. - Make devm_tcpm_psy_register() static as not used outside this file. Changes in v3: - Drop 'RFC' from patch series titles - Rename PPS related defines to be PPS specific rather than generic APDO titles - Update source caps logging to only print PPS APDOs, and for others report as undefined. - Add ABI documentation for tcpm-source-psy sysfs properties - Rebase PDO selection on top of 'typec: tcpm: Only request matching pdos' patch. - Update capabilities validation introduced in 'typec: tcpm: Validate source and sink caps' to support PPS APDOs. - Dropped power_supply 'type' property update for PPS addition - Added 'connected_type' property to power_supply framework, to support supplies which can report multiple connected types (e.g. USB), as discussed with Heikki. Changes in v2: - Use USB_PD and usb_pd prefixes for macros and inline functions in headers. - Negotiate spec revision of PD headers during initial contract agreement. - New headers now use SPDX tags for referencing correct license. NOTE: Code changes based on usb-next (027bd6cafd9a1e3a109b5e5682c85ac84e804a8d) Adam Thomson (6): typec: tcpm: Add core support for sink side PPS Documentation: power: Initial effort to document power_supply ABI power: supply: Add error checking of psy desc during registration power: supply: Add 'usb_type' property and supporting code typec: tcpm: Represent source supply through power_supply typec: tcpm: Add support for sink PPS related messages Documentation/ABI/testing/sysfs-class-power | 455 ++ MAINTAINERS | 1 + drivers/power/supply/power_supply_core.c| 11 +- drivers/power/supply/power_supply_sysfs.c | 45 ++ drivers/usb/typec/Kconfig | 1 + drivers/usb/typec/fusb302/Kconfig | 2 +- drivers/usb/typec/fusb302/fusb302.c | 63 +- drivers/usb/typec/tcpm.c| 903 +++- include/linux/power_supply.h| 16 + include/linux/usb/pd.h | 4 +- include/linux/usb/tcpm.h| 1 + 11 files changed, 1417 insertions(+), 85 deletions(-) -- 1.9.1
RE: [PATCH] power: supply: da9150-fg: remove VLA usage
On 09 March 2018 04:58, Gustavo A. R. Silva wrote: > In preparation to enabling -Wvla, remove VLA usage and replace it > with fixed-length arrays. > > It seems that the length of array 'buf' will not exceed > DA9150_QIF_SHORT_SIZE bytes (2 bytes). But a fixed length > of DA9150_QIF_BYTE_SIZE bytes (8 bytes) was chosen in case > this change in the future. > > Fixed as part of the directive to remove all VLAs from > the kernel: https://lkml.org/lkml/2018/3/7/621 > > Signed-off-by: Gustavo A. R. Silva > --- > drivers/power/supply/da9150-fg.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/power/supply/da9150-fg.c > b/drivers/power/supply/da9150-fg.c > index 8b8ce97..96893be 100644 > --- a/drivers/power/supply/da9150-fg.c > +++ b/drivers/power/supply/da9150-fg.c > @@ -92,7 +92,7 @@ struct da9150_fg { > static u32 da9150_fg_read_attr(struct da9150_fg *fg, u8 code, u8 size) > > { > - u8 buf[size]; > + u8 buf[DA9150_QIF_BYTE_SIZE]; You can use DA9150_QIF_LONG_SIZE as that's the biggest size of an attribute which can be accessed. This will also save a little space. > u8 read_addr; > u32 res = 0; > int i; > @@ -111,7 +111,7 @@ static void da9150_fg_write_attr(struct da9150_fg *fg, u8 > code, u8 size, >u32 val) > > { > - u8 buf[size]; > + u8 buf[DA9150_QIF_BYTE_SIZE]; > u8 write_addr; > int i; > > -- > 2.7.4
[PATCH] ASoC: da7219: Add common clock usage for providing DAI clks
There is a need to use DA7219 as DAI clock master for other codecs within a system, which means that the DAI clocks are required to remain, regardless of whether the codec is actually running playback/capture. To be able to expose control of the DAI clocking the common clock framework has been employed. The current implementation adds a simple clock gate for enabling and disabling the DAI clocks, with no rate control supported (this is still handled through standard hw_params() functions as before). If DT is enabled then the clock is added to the OF providers list, otherwise a clkdev lookup is used. Signed-off-by: Adam Thomson --- Documentation/devicetree/bindings/sound/da7219.txt | 6 + include/sound/da7219.h | 2 + sound/soc/codecs/da7219.c | 129 +++-- sound/soc/codecs/da7219.h | 9 ++ 4 files changed, 138 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/da7219.txt b/Documentation/devicetree/bindings/sound/da7219.txt index 5b54d2d..c3df92d 100644 --- a/Documentation/devicetree/bindings/sound/da7219.txt +++ b/Documentation/devicetree/bindings/sound/da7219.txt @@ -25,6 +25,9 @@ Optional properties: interrupt is to be used to wake system, otherwise "irq" should be used. - wakeup-source: Flag to indicate this device can wake system (suspend/resume). +- #clock-cells : Should be set to '<0>', only one clock source provided; +- clock-output-names : Name given for DAI clocks output; + - clocks : phandle and clock specifier for codec MCLK. - clock-names : Clock name string for 'clocks' attribute, should be "mclk". @@ -83,6 +86,9 @@ Example: VDDMIC-supply = <®_audio>; VDDIO-supply = <®_audio>; + #clock-cells = <0>; + clock-output-names = "dai-clks"; + clocks = <&clks 201>; clock-names = "mclk"; diff --git a/include/sound/da7219.h b/include/sound/da7219.h index 409ef139..1bfcb16 100644 --- a/include/sound/da7219.h +++ b/include/sound/da7219.h @@ -36,6 +36,8 @@ enum da7219_mic_amp_in_sel { struct da7219_pdata { bool wakeup_source; + const char *dai_clks_name; + /* Mic */ enum da7219_micbias_voltage micbias_lvl; enum da7219_mic_amp_in_sel mic_amp_in_sel; diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 5e043d0..4412159 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -13,6 +13,8 @@ #include #include +#include +#include #include #include #include @@ -772,16 +774,27 @@ static int da7219_dai_event(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component); u8 pll_ctrl, pll_status; - int i = 0; + int i = 0, ret; bool srm_lock = false; switch (event) { case SND_SOC_DAPM_PRE_PMU: - if (da7219->master) + if (da7219->master) { /* Enable DAI clks for master mode */ - snd_soc_component_update_bits(component, DA7219_DAI_CLK_MODE, - DA7219_DAI_CLK_EN_MASK, - DA7219_DAI_CLK_EN_MASK); + if (da7219->dai_clks) { + ret = clk_prepare_enable(da7219->dai_clks); + if (ret) { + dev_err(component->dev, + "Failed to enable dai_clks\n"); + return ret; + } + } else { + snd_soc_component_update_bits(component, + DA7219_DAI_CLK_MODE, + DA7219_DAI_CLK_EN_MASK, + DA7219_DAI_CLK_EN_MASK); + } + } /* PC synchronised to DAI */ snd_soc_component_update_bits(component, DA7219_PC_COUNT, @@ -814,9 +827,16 @@ static int da7219_dai_event(struct snd_soc_dapm_widget *w, DA7219_PC_FREERUN_MASK); /* Disable DAI clks if in master mode */ - if (da7219->master) - snd_soc_component_update_bits(component, DA7219_DAI_CLK_MODE, - DA7219_DAI_CLK_EN_MASK, 0); + if (da7219->master) { + if (da7219->dai_clks) + clk_disabl
RE: linux-next: build failure after merge of the sound-asoc tree
On 13 March 2018 06:09, Stephen Rothwell wrote: > Hi all, > > After merging the sound-asoc tree, today's linux-next build (powerpc > allyesconfig) failed like this: > > sound/soc/codecs/da7219.o: In function `.da7219_remove': > da7219.c:(.text+0xcbc): undefined reference to `.clkdev_drop' > > Caused by commit > > fc8f7ea2d6c0 ("ASoC: da7219: Add common clock usage for providing DAI clks") > > CONFIG_CLKDEV_LOOKUP is not set for this build. > > I have reverted that commit for today. My bad. Apologies for this. :( Mark, I'll send a follow up patch to fix this ASAP.
[PATCH] ASoC: da7219: clkdev_drop usage depends on CONFIG_COMMON_CLK
Fixes: ASoC: da7219: Add common clock usage for providing DAI clks clkdev_drop usage in the codec remove function should be dependent on if CONFIG_COMMON_CLK is defined for the platform, otherwise it can cause build failures for platforms that do not support this. The clkdev_* functions are still defined for those platforms, in headers and source but the functions are not linked in. This patch resolves this issue, so clkdev_drop is only used if CONFIG_COMMON_CLK is defined. Signed-off-by: Adam Thomson --- sound/soc/codecs/da7219.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 4412159..08f55d7 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -1966,8 +1966,10 @@ static void da7219_remove(struct snd_soc_component *component) da7219_aad_exit(component); +#ifdef CONFIG_COMMON_CLK if (da7219->dai_clks_lookup) clkdev_drop(da7219->dai_clks_lookup); +#endif /* Supplies */ regulator_bulk_disable(DA7219_NUM_SUPPLIES, da7219->supplies); -- 1.9.1
RE: [PATCH 1/2] power: supply: add input voltage limit property.
On 21 November 2018 15:35, Enric Balletbo i Serra wrote: > We have a problem with USBPD chargers which under certain conditions > can result in system overheating if the voltage provided by the USBPD > port is too high. While the preferred means to control this would be > through devicetree or ACPI settings, this is not always possible, and > we need to have a means to set a voltage limit. > > This patch exposes a new property, similar to input current limit, to > re-configure the maximum voltage from the external supply at runtime > based on system-level knowledge or user input. I think we should be adding new documentation to the following file for any property changes: Documentation/ABI/testing/sysfs-class-power Sebastian can maybe comment further though. > Signed-off-by: Enric Balletbo i Serra > --- > > Documentation/power/power_supply_class.txt | 2 ++ > drivers/power/supply/power_supply_sysfs.c | 1 + > include/linux/power_supply.h | 1 + > 3 files changed, 4 insertions(+) > > diff --git a/Documentation/power/power_supply_class.txt > b/Documentation/power/power_supply_class.txt > index 300d37896e51..7b4be615b4f8 100644 > --- a/Documentation/power/power_supply_class.txt > +++ b/Documentation/power/power_supply_class.txt > @@ -137,6 +137,8 @@ power supply object. > > INPUT_CURRENT_LIMIT - input current limit programmed by charger. > Indicates the current drawn from a charging source. > +INPUT_VOLTAGE_LIMIT - input voltage limit programmed by charger. > +Indicates the voltage limit from a charging source. > > CHARGE_CONTROL_LIMIT - current charge control limit setting > CHARGE_CONTROL_LIMIT_MAX - maximum charge control limit setting diff > --git a/drivers/power/supply/power_supply_sysfs.c > b/drivers/power/supply/power_supply_sysfs.c > index dce24f596160..5848742ebb59 100644 > --- a/drivers/power/supply/power_supply_sysfs.c > +++ b/drivers/power/supply/power_supply_sysfs.c > @@ -275,6 +275,7 @@ static struct device_attribute power_supply_attrs[] = { > POWER_SUPPLY_ATTR(charge_control_limit), > POWER_SUPPLY_ATTR(charge_control_limit_max), > POWER_SUPPLY_ATTR(input_current_limit), > + POWER_SUPPLY_ATTR(input_voltage_limit), > POWER_SUPPLY_ATTR(energy_full_design), > POWER_SUPPLY_ATTR(energy_empty_design), > POWER_SUPPLY_ATTR(energy_full), > diff --git a/include/linux/power_supply.h > b/include/linux/power_supply.h index f80769175c56..608ba88e32ee 100644 > --- a/include/linux/power_supply.h > +++ b/include/linux/power_supply.h > @@ -122,6 +122,7 @@ enum power_supply_property { > POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, > POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, > POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, > + POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT, > POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, > POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN, > POWER_SUPPLY_PROP_ENERGY_FULL, > -- > 2.19.1
RE: [PATCH v2 1/2] power: supply: add input voltage limit property.
On 22 November 2018 10:11, Enric Balletbo i Serra wrote: > We have a problem with USBPD chargers which under certain conditions can > result in system overheating if the voltage provided by the USBPD port is too > high. While the preferred means to control this would be through devicetree or > ACPI settings, this is not always possible, and we need to have a means to > set a > voltage limit. > > This patch exposes a new property, similar to input current limit, to > re-configure > the maximum voltage from the external supply at runtime based on system-level > knowledge or user input. > > Signed-off-by: Enric Balletbo i Serra > Reviewed-by: Guenter Roeck Acked-by: Adam Thomson > --- > > Changes in v2: > - Document the new property in ABI/testing/sysfs-class-power. > - Add the Reviewed-by Guenter Roeck tag. > > Documentation/ABI/testing/sysfs-class-power | 11 +++ > Documentation/power/power_supply_class.txt | 2 ++ > drivers/power/supply/power_supply_sysfs.c | 1 + > include/linux/power_supply.h| 1 + > 4 files changed, 15 insertions(+) > > diff --git a/Documentation/ABI/testing/sysfs-class-power > b/Documentation/ABI/testing/sysfs-class-power > index 5e23e22dce1b..4fb24b0a28df 100644 > --- a/Documentation/ABI/testing/sysfs-class-power > +++ b/Documentation/ABI/testing/sysfs-class-power > @@ -335,6 +335,17 @@ Description: > Access: Read, Write > Valid values: Represented in microamps > > +What: > /sys/class/power_supply//input_voltage_limit > +Date:Nov 2018 > +Contact: linux...@vger.kernel.org > +Description: > + Details the incoming VBUS voltage limit currently set in the > + supply. Normally this is configured based on the type of > + connection made. > + > + Access: Read, Write > + Valid values: Represented in microvolts > + > What:/sys/class/power_supply//online, > Date:May 2007 > Contact: linux...@vger.kernel.org > diff --git a/Documentation/power/power_supply_class.txt > b/Documentation/power/power_supply_class.txt > index 300d37896e51..7b4be615b4f8 100644 > --- a/Documentation/power/power_supply_class.txt > +++ b/Documentation/power/power_supply_class.txt > @@ -137,6 +137,8 @@ power supply object. > > INPUT_CURRENT_LIMIT - input current limit programmed by charger. Indicates > the current drawn from a charging source. > +INPUT_VOLTAGE_LIMIT - input voltage limit programmed by charger. > +Indicates the voltage limit from a charging source. > > CHARGE_CONTROL_LIMIT - current charge control limit setting > CHARGE_CONTROL_LIMIT_MAX - maximum charge control limit setting diff --git > a/drivers/power/supply/power_supply_sysfs.c > b/drivers/power/supply/power_supply_sysfs.c > index dce24f596160..5848742ebb59 100644 > --- a/drivers/power/supply/power_supply_sysfs.c > +++ b/drivers/power/supply/power_supply_sysfs.c > @@ -275,6 +275,7 @@ static struct device_attribute power_supply_attrs[] = { > POWER_SUPPLY_ATTR(charge_control_limit), > POWER_SUPPLY_ATTR(charge_control_limit_max), > POWER_SUPPLY_ATTR(input_current_limit), > + POWER_SUPPLY_ATTR(input_voltage_limit), > POWER_SUPPLY_ATTR(energy_full_design), > POWER_SUPPLY_ATTR(energy_empty_design), > POWER_SUPPLY_ATTR(energy_full), > diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index > f80769175c56..608ba88e32ee 100644 > --- a/include/linux/power_supply.h > +++ b/include/linux/power_supply.h > @@ -122,6 +122,7 @@ enum power_supply_property { > POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, > POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, > POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, > + POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT, > POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, > POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN, > POWER_SUPPLY_PROP_ENERGY_FULL, > -- > 2.19.1
RE: [PATCH 2/2] ASoC: DA7219: Implement error check on reg read and write
On 04 December 2018 18:36, Akshu Agrawal wrote: > Failed i2c transaction can lead to failure in reg read or write. > Need to have error check for each read write operation. > I'm not really clear what this gains you. If I2C is broken this won't solve anything, and you have far deeper problems. Seems to me like a lot of code which adds almost nothing. > Signed-off-by: Akshu Agrawal > --- > sound/soc/codecs/da7219.c | 323 +++- > -- > sound/soc/codecs/da7219.h | 2 +- > 2 files changed, 247 insertions(+), 78 deletions(-) > > diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index > e46e9f4..6757129 100644 > --- a/sound/soc/codecs/da7219.c > +++ b/sound/soc/codecs/da7219.c > @@ -312,69 +312,103 @@ static int da7219_enum_locked_put(struct > snd_kcontrol *kcontrol, } > > /* ALC */ > -static void da7219_alc_calib(struct snd_soc_component *component) > +static int da7219_alc_calib(struct snd_soc_component *component) > { > - u8 mic_ctrl, mixin_ctrl, adc_ctrl, calib_ctrl; > + int mic_ctrl, mixin_ctrl, adc_ctrl, calib_ctrl; > + int ret; > > /* Save current state of mic control register */ > mic_ctrl = snd_soc_component_read32(component, > DA7219_MIC_1_CTRL); > + if (mic_ctrl < 0) > + return mic_ctrl; > > /* Save current state of input mixer control register */ > mixin_ctrl = snd_soc_component_read32(component, > DA7219_MIXIN_L_CTRL); > + if (mixin_ctrl < 0) > + return mixin_ctrl; > > /* Save current state of input ADC control register */ > adc_ctrl = snd_soc_component_read32(component, > DA7219_ADC_L_CTRL); > + if (adc_ctrl < 0) > + return adc_ctrl; > > /* Enable then Mute MIC PGAs */ > - snd_soc_component_update_bits(component, DA7219_MIC_1_CTRL, > DA7219_MIC_1_AMP_EN_MASK, > + ret = snd_soc_component_update_bits(component, > DA7219_MIC_1_CTRL, > + DA7219_MIC_1_AMP_EN_MASK, > DA7219_MIC_1_AMP_EN_MASK); > - snd_soc_component_update_bits(component, DA7219_MIC_1_CTRL, > + if (ret < 0) > + return ret; > + > + ret = snd_soc_component_update_bits(component, > DA7219_MIC_1_CTRL, > DA7219_MIC_1_AMP_MUTE_EN_MASK, > DA7219_MIC_1_AMP_MUTE_EN_MASK); > + if (ret < 0) > + return ret; > > /* Enable input mixers unmuted */ > - snd_soc_component_update_bits(component, DA7219_MIXIN_L_CTRL, > + ret = snd_soc_component_update_bits(component, > DA7219_MIXIN_L_CTRL, > DA7219_MIXIN_L_AMP_EN_MASK | > DA7219_MIXIN_L_AMP_MUTE_EN_MASK, > DA7219_MIXIN_L_AMP_EN_MASK); > + if (ret < 0) > + return ret; > > /* Enable input filters unmuted */ > - snd_soc_component_update_bits(component, DA7219_ADC_L_CTRL, > + ret = snd_soc_component_update_bits(component, > DA7219_ADC_L_CTRL, > DA7219_ADC_L_MUTE_EN_MASK | > DA7219_ADC_L_EN_MASK, > DA7219_ADC_L_EN_MASK); > + if (ret < 0) > + return ret; > > /* Perform auto calibration */ > - snd_soc_component_update_bits(component, DA7219_ALC_CTRL1, > + ret = snd_soc_component_update_bits(component, > DA7219_ALC_CTRL1, > DA7219_ALC_AUTO_CALIB_EN_MASK, > DA7219_ALC_AUTO_CALIB_EN_MASK); > + if (ret < 0) > + return ret; > do { > calib_ctrl = snd_soc_component_read32(component, > DA7219_ALC_CTRL1); > + if (calib_ctrl < 0) > + return calib_ctrl; > } while (calib_ctrl & DA7219_ALC_AUTO_CALIB_EN_MASK); > > /* If auto calibration fails, disable DC offset, hybrid ALC */ > if (calib_ctrl & DA7219_ALC_CALIB_OVERFLOW_MASK) { > dev_warn(component->dev, >"ALC auto calibration failed with overflow\n"); > - snd_soc_component_update_bits(component, > DA7219_ALC_CTRL1, > + ret = snd_soc_component_update_bits(component, > DA7219_ALC_CTRL1, > DA7219_ALC_OFFSET_EN_MASK | > DA7219_ALC_SYNC_MODE_MASK, 0); > + if (ret < 0) > + return ret; > } else { > /* Enable DC offset cancellation, hybrid mode */ > - snd_soc_component_update_bits(component, > DA7219_ALC_CTRL1, > + ret = snd_soc_component_update_bits(component, > DA7219_ALC_CTRL1, > DA7219_ALC_OFFSET_EN_MASK | > DA7219_ALC_SYNC_MODE_MASK, > DA7219_ALC_OFFSET_EN_MASK | > DA7219_ALC_SYNC_MODE_MASK); > + if (ret < 0) > + return ret; > } > > /* Restor
RE: [PATCH 2/2] ASoC: DA7219: Implement error check on reg read and write
On 05 December 2018 04:27, Akshu Agrawal wrote: > On 12/5/2018 2:46 AM, Adam Thomson wrote: > > On 04 December 2018 18:36, Akshu Agrawal wrote: > > > >> Failed i2c transaction can lead to failure in reg read or write. > >> Need to have error check for each read write operation. > >> > > > > I'm not really clear what this gains you. If I2C is broken this won't > > solve anything, and you have far deeper problems. Seems to me like a > > lot of code which adds almost nothing. > > > > I agree Adam that if I2C is broken, system is in bad state. But so is the > case with > most of the error situations. Error handling is anyway needed. > We have seen case where read32 returned -1, unsigned int cast and the write > back of the error value ends up in updating the register with 0xff. > Need to avoid scenarios like this. If the previous I2C access failed, how can we be sure that the write back to HW of 0xFF even succeeds? More importantly these error returns won't necessarily stop subsequent calls to controls within the Codec I believe, so you could still see unwanted writes to HW via I2C, if I2C is sporadically operational. Again I don't see this update resolving that. The key thing is to resolve why even just one I2C transaction fails. I'd like to hear input from others on this as if this was something fundamentally required, all other I2C based codecs would be doing this and that's just not the case right now. One last thing, if a change like this is somehow deemed to be required, you will need to update the AAD part of the driver as well. > > Thanks, > Akshu > >> Signed-off-by: Akshu Agrawal > >> --- > >> sound/soc/codecs/da7219.c | 323 > +++- > >> -- > >> sound/soc/codecs/da7219.h | 2 +- > >> 2 files changed, 247 insertions(+), 78 deletions(-) > >> > >> diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c > >> index > >> e46e9f4..6757129 100644 > >> --- a/sound/soc/codecs/da7219.c > >> +++ b/sound/soc/codecs/da7219.c > >> @@ -312,69 +312,103 @@ static int da7219_enum_locked_put(struct > >> snd_kcontrol *kcontrol, } > >> > >> /* ALC */ > >> -static void da7219_alc_calib(struct snd_soc_component *component) > >> +static int da7219_alc_calib(struct snd_soc_component *component) > >> { > >> - u8 mic_ctrl, mixin_ctrl, adc_ctrl, calib_ctrl; > >> + int mic_ctrl, mixin_ctrl, adc_ctrl, calib_ctrl; > >> + int ret; > >> > >>/* Save current state of mic control register */ > >>mic_ctrl = snd_soc_component_read32(component, > >> DA7219_MIC_1_CTRL); > >> + if (mic_ctrl < 0) > >> + return mic_ctrl; > >> > >>/* Save current state of input mixer control register */ > >>mixin_ctrl = snd_soc_component_read32(component, > >> DA7219_MIXIN_L_CTRL); > >> + if (mixin_ctrl < 0) > >> + return mixin_ctrl; > >> > >>/* Save current state of input ADC control register */ > >>adc_ctrl = snd_soc_component_read32(component, > >> DA7219_ADC_L_CTRL); > >> + if (adc_ctrl < 0) > >> + return adc_ctrl; > >> > >>/* Enable then Mute MIC PGAs */ > >> - snd_soc_component_update_bits(component, DA7219_MIC_1_CTRL, > >> DA7219_MIC_1_AMP_EN_MASK, > >> + ret = snd_soc_component_update_bits(component, > >> DA7219_MIC_1_CTRL, > >> + DA7219_MIC_1_AMP_EN_MASK, > >>DA7219_MIC_1_AMP_EN_MASK); > >> - snd_soc_component_update_bits(component, DA7219_MIC_1_CTRL, > >> + if (ret < 0) > >> + return ret; > >> + > >> + ret = snd_soc_component_update_bits(component, > >> DA7219_MIC_1_CTRL, > >>DA7219_MIC_1_AMP_MUTE_EN_MASK, > >>DA7219_MIC_1_AMP_MUTE_EN_MASK); > >> + if (ret < 0) > >> + return ret; > >> > >>/* Enable input mixers unmuted */ > >> - snd_soc_component_update_bits(component, DA7219_MIXIN_L_CTRL, > >> + ret = snd_soc_component_update_bits(component, > >> DA7219_MIXIN_L_CTRL, > >>DA7219_MIXIN_L_AMP_EN_MASK | > >>DA7219_MIXIN_L_AMP_MUTE_EN_MASK, > >>DA7219_MIXIN_L_AMP_EN_MASK); > >> + if (ret < 0) > >> + return ret; > >> > >>/* Enable input filters unmuted */ >
RE: [PATCH] regulator: Use of_node_name_eq for node name comparisons
On 05 December 2018 19:51, Rob Herring wrote: > Convert string compares of DT node names to use of_node_name_eq helper > instead. This removes direct access to the node name pointer. > > For instances using of_node_cmp, this has the side effect of now using case > sensitive comparisons. This should not matter for any FDT based system which > all > of these are. > > Cc: Liam Girdwood > Cc: Mark Brown > Cc: Support Opensource > Cc: Sangbeom Kim > Cc: Krzysztof Kozlowski > Cc: Bartlomiej Zolnierkiewicz > Cc: linux-samsung-...@vger.kernel.org > Signed-off-by: Rob Herring For da9052 regulator driver: Acked-by: Adam Thomson > --- > drivers/regulator/88pm8607.c | 2 +- > drivers/regulator/da9052-regulator.c | 2 +- > drivers/regulator/max8997-regulator.c | 2 +- > drivers/regulator/mc13xxx-regulator-core.c | 2 +- > drivers/regulator/qcom-rpmh-regulator.c| 2 +- > drivers/regulator/s5m8767.c| 2 +- > 6 files changed, 6 insertions(+), 6 deletions(-) > > diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index > fd86446e499b..28f55248eb90 100644 > --- a/drivers/regulator/88pm8607.c > +++ b/drivers/regulator/88pm8607.c > @@ -328,7 +328,7 @@ static int pm8607_regulator_dt_init(struct > platform_device *pdev, > return -ENODEV; > } > for_each_child_of_node(nproot, np) { > - if (!of_node_cmp(np->name, info->desc.name)) { > + if (of_node_name_eq(np, info->desc.name)) { > config->init_data = > of_get_regulator_init_data(&pdev->dev, np, > &info->desc); > diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052- > regulator.c > index 37e4025203e3..207cb3859dcc 100644 > --- a/drivers/regulator/da9052-regulator.c > +++ b/drivers/regulator/da9052-regulator.c > @@ -435,7 +435,7 @@ static int da9052_regulator_probe(struct platform_device > *pdev) > return -ENODEV; > > for_each_child_of_node(nproot, np) { > - if (!of_node_cmp(np->name, > + if (of_node_name_eq(np, >regulator->info->reg_desc.name)) { > config.init_data = of_get_regulator_init_data( > &pdev->dev, np, > diff --git a/drivers/regulator/max8997-regulator.c > b/drivers/regulator/max8997- > regulator.c > index 3bf5ddfaaea8..4d2487279a0a 100644 > --- a/drivers/regulator/max8997-regulator.c > +++ b/drivers/regulator/max8997-regulator.c > @@ -925,7 +925,7 @@ static int max8997_pmic_dt_parse_pdata(struct > platform_device *pdev, > pdata->regulators = rdata; > for_each_child_of_node(regulators_np, reg_np) { > for (i = 0; i < ARRAY_SIZE(regulators); i++) > - if (!of_node_cmp(reg_np->name, regulators[i].name)) > + if (of_node_name_eq(reg_np, regulators[i].name)) > break; > > if (i == ARRAY_SIZE(regulators)) { > diff --git a/drivers/regulator/mc13xxx-regulator-core.c > b/drivers/regulator/mc13xxx-regulator-core.c > index 65eb1e0350cf..2243138d8a58 100644 > --- a/drivers/regulator/mc13xxx-regulator-core.c > +++ b/drivers/regulator/mc13xxx-regulator-core.c > @@ -186,7 +186,7 @@ struct mc13xxx_regulator_init_data > *mc13xxx_parse_regulators_dt( > for (i = 0; i < num_regulators; i++) { > if (!regulators[i].desc.name) > continue; > - if (!of_node_cmp(child->name, > + if (of_node_name_eq(child, >regulators[i].desc.name)) { > p->id = i; > p->init_data = of_get_regulator_init_data( diff > -- > git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh- > regulator.c > index 39ccf53fdeb3..b2c2d01d1637 100644 > --- a/drivers/regulator/qcom-rpmh-regulator.c > +++ b/drivers/regulator/qcom-rpmh-regulator.c > @@ -410,7 +410,7 @@ static int rpmh_regulator_init_vreg(struct rpmh_vreg > *vreg, struct device *dev, > vreg->dev = dev; > > for (rpmh_data = pmic_rpmh_data; rpmh_data->name; rpmh_data++) > - if (!strcmp(rpmh_data->name, node->name)) > + if (of_node_name_eq(node, rpmh_data->name)) > break; > > if (!rpmh_data->name) { > diff --git a/drivers/regulator/s5m8
RE: [PATCH] usb: typec: tcpm: Extend the matching rules on PPS APDO selection
On 12 December 2018 02:47, Kyle Tso wrote: > On Mon, Dec 10, 2018 at 7:36 PM Adam Thomson > wrote: > > > > On 10 December 2018 09:01, Adam Thomson wrote: > > > > > On 06 December 2018 03:02, Kyle Tso wrote: > > > > > > > Current matching rules ensure that the voltage range of selected > > > > Source Capability is entirely within the range defined in one of > > > > the Sink Capabilities. This is reasonable but not practical > > > > because Sink may not support wide range of voltage when sinking > > > > power while Source could advertise its capabilities in raletively > > > > wider range. For example, a Source PDO advertising 3.3V-11V@3A (9V > > > > Prog of Fixed Nominal Voltage) will not be selected if the Sink > > > > requires 5V- 12V@3A PPS power. However, the Sink could work well > > > > if the requested voltage range in > > > RDOs is 5V-11V@3A. > > > > > > Is there a real world example of a sink requiring the 5V - 12V > > > range? In that scenario could we not add an additional sink > > > capability which allows for this range to be supported, and the current > implementation should work just fine? > > > > Ok, I maybe should have waited until after my morning coffee to > > respond. So because the lower limit on the sink side, is higher than > > the advertised source's PPS minimum voltage it never gets selected? > > Personally I'd prefer to keep the upper limit checking as is as I > > think that's an additional safety benefit helping to prevent > > over-voltage scenarios. I think if a PPS APDO can supply up to 11V > > then the system should be capable of handling that voltage, otherwise > > it shouldn't be considered at all. The Source provides limits checking > > as well to make sure the Sink doesn't request a value above the maximum > voltage limit for that selected APDO. > > > > If the over-voltage occurs, it means: > 1. the adapter malfunctioned. or > 2. the code on the Sink accidentally requests a voltage level which is over > the limit > of the Sink. > > For 1., it is difficult to predict the behaviors of a malfunctioned adapter. > The over- > voltage event may happen even if the Sink doesn't select the APDO from this > broken adapter. Yes, I agree it's almost impossible to do anything from software to mitigate this which is why the HW design has to have protection for this. > For 2., it is difficult to predict the behaviors from the careless code as > well. Yes, that's also true, but if it's coded with the intention not to select an option that's potentially higher than the system can handle then we're less likely to fall foul of over-voltage scenarios in my opinion. By selecting a PPS APDO with an upper threshold which falls within the board limits, assuming the code were to accidentally request something higher than the PPS APDO maximum then the Source should reject this. Just feels a little safer as we're talking about controlling an external power source. At the end of the day though the decision lies with the maintainers on this. > > For the lower limit I'm more inclined to agree with allowing a higher > > minimum on the sink side as that's less of a safety/damage issue as I > understand it. > > FWIW, what is the real world scenario? What happens if voltage drops below > 5V? > > > > Some products (in Sink mode) have under-voltage protection (the lower bound > might be around 3.8V - 4V before the calculation of IR-drop) that will cause > the > disconnection. Ok, so the system would just stop charging, correct? I guess the calling code to control the Source/adapter, via TCPM, wouldn't select a value below 4V in that scenario anyway? > > thanks, > Kyle
RE: [PATCH v3 1/2] power: supply: add input voltage limit property
On 13 December 2018 12:10, Enric Balletbo i Serra wrote: > This is part of the Pixel C's thermal management strategy to effectively > limit the > input power to 5V 3A when the screen is on. When the screen is on, the > display, > the CPU, and the GPU all contribute more heat to the system than while the > screen is off, and we made a tradeoff to throttle the charger in order to give > more of the thermal budget to those other components. > > So there's nothing fundamentally broken about the hardware that would cause > the Pixel C to malfunction if we were charging at 9V or 12V instead of 5V when > the screen is on, ie if userspace doesn't change this. > > What would happen is that you wouldn't meet Google's skin temperature targets > on the system if the charger was allowed to run at 9V or 12V with the screen > on. > > For folks hacking on Pixel Cs (which is now outside of Google's official > support > window for Android) and customizing their own kernel and userspace this would > be acceptable, but we wanted to expose this feature in the power supply > properties because the feature does exist in the Emedded Controller firmware > of > the Pixel C and all of Google's Chromebooks with USB-C made since 2015 in case > someone running an up to date kernel wanted to limit the charging power for > thermal or other reasons. > > This patch exposes a new property, similar to input current limit, to > re-configure > the maximum voltage from the external supply at runtime based on system-level > knowledge or user input. > > Signed-off-by: Enric Balletbo i Serra > Reviewed-by: Guenter Roeck Acked-by: Adam Thomson > --- > > Changes in v3: > - Improve commit log and documentation with Benson comments. > > Changes in v2: > - Document the new property in ABI/testing/sysfs-class-power. > - Add the Reviewed-by Guenter Roeck tag. > > Documentation/ABI/testing/sysfs-class-power | 15 +++ > Documentation/power/power_supply_class.txt | 2 ++ > drivers/power/supply/power_supply_sysfs.c | 1 + > include/linux/power_supply.h| 1 + > 4 files changed, 19 insertions(+) > > diff --git a/Documentation/ABI/testing/sysfs-class-power > b/Documentation/ABI/testing/sysfs-class-power > index 5e23e22dce1b..6dee5c105a28 100644 > --- a/Documentation/ABI/testing/sysfs-class-power > +++ b/Documentation/ABI/testing/sysfs-class-power > @@ -335,6 +335,21 @@ Description: > Access: Read, Write > Valid values: Represented in microamps > > +What: > /sys/class/power_supply//input_voltage_limit > +Date:Nov 2018 > +Contact: linux...@vger.kernel.org > +Description: > + This entry configures the incoming VBUS voltage limit currently > + set in the supply. Normally this is configured based on > + system-level knowledge or user input (e.g. This is part of the > + Pixel C's thermal management strategy to effectively limit the > + input power to 5V when the screen is on to meet Google's skin > + temperature targets). Note that this feature should not be > + used for safety critical things. > + > + Access: Read, Write > + Valid values: Represented in microvolts > + > What:/sys/class/power_supply//online, > Date:May 2007 > Contact: linux...@vger.kernel.org > diff --git a/Documentation/power/power_supply_class.txt > b/Documentation/power/power_supply_class.txt > index 300d37896e51..7b4be615b4f8 100644 > --- a/Documentation/power/power_supply_class.txt > +++ b/Documentation/power/power_supply_class.txt > @@ -137,6 +137,8 @@ power supply object. > > INPUT_CURRENT_LIMIT - input current limit programmed by charger. Indicates > the current drawn from a charging source. > +INPUT_VOLTAGE_LIMIT - input voltage limit programmed by charger. > +Indicates the voltage limit from a charging source. > > CHARGE_CONTROL_LIMIT - current charge control limit setting > CHARGE_CONTROL_LIMIT_MAX - maximum charge control limit setting diff --git > a/drivers/power/supply/power_supply_sysfs.c > b/drivers/power/supply/power_supply_sysfs.c > index dce24f596160..5848742ebb59 100644 > --- a/drivers/power/supply/power_supply_sysfs.c > +++ b/drivers/power/supply/power_supply_sysfs.c > @@ -275,6 +275,7 @@ static struct device_attribute power_supply_attrs[] = { > POWER_SUPPLY_ATTR(charge_control_limit), > POWER_SUPPLY_ATTR(charge_control_limit_max), > POWER_SUPPLY_ATTR(input_current_limit), > + POWER_SUPPLY_ATTR(input_voltage_limit), > POWER_SUPPLY_ATTR(
RE: [PATCH] usb: typec: tcpm: Extend the matching rules on PPS APDO selection
On 17 December 2018 02:48, Kyle Tso wrote: > Current matching rules ensure that the voltage range of selected Source > Capability is entirely within the range defined in one of the Sink > Capabilities. This > is reasonable but not practical because Sink may not support wide range of > voltage when sinking power while Source could advertise its capabilities in > raletively wider range. For example, a Source PDO advertising 3.3V-11V@3A (9V relatively > Prog of Fixed Nominal Voltage) will not be selected if the Sink requires 5V- > 12V@3A PPS power. However, the Sink could work well if the requested voltage > range in RDOs is 5V-11V@3A. > > Currently accepted: > |- source -| > |--- sink ---| > > Currently not accepted: > |- source -| > |--- sink ---| > > |- source -| > |--- sink ---| > > |- source -| > |-- sink ---| > > To improve the usability, change the matching rules to what listed > below: > a. The Source PDO is selectable if any portion of the voltage range >overlaps one of the Sink PDO's voltage range. > b. The maximum operational voltage will be the lower one between the >selected Source PDO and the matching Sink PDO. > c. The maximum power will be the maximum operational voltage times the >maximum current defined in the selected Source PDO d. Select the Source PDO > with the highest maximum power > > Signed-off-by: Kyle Tso > > --- > Changelog since v1: > - updated the commit message as suggested by Guenter Roeck us.net> > --- > drivers/usb/typec/tcpm/tcpm.c | 29 + > 1 file changed, 17 insertions(+), 12 deletions(-) > > diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c > index 3620efee2688..3001df7bd602 100644 > --- a/drivers/usb/typec/tcpm/tcpm.c > +++ b/drivers/usb/typec/tcpm/tcpm.c > @@ -2213,7 +2213,8 @@ static unsigned int tcpm_pd_select_pps_apdo(struct > tcpm_port *port) > unsigned int i, j, max_mw = 0, max_mv = 0; > unsigned int min_src_mv, max_src_mv, src_ma, src_mw; > unsigned int min_snk_mv, max_snk_mv; > - u32 pdo; > + unsigned int max_op_mv; > + u32 pdo, src, snk; > unsigned int src_pdo = 0, snk_pdo = 0; > > /* > @@ -2263,16 +2264,18 @@ static unsigned int tcpm_pd_select_pps_apdo(struct > tcpm_port *port) > continue; > } > > - if (max_src_mv <= max_snk_mv && > - min_src_mv >= min_snk_mv) { > + if (min_src_mv <= max_snk_mv && > + max_src_mv >= min_snk_mv) { > + max_op_mv = min(max_src_mv, > max_snk_mv); > + src_mw = (max_op_mv * src_ma) / 1000; > /* Prefer higher voltages if available > */ > if ((src_mw == max_mw && > - min_src_mv > max_mv) || > + max_op_mv > max_mv) || > src_mw > max_mw) { Sorry I didn't raise this before, but came to mind this morning when I was considering your updates again. What happens if the Source validly provides two PPS APDOs, for example: 3.3V - 11V, 3A (9V programmable) 3.3V - 16V, 3A (15V programmable) and the sink APDO is: 5V - 9V, 3A I think the code here will now select the higher range (15V programmable) as it gives a larger power output value, even if the sink can only support a voltage that's far smaller. I really don't think this is correct. *If* you are going to allow selection of PPS APDOs that provide a larger voltage range than the Sink can actually cope with, then I think you should at least select the lower of those advertised which fulfils the needs of the Sink. > src_pdo = i; > snk_pdo = j; > max_mw = src_mw; > - max_mv = max_src_mv; > + max_mv = max_op_mv; > } > } > } > @@ -2285,14 +2288,16 @@ static unsigned int tcpm_pd_select_pps_apdo(struct > tcpm_port *port) > } > > if (src_pdo) { > - pdo = port->source_caps[src_pdo]; > - > - port->pps_data.min_volt = pdo_pps_apdo_min_voltage(pdo); > - port->pps_data.max_volt = pdo_pps_apdo_max_voltage(pdo); > - port->pps_data.max_curr = > - min_pps_apdo_current(pdo, port->snk_pdo[snk_pdo]); > +
RE: [PATCH] usb: typec: tcpm: Extend the matching rules on PPS APDO selection
On 17 December 2018 12:45, Kyle Tso wrote: > On Mon, Dec 17, 2018 at 8:23 PM Adam Thomson > wrote: > > > > On 17 December 2018 02:48, Kyle Tso wrote: > > > > > Current matching rules ensure that the voltage range of selected > > > Source Capability is entirely within the range defined in one of the > > > Sink Capabilities. This is reasonable but not practical because Sink > > > may not support wide range of voltage when sinking power while > > > Source could advertise its capabilities in raletively wider range. > > > For example, a Source PDO advertising 3.3V-11V@3A (9V > > > > relatively > > > > noted! > Thanks for the correction. I will fix this in the next patch. > > > > Prog of Fixed Nominal Voltage) will not be selected if the Sink > > > requires 5V- 12V@3A PPS power. However, the Sink could work well if > > > the requested voltage range in RDOs is 5V-11V@3A. > > > > > > Currently accepted: > > > |- source -| > > > |--- sink ---| > > > > > > Currently not accepted: > > > |- source -| > > > |--- sink ---| > > > > > > |- source -| > > > |--- sink ---| > > > > > > |- source -| > > > |-- sink ---| > > > > > > To improve the usability, change the matching rules to what listed > > > below: > > > a. The Source PDO is selectable if any portion of the voltage range > > >overlaps one of the Sink PDO's voltage range. > > > b. The maximum operational voltage will be the lower one between the > > >selected Source PDO and the matching Sink PDO. > > > c. The maximum power will be the maximum operational voltage times the > > >maximum current defined in the selected Source PDO d. Select the > > > Source PDO with the highest maximum power > > > > > > Signed-off-by: Kyle Tso > > > > > > --- > > > Changelog since v1: > > > - updated the commit message as suggested by Guenter Roeck > > > > > > --- > > > drivers/usb/typec/tcpm/tcpm.c | 29 + > > > 1 file changed, 17 insertions(+), 12 deletions(-) > > > > > > diff --git a/drivers/usb/typec/tcpm/tcpm.c > > > b/drivers/usb/typec/tcpm/tcpm.c index 3620efee2688..3001df7bd602 > > > 100644 > > > --- a/drivers/usb/typec/tcpm/tcpm.c > > > +++ b/drivers/usb/typec/tcpm/tcpm.c > > > @@ -2213,7 +2213,8 @@ static unsigned int > > > tcpm_pd_select_pps_apdo(struct tcpm_port *port) > > > unsigned int i, j, max_mw = 0, max_mv = 0; > > > unsigned int min_src_mv, max_src_mv, src_ma, src_mw; > > > unsigned int min_snk_mv, max_snk_mv; > > > - u32 pdo; > > > + unsigned int max_op_mv; > > > + u32 pdo, src, snk; > > > unsigned int src_pdo = 0, snk_pdo = 0; > > > > > > /* > > > @@ -2263,16 +2264,18 @@ static unsigned int > > > tcpm_pd_select_pps_apdo(struct tcpm_port *port) > > > continue; > > > } > > > > > > - if (max_src_mv <= max_snk_mv && > > > - min_src_mv >= min_snk_mv) { > > > + if (min_src_mv <= max_snk_mv && > > > + max_src_mv >= min_snk_mv) { > > > + max_op_mv = min(max_src_mv, > > > max_snk_mv); > > > + src_mw = (max_op_mv * src_ma) > > > + / 1000; > > > /* Prefer higher voltages if > > > available */ > > > if ((src_mw == max_mw && > > > - min_src_mv > max_mv) || > > > + max_op_mv > max_mv) || > > > src_mw > max_mw) { > > > > Sorry I didn't raise this before, but came to mind this morning when I > > was considering your updates again. What happens if the Source validly > > provides two PPS APDOs, for example: > > > > 3.3V - 11V, 3A (9V programmable) > > 3.3V - 16V, 3A (
RE: [PATCH v3] usb: typec: tcpm: Extend the matching rules on PPS APDO selection
On 17 December 2018 13:22, Kyle Tso wrote: > Current matching rules ensure that the voltage range of selected Source > Capability is entirely within the range defined in one of the Sink > Capabilities. This > is reasonable but not practical because Sink may not support wide range of > voltage when sinking power while Source could advertise its capabilities in > relatively wider range. For example, a Source PDO advertising 3.3V-11V@3A (9V > Prog of Fixed Nominal Voltage) will not be selected if the Sink requires 5V- > 12V@3A PPS power. However, the Sink could work well if the requested voltage > range in RDOs is 5V-11V@3A. > > Currently accepted: > |- source -| > |--- sink ---| > > Currently not accepted: > |- source -| > |--- sink ---| > > |- source -| > |--- sink ---| > > |- source -| > |-- sink ---| > > To improve the usability, change the matching rules to what listed > below: > a. The Source PDO is selectable if any portion of the voltage range >overlaps one of the Sink PDO's voltage range. > b. The maximum operational voltage will be the lower one between the >selected Source PDO and the matching Sink PDO. > c. The maximum power will be the maximum operational voltage times the >maximum current defined in the selected Source PDO d. Select the Source PDO > with the highest maximum power > > Signed-off-by: Kyle Tso Acked-by: Adam Thomson > > --- > Changelog since v1: > - updated the commit message as suggested by Guenter Roeck us.net> > > Changelog since v2: > - fixed the coding style problems as suggested by Heikki Krogerus > > - Corrected a wrong word in the commit message as suggested by Adam > Thomson > > --- > drivers/usb/typec/tcpm/tcpm.c | 35 --- > 1 file changed, 20 insertions(+), 15 deletions(-) > > diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c > index 3620efee2688..4bc29b586698 100644 > --- a/drivers/usb/typec/tcpm/tcpm.c > +++ b/drivers/usb/typec/tcpm/tcpm.c > @@ -2213,7 +2213,8 @@ static unsigned int tcpm_pd_select_pps_apdo(struct > tcpm_port *port) > unsigned int i, j, max_mw = 0, max_mv = 0; > unsigned int min_src_mv, max_src_mv, src_ma, src_mw; > unsigned int min_snk_mv, max_snk_mv; > - u32 pdo; > + unsigned int max_op_mv; > + u32 pdo, src, snk; > unsigned int src_pdo = 0, snk_pdo = 0; > > /* > @@ -2263,16 +2264,18 @@ static unsigned int tcpm_pd_select_pps_apdo(struct > tcpm_port *port) > continue; > } > > - if (max_src_mv <= max_snk_mv && > - min_src_mv >= min_snk_mv) { > + if (min_src_mv <= max_snk_mv && > + max_src_mv >= min_snk_mv) { > + max_op_mv = min(max_src_mv, > max_snk_mv); > + src_mw = (max_op_mv * src_ma) / 1000; > /* Prefer higher voltages if available > */ > if ((src_mw == max_mw && > - min_src_mv > max_mv) || > + max_op_mv > max_mv) || > src_mw > max_mw) { > src_pdo = i; > snk_pdo = j; > max_mw = src_mw; > - max_mv = max_src_mv; > + max_mv = max_op_mv; > } > } > } > @@ -2285,16 +2288,18 @@ static unsigned int tcpm_pd_select_pps_apdo(struct > tcpm_port *port) > } > > if (src_pdo) { > - pdo = port->source_caps[src_pdo]; > - > - port->pps_data.min_volt = pdo_pps_apdo_min_voltage(pdo); > - port->pps_data.max_volt = pdo_pps_apdo_max_voltage(pdo); > - port->pps_data.max_curr = > - min_pps_apdo_current(pdo, port->snk_pdo[snk_pdo]); > - port->pps_data.out_volt = > - min(pdo_pps_apdo_max_voltage(pdo), port- > >pps_data.out_volt); > - port->pps_da
RE: [PATCH] usb: typec: tcpm: Extend the matching rules on PPS APDO selection
On 06 December 2018 03:02, Kyle Tso wrote: > Current matching rules ensure that the voltage range of selected Source > Capability is entirely within the range defined in one of the Sink > Capabilities. This > is reasonable but not practical because Sink may not support wide range of > voltage when sinking power while Source could advertise its capabilities in > raletively wider range. For example, a Source PDO advertising 3.3V-11V@3A (9V > Prog of Fixed Nominal Voltage) will not be selected if the Sink requires 5V- > 12V@3A PPS power. However, the Sink could work well if the requested voltage > range in RDOs is 5V-11V@3A. Is there a real world example of a sink requiring the 5V - 12V range? In that scenario could we not add an additional sink capability which allows for this range to be supported, and the current implementation should work just fine? > > To improve the usability, change the matching rules to what listed > below: > a. The Source PDO is selectable if any portion of the voltage range >overlaps one of the Sink PDO's voltage range. > b. The maximum operational voltage will be the lower one between the >selected Source PDO and the matching Sink PDO. > c. The maximum power will be the maximum operational voltage times the >maximum current defined in the selected Source PDO d. Select the Source PDO > with the highest maximum power > > Signed-off-by: Kyle Tso > --- > drivers/usb/typec/tcpm/tcpm.c | 29 + > 1 file changed, 17 insertions(+), 12 deletions(-) > > diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c > index 3620efee2688..3001df7bd602 100644 > --- a/drivers/usb/typec/tcpm/tcpm.c > +++ b/drivers/usb/typec/tcpm/tcpm.c > @@ -2213,7 +2213,8 @@ static unsigned int tcpm_pd_select_pps_apdo(struct > tcpm_port *port) > unsigned int i, j, max_mw = 0, max_mv = 0; > unsigned int min_src_mv, max_src_mv, src_ma, src_mw; > unsigned int min_snk_mv, max_snk_mv; > - u32 pdo; > + unsigned int max_op_mv; > + u32 pdo, src, snk; > unsigned int src_pdo = 0, snk_pdo = 0; > > /* > @@ -2263,16 +2264,18 @@ static unsigned int tcpm_pd_select_pps_apdo(struct > tcpm_port *port) > continue; > } > > - if (max_src_mv <= max_snk_mv && > - min_src_mv >= min_snk_mv) { > + if (min_src_mv <= max_snk_mv && > + max_src_mv >= min_snk_mv) { > + max_op_mv = min(max_src_mv, > max_snk_mv); > + src_mw = (max_op_mv * src_ma) / 1000; > /* Prefer higher voltages if available > */ > if ((src_mw == max_mw && > - min_src_mv > max_mv) || > + max_op_mv > max_mv) || > src_mw > max_mw) { > src_pdo = i; > snk_pdo = j; > max_mw = src_mw; > - max_mv = max_src_mv; > + max_mv = max_op_mv; > } > } > } > @@ -2285,14 +2288,16 @@ static unsigned int tcpm_pd_select_pps_apdo(struct > tcpm_port *port) > } > > if (src_pdo) { > - pdo = port->source_caps[src_pdo]; > - > - port->pps_data.min_volt = pdo_pps_apdo_min_voltage(pdo); > - port->pps_data.max_volt = pdo_pps_apdo_max_voltage(pdo); > - port->pps_data.max_curr = > - min_pps_apdo_current(pdo, port->snk_pdo[snk_pdo]); > + src = port->source_caps[src_pdo]; > + snk = port->snk_pdo[snk_pdo]; > + > + port->pps_data.min_volt = > max(pdo_pps_apdo_min_voltage(src), > + pdo_pps_apdo_min_voltage(snk)); > + port->pps_data.max_volt = > min(pdo_pps_apdo_max_voltage(src), > + pdo_pps_apdo_max_voltage(snk)); > + port->pps_data.max_curr = min_pps_apdo_current(src, snk); > port->pps_data.out_volt = > - min(pdo_pps_apdo_max_voltage(pdo), port- > >pps_data.out_volt); > + min(port->pps_data.max_volt, port- > >pps_data.out_volt); > port->pps_data.op_curr = > min(port->pps_data.max_curr, port->pps_data.op_curr); > } > -- > 2.20.0.rc2.403.gdbc3b29805-goog