Commit ca9eb48f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'regulator-v5.0' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator

Pull regulator updates from Mark Brown:
 "The biggest chunk of the regulator changes for this release outside of
  the new drivers is the conversion of the fixed regulator to use the
  GPIO descriptor API, there's a small addition to the GPIO API plus a
  bunch of updates to board files to implement it. This is some really
  welcome work from Linus Walleij that's had a bunch of review and has
  been sitting in -next for a while so I'm fairly happy there's no major
  issues.

   - Helpers for overlapping linear ranges.

   - Display opmode and consumer requested load in the regualtor_summary
     file in debugfs, plus a fix there.

   - Support for the fun and entertaining power off mechanism that the
     pfuze100 hardware implements.

   - Conversion of the fixed regulator API to use GPIO descriptors,
     including pulling in a bunch of patches to a bunch of board files.

   - New drivers for Cirrus Logic Lochnagar, Qualcomm PMS405, Rohm
     BD71847, ST PMIC1, and TI LM363x devices"

* tag 'regulator-v5.0' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (36 commits)
  regulator: lochnagar: Use a consisent comment style for SPDX header
  regulator: bd718x7: Remove struct bd718xx_pmic
  regulator: Fetch enable gpiods nonexclusive
  regulator/gpio: Allow nonexclusive GPIO access
  regulator: lochnagar: Add support for the Cirrus Logic Lochnagar
  regulator: stpmic1: Return REGULATOR_MODE_INVALID for invalid mode
  regulator: stpmic1: add stpmic1 regulator driver
  dt-bindings: regulator: document stpmic1 pmic regulators
  regulator: axp20x: Mark expected switch fall-throughs
  regulator: bd718xx: fix build warning on x86_64
  regulator: fixed: Default enable high on DT regulators
  regulator: bd718xx: rename bd71837 to 718xx
  regulator: bd718XX use pickable ranges
  regulator/mfd: bd718xx: rename bd71837/bd71847 common instances
  regulator: Support regulators where voltage ranges are selectable
  mfd: dt bindings: add BD71847 device-tree binding documentation
  regulator: dt bindings: add BD71847 device-tree binding documentation
  regulator/mfd: Support ROHM BD71847 power management IC
  regulator: da905{2,5}: Remove unnecessary array check
  regulator: qcom: Add PMS405 regulators
  ...
parents b537149a f35b1e53
* ROHM BD71837 Power Management Integrated Circuit bindings * ROHM BD71837 and BD71847 Power Management Integrated Circuit bindings
BD71837MWV is a programmable Power Management IC for powering single-core, BD71837MWV and BD71847MWV are programmable Power Management ICs for powering
dual-core, and quad-core SoCs such as NXP-i.MX 8M. It is optimized for single-core, dual-core, and quad-core SoCs such as NXP-i.MX 8M. They are
low BOM cost and compact solution footprint. It integrates 8 Buck optimized for low BOM cost and compact solution footprint. BD71837MWV
egulators and 7 LDOs to provide all the power rails required by the SoC and integrates 8 Buck regulators and 7 LDOs. BD71847MWV contains 6 Buck regulators
the commonly used peripherals. and 6 LDOs.
Datasheet for PMIC is available at: Datasheet for BD71837 is available at:
https://www.rohm.com/datasheet/BD71837MWV/bd71837mwv-e https://www.rohm.com/datasheet/BD71837MWV/bd71837mwv-e
Required properties: Required properties:
- compatible : Should be "rohm,bd71837". - compatible : Should be "rohm,bd71837" for bd71837
"rohm,bd71847" for bd71847.
- reg : I2C slave address. - reg : I2C slave address.
- interrupt-parent : Phandle to the parent interrupt controller. - interrupt-parent : Phandle to the parent interrupt controller.
- interrupts : The interrupt line the device is connected to. - interrupts : The interrupt line the device is connected to.
......
...@@ -12,6 +12,11 @@ Optional properties: ...@@ -12,6 +12,11 @@ Optional properties:
disabled. This binding is a workaround to keep backward compatibility with disabled. This binding is a workaround to keep backward compatibility with
old dtb's which rely on the fact that the switched regulators are always on old dtb's which rely on the fact that the switched regulators are always on
and don't mark them explicit as "regulator-always-on". and don't mark them explicit as "regulator-always-on".
- fsl,pmic-stby-poweroff: if present, configure the PMIC to shutdown all
power rails when PMIC_STBY_REQ line is asserted during the power off sequence.
Use this option if the SoC should be powered off by external power
management IC (PMIC) on PMIC_STBY_REQ signal.
As opposite to PMIC_STBY_REQ boards can implement PMIC_ON_REQ signal.
Required child node: Required child node:
- regulators: This is the list of child nodes that specify the regulator - regulators: This is the list of child nodes that specify the regulator
......
...@@ -26,6 +26,7 @@ Regulator nodes are identified by their compatible: ...@@ -26,6 +26,7 @@ Regulator nodes are identified by their compatible:
"qcom,rpm-pm8998-regulators" "qcom,rpm-pm8998-regulators"
"qcom,rpm-pma8084-regulators" "qcom,rpm-pma8084-regulators"
"qcom,rpm-pmi8998-regulators" "qcom,rpm-pmi8998-regulators"
"qcom,rpm-pms405-regulators"
- vdd_s1-supply: - vdd_s1-supply:
- vdd_s2-supply: - vdd_s2-supply:
...@@ -188,6 +189,24 @@ Regulator nodes are identified by their compatible: ...@@ -188,6 +189,24 @@ Regulator nodes are identified by their compatible:
Definition: reference to regulator supplying the input pin, as Definition: reference to regulator supplying the input pin, as
described in the data sheet described in the data sheet
- vdd_s1-supply:
- vdd_s2-supply:
- vdd_s3-supply:
- vdd_s4-supply:
- vdd_s5-supply:
- vdd_l1_l2-supply:
- vdd_l3_l8-supply:
- vdd_l4-supply:
- vdd_l5_l6-supply:
- vdd_l7-supply:
- vdd_l3_l8-supply:
- vdd_l9-supply:
- vdd_l10_l11_l12_l13-supply:
Usage: optional (pms405 only)
Value type: <phandle>
Definition: reference to regulator supplying the input pin, as
described in the data sheet
The regulator node houses sub-nodes for each regulator within the device. Each The regulator node houses sub-nodes for each regulator within the device. Each
sub-node is identified using the node's name, with valid values listed for each sub-node is identified using the node's name, with valid values listed for each
of the pmics below. of the pmics below.
...@@ -222,6 +241,10 @@ pma8084: ...@@ -222,6 +241,10 @@ pma8084:
pmi8998: pmi8998:
bob bob
pms405:
s1, s2, s3, s4, s5, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12,
l13
The content of each sub-node is defined by the standard binding for regulators - The content of each sub-node is defined by the standard binding for regulators -
see regulator.txt. see regulator.txt.
......
ROHM BD71837 Power Management Integrated Circuit (PMIC) regulator bindings ROHM BD71837 and BD71847 Power Management Integrated Circuit regulator bindings
Required properties: Required properties:
- regulator-name: should be "buck1", ..., "buck8" and "ldo1", ..., "ldo7" - regulator-name: should be "buck1", ..., "buck8" and "ldo1", ..., "ldo7" for
BD71837. For BD71847 names should be "buck1", ..., "buck6"
and "ldo1", ..., "ldo6"
List of regulators provided by this controller. BD71837 regulators node List of regulators provided by this controller. BD71837 regulators node
should be sub node of the BD71837 MFD node. See BD71837 MFD bindings at should be sub node of the BD71837 MFD node. See BD71837 MFD bindings at
...@@ -16,10 +18,14 @@ disabled by driver at startup. LDO5 and LDO6 are supplied by those and ...@@ -16,10 +18,14 @@ disabled by driver at startup. LDO5 and LDO6 are supplied by those and
if they are disabled at startup the voltage monitoring for LDO5/LDO6 will if they are disabled at startup the voltage monitoring for LDO5/LDO6 will
cause PMIC to reset. cause PMIC to reset.
The valid names for regulator nodes are: The valid names for BD71837 regulator nodes are:
BUCK1, BUCK2, BUCK3, BUCK4, BUCK5, BUCK6, BUCK7, BUCK8 BUCK1, BUCK2, BUCK3, BUCK4, BUCK5, BUCK6, BUCK7, BUCK8
LDO1, LDO2, LDO3, LDO4, LDO5, LDO6, LDO7 LDO1, LDO2, LDO3, LDO4, LDO5, LDO6, LDO7
The valid names for BD71847 regulator nodes are:
BUCK1, BUCK2, BUCK3, BUCK4, BUCK5, BUCK6
LDO1, LDO2, LDO3, LDO4, LDO5, LDO6
Optional properties: Optional properties:
- Any optional property defined in bindings/regulator/regulator.txt - Any optional property defined in bindings/regulator/regulator.txt
......
STMicroelectronics STPMIC1 Voltage regulators
Regulator Nodes are optional depending on needs.
Available Regulators in STPMIC1 device are:
- buck1 for Buck BUCK1
- buck2 for Buck BUCK2
- buck3 for Buck BUCK3
- buck4 for Buck BUCK4
- ldo1 for LDO LDO1
- ldo2 for LDO LDO2
- ldo3 for LDO LDO3
- ldo4 for LDO LDO4
- ldo5 for LDO LDO5
- ldo6 for LDO LDO6
- vref_ddr for LDO Vref DDR
- boost for Buck BOOST
- pwr_sw1 for VBUS_OTG switch
- pwr_sw2 for SW_OUT switch
Switches are fixed voltage regulators with only enable/disable capability.
Optional properties:
- st,mask-reset: mask reset for this regulator: the regulator configuration
is maintained during pmic reset.
- regulator-pull-down: enable high pull down
if not specified light pull down is used
- regulator-over-current-protection:
if set, all regulators are switched off in case of over-current detection
on this regulator,
if not set, the driver only sends an over-current event.
- interrupt-parent: phandle to the parent interrupt controller
- interrupts: index of current limit detection interrupt
- <regulator>-supply: phandle to the parent supply/regulator node
each regulator supply can be described except vref_ddr.
Example:
regulators {
compatible = "st,stpmic1-regulators";
ldo6-supply = <&v3v3>;
vdd_core: buck1 {
regulator-name = "vdd_core";
interrupts = <IT_CURLIM_BUCK1 0>;
interrupt-parent = <&pmic>;
st,mask-reset;
regulator-pull-down;
regulator-min-microvolt = <700000>;
regulator-max-microvolt = <1200000>;
};
v3v3: buck4 {
regulator-name = "v3v3";
interrupts = <IT_CURLIM_BUCK4 0>;
interrupt-parent = <&mypmic>;
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
v1v8: ldo6 {
regulator-name = "v1v8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-over-current-protection;
};
};
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/gpio/driver.h> #include <linux/gpio/driver.h>
#include <linux/gpio/machine.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/regulator/fixed.h> #include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
...@@ -175,6 +176,7 @@ static struct resource mx21ads_mmgpio_resource = ...@@ -175,6 +176,7 @@ static struct resource mx21ads_mmgpio_resource =
DEFINE_RES_MEM_NAMED(MX21ADS_IO_REG, SZ_2, "dat"); DEFINE_RES_MEM_NAMED(MX21ADS_IO_REG, SZ_2, "dat");
static struct bgpio_pdata mx21ads_mmgpio_pdata = { static struct bgpio_pdata mx21ads_mmgpio_pdata = {
.label = "mx21ads-mmgpio",
.base = MX21ADS_MMGPIO_BASE, .base = MX21ADS_MMGPIO_BASE,
.ngpio = 16, .ngpio = 16,
}; };
...@@ -203,7 +205,6 @@ static struct regulator_init_data mx21ads_lcd_regulator_init_data = { ...@@ -203,7 +205,6 @@ static struct regulator_init_data mx21ads_lcd_regulator_init_data = {
static struct fixed_voltage_config mx21ads_lcd_regulator_pdata = { static struct fixed_voltage_config mx21ads_lcd_regulator_pdata = {
.supply_name = "LCD", .supply_name = "LCD",
.microvolts = 3300000, .microvolts = 3300000,
.gpio = MX21ADS_IO_LCDON,
.enable_high = 1, .enable_high = 1,
.init_data = &mx21ads_lcd_regulator_init_data, .init_data = &mx21ads_lcd_regulator_init_data,
}; };
...@@ -216,6 +217,14 @@ static struct platform_device mx21ads_lcd_regulator = { ...@@ -216,6 +217,14 @@ static struct platform_device mx21ads_lcd_regulator = {
}, },
}; };
static struct gpiod_lookup_table mx21ads_lcd_regulator_gpiod_table = {
.dev_id = "reg-fixed-voltage.0", /* Let's hope ID 0 is what we get */
.table = {
GPIO_LOOKUP("mx21ads-mmgpio", 9, NULL, GPIO_ACTIVE_HIGH),
{ },
},
};
/* /*
* Connected is a portrait Sharp-QVGA display * Connected is a portrait Sharp-QVGA display
* of type: LQ035Q7DB02 * of type: LQ035Q7DB02
...@@ -311,6 +320,7 @@ static void __init mx21ads_late_init(void) ...@@ -311,6 +320,7 @@ static void __init mx21ads_late_init(void)
{ {
imx21_add_mxc_mmc(0, &mx21ads_sdhc_pdata); imx21_add_mxc_mmc(0, &mx21ads_sdhc_pdata);
gpiod_add_lookup_table(&mx21ads_lcd_regulator_gpiod_table);
platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
mx21ads_cs8900_resources[1].start = mx21ads_cs8900_resources[1].start =
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/gpio/driver.h> #include <linux/gpio/driver.h>
/* Needed for gpio_to_irq() */ /* Needed for gpio_to_irq() */
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/mtd/map.h> #include <linux/mtd/map.h>
...@@ -230,10 +231,17 @@ static struct regulator_init_data mx27ads_lcd_regulator_init_data = { ...@@ -230,10 +231,17 @@ static struct regulator_init_data mx27ads_lcd_regulator_init_data = {
static struct fixed_voltage_config mx27ads_lcd_regulator_pdata = { static struct fixed_voltage_config mx27ads_lcd_regulator_pdata = {
.supply_name = "LCD", .supply_name = "LCD",
.microvolts = 3300000, .microvolts = 3300000,
.gpio = MX27ADS_LCD_GPIO,
.init_data = &mx27ads_lcd_regulator_init_data, .init_data = &mx27ads_lcd_regulator_init_data,
}; };
static struct gpiod_lookup_table mx27ads_lcd_regulator_gpiod_table = {
.dev_id = "reg-fixed-voltage.0", /* Let's hope ID 0 is what we get */
.table = {
GPIO_LOOKUP("LCD", 0, NULL, GPIO_ACTIVE_HIGH),
{ },
},
};
static void __init mx27ads_regulator_init(void) static void __init mx27ads_regulator_init(void)
{ {
struct gpio_chip *vchip; struct gpio_chip *vchip;
...@@ -247,6 +255,8 @@ static void __init mx27ads_regulator_init(void) ...@@ -247,6 +255,8 @@ static void __init mx27ads_regulator_init(void)
vchip->set = vgpio_set; vchip->set = vgpio_set;
gpiochip_add_data(vchip, NULL); gpiochip_add_data(vchip, NULL);
gpiod_add_lookup_table(&mx27ads_lcd_regulator_gpiod_table);
platform_device_register_data(NULL, "reg-fixed-voltage", platform_device_register_data(NULL, "reg-fixed-voltage",
PLATFORM_DEVID_AUTO, PLATFORM_DEVID_AUTO,
&mx27ads_lcd_regulator_pdata, &mx27ads_lcd_regulator_pdata,
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/gpio-pxa.h> #include <linux/gpio-pxa.h>
#include <linux/gpio/machine.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/regulator/max8649.h> #include <linux/regulator/max8649.h>
#include <linux/regulator/fixed.h> #include <linux/regulator/fixed.h>
...@@ -148,7 +149,6 @@ static struct regulator_init_data brownstone_v_5vp_data = { ...@@ -148,7 +149,6 @@ static struct regulator_init_data brownstone_v_5vp_data = {
static struct fixed_voltage_config brownstone_v_5vp = { static struct fixed_voltage_config brownstone_v_5vp = {
.supply_name = "v_5vp", .supply_name = "v_5vp",
.microvolts = 5000000, .microvolts = 5000000,
.gpio = GPIO_5V_ENABLE,
.enable_high = 1, .enable_high = 1,
.enabled_at_boot = 1, .enabled_at_boot = 1,
.init_data = &brownstone_v_5vp_data, .init_data = &brownstone_v_5vp_data,
...@@ -162,6 +162,15 @@ static struct platform_device brownstone_v_5vp_device = { ...@@ -162,6 +162,15 @@ static struct platform_device brownstone_v_5vp_device = {
}, },
}; };
static struct gpiod_lookup_table brownstone_v_5vp_gpiod_table = {
.dev_id = "reg-fixed-voltage.1", /* .id set to 1 above */
.table = {
GPIO_LOOKUP("gpio-pxa", GPIO_5V_ENABLE,
NULL, GPIO_ACTIVE_HIGH),
{ },
},
};
static struct max8925_platform_data brownstone_max8925_info = { static struct max8925_platform_data brownstone_max8925_info = {
.irq_base = MMP_NR_IRQS, .irq_base = MMP_NR_IRQS,
}; };
...@@ -217,6 +226,7 @@ static void __init brownstone_init(void) ...@@ -217,6 +226,7 @@ static void __init brownstone_init(void)
mmp2_add_isram(&mmp2_isram_platdata); mmp2_add_isram(&mmp2_isram_platdata);
/* enable 5v regulator */ /* enable 5v regulator */
gpiod_add_lookup_table(&brownstone_v_5vp_gpiod_table);
platform_device_register(&brownstone_v_5vp_device); platform_device_register(&brownstone_v_5vp_device);
} }
......
...@@ -300,7 +300,6 @@ static struct regulator_init_data modem_nreset_data = { ...@@ -300,7 +300,6 @@ static struct regulator_init_data modem_nreset_data = {
static struct fixed_voltage_config modem_nreset_config = { static struct fixed_voltage_config modem_nreset_config = {
.supply_name = "modem_nreset", .supply_name = "modem_nreset",
.microvolts = 3300000, .microvolts = 3300000,
.gpio = AMS_DELTA_GPIO_PIN_MODEM_NRESET,
.startup_delay = 25000, .startup_delay = 25000,
.enable_high = 1, .enable_high = 1,
.enabled_at_boot = 1, .enabled_at_boot = 1,
...@@ -315,6 +314,15 @@ static struct platform_device modem_nreset_device = { ...@@ -315,6 +314,15 @@ static struct platform_device modem_nreset_device = {
}, },
}; };
static struct gpiod_lookup_table ams_delta_nreset_gpiod_table = {
.dev_id = "reg-fixed-voltage",
.table = {
GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_MODEM_NRESET,
NULL, GPIO_ACTIVE_HIGH),
{ },
},
};
struct modem_private_data { struct modem_private_data {
struct regulator *regulator; struct regulator *regulator;
}; };
...@@ -568,7 +576,6 @@ static struct regulator_init_data keybrd_pwr_initdata = { ...@@ -568,7 +576,6 @@ static struct regulator_init_data keybrd_pwr_initdata = {
static struct fixed_voltage_config keybrd_pwr_config = { static struct fixed_voltage_config keybrd_pwr_config = {
.supply_name = "keybrd_pwr", .supply_name = "keybrd_pwr",
.microvolts = 5000000, .microvolts = 5000000,
.gpio = AMS_DELTA_GPIO_PIN_KEYBRD_PWR,
.enable_high = 1, .enable_high = 1,
.init_data = &keybrd_pwr_initdata, .init_data = &keybrd_pwr_initdata,
}; };
...@@ -602,6 +609,7 @@ static struct platform_device *ams_delta_devices[] __initdata = { ...@@ -602,6 +609,7 @@ static struct platform_device *ams_delta_devices[] __initdata = {
}; };
static struct gpiod_lookup_table *ams_delta_gpio_tables[] __initdata = { static struct gpiod_lookup_table *ams_delta_gpio_tables[] __initdata = {
&ams_delta_nreset_gpiod_table,
&ams_delta_audio_gpio_table, &ams_delta_audio_gpio_table,
&keybrd_pwr_gpio_table, &keybrd_pwr_gpio_table,
&ams_delta_lcd_gpio_table, &ams_delta_lcd_gpio_table,
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/davinci_emac.h> #include <linux/davinci_emac.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
...@@ -328,7 +329,6 @@ static struct regulator_init_data pandora_vmmc3 = { ...@@ -328,7 +329,6 @@ static struct regulator_init_data pandora_vmmc3 = {
static struct fixed_voltage_config pandora_vwlan = { static struct fixed_voltage_config pandora_vwlan = {
.supply_name = "vwlan", .supply_name = "vwlan",
.microvolts = 1800000, /* 1.8V */ .microvolts = 1800000, /* 1.8V */
.gpio = PANDORA_WIFI_NRESET_GPIO,
.startup_delay = 50000, /* 50ms */ .startup_delay = 50000, /* 50ms */
.enable_high = 1, .enable_high = 1,
.init_data = &pandora_vmmc3, .init_data = &pandora_vmmc3,
...@@ -342,6 +342,19 @@ static struct platform_device pandora_vwlan_device = { ...@@ -342,6 +342,19 @@ static struct platform_device pandora_vwlan_device = {
}, },
}; };
static struct gpiod_lookup_table pandora_vwlan_gpiod_table = {
.dev_id = "reg-fixed-voltage.1",
.table = {
/*
* As this is a low GPIO number it should be at the first
* GPIO bank.
*/
GPIO_LOOKUP("gpio-0-31", PANDORA_WIFI_NRESET_GPIO,
NULL, GPIO_ACTIVE_HIGH),
{ },
},
};
static void pandora_wl1251_init_card(struct mmc_card *card) static void pandora_wl1251_init_card(struct mmc_card *card)
{ {
/* /*
...@@ -403,6 +416,7 @@ static void __init pandora_wl1251_init(void) ...@@ -403,6 +416,7 @@ static void __init pandora_wl1251_init(void)
static void __init omap3_pandora_legacy_init(void) static void __init omap3_pandora_legacy_init(void)
{ {
platform_device_register(&pandora_backlight); platform_device_register(&pandora_backlight);
gpiod_add_lookup_table(&pandora_vwlan_gpiod_table);
platform_device_register(&pandora_vwlan_device); platform_device_register(&pandora_vwlan_device);
omap_hsmmc_init(pandora_mmc3); omap_hsmmc_init(pandora_mmc3);
omap_hsmmc_late_init(pandora_mmc3); omap_hsmmc_late_init(pandora_mmc3);
......
...@@ -984,7 +984,6 @@ static struct fixed_voltage_config camera_dummy_config = { ...@@ -984,7 +984,6 @@ static struct fixed_voltage_config camera_dummy_config = {
.supply_name = "camera_vdd", .supply_name = "camera_vdd",
.input_supply = "vcc cam", .input_supply = "vcc cam",
.microvolts = 2800000, .microvolts = 2800000,
.gpio = -1,
.enable_high = 0, .enable_high = 0,
.init_data = &camera_dummy_initdata, .init_data = &camera_dummy_initdata,
}; };
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/regulator/fixed.h> #include <linux/regulator/fixed.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/gpio_keys.h> #include <linux/gpio_keys.h>
#include <linux/leds-lp3944.h> #include <linux/leds-lp3944.h>
#include <linux/platform_data/i2c-pxa.h> #include <linux/platform_data/i2c-pxa.h>
...@@ -698,31 +699,39 @@ static struct pxa27x_keypad_platform_data e2_keypad_platform_data = { ...@@ -698,31 +699,39 @@ static struct pxa27x_keypad_platform_data e2_keypad_platform_data = {
#if defined(CONFIG_MACH_EZX_A780) || defined(CONFIG_MACH_EZX_A910) #if defined(CONFIG_MACH_EZX_A780) || defined(CONFIG_MACH_EZX_A910)
/* camera */ /* camera */
static struct regulator_consumer_supply camera_dummy_supplies[] = { static struct regulator_consumer_supply camera_regulator_supplies[] = {
REGULATOR_SUPPLY("vdd", "0-005d"), REGULATOR_SUPPLY("vdd", "0-005d"),
}; };
static struct regulator_init_data camera_dummy_initdata = { static struct regulator_init_data camera_regulator_initdata = {
.consumer_supplies = camera_dummy_supplies, .consumer_supplies = camera_regulator_supplies,
.num_consumer_supplies = ARRAY_SIZE(camera_dummy_supplies), .num_consumer_supplies = ARRAY_SIZE(camera_regulator_supplies),
.constraints = { .constraints = {
.valid_ops_mask = REGULATOR_CHANGE_STATUS, .valid_ops_mask = REGULATOR_CHANGE_STATUS,
}, },
}; };
static struct fixed_voltage_config camera_dummy_config = { static struct fixed_voltage_config camera_regulator_config = {
.supply_name = "camera_vdd", .supply_name = "camera_vdd",
.microvolts = 2800000, .microvolts = 2800000,
.gpio = GPIO50_nCAM_EN,
.enable_high = 0, .enable_high = 0,
.init_data = &camera_dummy_initdata, .init_data = &camera_regulator_initdata,
}; };
static struct platform_device camera_supply_dummy_device = { static struct platform_device camera_supply_regulator_device = {
.name = "reg-fixed-voltage", .name = "reg-fixed-voltage",
.id = 1, .id = 1,
.dev = { .dev = {
.platform_data = &camera_dummy_config, .platform_data = &camera_regulator_config,
},
};
static struct gpiod_lookup_table camera_supply_gpiod_table = {
.dev_id = "reg-fixed-voltage.1",
.table = {
GPIO_LOOKUP("gpio-pxa", GPIO50_nCAM_EN,
NULL, GPIO_ACTIVE_HIGH),
{ },
}, },
}; };
#endif #endif
...@@ -800,7 +809,7 @@ static struct i2c_board_info a780_i2c_board_info[] = { ...@@ -800,7 +809,7 @@ static struct i2c_board_info a780_i2c_board_info[] = {
static struct platform_device *a780_devices[] __initdata = { static struct platform_device *a780_devices[] __initdata = {
&a780_gpio_keys, &a780_gpio_keys,
&camera_supply_dummy_device, &camera_supply_regulator_device,
}; };
static void __init a780_init(void) static void __init a780_init(void)
...@@ -823,6 +832,7 @@ static void __init a780_init(void) ...@@ -823,6 +832,7 @@ static void __init a780_init(void)
if (a780_camera_init() == 0) if (a780_camera_init() == 0)
pxa_set_camera_info(&a780_pxacamera_platform_data); pxa_set_camera_info(&a780_pxacamera_platform_data);
gpiod_add_lookup_table(&camera_supply_gpiod_table);
pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup)); pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup));
platform_add_devices(ARRAY_AND_SIZE(ezx_devices)); platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
platform_add_devices(ARRAY_AND_SIZE(a780_devices)); platform_add_devices(ARRAY_AND_SIZE(a780_devices));
...@@ -1098,7 +1108,7 @@ static struct i2c_board_info __initdata a910_i2c_board_info[] = { ...@@ -1098,7 +1108,7 @@ static struct i2c_board_info __initdata a910_i2c_board_info[] = {
static struct platform_device *a910_devices[] __initdata = { static struct platform_device *a910_devices[] __initdata = {
&a910_gpio_keys, &a910_gpio_keys,
&camera_supply_dummy_device, &camera_supply_regulator_device,
}; };
static void __init a910_init(void) static void __init a910_init(void)
...@@ -1121,6 +1131,7 @@ static void __init a910_init(void) ...@@ -1121,6 +1131,7 @@ static void __init a910_init(void)
if (a910_camera_init() == 0) if (a910_camera_init() == 0)
pxa_set_camera_info(&a910_pxacamera_platform_data); pxa_set_camera_info(&a910_pxacamera_platform_data);
gpiod_add_lookup_table(&camera_supply_gpiod_table);
pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup)); pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup));
platform_add_devices(ARRAY_AND_SIZE(ezx_devices)); platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
platform_add_devices(ARRAY_AND_SIZE(a910_devices)); platform_add_devices(ARRAY_AND_SIZE(a910_devices));
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/gpio_keys.h> #include <linux/gpio_keys.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/mfd/htc-pasic3.h> #include <linux/mfd/htc-pasic3.h>
...@@ -696,7 +697,6 @@ static struct regulator_init_data vads7846_regulator = { ...@@ -696,7 +697,6 @@ static struct regulator_init_data vads7846_regulator = {
static struct fixed_voltage_config vads7846 = { static struct fixed_voltage_config vads7846 = {
.supply_name = "vads7846", .supply_name = "vads7846",
.microvolts = 3300000, /* probably */ .microvolts = 3300000, /* probably */
.gpio = -EINVAL,
.startup_delay = 0, .startup_delay = 0,
.init_data = &vads7846_regulator, .init_data = &vads7846_regulator,
}; };
......
...@@ -886,7 +886,6 @@ static struct regulator_init_data audio_va_initdata = { ...@@ -886,7 +886,6 @@ static struct regulator_init_data audio_va_initdata = {
static struct fixed_voltage_config audio_va_config = { static struct fixed_voltage_config audio_va_config = {
.supply_name = "audio_va", .supply_name = "audio_va",
.microvolts = 5000000, .microvolts = 5000000,
.gpio = GPIO_AUDIO_VA_ENABLE,
.enable_high = 1, .enable_high = 1,
.enabled_at_boot = 0, .enabled_at_boot = 0,
.init_data = &audio_va_initdata, .init_data = &audio_va_initdata,
...@@ -900,6 +899,15 @@ static struct platform_device audio_va_device = { ...@@ -900,6 +899,15 @@ static struct platform_device audio_va_device = {
}, },
}; };
static struct gpiod_lookup_table audio_va_gpiod_table = {
.dev_id = "reg-fixed-voltage.0",
.table = {
GPIO_LOOKUP("gpio-pxa", GPIO_AUDIO_VA_ENABLE,
NULL, GPIO_ACTIVE_HIGH),
{ },
},
};
/* Dummy supplies for Codec's VD/VLC */ /* Dummy supplies for Codec's VD/VLC */
static struct regulator_consumer_supply audio_dummy_supplies[] = { static struct regulator_consumer_supply audio_dummy_supplies[] = {
...@@ -918,7 +926,6 @@ static struct regulator_init_data audio_dummy_initdata = { ...@@ -918,7 +926,6 @@ static struct regulator_init_data audio_dummy_initdata = {
static struct fixed_voltage_config audio_dummy_config = { static struct fixed_voltage_config audio_dummy_config = {
.supply_name = "audio_vd", .supply_name = "audio_vd",
.microvolts = 3300000, .microvolts = 3300000,
.gpio = -1,
.init_data = &audio_dummy_initdata, .init_data = &audio_dummy_initdata,
}; };
...@@ -1033,6 +1040,7 @@ static void __init raumfeld_audio_init(void) ...@@ -1033,6 +1040,7 @@ static void __init raumfeld_audio_init(void)
else else
gpio_direction_output(GPIO_MCLK_RESET, 1); gpio_direction_output(GPIO_MCLK_RESET, 1);
gpiod_add_lookup_table(&audio_va_gpiod_table);
platform_add_devices(ARRAY_AND_SIZE(audio_regulator_devices)); platform_add_devices(ARRAY_AND_SIZE(audio_regulator_devices));
} }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/dm9000.h> #include <linux/dm9000.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
...@@ -410,7 +411,6 @@ static struct regulator_init_data can_regulator_init_data = { ...@@ -410,7 +411,6 @@ static struct regulator_init_data can_regulator_init_data = {
static struct fixed_voltage_config can_regulator_pdata = { static struct fixed_voltage_config can_regulator_pdata = {
.supply_name = "CAN_SHDN", .supply_name = "CAN_SHDN",
.microvolts = 3300000, .microvolts = 3300000,
.gpio = ZEUS_CAN_SHDN_GPIO,
.init_data = &can_regulator_init_data, .init_data = &can_regulator_init_data,
}; };
...@@ -422,6 +422,15 @@ static struct platform_device can_regulator_device = { ...@@ -422,6 +422,15 @@ static struct platform_device can_regulator_device = {
}, },
}; };
static struct gpiod_lookup_table can_regulator_gpiod_table = {
.dev_id = "reg-fixed-voltage.0",
.table = {
GPIO_LOOKUP("gpio-pxa", ZEUS_CAN_SHDN_GPIO,
NULL, GPIO_ACTIVE_HIGH),
{ },
},
};
static struct mcp251x_platform_data zeus_mcp2515_pdata = { static struct mcp251x_platform_data zeus_mcp2515_pdata = {
.oscillator_frequency = 16*1000*1000, .oscillator_frequency = 16*1000*1000,
}; };
...@@ -538,7 +547,6 @@ static struct regulator_init_data zeus_ohci_regulator_data = { ...@@ -538,7 +547,6 @@ static struct regulator_init_data zeus_ohci_regulator_data = {
static struct fixed_voltage_config zeus_ohci_regulator_config = { static struct fixed_voltage_config zeus_ohci_regulator_config = {
.supply_name = "vbus2", .supply_name = "vbus2",
.microvolts = 5000000, /* 5.0V */ .microvolts = 5000000, /* 5.0V */
.gpio = ZEUS_USB2_PWREN_GPIO,
.enable_high = 1, .enable_high = 1,
.startup_delay = 0, .startup_delay = 0,
.init_data = &zeus_ohci_regulator_data, .init_data = &zeus_ohci_regulator_data,
...@@ -552,6 +560,15 @@ static struct platform_device zeus_ohci_regulator_device = { ...@@ -552,6 +560,15 @@ static struct platform_device zeus_ohci_regulator_device = {
}, },
}; };
static struct gpiod_lookup_table zeus_ohci_regulator_gpiod_table = {
.dev_id = "reg-fixed-voltage.0",
.table = {
GPIO_LOOKUP("gpio-pxa", ZEUS_USB2_PWREN_GPIO,
NULL, GPIO_ACTIVE_HIGH),
{ },
},
};
static struct pxaohci_platform_data zeus_ohci_platform_data = { static struct pxaohci_platform_data zeus_ohci_platform_data = {
.port_mode = PMM_NPS_MODE, .port_mode = PMM_NPS_MODE,
/* Clear Power Control Polarity Low and set Power Sense /* Clear Power Control Polarity Low and set Power Sense
...@@ -855,6 +872,8 @@ static void __init zeus_init(void) ...@@ -855,6 +872,8 @@ static void __init zeus_init(void)
pxa2xx_mfp_config(ARRAY_AND_SIZE(zeus_pin_config)); pxa2xx_mfp_config(ARRAY_AND_SIZE(zeus_pin_config));
gpiod_add_lookup_table(&can_regulator_gpiod_table);
gpiod_add_lookup_table(&zeus_ohci_regulator_gpiod_table);
platform_add_devices(zeus_devices, ARRAY_SIZE(zeus_devices)); platform_add_devices(zeus_devices, ARRAY_SIZE(zeus_devices));
zeus_register_ohci(); zeus_register_ohci();
......
...@@ -352,7 +352,6 @@ static struct fixed_voltage_config wallvdd_pdata = { ...@@ -352,7 +352,6 @@ static struct fixed_voltage_config wallvdd_pdata = {
.supply_name = "WALLVDD", .supply_name = "WALLVDD",
.microvolts = 5000000, .microvolts = 5000000,
.init_data = &wallvdd_data, .init_data = &wallvdd_data,
.gpio = -EINVAL,
}; };
static struct platform_device wallvdd_device = { static struct platform_device wallvdd_device = {
......
...@@ -222,7 +222,6 @@ static struct fixed_voltage_config smdk6410_b_pwr_5v_pdata = { ...@@ -222,7 +222,6 @@ static struct fixed_voltage_config smdk6410_b_pwr_5v_pdata = {
.supply_name = "B_PWR_5V", .supply_name = "B_PWR_5V",
.microvolts = 5000000, .microvolts = 5000000,
.init_data = &smdk6410_b_pwr_5v_data, .init_data = &smdk6410_b_pwr_5v_data,
.gpio = -EINVAL,
}; };
static struct platform_device smdk6410_b_pwr_5v = { static struct platform_device smdk6410_b_pwr_5v = {
......
...@@ -101,7 +101,7 @@ static int __init assabet_init_gpio(void __iomem *reg, u32 def_val) ...@@ -101,7 +101,7 @@ static int __init assabet_init_gpio(void __iomem *reg, u32 def_val)
assabet_bcr_gc = gc; assabet_bcr_gc = gc;
return gc->base; return 0;
} }
/* /*
...@@ -471,6 +471,14 @@ static struct fixed_voltage_config assabet_cf_vcc_pdata __initdata = { ...@@ -471,6 +471,14 @@ static struct fixed_voltage_config assabet_cf_vcc_pdata __initdata = {
.enable_high = 1, .enable_high = 1,
}; };
static struct gpiod_lookup_table assabet_cf_vcc_gpio_table = {
.dev_id = "reg-fixed-voltage.0",
.table = {
GPIO_LOOKUP("assabet", 0, NULL, GPIO_ACTIVE_HIGH),
{ },
},
};
static void __init assabet_init(void) static void __init assabet_init(void)
{ {
/* /*
...@@ -517,9 +525,11 @@ static void __init assabet_init(void) ...@@ -517,9 +525,11 @@ static void __init assabet_init(void)
neponset_resources, ARRAY_SIZE(neponset_resources)); neponset_resources, ARRAY_SIZE(neponset_resources));
#endif #endif
} else { } else {
gpiod_add_lookup_table(&assabet_cf_vcc_gpio_table);
sa11x0_register_fixed_regulator(0, &assabet_cf_vcc_pdata, sa11x0_register_fixed_regulator(0, &assabet_cf_vcc_pdata,
assabet_cf_vcc_consumers, assabet_cf_vcc_consumers,
ARRAY_SIZE(assabet_cf_vcc_consumers)); ARRAY_SIZE(assabet_cf_vcc_consumers),
true);
} }
...@@ -802,7 +812,6 @@ fs_initcall(assabet_leds_init); ...@@ -802,7 +812,6 @@ fs_initcall(assabet_leds_init);
void __init assabet_init_irq(void) void __init assabet_init_irq(void)
{ {
unsigned int assabet_gpio_base;
u32 def_val; u32 def_val;
sa1100_init_irq(); sa1100_init_irq();
...@@ -817,9 +826,7 @@ void __init assabet_init_irq(void) ...@@ -817,9 +826,7 @@ void __init assabet_init_irq(void)
* *
* This must precede any driver calls to BCR_set() or BCR_clear(). * This must precede any driver calls to BCR_set() or BCR_clear().
*/ */
assabet_gpio_base = assabet_init_gpio((void *)&ASSABET_BCR, def_val); assabet_init_gpio((void *)&ASSABET_BCR, def_val);
assabet_cf_vcc_pdata.gpio = assabet_gpio_base + 0;
} }
MACHINE_START(ASSABET, "Intel-Assabet") MACHINE_START(ASSABET, "Intel-Assabet")
......
...@@ -348,7 +348,8 @@ void __init sa11x0_init_late(void) ...@@ -348,7 +348,8 @@ void __init sa11x0_init_late(void)
int __init sa11x0_register_fixed_regulator(int n, int __init sa11x0_register_fixed_regulator(int n,
struct fixed_voltage_config *cfg, struct fixed_voltage_config *cfg,
struct regulator_consumer_supply *supplies, unsigned num_supplies) struct regulator_consumer_supply *supplies, unsigned num_supplies,
bool uses_gpio)
{ {
struct regulator_init_data *id; struct regulator_init_data *id;
...@@ -356,7 +357,7 @@ int __init sa11x0_register_fixed_regulator(int n, ...@@ -356,7 +357,7 @@ int __init sa11x0_register_fixed_regulator(int n,
if (!cfg->init_data) if (!cfg->init_data)
return -ENOMEM; return -ENOMEM;
if (cfg->gpio < 0) if (!uses_gpio)
id->constraints.always_on = 1; id->constraints.always_on = 1;
id->constraints.name = cfg->supply_name; id->constraints.name = cfg->supply_name;
id->constraints.min_uV = cfg->microvolts; id->constraints.min_uV = cfg->microvolts;
......
...@@ -54,4 +54,5 @@ void sa11x0_register_pcmcia(int socket, struct gpiod_lookup_table *); ...@@ -54,4 +54,5 @@ void sa11x0_register_pcmcia(int socket, struct gpiod_lookup_table *);
struct fixed_voltage_config; struct fixed_voltage_config;
struct regulator_consumer_supply; struct regulator_consumer_supply;
int sa11x0_register_fixed_regulator(int n, struct fixed_voltage_config *cfg, int sa11x0_register_fixed_regulator(int n, struct fixed_voltage_config *cfg,
struct regulator_consumer_supply *supplies, unsigned num_supplies); struct regulator_consumer_supply *supplies, unsigned num_supplies,
bool uses_gpio);
...@@ -102,14 +102,14 @@ static struct fixed_voltage_config shannon_cf_vcc_pdata __initdata = { ...@@ -102,14 +102,14 @@ static struct fixed_voltage_config shannon_cf_vcc_pdata __initdata = {
.supply_name = "cf-power", .supply_name = "cf-power",
.microvolts = 3300000, .microvolts = 3300000,
.enabled_at_boot = 1, .enabled_at_boot = 1,
.gpio = -EINVAL,
}; };
static void __init shannon_init(void) static void __init shannon_init(void)
{ {
sa11x0_register_fixed_regulator(0, &shannon_cf_vcc_pdata, sa11x0_register_fixed_regulator(0, &shannon_cf_vcc_pdata,
shannon_cf_vcc_consumers, shannon_cf_vcc_consumers,
ARRAY_SIZE(shannon_cf_vcc_consumers)); ARRAY_SIZE(shannon_cf_vcc_consumers),
false);
sa11x0_register_pcmcia(0, &shannon_pcmcia0_gpio_table); sa11x0_register_pcmcia(0, &shannon_pcmcia0_gpio_table);
sa11x0_register_pcmcia(1, &shannon_pcmcia1_gpio_table); sa11x0_register_pcmcia(1, &shannon_pcmcia1_gpio_table);
sa11x0_ppc_configure_mcp(); sa11x0_ppc_configure_mcp();
......
...@@ -633,7 +633,6 @@ static struct regulator_init_data cn12_power_init_data = { ...@@ -633,7 +633,6 @@ static struct regulator_init_data cn12_power_init_data = {
static struct fixed_voltage_config cn12_power_info = { static struct fixed_voltage_config cn12_power_info = {
.supply_name = "CN12 SD/MMC Vdd", .supply_name = "CN12 SD/MMC Vdd",
.microvolts = 3300000, .microvolts = 3300000,
.gpio = GPIO_PTB7,
.enable_high = 1, .enable_high = 1,
.init_data = &cn12_power_init_data, .init_data = &cn12_power_init_data,
}; };
...@@ -646,6 +645,16 @@ static struct platform_device cn12_power = { ...@@ -646,6 +645,16 @@ static struct platform_device cn12_power = {
}, },
}; };
static struct gpiod_lookup_table cn12_power_gpiod_table = {
.dev_id = "reg-fixed-voltage.0",
.table = {
/* Offset 7 on port B */
GPIO_LOOKUP("sh7724_pfc", GPIO_PTB7,
NULL, GPIO_ACTIVE_HIGH),
{ },
},
};
#if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE) #if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE)
/* SDHI0 */ /* SDHI0 */
static struct regulator_consumer_supply sdhi0_power_consumers[] = static struct regulator_consumer_supply sdhi0_power_consumers[] =
...@@ -665,7 +674,6 @@ static struct regulator_init_data sdhi0_power_init_data = { ...@@ -665,7 +674,6 @@ static struct regulator_init_data sdhi0_power_init_data = {
static struct fixed_voltage_config sdhi0_power_info = { static struct fixed_voltage_config sdhi0_power_info = {
.supply_name = "CN11 SD/MMC Vdd", .supply_name = "CN11 SD/MMC Vdd",
.microvolts = 3300000, .microvolts = 3300000,
.gpio = GPIO_PTB6,
.enable_high = 1, .enable_high = 1,
.init_data = &sdhi0_power_init_data, .init_data = &sdhi0_power_init_data,
}; };
...@@ -678,6 +686,16 @@ static struct platform_device sdhi0_power = { ...@@ -678,6 +686,16 @@ static struct platform_device sdhi0_power = {
}, },
}; };
static struct gpiod_lookup_table sdhi0_power_gpiod_table = {
.dev_id = "reg-fixed-voltage.1",
.table = {
/* Offset 6 on port B */
GPIO_LOOKUP("sh7724_pfc", GPIO_PTB6,
NULL, GPIO_ACTIVE_HIGH),
{ },
},
};
static struct tmio_mmc_data sdhi0_info = { static struct tmio_mmc_data sdhi0_info = {
.chan_priv_tx = (void *)SHDMA_SLAVE_SDHI0_TX, .chan_priv_tx = (void *)SHDMA_SLAVE_SDHI0_TX,
.chan_priv_rx = (void *)SHDMA_SLAVE_SDHI0_RX, .chan_priv_rx = (void *)SHDMA_SLAVE_SDHI0_RX,
...@@ -1413,6 +1431,11 @@ static int __init arch_setup(void) ...@@ -1413,6 +1431,11 @@ static int __init arch_setup(void)
DMA_MEMORY_EXCLUSIVE); DMA_MEMORY_EXCLUSIVE);
platform_device_add(ecovec_ceu_devices[1]); platform_device_add(ecovec_ceu_devices[1]);
gpiod_add_lookup_table(&cn12_power_gpiod_table);
#if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE)
gpiod_add_lookup_table(&sdhi0_power_gpiod_table);
#endif
return platform_add_devices(ecovec_devices, return platform_add_devices(ecovec_devices,
ARRAY_SIZE(ecovec_devices)); ARRAY_SIZE(ecovec_devices));
} }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* of the License. * of the License.
*/ */
#include <linux/gpio.h> #include <linux/gpio/machine.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/regulator/fixed.h> #include <linux/regulator/fixed.h>
...@@ -43,7 +43,6 @@ static struct fixed_voltage_config bcm43xx_vmmc = { ...@@ -43,7 +43,6 @@ static struct fixed_voltage_config bcm43xx_vmmc = {
* real voltage and signaling are still 1.8V. * real voltage and signaling are still 1.8V.
*/ */
.microvolts = 2000000, /* 1.8V */ .microvolts = 2000000, /* 1.8V */
.gpio = -EINVAL,
.startup_delay = 250 * 1000, /* 250ms */ .startup_delay = 250 * 1000, /* 250ms */
.enable_high = 1, /* active high */ .enable_high = 1, /* active high */
.enabled_at_boot = 0, /* disabled at boot */ .enabled_at_boot = 0, /* disabled at boot */
...@@ -58,11 +57,23 @@ static struct platform_device bcm43xx_vmmc_regulator = { ...@@ -58,11 +57,23 @@ static struct platform_device bcm43xx_vmmc_regulator = {
}, },
}; };
static struct gpiod_lookup_table bcm43xx_vmmc_gpio_table = {
.dev_id = "reg-fixed-voltage.0",
.table = {
GPIO_LOOKUP("0000:00:0c.0", -1, NULL, GPIO_ACTIVE_LOW),
{}
},
};
static int __init bcm43xx_regulator_register(void) static int __init bcm43xx_regulator_register(void)
{ {
struct gpiod_lookup_table *table = &bcm43xx_vmmc_gpio_table;
struct gpiod_lookup *lookup = table->table;
int ret; int ret;
bcm43xx_vmmc.gpio = get_gpio_by_name(WLAN_SFI_GPIO_ENABLE_NAME); lookup[0].chip_hwnum = get_gpio_by_name(WLAN_SFI_GPIO_ENABLE_NAME);
gpiod_add_lookup_table(table);
ret = platform_device_register(&bcm43xx_vmmc_regulator); ret = platform_device_register(&bcm43xx_vmmc_regulator);
if (ret) { if (ret) {
pr_err("%s: vmmc regulator register failed\n", __func__); pr_err("%s: vmmc regulator register failed\n", __func__);
......
...@@ -3909,8 +3909,23 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, ...@@ -3909,8 +3909,23 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
* the device name as label * the device name as label
*/ */
status = gpiod_request(desc, con_id ? con_id : devname); status = gpiod_request(desc, con_id ? con_id : devname);
if (status < 0) if (status < 0) {
return ERR_PTR(status); if (status == -EBUSY && flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) {
/*
* This happens when there are several consumers for
* the same GPIO line: we just return here without
* further initialization. It is a bit if a hack.
* This is necessary to support fixed regulators.
*
* FIXME: Make this more sane and safe.
*/
dev_info(dev, "nonexclusive access to GPIO for %s\n",
con_id ? con_id : devname);
return desc;
} else {
return ERR_PTR(status);
}
}
status = gpiod_configure_flags(desc, con_id, lookupflags, flags); status = gpiod_configure_flags(desc, con_id, lookupflags, flags);
if (status < 0) { if (status < 0) {
......
...@@ -2,26 +2,21 @@ ...@@ -2,26 +2,21 @@
// //
// Copyright (C) 2018 ROHM Semiconductors // Copyright (C) 2018 ROHM Semiconductors
// //
// ROHM BD71837MWV PMIC driver // ROHM BD71837MWV and BD71847MWV PMIC driver
// //
// Datasheet available from // Datasheet for BD71837MWV available from
// https://www.rohm.com/datasheet/BD71837MWV/bd71837mwv-e // https://www.rohm.com/datasheet/BD71837MWV/bd71837mwv-e
#include <linux/gpio_keys.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/mfd/rohm-bd718x7.h> #include <linux/mfd/rohm-bd718x7.h>
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_device.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/types.h>
/*
* gpio_keys.h requires definiton of bool. It is brought in
* by above includes. Keep this as last until gpio_keys.h gets fixed.
*/
#include <linux/gpio_keys.h>
static const u8 supported_revisions[] = { 0xA2 /* BD71837 */ };
static struct gpio_keys_button button = { static struct gpio_keys_button button = {
.code = KEY_POWER, .code = KEY_POWER,
...@@ -35,42 +30,42 @@ static struct gpio_keys_platform_data bd718xx_powerkey_data = { ...@@ -35,42 +30,42 @@ static struct gpio_keys_platform_data bd718xx_powerkey_data = {
.name = "bd718xx-pwrkey", .name = "bd718xx-pwrkey",
}; };
static struct mfd_cell bd71837_mfd_cells[] = { static struct mfd_cell bd718xx_mfd_cells[] = {
{ {
.name = "gpio-keys", .name = "gpio-keys",
.platform_data = &bd718xx_powerkey_data, .platform_data = &bd718xx_powerkey_data,
.pdata_size = sizeof(bd718xx_powerkey_data), .pdata_size = sizeof(bd718xx_powerkey_data),
}, },
{ .name = "bd71837-clk", }, { .name = "bd718xx-clk", },
{ .name = "bd71837-pmic", }, { .name = "bd718xx-pmic", },
}; };
static const struct regmap_irq bd71837_irqs[] = { static const struct regmap_irq bd718xx_irqs[] = {
REGMAP_IRQ_REG(BD71837_INT_SWRST, 0, BD71837_INT_SWRST_MASK), REGMAP_IRQ_REG(BD718XX_INT_SWRST, 0, BD718XX_INT_SWRST_MASK),
REGMAP_IRQ_REG(BD71837_INT_PWRBTN_S, 0, BD71837_INT_PWRBTN_S_MASK), REGMAP_IRQ_REG(BD718XX_INT_PWRBTN_S, 0, BD718XX_INT_PWRBTN_S_MASK),
REGMAP_IRQ_REG(BD71837_INT_PWRBTN_L, 0, BD71837_INT_PWRBTN_L_MASK), REGMAP_IRQ_REG(BD718XX_INT_PWRBTN_L, 0, BD718XX_INT_PWRBTN_L_MASK),
REGMAP_IRQ_REG(BD71837_INT_PWRBTN, 0, BD71837_INT_PWRBTN_MASK), REGMAP_IRQ_REG(BD718XX_INT_PWRBTN, 0, BD718XX_INT_PWRBTN_MASK),
REGMAP_IRQ_REG(BD71837_INT_WDOG, 0, BD71837_INT_WDOG_MASK), REGMAP_IRQ_REG(BD718XX_INT_WDOG, 0, BD718XX_INT_WDOG_MASK),
REGMAP_IRQ_REG(BD71837_INT_ON_REQ, 0, BD71837_INT_ON_REQ_MASK), REGMAP_IRQ_REG(BD718XX_INT_ON_REQ, 0, BD718XX_INT_ON_REQ_MASK),
REGMAP_IRQ_REG(BD71837_INT_STBY_REQ, 0, BD71837_INT_STBY_REQ_MASK), REGMAP_IRQ_REG(BD718XX_INT_STBY_REQ, 0, BD718XX_INT_STBY_REQ_MASK),
}; };
static struct regmap_irq_chip bd71837_irq_chip = { static struct regmap_irq_chip bd718xx_irq_chip = {
.name = "bd71837-irq", .name = "bd718xx-irq",
.irqs = bd71837_irqs, .irqs = bd718xx_irqs,
.num_irqs = ARRAY_SIZE(bd71837_irqs), .num_irqs = ARRAY_SIZE(bd718xx_irqs),
.num_regs = 1, .num_regs = 1,
.irq_reg_stride = 1, .irq_reg_stride = 1,
.status_base = BD71837_REG_IRQ, .status_base = BD718XX_REG_IRQ,
.mask_base = BD71837_REG_MIRQ, .mask_base = BD718XX_REG_MIRQ,
.ack_base = BD71837_REG_IRQ, .ack_base = BD718XX_REG_IRQ,
.init_ack_masked = true, .init_ack_masked = true,
.mask_invert = false, .mask_invert = false,
}; };
static const struct regmap_range pmic_status_range = { static const struct regmap_range pmic_status_range = {
.range_min = BD71837_REG_IRQ, .range_min = BD718XX_REG_IRQ,
.range_max = BD71837_REG_POW_STATE, .range_max = BD718XX_REG_POW_STATE,
}; };
static const struct regmap_access_table volatile_regs = { static const struct regmap_access_table volatile_regs = {
...@@ -78,67 +73,53 @@ static const struct regmap_access_table volatile_regs = { ...@@ -78,67 +73,53 @@ static const struct regmap_access_table volatile_regs = {
.n_yes_ranges = 1, .n_yes_ranges = 1,
}; };
static const struct regmap_config bd71837_regmap_config = { static const struct regmap_config bd718xx_regmap_config = {
.reg_bits = 8, .reg_bits = 8,
.val_bits = 8, .val_bits = 8,
.volatile_table = &volatile_regs, .volatile_table = &volatile_regs,
.max_register = BD71837_MAX_REGISTER - 1, .max_register = BD718XX_MAX_REGISTER - 1,
.cache_type = REGCACHE_RBTREE, .cache_type = REGCACHE_RBTREE,
}; };
static int bd71837_i2c_probe(struct i2c_client *i2c, static int bd718xx_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct bd71837 *bd71837; struct bd718xx *bd718xx;
int ret, i; int ret;
unsigned int val;
bd71837 = devm_kzalloc(&i2c->dev, sizeof(struct bd71837), GFP_KERNEL);
if (!bd71837) if (!i2c->irq) {
return -ENOMEM;
bd71837->chip_irq = i2c->irq;
if (!bd71837->chip_irq) {
dev_err(&i2c->dev, "No IRQ configured\n"); dev_err(&i2c->dev, "No IRQ configured\n");
return -EINVAL; return -EINVAL;
} }
bd71837->dev = &i2c->dev; bd718xx = devm_kzalloc(&i2c->dev, sizeof(struct bd718xx), GFP_KERNEL);
dev_set_drvdata(&i2c->dev, bd71837);
bd71837->regmap = devm_regmap_init_i2c(i2c, &bd71837_regmap_config); if (!bd718xx)
if (IS_ERR(bd71837->regmap)) { return -ENOMEM;
dev_err(&i2c->dev, "regmap initialization failed\n");
return PTR_ERR(bd71837->regmap);
}
ret = regmap_read(bd71837->regmap, BD71837_REG_REV, &val); bd718xx->chip_irq = i2c->irq;
if (ret) { bd718xx->chip_type = (unsigned int)(uintptr_t)
dev_err(&i2c->dev, "Read BD71837_REG_DEVICE failed\n"); of_device_get_match_data(&i2c->dev);
return ret; bd718xx->dev = &i2c->dev;
} dev_set_drvdata(&i2c->dev, bd718xx);
for (i = 0; i < ARRAY_SIZE(supported_revisions); i++)
if (supported_revisions[i] == val)
break;
if (i == ARRAY_SIZE(supported_revisions)) { bd718xx->regmap = devm_regmap_init_i2c(i2c, &bd718xx_regmap_config);
dev_err(&i2c->dev, "Unsupported chip revision\n"); if (IS_ERR(bd718xx->regmap)) {
return -ENODEV; dev_err(&i2c->dev, "regmap initialization failed\n");
return PTR_ERR(bd718xx->regmap);
} }
ret = devm_regmap_add_irq_chip(&i2c->dev, bd71837->regmap, ret = devm_regmap_add_irq_chip(&i2c->dev, bd718xx->regmap,
bd71837->chip_irq, IRQF_ONESHOT, 0, bd718xx->chip_irq, IRQF_ONESHOT, 0,
&bd71837_irq_chip, &bd71837->irq_data); &bd718xx_irq_chip, &bd718xx->irq_data);
if (ret) { if (ret) {
dev_err(&i2c->dev, "Failed to add irq_chip\n"); dev_err(&i2c->dev, "Failed to add irq_chip\n");
return ret; return ret;
} }
/* Configure short press to 10 milliseconds */ /* Configure short press to 10 milliseconds */
ret = regmap_update_bits(bd71837->regmap, ret = regmap_update_bits(bd718xx->regmap,
BD71837_REG_PWRONCONFIG0, BD718XX_REG_PWRONCONFIG0,
BD718XX_PWRBTN_PRESS_DURATION_MASK, BD718XX_PWRBTN_PRESS_DURATION_MASK,
BD718XX_PWRBTN_SHORT_PRESS_10MS); BD718XX_PWRBTN_SHORT_PRESS_10MS);
if (ret) { if (ret) {
...@@ -148,8 +129,8 @@ static int bd71837_i2c_probe(struct i2c_client *i2c, ...@@ -148,8 +129,8 @@ static int bd71837_i2c_probe(struct i2c_client *i2c,
} }
/* Configure long press to 10 seconds */ /* Configure long press to 10 seconds */
ret = regmap_update_bits(bd71837->regmap, ret = regmap_update_bits(bd718xx->regmap,
BD71837_REG_PWRONCONFIG1, BD718XX_REG_PWRONCONFIG1,
BD718XX_PWRBTN_PRESS_DURATION_MASK, BD718XX_PWRBTN_PRESS_DURATION_MASK,
BD718XX_PWRBTN_LONG_PRESS_10S); BD718XX_PWRBTN_LONG_PRESS_10S);
...@@ -159,7 +140,7 @@ static int bd71837_i2c_probe(struct i2c_client *i2c, ...@@ -159,7 +140,7 @@ static int bd71837_i2c_probe(struct i2c_client *i2c,
return ret; return ret;
} }
ret = regmap_irq_get_virq(bd71837->irq_data, BD71837_INT_PWRBTN_S); ret = regmap_irq_get_virq(bd718xx->irq_data, BD718XX_INT_PWRBTN_S);
if (ret < 0) { if (ret < 0) {
dev_err(&i2c->dev, "Failed to get the IRQ\n"); dev_err(&i2c->dev, "Failed to get the IRQ\n");
...@@ -168,44 +149,51 @@ static int bd71837_i2c_probe(struct i2c_client *i2c, ...@@ -168,44 +149,51 @@ static int bd71837_i2c_probe(struct i2c_client *i2c,
button.irq = ret; button.irq = ret;
ret = devm_mfd_add_devices(bd71837->dev, PLATFORM_DEVID_AUTO, ret = devm_mfd_add_devices(bd718xx->dev, PLATFORM_DEVID_AUTO,
bd71837_mfd_cells, bd718xx_mfd_cells,
ARRAY_SIZE(bd71837_mfd_cells), NULL, 0, ARRAY_SIZE(bd718xx_mfd_cells), NULL, 0,
regmap_irq_get_domain(bd71837->irq_data)); regmap_irq_get_domain(bd718xx->irq_data));
if (ret) if (ret)
dev_err(&i2c->dev, "Failed to create subdevices\n"); dev_err(&i2c->dev, "Failed to create subdevices\n");
return ret; return ret;
} }
static const struct of_device_id bd71837_of_match[] = { static const struct of_device_id bd718xx_of_match[] = {
{ .compatible = "rohm,bd71837", }, {
.compatible = "rohm,bd71837",
.data = (void *)BD718XX_TYPE_BD71837,
},
{
.compatible = "rohm,bd71847",
.data = (void *)BD718XX_TYPE_BD71847,
},
{ } { }
}; };
MODULE_DEVICE_TABLE(of, bd71837_of_match); MODULE_DEVICE_TABLE(of, bd718xx_of_match);
static struct i2c_driver bd71837_i2c_driver = { static struct i2c_driver bd718xx_i2c_driver = {
.driver = { .driver = {
.name = "rohm-bd718x7", .name = "rohm-bd718x7",
.of_match_table = bd71837_of_match, .of_match_table = bd718xx_of_match,
}, },
.probe = bd71837_i2c_probe, .probe = bd718xx_i2c_probe,
}; };
static int __init bd71837_i2c_init(void) static int __init bd718xx_i2c_init(void)
{ {
return i2c_add_driver(&bd71837_i2c_driver); return i2c_add_driver(&bd718xx_i2c_driver);
} }
/* Initialise early so consumer devices can complete system boot */ /* Initialise early so consumer devices can complete system boot */
subsys_initcall(bd71837_i2c_init); subsys_initcall(bd718xx_i2c_init);
static void __exit bd71837_i2c_exit(void) static void __exit bd718xx_i2c_exit(void)
{ {
i2c_del_driver(&bd71837_i2c_driver); i2c_del_driver(&bd718xx_i2c_driver);
} }
module_exit(bd71837_i2c_exit); module_exit(bd718xx_i2c_exit);
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
MODULE_DESCRIPTION("ROHM BD71837 Power Management IC driver"); MODULE_DESCRIPTION("ROHM BD71837/BD71847 Power Management IC driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -189,7 +189,7 @@ config REGULATOR_BD718XX ...@@ -189,7 +189,7 @@ config REGULATOR_BD718XX
and LDO regulators. and LDO regulators.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called bd71837-regulator. will be called bd718x7-regulator.
config REGULATOR_BD9571MWV config REGULATOR_BD9571MWV
tristate "ROHM BD9571MWV Regulators" tristate "ROHM BD9571MWV Regulators"
...@@ -356,6 +356,13 @@ config REGULATOR_LM363X ...@@ -356,6 +356,13 @@ config REGULATOR_LM363X
One boost output voltage is configurable and always on. One boost output voltage is configurable and always on.
Other LDOs are used for the display module. Other LDOs are used for the display module.
config REGULATOR_LOCHNAGAR
tristate "Cirrus Logic Lochnagar regulator driver"
depends on MFD_LOCHNAGAR
help
This enables regulator support on the Cirrus Logic Lochnagar audio
development board.
config REGULATOR_LP3971 config REGULATOR_LP3971
tristate "National Semiconductors LP3971 PMIC regulator driver" tristate "National Semiconductors LP3971 PMIC regulator driver"
depends on I2C depends on I2C
...@@ -803,6 +810,18 @@ config REGULATOR_STM32_VREFBUF ...@@ -803,6 +810,18 @@ config REGULATOR_STM32_VREFBUF
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called stm32-vrefbuf. will be called stm32-vrefbuf.
config REGULATOR_STPMIC1
tristate "STMicroelectronics STPMIC1 PMIC Regulators"
depends on MFD_STPMIC1
help
This driver supports STMicroelectronics STPMIC1 PMIC voltage
regulators and switches. The STPMIC1 regulators supply power to
an application processor as well as to external system
peripherals such as DDR, Flash memories and system devices.
To compile this driver as a module, choose M here: the
module will be called stpmic1_regulator.
config REGULATOR_TI_ABB config REGULATOR_TI_ABB
tristate "TI Adaptive Body Bias on-chip LDO" tristate "TI Adaptive Body Bias on-chip LDO"
depends on ARCH_OMAP depends on ARCH_OMAP
......
...@@ -27,7 +27,7 @@ obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o ...@@ -27,7 +27,7 @@ obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o
obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o
obj-$(CONFIG_REGULATOR_BD718XX) += bd71837-regulator.o obj-$(CONFIG_REGULATOR_BD718XX) += bd718x7-regulator.o
obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o obj-$(CONFIG_REGULATOR_BD9571MWV) += bd9571mwv-regulator.o
obj-$(CONFIG_REGULATOR_DA903X) += da903x.o obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
...@@ -46,6 +46,7 @@ obj-$(CONFIG_REGULATOR_HI655X) += hi655x-regulator.o ...@@ -46,6 +46,7 @@ obj-$(CONFIG_REGULATOR_HI655X) += hi655x-regulator.o
obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o
obj-$(CONFIG_REGULATOR_LM363X) += lm363x-regulator.o obj-$(CONFIG_REGULATOR_LM363X) += lm363x-regulator.o
obj-$(CONFIG_REGULATOR_LOCHNAGAR) += lochnagar-regulator.o
obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o
obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o
...@@ -101,6 +102,7 @@ obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o ...@@ -101,6 +102,7 @@ obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
obj-$(CONFIG_REGULATOR_SC2731) += sc2731-regulator.o obj-$(CONFIG_REGULATOR_SC2731) += sc2731-regulator.o
obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o
obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
obj-$(CONFIG_REGULATOR_STPMIC1) += stpmic1_regulator.o
obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
obj-$(CONFIG_REGULATOR_SY8106A) += sy8106a-regulator.o obj-$(CONFIG_REGULATOR_SY8106A) += sy8106a-regulator.o
obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
......
...@@ -260,7 +260,7 @@ static int arizona_ldo1_common_init(struct platform_device *pdev, ...@@ -260,7 +260,7 @@ static int arizona_ldo1_common_init(struct platform_device *pdev,
* so clean up would happen at the wrong time * so clean up would happen at the wrong time
*/ */
config.ena_gpiod = gpiod_get_optional(parent_dev, "wlf,ldoena", config.ena_gpiod = gpiod_get_optional(parent_dev, "wlf,ldoena",
GPIOD_OUT_LOW); GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
if (IS_ERR(config.ena_gpiod)) if (IS_ERR(config.ena_gpiod))
return PTR_ERR(config.ena_gpiod); return PTR_ERR(config.ena_gpiod);
......
...@@ -509,10 +509,10 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) ...@@ -509,10 +509,10 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
/* /*
* AXP803/AXP813 DCDC work frequency setting has the same * AXP803/AXP813 DCDC work frequency setting has the same
* range and step as AXP22X, but at a different register. * range and step as AXP22X, but at a different register.
* Fall through to the check below.
* (See include/linux/mfd/axp20x.h) * (See include/linux/mfd/axp20x.h)
*/ */
reg = AXP803_DCDC_FREQ_CTRL; reg = AXP803_DCDC_FREQ_CTRL;
/* Fall through to the check below.*/
case AXP806_ID: case AXP806_ID:
/* /*
* AXP806 also have DCDC work frequency setting register at a * AXP806 also have DCDC work frequency setting register at a
...@@ -520,6 +520,7 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) ...@@ -520,6 +520,7 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
*/ */
if (axp20x->variant == AXP806_ID) if (axp20x->variant == AXP806_ID)
reg = AXP806_DCDC_FREQ_CTRL; reg = AXP806_DCDC_FREQ_CTRL;
/* Fall through */
case AXP221_ID: case AXP221_ID:
case AXP223_ID: case AXP223_ID:
case AXP809_ID: case AXP809_ID:
......
This diff is collapsed.
This diff is collapsed.
...@@ -426,19 +426,24 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr, ...@@ -426,19 +426,24 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr,
} }
static DEVICE_ATTR_RO(name); static DEVICE_ATTR_RO(name);
static ssize_t regulator_print_opmode(char *buf, int mode) static const char *regulator_opmode_to_str(int mode)
{ {
switch (mode) { switch (mode) {
case REGULATOR_MODE_FAST: case REGULATOR_MODE_FAST:
return sprintf(buf, "fast\n"); return "fast";
case REGULATOR_MODE_NORMAL: case REGULATOR_MODE_NORMAL:
return sprintf(buf, "normal\n"); return "normal";
case REGULATOR_MODE_IDLE: case REGULATOR_MODE_IDLE:
return sprintf(buf, "idle\n"); return "idle";
case REGULATOR_MODE_STANDBY: case REGULATOR_MODE_STANDBY:
return sprintf(buf, "standby\n"); return "standby";
} }
return sprintf(buf, "unknown\n"); return "unknown";
}
static ssize_t regulator_print_opmode(char *buf, int mode)
{
return sprintf(buf, "%s\n", regulator_opmode_to_str(mode));
} }
static ssize_t regulator_opmode_show(struct device *dev, static ssize_t regulator_opmode_show(struct device *dev,
...@@ -2783,6 +2788,11 @@ static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV, ...@@ -2783,6 +2788,11 @@ static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV,
if (desc->ops->list_voltage == regulator_list_voltage_linear_range) if (desc->ops->list_voltage == regulator_list_voltage_linear_range)
return regulator_map_voltage_linear_range(rdev, min_uV, max_uV); return regulator_map_voltage_linear_range(rdev, min_uV, max_uV);
if (desc->ops->list_voltage ==
regulator_list_voltage_pickable_linear_range)
return regulator_map_voltage_pickable_linear_range(rdev,
min_uV, max_uV);
return regulator_map_voltage_iterate(rdev, min_uV, max_uV); return regulator_map_voltage_iterate(rdev, min_uV, max_uV);
} }
...@@ -3470,21 +3480,23 @@ int regulator_set_current_limit(struct regulator *regulator, ...@@ -3470,21 +3480,23 @@ int regulator_set_current_limit(struct regulator *regulator,
} }
EXPORT_SYMBOL_GPL(regulator_set_current_limit); EXPORT_SYMBOL_GPL(regulator_set_current_limit);
static int _regulator_get_current_limit_unlocked(struct regulator_dev *rdev)
{
/* sanity check */
if (!rdev->desc->ops->get_current_limit)
return -EINVAL;
return rdev->desc->ops->get_current_limit(rdev);
}
static int _regulator_get_current_limit(struct regulator_dev *rdev) static int _regulator_get_current_limit(struct regulator_dev *rdev)
{ {
int ret; int ret;
regulator_lock(rdev); regulator_lock(rdev);
ret = _regulator_get_current_limit_unlocked(rdev);
/* sanity check */
if (!rdev->desc->ops->get_current_limit) {
ret = -EINVAL;
goto out;
}
ret = rdev->desc->ops->get_current_limit(rdev);
out:
regulator_unlock(rdev); regulator_unlock(rdev);
return ret; return ret;
} }
...@@ -3549,21 +3561,23 @@ int regulator_set_mode(struct regulator *regulator, unsigned int mode) ...@@ -3549,21 +3561,23 @@ int regulator_set_mode(struct regulator *regulator, unsigned int mode)
} }
EXPORT_SYMBOL_GPL(regulator_set_mode); EXPORT_SYMBOL_GPL(regulator_set_mode);
static unsigned int _regulator_get_mode_unlocked(struct regulator_dev *rdev)
{
/* sanity check */
if (!rdev->desc->ops->get_mode)
return -EINVAL;
return rdev->desc->ops->get_mode(rdev);
}
static unsigned int _regulator_get_mode(struct regulator_dev *rdev) static unsigned int _regulator_get_mode(struct regulator_dev *rdev)
{ {
int ret; int ret;
regulator_lock(rdev); regulator_lock(rdev);
ret = _regulator_get_mode_unlocked(rdev);
/* sanity check */
if (!rdev->desc->ops->get_mode) {
ret = -EINVAL;
goto out;
}
ret = rdev->desc->ops->get_mode(rdev);
out:
regulator_unlock(rdev); regulator_unlock(rdev);
return ret; return ret;
} }
...@@ -4455,41 +4469,33 @@ void regulator_unregister(struct regulator_dev *rdev) ...@@ -4455,41 +4469,33 @@ void regulator_unregister(struct regulator_dev *rdev)
EXPORT_SYMBOL_GPL(regulator_unregister); EXPORT_SYMBOL_GPL(regulator_unregister);
#ifdef CONFIG_SUSPEND #ifdef CONFIG_SUSPEND
static int _regulator_suspend(struct device *dev, void *data)
{
struct regulator_dev *rdev = dev_to_rdev(dev);
suspend_state_t *state = data;
int ret;
regulator_lock(rdev);
ret = suspend_set_state(rdev, *state);
regulator_unlock(rdev);
return ret;
}
/** /**
* regulator_suspend - prepare regulators for system wide suspend * regulator_suspend - prepare regulators for system wide suspend
* @state: system suspend state * @dev: ``&struct device`` pointer that is passed to _regulator_suspend()
* *
* Configure each regulator with it's suspend operating parameters for state. * Configure each regulator with it's suspend operating parameters for state.
*/ */
static int regulator_suspend(struct device *dev) static int regulator_suspend(struct device *dev)
{ {
struct regulator_dev *rdev = dev_to_rdev(dev);
suspend_state_t state = pm_suspend_target_state; suspend_state_t state = pm_suspend_target_state;
int ret;
regulator_lock(rdev);
ret = suspend_set_state(rdev, state);
regulator_unlock(rdev);
return class_for_each_device(&regulator_class, NULL, &state, return ret;
_regulator_suspend);
} }
static int _regulator_resume(struct device *dev, void *data) static int regulator_resume(struct device *dev)
{ {
int ret = 0; suspend_state_t state = pm_suspend_target_state;
struct regulator_dev *rdev = dev_to_rdev(dev); struct regulator_dev *rdev = dev_to_rdev(dev);
suspend_state_t *state = data;
struct regulator_state *rstate; struct regulator_state *rstate;
int ret = 0;
rstate = regulator_get_suspend_state(rdev, *state); rstate = regulator_get_suspend_state(rdev, state);
if (rstate == NULL) if (rstate == NULL)
return 0; return 0;
...@@ -4504,15 +4510,6 @@ static int _regulator_resume(struct device *dev, void *data) ...@@ -4504,15 +4510,6 @@ static int _regulator_resume(struct device *dev, void *data)
return ret; return ret;
} }
static int regulator_resume(struct device *dev)
{
suspend_state_t state = pm_suspend_target_state;
return class_for_each_device(&regulator_class, NULL, &state,
_regulator_resume);
}
#else /* !CONFIG_SUSPEND */ #else /* !CONFIG_SUSPEND */
#define regulator_suspend NULL #define regulator_suspend NULL
...@@ -4670,17 +4667,23 @@ static void regulator_summary_show_subtree(struct seq_file *s, ...@@ -4670,17 +4667,23 @@ static void regulator_summary_show_subtree(struct seq_file *s,
struct regulation_constraints *c; struct regulation_constraints *c;
struct regulator *consumer; struct regulator *consumer;
struct summary_data summary_data; struct summary_data summary_data;
unsigned int opmode;
if (!rdev) if (!rdev)
return; return;
seq_printf(s, "%*s%-*s %3d %4d %6d ", regulator_lock_nested(rdev, level);
opmode = _regulator_get_mode_unlocked(rdev);
seq_printf(s, "%*s%-*s %3d %4d %6d %7s ",
level * 3 + 1, "", level * 3 + 1, "",
30 - level * 3, rdev_get_name(rdev), 30 - level * 3, rdev_get_name(rdev),
rdev->use_count, rdev->open_count, rdev->bypass_count); rdev->use_count, rdev->open_count, rdev->bypass_count,
regulator_opmode_to_str(opmode));
seq_printf(s, "%5dmV ", _regulator_get_voltage(rdev) / 1000); seq_printf(s, "%5dmV ", _regulator_get_voltage(rdev) / 1000);
seq_printf(s, "%5dmA ", _regulator_get_current_limit(rdev) / 1000); seq_printf(s, "%5dmA ",
_regulator_get_current_limit_unlocked(rdev) / 1000);
c = rdev->constraints; c = rdev->constraints;
if (c) { if (c) {
...@@ -4709,7 +4712,8 @@ static void regulator_summary_show_subtree(struct seq_file *s, ...@@ -4709,7 +4712,8 @@ static void regulator_summary_show_subtree(struct seq_file *s,
switch (rdev->desc->type) { switch (rdev->desc->type) {
case REGULATOR_VOLTAGE: case REGULATOR_VOLTAGE:
seq_printf(s, "%37dmV %5dmV", seq_printf(s, "%37dmA %5dmV %5dmV",
consumer->uA_load / 1000,
consumer->voltage[PM_SUSPEND_ON].min_uV / 1000, consumer->voltage[PM_SUSPEND_ON].min_uV / 1000,
consumer->voltage[PM_SUSPEND_ON].max_uV / 1000); consumer->voltage[PM_SUSPEND_ON].max_uV / 1000);
break; break;
...@@ -4726,6 +4730,8 @@ static void regulator_summary_show_subtree(struct seq_file *s, ...@@ -4726,6 +4730,8 @@ static void regulator_summary_show_subtree(struct seq_file *s,
class_for_each_device(&regulator_class, NULL, &summary_data, class_for_each_device(&regulator_class, NULL, &summary_data,
regulator_summary_show_children); regulator_summary_show_children);
regulator_unlock(rdev);
} }
static int regulator_summary_show_roots(struct device *dev, void *data) static int regulator_summary_show_roots(struct device *dev, void *data)
...@@ -4741,8 +4747,8 @@ static int regulator_summary_show_roots(struct device *dev, void *data) ...@@ -4741,8 +4747,8 @@ static int regulator_summary_show_roots(struct device *dev, void *data)
static int regulator_summary_show(struct seq_file *s, void *data) static int regulator_summary_show(struct seq_file *s, void *data)
{ {
seq_puts(s, " regulator use open bypass voltage current min max\n"); seq_puts(s, " regulator use open bypass opmode voltage current min max\n");
seq_puts(s, "-------------------------------------------------------------------------------\n"); seq_puts(s, "---------------------------------------------------------------------------------------\n");
class_for_each_device(&regulator_class, NULL, s, class_for_each_device(&regulator_class, NULL, s,
regulator_summary_show_roots); regulator_summary_show_roots);
......
...@@ -420,7 +420,7 @@ static int da9052_regulator_probe(struct platform_device *pdev) ...@@ -420,7 +420,7 @@ static int da9052_regulator_probe(struct platform_device *pdev)
config.dev = &pdev->dev; config.dev = &pdev->dev;
config.driver_data = regulator; config.driver_data = regulator;
config.regmap = da9052->regmap; config.regmap = da9052->regmap;
if (pdata && pdata->regulators) { if (pdata) {
config.init_data = pdata->regulators[cell->id]; config.init_data = pdata->regulators[cell->id];
} else { } else {
#ifdef CONFIG_OF #ifdef CONFIG_OF
......
...@@ -612,7 +612,7 @@ static int da9055_regulator_probe(struct platform_device *pdev) ...@@ -612,7 +612,7 @@ static int da9055_regulator_probe(struct platform_device *pdev)
config.driver_data = regulator; config.driver_data = regulator;
config.regmap = da9055->regmap; config.regmap = da9055->regmap;
if (pdata && pdata->regulators) { if (pdata) {
config.init_data = pdata->regulators[pdev->id]; config.init_data = pdata->regulators[pdev->id];
} else { } else {
ret = da9055_regulator_dt_init(pdev, regulator, &config, ret = da9055_regulator_dt_init(pdev, regulator, &config,
......
...@@ -294,11 +294,11 @@ static struct da9211_pdata *da9211_parse_regulators_dt( ...@@ -294,11 +294,11 @@ static struct da9211_pdata *da9211_parse_regulators_dt(
pdata->init_data[n] = da9211_matches[i].init_data; pdata->init_data[n] = da9211_matches[i].init_data;
pdata->reg_node[n] = da9211_matches[i].of_node; pdata->reg_node[n] = da9211_matches[i].of_node;
pdata->gpiod_ren[n] = devm_gpiod_get_from_of_node(dev, pdata->gpiod_ren[n] = devm_gpiod_get_from_of_node(dev,
da9211_matches[i].of_node, da9211_matches[i].of_node,
"enable", "enable",
0, 0,
GPIOD_OUT_HIGH, GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
"da9211-enable"); "da9211-enable");
n++; n++;
} }
......
...@@ -43,7 +43,6 @@ struct platform_device *regulator_register_always_on(int id, const char *name, ...@@ -43,7 +43,6 @@ struct platform_device *regulator_register_always_on(int id, const char *name,
} }
data->cfg.microvolts = uv; data->cfg.microvolts = uv;
data->cfg.gpio = -EINVAL;
data->cfg.enabled_at_boot = 1; data->cfg.enabled_at_boot = 1;
data->cfg.init_data = &data->init_data; data->cfg.init_data = &data->init_data;
......
...@@ -24,10 +24,9 @@ ...@@ -24,10 +24,9 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>
#include <linux/regulator/fixed.h> #include <linux/regulator/fixed.h>
#include <linux/gpio.h> #include <linux/gpio/consumer.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/regulator/of_regulator.h> #include <linux/regulator/of_regulator.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
...@@ -78,15 +77,16 @@ of_get_fixed_voltage_config(struct device *dev, ...@@ -78,15 +77,16 @@ of_get_fixed_voltage_config(struct device *dev,
if (init_data->constraints.boot_on) if (init_data->constraints.boot_on)
config->enabled_at_boot = true; config->enabled_at_boot = true;
config->gpio = of_get_named_gpio(np, "gpio", 0);
if ((config->gpio < 0) && (config->gpio != -ENOENT))
return ERR_PTR(config->gpio);
of_property_read_u32(np, "startup-delay-us", &config->startup_delay); of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
config->enable_high = of_property_read_bool(np, "enable-active-high"); /*
config->gpio_is_open_drain = of_property_read_bool(np, * FIXME: we pulled active low/high and open drain handling into
"gpio-open-drain"); * gpiolib so it will be handled there. Delete this in the second
* step when we also remove the custom inversion handling for all
* legacy boardfiles.
*/
config->enable_high = 1;
config->gpio_is_open_drain = 0;
if (of_find_property(np, "vin-supply", NULL)) if (of_find_property(np, "vin-supply", NULL))
config->input_supply = "vin"; config->input_supply = "vin";
...@@ -102,6 +102,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) ...@@ -102,6 +102,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
struct fixed_voltage_config *config; struct fixed_voltage_config *config;
struct fixed_voltage_data *drvdata; struct fixed_voltage_data *drvdata;
struct regulator_config cfg = { }; struct regulator_config cfg = { };
enum gpiod_flags gflags;
int ret; int ret;
drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data), drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data),
...@@ -150,25 +151,41 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) ...@@ -150,25 +151,41 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
drvdata->desc.fixed_uV = config->microvolts; drvdata->desc.fixed_uV = config->microvolts;
if (gpio_is_valid(config->gpio)) {
cfg.ena_gpio = config->gpio;
if (pdev->dev.of_node)
cfg.ena_gpio_initialized = true;
}
cfg.ena_gpio_invert = !config->enable_high; cfg.ena_gpio_invert = !config->enable_high;
if (config->enabled_at_boot) { if (config->enabled_at_boot) {
if (config->enable_high) if (config->enable_high)
cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH; gflags = GPIOD_OUT_HIGH;
else else
cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW; gflags = GPIOD_OUT_LOW;
} else { } else {
if (config->enable_high) if (config->enable_high)
cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW; gflags = GPIOD_OUT_LOW;
else else
cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH; gflags = GPIOD_OUT_HIGH;
} }
if (config->gpio_is_open_drain) if (config->gpio_is_open_drain) {
cfg.ena_gpio_flags |= GPIOF_OPEN_DRAIN; if (gflags == GPIOD_OUT_HIGH)
gflags = GPIOD_OUT_HIGH_OPEN_DRAIN;
else
gflags = GPIOD_OUT_LOW_OPEN_DRAIN;
}
/*
* Some fixed regulators share the enable line between two
* regulators which makes it necessary to get a handle on the
* same descriptor for two different consumers. This will get
* the GPIO descriptor, but only the first call will initialize
* it so any flags such as inversion or open drain will only
* be set up by the first caller and assumed identical on the
* next caller.
*
* FIXME: find a better way to deal with this.
*/
gflags |= GPIOD_FLAGS_BIT_NONEXCLUSIVE;
cfg.ena_gpiod = devm_gpiod_get_optional(&pdev->dev, NULL, gflags);
if (IS_ERR(cfg.ena_gpiod))
return PTR_ERR(cfg.ena_gpiod);
cfg.dev = &pdev->dev; cfg.dev = &pdev->dev;
cfg.init_data = config->init_data; cfg.init_data = config->init_data;
......
...@@ -103,6 +103,128 @@ int regulator_disable_regmap(struct regulator_dev *rdev) ...@@ -103,6 +103,128 @@ int regulator_disable_regmap(struct regulator_dev *rdev)
} }
EXPORT_SYMBOL_GPL(regulator_disable_regmap); EXPORT_SYMBOL_GPL(regulator_disable_regmap);
static int regulator_range_selector_to_index(struct regulator_dev *rdev,
unsigned int rval)
{
int i;
if (!rdev->desc->linear_range_selectors)
return -EINVAL;
rval &= rdev->desc->vsel_range_mask;
for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
if (rdev->desc->linear_range_selectors[i] == rval)
return i;
}
return -EINVAL;
}
/**
* regulator_get_voltage_sel_pickable_regmap - pickable range get_voltage_sel
*
* @rdev: regulator to operate on
*
* Regulators that use regmap for their register I/O and use pickable
* ranges can set the vsel_reg, vsel_mask, vsel_range_reg and vsel_range_mask
* fields in their descriptor and then use this as their get_voltage_vsel
* operation, saving some code.
*/
int regulator_get_voltage_sel_pickable_regmap(struct regulator_dev *rdev)
{
unsigned int r_val;
int range;
unsigned int val;
int ret, i;
unsigned int voltages_in_range = 0;
if (!rdev->desc->linear_ranges)
return -EINVAL;
ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
if (ret != 0)
return ret;
ret = regmap_read(rdev->regmap, rdev->desc->vsel_range_reg, &r_val);
if (ret != 0)
return ret;
val &= rdev->desc->vsel_mask;
val >>= ffs(rdev->desc->vsel_mask) - 1;
range = regulator_range_selector_to_index(rdev, r_val);
if (range < 0)
return -EINVAL;
for (i = 0; i < range; i++)
voltages_in_range += (rdev->desc->linear_ranges[i].max_sel -
rdev->desc->linear_ranges[i].min_sel) + 1;
return val + voltages_in_range;
}
EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_pickable_regmap);
/**
* regulator_set_voltage_sel_pickable_regmap - pickable range set_voltage_sel
*
* @rdev: regulator to operate on
* @sel: Selector to set
*
* Regulators that use regmap for their register I/O and use pickable
* ranges can set the vsel_reg, vsel_mask, vsel_range_reg and vsel_range_mask
* fields in their descriptor and then use this as their set_voltage_vsel
* operation, saving some code.
*/
int regulator_set_voltage_sel_pickable_regmap(struct regulator_dev *rdev,
unsigned int sel)
{
unsigned int range;
int ret, i;
unsigned int voltages_in_range = 0;
for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
voltages_in_range = (rdev->desc->linear_ranges[i].max_sel -
rdev->desc->linear_ranges[i].min_sel) + 1;
if (sel < voltages_in_range)
break;
sel -= voltages_in_range;
}
if (i == rdev->desc->n_linear_ranges)
return -EINVAL;
sel <<= ffs(rdev->desc->vsel_mask) - 1;
sel += rdev->desc->linear_ranges[i].min_sel;
range = rdev->desc->linear_range_selectors[i];
if (rdev->desc->vsel_reg == rdev->desc->vsel_range_reg) {
ret = regmap_update_bits(rdev->regmap,
rdev->desc->vsel_reg,
rdev->desc->vsel_range_mask |
rdev->desc->vsel_mask, sel | range);
} else {
ret = regmap_update_bits(rdev->regmap,
rdev->desc->vsel_range_reg,
rdev->desc->vsel_range_mask, range);
if (ret)
return ret;
ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
rdev->desc->vsel_mask, sel);
}
if (ret)
return ret;
if (rdev->desc->apply_bit)
ret = regmap_update_bits(rdev->regmap, rdev->desc->apply_reg,
rdev->desc->apply_bit,
rdev->desc->apply_bit);
return ret;
}
EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_pickable_regmap);
/** /**
* regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users
* *
...@@ -321,20 +443,91 @@ int regulator_map_voltage_linear_range(struct regulator_dev *rdev, ...@@ -321,20 +443,91 @@ int regulator_map_voltage_linear_range(struct regulator_dev *rdev,
ret += range->min_sel; ret += range->min_sel;
break; /*
* Map back into a voltage to verify we're still in bounds.
* If we are not, then continue checking rest of the ranges.
*/
voltage = rdev->desc->ops->list_voltage(rdev, ret);
if (voltage >= min_uV && voltage <= max_uV)
break;
} }
if (i == rdev->desc->n_linear_ranges) if (i == rdev->desc->n_linear_ranges)
return -EINVAL; return -EINVAL;
/* Map back into a voltage to verify we're still in bounds */ return ret;
voltage = rdev->desc->ops->list_voltage(rdev, ret); }
if (voltage < min_uV || voltage > max_uV) EXPORT_SYMBOL_GPL(regulator_map_voltage_linear_range);
/**
* regulator_map_voltage_pickable_linear_range - map_voltage, pickable ranges
*
* @rdev: Regulator to operate on
* @min_uV: Lower bound for voltage
* @max_uV: Upper bound for voltage
*
* Drivers providing pickable linear_ranges in their descriptor can use
* this as their map_voltage() callback.
*/
int regulator_map_voltage_pickable_linear_range(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
const struct regulator_linear_range *range;
int ret = -EINVAL;
int voltage, i;
unsigned int selector = 0;
if (!rdev->desc->n_linear_ranges) {
BUG_ON(!rdev->desc->n_linear_ranges);
return -EINVAL;
}
for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
int linear_max_uV;
range = &rdev->desc->linear_ranges[i];
linear_max_uV = range->min_uV +
(range->max_sel - range->min_sel) * range->uV_step;
if (!(min_uV <= linear_max_uV && max_uV >= range->min_uV)) {
selector += (range->max_sel - range->min_sel + 1);
continue;
}
if (min_uV <= range->min_uV)
min_uV = range->min_uV;
/* range->uV_step == 0 means fixed voltage range */
if (range->uV_step == 0) {
ret = 0;
} else {
ret = DIV_ROUND_UP(min_uV - range->min_uV,
range->uV_step);
if (ret < 0)
return ret;
}
ret += selector;
voltage = rdev->desc->ops->list_voltage(rdev, ret);
/*
* Map back into a voltage to verify we're still in bounds.
* We may have overlapping voltage ranges. Hence we don't
* exit but retry until we have checked all ranges.
*/
if (voltage < min_uV || voltage > max_uV)
selector += (range->max_sel - range->min_sel + 1);
else
break;
}
if (i == rdev->desc->n_linear_ranges)
return -EINVAL; return -EINVAL;
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(regulator_map_voltage_linear_range); EXPORT_SYMBOL_GPL(regulator_map_voltage_pickable_linear_range);
/** /**
* regulator_list_voltage_linear - List voltages with simple calculation * regulator_list_voltage_linear - List voltages with simple calculation
...@@ -360,6 +553,46 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev, ...@@ -360,6 +553,46 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev,
} }
EXPORT_SYMBOL_GPL(regulator_list_voltage_linear); EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
/**
* regulator_list_voltage_pickable_linear_range - pickable range list voltages
*
* @rdev: Regulator device
* @selector: Selector to convert into a voltage
*
* list_voltage() operation, intended to be used by drivers utilizing pickable
* ranges helpers.
*/
int regulator_list_voltage_pickable_linear_range(struct regulator_dev *rdev,
unsigned int selector)
{
const struct regulator_linear_range *range;
int i;
unsigned int all_sels = 0;
if (!rdev->desc->n_linear_ranges) {
BUG_ON(!rdev->desc->n_linear_ranges);
return -EINVAL;
}
for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
unsigned int sels_in_range;
range = &rdev->desc->linear_ranges[i];
sels_in_range = range->max_sel - range->min_sel;
if (all_sels + sels_in_range >= selector) {
selector -= all_sels;
return range->min_uV + (range->uV_step * selector);
}
all_sels += (sels_in_range + 1);
}
return -EINVAL;
}
EXPORT_SYMBOL_GPL(regulator_list_voltage_pickable_linear_range);
/** /**
* regulator_list_voltage_linear_range - List voltages for linear ranges * regulator_list_voltage_linear_range - List voltages for linear ranges
* *
......
...@@ -84,6 +84,7 @@ static const struct regulator_desc isl9305_regulators[] = { ...@@ -84,6 +84,7 @@ static const struct regulator_desc isl9305_regulators[] = {
.enable_mask = ISL9305_DCD1_EN, .enable_mask = ISL9305_DCD1_EN,
.supply_name = "VINDCD1", .supply_name = "VINDCD1",
.ops = &isl9305_ops, .ops = &isl9305_ops,
.owner = THIS_MODULE,
}, },
[ISL9305_DCD2] = { [ISL9305_DCD2] = {
.name = "DCD2", .name = "DCD2",
...@@ -98,6 +99,7 @@ static const struct regulator_desc isl9305_regulators[] = { ...@@ -98,6 +99,7 @@ static const struct regulator_desc isl9305_regulators[] = {
.enable_mask = ISL9305_DCD2_EN, .enable_mask = ISL9305_DCD2_EN,
.supply_name = "VINDCD2", .supply_name = "VINDCD2",
.ops = &isl9305_ops, .ops = &isl9305_ops,
.owner = THIS_MODULE,
}, },
[ISL9305_LDO1] = { [ISL9305_LDO1] = {
.name = "LDO1", .name = "LDO1",
...@@ -112,6 +114,7 @@ static const struct regulator_desc isl9305_regulators[] = { ...@@ -112,6 +114,7 @@ static const struct regulator_desc isl9305_regulators[] = {
.enable_mask = ISL9305_LDO1_EN, .enable_mask = ISL9305_LDO1_EN,
.supply_name = "VINLDO1", .supply_name = "VINLDO1",
.ops = &isl9305_ops, .ops = &isl9305_ops,
.owner = THIS_MODULE,
}, },
[ISL9305_LDO2] = { [ISL9305_LDO2] = {
.name = "LDO2", .name = "LDO2",
...@@ -126,6 +129,7 @@ static const struct regulator_desc isl9305_regulators[] = { ...@@ -126,6 +129,7 @@ static const struct regulator_desc isl9305_regulators[] = {
.enable_mask = ISL9305_LDO2_EN, .enable_mask = ISL9305_LDO2_EN,
.supply_name = "VINLDO2", .supply_name = "VINLDO2",
.ops = &isl9305_ops, .ops = &isl9305_ops,
.owner = THIS_MODULE,
}, },
}; };
......
...@@ -227,9 +227,11 @@ static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev, ...@@ -227,9 +227,11 @@ static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev,
*/ */
switch (id) { switch (id) {
case LM3632_LDO_POS: case LM3632_LDO_POS:
return devm_gpiod_get_index_optional(dev, "enable", 0, GPIOD_OUT_LOW); return devm_gpiod_get_index_optional(dev, "enable", 0,
GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
case LM3632_LDO_NEG: case LM3632_LDO_NEG:
return devm_gpiod_get_index_optional(dev, "enable", 1, GPIOD_OUT_LOW); return devm_gpiod_get_index_optional(dev, "enable", 1,
GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
default: default:
return NULL; return NULL;
} }
......
// SPDX-License-Identifier: GPL-2.0
//
// Lochnagar regulator driver
//
// Copyright (c) 2017-2018 Cirrus Logic, Inc. and
// Cirrus Logic International Semiconductor Ltd.
//
// Author: Charles Keepax <ckeepax@opensource.cirrus.com>
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include <linux/mfd/lochnagar.h>
static const struct regulator_ops lochnagar_micvdd_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
};
static const struct regulator_linear_range lochnagar_micvdd_ranges[] = {
REGULATOR_LINEAR_RANGE(1000000, 0, 0xC, 50000),
REGULATOR_LINEAR_RANGE(1700000, 0xD, 0x1F, 100000),
};
static int lochnagar_micbias_enable(struct regulator_dev *rdev)
{
struct lochnagar *lochnagar = rdev_get_drvdata(rdev);
int ret;
mutex_lock(&lochnagar->analogue_config_lock);
ret = regulator_enable_regmap(rdev);
if (ret < 0)
goto err;
ret = lochnagar_update_config(lochnagar);
err:
mutex_unlock(&lochnagar->analogue_config_lock);
return ret;
}
static int lochnagar_micbias_disable(struct regulator_dev *rdev)
{
struct lochnagar *lochnagar = rdev_get_drvdata(rdev);
int ret;
mutex_lock(&lochnagar->analogue_config_lock);
ret = regulator_disable_regmap(rdev);
if (ret < 0)
goto err;
ret = lochnagar_update_config(lochnagar);
err:
mutex_unlock(&lochnagar->analogue_config_lock);
return ret;
}
static const struct regulator_ops lochnagar_micbias_ops = {
.enable = lochnagar_micbias_enable,
.disable = lochnagar_micbias_disable,
.is_enabled = regulator_is_enabled_regmap,
};
static const struct regulator_ops lochnagar_vddcore_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
};
static const struct regulator_linear_range lochnagar_vddcore_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0x8, 0x41, 12500),
};
enum lochnagar_regulators {
LOCHNAGAR_MICVDD,
LOCHNAGAR_MIC1VDD,
LOCHNAGAR_MIC2VDD,
LOCHNAGAR_VDDCORE,
};
static int lochnagar_micbias_of_parse(struct device_node *np,
const struct regulator_desc *desc,
struct regulator_config *config)
{
struct lochnagar *lochnagar = config->driver_data;
int shift = (desc->id - LOCHNAGAR_MIC1VDD) *
LOCHNAGAR2_P2_MICBIAS_SRC_SHIFT;
int mask = LOCHNAGAR2_P1_MICBIAS_SRC_MASK << shift;
unsigned int val;
int ret;
ret = of_property_read_u32(np, "cirrus,micbias-input", &val);
if (ret >= 0) {
mutex_lock(&lochnagar->analogue_config_lock);
ret = regmap_update_bits(lochnagar->regmap,
LOCHNAGAR2_ANALOGUE_PATH_CTRL2,
mask, val << shift);
mutex_unlock(&lochnagar->analogue_config_lock);
if (ret < 0) {
dev_err(lochnagar->dev,
"Failed to update micbias source: %d\n", ret);
return ret;
}
}
return 0;
}
static const struct regulator_desc lochnagar_regulators[] = {
[LOCHNAGAR_MICVDD] = {
.name = "MICVDD",
.supply_name = "SYSVDD",
.type = REGULATOR_VOLTAGE,
.n_voltages = 32,
.ops = &lochnagar_micvdd_ops,
.id = LOCHNAGAR_MICVDD,
.of_match = of_match_ptr("MICVDD"),
.enable_reg = LOCHNAGAR2_MICVDD_CTRL1,
.enable_mask = LOCHNAGAR2_MICVDD_REG_ENA_MASK,
.vsel_reg = LOCHNAGAR2_MICVDD_CTRL2,
.vsel_mask = LOCHNAGAR2_MICVDD_VSEL_MASK,
.linear_ranges = lochnagar_micvdd_ranges,
.n_linear_ranges = ARRAY_SIZE(lochnagar_micvdd_ranges),
.enable_time = 3000,
.ramp_delay = 1000,
.owner = THIS_MODULE,
},
[LOCHNAGAR_MIC1VDD] = {
.name = "MIC1VDD",
.supply_name = "MICBIAS1",
.type = REGULATOR_VOLTAGE,
.ops = &lochnagar_micbias_ops,
.id = LOCHNAGAR_MIC1VDD,
.of_match = of_match_ptr("MIC1VDD"),
.of_parse_cb = lochnagar_micbias_of_parse,
.enable_reg = LOCHNAGAR2_ANALOGUE_PATH_CTRL2,
.enable_mask = LOCHNAGAR2_P1_INPUT_BIAS_ENA_MASK,
.owner = THIS_MODULE,
},
[LOCHNAGAR_MIC2VDD] = {
.name = "MIC2VDD",
.supply_name = "MICBIAS2",
.type = REGULATOR_VOLTAGE,
.ops = &lochnagar_micbias_ops,
.id = LOCHNAGAR_MIC2VDD,
.of_match = of_match_ptr("MIC2VDD"),
.of_parse_cb = lochnagar_micbias_of_parse,
.enable_reg = LOCHNAGAR2_ANALOGUE_PATH_CTRL2,
.enable_mask = LOCHNAGAR2_P2_INPUT_BIAS_ENA_MASK,
.owner = THIS_MODULE,
},
[LOCHNAGAR_VDDCORE] = {
.name = "VDDCORE",
.supply_name = "SYSVDD",
.type = REGULATOR_VOLTAGE,
.n_voltages = 57,
.ops = &lochnagar_vddcore_ops,
.id = LOCHNAGAR_VDDCORE,
.of_match = of_match_ptr("VDDCORE"),
.enable_reg = LOCHNAGAR2_VDDCORE_CDC_CTRL1,
.enable_mask = LOCHNAGAR2_VDDCORE_CDC_REG_ENA_MASK,
.vsel_reg = LOCHNAGAR2_VDDCORE_CDC_CTRL2,
.vsel_mask = LOCHNAGAR2_VDDCORE_CDC_VSEL_MASK,
.linear_ranges = lochnagar_vddcore_ranges,
.n_linear_ranges = ARRAY_SIZE(lochnagar_vddcore_ranges),
.enable_time = 3000,
.ramp_delay = 1000,
.owner = THIS_MODULE,
},
};
static int lochnagar_regulator_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct lochnagar *lochnagar = dev_get_drvdata(dev->parent);
struct regulator_config config = { };
struct regulator_dev *rdev;
int ret, i;
config.dev = lochnagar->dev;
config.regmap = lochnagar->regmap;
config.driver_data = lochnagar;
for (i = 0; i < ARRAY_SIZE(lochnagar_regulators); i++) {
const struct regulator_desc *desc = &lochnagar_regulators[i];
rdev = devm_regulator_register(dev, desc, &config);
if (IS_ERR(rdev)) {
ret = PTR_ERR(rdev);
dev_err(dev, "Failed to register %s regulator: %d\n",
desc->name, ret);
return ret;
}
}
return 0;
}
static struct platform_driver lochnagar_regulator_driver = {
.driver = {
.name = "lochnagar-regulator",
},
.probe = lochnagar_regulator_probe,
};
module_platform_driver(lochnagar_regulator_driver);
MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>");
MODULE_DESCRIPTION("Regulator driver for Cirrus Logic Lochnagar Board");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:lochnagar-regulator");
...@@ -503,9 +503,10 @@ static int lp8788_config_ldo_enable_mode(struct platform_device *pdev, ...@@ -503,9 +503,10 @@ static int lp8788_config_ldo_enable_mode(struct platform_device *pdev,
/* FIXME: check default mode for GPIO here: high or low? */ /* FIXME: check default mode for GPIO here: high or low? */
ldo->ena_gpiod = devm_gpiod_get_index_optional(&pdev->dev, ldo->ena_gpiod = devm_gpiod_get_index_optional(&pdev->dev,
"enable", "enable",
enable_id, enable_id,
GPIOD_OUT_HIGH); GPIOD_OUT_HIGH |
GPIOD_FLAGS_BIT_NONEXCLUSIVE);
if (IS_ERR(ldo->ena_gpiod)) if (IS_ERR(ldo->ena_gpiod))
return PTR_ERR(ldo->ena_gpiod); return PTR_ERR(ldo->ena_gpiod);
......
...@@ -230,6 +230,7 @@ static int max8952_pmic_probe(struct i2c_client *client, ...@@ -230,6 +230,7 @@ static int max8952_pmic_probe(struct i2c_client *client,
gflags = GPIOD_OUT_HIGH; gflags = GPIOD_OUT_HIGH;
else else
gflags = GPIOD_OUT_LOW; gflags = GPIOD_OUT_LOW;
gflags |= GPIOD_FLAGS_BIT_NONEXCLUSIVE;
gpiod = devm_gpiod_get_optional(&client->dev, gpiod = devm_gpiod_get_optional(&client->dev,
"max8952,en", "max8952,en",
gflags); gflags);
......
...@@ -758,6 +758,7 @@ static int max8973_probe(struct i2c_client *client, ...@@ -758,6 +758,7 @@ static int max8973_probe(struct i2c_client *client,
gflags = GPIOD_OUT_HIGH; gflags = GPIOD_OUT_HIGH;
else else
gflags = GPIOD_OUT_LOW; gflags = GPIOD_OUT_LOW;
gflags |= GPIOD_FLAGS_BIT_NONEXCLUSIVE;
gpiod = devm_gpiod_get_optional(&client->dev, gpiod = devm_gpiod_get_optional(&client->dev,
"maxim,enable", "maxim,enable",
gflags); gflags);
......
...@@ -929,8 +929,8 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev, ...@@ -929,8 +929,8 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,
break; break;
if (i == ARRAY_SIZE(regulators)) { if (i == ARRAY_SIZE(regulators)) {
dev_warn(&pdev->dev, "don't know how to configure regulator %s\n", dev_warn(&pdev->dev, "don't know how to configure regulator %pOFn\n",
reg_np->name); reg_np);
continue; continue;
} }
......
...@@ -203,7 +203,7 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( ...@@ -203,7 +203,7 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
if (!found) if (!found)
dev_warn(&pdev->dev, dev_warn(&pdev->dev,
"Unknown regulator: %s\n", child->name); "Unknown regulator: %pOFn\n", child);
} }
of_node_put(parent); of_node_put(parent);
......
...@@ -95,8 +95,8 @@ static void of_get_regulation_constraints(struct device_node *np, ...@@ -95,8 +95,8 @@ static void of_get_regulation_constraints(struct device_node *np,
if (!ret) if (!ret)
constraints->settling_time_up = pval; constraints->settling_time_up = pval;
if (constraints->settling_time_up && constraints->settling_time) { if (constraints->settling_time_up && constraints->settling_time) {
pr_warn("%s: ambiguous configuration for settling time, ignoring 'regulator-settling-time-up-us'\n", pr_warn("%pOFn: ambiguous configuration for settling time, ignoring 'regulator-settling-time-up-us'\n",
np->name); np);
constraints->settling_time_up = 0; constraints->settling_time_up = 0;
} }
...@@ -105,8 +105,8 @@ static void of_get_regulation_constraints(struct device_node *np, ...@@ -105,8 +105,8 @@ static void of_get_regulation_constraints(struct device_node *np,
if (!ret) if (!ret)
constraints->settling_time_down = pval; constraints->settling_time_down = pval;
if (constraints->settling_time_down && constraints->settling_time) { if (constraints->settling_time_down && constraints->settling_time) {
pr_warn("%s: ambiguous configuration for settling time, ignoring 'regulator-settling-time-down-us'\n", pr_warn("%pOFn: ambiguous configuration for settling time, ignoring 'regulator-settling-time-down-us'\n",
np->name); np);
constraints->settling_time_down = 0; constraints->settling_time_down = 0;
} }
...@@ -127,12 +127,12 @@ static void of_get_regulation_constraints(struct device_node *np, ...@@ -127,12 +127,12 @@ static void of_get_regulation_constraints(struct device_node *np,
if (desc && desc->of_map_mode) { if (desc && desc->of_map_mode) {
mode = desc->of_map_mode(pval); mode = desc->of_map_mode(pval);
if (mode == REGULATOR_MODE_INVALID) if (mode == REGULATOR_MODE_INVALID)
pr_err("%s: invalid mode %u\n", np->name, pval); pr_err("%pOFn: invalid mode %u\n", np, pval);
else else
constraints->initial_mode = mode; constraints->initial_mode = mode;
} else { } else {
pr_warn("%s: mapping for mode %d not defined\n", pr_warn("%pOFn: mapping for mode %d not defined\n",
np->name, pval); np, pval);
} }
} }
...@@ -144,14 +144,14 @@ static void of_get_regulation_constraints(struct device_node *np, ...@@ -144,14 +144,14 @@ static void of_get_regulation_constraints(struct device_node *np,
ret = of_property_read_u32_index(np, ret = of_property_read_u32_index(np,
"regulator-allowed-modes", i, &pval); "regulator-allowed-modes", i, &pval);
if (ret) { if (ret) {
pr_err("%s: couldn't read allowed modes index %d, ret=%d\n", pr_err("%pOFn: couldn't read allowed modes index %d, ret=%d\n",
np->name, i, ret); np, i, ret);
break; break;
} }
mode = desc->of_map_mode(pval); mode = desc->of_map_mode(pval);
if (mode == REGULATOR_MODE_INVALID) if (mode == REGULATOR_MODE_INVALID)
pr_err("%s: invalid regulator-allowed-modes element %u\n", pr_err("%pOFn: invalid regulator-allowed-modes element %u\n",
np->name, pval); np, pval);
else else
constraints->valid_modes_mask |= mode; constraints->valid_modes_mask |= mode;
} }
...@@ -159,7 +159,7 @@ static void of_get_regulation_constraints(struct device_node *np, ...@@ -159,7 +159,7 @@ static void of_get_regulation_constraints(struct device_node *np,
constraints->valid_ops_mask constraints->valid_ops_mask
|= REGULATOR_CHANGE_MODE; |= REGULATOR_CHANGE_MODE;
} else { } else {
pr_warn("%s: mode mapping not defined\n", np->name); pr_warn("%pOFn: mode mapping not defined\n", np);
} }
} }
...@@ -197,13 +197,13 @@ static void of_get_regulation_constraints(struct device_node *np, ...@@ -197,13 +197,13 @@ static void of_get_regulation_constraints(struct device_node *np,
if (desc && desc->of_map_mode) { if (desc && desc->of_map_mode) {
mode = desc->of_map_mode(pval); mode = desc->of_map_mode(pval);
if (mode == REGULATOR_MODE_INVALID) if (mode == REGULATOR_MODE_INVALID)
pr_err("%s: invalid mode %u\n", pr_err("%pOFn: invalid mode %u\n",
np->name, pval); np, pval);
else else
suspend_state->mode = mode; suspend_state->mode = mode;
} else { } else {
pr_warn("%s: mapping for mode %d not defined\n", pr_warn("%pOFn: mapping for mode %d not defined\n",
np->name, pval); np, pval);
} }
} }
...@@ -349,8 +349,8 @@ int of_regulator_match(struct device *dev, struct device_node *node, ...@@ -349,8 +349,8 @@ int of_regulator_match(struct device *dev, struct device_node *node,
match->desc); match->desc);
if (!match->init_data) { if (!match->init_data) {
dev_err(dev, dev_err(dev,
"failed to parse DT for regulator %s\n", "failed to parse DT for regulator %pOFn\n",
child->name); child);
of_node_put(child); of_node_put(child);
return -EINVAL; return -EINVAL;
} }
...@@ -399,16 +399,16 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev, ...@@ -399,16 +399,16 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
init_data = of_get_regulator_init_data(dev, child, desc); init_data = of_get_regulator_init_data(dev, child, desc);
if (!init_data) { if (!init_data) {
dev_err(dev, dev_err(dev,
"failed to parse DT for regulator %s\n", "failed to parse DT for regulator %pOFn\n",
child->name); child);
break; break;
} }
if (desc->of_parse_cb) { if (desc->of_parse_cb) {
if (desc->of_parse_cb(child, desc, config)) { if (desc->of_parse_cb(child, desc, config)) {
dev_err(dev, dev_err(dev,
"driver callback failed to parse DT for regulator %s\n", "driver callback failed to parse DT for regulator %pOFn\n",
child->name); child);
init_data = NULL; init_data = NULL;
break; break;
} }
......
...@@ -31,11 +31,17 @@ ...@@ -31,11 +31,17 @@
#define PFUZE100_COINVOL 0x1a #define PFUZE100_COINVOL 0x1a
#define PFUZE100_SW1ABVOL 0x20 #define PFUZE100_SW1ABVOL 0x20
#define PFUZE100_SW1ABMODE 0x23
#define PFUZE100_SW1CVOL 0x2e #define PFUZE100_SW1CVOL 0x2e
#define PFUZE100_SW1CMODE 0x31
#define PFUZE100_SW2VOL 0x35 #define PFUZE100_SW2VOL 0x35
#define PFUZE100_SW2MODE 0x38
#define PFUZE100_SW3AVOL 0x3c #define PFUZE100_SW3AVOL 0x3c
#define PFUZE100_SW3AMODE 0x3f
#define PFUZE100_SW3BVOL 0x43 #define PFUZE100_SW3BVOL 0x43
#define PFUZE100_SW3BMODE 0x46
#define PFUZE100_SW4VOL 0x4a #define PFUZE100_SW4VOL 0x4a
#define PFUZE100_SW4MODE 0x4d
#define PFUZE100_SWBSTCON1 0x66 #define PFUZE100_SWBSTCON1 0x66
#define PFUZE100_VREFDDRCON 0x6a #define PFUZE100_VREFDDRCON 0x6a
#define PFUZE100_VSNVSVOL 0x6b #define PFUZE100_VSNVSVOL 0x6b
...@@ -46,6 +52,13 @@ ...@@ -46,6 +52,13 @@
#define PFUZE100_VGEN5VOL 0x70 #define PFUZE100_VGEN5VOL 0x70
#define PFUZE100_VGEN6VOL 0x71 #define PFUZE100_VGEN6VOL 0x71
#define PFUZE100_SWxMODE_MASK 0xf
#define PFUZE100_SWxMODE_APS_APS 0x8
#define PFUZE100_SWxMODE_APS_OFF 0x4
#define PFUZE100_VGENxLPWR BIT(6)
#define PFUZE100_VGENxSTBY BIT(5)
enum chips { PFUZE100, PFUZE200, PFUZE3000 = 3, PFUZE3001 = 0x31, }; enum chips { PFUZE100, PFUZE200, PFUZE3000 = 3, PFUZE3001 = 0x31, };
struct pfuze_regulator { struct pfuze_regulator {
...@@ -559,6 +572,69 @@ static inline struct device_node *match_of_node(int index) ...@@ -559,6 +572,69 @@ static inline struct device_node *match_of_node(int index)
} }
#endif #endif
static struct pfuze_chip *syspm_pfuze_chip;
static void pfuze_power_off_prepare(void)
{
dev_info(syspm_pfuze_chip->dev, "Configure standby mode for power off");
/* Switch from default mode: APS/APS to APS/Off */
regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_SW1ABMODE,
PFUZE100_SWxMODE_MASK, PFUZE100_SWxMODE_APS_OFF);
regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_SW1CMODE,
PFUZE100_SWxMODE_MASK, PFUZE100_SWxMODE_APS_OFF);
regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_SW2MODE,
PFUZE100_SWxMODE_MASK, PFUZE100_SWxMODE_APS_OFF);
regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_SW3AMODE,
PFUZE100_SWxMODE_MASK, PFUZE100_SWxMODE_APS_OFF);
regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_SW3BMODE,
PFUZE100_SWxMODE_MASK, PFUZE100_SWxMODE_APS_OFF);
regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_SW4MODE,
PFUZE100_SWxMODE_MASK, PFUZE100_SWxMODE_APS_OFF);
regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_VGEN1VOL,
PFUZE100_VGENxLPWR | PFUZE100_VGENxSTBY,
PFUZE100_VGENxSTBY);
regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_VGEN2VOL,
PFUZE100_VGENxLPWR | PFUZE100_VGENxSTBY,
PFUZE100_VGENxSTBY);
regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_VGEN3VOL,
PFUZE100_VGENxLPWR | PFUZE100_VGENxSTBY,
PFUZE100_VGENxSTBY);
regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_VGEN4VOL,
PFUZE100_VGENxLPWR | PFUZE100_VGENxSTBY,
PFUZE100_VGENxSTBY);
regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_VGEN5VOL,
PFUZE100_VGENxLPWR | PFUZE100_VGENxSTBY,
PFUZE100_VGENxSTBY);
regmap_update_bits(syspm_pfuze_chip->regmap, PFUZE100_VGEN6VOL,
PFUZE100_VGENxLPWR | PFUZE100_VGENxSTBY,
PFUZE100_VGENxSTBY);
}
static int pfuze_power_off_prepare_init(struct pfuze_chip *pfuze_chip)
{
if (pfuze_chip->chip_id != PFUZE100) {
dev_warn(pfuze_chip->dev, "Requested pm_power_off_prepare handler for not supported chip\n");
return -ENODEV;
}
if (pm_power_off_prepare) {
dev_warn(pfuze_chip->dev, "pm_power_off_prepare is already registered.\n");
return -EBUSY;
}
if (syspm_pfuze_chip) {
dev_warn(pfuze_chip->dev, "syspm_pfuze_chip is already set.\n");
return -EBUSY;
}
syspm_pfuze_chip = pfuze_chip;
pm_power_off_prepare = pfuze_power_off_prepare;
return 0;
}
static int pfuze_identify(struct pfuze_chip *pfuze_chip) static int pfuze_identify(struct pfuze_chip *pfuze_chip)
{ {
unsigned int value; unsigned int value;
...@@ -753,6 +829,20 @@ static int pfuze100_regulator_probe(struct i2c_client *client, ...@@ -753,6 +829,20 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
} }
} }
if (of_property_read_bool(client->dev.of_node,
"fsl,pmic-stby-poweroff"))
return pfuze_power_off_prepare_init(pfuze_chip);
return 0;
}
static int pfuze100_regulator_remove(struct i2c_client *client)
{
if (syspm_pfuze_chip) {
syspm_pfuze_chip = NULL;
pm_power_off_prepare = NULL;
}
return 0; return 0;
} }
...@@ -763,6 +853,7 @@ static struct i2c_driver pfuze_driver = { ...@@ -763,6 +853,7 @@ static struct i2c_driver pfuze_driver = {
.of_match_table = pfuze_dt_ids, .of_match_table = pfuze_dt_ids,
}, },
.probe = pfuze100_regulator_probe, .probe = pfuze100_regulator_probe,
.remove = pfuze100_regulator_remove,
}; };
module_i2c_driver(pfuze_driver); module_i2c_driver(pfuze_driver);
......
...@@ -414,7 +414,7 @@ static int rpmh_regulator_init_vreg(struct rpmh_vreg *vreg, struct device *dev, ...@@ -414,7 +414,7 @@ static int rpmh_regulator_init_vreg(struct rpmh_vreg *vreg, struct device *dev,
break; break;
if (!rpmh_data->name) { if (!rpmh_data->name) {
dev_err(dev, "Unknown regulator %s\n", node->name); dev_err(dev, "Unknown regulator %pOFn\n", node);
return -EINVAL; return -EINVAL;
} }
...@@ -423,8 +423,8 @@ static int rpmh_regulator_init_vreg(struct rpmh_vreg *vreg, struct device *dev, ...@@ -423,8 +423,8 @@ static int rpmh_regulator_init_vreg(struct rpmh_vreg *vreg, struct device *dev,
vreg->addr = cmd_db_read_addr(rpmh_resource_name); vreg->addr = cmd_db_read_addr(rpmh_resource_name);
if (!vreg->addr) { if (!vreg->addr) {
dev_err(dev, "%s: could not find RPMh address for resource %s\n", dev_err(dev, "%pOFn: could not find RPMh address for resource %s\n",
node->name, rpmh_resource_name); node, rpmh_resource_name);
return -ENODEV; return -ENODEV;
} }
...@@ -469,13 +469,13 @@ static int rpmh_regulator_init_vreg(struct rpmh_vreg *vreg, struct device *dev, ...@@ -469,13 +469,13 @@ static int rpmh_regulator_init_vreg(struct rpmh_vreg *vreg, struct device *dev,
rdev = devm_regulator_register(dev, &vreg->rdesc, &reg_config); rdev = devm_regulator_register(dev, &vreg->rdesc, &reg_config);
if (IS_ERR(rdev)) { if (IS_ERR(rdev)) {
ret = PTR_ERR(rdev); ret = PTR_ERR(rdev);
dev_err(dev, "%s: devm_regulator_register() failed, ret=%d\n", dev_err(dev, "%pOFn: devm_regulator_register() failed, ret=%d\n",
node->name, ret); node, ret);
return ret; return ret;
} }
dev_dbg(dev, "%s regulator registered for RPMh resource %s @ 0x%05X\n", dev_dbg(dev, "%pOFn regulator registered for RPMh resource %s @ 0x%05X\n",
node->name, rpmh_resource_name, vreg->addr); node, rpmh_resource_name, vreg->addr);
return 0; return 0;
} }
...@@ -504,6 +504,7 @@ static unsigned int rpmh_regulator_pmic4_ldo_of_map_mode(unsigned int rpmh_mode) ...@@ -504,6 +504,7 @@ static unsigned int rpmh_regulator_pmic4_ldo_of_map_mode(unsigned int rpmh_mode)
break; break;
default: default:
mode = REGULATOR_MODE_INVALID; mode = REGULATOR_MODE_INVALID;
break;
} }
return mode; return mode;
...@@ -537,6 +538,7 @@ rpmh_regulator_pmic4_smps_of_map_mode(unsigned int rpmh_mode) ...@@ -537,6 +538,7 @@ rpmh_regulator_pmic4_smps_of_map_mode(unsigned int rpmh_mode)
break; break;
default: default:
mode = REGULATOR_MODE_INVALID; mode = REGULATOR_MODE_INVALID;
break;
} }
return mode; return mode;
...@@ -566,6 +568,7 @@ static unsigned int rpmh_regulator_pmic4_bob_of_map_mode(unsigned int rpmh_mode) ...@@ -566,6 +568,7 @@ static unsigned int rpmh_regulator_pmic4_bob_of_map_mode(unsigned int rpmh_mode)
break; break;
default: default:
mode = REGULATOR_MODE_INVALID; mode = REGULATOR_MODE_INVALID;
break;
} }
return mode; return mode;
......
...@@ -420,6 +420,60 @@ static const struct regulator_desc pmi8998_bob = { ...@@ -420,6 +420,60 @@ static const struct regulator_desc pmi8998_bob = {
.ops = &rpm_bob_ops, .ops = &rpm_bob_ops,
}; };
static const struct regulator_desc pms405_hfsmps3 = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(320000, 0, 215, 8000),
},
.n_linear_ranges = 1,
.n_voltages = 216,
.ops = &rpm_smps_ldo_ops,
};
static const struct regulator_desc pms405_nldo300 = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(312000, 0, 127, 8000),
},
.n_linear_ranges = 1,
.n_voltages = 128,
.ops = &rpm_smps_ldo_ops,
};
static const struct regulator_desc pms405_nldo1200 = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(312000, 0, 127, 8000),
},
.n_linear_ranges = 1,
.n_voltages = 128,
.ops = &rpm_smps_ldo_ops,
};
static const struct regulator_desc pms405_pldo50 = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(1664000, 0, 128, 16000),
},
.n_linear_ranges = 1,
.n_voltages = 129,
.ops = &rpm_smps_ldo_ops,
};
static const struct regulator_desc pms405_pldo150 = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(1664000, 0, 128, 16000),
},
.n_linear_ranges = 1,
.n_voltages = 129,
.ops = &rpm_smps_ldo_ops,
};
static const struct regulator_desc pms405_pldo600 = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(1256000, 0, 98, 8000),
},
.n_linear_ranges = 1,
.n_voltages = 99,
.ops = &rpm_smps_ldo_ops,
};
struct rpm_regulator_data { struct rpm_regulator_data {
const char *name; const char *name;
u32 type; u32 type;
...@@ -661,6 +715,28 @@ static const struct rpm_regulator_data rpm_pmi8998_regulators[] = { ...@@ -661,6 +715,28 @@ static const struct rpm_regulator_data rpm_pmi8998_regulators[] = {
{} {}
}; };
static const struct rpm_regulator_data rpm_pms405_regulators[] = {
{ "s1", QCOM_SMD_RPM_SMPA, 1, &pms405_hfsmps3, "vdd_s1" },
{ "s2", QCOM_SMD_RPM_SMPA, 2, &pms405_hfsmps3, "vdd_s2" },
{ "s3", QCOM_SMD_RPM_SMPA, 3, &pms405_hfsmps3, "vdd_s3" },
{ "s4", QCOM_SMD_RPM_SMPA, 4, &pms405_hfsmps3, "vdd_s4" },
{ "s5", QCOM_SMD_RPM_SMPA, 5, &pms405_hfsmps3, "vdd_s5" },
{ "l1", QCOM_SMD_RPM_LDOA, 1, &pms405_nldo1200, "vdd_l1_l2" },
{ "l2", QCOM_SMD_RPM_LDOA, 2, &pms405_nldo1200, "vdd_l1_l2" },
{ "l3", QCOM_SMD_RPM_LDOA, 3, &pms405_nldo1200, "vdd_l3_l8" },
{ "l4", QCOM_SMD_RPM_LDOA, 4, &pms405_nldo300, "vdd_l4" },
{ "l5", QCOM_SMD_RPM_LDOA, 5, &pms405_pldo600, "vdd_l5_l6" },
{ "l6", QCOM_SMD_RPM_LDOA, 6, &pms405_pldo600, "vdd_l5_l6" },
{ "l7", QCOM_SMD_RPM_LDOA, 7, &pms405_pldo150, "vdd_l7" },
{ "l8", QCOM_SMD_RPM_LDOA, 8, &pms405_nldo1200, "vdd_l3_l8" },
{ "l9", QCOM_SMD_RPM_LDOA, 9, &pms405_nldo1200, "vdd_l9" },
{ "l10", QCOM_SMD_RPM_LDOA, 10, &pms405_pldo50, "vdd_l10_l11_l12_l13" },
{ "l11", QCOM_SMD_RPM_LDOA, 11, &pms405_pldo150, "vdd_l10_l11_l12_l13" },
{ "l12", QCOM_SMD_RPM_LDOA, 12, &pms405_pldo150, "vdd_l10_l11_l12_l13" },
{ "l13", QCOM_SMD_RPM_LDOA, 13, &pms405_pldo150, "vdd_l10_l11_l12_l13" },
{}
};
static const struct of_device_id rpm_of_match[] = { static const struct of_device_id rpm_of_match[] = {
{ .compatible = "qcom,rpm-pm8841-regulators", .data = &rpm_pm8841_regulators }, { .compatible = "qcom,rpm-pm8841-regulators", .data = &rpm_pm8841_regulators },
{ .compatible = "qcom,rpm-pm8916-regulators", .data = &rpm_pm8916_regulators }, { .compatible = "qcom,rpm-pm8916-regulators", .data = &rpm_pm8916_regulators },
...@@ -669,6 +745,7 @@ static const struct of_device_id rpm_of_match[] = { ...@@ -669,6 +745,7 @@ static const struct of_device_id rpm_of_match[] = {
{ .compatible = "qcom,rpm-pm8998-regulators", .data = &rpm_pm8998_regulators }, { .compatible = "qcom,rpm-pm8998-regulators", .data = &rpm_pm8998_regulators },
{ .compatible = "qcom,rpm-pma8084-regulators", .data = &rpm_pma8084_regulators }, { .compatible = "qcom,rpm-pma8084-regulators", .data = &rpm_pma8084_regulators },
{ .compatible = "qcom,rpm-pmi8998-regulators", .data = &rpm_pmi8998_regulators }, { .compatible = "qcom,rpm-pmi8998-regulators", .data = &rpm_pmi8998_regulators },
{ .compatible = "qcom,rpm-pms405-regulators", .data = &rpm_pms405_regulators },
{} {}
}; };
MODULE_DEVICE_TABLE(of, rpm_of_match); MODULE_DEVICE_TABLE(of, rpm_of_match);
......
...@@ -447,15 +447,15 @@ static void s5m8767_regulator_config_ext_control(struct s5m8767_info *s5m8767, ...@@ -447,15 +447,15 @@ static void s5m8767_regulator_config_ext_control(struct s5m8767_info *s5m8767,
} }
if (mode != S5M8767_ENCTRL_USE_GPIO) { if (mode != S5M8767_ENCTRL_USE_GPIO) {
dev_warn(s5m8767->dev, dev_warn(s5m8767->dev,
"ext-control for %s: mismatched op_mode (%x), ignoring\n", "ext-control for %pOFn: mismatched op_mode (%x), ignoring\n",
rdata->reg_node->name, mode); rdata->reg_node, mode);
return; return;
} }
if (!rdata->ext_control_gpiod) { if (!rdata->ext_control_gpiod) {
dev_warn(s5m8767->dev, dev_warn(s5m8767->dev,
"ext-control for %s: GPIO not valid, ignoring\n", "ext-control for %pOFn: GPIO not valid, ignoring\n",
rdata->reg_node->name); rdata->reg_node);
return; return;
} }
...@@ -566,17 +566,18 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, ...@@ -566,17 +566,18 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
if (i == ARRAY_SIZE(regulators)) { if (i == ARRAY_SIZE(regulators)) {
dev_warn(iodev->dev, dev_warn(iodev->dev,
"don't know how to configure regulator %s\n", "don't know how to configure regulator %pOFn\n",
reg_np->name); reg_np);
continue; continue;
} }
rdata->ext_control_gpiod = devm_gpiod_get_from_of_node(&pdev->dev, rdata->ext_control_gpiod = devm_gpiod_get_from_of_node(
reg_np, &pdev->dev,
"s5m8767,pmic-ext-control-gpios", reg_np,
0, "s5m8767,pmic-ext-control-gpios",
GPIOD_OUT_HIGH, 0,
"s5m8767"); GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
"s5m8767");
if (IS_ERR(rdata->ext_control_gpiod)) if (IS_ERR(rdata->ext_control_gpiod))
return PTR_ERR(rdata->ext_control_gpiod); return PTR_ERR(rdata->ext_control_gpiod);
......
This diff is collapsed.
...@@ -374,6 +374,7 @@ static struct tps65090_platform_data *tps65090_parse_dt_reg_data( ...@@ -374,6 +374,7 @@ static struct tps65090_platform_data *tps65090_parse_dt_reg_data(
gflags = GPIOD_OUT_HIGH; gflags = GPIOD_OUT_HIGH;
else else
gflags = GPIOD_OUT_LOW; gflags = GPIOD_OUT_LOW;
gflags |= GPIOD_FLAGS_BIT_NONEXCLUSIVE;
rpdata->gpiod = devm_gpiod_get_from_of_node(&pdev->dev, rpdata->gpiod = devm_gpiod_get_from_of_node(&pdev->dev,
tps65090_matches[idx].of_node, tps65090_matches[idx].of_node,
......
...@@ -30,6 +30,7 @@ struct gpio_descs { ...@@ -30,6 +30,7 @@ struct gpio_descs {
#define GPIOD_FLAGS_BIT_DIR_OUT BIT(1) #define GPIOD_FLAGS_BIT_DIR_OUT BIT(1)
#define GPIOD_FLAGS_BIT_DIR_VAL BIT(2) #define GPIOD_FLAGS_BIT_DIR_VAL BIT(2)
#define GPIOD_FLAGS_BIT_OPEN_DRAIN BIT(3) #define GPIOD_FLAGS_BIT_OPEN_DRAIN BIT(3)
#define GPIOD_FLAGS_BIT_NONEXCLUSIVE BIT(4)
/** /**
* Optional flags that can be passed to one of gpiod_* to configure direction * Optional flags that can be passed to one of gpiod_* to configure direction
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -49,6 +49,7 @@ int reboot_force; ...@@ -49,6 +49,7 @@ int reboot_force;
*/ */
void (*pm_power_off_prepare)(void); void (*pm_power_off_prepare)(void);
EXPORT_SYMBOL_GPL(pm_power_off_prepare);
/** /**
* emergency_restart - reboot the system * emergency_restart - reboot the system
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment