diff options
20 files changed, 2487 insertions, 278 deletions
diff --git a/Documentation/devicetree/bindings/regulator/fan53555.txt b/Documentation/devicetree/bindings/regulator/fan53555.txt new file mode 100644 index 000000000000..54a3f2c80e3a --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/fan53555.txt | |||
@@ -0,0 +1,23 @@ | |||
1 | Binding for Fairchild FAN53555 regulators | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: one of "fcs,fan53555", "silergy,syr827", "silergy,syr828" | ||
5 | - reg: I2C address | ||
6 | |||
7 | Optional properties: | ||
8 | - fcs,suspend-voltage-selector: declare which of the two available | ||
9 | voltage selector registers should be used for the suspend | ||
10 | voltage. The other one is used for the runtime voltage setting | ||
11 | Possible values are either <0> or <1> | ||
12 | - vin-supply: regulator supplying the vin pin | ||
13 | |||
14 | Example: | ||
15 | |||
16 | regulator@40 { | ||
17 | compatible = "fcs,fan53555"; | ||
18 | regulator-name = "fan53555"; | ||
19 | regulator-min-microvolt = <1000000>; | ||
20 | regulator-max-microvolt = <1800000>; | ||
21 | vin-supply = <&parent_reg>; | ||
22 | fcs,suspend-voltage-selector = <1>; | ||
23 | }; | ||
diff --git a/Documentation/devicetree/bindings/regulator/isl9305.txt b/Documentation/devicetree/bindings/regulator/isl9305.txt new file mode 100644 index 000000000000..a626fc1bbf0d --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/isl9305.txt | |||
@@ -0,0 +1,36 @@ | |||
1 | Intersil ISL9305/ISL9305H voltage regulator | ||
2 | |||
3 | Required properties: | ||
4 | |||
5 | - compatible: "isl,isl9305" or "isl,isl9305h" | ||
6 | - reg: I2C slave address, usually 0x68. | ||
7 | - regulators: A node that houses a sub-node for each regulator within the | ||
8 | device. Each sub-node is identified using the node's name, with valid | ||
9 | values being "dcd1", "dcd2", "ldo1" and "ldo2". The content of each sub-node | ||
10 | is defined by the standard binding for regulators; see regulator.txt. | ||
11 | - VINDCD1-supply: A phandle to a regulator node supplying VINDCD1. | ||
12 | VINDCD2-supply: A phandle to a regulator node supplying VINDCD2. | ||
13 | VINLDO1-supply: A phandle to a regulator node supplying VINLDO1. | ||
14 | VINLDO2-supply: A phandle to a regulator node supplying VINLDO2. | ||
15 | |||
16 | Optional properties: | ||
17 | - Per-regulator optional properties are defined in regulator.txt | ||
18 | |||
19 | Example | ||
20 | |||
21 | pmic: isl9305@68 { | ||
22 | compatible = "isl,isl9305"; | ||
23 | reg = <0x68>; | ||
24 | |||
25 | VINDCD1-supply = <&system_power>; | ||
26 | VINDCD2-supply = <&system_power>; | ||
27 | VINLDO1-supply = <&system_power>; | ||
28 | VINLDO2-supply = <&system_power>; | ||
29 | |||
30 | regulators { | ||
31 | dcd1 { | ||
32 | regulator-name = "VDD_DSP"; | ||
33 | regulator-always-on; | ||
34 | }; | ||
35 | }; | ||
36 | }; | ||
diff --git a/Documentation/devicetree/bindings/regulator/pwm-regulator.txt b/Documentation/devicetree/bindings/regulator/pwm-regulator.txt new file mode 100644 index 000000000000..ce91f61feb12 --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/pwm-regulator.txt | |||
@@ -0,0 +1,27 @@ | |||
1 | pwm regulator bindings | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: Should be "pwm-regulator" | ||
5 | - pwms: OF device-tree PWM specification (see PWM binding pwm.txt) | ||
6 | - voltage-table: voltage and duty table, include 2 members in each set of | ||
7 | brackets, first one is voltage(unit: uv), the next is duty(unit: percent) | ||
8 | |||
9 | Any property defined as part of the core regulator binding defined in | ||
10 | regulator.txt can also be used. | ||
11 | |||
12 | Example: | ||
13 | pwm_regulator { | ||
14 | compatible = "pwm-regulator; | ||
15 | pwms = <&pwm1 0 8448 0>; | ||
16 | |||
17 | voltage-table = <1114000 0>, | ||
18 | <1095000 10>, | ||
19 | <1076000 20>, | ||
20 | <1056000 30>, | ||
21 | <1036000 40>, | ||
22 | <1016000 50>; | ||
23 | |||
24 | regulator-min-microvolt = <1016000>; | ||
25 | regulator-max-microvolt = <1114000>; | ||
26 | regulator-name = "vdd_logic"; | ||
27 | }; | ||
diff --git a/Documentation/devicetree/bindings/regulator/sky81452-regulator.txt b/Documentation/devicetree/bindings/regulator/sky81452-regulator.txt new file mode 100644 index 000000000000..882455e9b36d --- /dev/null +++ b/Documentation/devicetree/bindings/regulator/sky81452-regulator.txt | |||
@@ -0,0 +1,16 @@ | |||
1 | SKY81452 voltage regulator | ||
2 | |||
3 | Required properties: | ||
4 | - any required generic properties defined in regulator.txt | ||
5 | |||
6 | Optional properties: | ||
7 | - any available generic properties defined in regulator.txt | ||
8 | |||
9 | Example: | ||
10 | |||
11 | regulator { | ||
12 | /* generic regulator properties */ | ||
13 | regulator-name = "touch_en"; | ||
14 | regulator-min-microvolt = <4500000>; | ||
15 | regulator-max-microvolt = <8000000>; | ||
16 | }; | ||
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index ac7269f90764..6073e76575ea 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt | |||
@@ -49,6 +49,7 @@ epson Seiko Epson Corp. | |||
49 | est ESTeem Wireless Modems | 49 | est ESTeem Wireless Modems |
50 | eukrea Eukréa Electromatique | 50 | eukrea Eukréa Electromatique |
51 | excito Excito | 51 | excito Excito |
52 | fcs Fairchild Semiconductor | ||
52 | fsl Freescale Semiconductor | 53 | fsl Freescale Semiconductor |
53 | GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc. | 54 | GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc. |
54 | gef GE Fanuc Intelligent Platforms Embedded Systems, Inc. | 55 | gef GE Fanuc Intelligent Platforms Embedded Systems, Inc. |
@@ -124,6 +125,7 @@ sil Silicon Image | |||
124 | silabs Silicon Laboratories | 125 | silabs Silicon Laboratories |
125 | simtek | 126 | simtek |
126 | sii Seiko Instruments, Inc. | 127 | sii Seiko Instruments, Inc. |
128 | silergy Silergy Corp. | ||
127 | sirf SiRF Technology, Inc. | 129 | sirf SiRF Technology, Inc. |
128 | smsc Standard Microsystems Corporation | 130 | smsc Standard Microsystems Corporation |
129 | snps Synopsys, Inc. | 131 | snps Synopsys, Inc. |
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 1344aa83b438..40eab775047e 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
@@ -241,6 +241,23 @@ config REGULATOR_GPIO | |||
241 | and the platform has to provide a mapping of GPIO-states | 241 | and the platform has to provide a mapping of GPIO-states |
242 | to target volts/amps. | 242 | to target volts/amps. |
243 | 243 | ||
244 | config REGULATOR_HI6421 | ||
245 | tristate "HiSilicon Hi6421 PMIC voltage regulator support" | ||
246 | depends on MFD_HI6421_PMIC && OF | ||
247 | help | ||
248 | This driver provides support for the voltage regulators on the | ||
249 | HiSilicon Hi6421 PMU / Codec IC. | ||
250 | Hi6421 is a multi-function device which, on regulator part, provides | ||
251 | 21 general purpose LDOs, 3 dedicated LDOs, and 5 BUCKs. All | ||
252 | of them come with support to either ECO (idle) or sleep mode. | ||
253 | |||
254 | config REGULATOR_ISL9305 | ||
255 | tristate "Intersil ISL9305 regulator" | ||
256 | depends on I2C | ||
257 | select REGMAP_I2C | ||
258 | help | ||
259 | This driver supports ISL9305 voltage regulator chip. | ||
260 | |||
244 | config REGULATOR_ISL6271A | 261 | config REGULATOR_ISL6271A |
245 | tristate "Intersil ISL6271A Power regulator" | 262 | tristate "Intersil ISL6271A Power regulator" |
246 | depends on I2C | 263 | depends on I2C |
@@ -450,6 +467,25 @@ config REGULATOR_PFUZE100 | |||
450 | Say y here to support the regulators found on the Freescale | 467 | Say y here to support the regulators found on the Freescale |
451 | PFUZE100/PFUZE200 PMIC. | 468 | PFUZE100/PFUZE200 PMIC. |
452 | 469 | ||
470 | config REGULATOR_PWM | ||
471 | tristate "PWM voltage regulator" | ||
472 | depends on PWM | ||
473 | help | ||
474 | This driver supports PWM controlled voltage regulators. PWM | ||
475 | duty cycle can increase or decrease the voltage. | ||
476 | |||
477 | config REGULATOR_QCOM_RPM | ||
478 | tristate "Qualcomm RPM regulator driver" | ||
479 | depends on MFD_QCOM_RPM | ||
480 | help | ||
481 | If you say yes to this option, support will be included for the | ||
482 | regulators exposed by the Resource Power Manager found in Qualcomm | ||
483 | 8660, 8960 and 8064 based devices. | ||
484 | |||
485 | Say M here if you want to include support for the regulators on the | ||
486 | Qualcomm RPM as a module. The module will be named | ||
487 | "qcom_rpm-regulator". | ||
488 | |||
453 | config REGULATOR_RC5T583 | 489 | config REGULATOR_RC5T583 |
454 | tristate "RICOH RC5T583 Power regulators" | 490 | tristate "RICOH RC5T583 Power regulators" |
455 | depends on MFD_RC5T583 | 491 | depends on MFD_RC5T583 |
@@ -484,11 +520,16 @@ config REGULATOR_S5M8767 | |||
484 | via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and | 520 | via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and |
485 | supports DVS mode with 8bits of output voltage control. | 521 | supports DVS mode with 8bits of output voltage control. |
486 | 522 | ||
487 | config REGULATOR_ST_PWM | 523 | config REGULATOR_SKY81452 |
488 | tristate "STMicroelectronics PWM voltage regulator" | 524 | tristate "Skyworks Solutions SKY81452 voltage regulator" |
489 | depends on ARCH_STI | 525 | depends on SKY81452 |
490 | help | 526 | help |
491 | This driver supports ST's PWM controlled voltage regulators. | 527 | This driver supports Skyworks SKY81452 voltage output regulator |
528 | via I2C bus. SKY81452 has one voltage linear regulator can be | ||
529 | programmed from 4.5V to 20V. | ||
530 | |||
531 | This driver can also be built as a module. If so, the module | ||
532 | will be called sky81452-regulator. | ||
492 | 533 | ||
493 | config REGULATOR_TI_ABB | 534 | config REGULATOR_TI_ABB |
494 | tristate "TI Adaptive Body Bias on-chip LDO" | 535 | tristate "TI Adaptive Body Bias on-chip LDO" |
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index aa4a6aa7b558..662834856c37 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
@@ -32,7 +32,9 @@ obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o | |||
32 | obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o | 32 | obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o |
33 | obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o | 33 | obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o |
34 | obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o | 34 | obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o |
35 | obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o | ||
35 | obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o | 36 | obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o |
37 | obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o | ||
36 | obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o | 38 | obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o |
37 | obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o | 39 | obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o |
38 | obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o | 40 | obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o |
@@ -55,8 +57,10 @@ obj-$(CONFIG_REGULATOR_MAX77693) += max77693.o | |||
55 | obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o | 57 | obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o |
56 | obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o | 58 | obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o |
57 | obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o | 59 | obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o |
60 | obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o | ||
58 | obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o | 61 | obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o |
59 | obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o | 62 | obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o |
63 | obj-$(CONFIG_REGULATOR_PWM) += pwm-regulator.o | ||
60 | obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o | 64 | obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o |
61 | obj-$(CONFIG_REGULATOR_PBIAS) += pbias-regulator.o | 65 | obj-$(CONFIG_REGULATOR_PBIAS) += pbias-regulator.o |
62 | obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o | 66 | obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o |
@@ -65,7 +69,7 @@ obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o | |||
65 | obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o | 69 | obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o |
66 | obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o | 70 | obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o |
67 | obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o | 71 | obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o |
68 | obj-$(CONFIG_REGULATOR_ST_PWM) += st-pwm.o | 72 | obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o |
69 | obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o | 73 | obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o |
70 | obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o | 74 | obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o |
71 | obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o | 75 | obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o |
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index a3c3785901f5..44b4045b98d8 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
@@ -839,7 +839,7 @@ static void print_constraints(struct regulator_dev *rdev) | |||
839 | static int machine_constraints_voltage(struct regulator_dev *rdev, | 839 | static int machine_constraints_voltage(struct regulator_dev *rdev, |
840 | struct regulation_constraints *constraints) | 840 | struct regulation_constraints *constraints) |
841 | { | 841 | { |
842 | struct regulator_ops *ops = rdev->desc->ops; | 842 | const struct regulator_ops *ops = rdev->desc->ops; |
843 | int ret; | 843 | int ret; |
844 | 844 | ||
845 | /* do we need to apply the constraint voltage */ | 845 | /* do we need to apply the constraint voltage */ |
@@ -938,7 +938,7 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, | |||
938 | static int machine_constraints_current(struct regulator_dev *rdev, | 938 | static int machine_constraints_current(struct regulator_dev *rdev, |
939 | struct regulation_constraints *constraints) | 939 | struct regulation_constraints *constraints) |
940 | { | 940 | { |
941 | struct regulator_ops *ops = rdev->desc->ops; | 941 | const struct regulator_ops *ops = rdev->desc->ops; |
942 | int ret; | 942 | int ret; |
943 | 943 | ||
944 | if (!constraints->min_uA && !constraints->max_uA) | 944 | if (!constraints->min_uA && !constraints->max_uA) |
@@ -982,7 +982,7 @@ static int set_machine_constraints(struct regulator_dev *rdev, | |||
982 | const struct regulation_constraints *constraints) | 982 | const struct regulation_constraints *constraints) |
983 | { | 983 | { |
984 | int ret = 0; | 984 | int ret = 0; |
985 | struct regulator_ops *ops = rdev->desc->ops; | 985 | const struct regulator_ops *ops = rdev->desc->ops; |
986 | 986 | ||
987 | if (constraints) | 987 | if (constraints) |
988 | rdev->constraints = kmemdup(constraints, sizeof(*constraints), | 988 | rdev->constraints = kmemdup(constraints, sizeof(*constraints), |
@@ -1759,6 +1759,45 @@ static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) | |||
1759 | return 0; | 1759 | return 0; |
1760 | } | 1760 | } |
1761 | 1761 | ||
1762 | /** | ||
1763 | * _regulator_enable_delay - a delay helper function | ||
1764 | * @delay: time to delay in microseconds | ||
1765 | * | ||
1766 | * Delay for the requested amount of time as per the guidelines in: | ||
1767 | * | ||
1768 | * Documentation/timers/timers-howto.txt | ||
1769 | * | ||
1770 | * The assumption here is that regulators will never be enabled in | ||
1771 | * atomic context and therefore sleeping functions can be used. | ||
1772 | */ | ||
1773 | static void _regulator_enable_delay(unsigned int delay) | ||
1774 | { | ||
1775 | unsigned int ms = delay / 1000; | ||
1776 | unsigned int us = delay % 1000; | ||
1777 | |||
1778 | if (ms > 0) { | ||
1779 | /* | ||
1780 | * For small enough values, handle super-millisecond | ||
1781 | * delays in the usleep_range() call below. | ||
1782 | */ | ||
1783 | if (ms < 20) | ||
1784 | us += ms * 1000; | ||
1785 | else | ||
1786 | msleep(ms); | ||
1787 | } | ||
1788 | |||
1789 | /* | ||
1790 | * Give the scheduler some room to coalesce with any other | ||
1791 | * wakeup sources. For delays shorter than 10 us, don't even | ||
1792 | * bother setting up high-resolution timers and just busy- | ||
1793 | * loop. | ||
1794 | */ | ||
1795 | if (us >= 10) | ||
1796 | usleep_range(us, us + 100); | ||
1797 | else | ||
1798 | udelay(us); | ||
1799 | } | ||
1800 | |||
1762 | static int _regulator_do_enable(struct regulator_dev *rdev) | 1801 | static int _regulator_do_enable(struct regulator_dev *rdev) |
1763 | { | 1802 | { |
1764 | int ret, delay; | 1803 | int ret, delay; |
@@ -1774,6 +1813,31 @@ static int _regulator_do_enable(struct regulator_dev *rdev) | |||
1774 | 1813 | ||
1775 | trace_regulator_enable(rdev_get_name(rdev)); | 1814 | trace_regulator_enable(rdev_get_name(rdev)); |
1776 | 1815 | ||
1816 | if (rdev->desc->off_on_delay) { | ||
1817 | /* if needed, keep a distance of off_on_delay from last time | ||
1818 | * this regulator was disabled. | ||
1819 | */ | ||
1820 | unsigned long start_jiffy = jiffies; | ||
1821 | unsigned long intended, max_delay, remaining; | ||
1822 | |||
1823 | max_delay = usecs_to_jiffies(rdev->desc->off_on_delay); | ||
1824 | intended = rdev->last_off_jiffy + max_delay; | ||
1825 | |||
1826 | if (time_before(start_jiffy, intended)) { | ||
1827 | /* calc remaining jiffies to deal with one-time | ||
1828 | * timer wrapping. | ||
1829 | * in case of multiple timer wrapping, either it can be | ||
1830 | * detected by out-of-range remaining, or it cannot be | ||
1831 | * detected and we gets a panelty of | ||
1832 | * _regulator_enable_delay(). | ||
1833 | */ | ||
1834 | remaining = intended - start_jiffy; | ||
1835 | if (remaining <= max_delay) | ||
1836 | _regulator_enable_delay( | ||
1837 | jiffies_to_usecs(remaining)); | ||
1838 | } | ||
1839 | } | ||
1840 | |||
1777 | if (rdev->ena_pin) { | 1841 | if (rdev->ena_pin) { |
1778 | ret = regulator_ena_gpio_ctrl(rdev, true); | 1842 | ret = regulator_ena_gpio_ctrl(rdev, true); |
1779 | if (ret < 0) | 1843 | if (ret < 0) |
@@ -1792,40 +1856,7 @@ static int _regulator_do_enable(struct regulator_dev *rdev) | |||
1792 | * together. */ | 1856 | * together. */ |
1793 | trace_regulator_enable_delay(rdev_get_name(rdev)); | 1857 | trace_regulator_enable_delay(rdev_get_name(rdev)); |
1794 | 1858 | ||
1795 | /* | 1859 | _regulator_enable_delay(delay); |
1796 | * Delay for the requested amount of time as per the guidelines in: | ||
1797 | * | ||
1798 | * Documentation/timers/timers-howto.txt | ||
1799 | * | ||
1800 | * The assumption here is that regulators will never be enabled in | ||
1801 | * atomic context and therefore sleeping functions can be used. | ||
1802 | */ | ||
1803 | if (delay) { | ||
1804 | unsigned int ms = delay / 1000; | ||
1805 | unsigned int us = delay % 1000; | ||
1806 | |||
1807 | if (ms > 0) { | ||
1808 | /* | ||
1809 | * For small enough values, handle super-millisecond | ||
1810 | * delays in the usleep_range() call below. | ||
1811 | */ | ||
1812 | if (ms < 20) | ||
1813 | us += ms * 1000; | ||
1814 | else | ||
1815 | msleep(ms); | ||
1816 | } | ||
1817 | |||
1818 | /* | ||
1819 | * Give the scheduler some room to coalesce with any other | ||
1820 | * wakeup sources. For delays shorter than 10 us, don't even | ||
1821 | * bother setting up high-resolution timers and just busy- | ||
1822 | * loop. | ||
1823 | */ | ||
1824 | if (us >= 10) | ||
1825 | usleep_range(us, us + 100); | ||
1826 | else | ||
1827 | udelay(us); | ||
1828 | } | ||
1829 | 1860 | ||
1830 | trace_regulator_enable_complete(rdev_get_name(rdev)); | 1861 | trace_regulator_enable_complete(rdev_get_name(rdev)); |
1831 | 1862 | ||
@@ -1919,6 +1950,12 @@ static int _regulator_do_disable(struct regulator_dev *rdev) | |||
1919 | return ret; | 1950 | return ret; |
1920 | } | 1951 | } |
1921 | 1952 | ||
1953 | /* cares about last_off_jiffy only if off_on_delay is required by | ||
1954 | * device. | ||
1955 | */ | ||
1956 | if (rdev->desc->off_on_delay) | ||
1957 | rdev->last_off_jiffy = jiffies; | ||
1958 | |||
1922 | trace_regulator_disable_complete(rdev_get_name(rdev)); | 1959 | trace_regulator_disable_complete(rdev_get_name(rdev)); |
1923 | 1960 | ||
1924 | return 0; | 1961 | return 0; |
@@ -2208,9 +2245,9 @@ EXPORT_SYMBOL_GPL(regulator_count_voltages); | |||
2208 | */ | 2245 | */ |
2209 | int regulator_list_voltage(struct regulator *regulator, unsigned selector) | 2246 | int regulator_list_voltage(struct regulator *regulator, unsigned selector) |
2210 | { | 2247 | { |
2211 | struct regulator_dev *rdev = regulator->rdev; | 2248 | struct regulator_dev *rdev = regulator->rdev; |
2212 | struct regulator_ops *ops = rdev->desc->ops; | 2249 | const struct regulator_ops *ops = rdev->desc->ops; |
2213 | int ret; | 2250 | int ret; |
2214 | 2251 | ||
2215 | if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) | 2252 | if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) |
2216 | return rdev->desc->fixed_uV; | 2253 | return rdev->desc->fixed_uV; |
@@ -2270,8 +2307,8 @@ int regulator_get_hardware_vsel_register(struct regulator *regulator, | |||
2270 | unsigned *vsel_reg, | 2307 | unsigned *vsel_reg, |
2271 | unsigned *vsel_mask) | 2308 | unsigned *vsel_mask) |
2272 | { | 2309 | { |
2273 | struct regulator_dev *rdev = regulator->rdev; | 2310 | struct regulator_dev *rdev = regulator->rdev; |
2274 | struct regulator_ops *ops = rdev->desc->ops; | 2311 | const struct regulator_ops *ops = rdev->desc->ops; |
2275 | 2312 | ||
2276 | if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) | 2313 | if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) |
2277 | return -EOPNOTSUPP; | 2314 | return -EOPNOTSUPP; |
@@ -2297,8 +2334,8 @@ EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register); | |||
2297 | int regulator_list_hardware_vsel(struct regulator *regulator, | 2334 | int regulator_list_hardware_vsel(struct regulator *regulator, |
2298 | unsigned selector) | 2335 | unsigned selector) |
2299 | { | 2336 | { |
2300 | struct regulator_dev *rdev = regulator->rdev; | 2337 | struct regulator_dev *rdev = regulator->rdev; |
2301 | struct regulator_ops *ops = rdev->desc->ops; | 2338 | const struct regulator_ops *ops = rdev->desc->ops; |
2302 | 2339 | ||
2303 | if (selector >= rdev->desc->n_voltages) | 2340 | if (selector >= rdev->desc->n_voltages) |
2304 | return -EINVAL; | 2341 | return -EINVAL; |
@@ -2572,8 +2609,8 @@ EXPORT_SYMBOL_GPL(regulator_set_voltage); | |||
2572 | int regulator_set_voltage_time(struct regulator *regulator, | 2609 | int regulator_set_voltage_time(struct regulator *regulator, |
2573 | int old_uV, int new_uV) | 2610 | int old_uV, int new_uV) |
2574 | { | 2611 | { |
2575 | struct regulator_dev *rdev = regulator->rdev; | 2612 | struct regulator_dev *rdev = regulator->rdev; |
2576 | struct regulator_ops *ops = rdev->desc->ops; | 2613 | const struct regulator_ops *ops = rdev->desc->ops; |
2577 | int old_sel = -1; | 2614 | int old_sel = -1; |
2578 | int new_sel = -1; | 2615 | int new_sel = -1; |
2579 | int voltage; | 2616 | int voltage; |
@@ -3336,9 +3373,9 @@ EXPORT_SYMBOL_GPL(regulator_mode_to_status); | |||
3336 | */ | 3373 | */ |
3337 | static int add_regulator_attributes(struct regulator_dev *rdev) | 3374 | static int add_regulator_attributes(struct regulator_dev *rdev) |
3338 | { | 3375 | { |
3339 | struct device *dev = &rdev->dev; | 3376 | struct device *dev = &rdev->dev; |
3340 | struct regulator_ops *ops = rdev->desc->ops; | 3377 | const struct regulator_ops *ops = rdev->desc->ops; |
3341 | int status = 0; | 3378 | int status = 0; |
3342 | 3379 | ||
3343 | /* some attributes need specific methods to be displayed */ | 3380 | /* some attributes need specific methods to be displayed */ |
3344 | if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || | 3381 | if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || |
@@ -3516,12 +3553,17 @@ regulator_register(const struct regulator_desc *regulator_desc, | |||
3516 | return ERR_PTR(-EINVAL); | 3553 | return ERR_PTR(-EINVAL); |
3517 | } | 3554 | } |
3518 | 3555 | ||
3519 | init_data = config->init_data; | ||
3520 | |||
3521 | rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); | 3556 | rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); |
3522 | if (rdev == NULL) | 3557 | if (rdev == NULL) |
3523 | return ERR_PTR(-ENOMEM); | 3558 | return ERR_PTR(-ENOMEM); |
3524 | 3559 | ||
3560 | init_data = regulator_of_get_init_data(dev, regulator_desc, | ||
3561 | &rdev->dev.of_node); | ||
3562 | if (!init_data) { | ||
3563 | init_data = config->init_data; | ||
3564 | rdev->dev.of_node = of_node_get(config->of_node); | ||
3565 | } | ||
3566 | |||
3525 | mutex_lock(®ulator_list_mutex); | 3567 | mutex_lock(®ulator_list_mutex); |
3526 | 3568 | ||
3527 | mutex_init(&rdev->mutex); | 3569 | mutex_init(&rdev->mutex); |
@@ -3548,7 +3590,6 @@ regulator_register(const struct regulator_desc *regulator_desc, | |||
3548 | 3590 | ||
3549 | /* register with sysfs */ | 3591 | /* register with sysfs */ |
3550 | rdev->dev.class = ®ulator_class; | 3592 | rdev->dev.class = ®ulator_class; |
3551 | rdev->dev.of_node = of_node_get(config->of_node); | ||
3552 | rdev->dev.parent = dev; | 3593 | rdev->dev.parent = dev; |
3553 | dev_set_name(&rdev->dev, "regulator.%d", | 3594 | dev_set_name(&rdev->dev, "regulator.%d", |
3554 | atomic_inc_return(®ulator_no) - 1); | 3595 | atomic_inc_return(®ulator_no) - 1); |
@@ -3905,7 +3946,7 @@ core_initcall(regulator_init); | |||
3905 | static int __init regulator_init_complete(void) | 3946 | static int __init regulator_init_complete(void) |
3906 | { | 3947 | { |
3907 | struct regulator_dev *rdev; | 3948 | struct regulator_dev *rdev; |
3908 | struct regulator_ops *ops; | 3949 | const struct regulator_ops *ops; |
3909 | struct regulation_constraints *c; | 3950 | struct regulation_constraints *c; |
3910 | int enabled, ret; | 3951 | int enabled, ret; |
3911 | 3952 | ||
diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index 714fd9a89aa1..f8e4257aef92 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/regulator/driver.h> | 19 | #include <linux/regulator/driver.h> |
20 | #include <linux/regulator/machine.h> | 20 | #include <linux/regulator/machine.h> |
21 | #include <linux/regulator/of_regulator.h> | ||
22 | #include <linux/of_device.h> | ||
21 | #include <linux/i2c.h> | 23 | #include <linux/i2c.h> |
22 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
23 | #include <linux/regmap.h> | 25 | #include <linux/regmap.h> |
@@ -50,6 +52,11 @@ | |||
50 | 52 | ||
51 | #define FAN53555_NVOLTAGES 64 /* Numbers of voltages */ | 53 | #define FAN53555_NVOLTAGES 64 /* Numbers of voltages */ |
52 | 54 | ||
55 | enum fan53555_vendor { | ||
56 | FAN53555_VENDOR_FAIRCHILD = 0, | ||
57 | FAN53555_VENDOR_SILERGY, | ||
58 | }; | ||
59 | |||
53 | /* IC Type */ | 60 | /* IC Type */ |
54 | enum { | 61 | enum { |
55 | FAN53555_CHIP_ID_00 = 0, | 62 | FAN53555_CHIP_ID_00 = 0, |
@@ -60,7 +67,12 @@ enum { | |||
60 | FAN53555_CHIP_ID_05, | 67 | FAN53555_CHIP_ID_05, |
61 | }; | 68 | }; |
62 | 69 | ||
70 | enum { | ||
71 | SILERGY_SYR82X = 8, | ||
72 | }; | ||
73 | |||
63 | struct fan53555_device_info { | 74 | struct fan53555_device_info { |
75 | enum fan53555_vendor vendor; | ||
64 | struct regmap *regmap; | 76 | struct regmap *regmap; |
65 | struct device *dev; | 77 | struct device *dev; |
66 | struct regulator_desc desc; | 78 | struct regulator_desc desc; |
@@ -135,6 +147,38 @@ static unsigned int fan53555_get_mode(struct regulator_dev *rdev) | |||
135 | return REGULATOR_MODE_NORMAL; | 147 | return REGULATOR_MODE_NORMAL; |
136 | } | 148 | } |
137 | 149 | ||
150 | static int slew_rates[] = { | ||
151 | 64000, | ||
152 | 32000, | ||
153 | 16000, | ||
154 | 8000, | ||
155 | 4000, | ||
156 | 2000, | ||
157 | 1000, | ||
158 | 500, | ||
159 | }; | ||
160 | |||
161 | static int fan53555_set_ramp(struct regulator_dev *rdev, int ramp) | ||
162 | { | ||
163 | struct fan53555_device_info *di = rdev_get_drvdata(rdev); | ||
164 | int regval = -1, i; | ||
165 | |||
166 | for (i = 0; i < ARRAY_SIZE(slew_rates); i++) { | ||
167 | if (ramp <= slew_rates[i]) | ||
168 | regval = i; | ||
169 | else | ||
170 | break; | ||
171 | } | ||
172 | |||
173 | if (regval < 0) { | ||
174 | dev_err(di->dev, "unsupported ramp value %d\n", ramp); | ||
175 | return -EINVAL; | ||
176 | } | ||
177 | |||
178 | return regmap_update_bits(di->regmap, FAN53555_CONTROL, | ||
179 | CTL_SLEW_MASK, regval << CTL_SLEW_SHIFT); | ||
180 | } | ||
181 | |||
138 | static struct regulator_ops fan53555_regulator_ops = { | 182 | static struct regulator_ops fan53555_regulator_ops = { |
139 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | 183 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
140 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 184 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
@@ -146,8 +190,50 @@ static struct regulator_ops fan53555_regulator_ops = { | |||
146 | .is_enabled = regulator_is_enabled_regmap, | 190 | .is_enabled = regulator_is_enabled_regmap, |
147 | .set_mode = fan53555_set_mode, | 191 | .set_mode = fan53555_set_mode, |
148 | .get_mode = fan53555_get_mode, | 192 | .get_mode = fan53555_get_mode, |
193 | .set_ramp_delay = fan53555_set_ramp, | ||
149 | }; | 194 | }; |
150 | 195 | ||
196 | static int fan53555_voltages_setup_fairchild(struct fan53555_device_info *di) | ||
197 | { | ||
198 | /* Init voltage range and step */ | ||
199 | switch (di->chip_id) { | ||
200 | case FAN53555_CHIP_ID_00: | ||
201 | case FAN53555_CHIP_ID_01: | ||
202 | case FAN53555_CHIP_ID_03: | ||
203 | case FAN53555_CHIP_ID_05: | ||
204 | di->vsel_min = 600000; | ||
205 | di->vsel_step = 10000; | ||
206 | break; | ||
207 | case FAN53555_CHIP_ID_04: | ||
208 | di->vsel_min = 603000; | ||
209 | di->vsel_step = 12826; | ||
210 | break; | ||
211 | default: | ||
212 | dev_err(di->dev, | ||
213 | "Chip ID %d not supported!\n", di->chip_id); | ||
214 | return -EINVAL; | ||
215 | } | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static int fan53555_voltages_setup_silergy(struct fan53555_device_info *di) | ||
221 | { | ||
222 | /* Init voltage range and step */ | ||
223 | switch (di->chip_id) { | ||
224 | case SILERGY_SYR82X: | ||
225 | di->vsel_min = 712500; | ||
226 | di->vsel_step = 12500; | ||
227 | break; | ||
228 | default: | ||
229 | dev_err(di->dev, | ||
230 | "Chip ID %d not supported!\n", di->chip_id); | ||
231 | return -EINVAL; | ||
232 | } | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
151 | /* For 00,01,03,05 options: | 237 | /* For 00,01,03,05 options: |
152 | * VOUT = 0.60V + NSELx * 10mV, from 0.60 to 1.23V. | 238 | * VOUT = 0.60V + NSELx * 10mV, from 0.60 to 1.23V. |
153 | * For 04 option: | 239 | * For 04 option: |
@@ -156,7 +242,7 @@ static struct regulator_ops fan53555_regulator_ops = { | |||
156 | static int fan53555_device_setup(struct fan53555_device_info *di, | 242 | static int fan53555_device_setup(struct fan53555_device_info *di, |
157 | struct fan53555_platform_data *pdata) | 243 | struct fan53555_platform_data *pdata) |
158 | { | 244 | { |
159 | unsigned int reg, data, mask; | 245 | int ret = 0; |
160 | 246 | ||
161 | /* Setup voltage control register */ | 247 | /* Setup voltage control register */ |
162 | switch (pdata->sleep_vsel_id) { | 248 | switch (pdata->sleep_vsel_id) { |
@@ -172,33 +258,20 @@ static int fan53555_device_setup(struct fan53555_device_info *di, | |||
172 | dev_err(di->dev, "Invalid VSEL ID!\n"); | 258 | dev_err(di->dev, "Invalid VSEL ID!\n"); |
173 | return -EINVAL; | 259 | return -EINVAL; |
174 | } | 260 | } |
175 | /* Init voltage range and step */ | 261 | |
176 | switch (di->chip_id) { | 262 | switch (di->vendor) { |
177 | case FAN53555_CHIP_ID_00: | 263 | case FAN53555_VENDOR_FAIRCHILD: |
178 | case FAN53555_CHIP_ID_01: | 264 | ret = fan53555_voltages_setup_fairchild(di); |
179 | case FAN53555_CHIP_ID_03: | ||
180 | case FAN53555_CHIP_ID_05: | ||
181 | di->vsel_min = 600000; | ||
182 | di->vsel_step = 10000; | ||
183 | break; | 265 | break; |
184 | case FAN53555_CHIP_ID_04: | 266 | case FAN53555_VENDOR_SILERGY: |
185 | di->vsel_min = 603000; | 267 | ret = fan53555_voltages_setup_silergy(di); |
186 | di->vsel_step = 12826; | ||
187 | break; | 268 | break; |
188 | default: | 269 | default: |
189 | dev_err(di->dev, | 270 | dev_err(di->dev, "vendor %d not supported!\n", di->vendor); |
190 | "Chip ID[%d]\n not supported!\n", di->chip_id); | ||
191 | return -EINVAL; | 271 | return -EINVAL; |
192 | } | 272 | } |
193 | /* Init slew rate */ | 273 | |
194 | if (pdata->slew_rate & 0x7) | 274 | return ret; |
195 | di->slew_rate = pdata->slew_rate; | ||
196 | else | ||
197 | di->slew_rate = FAN53555_SLEW_RATE_64MV; | ||
198 | reg = FAN53555_CONTROL; | ||
199 | data = di->slew_rate << CTL_SLEW_SHIFT; | ||
200 | mask = CTL_SLEW_MASK; | ||
201 | return regmap_update_bits(di->regmap, reg, mask, data); | ||
202 | } | 275 | } |
203 | 276 | ||
204 | static int fan53555_regulator_register(struct fan53555_device_info *di, | 277 | static int fan53555_regulator_register(struct fan53555_device_info *di, |
@@ -207,6 +280,7 @@ static int fan53555_regulator_register(struct fan53555_device_info *di, | |||
207 | struct regulator_desc *rdesc = &di->desc; | 280 | struct regulator_desc *rdesc = &di->desc; |
208 | 281 | ||
209 | rdesc->name = "fan53555-reg"; | 282 | rdesc->name = "fan53555-reg"; |
283 | rdesc->supply_name = "vin"; | ||
210 | rdesc->ops = &fan53555_regulator_ops; | 284 | rdesc->ops = &fan53555_regulator_ops; |
211 | rdesc->type = REGULATOR_VOLTAGE; | 285 | rdesc->type = REGULATOR_VOLTAGE; |
212 | rdesc->n_voltages = FAN53555_NVOLTAGES; | 286 | rdesc->n_voltages = FAN53555_NVOLTAGES; |
@@ -227,9 +301,46 @@ static struct regmap_config fan53555_regmap_config = { | |||
227 | .val_bits = 8, | 301 | .val_bits = 8, |
228 | }; | 302 | }; |
229 | 303 | ||
304 | static struct fan53555_platform_data *fan53555_parse_dt(struct device *dev, | ||
305 | struct device_node *np) | ||
306 | { | ||
307 | struct fan53555_platform_data *pdata; | ||
308 | int ret; | ||
309 | u32 tmp; | ||
310 | |||
311 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
312 | if (!pdata) | ||
313 | return NULL; | ||
314 | |||
315 | pdata->regulator = of_get_regulator_init_data(dev, np); | ||
316 | |||
317 | ret = of_property_read_u32(np, "fcs,suspend-voltage-selector", | ||
318 | &tmp); | ||
319 | if (!ret) | ||
320 | pdata->sleep_vsel_id = tmp; | ||
321 | |||
322 | return pdata; | ||
323 | } | ||
324 | |||
325 | static const struct of_device_id fan53555_dt_ids[] = { | ||
326 | { | ||
327 | .compatible = "fcs,fan53555", | ||
328 | .data = (void *)FAN53555_VENDOR_FAIRCHILD | ||
329 | }, { | ||
330 | .compatible = "silergy,syr827", | ||
331 | .data = (void *)FAN53555_VENDOR_SILERGY, | ||
332 | }, { | ||
333 | .compatible = "silergy,syr828", | ||
334 | .data = (void *)FAN53555_VENDOR_SILERGY, | ||
335 | }, | ||
336 | { } | ||
337 | }; | ||
338 | MODULE_DEVICE_TABLE(of, fan53555_dt_ids); | ||
339 | |||
230 | static int fan53555_regulator_probe(struct i2c_client *client, | 340 | static int fan53555_regulator_probe(struct i2c_client *client, |
231 | const struct i2c_device_id *id) | 341 | const struct i2c_device_id *id) |
232 | { | 342 | { |
343 | struct device_node *np = client->dev.of_node; | ||
233 | struct fan53555_device_info *di; | 344 | struct fan53555_device_info *di; |
234 | struct fan53555_platform_data *pdata; | 345 | struct fan53555_platform_data *pdata; |
235 | struct regulator_config config = { }; | 346 | struct regulator_config config = { }; |
@@ -237,6 +348,9 @@ static int fan53555_regulator_probe(struct i2c_client *client, | |||
237 | int ret; | 348 | int ret; |
238 | 349 | ||
239 | pdata = dev_get_platdata(&client->dev); | 350 | pdata = dev_get_platdata(&client->dev); |
351 | if (!pdata) | ||
352 | pdata = fan53555_parse_dt(&client->dev, np); | ||
353 | |||
240 | if (!pdata || !pdata->regulator) { | 354 | if (!pdata || !pdata->regulator) { |
241 | dev_err(&client->dev, "Platform data not found!\n"); | 355 | dev_err(&client->dev, "Platform data not found!\n"); |
242 | return -ENODEV; | 356 | return -ENODEV; |
@@ -247,13 +361,35 @@ static int fan53555_regulator_probe(struct i2c_client *client, | |||
247 | if (!di) | 361 | if (!di) |
248 | return -ENOMEM; | 362 | return -ENOMEM; |
249 | 363 | ||
364 | di->regulator = pdata->regulator; | ||
365 | if (client->dev.of_node) { | ||
366 | const struct of_device_id *match; | ||
367 | |||
368 | match = of_match_device(of_match_ptr(fan53555_dt_ids), | ||
369 | &client->dev); | ||
370 | if (!match) | ||
371 | return -ENODEV; | ||
372 | |||
373 | di->vendor = (unsigned long) match->data; | ||
374 | } else { | ||
375 | /* if no ramp constraint set, get the pdata ramp_delay */ | ||
376 | if (!di->regulator->constraints.ramp_delay) { | ||
377 | int slew_idx = (pdata->slew_rate & 0x7) | ||
378 | ? pdata->slew_rate : 0; | ||
379 | |||
380 | di->regulator->constraints.ramp_delay | ||
381 | = slew_rates[slew_idx]; | ||
382 | } | ||
383 | |||
384 | di->vendor = id->driver_data; | ||
385 | } | ||
386 | |||
250 | di->regmap = devm_regmap_init_i2c(client, &fan53555_regmap_config); | 387 | di->regmap = devm_regmap_init_i2c(client, &fan53555_regmap_config); |
251 | if (IS_ERR(di->regmap)) { | 388 | if (IS_ERR(di->regmap)) { |
252 | dev_err(&client->dev, "Failed to allocate regmap!\n"); | 389 | dev_err(&client->dev, "Failed to allocate regmap!\n"); |
253 | return PTR_ERR(di->regmap); | 390 | return PTR_ERR(di->regmap); |
254 | } | 391 | } |
255 | di->dev = &client->dev; | 392 | di->dev = &client->dev; |
256 | di->regulator = pdata->regulator; | ||
257 | i2c_set_clientdata(client, di); | 393 | i2c_set_clientdata(client, di); |
258 | /* Get chip ID */ | 394 | /* Get chip ID */ |
259 | ret = regmap_read(di->regmap, FAN53555_ID1, &val); | 395 | ret = regmap_read(di->regmap, FAN53555_ID1, &val); |
@@ -282,6 +418,8 @@ static int fan53555_regulator_probe(struct i2c_client *client, | |||
282 | config.init_data = di->regulator; | 418 | config.init_data = di->regulator; |
283 | config.regmap = di->regmap; | 419 | config.regmap = di->regmap; |
284 | config.driver_data = di; | 420 | config.driver_data = di; |
421 | config.of_node = np; | ||
422 | |||
285 | ret = fan53555_regulator_register(di, &config); | 423 | ret = fan53555_regulator_register(di, &config); |
286 | if (ret < 0) | 424 | if (ret < 0) |
287 | dev_err(&client->dev, "Failed to register regulator!\n"); | 425 | dev_err(&client->dev, "Failed to register regulator!\n"); |
@@ -290,13 +428,20 @@ static int fan53555_regulator_probe(struct i2c_client *client, | |||
290 | } | 428 | } |
291 | 429 | ||
292 | static const struct i2c_device_id fan53555_id[] = { | 430 | static const struct i2c_device_id fan53555_id[] = { |
293 | {"fan53555", -1}, | 431 | { |
432 | .name = "fan53555", | ||
433 | .driver_data = FAN53555_VENDOR_FAIRCHILD | ||
434 | }, { | ||
435 | .name = "syr82x", | ||
436 | .driver_data = FAN53555_VENDOR_SILERGY | ||
437 | }, | ||
294 | { }, | 438 | { }, |
295 | }; | 439 | }; |
296 | 440 | ||
297 | static struct i2c_driver fan53555_regulator_driver = { | 441 | static struct i2c_driver fan53555_regulator_driver = { |
298 | .driver = { | 442 | .driver = { |
299 | .name = "fan53555-regulator", | 443 | .name = "fan53555-regulator", |
444 | .of_match_table = of_match_ptr(fan53555_dt_ids), | ||
300 | }, | 445 | }, |
301 | .probe = fan53555_regulator_probe, | 446 | .probe = fan53555_regulator_probe, |
302 | .id_table = fan53555_id, | 447 | .id_table = fan53555_id, |
diff --git a/drivers/regulator/hi6421-regulator.c b/drivers/regulator/hi6421-regulator.c new file mode 100644 index 000000000000..156d0d1a55f1 --- /dev/null +++ b/drivers/regulator/hi6421-regulator.c | |||
@@ -0,0 +1,634 @@ | |||
1 | /* | ||
2 | * Device driver for regulators in Hi6421 IC | ||
3 | * | ||
4 | * Copyright (c) <2011-2014> HiSilicon Technologies Co., Ltd. | ||
5 | * http://www.hisilicon.com | ||
6 | * Copyright (c) <2013-2014> Linaro Ltd. | ||
7 | * http://www.linaro.org | ||
8 | * | ||
9 | * Author: Guodong Xu <guodong.xu@linaro.org> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/slab.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/of.h> | ||
22 | #include <linux/regmap.h> | ||
23 | #include <linux/regulator/driver.h> | ||
24 | #include <linux/regulator/machine.h> | ||
25 | #include <linux/regulator/of_regulator.h> | ||
26 | #include <linux/mfd/hi6421-pmic.h> | ||
27 | |||
28 | /* | ||
29 | * struct hi6421_regulator_pdata - Hi6421 regulator data of platform device | ||
30 | * @lock: mutex to serialize regulator enable | ||
31 | */ | ||
32 | struct hi6421_regulator_pdata { | ||
33 | struct mutex lock; | ||
34 | }; | ||
35 | |||
36 | /* | ||
37 | * struct hi6421_regulator_info - hi6421 regulator information | ||
38 | * @desc: regulator description | ||
39 | * @mode_mask: ECO mode bitmask of LDOs; for BUCKs, this masks sleep | ||
40 | * @eco_microamp: eco mode load upper limit (in uA), valid for LDOs only | ||
41 | */ | ||
42 | struct hi6421_regulator_info { | ||
43 | struct regulator_desc desc; | ||
44 | u8 mode_mask; | ||
45 | u32 eco_microamp; | ||
46 | }; | ||
47 | |||
48 | /* HI6421 regulators */ | ||
49 | enum hi6421_regulator_id { | ||
50 | HI6421_LDO0, | ||
51 | HI6421_LDO1, | ||
52 | HI6421_LDO2, | ||
53 | HI6421_LDO3, | ||
54 | HI6421_LDO4, | ||
55 | HI6421_LDO5, | ||
56 | HI6421_LDO6, | ||
57 | HI6421_LDO7, | ||
58 | HI6421_LDO8, | ||
59 | HI6421_LDO9, | ||
60 | HI6421_LDO10, | ||
61 | HI6421_LDO11, | ||
62 | HI6421_LDO12, | ||
63 | HI6421_LDO13, | ||
64 | HI6421_LDO14, | ||
65 | HI6421_LDO15, | ||
66 | HI6421_LDO16, | ||
67 | HI6421_LDO17, | ||
68 | HI6421_LDO18, | ||
69 | HI6421_LDO19, | ||
70 | HI6421_LDO20, | ||
71 | HI6421_LDOAUDIO, | ||
72 | HI6421_BUCK0, | ||
73 | HI6421_BUCK1, | ||
74 | HI6421_BUCK2, | ||
75 | HI6421_BUCK3, | ||
76 | HI6421_BUCK4, | ||
77 | HI6421_BUCK5, | ||
78 | HI6421_NUM_REGULATORS, | ||
79 | }; | ||
80 | |||
81 | #define HI6421_REGULATOR_OF_MATCH(_name, id) \ | ||
82 | { \ | ||
83 | .name = #_name, \ | ||
84 | .driver_data = (void *) HI6421_##id, \ | ||
85 | } | ||
86 | |||
87 | static struct of_regulator_match hi6421_regulator_match[] = { | ||
88 | HI6421_REGULATOR_OF_MATCH(hi6421_vout0, LDO0), | ||
89 | HI6421_REGULATOR_OF_MATCH(hi6421_vout1, LDO1), | ||
90 | HI6421_REGULATOR_OF_MATCH(hi6421_vout2, LDO2), | ||
91 | HI6421_REGULATOR_OF_MATCH(hi6421_vout3, LDO3), | ||
92 | HI6421_REGULATOR_OF_MATCH(hi6421_vout4, LDO4), | ||
93 | HI6421_REGULATOR_OF_MATCH(hi6421_vout5, LDO5), | ||
94 | HI6421_REGULATOR_OF_MATCH(hi6421_vout6, LDO6), | ||
95 | HI6421_REGULATOR_OF_MATCH(hi6421_vout7, LDO7), | ||
96 | HI6421_REGULATOR_OF_MATCH(hi6421_vout8, LDO8), | ||
97 | HI6421_REGULATOR_OF_MATCH(hi6421_vout9, LDO9), | ||
98 | HI6421_REGULATOR_OF_MATCH(hi6421_vout10, LDO10), | ||
99 | HI6421_REGULATOR_OF_MATCH(hi6421_vout11, LDO11), | ||
100 | HI6421_REGULATOR_OF_MATCH(hi6421_vout12, LDO12), | ||
101 | HI6421_REGULATOR_OF_MATCH(hi6421_vout13, LDO13), | ||
102 | HI6421_REGULATOR_OF_MATCH(hi6421_vout14, LDO14), | ||
103 | HI6421_REGULATOR_OF_MATCH(hi6421_vout15, LDO15), | ||
104 | HI6421_REGULATOR_OF_MATCH(hi6421_vout16, LDO16), | ||
105 | HI6421_REGULATOR_OF_MATCH(hi6421_vout17, LDO17), | ||
106 | HI6421_REGULATOR_OF_MATCH(hi6421_vout18, LDO18), | ||
107 | HI6421_REGULATOR_OF_MATCH(hi6421_vout19, LDO19), | ||
108 | HI6421_REGULATOR_OF_MATCH(hi6421_vout20, LDO20), | ||
109 | HI6421_REGULATOR_OF_MATCH(hi6421_vout_audio, LDOAUDIO), | ||
110 | HI6421_REGULATOR_OF_MATCH(hi6421_buck0, BUCK0), | ||
111 | HI6421_REGULATOR_OF_MATCH(hi6421_buck1, BUCK1), | ||
112 | HI6421_REGULATOR_OF_MATCH(hi6421_buck2, BUCK2), | ||
113 | HI6421_REGULATOR_OF_MATCH(hi6421_buck3, BUCK3), | ||
114 | HI6421_REGULATOR_OF_MATCH(hi6421_buck4, BUCK4), | ||
115 | HI6421_REGULATOR_OF_MATCH(hi6421_buck5, BUCK5), | ||
116 | }; | ||
117 | |||
118 | /* LDO 0, 4~7, 9~14, 16~20 have same voltage table. */ | ||
119 | static const unsigned int ldo_0_voltages[] = { | ||
120 | 1500000, 1800000, 2400000, 2500000, | ||
121 | 2600000, 2700000, 2850000, 3000000, | ||
122 | }; | ||
123 | |||
124 | /* LDO 8, 15 have same voltage table. */ | ||
125 | static const unsigned int ldo_8_voltages[] = { | ||
126 | 1500000, 1800000, 2400000, 2600000, | ||
127 | 2700000, 2850000, 3000000, 3300000, | ||
128 | }; | ||
129 | |||
130 | /* Ranges are sorted in ascending order. */ | ||
131 | static const struct regulator_linear_range ldo_audio_volt_range[] = { | ||
132 | REGULATOR_LINEAR_RANGE(2800000, 0, 3, 50000), | ||
133 | REGULATOR_LINEAR_RANGE(3000000, 4, 7, 100000), | ||
134 | }; | ||
135 | |||
136 | static const unsigned int buck_3_voltages[] = { | ||
137 | 950000, 1050000, 1100000, 1117000, | ||
138 | 1134000, 1150000, 1167000, 1200000, | ||
139 | }; | ||
140 | |||
141 | static const unsigned int buck_4_voltages[] = { | ||
142 | 1150000, 1200000, 1250000, 1350000, | ||
143 | 1700000, 1800000, 1900000, 2000000, | ||
144 | }; | ||
145 | |||
146 | static const unsigned int buck_5_voltages[] = { | ||
147 | 1150000, 1200000, 1250000, 1350000, | ||
148 | 1600000, 1700000, 1800000, 1900000, | ||
149 | }; | ||
150 | |||
151 | static const struct regulator_ops hi6421_ldo_ops; | ||
152 | static const struct regulator_ops hi6421_ldo_linear_ops; | ||
153 | static const struct regulator_ops hi6421_ldo_linear_range_ops; | ||
154 | static const struct regulator_ops hi6421_buck012_ops; | ||
155 | static const struct regulator_ops hi6421_buck345_ops; | ||
156 | |||
157 | #define HI6421_LDO_ENABLE_TIME (350) | ||
158 | /* | ||
159 | * _id - LDO id name string | ||
160 | * v_table - voltage table | ||
161 | * vreg - voltage select register | ||
162 | * vmask - voltage select mask | ||
163 | * ereg - enable register | ||
164 | * emask - enable mask | ||
165 | * odelay - off/on delay time in uS | ||
166 | * ecomask - eco mode mask | ||
167 | * ecoamp - eco mode load uppler limit in uA | ||
168 | */ | ||
169 | #define HI6421_LDO(_id, v_table, vreg, vmask, ereg, emask, \ | ||
170 | odelay, ecomask, ecoamp) \ | ||
171 | [HI6421_##_id] = { \ | ||
172 | .desc = { \ | ||
173 | .name = #_id, \ | ||
174 | .ops = &hi6421_ldo_ops, \ | ||
175 | .type = REGULATOR_VOLTAGE, \ | ||
176 | .id = HI6421_##_id, \ | ||
177 | .owner = THIS_MODULE, \ | ||
178 | .n_voltages = ARRAY_SIZE(v_table), \ | ||
179 | .volt_table = v_table, \ | ||
180 | .vsel_reg = HI6421_REG_TO_BUS_ADDR(vreg), \ | ||
181 | .vsel_mask = vmask, \ | ||
182 | .enable_reg = HI6421_REG_TO_BUS_ADDR(ereg), \ | ||
183 | .enable_mask = emask, \ | ||
184 | .enable_time = HI6421_LDO_ENABLE_TIME, \ | ||
185 | .off_on_delay = odelay, \ | ||
186 | }, \ | ||
187 | .mode_mask = ecomask, \ | ||
188 | .eco_microamp = ecoamp, \ | ||
189 | } | ||
190 | |||
191 | /* HI6421 LDO1~3 are linear voltage regulators at fixed uV_step | ||
192 | * | ||
193 | * _id - LDO id name string | ||
194 | * _min_uV - minimum voltage supported in uV | ||
195 | * n_volt - number of votages available | ||
196 | * vstep - voltage increase in each linear step in uV | ||
197 | * vreg - voltage select register | ||
198 | * vmask - voltage select mask | ||
199 | * ereg - enable register | ||
200 | * emask - enable mask | ||
201 | * odelay - off/on delay time in uS | ||
202 | * ecomask - eco mode mask | ||
203 | * ecoamp - eco mode load uppler limit in uA | ||
204 | */ | ||
205 | #define HI6421_LDO_LINEAR(_id, _min_uV, n_volt, vstep, vreg, vmask, \ | ||
206 | ereg, emask, odelay, ecomask, ecoamp) \ | ||
207 | [HI6421_##_id] = { \ | ||
208 | .desc = { \ | ||
209 | .name = #_id, \ | ||
210 | .ops = &hi6421_ldo_linear_ops, \ | ||
211 | .type = REGULATOR_VOLTAGE, \ | ||
212 | .id = HI6421_##_id, \ | ||
213 | .owner = THIS_MODULE, \ | ||
214 | .min_uV = _min_uV, \ | ||
215 | .n_voltages = n_volt, \ | ||
216 | .uV_step = vstep, \ | ||
217 | .vsel_reg = HI6421_REG_TO_BUS_ADDR(vreg), \ | ||
218 | .vsel_mask = vmask, \ | ||
219 | .enable_reg = HI6421_REG_TO_BUS_ADDR(ereg), \ | ||
220 | .enable_mask = emask, \ | ||
221 | .enable_time = HI6421_LDO_ENABLE_TIME, \ | ||
222 | .off_on_delay = odelay, \ | ||
223 | }, \ | ||
224 | .mode_mask = ecomask, \ | ||
225 | .eco_microamp = ecoamp, \ | ||
226 | } | ||
227 | |||
228 | /* HI6421 LDOAUDIO is a linear voltage regulator with two 4-step ranges | ||
229 | * | ||
230 | * _id - LDO id name string | ||
231 | * n_volt - number of votages available | ||
232 | * volt_ranges - array of regulator_linear_range | ||
233 | * vstep - voltage increase in each linear step in uV | ||
234 | * vreg - voltage select register | ||
235 | * vmask - voltage select mask | ||
236 | * ereg - enable register | ||
237 | * emask - enable mask | ||
238 | * odelay - off/on delay time in uS | ||
239 | * ecomask - eco mode mask | ||
240 | * ecoamp - eco mode load uppler limit in uA | ||
241 | */ | ||
242 | #define HI6421_LDO_LINEAR_RANGE(_id, n_volt, volt_ranges, vreg, vmask, \ | ||
243 | ereg, emask, odelay, ecomask, ecoamp) \ | ||
244 | [HI6421_##_id] = { \ | ||
245 | .desc = { \ | ||
246 | .name = #_id, \ | ||
247 | .ops = &hi6421_ldo_linear_range_ops, \ | ||
248 | .type = REGULATOR_VOLTAGE, \ | ||
249 | .id = HI6421_##_id, \ | ||
250 | .owner = THIS_MODULE, \ | ||
251 | .n_voltages = n_volt, \ | ||
252 | .linear_ranges = volt_ranges, \ | ||
253 | .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ | ||
254 | .vsel_reg = HI6421_REG_TO_BUS_ADDR(vreg), \ | ||
255 | .vsel_mask = vmask, \ | ||
256 | .enable_reg = HI6421_REG_TO_BUS_ADDR(ereg), \ | ||
257 | .enable_mask = emask, \ | ||
258 | .enable_time = HI6421_LDO_ENABLE_TIME, \ | ||
259 | .off_on_delay = odelay, \ | ||
260 | }, \ | ||
261 | .mode_mask = ecomask, \ | ||
262 | .eco_microamp = ecoamp, \ | ||
263 | } | ||
264 | |||
265 | /* HI6421 BUCK0/1/2 are linear voltage regulators at fixed uV_step | ||
266 | * | ||
267 | * _id - BUCK0/1/2 id name string | ||
268 | * vreg - voltage select register | ||
269 | * vmask - voltage select mask | ||
270 | * ereg - enable register | ||
271 | * emask - enable mask | ||
272 | * sleepmask - mask of sleep mode | ||
273 | * etime - enable time | ||
274 | * odelay - off/on delay time in uS | ||
275 | */ | ||
276 | #define HI6421_BUCK012(_id, vreg, vmask, ereg, emask, sleepmask, \ | ||
277 | etime, odelay) \ | ||
278 | [HI6421_##_id] = { \ | ||
279 | .desc = { \ | ||
280 | .name = #_id, \ | ||
281 | .ops = &hi6421_buck012_ops, \ | ||
282 | .type = REGULATOR_VOLTAGE, \ | ||
283 | .id = HI6421_##_id, \ | ||
284 | .owner = THIS_MODULE, \ | ||
285 | .min_uV = 700000, \ | ||
286 | .n_voltages = 128, \ | ||
287 | .uV_step = 7086, \ | ||
288 | .vsel_reg = HI6421_REG_TO_BUS_ADDR(vreg), \ | ||
289 | .vsel_mask = vmask, \ | ||
290 | .enable_reg = HI6421_REG_TO_BUS_ADDR(ereg), \ | ||
291 | .enable_mask = emask, \ | ||
292 | .enable_time = etime, \ | ||
293 | .off_on_delay = odelay, \ | ||
294 | }, \ | ||
295 | .mode_mask = sleepmask, \ | ||
296 | } | ||
297 | |||
298 | /* HI6421 BUCK3/4/5 share similar configurations as LDOs, with exception | ||
299 | * that it supports SLEEP mode, so has different .ops. | ||
300 | * | ||
301 | * _id - LDO id name string | ||
302 | * v_table - voltage table | ||
303 | * vreg - voltage select register | ||
304 | * vmask - voltage select mask | ||
305 | * ereg - enable register | ||
306 | * emask - enable mask | ||
307 | * odelay - off/on delay time in uS | ||
308 | * sleepmask - mask of sleep mode | ||
309 | */ | ||
310 | #define HI6421_BUCK345(_id, v_table, vreg, vmask, ereg, emask, \ | ||
311 | odelay, sleepmask) \ | ||
312 | [HI6421_##_id] = { \ | ||
313 | .desc = { \ | ||
314 | .name = #_id, \ | ||
315 | .ops = &hi6421_buck345_ops, \ | ||
316 | .type = REGULATOR_VOLTAGE, \ | ||
317 | .id = HI6421_##_id, \ | ||
318 | .owner = THIS_MODULE, \ | ||
319 | .n_voltages = ARRAY_SIZE(v_table), \ | ||
320 | .volt_table = v_table, \ | ||
321 | .vsel_reg = HI6421_REG_TO_BUS_ADDR(vreg), \ | ||
322 | .vsel_mask = vmask, \ | ||
323 | .enable_reg = HI6421_REG_TO_BUS_ADDR(ereg), \ | ||
324 | .enable_mask = emask, \ | ||
325 | .enable_time = HI6421_LDO_ENABLE_TIME, \ | ||
326 | .off_on_delay = odelay, \ | ||
327 | }, \ | ||
328 | .mode_mask = sleepmask, \ | ||
329 | } | ||
330 | |||
331 | /* HI6421 regulator information */ | ||
332 | static struct hi6421_regulator_info | ||
333 | hi6421_regulator_info[HI6421_NUM_REGULATORS] = { | ||
334 | HI6421_LDO(LDO0, ldo_0_voltages, 0x20, 0x07, 0x20, 0x10, | ||
335 | 10000, 0x20, 8000), | ||
336 | HI6421_LDO_LINEAR(LDO1, 1700000, 4, 100000, 0x21, 0x03, 0x21, 0x10, | ||
337 | 10000, 0x20, 5000), | ||
338 | HI6421_LDO_LINEAR(LDO2, 1050000, 8, 50000, 0x22, 0x07, 0x22, 0x10, | ||
339 | 20000, 0x20, 8000), | ||
340 | HI6421_LDO_LINEAR(LDO3, 1050000, 8, 50000, 0x23, 0x07, 0x23, 0x10, | ||
341 | 20000, 0x20, 8000), | ||
342 | HI6421_LDO(LDO4, ldo_0_voltages, 0x24, 0x07, 0x24, 0x10, | ||
343 | 20000, 0x20, 8000), | ||
344 | HI6421_LDO(LDO5, ldo_0_voltages, 0x25, 0x07, 0x25, 0x10, | ||
345 | 20000, 0x20, 8000), | ||
346 | HI6421_LDO(LDO6, ldo_0_voltages, 0x26, 0x07, 0x26, 0x10, | ||
347 | 20000, 0x20, 8000), | ||
348 | HI6421_LDO(LDO7, ldo_0_voltages, 0x27, 0x07, 0x27, 0x10, | ||
349 | 20000, 0x20, 5000), | ||
350 | HI6421_LDO(LDO8, ldo_8_voltages, 0x28, 0x07, 0x28, 0x10, | ||
351 | 20000, 0x20, 8000), | ||
352 | HI6421_LDO(LDO9, ldo_0_voltages, 0x29, 0x07, 0x29, 0x10, | ||
353 | 40000, 0x20, 8000), | ||
354 | HI6421_LDO(LDO10, ldo_0_voltages, 0x2a, 0x07, 0x2a, 0x10, | ||
355 | 40000, 0x20, 8000), | ||
356 | HI6421_LDO(LDO11, ldo_0_voltages, 0x2b, 0x07, 0x2b, 0x10, | ||
357 | 40000, 0x20, 8000), | ||
358 | HI6421_LDO(LDO12, ldo_0_voltages, 0x2c, 0x07, 0x2c, 0x10, | ||
359 | 40000, 0x20, 8000), | ||
360 | HI6421_LDO(LDO13, ldo_0_voltages, 0x2d, 0x07, 0x2d, 0x10, | ||
361 | 40000, 0x20, 8000), | ||
362 | HI6421_LDO(LDO14, ldo_0_voltages, 0x2e, 0x07, 0x2e, 0x10, | ||
363 | 40000, 0x20, 8000), | ||
364 | HI6421_LDO(LDO15, ldo_8_voltages, 0x2f, 0x07, 0x2f, 0x10, | ||
365 | 40000, 0x20, 8000), | ||
366 | HI6421_LDO(LDO16, ldo_0_voltages, 0x30, 0x07, 0x30, 0x10, | ||
367 | 40000, 0x20, 8000), | ||
368 | HI6421_LDO(LDO17, ldo_0_voltages, 0x31, 0x07, 0x31, 0x10, | ||
369 | 40000, 0x20, 8000), | ||
370 | HI6421_LDO(LDO18, ldo_0_voltages, 0x32, 0x07, 0x32, 0x10, | ||
371 | 40000, 0x20, 8000), | ||
372 | HI6421_LDO(LDO19, ldo_0_voltages, 0x33, 0x07, 0x33, 0x10, | ||
373 | 40000, 0x20, 8000), | ||
374 | HI6421_LDO(LDO20, ldo_0_voltages, 0x34, 0x07, 0x34, 0x10, | ||
375 | 40000, 0x20, 8000), | ||
376 | HI6421_LDO_LINEAR_RANGE(LDOAUDIO, 8, ldo_audio_volt_range, 0x36, | ||
377 | 0x70, 0x36, 0x01, 40000, 0x02, 5000), | ||
378 | HI6421_BUCK012(BUCK0, 0x0d, 0x7f, 0x0c, 0x01, 0x10, 400, 20000), | ||
379 | HI6421_BUCK012(BUCK1, 0x0f, 0x7f, 0x0e, 0x01, 0x10, 400, 20000), | ||
380 | HI6421_BUCK012(BUCK2, 0x11, 0x7f, 0x10, 0x01, 0x10, 350, 100), | ||
381 | HI6421_BUCK345(BUCK3, buck_3_voltages, 0x13, 0x07, 0x12, 0x01, | ||
382 | 20000, 0x10), | ||
383 | HI6421_BUCK345(BUCK4, buck_4_voltages, 0x15, 0x07, 0x14, 0x01, | ||
384 | 20000, 0x10), | ||
385 | HI6421_BUCK345(BUCK5, buck_5_voltages, 0x17, 0x07, 0x16, 0x01, | ||
386 | 20000, 0x10), | ||
387 | }; | ||
388 | |||
389 | static int hi6421_regulator_enable(struct regulator_dev *rdev) | ||
390 | { | ||
391 | struct hi6421_regulator_pdata *pdata; | ||
392 | |||
393 | pdata = dev_get_drvdata(rdev->dev.parent); | ||
394 | /* hi6421 spec requires regulator enablement must be serialized: | ||
395 | * - Because when BUCK, LDO switching from off to on, it will have | ||
396 | * a huge instantaneous current; so you can not turn on two or | ||
397 | * more LDO or BUCKs simultaneously, or it may burn the chip. | ||
398 | */ | ||
399 | mutex_lock(&pdata->lock); | ||
400 | |||
401 | /* call regulator regmap helper */ | ||
402 | regulator_enable_regmap(rdev); | ||
403 | |||
404 | mutex_unlock(&pdata->lock); | ||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | static unsigned int hi6421_regulator_ldo_get_mode(struct regulator_dev *rdev) | ||
409 | { | ||
410 | struct hi6421_regulator_info *info = rdev_get_drvdata(rdev); | ||
411 | u32 reg_val; | ||
412 | |||
413 | regmap_read(rdev->regmap, rdev->desc->enable_reg, ®_val); | ||
414 | if (reg_val & info->mode_mask) | ||
415 | return REGULATOR_MODE_IDLE; | ||
416 | |||
417 | return REGULATOR_MODE_NORMAL; | ||
418 | } | ||
419 | |||
420 | static unsigned int hi6421_regulator_buck_get_mode(struct regulator_dev *rdev) | ||
421 | { | ||
422 | struct hi6421_regulator_info *info = rdev_get_drvdata(rdev); | ||
423 | u32 reg_val; | ||
424 | |||
425 | regmap_read(rdev->regmap, rdev->desc->enable_reg, ®_val); | ||
426 | if (reg_val & info->mode_mask) | ||
427 | return REGULATOR_MODE_STANDBY; | ||
428 | |||
429 | return REGULATOR_MODE_NORMAL; | ||
430 | } | ||
431 | |||
432 | static int hi6421_regulator_ldo_set_mode(struct regulator_dev *rdev, | ||
433 | unsigned int mode) | ||
434 | { | ||
435 | struct hi6421_regulator_info *info = rdev_get_drvdata(rdev); | ||
436 | u32 new_mode; | ||
437 | |||
438 | switch (mode) { | ||
439 | case REGULATOR_MODE_NORMAL: | ||
440 | new_mode = 0; | ||
441 | break; | ||
442 | case REGULATOR_MODE_IDLE: | ||
443 | new_mode = info->mode_mask; | ||
444 | break; | ||
445 | default: | ||
446 | return -EINVAL; | ||
447 | } | ||
448 | |||
449 | /* set mode */ | ||
450 | regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, | ||
451 | info->mode_mask, new_mode); | ||
452 | |||
453 | return 0; | ||
454 | } | ||
455 | |||
456 | static int hi6421_regulator_buck_set_mode(struct regulator_dev *rdev, | ||
457 | unsigned int mode) | ||
458 | { | ||
459 | struct hi6421_regulator_info *info = rdev_get_drvdata(rdev); | ||
460 | u32 new_mode; | ||
461 | |||
462 | switch (mode) { | ||
463 | case REGULATOR_MODE_NORMAL: | ||
464 | new_mode = 0; | ||
465 | break; | ||
466 | case REGULATOR_MODE_STANDBY: | ||
467 | new_mode = info->mode_mask; | ||
468 | break; | ||
469 | default: | ||
470 | return -EINVAL; | ||
471 | } | ||
472 | |||
473 | /* set mode */ | ||
474 | regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, | ||
475 | info->mode_mask, new_mode); | ||
476 | |||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | unsigned int hi6421_regulator_ldo_get_optimum_mode(struct regulator_dev *rdev, | ||
481 | int input_uV, int output_uV, int load_uA) | ||
482 | { | ||
483 | struct hi6421_regulator_info *info = rdev_get_drvdata(rdev); | ||
484 | |||
485 | if (load_uA > info->eco_microamp) | ||
486 | return REGULATOR_MODE_NORMAL; | ||
487 | |||
488 | return REGULATOR_MODE_IDLE; | ||
489 | } | ||
490 | |||
491 | static const struct regulator_ops hi6421_ldo_ops = { | ||
492 | .is_enabled = regulator_is_enabled_regmap, | ||
493 | .enable = hi6421_regulator_enable, | ||
494 | .disable = regulator_disable_regmap, | ||
495 | .list_voltage = regulator_list_voltage_table, | ||
496 | .map_voltage = regulator_map_voltage_ascend, | ||
497 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
498 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
499 | .get_mode = hi6421_regulator_ldo_get_mode, | ||
500 | .set_mode = hi6421_regulator_ldo_set_mode, | ||
501 | .get_optimum_mode = hi6421_regulator_ldo_get_optimum_mode, | ||
502 | }; | ||
503 | |||
504 | static const struct regulator_ops hi6421_ldo_linear_ops = { | ||
505 | .is_enabled = regulator_is_enabled_regmap, | ||
506 | .enable = hi6421_regulator_enable, | ||
507 | .disable = regulator_disable_regmap, | ||
508 | .list_voltage = regulator_list_voltage_linear, | ||
509 | .map_voltage = regulator_map_voltage_linear, | ||
510 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
511 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
512 | .get_mode = hi6421_regulator_ldo_get_mode, | ||
513 | .set_mode = hi6421_regulator_ldo_set_mode, | ||
514 | .get_optimum_mode = hi6421_regulator_ldo_get_optimum_mode, | ||
515 | }; | ||
516 | |||
517 | static const struct regulator_ops hi6421_ldo_linear_range_ops = { | ||
518 | .is_enabled = regulator_is_enabled_regmap, | ||
519 | .enable = hi6421_regulator_enable, | ||
520 | .disable = regulator_disable_regmap, | ||
521 | .list_voltage = regulator_list_voltage_linear_range, | ||
522 | .map_voltage = regulator_map_voltage_linear_range, | ||
523 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
524 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
525 | .get_mode = hi6421_regulator_ldo_get_mode, | ||
526 | .set_mode = hi6421_regulator_ldo_set_mode, | ||
527 | .get_optimum_mode = hi6421_regulator_ldo_get_optimum_mode, | ||
528 | }; | ||
529 | |||
530 | static const struct regulator_ops hi6421_buck012_ops = { | ||
531 | .is_enabled = regulator_is_enabled_regmap, | ||
532 | .enable = hi6421_regulator_enable, | ||
533 | .disable = regulator_disable_regmap, | ||
534 | .list_voltage = regulator_list_voltage_linear, | ||
535 | .map_voltage = regulator_map_voltage_linear, | ||
536 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
537 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
538 | .get_mode = hi6421_regulator_buck_get_mode, | ||
539 | .set_mode = hi6421_regulator_buck_set_mode, | ||
540 | }; | ||
541 | |||
542 | static const struct regulator_ops hi6421_buck345_ops = { | ||
543 | .is_enabled = regulator_is_enabled_regmap, | ||
544 | .enable = hi6421_regulator_enable, | ||
545 | .disable = regulator_disable_regmap, | ||
546 | .list_voltage = regulator_list_voltage_table, | ||
547 | .map_voltage = regulator_map_voltage_ascend, | ||
548 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
549 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
550 | .get_mode = hi6421_regulator_buck_get_mode, | ||
551 | .set_mode = hi6421_regulator_buck_set_mode, | ||
552 | }; | ||
553 | |||
554 | static int hi6421_regulator_register(struct platform_device *pdev, | ||
555 | struct regmap *rmap, | ||
556 | struct regulator_init_data *init_data, | ||
557 | int id, struct device_node *np) | ||
558 | { | ||
559 | struct hi6421_regulator_info *info = NULL; | ||
560 | struct regulator_config config = { }; | ||
561 | struct regulator_dev *rdev; | ||
562 | |||
563 | /* assign per-regulator data */ | ||
564 | info = &hi6421_regulator_info[id]; | ||
565 | |||
566 | config.dev = &pdev->dev; | ||
567 | config.init_data = init_data; | ||
568 | config.driver_data = info; | ||
569 | config.regmap = rmap; | ||
570 | config.of_node = np; | ||
571 | |||
572 | /* register regulator with framework */ | ||
573 | rdev = devm_regulator_register(&pdev->dev, &info->desc, &config); | ||
574 | if (IS_ERR(rdev)) { | ||
575 | dev_err(&pdev->dev, "failed to register regulator %s\n", | ||
576 | info->desc.name); | ||
577 | return PTR_ERR(rdev); | ||
578 | } | ||
579 | |||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | static int hi6421_regulator_probe(struct platform_device *pdev) | ||
584 | { | ||
585 | struct device *dev = &pdev->dev; | ||
586 | struct device_node *np; | ||
587 | struct hi6421_pmic *pmic; | ||
588 | struct hi6421_regulator_pdata *pdata; | ||
589 | int i, ret = 0; | ||
590 | |||
591 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
592 | if (!pdata) | ||
593 | return -ENOMEM; | ||
594 | mutex_init(&pdata->lock); | ||
595 | platform_set_drvdata(pdev, pdata); | ||
596 | |||
597 | np = of_get_child_by_name(dev->parent->of_node, "regulators"); | ||
598 | if (!np) | ||
599 | return -ENODEV; | ||
600 | |||
601 | ret = of_regulator_match(dev, np, | ||
602 | hi6421_regulator_match, | ||
603 | ARRAY_SIZE(hi6421_regulator_match)); | ||
604 | of_node_put(np); | ||
605 | if (ret < 0) { | ||
606 | dev_err(dev, "Error parsing regulator init data: %d\n", ret); | ||
607 | return ret; | ||
608 | } | ||
609 | |||
610 | pmic = dev_get_drvdata(dev->parent); | ||
611 | |||
612 | for (i = 0; i < ARRAY_SIZE(hi6421_regulator_info); i++) { | ||
613 | ret = hi6421_regulator_register(pdev, pmic->regmap, | ||
614 | hi6421_regulator_match[i].init_data, i, | ||
615 | hi6421_regulator_match[i].of_node); | ||
616 | if (ret) | ||
617 | return ret; | ||
618 | } | ||
619 | |||
620 | return 0; | ||
621 | } | ||
622 | |||
623 | static struct platform_driver hi6421_regulator_driver = { | ||
624 | .driver = { | ||
625 | .name = "hi6421-regulator", | ||
626 | .owner = THIS_MODULE, | ||
627 | }, | ||
628 | .probe = hi6421_regulator_probe, | ||
629 | }; | ||
630 | module_platform_driver(hi6421_regulator_driver); | ||
631 | |||
632 | MODULE_AUTHOR("Guodong Xu <guodong.xu@linaro.org>"); | ||
633 | MODULE_DESCRIPTION("Hi6421 regulator driver"); | ||
634 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h index 84bbda10c396..a6043ad32ead 100644 --- a/drivers/regulator/internal.h +++ b/drivers/regulator/internal.h | |||
@@ -35,4 +35,8 @@ struct regulator { | |||
35 | struct dentry *debugfs; | 35 | struct dentry *debugfs; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | struct regulator_init_data *regulator_of_get_init_data(struct device *dev, | ||
39 | const struct regulator_desc *desc, | ||
40 | struct device_node **node); | ||
41 | |||
38 | #endif | 42 | #endif |
diff --git a/drivers/regulator/isl9305.c b/drivers/regulator/isl9305.c new file mode 100644 index 000000000000..92fefd98da58 --- /dev/null +++ b/drivers/regulator/isl9305.c | |||
@@ -0,0 +1,207 @@ | |||
1 | /* | ||
2 | * isl9305 - Intersil ISL9305 DCDC regulator | ||
3 | * | ||
4 | * Copyright 2014 Linaro Ltd | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@kernel.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/of.h> | ||
18 | #include <linux/platform_data/isl9305.h> | ||
19 | #include <linux/regmap.h> | ||
20 | #include <linux/regulator/driver.h> | ||
21 | #include <linux/regulator/of_regulator.h> | ||
22 | #include <linux/slab.h> | ||
23 | |||
24 | /* | ||
25 | * Registers | ||
26 | */ | ||
27 | #define ISL9305_DCD1OUT 0x0 | ||
28 | #define ISL9305_DCD2OUT 0x1 | ||
29 | #define ISL9305_LDO1OUT 0x2 | ||
30 | #define ISL9305_LDO2OUT 0x3 | ||
31 | #define ISL9305_DCD_PARAMETER 0x4 | ||
32 | #define ISL9305_SYSTEM_PARAMETER 0x5 | ||
33 | #define ISL9305_DCD_SRCTL 0x6 | ||
34 | |||
35 | #define ISL9305_MAX_REG ISL9305_DCD_SRCTL | ||
36 | |||
37 | /* | ||
38 | * DCD_PARAMETER | ||
39 | */ | ||
40 | #define ISL9305_DCD_PHASE 0x40 | ||
41 | #define ISL9305_DCD2_ULTRA 0x20 | ||
42 | #define ISL9305_DCD1_ULTRA 0x10 | ||
43 | #define ISL9305_DCD2_BLD 0x08 | ||
44 | #define ISL9305_DCD1_BLD 0x04 | ||
45 | #define ISL9305_DCD2_MODE 0x02 | ||
46 | #define ISL9305_DCD1_MODE 0x01 | ||
47 | |||
48 | /* | ||
49 | * SYSTEM_PARAMETER | ||
50 | */ | ||
51 | #define ISL9305_I2C_EN 0x40 | ||
52 | #define ISL9305_DCDPOR_MASK 0x30 | ||
53 | #define ISL9305_LDO2_EN 0x08 | ||
54 | #define ISL9305_LDO1_EN 0x04 | ||
55 | #define ISL9305_DCD2_EN 0x02 | ||
56 | #define ISL9305_DCD1_EN 0x01 | ||
57 | |||
58 | /* | ||
59 | * DCD_SRCTL | ||
60 | */ | ||
61 | #define ISL9305_DCD2SR_MASK 0xc0 | ||
62 | #define ISL9305_DCD1SR_MASK 0x07 | ||
63 | |||
64 | static const struct regulator_ops isl9305_ops = { | ||
65 | .enable = regulator_enable_regmap, | ||
66 | .disable = regulator_disable_regmap, | ||
67 | .is_enabled = regulator_is_enabled_regmap, | ||
68 | .list_voltage = regulator_list_voltage_linear, | ||
69 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
70 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
71 | }; | ||
72 | |||
73 | static const struct regulator_desc isl9305_regulators[] = { | ||
74 | [ISL9305_DCD1] = { | ||
75 | .name = "DCD1", | ||
76 | .of_match = of_match_ptr("dcd1"), | ||
77 | .regulators_node = of_match_ptr("regulators"), | ||
78 | .n_voltages = 0x70, | ||
79 | .min_uV = 825000, | ||
80 | .uV_step = 25000, | ||
81 | .vsel_reg = ISL9305_DCD1OUT, | ||
82 | .vsel_mask = 0x7f, | ||
83 | .enable_reg = ISL9305_SYSTEM_PARAMETER, | ||
84 | .enable_mask = ISL9305_DCD1_EN, | ||
85 | .supply_name = "VINDCD1", | ||
86 | .ops = &isl9305_ops, | ||
87 | }, | ||
88 | [ISL9305_DCD2] = { | ||
89 | .name = "DCD2", | ||
90 | .of_match = of_match_ptr("dcd2"), | ||
91 | .regulators_node = of_match_ptr("regulators"), | ||
92 | .n_voltages = 0x70, | ||
93 | .min_uV = 825000, | ||
94 | .uV_step = 25000, | ||
95 | .vsel_reg = ISL9305_DCD2OUT, | ||
96 | .vsel_mask = 0x7f, | ||
97 | .enable_reg = ISL9305_SYSTEM_PARAMETER, | ||
98 | .enable_mask = ISL9305_DCD2_EN, | ||
99 | .supply_name = "VINDCD2", | ||
100 | .ops = &isl9305_ops, | ||
101 | }, | ||
102 | [ISL9305_LDO1] = { | ||
103 | .name = "LDO1", | ||
104 | .of_match = of_match_ptr("ldo1"), | ||
105 | .regulators_node = of_match_ptr("regulators"), | ||
106 | .n_voltages = 0x37, | ||
107 | .min_uV = 900000, | ||
108 | .uV_step = 50000, | ||
109 | .vsel_reg = ISL9305_LDO1OUT, | ||
110 | .vsel_mask = 0x3f, | ||
111 | .enable_reg = ISL9305_SYSTEM_PARAMETER, | ||
112 | .enable_mask = ISL9305_LDO1_EN, | ||
113 | .supply_name = "VINLDO1", | ||
114 | .ops = &isl9305_ops, | ||
115 | }, | ||
116 | [ISL9305_LDO2] = { | ||
117 | .name = "LDO2", | ||
118 | .of_match = of_match_ptr("ldo2"), | ||
119 | .regulators_node = of_match_ptr("regulators"), | ||
120 | .n_voltages = 0x37, | ||
121 | .min_uV = 900000, | ||
122 | .uV_step = 50000, | ||
123 | .vsel_reg = ISL9305_LDO2OUT, | ||
124 | .vsel_mask = 0x3f, | ||
125 | .enable_reg = ISL9305_SYSTEM_PARAMETER, | ||
126 | .enable_mask = ISL9305_LDO2_EN, | ||
127 | .supply_name = "VINLDO2", | ||
128 | .ops = &isl9305_ops, | ||
129 | }, | ||
130 | }; | ||
131 | |||
132 | static const struct regmap_config isl9305_regmap = { | ||
133 | .reg_bits = 8, | ||
134 | .val_bits = 8, | ||
135 | |||
136 | .max_register = ISL9305_MAX_REG, | ||
137 | .cache_type = REGCACHE_RBTREE, | ||
138 | }; | ||
139 | |||
140 | static int isl9305_i2c_probe(struct i2c_client *i2c, | ||
141 | const struct i2c_device_id *id) | ||
142 | { | ||
143 | struct regulator_config config = { }; | ||
144 | struct isl9305_pdata *pdata = i2c->dev.platform_data; | ||
145 | struct regulator_dev *rdev; | ||
146 | struct regmap *regmap; | ||
147 | int i, ret; | ||
148 | |||
149 | regmap = devm_regmap_init_i2c(i2c, &isl9305_regmap); | ||
150 | if (IS_ERR(regmap)) { | ||
151 | ret = PTR_ERR(regmap); | ||
152 | dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret); | ||
153 | return ret; | ||
154 | } | ||
155 | |||
156 | config.dev = &i2c->dev; | ||
157 | |||
158 | for (i = 0; i < ARRAY_SIZE(isl9305_regulators); i++) { | ||
159 | if (pdata) | ||
160 | config.init_data = pdata->init_data[i]; | ||
161 | else | ||
162 | config.init_data = NULL; | ||
163 | |||
164 | rdev = devm_regulator_register(&i2c->dev, | ||
165 | &isl9305_regulators[i], | ||
166 | &config); | ||
167 | if (IS_ERR(rdev)) { | ||
168 | ret = PTR_ERR(rdev); | ||
169 | dev_err(&i2c->dev, "Failed to register %s: %d\n", | ||
170 | isl9305_regulators[i].name, ret); | ||
171 | return ret; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | #ifdef CONFIG_OF | ||
179 | static const struct of_device_id isl9305_dt_ids[] = { | ||
180 | { .compatible = "isl,isl9305" }, | ||
181 | { .compatible = "isl,isl9305h" }, | ||
182 | {}, | ||
183 | }; | ||
184 | #endif | ||
185 | |||
186 | static const struct i2c_device_id isl9305_i2c_id[] = { | ||
187 | { "isl9305", }, | ||
188 | { "isl9305h", }, | ||
189 | { } | ||
190 | }; | ||
191 | MODULE_DEVICE_TABLE(i2c, isl9305_i2c_id); | ||
192 | |||
193 | static struct i2c_driver isl9305_regulator_driver = { | ||
194 | .driver = { | ||
195 | .name = "isl9305", | ||
196 | .owner = THIS_MODULE, | ||
197 | .of_match_table = of_match_ptr(isl9305_dt_ids), | ||
198 | }, | ||
199 | .probe = isl9305_i2c_probe, | ||
200 | .id_table = isl9305_i2c_id, | ||
201 | }; | ||
202 | |||
203 | module_i2c_driver(isl9305_regulator_driver); | ||
204 | |||
205 | MODULE_AUTHOR("Mark Brown"); | ||
206 | MODULE_DESCRIPTION("Intersil ISL9305 DCDC regulator"); | ||
207 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index f374fa57220f..793b662a1967 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c | |||
@@ -526,6 +526,7 @@ static unsigned int mc13892_vcam_get_mode(struct regulator_dev *rdev) | |||
526 | return REGULATOR_MODE_NORMAL; | 526 | return REGULATOR_MODE_NORMAL; |
527 | } | 527 | } |
528 | 528 | ||
529 | static struct regulator_ops mc13892_vcam_ops; | ||
529 | 530 | ||
530 | static int mc13892_regulator_probe(struct platform_device *pdev) | 531 | static int mc13892_regulator_probe(struct platform_device *pdev) |
531 | { | 532 | { |
@@ -582,10 +583,12 @@ static int mc13892_regulator_probe(struct platform_device *pdev) | |||
582 | } | 583 | } |
583 | mc13xxx_unlock(mc13892); | 584 | mc13xxx_unlock(mc13892); |
584 | 585 | ||
585 | mc13892_regulators[MC13892_VCAM].desc.ops->set_mode | 586 | /* update mc13892_vcam ops */ |
586 | = mc13892_vcam_set_mode; | 587 | memcpy(&mc13892_vcam_ops, mc13892_regulators[MC13892_VCAM].desc.ops, |
587 | mc13892_regulators[MC13892_VCAM].desc.ops->get_mode | 588 | sizeof(struct regulator_ops)); |
588 | = mc13892_vcam_get_mode; | 589 | mc13892_vcam_ops.set_mode = mc13892_vcam_set_mode, |
590 | mc13892_vcam_ops.get_mode = mc13892_vcam_get_mode, | ||
591 | mc13892_regulators[MC13892_VCAM].desc.ops = &mc13892_vcam_ops; | ||
589 | 592 | ||
590 | mc13xxx_data = mc13xxx_parse_regulators_dt(pdev, mc13892_regulators, | 593 | mc13xxx_data = mc13xxx_parse_regulators_dt(pdev, mc13892_regulators, |
591 | ARRAY_SIZE(mc13892_regulators)); | 594 | ARRAY_SIZE(mc13892_regulators)); |
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index ee5e67bc8d5b..7a51814abdc5 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c | |||
@@ -14,8 +14,11 @@ | |||
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/of.h> | 15 | #include <linux/of.h> |
16 | #include <linux/regulator/machine.h> | 16 | #include <linux/regulator/machine.h> |
17 | #include <linux/regulator/driver.h> | ||
17 | #include <linux/regulator/of_regulator.h> | 18 | #include <linux/regulator/of_regulator.h> |
18 | 19 | ||
20 | #include "internal.h" | ||
21 | |||
19 | static void of_get_regulation_constraints(struct device_node *np, | 22 | static void of_get_regulation_constraints(struct device_node *np, |
20 | struct regulator_init_data **init_data) | 23 | struct regulator_init_data **init_data) |
21 | { | 24 | { |
@@ -189,3 +192,51 @@ int of_regulator_match(struct device *dev, struct device_node *node, | |||
189 | return count; | 192 | return count; |
190 | } | 193 | } |
191 | EXPORT_SYMBOL_GPL(of_regulator_match); | 194 | EXPORT_SYMBOL_GPL(of_regulator_match); |
195 | |||
196 | struct regulator_init_data *regulator_of_get_init_data(struct device *dev, | ||
197 | const struct regulator_desc *desc, | ||
198 | struct device_node **node) | ||
199 | { | ||
200 | struct device_node *search, *child; | ||
201 | struct regulator_init_data *init_data = NULL; | ||
202 | const char *name; | ||
203 | |||
204 | if (!dev->of_node || !desc->of_match) | ||
205 | return NULL; | ||
206 | |||
207 | if (desc->regulators_node) | ||
208 | search = of_get_child_by_name(dev->of_node, | ||
209 | desc->regulators_node); | ||
210 | else | ||
211 | search = dev->of_node; | ||
212 | |||
213 | if (!search) { | ||
214 | dev_err(dev, "Failed to find regulator container node\n"); | ||
215 | return NULL; | ||
216 | } | ||
217 | |||
218 | for_each_child_of_node(search, child) { | ||
219 | name = of_get_property(child, "regulator-compatible", NULL); | ||
220 | if (!name) | ||
221 | name = child->name; | ||
222 | |||
223 | if (strcmp(desc->of_match, name)) | ||
224 | continue; | ||
225 | |||
226 | init_data = of_get_regulator_init_data(dev, child); | ||
227 | if (!init_data) { | ||
228 | dev_err(dev, | ||
229 | "failed to parse DT for regulator %s\n", | ||
230 | child->name); | ||
231 | break; | ||
232 | } | ||
233 | |||
234 | of_node_get(child); | ||
235 | *node = child; | ||
236 | break; | ||
237 | } | ||
238 | |||
239 | of_node_put(search); | ||
240 | |||
241 | return init_data; | ||
242 | } | ||
diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c new file mode 100644 index 000000000000..d3f55eaea058 --- /dev/null +++ b/drivers/regulator/pwm-regulator.c | |||
@@ -0,0 +1,197 @@ | |||
1 | /* | ||
2 | * Regulator driver for PWM Regulators | ||
3 | * | ||
4 | * Copyright (C) 2014 - STMicroelectronics Inc. | ||
5 | * | ||
6 | * Author: Lee Jones <lee.jones@linaro.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/regulator/driver.h> | ||
17 | #include <linux/regulator/machine.h> | ||
18 | #include <linux/regulator/of_regulator.h> | ||
19 | #include <linux/of.h> | ||
20 | #include <linux/of_device.h> | ||
21 | #include <linux/pwm.h> | ||
22 | |||
23 | struct pwm_regulator_data { | ||
24 | struct regulator_desc desc; | ||
25 | struct pwm_voltages *duty_cycle_table; | ||
26 | struct pwm_device *pwm; | ||
27 | bool enabled; | ||
28 | int state; | ||
29 | }; | ||
30 | |||
31 | struct pwm_voltages { | ||
32 | unsigned int uV; | ||
33 | unsigned int dutycycle; | ||
34 | }; | ||
35 | |||
36 | static int pwm_regulator_get_voltage_sel(struct regulator_dev *dev) | ||
37 | { | ||
38 | struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); | ||
39 | |||
40 | return drvdata->state; | ||
41 | } | ||
42 | |||
43 | static int pwm_regulator_set_voltage_sel(struct regulator_dev *dev, | ||
44 | unsigned selector) | ||
45 | { | ||
46 | struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); | ||
47 | unsigned int pwm_reg_period; | ||
48 | int dutycycle; | ||
49 | int ret; | ||
50 | |||
51 | pwm_reg_period = pwm_get_period(drvdata->pwm); | ||
52 | |||
53 | dutycycle = (pwm_reg_period * | ||
54 | drvdata->duty_cycle_table[selector].dutycycle) / 100; | ||
55 | |||
56 | ret = pwm_config(drvdata->pwm, dutycycle, pwm_reg_period); | ||
57 | if (ret) { | ||
58 | dev_err(&dev->dev, "Failed to configure PWM\n"); | ||
59 | return ret; | ||
60 | } | ||
61 | |||
62 | drvdata->state = selector; | ||
63 | |||
64 | if (!drvdata->enabled) { | ||
65 | ret = pwm_enable(drvdata->pwm); | ||
66 | if (ret) { | ||
67 | dev_err(&dev->dev, "Failed to enable PWM\n"); | ||
68 | return ret; | ||
69 | } | ||
70 | drvdata->enabled = true; | ||
71 | } | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static int pwm_regulator_list_voltage(struct regulator_dev *dev, | ||
77 | unsigned selector) | ||
78 | { | ||
79 | struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev); | ||
80 | |||
81 | if (selector >= drvdata->desc.n_voltages) | ||
82 | return -EINVAL; | ||
83 | |||
84 | return drvdata->duty_cycle_table[selector].uV; | ||
85 | } | ||
86 | |||
87 | static struct regulator_ops pwm_regulator_voltage_ops = { | ||
88 | .set_voltage_sel = pwm_regulator_set_voltage_sel, | ||
89 | .get_voltage_sel = pwm_regulator_get_voltage_sel, | ||
90 | .list_voltage = pwm_regulator_list_voltage, | ||
91 | .map_voltage = regulator_map_voltage_iterate, | ||
92 | }; | ||
93 | |||
94 | static const struct regulator_desc pwm_regulator_desc = { | ||
95 | .name = "pwm-regulator", | ||
96 | .ops = &pwm_regulator_voltage_ops, | ||
97 | .type = REGULATOR_VOLTAGE, | ||
98 | .owner = THIS_MODULE, | ||
99 | .supply_name = "pwm", | ||
100 | }; | ||
101 | |||
102 | static int pwm_regulator_probe(struct platform_device *pdev) | ||
103 | { | ||
104 | struct pwm_regulator_data *drvdata; | ||
105 | struct property *prop; | ||
106 | struct regulator_dev *regulator; | ||
107 | struct regulator_config config = { }; | ||
108 | struct device_node *np = pdev->dev.of_node; | ||
109 | int length, ret; | ||
110 | |||
111 | if (!np) { | ||
112 | dev_err(&pdev->dev, "Device Tree node missing\n"); | ||
113 | return -EINVAL; | ||
114 | } | ||
115 | |||
116 | drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); | ||
117 | if (!drvdata) | ||
118 | return -ENOMEM; | ||
119 | |||
120 | memcpy(&drvdata->desc, &pwm_regulator_desc, sizeof(pwm_regulator_desc)); | ||
121 | |||
122 | /* determine the number of voltage-table */ | ||
123 | prop = of_find_property(np, "voltage-table", &length); | ||
124 | if (!prop) { | ||
125 | dev_err(&pdev->dev, "No voltage-table\n"); | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | |||
129 | if ((length < sizeof(*drvdata->duty_cycle_table)) || | ||
130 | (length % sizeof(*drvdata->duty_cycle_table))) { | ||
131 | dev_err(&pdev->dev, "voltage-table length(%d) is invalid\n", | ||
132 | length); | ||
133 | return -EINVAL; | ||
134 | } | ||
135 | |||
136 | drvdata->desc.n_voltages = length / sizeof(*drvdata->duty_cycle_table); | ||
137 | |||
138 | drvdata->duty_cycle_table = devm_kzalloc(&pdev->dev, | ||
139 | length, GFP_KERNEL); | ||
140 | if (!drvdata->duty_cycle_table) | ||
141 | return -ENOMEM; | ||
142 | |||
143 | /* read voltage table from DT property */ | ||
144 | ret = of_property_read_u32_array(np, "voltage-table", | ||
145 | (u32 *)drvdata->duty_cycle_table, | ||
146 | length / sizeof(u32)); | ||
147 | if (ret < 0) { | ||
148 | dev_err(&pdev->dev, "read voltage-table failed\n"); | ||
149 | return ret; | ||
150 | } | ||
151 | |||
152 | config.init_data = of_get_regulator_init_data(&pdev->dev, np); | ||
153 | if (!config.init_data) | ||
154 | return -ENOMEM; | ||
155 | |||
156 | config.of_node = np; | ||
157 | config.dev = &pdev->dev; | ||
158 | config.driver_data = drvdata; | ||
159 | |||
160 | drvdata->pwm = devm_pwm_get(&pdev->dev, NULL); | ||
161 | if (IS_ERR(drvdata->pwm)) { | ||
162 | dev_err(&pdev->dev, "Failed to get PWM\n"); | ||
163 | return PTR_ERR(drvdata->pwm); | ||
164 | } | ||
165 | |||
166 | regulator = devm_regulator_register(&pdev->dev, | ||
167 | &drvdata->desc, &config); | ||
168 | if (IS_ERR(regulator)) { | ||
169 | dev_err(&pdev->dev, "Failed to register regulator %s\n", | ||
170 | drvdata->desc.name); | ||
171 | return PTR_ERR(regulator); | ||
172 | } | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | static const struct of_device_id pwm_of_match[] = { | ||
178 | { .compatible = "pwm-regulator" }, | ||
179 | { }, | ||
180 | }; | ||
181 | MODULE_DEVICE_TABLE(of, pwm_of_match); | ||
182 | |||
183 | static struct platform_driver pwm_regulator_driver = { | ||
184 | .driver = { | ||
185 | .name = "pwm-regulator", | ||
186 | .owner = THIS_MODULE, | ||
187 | .of_match_table = of_match_ptr(pwm_of_match), | ||
188 | }, | ||
189 | .probe = pwm_regulator_probe, | ||
190 | }; | ||
191 | |||
192 | module_platform_driver(pwm_regulator_driver); | ||
193 | |||
194 | MODULE_LICENSE("GPL"); | ||
195 | MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>"); | ||
196 | MODULE_DESCRIPTION("PWM Regulator Driver"); | ||
197 | MODULE_ALIAS("platform:pwm-regulator"); | ||
diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c new file mode 100644 index 000000000000..b55cd5b50ebe --- /dev/null +++ b/drivers/regulator/qcom_rpm-regulator.c | |||
@@ -0,0 +1,798 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014, Sony Mobile Communications AB. | ||
3 | * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 and | ||
7 | * only version 2 as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/of.h> | ||
18 | #include <linux/of_device.h> | ||
19 | #include <linux/regulator/driver.h> | ||
20 | #include <linux/regulator/machine.h> | ||
21 | #include <linux/regulator/of_regulator.h> | ||
22 | #include <linux/mfd/qcom_rpm.h> | ||
23 | |||
24 | #include <dt-bindings/mfd/qcom-rpm.h> | ||
25 | |||
26 | #define MAX_REQUEST_LEN 2 | ||
27 | |||
28 | struct request_member { | ||
29 | int word; | ||
30 | unsigned int mask; | ||
31 | int shift; | ||
32 | }; | ||
33 | |||
34 | struct rpm_reg_parts { | ||
35 | struct request_member mV; /* used if voltage is in mV */ | ||
36 | struct request_member uV; /* used if voltage is in uV */ | ||
37 | struct request_member ip; /* peak current in mA */ | ||
38 | struct request_member pd; /* pull down enable */ | ||
39 | struct request_member ia; /* average current in mA */ | ||
40 | struct request_member fm; /* force mode */ | ||
41 | struct request_member pm; /* power mode */ | ||
42 | struct request_member pc; /* pin control */ | ||
43 | struct request_member pf; /* pin function */ | ||
44 | struct request_member enable_state; /* NCP and switch */ | ||
45 | struct request_member comp_mode; /* NCP */ | ||
46 | struct request_member freq; /* frequency: NCP and SMPS */ | ||
47 | struct request_member freq_clk_src; /* clock source: SMPS */ | ||
48 | struct request_member hpm; /* switch: control OCP and SS */ | ||
49 | int request_len; | ||
50 | }; | ||
51 | |||
52 | #define FORCE_MODE_IS_2_BITS(reg) \ | ||
53 | (((reg)->parts->fm.mask >> (reg)->parts->fm.shift) == 3) | ||
54 | |||
55 | struct qcom_rpm_reg { | ||
56 | struct qcom_rpm *rpm; | ||
57 | |||
58 | struct mutex lock; | ||
59 | struct device *dev; | ||
60 | struct regulator_desc desc; | ||
61 | const struct rpm_reg_parts *parts; | ||
62 | |||
63 | int resource; | ||
64 | u32 val[MAX_REQUEST_LEN]; | ||
65 | |||
66 | int uV; | ||
67 | int is_enabled; | ||
68 | |||
69 | bool supports_force_mode_auto; | ||
70 | bool supports_force_mode_bypass; | ||
71 | }; | ||
72 | |||
73 | static const struct rpm_reg_parts rpm8660_ldo_parts = { | ||
74 | .request_len = 2, | ||
75 | .mV = { 0, 0x00000FFF, 0 }, | ||
76 | .ip = { 0, 0x00FFF000, 12 }, | ||
77 | .fm = { 0, 0x03000000, 24 }, | ||
78 | .pc = { 0, 0x3C000000, 26 }, | ||
79 | .pf = { 0, 0xC0000000, 30 }, | ||
80 | .pd = { 1, 0x00000001, 0 }, | ||
81 | .ia = { 1, 0x00001FFE, 1 }, | ||
82 | }; | ||
83 | |||
84 | static const struct rpm_reg_parts rpm8660_smps_parts = { | ||
85 | .request_len = 2, | ||
86 | .mV = { 0, 0x00000FFF, 0 }, | ||
87 | .ip = { 0, 0x00FFF000, 12 }, | ||
88 | .fm = { 0, 0x03000000, 24 }, | ||
89 | .pc = { 0, 0x3C000000, 26 }, | ||
90 | .pf = { 0, 0xC0000000, 30 }, | ||
91 | .pd = { 1, 0x00000001, 0 }, | ||
92 | .ia = { 1, 0x00001FFE, 1 }, | ||
93 | .freq = { 1, 0x001FE000, 13 }, | ||
94 | .freq_clk_src = { 1, 0x00600000, 21 }, | ||
95 | }; | ||
96 | |||
97 | static const struct rpm_reg_parts rpm8660_switch_parts = { | ||
98 | .request_len = 1, | ||
99 | .enable_state = { 0, 0x00000001, 0 }, | ||
100 | .pd = { 0, 0x00000002, 1 }, | ||
101 | .pc = { 0, 0x0000003C, 2 }, | ||
102 | .pf = { 0, 0x000000C0, 6 }, | ||
103 | .hpm = { 0, 0x00000300, 8 }, | ||
104 | }; | ||
105 | |||
106 | static const struct rpm_reg_parts rpm8660_ncp_parts = { | ||
107 | .request_len = 1, | ||
108 | .mV = { 0, 0x00000FFF, 0 }, | ||
109 | .enable_state = { 0, 0x00001000, 12 }, | ||
110 | .comp_mode = { 0, 0x00002000, 13 }, | ||
111 | .freq = { 0, 0x003FC000, 14 }, | ||
112 | }; | ||
113 | |||
114 | static const struct rpm_reg_parts rpm8960_ldo_parts = { | ||
115 | .request_len = 2, | ||
116 | .uV = { 0, 0x007FFFFF, 0 }, | ||
117 | .pd = { 0, 0x00800000, 23 }, | ||
118 | .pc = { 0, 0x0F000000, 24 }, | ||
119 | .pf = { 0, 0xF0000000, 28 }, | ||
120 | .ip = { 1, 0x000003FF, 0 }, | ||
121 | .ia = { 1, 0x000FFC00, 10 }, | ||
122 | .fm = { 1, 0x00700000, 20 }, | ||
123 | }; | ||
124 | |||
125 | static const struct rpm_reg_parts rpm8960_smps_parts = { | ||
126 | .request_len = 2, | ||
127 | .uV = { 0, 0x007FFFFF, 0 }, | ||
128 | .pd = { 0, 0x00800000, 23 }, | ||
129 | .pc = { 0, 0x0F000000, 24 }, | ||
130 | .pf = { 0, 0xF0000000, 28 }, | ||
131 | .ip = { 1, 0x000003FF, 0 }, | ||
132 | .ia = { 1, 0x000FFC00, 10 }, | ||
133 | .fm = { 1, 0x00700000, 20 }, | ||
134 | .pm = { 1, 0x00800000, 23 }, | ||
135 | .freq = { 1, 0x1F000000, 24 }, | ||
136 | .freq_clk_src = { 1, 0x60000000, 29 }, | ||
137 | }; | ||
138 | |||
139 | static const struct rpm_reg_parts rpm8960_switch_parts = { | ||
140 | .request_len = 1, | ||
141 | .enable_state = { 0, 0x00000001, 0 }, | ||
142 | .pd = { 0, 0x00000002, 1 }, | ||
143 | .pc = { 0, 0x0000003C, 2 }, | ||
144 | .pf = { 0, 0x000003C0, 6 }, | ||
145 | .hpm = { 0, 0x00000C00, 10 }, | ||
146 | }; | ||
147 | |||
148 | static const struct rpm_reg_parts rpm8960_ncp_parts = { | ||
149 | .request_len = 1, | ||
150 | .uV = { 0, 0x007FFFFF, 0 }, | ||
151 | .enable_state = { 0, 0x00800000, 23 }, | ||
152 | .comp_mode = { 0, 0x01000000, 24 }, | ||
153 | .freq = { 0, 0x3E000000, 25 }, | ||
154 | }; | ||
155 | |||
156 | /* | ||
157 | * Physically available PMIC regulator voltage ranges | ||
158 | */ | ||
159 | static const struct regulator_linear_range pldo_ranges[] = { | ||
160 | REGULATOR_LINEAR_RANGE( 750000, 0, 59, 12500), | ||
161 | REGULATOR_LINEAR_RANGE(1500000, 60, 123, 25000), | ||
162 | REGULATOR_LINEAR_RANGE(3100000, 124, 160, 50000), | ||
163 | }; | ||
164 | |||
165 | static const struct regulator_linear_range nldo_ranges[] = { | ||
166 | REGULATOR_LINEAR_RANGE( 750000, 0, 63, 12500), | ||
167 | }; | ||
168 | |||
169 | static const struct regulator_linear_range nldo1200_ranges[] = { | ||
170 | REGULATOR_LINEAR_RANGE( 375000, 0, 59, 6250), | ||
171 | REGULATOR_LINEAR_RANGE( 750000, 60, 123, 12500), | ||
172 | }; | ||
173 | |||
174 | static const struct regulator_linear_range smps_ranges[] = { | ||
175 | REGULATOR_LINEAR_RANGE( 375000, 0, 29, 12500), | ||
176 | REGULATOR_LINEAR_RANGE( 750000, 30, 89, 12500), | ||
177 | REGULATOR_LINEAR_RANGE(1500000, 90, 153, 25000), | ||
178 | }; | ||
179 | |||
180 | static const struct regulator_linear_range ftsmps_ranges[] = { | ||
181 | REGULATOR_LINEAR_RANGE( 350000, 0, 6, 50000), | ||
182 | REGULATOR_LINEAR_RANGE( 700000, 7, 63, 12500), | ||
183 | REGULATOR_LINEAR_RANGE(1500000, 64, 100, 50000), | ||
184 | }; | ||
185 | |||
186 | static const struct regulator_linear_range ncp_ranges[] = { | ||
187 | REGULATOR_LINEAR_RANGE(1500000, 0, 31, 50000), | ||
188 | }; | ||
189 | |||
190 | static int rpm_reg_write(struct qcom_rpm_reg *vreg, | ||
191 | const struct request_member *req, | ||
192 | const int value) | ||
193 | { | ||
194 | if (WARN_ON((value << req->shift) & ~req->mask)) | ||
195 | return -EINVAL; | ||
196 | |||
197 | vreg->val[req->word] &= ~req->mask; | ||
198 | vreg->val[req->word] |= value << req->shift; | ||
199 | |||
200 | return qcom_rpm_write(vreg->rpm, | ||
201 | vreg->resource, | ||
202 | vreg->val, | ||
203 | vreg->parts->request_len); | ||
204 | } | ||
205 | |||
206 | static int rpm_reg_set_mV_sel(struct regulator_dev *rdev, | ||
207 | unsigned selector) | ||
208 | { | ||
209 | struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); | ||
210 | const struct rpm_reg_parts *parts = vreg->parts; | ||
211 | const struct request_member *req = &parts->mV; | ||
212 | int ret = 0; | ||
213 | int uV; | ||
214 | |||
215 | if (req->mask == 0) | ||
216 | return -EINVAL; | ||
217 | |||
218 | uV = regulator_list_voltage_linear_range(rdev, selector); | ||
219 | if (uV < 0) | ||
220 | return uV; | ||
221 | |||
222 | mutex_lock(&vreg->lock); | ||
223 | vreg->uV = uV; | ||
224 | if (vreg->is_enabled) | ||
225 | ret = rpm_reg_write(vreg, req, vreg->uV / 1000); | ||
226 | mutex_unlock(&vreg->lock); | ||
227 | |||
228 | return ret; | ||
229 | } | ||
230 | |||
231 | static int rpm_reg_set_uV_sel(struct regulator_dev *rdev, | ||
232 | unsigned selector) | ||
233 | { | ||
234 | struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); | ||
235 | const struct rpm_reg_parts *parts = vreg->parts; | ||
236 | const struct request_member *req = &parts->uV; | ||
237 | int ret = 0; | ||
238 | int uV; | ||
239 | |||
240 | if (req->mask == 0) | ||
241 | return -EINVAL; | ||
242 | |||
243 | uV = regulator_list_voltage_linear_range(rdev, selector); | ||
244 | if (uV < 0) | ||
245 | return uV; | ||
246 | |||
247 | mutex_lock(&vreg->lock); | ||
248 | vreg->uV = uV; | ||
249 | if (vreg->is_enabled) | ||
250 | ret = rpm_reg_write(vreg, req, vreg->uV); | ||
251 | mutex_unlock(&vreg->lock); | ||
252 | |||
253 | return ret; | ||
254 | } | ||
255 | |||
256 | static int rpm_reg_get_voltage(struct regulator_dev *rdev) | ||
257 | { | ||
258 | struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); | ||
259 | |||
260 | return vreg->uV; | ||
261 | } | ||
262 | |||
263 | static int rpm_reg_mV_enable(struct regulator_dev *rdev) | ||
264 | { | ||
265 | struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); | ||
266 | const struct rpm_reg_parts *parts = vreg->parts; | ||
267 | const struct request_member *req = &parts->mV; | ||
268 | int ret; | ||
269 | |||
270 | if (req->mask == 0) | ||
271 | return -EINVAL; | ||
272 | |||
273 | mutex_lock(&vreg->lock); | ||
274 | ret = rpm_reg_write(vreg, req, vreg->uV / 1000); | ||
275 | if (!ret) | ||
276 | vreg->is_enabled = 1; | ||
277 | mutex_unlock(&vreg->lock); | ||
278 | |||
279 | return ret; | ||
280 | } | ||
281 | |||
282 | static int rpm_reg_uV_enable(struct regulator_dev *rdev) | ||
283 | { | ||
284 | struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); | ||
285 | const struct rpm_reg_parts *parts = vreg->parts; | ||
286 | const struct request_member *req = &parts->uV; | ||
287 | int ret; | ||
288 | |||
289 | if (req->mask == 0) | ||
290 | return -EINVAL; | ||
291 | |||
292 | mutex_lock(&vreg->lock); | ||
293 | ret = rpm_reg_write(vreg, req, vreg->uV); | ||
294 | if (!ret) | ||
295 | vreg->is_enabled = 1; | ||
296 | mutex_unlock(&vreg->lock); | ||
297 | |||
298 | return ret; | ||
299 | } | ||
300 | |||
301 | static int rpm_reg_switch_enable(struct regulator_dev *rdev) | ||
302 | { | ||
303 | struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); | ||
304 | const struct rpm_reg_parts *parts = vreg->parts; | ||
305 | const struct request_member *req = &parts->enable_state; | ||
306 | int ret; | ||
307 | |||
308 | if (req->mask == 0) | ||
309 | return -EINVAL; | ||
310 | |||
311 | mutex_lock(&vreg->lock); | ||
312 | ret = rpm_reg_write(vreg, req, 1); | ||
313 | if (!ret) | ||
314 | vreg->is_enabled = 1; | ||
315 | mutex_unlock(&vreg->lock); | ||
316 | |||
317 | return ret; | ||
318 | } | ||
319 | |||
320 | static int rpm_reg_mV_disable(struct regulator_dev *rdev) | ||
321 | { | ||
322 | struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); | ||
323 | const struct rpm_reg_parts *parts = vreg->parts; | ||
324 | const struct request_member *req = &parts->mV; | ||
325 | int ret; | ||
326 | |||
327 | if (req->mask == 0) | ||
328 | return -EINVAL; | ||
329 | |||
330 | mutex_lock(&vreg->lock); | ||
331 | ret = rpm_reg_write(vreg, req, 0); | ||
332 | if (!ret) | ||
333 | vreg->is_enabled = 0; | ||
334 | mutex_unlock(&vreg->lock); | ||
335 | |||
336 | return ret; | ||
337 | } | ||
338 | |||
339 | static int rpm_reg_uV_disable(struct regulator_dev *rdev) | ||
340 | { | ||
341 | struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); | ||
342 | const struct rpm_reg_parts *parts = vreg->parts; | ||
343 | const struct request_member *req = &parts->uV; | ||
344 | int ret; | ||
345 | |||
346 | if (req->mask == 0) | ||
347 | return -EINVAL; | ||
348 | |||
349 | mutex_lock(&vreg->lock); | ||
350 | ret = rpm_reg_write(vreg, req, 0); | ||
351 | if (!ret) | ||
352 | vreg->is_enabled = 0; | ||
353 | mutex_unlock(&vreg->lock); | ||
354 | |||
355 | return ret; | ||
356 | } | ||
357 | |||
358 | static int rpm_reg_switch_disable(struct regulator_dev *rdev) | ||
359 | { | ||
360 | struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); | ||
361 | const struct rpm_reg_parts *parts = vreg->parts; | ||
362 | const struct request_member *req = &parts->enable_state; | ||
363 | int ret; | ||
364 | |||
365 | if (req->mask == 0) | ||
366 | return -EINVAL; | ||
367 | |||
368 | mutex_lock(&vreg->lock); | ||
369 | ret = rpm_reg_write(vreg, req, 0); | ||
370 | if (!ret) | ||
371 | vreg->is_enabled = 0; | ||
372 | mutex_unlock(&vreg->lock); | ||
373 | |||
374 | return ret; | ||
375 | } | ||
376 | |||
377 | static int rpm_reg_is_enabled(struct regulator_dev *rdev) | ||
378 | { | ||
379 | struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev); | ||
380 | |||
381 | return vreg->is_enabled; | ||
382 | } | ||
383 | |||
384 | static struct regulator_ops uV_ops = { | ||
385 | .list_voltage = regulator_list_voltage_linear_range, | ||
386 | |||
387 | .set_voltage_sel = rpm_reg_set_uV_sel, | ||
388 | .get_voltage = rpm_reg_get_voltage, | ||
389 | |||
390 | .enable = rpm_reg_uV_enable, | ||
391 | .disable = rpm_reg_uV_disable, | ||
392 | .is_enabled = rpm_reg_is_enabled, | ||
393 | }; | ||
394 | |||
395 | static struct regulator_ops mV_ops = { | ||
396 | .list_voltage = regulator_list_voltage_linear_range, | ||
397 | |||
398 | .set_voltage_sel = rpm_reg_set_mV_sel, | ||
399 | .get_voltage = rpm_reg_get_voltage, | ||
400 | |||
401 | .enable = rpm_reg_mV_enable, | ||
402 | .disable = rpm_reg_mV_disable, | ||
403 | .is_enabled = rpm_reg_is_enabled, | ||
404 | }; | ||
405 | |||
406 | static struct regulator_ops switch_ops = { | ||
407 | .enable = rpm_reg_switch_enable, | ||
408 | .disable = rpm_reg_switch_disable, | ||
409 | .is_enabled = rpm_reg_is_enabled, | ||
410 | }; | ||
411 | |||
412 | /* | ||
413 | * PM8058 regulators | ||
414 | */ | ||
415 | static const struct qcom_rpm_reg pm8058_pldo = { | ||
416 | .desc.linear_ranges = pldo_ranges, | ||
417 | .desc.n_linear_ranges = ARRAY_SIZE(pldo_ranges), | ||
418 | .desc.n_voltages = 161, | ||
419 | .desc.ops = &mV_ops, | ||
420 | .parts = &rpm8660_ldo_parts, | ||
421 | .supports_force_mode_auto = false, | ||
422 | .supports_force_mode_bypass = false, | ||
423 | }; | ||
424 | |||
425 | static const struct qcom_rpm_reg pm8058_nldo = { | ||
426 | .desc.linear_ranges = nldo_ranges, | ||
427 | .desc.n_linear_ranges = ARRAY_SIZE(nldo_ranges), | ||
428 | .desc.n_voltages = 64, | ||
429 | .desc.ops = &mV_ops, | ||
430 | .parts = &rpm8660_ldo_parts, | ||
431 | .supports_force_mode_auto = false, | ||
432 | .supports_force_mode_bypass = false, | ||
433 | }; | ||
434 | |||
435 | static const struct qcom_rpm_reg pm8058_smps = { | ||
436 | .desc.linear_ranges = smps_ranges, | ||
437 | .desc.n_linear_ranges = ARRAY_SIZE(smps_ranges), | ||
438 | .desc.n_voltages = 154, | ||
439 | .desc.ops = &mV_ops, | ||
440 | .parts = &rpm8660_smps_parts, | ||
441 | .supports_force_mode_auto = false, | ||
442 | .supports_force_mode_bypass = false, | ||
443 | }; | ||
444 | |||
445 | static const struct qcom_rpm_reg pm8058_ncp = { | ||
446 | .desc.linear_ranges = ncp_ranges, | ||
447 | .desc.n_linear_ranges = ARRAY_SIZE(ncp_ranges), | ||
448 | .desc.n_voltages = 32, | ||
449 | .desc.ops = &mV_ops, | ||
450 | .parts = &rpm8660_ncp_parts, | ||
451 | }; | ||
452 | |||
453 | static const struct qcom_rpm_reg pm8058_switch = { | ||
454 | .desc.ops = &switch_ops, | ||
455 | .parts = &rpm8660_switch_parts, | ||
456 | }; | ||
457 | |||
458 | /* | ||
459 | * PM8901 regulators | ||
460 | */ | ||
461 | static const struct qcom_rpm_reg pm8901_pldo = { | ||
462 | .desc.linear_ranges = pldo_ranges, | ||
463 | .desc.n_linear_ranges = ARRAY_SIZE(pldo_ranges), | ||
464 | .desc.n_voltages = 161, | ||
465 | .desc.ops = &mV_ops, | ||
466 | .parts = &rpm8660_ldo_parts, | ||
467 | .supports_force_mode_auto = false, | ||
468 | .supports_force_mode_bypass = true, | ||
469 | }; | ||
470 | |||
471 | static const struct qcom_rpm_reg pm8901_nldo = { | ||
472 | .desc.linear_ranges = nldo_ranges, | ||
473 | .desc.n_linear_ranges = ARRAY_SIZE(nldo_ranges), | ||
474 | .desc.n_voltages = 64, | ||
475 | .desc.ops = &mV_ops, | ||
476 | .parts = &rpm8660_ldo_parts, | ||
477 | .supports_force_mode_auto = false, | ||
478 | .supports_force_mode_bypass = true, | ||
479 | }; | ||
480 | |||
481 | static const struct qcom_rpm_reg pm8901_ftsmps = { | ||
482 | .desc.linear_ranges = ftsmps_ranges, | ||
483 | .desc.n_linear_ranges = ARRAY_SIZE(ftsmps_ranges), | ||
484 | .desc.n_voltages = 101, | ||
485 | .desc.ops = &mV_ops, | ||
486 | .parts = &rpm8660_smps_parts, | ||
487 | .supports_force_mode_auto = true, | ||
488 | .supports_force_mode_bypass = false, | ||
489 | }; | ||
490 | |||
491 | static const struct qcom_rpm_reg pm8901_switch = { | ||
492 | .desc.ops = &switch_ops, | ||
493 | .parts = &rpm8660_switch_parts, | ||
494 | }; | ||
495 | |||
496 | /* | ||
497 | * PM8921 regulators | ||
498 | */ | ||
499 | static const struct qcom_rpm_reg pm8921_pldo = { | ||
500 | .desc.linear_ranges = pldo_ranges, | ||
501 | .desc.n_linear_ranges = ARRAY_SIZE(pldo_ranges), | ||
502 | .desc.n_voltages = 161, | ||
503 | .desc.ops = &uV_ops, | ||
504 | .parts = &rpm8960_ldo_parts, | ||
505 | .supports_force_mode_auto = false, | ||
506 | .supports_force_mode_bypass = true, | ||
507 | }; | ||
508 | |||
509 | static const struct qcom_rpm_reg pm8921_nldo = { | ||
510 | .desc.linear_ranges = nldo_ranges, | ||
511 | .desc.n_linear_ranges = ARRAY_SIZE(nldo_ranges), | ||
512 | .desc.n_voltages = 64, | ||
513 | .desc.ops = &uV_ops, | ||
514 | .parts = &rpm8960_ldo_parts, | ||
515 | .supports_force_mode_auto = false, | ||
516 | .supports_force_mode_bypass = true, | ||
517 | }; | ||
518 | |||
519 | static const struct qcom_rpm_reg pm8921_nldo1200 = { | ||
520 | .desc.linear_ranges = nldo1200_ranges, | ||
521 | .desc.n_linear_ranges = ARRAY_SIZE(nldo1200_ranges), | ||
522 | .desc.n_voltages = 124, | ||
523 | .desc.ops = &uV_ops, | ||
524 | .parts = &rpm8960_ldo_parts, | ||
525 | .supports_force_mode_auto = false, | ||
526 | .supports_force_mode_bypass = true, | ||
527 | }; | ||
528 | |||
529 | static const struct qcom_rpm_reg pm8921_smps = { | ||
530 | .desc.linear_ranges = smps_ranges, | ||
531 | .desc.n_linear_ranges = ARRAY_SIZE(smps_ranges), | ||
532 | .desc.n_voltages = 154, | ||
533 | .desc.ops = &uV_ops, | ||
534 | .parts = &rpm8960_smps_parts, | ||
535 | .supports_force_mode_auto = true, | ||
536 | .supports_force_mode_bypass = false, | ||
537 | }; | ||
538 | |||
539 | static const struct qcom_rpm_reg pm8921_ftsmps = { | ||
540 | .desc.linear_ranges = ftsmps_ranges, | ||
541 | .desc.n_linear_ranges = ARRAY_SIZE(ftsmps_ranges), | ||
542 | .desc.n_voltages = 101, | ||
543 | .desc.ops = &uV_ops, | ||
544 | .parts = &rpm8960_smps_parts, | ||
545 | .supports_force_mode_auto = true, | ||
546 | .supports_force_mode_bypass = false, | ||
547 | }; | ||
548 | |||
549 | static const struct qcom_rpm_reg pm8921_ncp = { | ||
550 | .desc.linear_ranges = ncp_ranges, | ||
551 | .desc.n_linear_ranges = ARRAY_SIZE(ncp_ranges), | ||
552 | .desc.n_voltages = 32, | ||
553 | .desc.ops = &uV_ops, | ||
554 | .parts = &rpm8960_ncp_parts, | ||
555 | }; | ||
556 | |||
557 | static const struct qcom_rpm_reg pm8921_switch = { | ||
558 | .desc.ops = &switch_ops, | ||
559 | .parts = &rpm8960_switch_parts, | ||
560 | }; | ||
561 | |||
562 | static const struct of_device_id rpm_of_match[] = { | ||
563 | { .compatible = "qcom,rpm-pm8058-pldo", .data = &pm8058_pldo }, | ||
564 | { .compatible = "qcom,rpm-pm8058-nldo", .data = &pm8058_nldo }, | ||
565 | { .compatible = "qcom,rpm-pm8058-smps", .data = &pm8058_smps }, | ||
566 | { .compatible = "qcom,rpm-pm8058-ncp", .data = &pm8058_ncp }, | ||
567 | { .compatible = "qcom,rpm-pm8058-switch", .data = &pm8058_switch }, | ||
568 | |||
569 | { .compatible = "qcom,rpm-pm8901-pldo", .data = &pm8901_pldo }, | ||
570 | { .compatible = "qcom,rpm-pm8901-nldo", .data = &pm8901_nldo }, | ||
571 | { .compatible = "qcom,rpm-pm8901-ftsmps", .data = &pm8901_ftsmps }, | ||
572 | { .compatible = "qcom,rpm-pm8901-switch", .data = &pm8901_switch }, | ||
573 | |||
574 | { .compatible = "qcom,rpm-pm8921-pldo", .data = &pm8921_pldo }, | ||
575 | { .compatible = "qcom,rpm-pm8921-nldo", .data = &pm8921_nldo }, | ||
576 | { .compatible = "qcom,rpm-pm8921-nldo1200", .data = &pm8921_nldo1200 }, | ||
577 | { .compatible = "qcom,rpm-pm8921-smps", .data = &pm8921_smps }, | ||
578 | { .compatible = "qcom,rpm-pm8921-ftsmps", .data = &pm8921_ftsmps }, | ||
579 | { .compatible = "qcom,rpm-pm8921-ncp", .data = &pm8921_ncp }, | ||
580 | { .compatible = "qcom,rpm-pm8921-switch", .data = &pm8921_switch }, | ||
581 | { } | ||
582 | }; | ||
583 | MODULE_DEVICE_TABLE(of, rpm_of_match); | ||
584 | |||
585 | static int rpm_reg_set(struct qcom_rpm_reg *vreg, | ||
586 | const struct request_member *req, | ||
587 | const int value) | ||
588 | { | ||
589 | if (req->mask == 0 || (value << req->shift) & ~req->mask) | ||
590 | return -EINVAL; | ||
591 | |||
592 | vreg->val[req->word] &= ~req->mask; | ||
593 | vreg->val[req->word] |= value << req->shift; | ||
594 | |||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | static int rpm_reg_of_parse_freq(struct device *dev, struct qcom_rpm_reg *vreg) | ||
599 | { | ||
600 | static const int freq_table[] = { | ||
601 | 19200000, 9600000, 6400000, 4800000, 3840000, 3200000, 2740000, | ||
602 | 2400000, 2130000, 1920000, 1750000, 1600000, 1480000, 1370000, | ||
603 | 1280000, 1200000, | ||
604 | |||
605 | }; | ||
606 | const char *key; | ||
607 | u32 freq; | ||
608 | int ret; | ||
609 | int i; | ||
610 | |||
611 | key = "qcom,switch-mode-frequency"; | ||
612 | ret = of_property_read_u32(dev->of_node, key, &freq); | ||
613 | if (ret) { | ||
614 | dev_err(dev, "regulator requires %s property\n", key); | ||
615 | return -EINVAL; | ||
616 | } | ||
617 | |||
618 | for (i = 0; i < ARRAY_SIZE(freq_table); i++) { | ||
619 | if (freq == freq_table[i]) { | ||
620 | rpm_reg_set(vreg, &vreg->parts->freq, i + 1); | ||
621 | return 0; | ||
622 | } | ||
623 | } | ||
624 | |||
625 | dev_err(dev, "invalid frequency %d\n", freq); | ||
626 | return -EINVAL; | ||
627 | } | ||
628 | |||
629 | static int rpm_reg_probe(struct platform_device *pdev) | ||
630 | { | ||
631 | struct regulator_init_data *initdata; | ||
632 | const struct qcom_rpm_reg *template; | ||
633 | const struct of_device_id *match; | ||
634 | struct regulator_config config = { }; | ||
635 | struct regulator_dev *rdev; | ||
636 | struct qcom_rpm_reg *vreg; | ||
637 | const char *key; | ||
638 | u32 force_mode; | ||
639 | bool pwm; | ||
640 | u32 val; | ||
641 | int ret; | ||
642 | |||
643 | match = of_match_device(rpm_of_match, &pdev->dev); | ||
644 | template = match->data; | ||
645 | |||
646 | initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node); | ||
647 | if (!initdata) | ||
648 | return -EINVAL; | ||
649 | |||
650 | vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL); | ||
651 | if (!vreg) { | ||
652 | dev_err(&pdev->dev, "failed to allocate vreg\n"); | ||
653 | return -ENOMEM; | ||
654 | } | ||
655 | memcpy(vreg, template, sizeof(*vreg)); | ||
656 | mutex_init(&vreg->lock); | ||
657 | vreg->dev = &pdev->dev; | ||
658 | vreg->desc.id = -1; | ||
659 | vreg->desc.owner = THIS_MODULE; | ||
660 | vreg->desc.type = REGULATOR_VOLTAGE; | ||
661 | vreg->desc.name = pdev->dev.of_node->name; | ||
662 | |||
663 | vreg->rpm = dev_get_drvdata(pdev->dev.parent); | ||
664 | if (!vreg->rpm) { | ||
665 | dev_err(&pdev->dev, "unable to retrieve handle to rpm\n"); | ||
666 | return -ENODEV; | ||
667 | } | ||
668 | |||
669 | key = "reg"; | ||
670 | ret = of_property_read_u32(pdev->dev.of_node, key, &val); | ||
671 | if (ret) { | ||
672 | dev_err(&pdev->dev, "failed to read %s\n", key); | ||
673 | return ret; | ||
674 | } | ||
675 | vreg->resource = val; | ||
676 | |||
677 | if ((vreg->parts->uV.mask || vreg->parts->mV.mask) && | ||
678 | (!initdata->constraints.min_uV || !initdata->constraints.max_uV)) { | ||
679 | dev_err(&pdev->dev, "no voltage specified for regulator\n"); | ||
680 | return -EINVAL; | ||
681 | } | ||
682 | |||
683 | key = "bias-pull-down"; | ||
684 | if (of_property_read_bool(pdev->dev.of_node, key)) { | ||
685 | ret = rpm_reg_set(vreg, &vreg->parts->pd, 1); | ||
686 | if (ret) { | ||
687 | dev_err(&pdev->dev, "%s is invalid", key); | ||
688 | return ret; | ||
689 | } | ||
690 | } | ||
691 | |||
692 | if (vreg->parts->freq.mask) { | ||
693 | ret = rpm_reg_of_parse_freq(&pdev->dev, vreg); | ||
694 | if (ret < 0) | ||
695 | return ret; | ||
696 | } | ||
697 | |||
698 | if (vreg->parts->pm.mask) { | ||
699 | key = "qcom,power-mode-hysteretic"; | ||
700 | pwm = !of_property_read_bool(pdev->dev.of_node, key); | ||
701 | |||
702 | ret = rpm_reg_set(vreg, &vreg->parts->pm, pwm); | ||
703 | if (ret) { | ||
704 | dev_err(&pdev->dev, "failed to set power mode\n"); | ||
705 | return ret; | ||
706 | } | ||
707 | } | ||
708 | |||
709 | if (vreg->parts->fm.mask) { | ||
710 | force_mode = -1; | ||
711 | |||
712 | key = "qcom,force-mode"; | ||
713 | ret = of_property_read_u32(pdev->dev.of_node, key, &val); | ||
714 | if (ret == -EINVAL) { | ||
715 | val = QCOM_RPM_FORCE_MODE_NONE; | ||
716 | } else if (ret < 0) { | ||
717 | dev_err(&pdev->dev, "failed to read %s\n", key); | ||
718 | return ret; | ||
719 | } | ||
720 | |||
721 | /* | ||
722 | * If force-mode is encoded as 2 bits then the | ||
723 | * possible register values are: | ||
724 | * NONE, LPM, HPM | ||
725 | * otherwise: | ||
726 | * NONE, LPM, AUTO, HPM, BYPASS | ||
727 | */ | ||
728 | switch (val) { | ||
729 | case QCOM_RPM_FORCE_MODE_NONE: | ||
730 | force_mode = 0; | ||
731 | break; | ||
732 | case QCOM_RPM_FORCE_MODE_LPM: | ||
733 | force_mode = 1; | ||
734 | break; | ||
735 | case QCOM_RPM_FORCE_MODE_HPM: | ||
736 | if (FORCE_MODE_IS_2_BITS(vreg)) | ||
737 | force_mode = 2; | ||
738 | else | ||
739 | force_mode = 3; | ||
740 | break; | ||
741 | case QCOM_RPM_FORCE_MODE_AUTO: | ||
742 | if (vreg->supports_force_mode_auto) | ||
743 | force_mode = 2; | ||
744 | break; | ||
745 | case QCOM_RPM_FORCE_MODE_BYPASS: | ||
746 | if (vreg->supports_force_mode_bypass) | ||
747 | force_mode = 4; | ||
748 | break; | ||
749 | } | ||
750 | |||
751 | if (force_mode < 0) { | ||
752 | dev_err(&pdev->dev, "invalid force mode\n"); | ||
753 | return -EINVAL; | ||
754 | } | ||
755 | |||
756 | ret = rpm_reg_set(vreg, &vreg->parts->fm, force_mode); | ||
757 | if (ret) { | ||
758 | dev_err(&pdev->dev, "failed to set force mode\n"); | ||
759 | return ret; | ||
760 | } | ||
761 | } | ||
762 | |||
763 | config.dev = &pdev->dev; | ||
764 | config.init_data = initdata; | ||
765 | config.driver_data = vreg; | ||
766 | config.of_node = pdev->dev.of_node; | ||
767 | rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config); | ||
768 | if (IS_ERR(rdev)) { | ||
769 | dev_err(&pdev->dev, "can't register regulator\n"); | ||
770 | return PTR_ERR(rdev); | ||
771 | } | ||
772 | |||
773 | return 0; | ||
774 | } | ||
775 | |||
776 | static struct platform_driver rpm_reg_driver = { | ||
777 | .probe = rpm_reg_probe, | ||
778 | .driver = { | ||
779 | .name = "qcom_rpm_reg", | ||
780 | .owner = THIS_MODULE, | ||
781 | .of_match_table = of_match_ptr(rpm_of_match), | ||
782 | }, | ||
783 | }; | ||
784 | |||
785 | static int __init rpm_reg_init(void) | ||
786 | { | ||
787 | return platform_driver_register(&rpm_reg_driver); | ||
788 | } | ||
789 | subsys_initcall(rpm_reg_init); | ||
790 | |||
791 | static void __exit rpm_reg_exit(void) | ||
792 | { | ||
793 | platform_driver_unregister(&rpm_reg_driver); | ||
794 | } | ||
795 | module_exit(rpm_reg_exit) | ||
796 | |||
797 | MODULE_DESCRIPTION("Qualcomm RPM regulator driver"); | ||
798 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/regulator/sky81452-regulator.c b/drivers/regulator/sky81452-regulator.c new file mode 100644 index 000000000000..97aff0ccd65f --- /dev/null +++ b/drivers/regulator/sky81452-regulator.c | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | * sky81452-regulator.c SKY81452 regulator driver | ||
3 | * | ||
4 | * Copyright 2014 Skyworks Solutions Inc. | ||
5 | * Author : Gyungoh Yoo <jack.yoo@skyworksinc.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2, or (at your option) any | ||
10 | * later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along | ||
18 | * with this program; if not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/err.h> | ||
26 | #include <linux/of.h> | ||
27 | #include <linux/regulator/driver.h> | ||
28 | #include <linux/regulator/of_regulator.h> | ||
29 | |||
30 | /* registers */ | ||
31 | #define SKY81452_REG1 0x01 | ||
32 | #define SKY81452_REG3 0x03 | ||
33 | |||
34 | /* bit mask */ | ||
35 | #define SKY81452_LEN 0x40 | ||
36 | #define SKY81452_LOUT 0x1F | ||
37 | |||
38 | static struct regulator_ops sky81452_reg_ops = { | ||
39 | .list_voltage = regulator_list_voltage_linear_range, | ||
40 | .map_voltage = regulator_map_voltage_linear_range, | ||
41 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
42 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
43 | .enable = regulator_enable_regmap, | ||
44 | .disable = regulator_disable_regmap, | ||
45 | .is_enabled = regulator_is_enabled_regmap, | ||
46 | }; | ||
47 | |||
48 | static const struct regulator_linear_range sky81452_reg_ranges[] = { | ||
49 | REGULATOR_LINEAR_RANGE(4500000, 0, 14, 250000), | ||
50 | REGULATOR_LINEAR_RANGE(9000000, 15, 31, 1000000), | ||
51 | }; | ||
52 | |||
53 | static const struct regulator_desc sky81452_reg = { | ||
54 | .name = "LOUT", | ||
55 | .ops = &sky81452_reg_ops, | ||
56 | .type = REGULATOR_VOLTAGE, | ||
57 | .owner = THIS_MODULE, | ||
58 | .n_voltages = SKY81452_LOUT + 1, | ||
59 | .linear_ranges = sky81452_reg_ranges, | ||
60 | .n_linear_ranges = ARRAY_SIZE(sky81452_reg_ranges), | ||
61 | .vsel_reg = SKY81452_REG3, | ||
62 | .vsel_mask = SKY81452_LOUT, | ||
63 | .enable_reg = SKY81452_REG1, | ||
64 | .enable_mask = SKY81452_LEN, | ||
65 | }; | ||
66 | |||
67 | #ifdef CONFIG_OF | ||
68 | static struct regulator_init_data *sky81452_reg_parse_dt(struct device *dev) | ||
69 | { | ||
70 | struct regulator_init_data *init_data; | ||
71 | struct device_node *np; | ||
72 | |||
73 | np = of_get_child_by_name(dev->parent->of_node, "regulator"); | ||
74 | if (unlikely(!np)) { | ||
75 | dev_err(dev, "regulator node not found"); | ||
76 | return NULL; | ||
77 | } | ||
78 | |||
79 | init_data = of_get_regulator_init_data(dev, np); | ||
80 | |||
81 | of_node_put(np); | ||
82 | return init_data; | ||
83 | } | ||
84 | #else | ||
85 | static struct regulator_init_data *sky81452_reg_parse_dt(struct device *dev) | ||
86 | { | ||
87 | return ERR_PTR(-EINVAL); | ||
88 | } | ||
89 | #endif | ||
90 | |||
91 | static int sky81452_reg_probe(struct platform_device *pdev) | ||
92 | { | ||
93 | struct device *dev = &pdev->dev; | ||
94 | const struct regulator_init_data *init_data = dev_get_platdata(dev); | ||
95 | struct regulator_config config = { }; | ||
96 | struct regulator_dev *rdev; | ||
97 | |||
98 | if (!init_data) { | ||
99 | init_data = sky81452_reg_parse_dt(dev); | ||
100 | if (IS_ERR(init_data)) | ||
101 | return PTR_ERR(init_data); | ||
102 | } | ||
103 | |||
104 | config.dev = dev; | ||
105 | config.init_data = init_data; | ||
106 | config.of_node = dev->of_node; | ||
107 | config.regmap = dev_get_drvdata(dev->parent); | ||
108 | |||
109 | rdev = devm_regulator_register(dev, &sky81452_reg, &config); | ||
110 | if (IS_ERR(rdev)) | ||
111 | return PTR_ERR(rdev); | ||
112 | |||
113 | platform_set_drvdata(pdev, rdev); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static struct platform_driver sky81452_reg_driver = { | ||
119 | .driver = { | ||
120 | .name = "sky81452-regulator", | ||
121 | }, | ||
122 | .probe = sky81452_reg_probe, | ||
123 | }; | ||
124 | |||
125 | module_platform_driver(sky81452_reg_driver); | ||
126 | |||
127 | MODULE_DESCRIPTION("Skyworks SKY81452 Regulator driver"); | ||
128 | MODULE_AUTHOR("Gyungoh Yoo <jack.yoo@skyworksinc.com>"); | ||
129 | MODULE_LICENSE("GPL"); | ||
130 | MODULE_VERSION("1.0"); | ||
diff --git a/drivers/regulator/st-pwm.c b/drivers/regulator/st-pwm.c deleted file mode 100644 index 5ea78df449f8..000000000000 --- a/drivers/regulator/st-pwm.c +++ /dev/null | |||
@@ -1,190 +0,0 @@ | |||
1 | /* | ||
2 | * Regulator driver for ST's PWM Regulators | ||
3 | * | ||
4 | * Copyright (C) 2014 - STMicroelectronics Inc. | ||
5 | * | ||
6 | * Author: Lee Jones <lee.jones@linaro.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/regulator/driver.h> | ||
17 | #include <linux/regulator/machine.h> | ||
18 | #include <linux/regulator/of_regulator.h> | ||
19 | #include <linux/of.h> | ||
20 | #include <linux/of_device.h> | ||
21 | #include <linux/pwm.h> | ||
22 | |||
23 | #define ST_PWM_REG_PERIOD 8448 | ||
24 | |||
25 | struct st_pwm_regulator_pdata { | ||
26 | const struct regulator_desc *desc; | ||
27 | struct st_pwm_voltages *duty_cycle_table; | ||
28 | }; | ||
29 | |||
30 | struct st_pwm_regulator_data { | ||
31 | const struct st_pwm_regulator_pdata *pdata; | ||
32 | struct pwm_device *pwm; | ||
33 | bool enabled; | ||
34 | int state; | ||
35 | }; | ||
36 | |||
37 | struct st_pwm_voltages { | ||
38 | unsigned int uV; | ||
39 | unsigned int dutycycle; | ||
40 | }; | ||
41 | |||
42 | static int st_pwm_regulator_get_voltage_sel(struct regulator_dev *dev) | ||
43 | { | ||
44 | struct st_pwm_regulator_data *drvdata = rdev_get_drvdata(dev); | ||
45 | |||
46 | return drvdata->state; | ||
47 | } | ||
48 | |||
49 | static int st_pwm_regulator_set_voltage_sel(struct regulator_dev *dev, | ||
50 | unsigned selector) | ||
51 | { | ||
52 | struct st_pwm_regulator_data *drvdata = rdev_get_drvdata(dev); | ||
53 | int dutycycle; | ||
54 | int ret; | ||
55 | |||
56 | dutycycle = (ST_PWM_REG_PERIOD / 100) * | ||
57 | drvdata->pdata->duty_cycle_table[selector].dutycycle; | ||
58 | |||
59 | ret = pwm_config(drvdata->pwm, dutycycle, ST_PWM_REG_PERIOD); | ||
60 | if (ret) { | ||
61 | dev_err(&dev->dev, "Failed to configure PWM\n"); | ||
62 | return ret; | ||
63 | } | ||
64 | |||
65 | drvdata->state = selector; | ||
66 | |||
67 | if (!drvdata->enabled) { | ||
68 | ret = pwm_enable(drvdata->pwm); | ||
69 | if (ret) { | ||
70 | dev_err(&dev->dev, "Failed to enable PWM\n"); | ||
71 | return ret; | ||
72 | } | ||
73 | drvdata->enabled = true; | ||
74 | } | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int st_pwm_regulator_list_voltage(struct regulator_dev *dev, | ||
80 | unsigned selector) | ||
81 | { | ||
82 | struct st_pwm_regulator_data *drvdata = rdev_get_drvdata(dev); | ||
83 | |||
84 | if (selector >= dev->desc->n_voltages) | ||
85 | return -EINVAL; | ||
86 | |||
87 | return drvdata->pdata->duty_cycle_table[selector].uV; | ||
88 | } | ||
89 | |||
90 | static struct regulator_ops st_pwm_regulator_voltage_ops = { | ||
91 | .set_voltage_sel = st_pwm_regulator_set_voltage_sel, | ||
92 | .get_voltage_sel = st_pwm_regulator_get_voltage_sel, | ||
93 | .list_voltage = st_pwm_regulator_list_voltage, | ||
94 | .map_voltage = regulator_map_voltage_iterate, | ||
95 | }; | ||
96 | |||
97 | static struct st_pwm_voltages b2105_duty_cycle_table[] = { | ||
98 | { .uV = 1114000, .dutycycle = 0, }, | ||
99 | { .uV = 1095000, .dutycycle = 10, }, | ||
100 | { .uV = 1076000, .dutycycle = 20, }, | ||
101 | { .uV = 1056000, .dutycycle = 30, }, | ||
102 | { .uV = 1036000, .dutycycle = 40, }, | ||
103 | { .uV = 1016000, .dutycycle = 50, }, | ||
104 | /* WARNING: Values above 50% duty-cycle cause boot failures. */ | ||
105 | }; | ||
106 | |||
107 | static const struct regulator_desc b2105_desc = { | ||
108 | .name = "b2105-pwm-regulator", | ||
109 | .ops = &st_pwm_regulator_voltage_ops, | ||
110 | .type = REGULATOR_VOLTAGE, | ||
111 | .owner = THIS_MODULE, | ||
112 | .n_voltages = ARRAY_SIZE(b2105_duty_cycle_table), | ||
113 | .supply_name = "pwm", | ||
114 | }; | ||
115 | |||
116 | static const struct st_pwm_regulator_pdata b2105_info = { | ||
117 | .desc = &b2105_desc, | ||
118 | .duty_cycle_table = b2105_duty_cycle_table, | ||
119 | }; | ||
120 | |||
121 | static const struct of_device_id st_pwm_of_match[] = { | ||
122 | { .compatible = "st,b2105-pwm-regulator", .data = &b2105_info, }, | ||
123 | { }, | ||
124 | }; | ||
125 | MODULE_DEVICE_TABLE(of, st_pwm_of_match); | ||
126 | |||
127 | static int st_pwm_regulator_probe(struct platform_device *pdev) | ||
128 | { | ||
129 | struct st_pwm_regulator_data *drvdata; | ||
130 | struct regulator_dev *regulator; | ||
131 | struct regulator_config config = { }; | ||
132 | struct device_node *np = pdev->dev.of_node; | ||
133 | const struct of_device_id *of_match; | ||
134 | |||
135 | if (!np) { | ||
136 | dev_err(&pdev->dev, "Device Tree node missing\n"); | ||
137 | return -EINVAL; | ||
138 | } | ||
139 | |||
140 | drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); | ||
141 | if (!drvdata) | ||
142 | return -ENOMEM; | ||
143 | |||
144 | of_match = of_match_device(st_pwm_of_match, &pdev->dev); | ||
145 | if (!of_match) { | ||
146 | dev_err(&pdev->dev, "failed to match of device\n"); | ||
147 | return -ENODEV; | ||
148 | } | ||
149 | drvdata->pdata = of_match->data; | ||
150 | |||
151 | config.init_data = of_get_regulator_init_data(&pdev->dev, np); | ||
152 | if (!config.init_data) | ||
153 | return -ENOMEM; | ||
154 | |||
155 | config.of_node = np; | ||
156 | config.dev = &pdev->dev; | ||
157 | config.driver_data = drvdata; | ||
158 | |||
159 | drvdata->pwm = devm_pwm_get(&pdev->dev, NULL); | ||
160 | if (IS_ERR(drvdata->pwm)) { | ||
161 | dev_err(&pdev->dev, "Failed to get PWM\n"); | ||
162 | return PTR_ERR(drvdata->pwm); | ||
163 | } | ||
164 | |||
165 | regulator = devm_regulator_register(&pdev->dev, | ||
166 | drvdata->pdata->desc, &config); | ||
167 | if (IS_ERR(regulator)) { | ||
168 | dev_err(&pdev->dev, "Failed to register regulator %s\n", | ||
169 | drvdata->pdata->desc->name); | ||
170 | return PTR_ERR(regulator); | ||
171 | } | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static struct platform_driver st_pwm_regulator_driver = { | ||
177 | .driver = { | ||
178 | .name = "st-pwm-regulator", | ||
179 | .owner = THIS_MODULE, | ||
180 | .of_match_table = of_match_ptr(st_pwm_of_match), | ||
181 | }, | ||
182 | .probe = st_pwm_regulator_probe, | ||
183 | }; | ||
184 | |||
185 | module_platform_driver(st_pwm_regulator_driver); | ||
186 | |||
187 | MODULE_LICENSE("GPL"); | ||
188 | MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>"); | ||
189 | MODULE_DESCRIPTION("ST PWM Regulator Driver"); | ||
190 | MODULE_ALIAS("platform:st_pwm-regulator"); | ||
diff --git a/include/linux/platform_data/isl9305.h b/include/linux/platform_data/isl9305.h new file mode 100644 index 000000000000..1419133fa69e --- /dev/null +++ b/include/linux/platform_data/isl9305.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * isl9305 - Intersil ISL9305 DCDC regulator | ||
3 | * | ||
4 | * Copyright 2014 Linaro Ltd | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@kernel.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #ifndef __ISL9305_H | ||
15 | #define __ISL9305_H | ||
16 | |||
17 | #define ISL9305_DCD1 0 | ||
18 | #define ISL9305_DCD2 1 | ||
19 | #define ISL9305_LDO1 2 | ||
20 | #define ISL9305_LDO2 3 | ||
21 | |||
22 | #define ISL9305_MAX_REGULATOR ISL9305_LDO2 | ||
23 | |||
24 | struct regulator_init_data; | ||
25 | |||
26 | struct isl9305_pdata { | ||
27 | struct regulator_init_data *init_data[ISL9305_MAX_REGULATOR]; | ||
28 | }; | ||
29 | |||
30 | #endif | ||
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index 4efa1ed8a2b0..fc0ee0ce8325 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h | |||
@@ -203,6 +203,8 @@ enum regulator_type { | |||
203 | * | 203 | * |
204 | * @name: Identifying name for the regulator. | 204 | * @name: Identifying name for the regulator. |
205 | * @supply_name: Identifying the regulator supply | 205 | * @supply_name: Identifying the regulator supply |
206 | * @of_match: Name used to identify regulator in DT. | ||
207 | * @regulators_node: Name of node containing regulator definitions in DT. | ||
206 | * @id: Numerical identifier for the regulator. | 208 | * @id: Numerical identifier for the regulator. |
207 | * @ops: Regulator operations table. | 209 | * @ops: Regulator operations table. |
208 | * @irq: Interrupt number for the regulator. | 210 | * @irq: Interrupt number for the regulator. |
@@ -240,14 +242,17 @@ enum regulator_type { | |||
240 | * @bypass_val_off: Disabling value for control when using regmap set_bypass | 242 | * @bypass_val_off: Disabling value for control when using regmap set_bypass |
241 | * | 243 | * |
242 | * @enable_time: Time taken for initial enable of regulator (in uS). | 244 | * @enable_time: Time taken for initial enable of regulator (in uS). |
245 | * @off_on_delay: guard time (in uS), before re-enabling a regulator | ||
243 | */ | 246 | */ |
244 | struct regulator_desc { | 247 | struct regulator_desc { |
245 | const char *name; | 248 | const char *name; |
246 | const char *supply_name; | 249 | const char *supply_name; |
250 | const char *of_match; | ||
251 | const char *regulators_node; | ||
247 | int id; | 252 | int id; |
248 | bool continuous_voltage_range; | 253 | bool continuous_voltage_range; |
249 | unsigned n_voltages; | 254 | unsigned n_voltages; |
250 | struct regulator_ops *ops; | 255 | const struct regulator_ops *ops; |
251 | int irq; | 256 | int irq; |
252 | enum regulator_type type; | 257 | enum regulator_type type; |
253 | struct module *owner; | 258 | struct module *owner; |
@@ -278,6 +283,8 @@ struct regulator_desc { | |||
278 | unsigned int bypass_val_off; | 283 | unsigned int bypass_val_off; |
279 | 284 | ||
280 | unsigned int enable_time; | 285 | unsigned int enable_time; |
286 | |||
287 | unsigned int off_on_delay; | ||
281 | }; | 288 | }; |
282 | 289 | ||
283 | /** | 290 | /** |
@@ -350,6 +357,9 @@ struct regulator_dev { | |||
350 | 357 | ||
351 | struct regulator_enable_gpio *ena_pin; | 358 | struct regulator_enable_gpio *ena_pin; |
352 | unsigned int ena_gpio_state:1; | 359 | unsigned int ena_gpio_state:1; |
360 | |||
361 | /* time when this regulator was disabled last time */ | ||
362 | unsigned long last_off_jiffy; | ||
353 | }; | 363 | }; |
354 | 364 | ||
355 | struct regulator_dev * | 365 | struct regulator_dev * |