* [PATCH v4 0/3] Driver for UCS1002
@ 2019-04-30 6:45 Andrey Smirnov
2019-04-30 6:45 ` Andrey Smirnov
` (3 more replies)
0 siblings, 4 replies; 16+ messages in thread
From: Andrey Smirnov @ 2019-04-30 6:45 UTC (permalink / raw)
To: linux-pm
Cc: Andrey Smirnov, Chris Healy, Lucas Stach, Fabio Estevam,
Guenter Roeck, Sebastian Reichel, Enric Balletbo Serra,
linux-kernel
Everyone:
This small series adds a driver for UCS1002 Programmable USB Port
Power Controller with Charger Emulation. See [page] for product page
and [datasheet] for device dataseet. Hopefully each individual patch
is self explanatory.
Note that this series is a revival of the upstreaming effort by Enric
Balletbo Serra last version of which can be found at [original-effort]
Feedback is welcome!
Thanks,
Andrey Smirnov
Changes since [v3]:
- Added a check for negative values to ucs1002_set_usb_type()
Changes since [v2]:
- Fixed a bug pointed out by Lucas
Changes since [v1]:
- Moved IRQ trigger specification to DT
- Fixed silent error paths in probe()
- Dropped error message in ucs1002_set_max_current()
- Fixed license mismatch
- Changed the driver to configure the chip to BC1.2 CDP by default
- Made other small fixes as per feedback for v1
[v3] https://lore.kernel.org/lkml/20190429195349.20335-1-andrew.smirnov@gmail.com
[v2] https://lore.kernel.org/lkml/20190429054741.7286-1-andrew.smirnov@gmail.com
[v1] https://lore.kernel.org/lkml/20190417084457.28747-1-andrew.smirnov@gmail.com/
[page] https://www.microchip.com/wwwproducts/en/UCS1002-2
[datasheet] https://ww1.microchip.com/downloads/en/DeviceDoc/UCS1002-2%20Data%20Sheet.pdf
[original-effort] https://lore.kernel.org/lkml/1460705181-10493-1-git-send-email-enric.balletbo@collabora.com/
Andrey Smirnov (3):
power: supply: core: Add POWER_SUPPLY_HEALTH_OVERCURRENT constant
power: supply: Add driver for Microchip UCS1002
dt-bindings: power: supply: Add bindings for Microchip UCS1002
.../power/supply/microchip,ucs1002.txt | 27 +
drivers/power/supply/Kconfig | 9 +
drivers/power/supply/Makefile | 1 +
drivers/power/supply/power_supply_sysfs.c | 2 +-
drivers/power/supply/ucs1002_power.c | 646 ++++++++++++++++++
include/linux/power_supply.h | 1 +
6 files changed, 685 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt
create mode 100644 drivers/power/supply/ucs1002_power.c
--
2.20.1
^ permalink raw reply [flat|nested] 16+ messages in thread* [PATCH v4 0/3] Driver for UCS1002 2019-04-30 6:45 [PATCH v4 0/3] Driver for UCS1002 Andrey Smirnov @ 2019-04-30 6:45 ` Andrey Smirnov 2019-04-30 6:45 ` [PATCH v4 1/3] power: supply: core: Add POWER_SUPPLY_HEALTH_OVERCURRENT constant Andrey Smirnov ` (2 subsequent siblings) 3 siblings, 0 replies; 16+ messages in thread From: Andrey Smirnov @ 2019-04-30 6:45 UTC (permalink / raw) To: linux-pm Cc: Andrey Smirnov, Chris Healy, Lucas Stach, Fabio Estevam, Guenter Roeck, Sebastian Reichel, Enric Balletbo Serra, linux-kernel Everyone: This small series adds a driver for UCS1002 Programmable USB Port Power Controller with Charger Emulation. See [page] for product page and [datasheet] for device dataseet. Hopefully each individual patch is self explanatory. Note that this series is a revival of the upstreaming effort by Enric Balletbo Serra last version of which can be found at [original-effort] Feedback is welcome! Thanks, Andrey Smirnov Changes since [v3]: - Added a check for negative values to ucs1002_set_usb_type() Changes since [v2]: - Fixed a bug pointed out by Lucas Changes since [v1]: - Moved IRQ trigger specification to DT - Fixed silent error paths in probe() - Dropped error message in ucs1002_set_max_current() - Fixed license mismatch - Changed the driver to configure the chip to BC1.2 CDP by default - Made other small fixes as per feedback for v1 [v3] https://lore.kernel.org/lkml/20190429195349.20335-1-andrew.smirnov@gmail.com [v2] https://lore.kernel.org/lkml/20190429054741.7286-1-andrew.smirnov@gmail.com [v1] https://lore.kernel.org/lkml/20190417084457.28747-1-andrew.smirnov@gmail.com/ [page] https://www.microchip.com/wwwproducts/en/UCS1002-2 [datasheet] https://ww1.microchip.com/downloads/en/DeviceDoc/UCS1002-2%20Data%20Sheet.pdf [original-effort] https://lore.kernel.org/lkml/1460705181-10493-1-git-send-email-enric.balletbo@collabora.com/ Andrey Smirnov (3): power: supply: core: Add POWER_SUPPLY_HEALTH_OVERCURRENT constant power: supply: Add driver for Microchip UCS1002 dt-bindings: power: supply: Add bindings for Microchip UCS1002 .../power/supply/microchip,ucs1002.txt | 27 + drivers/power/supply/Kconfig | 9 + drivers/power/supply/Makefile | 1 + drivers/power/supply/power_supply_sysfs.c | 2 +- drivers/power/supply/ucs1002_power.c | 646 ++++++++++++++++++ include/linux/power_supply.h | 1 + 6 files changed, 685 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt create mode 100644 drivers/power/supply/ucs1002_power.c -- 2.20.1 ^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v4 1/3] power: supply: core: Add POWER_SUPPLY_HEALTH_OVERCURRENT constant 2019-04-30 6:45 [PATCH v4 0/3] Driver for UCS1002 Andrey Smirnov 2019-04-30 6:45 ` Andrey Smirnov @ 2019-04-30 6:45 ` Andrey Smirnov 2019-04-30 6:45 ` Andrey Smirnov 2019-04-30 6:45 ` [PATCH v4 2/3] power: supply: Add driver for Microchip UCS1002 Andrey Smirnov 2019-04-30 6:45 ` [PATCH v4 3/3] dt-bindings: power: supply: Add bindings " Andrey Smirnov 3 siblings, 1 reply; 16+ messages in thread From: Andrey Smirnov @ 2019-04-30 6:45 UTC (permalink / raw) To: linux-pm Cc: Andrey Smirnov, Guenter Roeck, Enric Balletbo Serra, Chris Healy, Lucas Stach, Fabio Estevam, Sebastian Reichel, linux-kernel Add POWER_SUPPLY_HEALTH_OVERCURRENT constant in order to allow singalling overcurrent condition via power supply health information. Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Cc: Enric Balletbo Serra <enric.balletbo@collabora.com> Cc: Chris Healy <cphealy@gmail.com> Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Fabio Estevam <fabio.estevam@nxp.com> Cc: Guenter Roeck <linux@roeck-us.net> Cc: Sebastian Reichel <sre@kernel.org> Cc: linux-kernel@vger.kernel.org Cc: linux-pm@vger.kernel.org --- 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 5358a80d854f..153f4a6ca57c 100644 --- a/drivers/power/supply/power_supply_sysfs.c +++ b/drivers/power/supply/power_supply_sysfs.c @@ -62,7 +62,7 @@ static const char * const power_supply_charge_type_text[] = { static const char * const power_supply_health_text[] = { "Unknown", "Good", "Overheat", "Dead", "Over voltage", "Unspecified failure", "Cold", "Watchdog timer expire", - "Safety timer expire" + "Safety timer expire", "Over current" }; static const char * const power_supply_technology_text[] = { diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 2f9c201a54d1..bdab14c7ca4d 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -57,6 +57,7 @@ enum { POWER_SUPPLY_HEALTH_COLD, POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE, POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE, + POWER_SUPPLY_HEALTH_OVERCURRENT, }; enum { -- 2.20.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v4 1/3] power: supply: core: Add POWER_SUPPLY_HEALTH_OVERCURRENT constant 2019-04-30 6:45 ` [PATCH v4 1/3] power: supply: core: Add POWER_SUPPLY_HEALTH_OVERCURRENT constant Andrey Smirnov @ 2019-04-30 6:45 ` Andrey Smirnov 0 siblings, 0 replies; 16+ messages in thread From: Andrey Smirnov @ 2019-04-30 6:45 UTC (permalink / raw) To: linux-pm Cc: Andrey Smirnov, Guenter Roeck, Enric Balletbo Serra, Chris Healy, Lucas Stach, Fabio Estevam, Sebastian Reichel, linux-kernel Add POWER_SUPPLY_HEALTH_OVERCURRENT constant in order to allow singalling overcurrent condition via power supply health information. Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Cc: Enric Balletbo Serra <enric.balletbo@collabora.com> Cc: Chris Healy <cphealy@gmail.com> Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Fabio Estevam <fabio.estevam@nxp.com> Cc: Guenter Roeck <linux@roeck-us.net> Cc: Sebastian Reichel <sre@kernel.org> Cc: linux-kernel@vger.kernel.org Cc: linux-pm@vger.kernel.org --- 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 5358a80d854f..153f4a6ca57c 100644 --- a/drivers/power/supply/power_supply_sysfs.c +++ b/drivers/power/supply/power_supply_sysfs.c @@ -62,7 +62,7 @@ static const char * const power_supply_charge_type_text[] = { static const char * const power_supply_health_text[] = { "Unknown", "Good", "Overheat", "Dead", "Over voltage", "Unspecified failure", "Cold", "Watchdog timer expire", - "Safety timer expire" + "Safety timer expire", "Over current" }; static const char * const power_supply_technology_text[] = { diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 2f9c201a54d1..bdab14c7ca4d 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -57,6 +57,7 @@ enum { POWER_SUPPLY_HEALTH_COLD, POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE, POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE, + POWER_SUPPLY_HEALTH_OVERCURRENT, }; enum { -- 2.20.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v4 2/3] power: supply: Add driver for Microchip UCS1002 2019-04-30 6:45 [PATCH v4 0/3] Driver for UCS1002 Andrey Smirnov 2019-04-30 6:45 ` Andrey Smirnov 2019-04-30 6:45 ` [PATCH v4 1/3] power: supply: core: Add POWER_SUPPLY_HEALTH_OVERCURRENT constant Andrey Smirnov @ 2019-04-30 6:45 ` Andrey Smirnov 2019-04-30 6:45 ` Andrey Smirnov 2019-04-30 16:10 ` Guenter Roeck 2019-04-30 6:45 ` [PATCH v4 3/3] dt-bindings: power: supply: Add bindings " Andrey Smirnov 3 siblings, 2 replies; 16+ messages in thread From: Andrey Smirnov @ 2019-04-30 6:45 UTC (permalink / raw) To: linux-pm Cc: Andrey Smirnov, Enric Balletbo Serra, Chris Healy, Lucas Stach, Fabio Estevam, Guenter Roeck, Sebastian Reichel, linux-kernel Add driver for Microchip UCS1002 Programmable USB Port Power Controller with Charger Emulation. The driver exposed a power supply device to control/monitor various parameter of the device as well as a regulator to allow controlling VBUS line. Signed-off-by: Enric Balletbo Serra <enric.balletbo@collabora.com> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Cc: Chris Healy <cphealy@gmail.com> Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Fabio Estevam <fabio.estevam@nxp.com> Cc: Guenter Roeck <linux@roeck-us.net> Cc: Sebastian Reichel <sre@kernel.org> Cc: linux-kernel@vger.kernel.org Cc: linux-pm@vger.kernel.org --- drivers/power/supply/Kconfig | 9 + drivers/power/supply/Makefile | 1 + drivers/power/supply/ucs1002_power.c | 646 +++++++++++++++++++++++++++ 3 files changed, 656 insertions(+) create mode 100644 drivers/power/supply/ucs1002_power.c diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index e901b9879e7e..c614c8a196f3 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -660,4 +660,13 @@ config FUEL_GAUGE_SC27XX Say Y here to enable support for fuel gauge with SC27XX PMIC chips. +config CHARGER_UCS1002 + tristate "Microchip UCS1002 USB Port Power Controller" + depends on I2C + depends on OF + select REGMAP_I2C + help + Say Y to enable support for Microchip UCS1002 Programmable + USB Port Power Controller with Charger Emulation. + endif # POWER_SUPPLY diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index b731c2a9b695..c56803a9e4fe 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile @@ -87,3 +87,4 @@ obj-$(CONFIG_AXP288_CHARGER) += axp288_charger.o obj-$(CONFIG_CHARGER_CROS_USBPD) += cros_usbpd-charger.o obj-$(CONFIG_CHARGER_SC2731) += sc2731_charger.o obj-$(CONFIG_FUEL_GAUGE_SC27XX) += sc27xx_fuel_gauge.o +obj-$(CONFIG_CHARGER_UCS1002) += ucs1002_power.o diff --git a/drivers/power/supply/ucs1002_power.c b/drivers/power/supply/ucs1002_power.c new file mode 100644 index 000000000000..d66b4eff9b7a --- /dev/null +++ b/drivers/power/supply/ucs1002_power.c @@ -0,0 +1,646 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Driver for UCS1002 Programmable USB Port Power Controller + * + * Copyright (C) 2019 Zodiac Inflight Innovations + */ +#include <linux/bits.h> +#include <linux/freezer.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/kthread.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_irq.h> +#include <linux/power_supply.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/of_regulator.h> + +/* UCS1002 Registers */ +#define UCS1002_REG_CURRENT_MEASUREMENT 0x00 + +/* + * The Total Accumulated Charge registers store the total accumulated + * charge delivered from the VS source to a portable device. The total + * value is calculated using four registers, from 01h to 04h. The bit + * weighting of the registers is given in mA/hrs. + */ +#define UCS1002_REG_TOTAL_ACC_CHARGE 0x01 + +/* Other Status Register */ +#define UCS1002_REG_OTHER_STATUS 0x0f +# define F_ADET_PIN BIT(4) +# define F_CHG_ACT BIT(3) + +/* Interrupt Status */ +#define UCS1002_REG_INTERRUPT_STATUS 0x10 +# define F_DISCHARGE_ERR BIT(6) +# define F_RESET BIT(5) +# define F_MIN_KEEP_OUT BIT(4) +# define F_TSD BIT(3) +# define F_OVER_VOLT BIT(2) +# define F_BACK_VOLT BIT(1) +# define F_OVER_ILIM BIT(0) + +/* Pin Status Register */ +#define UCS1002_REG_PIN_STATUS 0x14 +# define UCS1002_PWR_STATE_MASK 0x03 +# define F_PWR_EN_PIN BIT(6) +# define F_M2_PIN BIT(5) +# define F_M1_PIN BIT(4) +# define F_EM_EN_PIN BIT(3) +# define F_SEL_PIN BIT(2) +# define F_ACTIVE_MODE_MASK GENMASK(5, 3) +# define F_ACTIVE_MODE_PASSTHROUGH F_M2_PIN +# define F_ACTIVE_MODE_DEDICATED F_EM_EN_PIN +# define F_ACTIVE_MODE_BC12_DCP (F_M2_PIN | F_EM_EN_PIN) +# define F_ACTIVE_MODE_BC12_SDP F_M1_PIN +# define F_ACTIVE_MODE_BC12_CDP (F_M1_PIN | F_M2_PIN | F_EM_EN_PIN) + +/* General Configuration Register */ +#define UCS1002_REG_GENERAL_CFG 0x15 +# define F_RATION_EN BIT(3) + +/* Emulation Configuration Register */ +#define UCS1002_REG_EMU_CFG 0x16 + +/* Switch Configuration Register */ +#define UCS1002_REG_SWITCH_CFG 0x17 +# define F_PIN_IGNORE BIT(7) +# define F_EM_EN_SET BIT(5) +# define F_M2_SET BIT(4) +# define F_M1_SET BIT(3) +# define F_S0_SET BIT(2) +# define F_PWR_EN_SET BIT(1) +# define F_LATCH_SET BIT(0) +# define V_SET_ACTIVE_MODE_MASK GENMASK(5, 3) +# define V_SET_ACTIVE_MODE_PASSTHROUGH F_M2_SET +# define V_SET_ACTIVE_MODE_DEDICATED F_EM_EN_SET +# define V_SET_ACTIVE_MODE_BC12_DCP (F_M2_SET | F_EM_EN_SET) +# define V_SET_ACTIVE_MODE_BC12_SDP F_M1_SET +# define V_SET_ACTIVE_MODE_BC12_CDP (F_M1_SET | F_M2_SET | F_EM_EN_SET) + +/* Current Limit Register */ +#define UCS1002_REG_ILIMIT 0x19 +# define UCS1002_ILIM_SW_MASK GENMASK(3, 0) + +/* Product ID */ +#define UCS1002_REG_PRODUCT_ID 0xfd +# define UCS1002_PRODUCT_ID 0x4e + +/* Manufacture name */ +#define UCS1002_MANUFACTURER "SMSC" + +struct ucs1002_info { + struct power_supply *charger; + struct i2c_client *client; + struct regmap *regmap; + struct regulator_desc *regulator_descriptor; + bool present; +}; + +static enum power_supply_property ucs1002_props[] = { + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_CHARGE_NOW, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_CURRENT_MAX, + POWER_SUPPLY_PROP_PRESENT, /* the presence of PED */ + POWER_SUPPLY_PROP_MANUFACTURER, + POWER_SUPPLY_PROP_USB_TYPE, + POWER_SUPPLY_PROP_HEALTH, +}; + +static int ucs1002_get_online(struct ucs1002_info *info, + union power_supply_propval *val) +{ + unsigned int reg; + int ret; + + ret = regmap_read(info->regmap, UCS1002_REG_OTHER_STATUS, ®); + if (ret) + return ret; + + val->intval = !!(reg & F_CHG_ACT); + + return 0; +} + +static int ucs1002_get_charge(struct ucs1002_info *info, + union power_supply_propval *val) +{ + /* + * To fit within 32 bits some values are rounded (uA/h) + * + * For Total Accumulated Charge Middle Low Byte register, addr + * 03h, byte 2 + * + * B0: 0.01084 mA/h rounded to 11 uA/h + * B1: 0.02169 mA/h rounded to 22 uA/h + * B2: 0.04340 mA/h rounded to 43 uA/h + * B3: 0.08676 mA/h rounded to 87 uA/h + * B4: 0.17350 mA/h rounded to 173 uÁ/h + * + * For Total Accumulated Charge Low Byte register, addr 04h, + * byte 3 + * + * B6: 0.00271 mA/h rounded to 3 uA/h + * B7: 0.005422 mA/h rounded to 5 uA/h + */ + static const int bit_weights_uAh[BITS_PER_TYPE(u32)] = { + /* + * Bit corresponding to low byte (offset 0x04) + * B0 B1 B2 B3 B4 B5 B6 B7 + */ + 0, 0, 0, 0, 0, 0, 3, 5, + /* + * Bit corresponding to middle low byte (offset 0x03) + * B0 B1 B2 B3 B4 B5 B6 B7 + */ + 11, 22, 43, 87, 173, 347, 694, 1388, + /* + * Bit corresponding to middle high byte (offset 0x02) + * B0 B1 B2 B3 B4 B5 B6 B7 + */ + 2776, 5552, 11105, 22210, 44420, 88840, 177700, 355400, + /* + * Bit corresponding to high byte (offset 0x01) + * B0 B1 B2 B3 B4 B5 B6 B7 + */ + 710700, 1421000, 2843000, 5685000, 11371000, 22742000, + 45484000, 90968000, + }; + unsigned long total_acc_charger; + unsigned int reg; + int i, ret; + + ret = regmap_bulk_read(info->regmap, UCS1002_REG_TOTAL_ACC_CHARGE, + ®, sizeof(u32)); + if (ret) + return ret; + + total_acc_charger = be32_to_cpu(reg); /* BE as per offsets above */ + val->intval = 0; + + for_each_set_bit(i, &total_acc_charger, ARRAY_SIZE(bit_weights_uAh)) + val->intval += bit_weights_uAh[i]; + + return 0; +} + +static int ucs1002_get_current(struct ucs1002_info *info, + union power_supply_propval *val) +{ + /* + * The Current Measurement register stores the measured + * current value delivered to the portable device. The range + * is from 9.76 mA to 2.5 A. + */ + static const int bit_weights_uA[BITS_PER_TYPE(u8)] = { + 9760, 19500, 39000, 78100, 156200, 312300, 624600, 1249300, + }; + unsigned long current_measurement; + unsigned int reg; + int i, ret; + + ret = regmap_read(info->regmap, UCS1002_REG_CURRENT_MEASUREMENT, ®); + if (ret) + return ret; + + current_measurement = reg; + val->intval = 0; + + for_each_set_bit(i, ¤t_measurement, ARRAY_SIZE(bit_weights_uA)) + val->intval += bit_weights_uA[i]; + + return 0; +} + +/* + * The Current Limit register stores the maximum current used by the + * port switch. The range is from 500mA to 2.5 A. + */ +static const u32 ucs1002_current_limit_uA[] = { + 500000, 900000, 1000000, 1200000, 1500000, 1800000, 2000000, 2500000, +}; + +static int ucs1002_get_max_current(struct ucs1002_info *info, + union power_supply_propval *val) +{ + unsigned int reg; + int ret; + + ret = regmap_read(info->regmap, UCS1002_REG_ILIMIT, ®); + if (ret) + return ret; + + val->intval = ucs1002_current_limit_uA[reg & UCS1002_ILIM_SW_MASK]; + + return 0; +} + +static int ucs1002_set_max_current(struct ucs1002_info *info, u32 val) +{ + unsigned int reg; + int ret, idx; + + for (idx = 0; idx < ARRAY_SIZE(ucs1002_current_limit_uA); idx++) { + if (val == ucs1002_current_limit_uA[idx]) + break; + } + + if (idx == ARRAY_SIZE(ucs1002_current_limit_uA)) + return -EINVAL; + + ret = regmap_write(info->regmap, UCS1002_REG_ILIMIT, idx); + if (ret) + return ret; + /* + * Any current limit setting exceeding the one set via ILIM + * pin will be rejected, so we read out freshly changed limit + * to make sure that it took effect. + */ + ret = regmap_read(info->regmap, UCS1002_REG_ILIMIT, ®); + if (ret) + return ret; + + if (reg != idx) + return -EINVAL; + + return 0; +} + +static enum power_supply_usb_type ucs1002_usb_types[] = { + POWER_SUPPLY_USB_TYPE_PD, + POWER_SUPPLY_USB_TYPE_SDP, + POWER_SUPPLY_USB_TYPE_DCP, + POWER_SUPPLY_USB_TYPE_CDP, + POWER_SUPPLY_USB_TYPE_UNKNOWN, +}; + +static int ucs1002_set_usb_type(struct ucs1002_info *info, int val) +{ + unsigned int mode; + + if (val < 0 || val >= ARRAY_SIZE(ucs1002_usb_types)) + return -EINVAL; + + switch (ucs1002_usb_types[val]) { + case POWER_SUPPLY_USB_TYPE_PD: + mode = V_SET_ACTIVE_MODE_DEDICATED; + break; + case POWER_SUPPLY_USB_TYPE_SDP: + mode = V_SET_ACTIVE_MODE_BC12_SDP; + break; + case POWER_SUPPLY_USB_TYPE_DCP: + mode = V_SET_ACTIVE_MODE_BC12_DCP; + break; + case POWER_SUPPLY_USB_TYPE_CDP: + mode = V_SET_ACTIVE_MODE_BC12_CDP; + break; + default: + return -EINVAL; + } + + return regmap_update_bits(info->regmap, UCS1002_REG_SWITCH_CFG, + V_SET_ACTIVE_MODE_MASK, mode); +} + +static int ucs1002_get_usb_type(struct ucs1002_info *info, + union power_supply_propval *val) +{ + enum power_supply_usb_type type; + unsigned int reg; + int ret; + + ret = regmap_read(info->regmap, UCS1002_REG_PIN_STATUS, ®); + if (ret) + return ret; + + switch (reg & F_ACTIVE_MODE_MASK) { + default: + type = POWER_SUPPLY_USB_TYPE_UNKNOWN; + break; + case F_ACTIVE_MODE_DEDICATED: + type = POWER_SUPPLY_USB_TYPE_PD; + break; + case F_ACTIVE_MODE_BC12_SDP: + type = POWER_SUPPLY_USB_TYPE_SDP; + break; + case F_ACTIVE_MODE_BC12_DCP: + type = POWER_SUPPLY_USB_TYPE_DCP; + break; + case F_ACTIVE_MODE_BC12_CDP: + type = POWER_SUPPLY_USB_TYPE_CDP; + break; + }; + + val->intval = type; + + return 0; +} + +static int ucs1002_get_health(struct ucs1002_info *info, + union power_supply_propval *val) +{ + unsigned int reg; + int ret, health; + + ret = regmap_read(info->regmap, UCS1002_REG_INTERRUPT_STATUS, ®); + if (ret) + return ret; + + if (reg & F_TSD) + health = POWER_SUPPLY_HEALTH_OVERHEAT; + else if (reg & (F_OVER_VOLT | F_BACK_VOLT)) + health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; + else if (reg & F_OVER_ILIM) + health = POWER_SUPPLY_HEALTH_OVERCURRENT; + else if (reg & (F_DISCHARGE_ERR | F_MIN_KEEP_OUT)) + health = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; + else + health = POWER_SUPPLY_HEALTH_GOOD; + + val->intval = health; + + return 0; +} + +static int ucs1002_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct ucs1002_info *info = power_supply_get_drvdata(psy); + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + return ucs1002_get_online(info, val); + case POWER_SUPPLY_PROP_CHARGE_NOW: + return ucs1002_get_charge(info, val); + case POWER_SUPPLY_PROP_CURRENT_NOW: + return ucs1002_get_current(info, val); + case POWER_SUPPLY_PROP_CURRENT_MAX: + return ucs1002_get_max_current(info, val); + case POWER_SUPPLY_PROP_USB_TYPE: + return ucs1002_get_usb_type(info, val); + case POWER_SUPPLY_PROP_HEALTH: + return ucs1002_get_health(info, val); + case POWER_SUPPLY_PROP_PRESENT: + val->intval = info->present; + return 0; + case POWER_SUPPLY_PROP_MANUFACTURER: + val->strval = UCS1002_MANUFACTURER; + return 0; + default: + return -EINVAL; + } +} + +static int ucs1002_set_property(struct power_supply *psy, + enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct ucs1002_info *info = power_supply_get_drvdata(psy); + + switch (psp) { + case POWER_SUPPLY_PROP_CURRENT_MAX: + return ucs1002_set_max_current(info, val->intval); + case POWER_SUPPLY_PROP_USB_TYPE: + return ucs1002_set_usb_type(info, val->intval); + default: + return -EINVAL; + } +} + +static int ucs1002_property_is_writeable(struct power_supply *psy, + enum power_supply_property psp) +{ + switch (psp) { + case POWER_SUPPLY_PROP_CURRENT_MAX: + case POWER_SUPPLY_PROP_USB_TYPE: + return true; + default: + return false; + } +} + +static const struct power_supply_desc ucs1002_charger_desc = { + .name = "ucs1002", + .type = POWER_SUPPLY_TYPE_USB, + .usb_types = ucs1002_usb_types, + .num_usb_types = ARRAY_SIZE(ucs1002_usb_types), + .get_property = ucs1002_get_property, + .set_property = ucs1002_set_property, + .property_is_writeable = ucs1002_property_is_writeable, + .properties = ucs1002_props, + .num_properties = ARRAY_SIZE(ucs1002_props), +}; + +static irqreturn_t ucs1002_charger_irq(int irq, void *data) +{ + int ret, regval; + bool present; + struct ucs1002_info *info = data; + + present = info->present; + + ret = regmap_read(info->regmap, UCS1002_REG_OTHER_STATUS, ®val); + if (ret) + return IRQ_HANDLED; + + /* update attached status */ + info->present = regval & F_ADET_PIN; + + /* notify the change */ + if (present != info->present) + power_supply_changed(info->charger); + + return IRQ_HANDLED; +} + +static irqreturn_t ucs1002_alert_irq(int irq, void *data) +{ + struct ucs1002_info *info = data; + + power_supply_changed(info->charger); + + return IRQ_HANDLED; +} + +static const struct regulator_ops ucs1002_regulator_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, +}; + +static const struct regulator_desc ucs1002_regulator_descriptor = { + .name = "ucs1002-vbus", + .ops = &ucs1002_regulator_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .enable_reg = UCS1002_REG_SWITCH_CFG, + .enable_mask = F_PWR_EN_SET, + .enable_val = F_PWR_EN_SET, + .fixed_uV = 5000000, + .n_voltages = 1, +}; + +static int ucs1002_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct device *dev = &client->dev; + struct power_supply_config charger_config = {}; + const struct regmap_config regmap_config = { + .reg_bits = 8, + .val_bits = 8, + }; + struct regulator_config regulator_config = {}; + int irq_a_det, irq_alert, ret; + struct regulator_dev *rdev; + struct ucs1002_info *info; + unsigned int regval; + + info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->regmap = devm_regmap_init_i2c(client, ®map_config); + ret = PTR_ERR_OR_ZERO(info->charger); + if (ret) { + dev_err(dev, "Regmap initialization failed: %d\n", ret); + return ret; + } + + info->client = client; + + irq_a_det = of_irq_get_byname(dev->of_node, "a_det"); + irq_alert = of_irq_get_byname(dev->of_node, "alert"); + + charger_config.of_node = dev->of_node; + charger_config.drv_data = info; + + ret = regmap_read(info->regmap, UCS1002_REG_PRODUCT_ID, ®val); + if (ret) { + dev_err(dev, "Failed to read product ID: %d\n", ret); + return ret; + } + + if (regval != UCS1002_PRODUCT_ID) { + dev_err(dev, + "Product ID does not match (0x%02x != 0x%02x)\n", + regval, UCS1002_PRODUCT_ID); + return -ENODEV; + } + + /* Enable charge rationing by default */ + ret = regmap_update_bits(info->regmap, UCS1002_REG_GENERAL_CFG, + F_RATION_EN, F_RATION_EN); + if (ret) { + dev_err(dev, "Failed to read general config: %d\n", ret); + return ret; + } + + /* + * Ignore the M1, M2, PWR_EN, and EM_EN pin states. Set active + * mode selection to BC1.2 CDP. + */ + ret = regmap_update_bits(info->regmap, UCS1002_REG_SWITCH_CFG, + V_SET_ACTIVE_MODE_MASK | F_PIN_IGNORE, + V_SET_ACTIVE_MODE_BC12_CDP | F_PIN_IGNORE); + if (ret) { + dev_err(dev, "Failed to configure default mode: %d\n", ret); + return ret; + } + /* + * Be safe and set initial current limit to 500mA + */ + ret = ucs1002_set_max_current(info, 500000); + if (ret) { + dev_err(dev, "Failed to set max current default: %d\n", ret); + return ret; + } + + info->charger = devm_power_supply_register(dev, &ucs1002_charger_desc, + &charger_config); + ret = PTR_ERR_OR_ZERO(info->charger); + if (ret) { + dev_err(dev, "Failed to register power supply: %d\n", ret); + return ret; + } + + ret = regmap_read(info->regmap, UCS1002_REG_PIN_STATUS, ®val); + if (ret) { + dev_err(dev, "Failed to read pin status: %d\n", ret); + return ret; + } + + info->regulator_descriptor = + devm_kmemdup(dev, &ucs1002_regulator_descriptor, + sizeof(ucs1002_regulator_descriptor), + GFP_KERNEL); + if (!info->regulator_descriptor) + return -ENOMEM; + + info->regulator_descriptor->enable_is_inverted = !(regval & F_SEL_PIN); + + regulator_config.dev = dev; + regulator_config.of_node = dev->of_node; + regulator_config.regmap = info->regmap; + + rdev = devm_regulator_register(dev, info->regulator_descriptor, + ®ulator_config); + ret = PTR_ERR_OR_ZERO(info->charger); + if (ret) { + dev_err(dev, "Failed to register VBUS regulator: %d\n", ret); + return ret; + } + + if (irq_a_det > 0) { + ret = devm_request_threaded_irq(dev, irq_a_det, NULL, + ucs1002_charger_irq, + IRQF_ONESHOT, + "ucs1002-a_det", info); + if (ret) { + dev_err(dev, "Failed to request A_DET threaded irq: %d\n", + ret); + return ret; + } + } + + if (irq_alert > 0) { + ret = devm_request_threaded_irq(dev, irq_alert, NULL, + ucs1002_alert_irq, + IRQF_ONESHOT, + "ucs1002-alert", info); + if (ret) { + dev_err(dev, "Failed to request ALERT threaded irq: %d\n", + ret); + return ret; + } + } + + return 0; +} + +static const struct of_device_id ucs1002_of_match[] = { + { .compatible = "microchip,ucs1002", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, ucs1002_of_match); + +static struct i2c_driver ucs1002_driver = { + .driver = { + .name = "ucs1002", + .of_match_table = ucs1002_of_match, + }, + .probe = ucs1002_probe, +}; +module_i2c_driver(ucs1002_driver); + +MODULE_DESCRIPTION("Microchip UCS1002 Programmable USB Port Power Controller"); +MODULE_AUTHOR("Enric Balletbo Serra <enric.balletbo@collabora.com>"); +MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>"); +MODULE_LICENSE("GPL"); -- 2.20.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v4 2/3] power: supply: Add driver for Microchip UCS1002 2019-04-30 6:45 ` [PATCH v4 2/3] power: supply: Add driver for Microchip UCS1002 Andrey Smirnov @ 2019-04-30 6:45 ` Andrey Smirnov 2019-04-30 16:10 ` Guenter Roeck 1 sibling, 0 replies; 16+ messages in thread From: Andrey Smirnov @ 2019-04-30 6:45 UTC (permalink / raw) To: linux-pm Cc: Andrey Smirnov, Enric Balletbo Serra, Chris Healy, Lucas Stach, Fabio Estevam, Guenter Roeck, Sebastian Reichel, linux-kernel Add driver for Microchip UCS1002 Programmable USB Port Power Controller with Charger Emulation. The driver exposed a power supply device to control/monitor various parameter of the device as well as a regulator to allow controlling VBUS line. Signed-off-by: Enric Balletbo Serra <enric.balletbo@collabora.com> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Cc: Chris Healy <cphealy@gmail.com> Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Fabio Estevam <fabio.estevam@nxp.com> Cc: Guenter Roeck <linux@roeck-us.net> Cc: Sebastian Reichel <sre@kernel.org> Cc: linux-kernel@vger.kernel.org Cc: linux-pm@vger.kernel.org --- drivers/power/supply/Kconfig | 9 + drivers/power/supply/Makefile | 1 + drivers/power/supply/ucs1002_power.c | 646 +++++++++++++++++++++++++++ 3 files changed, 656 insertions(+) create mode 100644 drivers/power/supply/ucs1002_power.c diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index e901b9879e7e..c614c8a196f3 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -660,4 +660,13 @@ config FUEL_GAUGE_SC27XX Say Y here to enable support for fuel gauge with SC27XX PMIC chips. +config CHARGER_UCS1002 + tristate "Microchip UCS1002 USB Port Power Controller" + depends on I2C + depends on OF + select REGMAP_I2C + help + Say Y to enable support for Microchip UCS1002 Programmable + USB Port Power Controller with Charger Emulation. + endif # POWER_SUPPLY diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile index b731c2a9b695..c56803a9e4fe 100644 --- a/drivers/power/supply/Makefile +++ b/drivers/power/supply/Makefile @@ -87,3 +87,4 @@ obj-$(CONFIG_AXP288_CHARGER) += axp288_charger.o obj-$(CONFIG_CHARGER_CROS_USBPD) += cros_usbpd-charger.o obj-$(CONFIG_CHARGER_SC2731) += sc2731_charger.o obj-$(CONFIG_FUEL_GAUGE_SC27XX) += sc27xx_fuel_gauge.o +obj-$(CONFIG_CHARGER_UCS1002) += ucs1002_power.o diff --git a/drivers/power/supply/ucs1002_power.c b/drivers/power/supply/ucs1002_power.c new file mode 100644 index 000000000000..d66b4eff9b7a --- /dev/null +++ b/drivers/power/supply/ucs1002_power.c @@ -0,0 +1,646 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Driver for UCS1002 Programmable USB Port Power Controller + * + * Copyright (C) 2019 Zodiac Inflight Innovations + */ +#include <linux/bits.h> +#include <linux/freezer.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/kthread.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_irq.h> +#include <linux/power_supply.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/of_regulator.h> + +/* UCS1002 Registers */ +#define UCS1002_REG_CURRENT_MEASUREMENT 0x00 + +/* + * The Total Accumulated Charge registers store the total accumulated + * charge delivered from the VS source to a portable device. The total + * value is calculated using four registers, from 01h to 04h. The bit + * weighting of the registers is given in mA/hrs. + */ +#define UCS1002_REG_TOTAL_ACC_CHARGE 0x01 + +/* Other Status Register */ +#define UCS1002_REG_OTHER_STATUS 0x0f +# define F_ADET_PIN BIT(4) +# define F_CHG_ACT BIT(3) + +/* Interrupt Status */ +#define UCS1002_REG_INTERRUPT_STATUS 0x10 +# define F_DISCHARGE_ERR BIT(6) +# define F_RESET BIT(5) +# define F_MIN_KEEP_OUT BIT(4) +# define F_TSD BIT(3) +# define F_OVER_VOLT BIT(2) +# define F_BACK_VOLT BIT(1) +# define F_OVER_ILIM BIT(0) + +/* Pin Status Register */ +#define UCS1002_REG_PIN_STATUS 0x14 +# define UCS1002_PWR_STATE_MASK 0x03 +# define F_PWR_EN_PIN BIT(6) +# define F_M2_PIN BIT(5) +# define F_M1_PIN BIT(4) +# define F_EM_EN_PIN BIT(3) +# define F_SEL_PIN BIT(2) +# define F_ACTIVE_MODE_MASK GENMASK(5, 3) +# define F_ACTIVE_MODE_PASSTHROUGH F_M2_PIN +# define F_ACTIVE_MODE_DEDICATED F_EM_EN_PIN +# define F_ACTIVE_MODE_BC12_DCP (F_M2_PIN | F_EM_EN_PIN) +# define F_ACTIVE_MODE_BC12_SDP F_M1_PIN +# define F_ACTIVE_MODE_BC12_CDP (F_M1_PIN | F_M2_PIN | F_EM_EN_PIN) + +/* General Configuration Register */ +#define UCS1002_REG_GENERAL_CFG 0x15 +# define F_RATION_EN BIT(3) + +/* Emulation Configuration Register */ +#define UCS1002_REG_EMU_CFG 0x16 + +/* Switch Configuration Register */ +#define UCS1002_REG_SWITCH_CFG 0x17 +# define F_PIN_IGNORE BIT(7) +# define F_EM_EN_SET BIT(5) +# define F_M2_SET BIT(4) +# define F_M1_SET BIT(3) +# define F_S0_SET BIT(2) +# define F_PWR_EN_SET BIT(1) +# define F_LATCH_SET BIT(0) +# define V_SET_ACTIVE_MODE_MASK GENMASK(5, 3) +# define V_SET_ACTIVE_MODE_PASSTHROUGH F_M2_SET +# define V_SET_ACTIVE_MODE_DEDICATED F_EM_EN_SET +# define V_SET_ACTIVE_MODE_BC12_DCP (F_M2_SET | F_EM_EN_SET) +# define V_SET_ACTIVE_MODE_BC12_SDP F_M1_SET +# define V_SET_ACTIVE_MODE_BC12_CDP (F_M1_SET | F_M2_SET | F_EM_EN_SET) + +/* Current Limit Register */ +#define UCS1002_REG_ILIMIT 0x19 +# define UCS1002_ILIM_SW_MASK GENMASK(3, 0) + +/* Product ID */ +#define UCS1002_REG_PRODUCT_ID 0xfd +# define UCS1002_PRODUCT_ID 0x4e + +/* Manufacture name */ +#define UCS1002_MANUFACTURER "SMSC" + +struct ucs1002_info { + struct power_supply *charger; + struct i2c_client *client; + struct regmap *regmap; + struct regulator_desc *regulator_descriptor; + bool present; +}; + +static enum power_supply_property ucs1002_props[] = { + POWER_SUPPLY_PROP_ONLINE, + POWER_SUPPLY_PROP_CHARGE_NOW, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_CURRENT_MAX, + POWER_SUPPLY_PROP_PRESENT, /* the presence of PED */ + POWER_SUPPLY_PROP_MANUFACTURER, + POWER_SUPPLY_PROP_USB_TYPE, + POWER_SUPPLY_PROP_HEALTH, +}; + +static int ucs1002_get_online(struct ucs1002_info *info, + union power_supply_propval *val) +{ + unsigned int reg; + int ret; + + ret = regmap_read(info->regmap, UCS1002_REG_OTHER_STATUS, ®); + if (ret) + return ret; + + val->intval = !!(reg & F_CHG_ACT); + + return 0; +} + +static int ucs1002_get_charge(struct ucs1002_info *info, + union power_supply_propval *val) +{ + /* + * To fit within 32 bits some values are rounded (uA/h) + * + * For Total Accumulated Charge Middle Low Byte register, addr + * 03h, byte 2 + * + * B0: 0.01084 mA/h rounded to 11 uA/h + * B1: 0.02169 mA/h rounded to 22 uA/h + * B2: 0.04340 mA/h rounded to 43 uA/h + * B3: 0.08676 mA/h rounded to 87 uA/h + * B4: 0.17350 mA/h rounded to 173 uÁ/h + * + * For Total Accumulated Charge Low Byte register, addr 04h, + * byte 3 + * + * B6: 0.00271 mA/h rounded to 3 uA/h + * B7: 0.005422 mA/h rounded to 5 uA/h + */ + static const int bit_weights_uAh[BITS_PER_TYPE(u32)] = { + /* + * Bit corresponding to low byte (offset 0x04) + * B0 B1 B2 B3 B4 B5 B6 B7 + */ + 0, 0, 0, 0, 0, 0, 3, 5, + /* + * Bit corresponding to middle low byte (offset 0x03) + * B0 B1 B2 B3 B4 B5 B6 B7 + */ + 11, 22, 43, 87, 173, 347, 694, 1388, + /* + * Bit corresponding to middle high byte (offset 0x02) + * B0 B1 B2 B3 B4 B5 B6 B7 + */ + 2776, 5552, 11105, 22210, 44420, 88840, 177700, 355400, + /* + * Bit corresponding to high byte (offset 0x01) + * B0 B1 B2 B3 B4 B5 B6 B7 + */ + 710700, 1421000, 2843000, 5685000, 11371000, 22742000, + 45484000, 90968000, + }; + unsigned long total_acc_charger; + unsigned int reg; + int i, ret; + + ret = regmap_bulk_read(info->regmap, UCS1002_REG_TOTAL_ACC_CHARGE, + ®, sizeof(u32)); + if (ret) + return ret; + + total_acc_charger = be32_to_cpu(reg); /* BE as per offsets above */ + val->intval = 0; + + for_each_set_bit(i, &total_acc_charger, ARRAY_SIZE(bit_weights_uAh)) + val->intval += bit_weights_uAh[i]; + + return 0; +} + +static int ucs1002_get_current(struct ucs1002_info *info, + union power_supply_propval *val) +{ + /* + * The Current Measurement register stores the measured + * current value delivered to the portable device. The range + * is from 9.76 mA to 2.5 A. + */ + static const int bit_weights_uA[BITS_PER_TYPE(u8)] = { + 9760, 19500, 39000, 78100, 156200, 312300, 624600, 1249300, + }; + unsigned long current_measurement; + unsigned int reg; + int i, ret; + + ret = regmap_read(info->regmap, UCS1002_REG_CURRENT_MEASUREMENT, ®); + if (ret) + return ret; + + current_measurement = reg; + val->intval = 0; + + for_each_set_bit(i, ¤t_measurement, ARRAY_SIZE(bit_weights_uA)) + val->intval += bit_weights_uA[i]; + + return 0; +} + +/* + * The Current Limit register stores the maximum current used by the + * port switch. The range is from 500mA to 2.5 A. + */ +static const u32 ucs1002_current_limit_uA[] = { + 500000, 900000, 1000000, 1200000, 1500000, 1800000, 2000000, 2500000, +}; + +static int ucs1002_get_max_current(struct ucs1002_info *info, + union power_supply_propval *val) +{ + unsigned int reg; + int ret; + + ret = regmap_read(info->regmap, UCS1002_REG_ILIMIT, ®); + if (ret) + return ret; + + val->intval = ucs1002_current_limit_uA[reg & UCS1002_ILIM_SW_MASK]; + + return 0; +} + +static int ucs1002_set_max_current(struct ucs1002_info *info, u32 val) +{ + unsigned int reg; + int ret, idx; + + for (idx = 0; idx < ARRAY_SIZE(ucs1002_current_limit_uA); idx++) { + if (val == ucs1002_current_limit_uA[idx]) + break; + } + + if (idx == ARRAY_SIZE(ucs1002_current_limit_uA)) + return -EINVAL; + + ret = regmap_write(info->regmap, UCS1002_REG_ILIMIT, idx); + if (ret) + return ret; + /* + * Any current limit setting exceeding the one set via ILIM + * pin will be rejected, so we read out freshly changed limit + * to make sure that it took effect. + */ + ret = regmap_read(info->regmap, UCS1002_REG_ILIMIT, ®); + if (ret) + return ret; + + if (reg != idx) + return -EINVAL; + + return 0; +} + +static enum power_supply_usb_type ucs1002_usb_types[] = { + POWER_SUPPLY_USB_TYPE_PD, + POWER_SUPPLY_USB_TYPE_SDP, + POWER_SUPPLY_USB_TYPE_DCP, + POWER_SUPPLY_USB_TYPE_CDP, + POWER_SUPPLY_USB_TYPE_UNKNOWN, +}; + +static int ucs1002_set_usb_type(struct ucs1002_info *info, int val) +{ + unsigned int mode; + + if (val < 0 || val >= ARRAY_SIZE(ucs1002_usb_types)) + return -EINVAL; + + switch (ucs1002_usb_types[val]) { + case POWER_SUPPLY_USB_TYPE_PD: + mode = V_SET_ACTIVE_MODE_DEDICATED; + break; + case POWER_SUPPLY_USB_TYPE_SDP: + mode = V_SET_ACTIVE_MODE_BC12_SDP; + break; + case POWER_SUPPLY_USB_TYPE_DCP: + mode = V_SET_ACTIVE_MODE_BC12_DCP; + break; + case POWER_SUPPLY_USB_TYPE_CDP: + mode = V_SET_ACTIVE_MODE_BC12_CDP; + break; + default: + return -EINVAL; + } + + return regmap_update_bits(info->regmap, UCS1002_REG_SWITCH_CFG, + V_SET_ACTIVE_MODE_MASK, mode); +} + +static int ucs1002_get_usb_type(struct ucs1002_info *info, + union power_supply_propval *val) +{ + enum power_supply_usb_type type; + unsigned int reg; + int ret; + + ret = regmap_read(info->regmap, UCS1002_REG_PIN_STATUS, ®); + if (ret) + return ret; + + switch (reg & F_ACTIVE_MODE_MASK) { + default: + type = POWER_SUPPLY_USB_TYPE_UNKNOWN; + break; + case F_ACTIVE_MODE_DEDICATED: + type = POWER_SUPPLY_USB_TYPE_PD; + break; + case F_ACTIVE_MODE_BC12_SDP: + type = POWER_SUPPLY_USB_TYPE_SDP; + break; + case F_ACTIVE_MODE_BC12_DCP: + type = POWER_SUPPLY_USB_TYPE_DCP; + break; + case F_ACTIVE_MODE_BC12_CDP: + type = POWER_SUPPLY_USB_TYPE_CDP; + break; + }; + + val->intval = type; + + return 0; +} + +static int ucs1002_get_health(struct ucs1002_info *info, + union power_supply_propval *val) +{ + unsigned int reg; + int ret, health; + + ret = regmap_read(info->regmap, UCS1002_REG_INTERRUPT_STATUS, ®); + if (ret) + return ret; + + if (reg & F_TSD) + health = POWER_SUPPLY_HEALTH_OVERHEAT; + else if (reg & (F_OVER_VOLT | F_BACK_VOLT)) + health = POWER_SUPPLY_HEALTH_OVERVOLTAGE; + else if (reg & F_OVER_ILIM) + health = POWER_SUPPLY_HEALTH_OVERCURRENT; + else if (reg & (F_DISCHARGE_ERR | F_MIN_KEEP_OUT)) + health = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; + else + health = POWER_SUPPLY_HEALTH_GOOD; + + val->intval = health; + + return 0; +} + +static int ucs1002_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct ucs1002_info *info = power_supply_get_drvdata(psy); + + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + return ucs1002_get_online(info, val); + case POWER_SUPPLY_PROP_CHARGE_NOW: + return ucs1002_get_charge(info, val); + case POWER_SUPPLY_PROP_CURRENT_NOW: + return ucs1002_get_current(info, val); + case POWER_SUPPLY_PROP_CURRENT_MAX: + return ucs1002_get_max_current(info, val); + case POWER_SUPPLY_PROP_USB_TYPE: + return ucs1002_get_usb_type(info, val); + case POWER_SUPPLY_PROP_HEALTH: + return ucs1002_get_health(info, val); + case POWER_SUPPLY_PROP_PRESENT: + val->intval = info->present; + return 0; + case POWER_SUPPLY_PROP_MANUFACTURER: + val->strval = UCS1002_MANUFACTURER; + return 0; + default: + return -EINVAL; + } +} + +static int ucs1002_set_property(struct power_supply *psy, + enum power_supply_property psp, + const union power_supply_propval *val) +{ + struct ucs1002_info *info = power_supply_get_drvdata(psy); + + switch (psp) { + case POWER_SUPPLY_PROP_CURRENT_MAX: + return ucs1002_set_max_current(info, val->intval); + case POWER_SUPPLY_PROP_USB_TYPE: + return ucs1002_set_usb_type(info, val->intval); + default: + return -EINVAL; + } +} + +static int ucs1002_property_is_writeable(struct power_supply *psy, + enum power_supply_property psp) +{ + switch (psp) { + case POWER_SUPPLY_PROP_CURRENT_MAX: + case POWER_SUPPLY_PROP_USB_TYPE: + return true; + default: + return false; + } +} + +static const struct power_supply_desc ucs1002_charger_desc = { + .name = "ucs1002", + .type = POWER_SUPPLY_TYPE_USB, + .usb_types = ucs1002_usb_types, + .num_usb_types = ARRAY_SIZE(ucs1002_usb_types), + .get_property = ucs1002_get_property, + .set_property = ucs1002_set_property, + .property_is_writeable = ucs1002_property_is_writeable, + .properties = ucs1002_props, + .num_properties = ARRAY_SIZE(ucs1002_props), +}; + +static irqreturn_t ucs1002_charger_irq(int irq, void *data) +{ + int ret, regval; + bool present; + struct ucs1002_info *info = data; + + present = info->present; + + ret = regmap_read(info->regmap, UCS1002_REG_OTHER_STATUS, ®val); + if (ret) + return IRQ_HANDLED; + + /* update attached status */ + info->present = regval & F_ADET_PIN; + + /* notify the change */ + if (present != info->present) + power_supply_changed(info->charger); + + return IRQ_HANDLED; +} + +static irqreturn_t ucs1002_alert_irq(int irq, void *data) +{ + struct ucs1002_info *info = data; + + power_supply_changed(info->charger); + + return IRQ_HANDLED; +} + +static const struct regulator_ops ucs1002_regulator_ops = { + .is_enabled = regulator_is_enabled_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, +}; + +static const struct regulator_desc ucs1002_regulator_descriptor = { + .name = "ucs1002-vbus", + .ops = &ucs1002_regulator_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .enable_reg = UCS1002_REG_SWITCH_CFG, + .enable_mask = F_PWR_EN_SET, + .enable_val = F_PWR_EN_SET, + .fixed_uV = 5000000, + .n_voltages = 1, +}; + +static int ucs1002_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct device *dev = &client->dev; + struct power_supply_config charger_config = {}; + const struct regmap_config regmap_config = { + .reg_bits = 8, + .val_bits = 8, + }; + struct regulator_config regulator_config = {}; + int irq_a_det, irq_alert, ret; + struct regulator_dev *rdev; + struct ucs1002_info *info; + unsigned int regval; + + info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->regmap = devm_regmap_init_i2c(client, ®map_config); + ret = PTR_ERR_OR_ZERO(info->charger); + if (ret) { + dev_err(dev, "Regmap initialization failed: %d\n", ret); + return ret; + } + + info->client = client; + + irq_a_det = of_irq_get_byname(dev->of_node, "a_det"); + irq_alert = of_irq_get_byname(dev->of_node, "alert"); + + charger_config.of_node = dev->of_node; + charger_config.drv_data = info; + + ret = regmap_read(info->regmap, UCS1002_REG_PRODUCT_ID, ®val); + if (ret) { + dev_err(dev, "Failed to read product ID: %d\n", ret); + return ret; + } + + if (regval != UCS1002_PRODUCT_ID) { + dev_err(dev, + "Product ID does not match (0x%02x != 0x%02x)\n", + regval, UCS1002_PRODUCT_ID); + return -ENODEV; + } + + /* Enable charge rationing by default */ + ret = regmap_update_bits(info->regmap, UCS1002_REG_GENERAL_CFG, + F_RATION_EN, F_RATION_EN); + if (ret) { + dev_err(dev, "Failed to read general config: %d\n", ret); + return ret; + } + + /* + * Ignore the M1, M2, PWR_EN, and EM_EN pin states. Set active + * mode selection to BC1.2 CDP. + */ + ret = regmap_update_bits(info->regmap, UCS1002_REG_SWITCH_CFG, + V_SET_ACTIVE_MODE_MASK | F_PIN_IGNORE, + V_SET_ACTIVE_MODE_BC12_CDP | F_PIN_IGNORE); + if (ret) { + dev_err(dev, "Failed to configure default mode: %d\n", ret); + return ret; + } + /* + * Be safe and set initial current limit to 500mA + */ + ret = ucs1002_set_max_current(info, 500000); + if (ret) { + dev_err(dev, "Failed to set max current default: %d\n", ret); + return ret; + } + + info->charger = devm_power_supply_register(dev, &ucs1002_charger_desc, + &charger_config); + ret = PTR_ERR_OR_ZERO(info->charger); + if (ret) { + dev_err(dev, "Failed to register power supply: %d\n", ret); + return ret; + } + + ret = regmap_read(info->regmap, UCS1002_REG_PIN_STATUS, ®val); + if (ret) { + dev_err(dev, "Failed to read pin status: %d\n", ret); + return ret; + } + + info->regulator_descriptor = + devm_kmemdup(dev, &ucs1002_regulator_descriptor, + sizeof(ucs1002_regulator_descriptor), + GFP_KERNEL); + if (!info->regulator_descriptor) + return -ENOMEM; + + info->regulator_descriptor->enable_is_inverted = !(regval & F_SEL_PIN); + + regulator_config.dev = dev; + regulator_config.of_node = dev->of_node; + regulator_config.regmap = info->regmap; + + rdev = devm_regulator_register(dev, info->regulator_descriptor, + ®ulator_config); + ret = PTR_ERR_OR_ZERO(info->charger); + if (ret) { + dev_err(dev, "Failed to register VBUS regulator: %d\n", ret); + return ret; + } + + if (irq_a_det > 0) { + ret = devm_request_threaded_irq(dev, irq_a_det, NULL, + ucs1002_charger_irq, + IRQF_ONESHOT, + "ucs1002-a_det", info); + if (ret) { + dev_err(dev, "Failed to request A_DET threaded irq: %d\n", + ret); + return ret; + } + } + + if (irq_alert > 0) { + ret = devm_request_threaded_irq(dev, irq_alert, NULL, + ucs1002_alert_irq, + IRQF_ONESHOT, + "ucs1002-alert", info); + if (ret) { + dev_err(dev, "Failed to request ALERT threaded irq: %d\n", + ret); + return ret; + } + } + + return 0; +} + +static const struct of_device_id ucs1002_of_match[] = { + { .compatible = "microchip,ucs1002", }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, ucs1002_of_match); + +static struct i2c_driver ucs1002_driver = { + .driver = { + .name = "ucs1002", + .of_match_table = ucs1002_of_match, + }, + .probe = ucs1002_probe, +}; +module_i2c_driver(ucs1002_driver); + +MODULE_DESCRIPTION("Microchip UCS1002 Programmable USB Port Power Controller"); +MODULE_AUTHOR("Enric Balletbo Serra <enric.balletbo@collabora.com>"); +MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>"); +MODULE_LICENSE("GPL"); -- 2.20.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v4 2/3] power: supply: Add driver for Microchip UCS1002 2019-04-30 6:45 ` [PATCH v4 2/3] power: supply: Add driver for Microchip UCS1002 Andrey Smirnov 2019-04-30 6:45 ` Andrey Smirnov @ 2019-04-30 16:10 ` Guenter Roeck 2019-04-30 16:10 ` Guenter Roeck 1 sibling, 1 reply; 16+ messages in thread From: Guenter Roeck @ 2019-04-30 16:10 UTC (permalink / raw) To: Andrey Smirnov Cc: linux-pm, Enric Balletbo Serra, Chris Healy, Lucas Stach, Fabio Estevam, Sebastian Reichel, linux-kernel On Mon, Apr 29, 2019 at 11:45:56PM -0700, Andrey Smirnov wrote: > Add driver for Microchip UCS1002 Programmable USB Port Power > Controller with Charger Emulation. The driver exposed a power supply > device to control/monitor various parameter of the device as well as a > regulator to allow controlling VBUS line. > > Signed-off-by: Enric Balletbo Serra <enric.balletbo@collabora.com> > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> > Cc: Chris Healy <cphealy@gmail.com> > Cc: Lucas Stach <l.stach@pengutronix.de> > Cc: Fabio Estevam <fabio.estevam@nxp.com> > Cc: Guenter Roeck <linux@roeck-us.net> > Cc: Sebastian Reichel <sre@kernel.org> > Cc: linux-kernel@vger.kernel.org > Cc: linux-pm@vger.kernel.org Reviewed-by: Guenter Roeck <linux@roeck-us.net> ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 2/3] power: supply: Add driver for Microchip UCS1002 2019-04-30 16:10 ` Guenter Roeck @ 2019-04-30 16:10 ` Guenter Roeck 0 siblings, 0 replies; 16+ messages in thread From: Guenter Roeck @ 2019-04-30 16:10 UTC (permalink / raw) To: Andrey Smirnov Cc: linux-pm, Enric Balletbo Serra, Chris Healy, Lucas Stach, Fabio Estevam, Sebastian Reichel, linux-kernel On Mon, Apr 29, 2019 at 11:45:56PM -0700, Andrey Smirnov wrote: > Add driver for Microchip UCS1002 Programmable USB Port Power > Controller with Charger Emulation. The driver exposed a power supply > device to control/monitor various parameter of the device as well as a > regulator to allow controlling VBUS line. > > Signed-off-by: Enric Balletbo Serra <enric.balletbo@collabora.com> > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> > Cc: Chris Healy <cphealy@gmail.com> > Cc: Lucas Stach <l.stach@pengutronix.de> > Cc: Fabio Estevam <fabio.estevam@nxp.com> > Cc: Guenter Roeck <linux@roeck-us.net> > Cc: Sebastian Reichel <sre@kernel.org> > Cc: linux-kernel@vger.kernel.org > Cc: linux-pm@vger.kernel.org Reviewed-by: Guenter Roeck <linux@roeck-us.net> ^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v4 3/3] dt-bindings: power: supply: Add bindings for Microchip UCS1002 2019-04-30 6:45 [PATCH v4 0/3] Driver for UCS1002 Andrey Smirnov ` (2 preceding siblings ...) 2019-04-30 6:45 ` [PATCH v4 2/3] power: supply: Add driver for Microchip UCS1002 Andrey Smirnov @ 2019-04-30 6:45 ` Andrey Smirnov 2019-04-30 6:45 ` Andrey Smirnov 2019-04-30 16:15 ` Guenter Roeck 3 siblings, 2 replies; 16+ messages in thread From: Andrey Smirnov @ 2019-04-30 6:45 UTC (permalink / raw) To: linux-pm Cc: Andrey Smirnov, Enric Balletbo Serra, Chris Healy, Lucas Stach, Fabio Estevam, Guenter Roeck, Rob Herring, devicetree, Sebastian Reichel, linux-kernel Add bindings for Microchip UCS1002 Programmable USB Port Power Controller with Charger Emulation. Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Cc: Enric Balletbo Serra <enric.balletbo@collabora.com> Cc: Chris Healy <cphealy@gmail.com> Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Fabio Estevam <fabio.estevam@nxp.com> Cc: Guenter Roeck <linux@roeck-us.net> Cc: Rob Herring <robh+dt@kernel.org> Cc: devicetree@vger.kernel.org Cc: Sebastian Reichel <sre@kernel.org> Cc: linux-kernel@vger.kernel.org Cc: linux-pm@vger.kernel.org --- .../power/supply/microchip,ucs1002.txt | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt diff --git a/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt b/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt new file mode 100644 index 000000000000..021fd7aba75e --- /dev/null +++ b/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt @@ -0,0 +1,27 @@ +Microchip UCS1002 USB Port Power Controller + +Required properties: +- compatible : Should be "microchip,ucs1002"; +- reg : I2C slave address + +Optional properties: +- interrupts-extended : A list of interrupts lines present (could be either + corresponding to A_DET# pin, ALERT# pin, or both) +- interrupt-names : A list of interrupt names. Should contain (if + present): + - "a_det" for line connected to A_DET# pin + - "alert" for line connected to ALERT# pin + Both are expected to be IRQ_TYPE_EDGE_BOTH +Example: + +&i2c3 { + charger@32 { + compatible = "microchip,ucs1002"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ucs1002_pins>; + reg = <0x32>; + interrupts-extended = <&gpio5 2 IRQ_TYPE_EDGE_BOTH>, + <&gpio3 21 IRQ_TYPE_EDGE_BOTH>; + interrupt-names = "a_det", "alert"; + }; +}; -- 2.20.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v4 3/3] dt-bindings: power: supply: Add bindings for Microchip UCS1002 2019-04-30 6:45 ` [PATCH v4 3/3] dt-bindings: power: supply: Add bindings " Andrey Smirnov @ 2019-04-30 6:45 ` Andrey Smirnov 2019-04-30 16:15 ` Guenter Roeck 1 sibling, 0 replies; 16+ messages in thread From: Andrey Smirnov @ 2019-04-30 6:45 UTC (permalink / raw) To: linux-pm Cc: Andrey Smirnov, Enric Balletbo Serra, Chris Healy, Lucas Stach, Fabio Estevam, Guenter Roeck, Rob Herring, devicetree, Sebastian Reichel, linux-kernel Add bindings for Microchip UCS1002 Programmable USB Port Power Controller with Charger Emulation. Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Cc: Enric Balletbo Serra <enric.balletbo@collabora.com> Cc: Chris Healy <cphealy@gmail.com> Cc: Lucas Stach <l.stach@pengutronix.de> Cc: Fabio Estevam <fabio.estevam@nxp.com> Cc: Guenter Roeck <linux@roeck-us.net> Cc: Rob Herring <robh+dt@kernel.org> Cc: devicetree@vger.kernel.org Cc: Sebastian Reichel <sre@kernel.org> Cc: linux-kernel@vger.kernel.org Cc: linux-pm@vger.kernel.org --- .../power/supply/microchip,ucs1002.txt | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt diff --git a/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt b/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt new file mode 100644 index 000000000000..021fd7aba75e --- /dev/null +++ b/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt @@ -0,0 +1,27 @@ +Microchip UCS1002 USB Port Power Controller + +Required properties: +- compatible : Should be "microchip,ucs1002"; +- reg : I2C slave address + +Optional properties: +- interrupts-extended : A list of interrupts lines present (could be either + corresponding to A_DET# pin, ALERT# pin, or both) +- interrupt-names : A list of interrupt names. Should contain (if + present): + - "a_det" for line connected to A_DET# pin + - "alert" for line connected to ALERT# pin + Both are expected to be IRQ_TYPE_EDGE_BOTH +Example: + +&i2c3 { + charger@32 { + compatible = "microchip,ucs1002"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ucs1002_pins>; + reg = <0x32>; + interrupts-extended = <&gpio5 2 IRQ_TYPE_EDGE_BOTH>, + <&gpio3 21 IRQ_TYPE_EDGE_BOTH>; + interrupt-names = "a_det", "alert"; + }; +}; -- 2.20.1 ^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v4 3/3] dt-bindings: power: supply: Add bindings for Microchip UCS1002 2019-04-30 6:45 ` [PATCH v4 3/3] dt-bindings: power: supply: Add bindings " Andrey Smirnov 2019-04-30 6:45 ` Andrey Smirnov @ 2019-04-30 16:15 ` Guenter Roeck 2019-04-30 16:15 ` Guenter Roeck 2019-04-30 22:32 ` Rob Herring 1 sibling, 2 replies; 16+ messages in thread From: Guenter Roeck @ 2019-04-30 16:15 UTC (permalink / raw) To: Andrey Smirnov Cc: linux-pm, Enric Balletbo Serra, Chris Healy, Lucas Stach, Fabio Estevam, Rob Herring, devicetree, Sebastian Reichel, linux-kernel On Mon, Apr 29, 2019 at 11:45:57PM -0700, Andrey Smirnov wrote: > Add bindings for Microchip UCS1002 Programmable USB Port Power > Controller with Charger Emulation. > > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> > Cc: Enric Balletbo Serra <enric.balletbo@collabora.com> > Cc: Chris Healy <cphealy@gmail.com> > Cc: Lucas Stach <l.stach@pengutronix.de> > Cc: Fabio Estevam <fabio.estevam@nxp.com> > Cc: Guenter Roeck <linux@roeck-us.net> > Cc: Rob Herring <robh+dt@kernel.org> > Cc: devicetree@vger.kernel.org > Cc: Sebastian Reichel <sre@kernel.org> > Cc: linux-kernel@vger.kernel.org > Cc: linux-pm@vger.kernel.org > --- > .../power/supply/microchip,ucs1002.txt | 27 +++++++++++++++++++ > 1 file changed, 27 insertions(+) > create mode 100644 Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt > > diff --git a/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt b/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt > new file mode 100644 > index 000000000000..021fd7aba75e > --- /dev/null > +++ b/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt > @@ -0,0 +1,27 @@ > +Microchip UCS1002 USB Port Power Controller > + > +Required properties: > +- compatible : Should be "microchip,ucs1002"; > +- reg : I2C slave address > + > +Optional properties: > +- interrupts-extended : A list of interrupts lines present (could be either > + corresponding to A_DET# pin, ALERT# pin, or both) > +- interrupt-names : A list of interrupt names. Should contain (if > + present): > + - "a_det" for line connected to A_DET# pin > + - "alert" for line connected to ALERT# pin > + Both are expected to be IRQ_TYPE_EDGE_BOTH > +Example: > + > +&i2c3 { > + charger@32 { > + compatible = "microchip,ucs1002"; > + pinctrl-names = "default"; > + pinctrl-0 = <&pinctrl_ucs1002_pins>; Document the above ? Or is that optional ? [ I am not a DT expert, so feel free to ignore. ] Guenter > + reg = <0x32>; > + interrupts-extended = <&gpio5 2 IRQ_TYPE_EDGE_BOTH>, > + <&gpio3 21 IRQ_TYPE_EDGE_BOTH>; > + interrupt-names = "a_det", "alert"; > + }; > +}; > -- > 2.20.1 > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 3/3] dt-bindings: power: supply: Add bindings for Microchip UCS1002 2019-04-30 16:15 ` Guenter Roeck @ 2019-04-30 16:15 ` Guenter Roeck 2019-04-30 22:32 ` Rob Herring 1 sibling, 0 replies; 16+ messages in thread From: Guenter Roeck @ 2019-04-30 16:15 UTC (permalink / raw) To: Andrey Smirnov Cc: linux-pm, Enric Balletbo Serra, Chris Healy, Lucas Stach, Fabio Estevam, Rob Herring, devicetree, Sebastian Reichel, linux-kernel On Mon, Apr 29, 2019 at 11:45:57PM -0700, Andrey Smirnov wrote: > Add bindings for Microchip UCS1002 Programmable USB Port Power > Controller with Charger Emulation. > > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> > Cc: Enric Balletbo Serra <enric.balletbo@collabora.com> > Cc: Chris Healy <cphealy@gmail.com> > Cc: Lucas Stach <l.stach@pengutronix.de> > Cc: Fabio Estevam <fabio.estevam@nxp.com> > Cc: Guenter Roeck <linux@roeck-us.net> > Cc: Rob Herring <robh+dt@kernel.org> > Cc: devicetree@vger.kernel.org > Cc: Sebastian Reichel <sre@kernel.org> > Cc: linux-kernel@vger.kernel.org > Cc: linux-pm@vger.kernel.org > --- > .../power/supply/microchip,ucs1002.txt | 27 +++++++++++++++++++ > 1 file changed, 27 insertions(+) > create mode 100644 Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt > > diff --git a/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt b/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt > new file mode 100644 > index 000000000000..021fd7aba75e > --- /dev/null > +++ b/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt > @@ -0,0 +1,27 @@ > +Microchip UCS1002 USB Port Power Controller > + > +Required properties: > +- compatible : Should be "microchip,ucs1002"; > +- reg : I2C slave address > + > +Optional properties: > +- interrupts-extended : A list of interrupts lines present (could be either > + corresponding to A_DET# pin, ALERT# pin, or both) > +- interrupt-names : A list of interrupt names. Should contain (if > + present): > + - "a_det" for line connected to A_DET# pin > + - "alert" for line connected to ALERT# pin > + Both are expected to be IRQ_TYPE_EDGE_BOTH > +Example: > + > +&i2c3 { > + charger@32 { > + compatible = "microchip,ucs1002"; > + pinctrl-names = "default"; > + pinctrl-0 = <&pinctrl_ucs1002_pins>; Document the above ? Or is that optional ? [ I am not a DT expert, so feel free to ignore. ] Guenter > + reg = <0x32>; > + interrupts-extended = <&gpio5 2 IRQ_TYPE_EDGE_BOTH>, > + <&gpio3 21 IRQ_TYPE_EDGE_BOTH>; > + interrupt-names = "a_det", "alert"; > + }; > +}; > -- > 2.20.1 > ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 3/3] dt-bindings: power: supply: Add bindings for Microchip UCS1002 2019-04-30 16:15 ` Guenter Roeck 2019-04-30 16:15 ` Guenter Roeck @ 2019-04-30 22:32 ` Rob Herring 2019-04-30 22:32 ` Rob Herring 2019-04-30 23:28 ` Guenter Roeck 1 sibling, 2 replies; 16+ messages in thread From: Rob Herring @ 2019-04-30 22:32 UTC (permalink / raw) To: Guenter Roeck Cc: Andrey Smirnov, linux-pm, Enric Balletbo Serra, Chris Healy, Lucas Stach, Fabio Estevam, devicetree, Sebastian Reichel, linux-kernel On Tue, Apr 30, 2019 at 09:15:42AM -0700, Guenter Roeck wrote: > On Mon, Apr 29, 2019 at 11:45:57PM -0700, Andrey Smirnov wrote: > > Add bindings for Microchip UCS1002 Programmable USB Port Power > > Controller with Charger Emulation. > > > > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> > > Cc: Enric Balletbo Serra <enric.balletbo@collabora.com> > > Cc: Chris Healy <cphealy@gmail.com> > > Cc: Lucas Stach <l.stach@pengutronix.de> > > Cc: Fabio Estevam <fabio.estevam@nxp.com> > > Cc: Guenter Roeck <linux@roeck-us.net> > > Cc: Rob Herring <robh+dt@kernel.org> > > Cc: devicetree@vger.kernel.org > > Cc: Sebastian Reichel <sre@kernel.org> > > Cc: linux-kernel@vger.kernel.org > > Cc: linux-pm@vger.kernel.org > > --- > > .../power/supply/microchip,ucs1002.txt | 27 +++++++++++++++++++ > > 1 file changed, 27 insertions(+) > > create mode 100644 Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt > > > > diff --git a/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt b/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt > > new file mode 100644 > > index 000000000000..021fd7aba75e > > --- /dev/null > > +++ b/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt > > @@ -0,0 +1,27 @@ > > +Microchip UCS1002 USB Port Power Controller > > + > > +Required properties: > > +- compatible : Should be "microchip,ucs1002"; > > +- reg : I2C slave address > > + > > +Optional properties: > > +- interrupts-extended : A list of interrupts lines present (could be either > > + corresponding to A_DET# pin, ALERT# pin, or both) Just make this 'interrupts'. Support for 'interrupts-extended' is implied. With that, Reviewed-by: Rob Herring <robh@kernel.org> > > +- interrupt-names : A list of interrupt names. Should contain (if > > + present): > > + - "a_det" for line connected to A_DET# pin > > + - "alert" for line connected to ALERT# pin > > + Both are expected to be IRQ_TYPE_EDGE_BOTH > > +Example: > > + > > +&i2c3 { > > + charger@32 { > > + compatible = "microchip,ucs1002"; > > + pinctrl-names = "default"; > > + pinctrl-0 = <&pinctrl_ucs1002_pins>; > > Document the above ? Or is that optional ? I would have said to document this, but recently we had some discussion about allowing this to be implied when there's only a 'default' entry. We'll add it automatically for schemas. Rob ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 3/3] dt-bindings: power: supply: Add bindings for Microchip UCS1002 2019-04-30 22:32 ` Rob Herring @ 2019-04-30 22:32 ` Rob Herring 2019-04-30 23:28 ` Guenter Roeck 1 sibling, 0 replies; 16+ messages in thread From: Rob Herring @ 2019-04-30 22:32 UTC (permalink / raw) To: Guenter Roeck Cc: Andrey Smirnov, linux-pm, Enric Balletbo Serra, Chris Healy, Lucas Stach, Fabio Estevam, devicetree, Sebastian Reichel, linux-kernel On Tue, Apr 30, 2019 at 09:15:42AM -0700, Guenter Roeck wrote: > On Mon, Apr 29, 2019 at 11:45:57PM -0700, Andrey Smirnov wrote: > > Add bindings for Microchip UCS1002 Programmable USB Port Power > > Controller with Charger Emulation. > > > > Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> > > Cc: Enric Balletbo Serra <enric.balletbo@collabora.com> > > Cc: Chris Healy <cphealy@gmail.com> > > Cc: Lucas Stach <l.stach@pengutronix.de> > > Cc: Fabio Estevam <fabio.estevam@nxp.com> > > Cc: Guenter Roeck <linux@roeck-us.net> > > Cc: Rob Herring <robh+dt@kernel.org> > > Cc: devicetree@vger.kernel.org > > Cc: Sebastian Reichel <sre@kernel.org> > > Cc: linux-kernel@vger.kernel.org > > Cc: linux-pm@vger.kernel.org > > --- > > .../power/supply/microchip,ucs1002.txt | 27 +++++++++++++++++++ > > 1 file changed, 27 insertions(+) > > create mode 100644 Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt > > > > diff --git a/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt b/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt > > new file mode 100644 > > index 000000000000..021fd7aba75e > > --- /dev/null > > +++ b/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt > > @@ -0,0 +1,27 @@ > > +Microchip UCS1002 USB Port Power Controller > > + > > +Required properties: > > +- compatible : Should be "microchip,ucs1002"; > > +- reg : I2C slave address > > + > > +Optional properties: > > +- interrupts-extended : A list of interrupts lines present (could be either > > + corresponding to A_DET# pin, ALERT# pin, or both) Just make this 'interrupts'. Support for 'interrupts-extended' is implied. With that, Reviewed-by: Rob Herring <robh@kernel.org> > > +- interrupt-names : A list of interrupt names. Should contain (if > > + present): > > + - "a_det" for line connected to A_DET# pin > > + - "alert" for line connected to ALERT# pin > > + Both are expected to be IRQ_TYPE_EDGE_BOTH > > +Example: > > + > > +&i2c3 { > > + charger@32 { > > + compatible = "microchip,ucs1002"; > > + pinctrl-names = "default"; > > + pinctrl-0 = <&pinctrl_ucs1002_pins>; > > Document the above ? Or is that optional ? I would have said to document this, but recently we had some discussion about allowing this to be implied when there's only a 'default' entry. We'll add it automatically for schemas. Rob ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 3/3] dt-bindings: power: supply: Add bindings for Microchip UCS1002 2019-04-30 22:32 ` Rob Herring 2019-04-30 22:32 ` Rob Herring @ 2019-04-30 23:28 ` Guenter Roeck 2019-04-30 23:28 ` Guenter Roeck 1 sibling, 1 reply; 16+ messages in thread From: Guenter Roeck @ 2019-04-30 23:28 UTC (permalink / raw) To: Rob Herring Cc: Andrey Smirnov, linux-pm, Enric Balletbo Serra, Chris Healy, Lucas Stach, Fabio Estevam, devicetree, Sebastian Reichel, linux-kernel On 4/30/19 3:32 PM, Rob Herring wrote: > On Tue, Apr 30, 2019 at 09:15:42AM -0700, Guenter Roeck wrote: >> On Mon, Apr 29, 2019 at 11:45:57PM -0700, Andrey Smirnov wrote: >>> Add bindings for Microchip UCS1002 Programmable USB Port Power >>> Controller with Charger Emulation. >>> >>> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> >>> Cc: Enric Balletbo Serra <enric.balletbo@collabora.com> >>> Cc: Chris Healy <cphealy@gmail.com> >>> Cc: Lucas Stach <l.stach@pengutronix.de> >>> Cc: Fabio Estevam <fabio.estevam@nxp.com> >>> Cc: Guenter Roeck <linux@roeck-us.net> >>> Cc: Rob Herring <robh+dt@kernel.org> >>> Cc: devicetree@vger.kernel.org >>> Cc: Sebastian Reichel <sre@kernel.org> >>> Cc: linux-kernel@vger.kernel.org >>> Cc: linux-pm@vger.kernel.org >>> --- >>> .../power/supply/microchip,ucs1002.txt | 27 +++++++++++++++++++ >>> 1 file changed, 27 insertions(+) >>> create mode 100644 Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt >>> >>> diff --git a/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt b/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt >>> new file mode 100644 >>> index 000000000000..021fd7aba75e >>> --- /dev/null >>> +++ b/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt >>> @@ -0,0 +1,27 @@ >>> +Microchip UCS1002 USB Port Power Controller >>> + >>> +Required properties: >>> +- compatible : Should be "microchip,ucs1002"; >>> +- reg : I2C slave address >>> + >>> +Optional properties: >>> +- interrupts-extended : A list of interrupts lines present (could be either >>> + corresponding to A_DET# pin, ALERT# pin, or both) > > Just make this 'interrupts'. Support for 'interrupts-extended' is > implied. > > With that, > > Reviewed-by: Rob Herring <robh@kernel.org> > >>> +- interrupt-names : A list of interrupt names. Should contain (if >>> + present): >>> + - "a_det" for line connected to A_DET# pin >>> + - "alert" for line connected to ALERT# pin >>> + Both are expected to be IRQ_TYPE_EDGE_BOTH >>> +Example: >>> + >>> +&i2c3 { >>> + charger@32 { >>> + compatible = "microchip,ucs1002"; >>> + pinctrl-names = "default"; >>> + pinctrl-0 = <&pinctrl_ucs1002_pins>; >> >> Document the above ? Or is that optional ? > > I would have said to document this, but recently we had some discussion > about allowing this to be implied when there's only a 'default' entry. > We'll add it automatically for schemas. > Good to know. Thanks for the information! Guenter ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 3/3] dt-bindings: power: supply: Add bindings for Microchip UCS1002 2019-04-30 23:28 ` Guenter Roeck @ 2019-04-30 23:28 ` Guenter Roeck 0 siblings, 0 replies; 16+ messages in thread From: Guenter Roeck @ 2019-04-30 23:28 UTC (permalink / raw) To: Rob Herring Cc: Andrey Smirnov, linux-pm, Enric Balletbo Serra, Chris Healy, Lucas Stach, Fabio Estevam, devicetree, Sebastian Reichel, linux-kernel On 4/30/19 3:32 PM, Rob Herring wrote: > On Tue, Apr 30, 2019 at 09:15:42AM -0700, Guenter Roeck wrote: >> On Mon, Apr 29, 2019 at 11:45:57PM -0700, Andrey Smirnov wrote: >>> Add bindings for Microchip UCS1002 Programmable USB Port Power >>> Controller with Charger Emulation. >>> >>> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> >>> Cc: Enric Balletbo Serra <enric.balletbo@collabora.com> >>> Cc: Chris Healy <cphealy@gmail.com> >>> Cc: Lucas Stach <l.stach@pengutronix.de> >>> Cc: Fabio Estevam <fabio.estevam@nxp.com> >>> Cc: Guenter Roeck <linux@roeck-us.net> >>> Cc: Rob Herring <robh+dt@kernel.org> >>> Cc: devicetree@vger.kernel.org >>> Cc: Sebastian Reichel <sre@kernel.org> >>> Cc: linux-kernel@vger.kernel.org >>> Cc: linux-pm@vger.kernel.org >>> --- >>> .../power/supply/microchip,ucs1002.txt | 27 +++++++++++++++++++ >>> 1 file changed, 27 insertions(+) >>> create mode 100644 Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt >>> >>> diff --git a/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt b/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt >>> new file mode 100644 >>> index 000000000000..021fd7aba75e >>> --- /dev/null >>> +++ b/Documentation/devicetree/bindings/power/supply/microchip,ucs1002.txt >>> @@ -0,0 +1,27 @@ >>> +Microchip UCS1002 USB Port Power Controller >>> + >>> +Required properties: >>> +- compatible : Should be "microchip,ucs1002"; >>> +- reg : I2C slave address >>> + >>> +Optional properties: >>> +- interrupts-extended : A list of interrupts lines present (could be either >>> + corresponding to A_DET# pin, ALERT# pin, or both) > > Just make this 'interrupts'. Support for 'interrupts-extended' is > implied. > > With that, > > Reviewed-by: Rob Herring <robh@kernel.org> > >>> +- interrupt-names : A list of interrupt names. Should contain (if >>> + present): >>> + - "a_det" for line connected to A_DET# pin >>> + - "alert" for line connected to ALERT# pin >>> + Both are expected to be IRQ_TYPE_EDGE_BOTH >>> +Example: >>> + >>> +&i2c3 { >>> + charger@32 { >>> + compatible = "microchip,ucs1002"; >>> + pinctrl-names = "default"; >>> + pinctrl-0 = <&pinctrl_ucs1002_pins>; >> >> Document the above ? Or is that optional ? > > I would have said to document this, but recently we had some discussion > about allowing this to be implied when there's only a 'default' entry. > We'll add it automatically for schemas. > Good to know. Thanks for the information! Guenter ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2019-04-30 23:29 UTC | newest] Thread overview: 16+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2019-04-30 6:45 [PATCH v4 0/3] Driver for UCS1002 Andrey Smirnov 2019-04-30 6:45 ` Andrey Smirnov 2019-04-30 6:45 ` [PATCH v4 1/3] power: supply: core: Add POWER_SUPPLY_HEALTH_OVERCURRENT constant Andrey Smirnov 2019-04-30 6:45 ` Andrey Smirnov 2019-04-30 6:45 ` [PATCH v4 2/3] power: supply: Add driver for Microchip UCS1002 Andrey Smirnov 2019-04-30 6:45 ` Andrey Smirnov 2019-04-30 16:10 ` Guenter Roeck 2019-04-30 16:10 ` Guenter Roeck 2019-04-30 6:45 ` [PATCH v4 3/3] dt-bindings: power: supply: Add bindings " Andrey Smirnov 2019-04-30 6:45 ` Andrey Smirnov 2019-04-30 16:15 ` Guenter Roeck 2019-04-30 16:15 ` Guenter Roeck 2019-04-30 22:32 ` Rob Herring 2019-04-30 22:32 ` Rob Herring 2019-04-30 23:28 ` Guenter Roeck 2019-04-30 23:28 ` Guenter Roeck
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox