aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorGraeme Gregory <gg@slimlogic.co.uk>2011-05-22 16:21:23 -0400
committerLiam Girdwood <lrg@slimlogic.co.uk>2011-05-27 05:49:29 -0400
commit4d94aee577ea8179bd40f0f17e64cada25c66b85 (patch)
tree42516842d77fcb874516e4e8f717090ef854d009 /drivers
parent0ff3897d79d4607d37432b3eb81a304f7e4b4841 (diff)
REGULATOR: TWL6025: add support to twl-regulator
Adding support for the twl6025. Major difference in the twl6025 is the group functionality has been removed from the chip so this affects how regulators are enabled and disabled. The names of the regulators also changed. The DCDCs of the 6025 are software controllable as well. Since V1 Use the features variable passed via platform data instead of calling global function. Change the very switch like if statements to be a more readable switch statement. Since V2 twl6025 doesn't use remap so remove it from the macros. Since V3 enable/disable functions for 4030/6030 were seperated upstream so rebase on top of this. Change DCDC reference to SMPS as this is used in TRM. Change list_voltage slightly to have less code. Signed-off-by: Graeme Gregory <gg@slimlogic.co.uk> Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/regulator/twl-regulator.c329
1 files changed, 321 insertions, 8 deletions
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 4702b8a7e0ef..87fe0f75a56e 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -51,8 +51,13 @@ struct twlreg_info {
51 u16 min_mV; 51 u16 min_mV;
52 u16 max_mV; 52 u16 max_mV;
53 53
54 u8 flags;
55
54 /* used by regulator core */ 56 /* used by regulator core */
55 struct regulator_desc desc; 57 struct regulator_desc desc;
58
59 /* chip specific features */
60 unsigned long features;
56}; 61};
57 62
58 63
@@ -70,6 +75,7 @@ struct twlreg_info {
70#define VREG_TRANS 1 75#define VREG_TRANS 1
71#define VREG_STATE 2 76#define VREG_STATE 2
72#define VREG_VOLTAGE 3 77#define VREG_VOLTAGE 3
78#define VREG_VOLTAGE_SMPS 4
73/* TWL6030 Misc register offsets */ 79/* TWL6030 Misc register offsets */
74#define VREG_BC_ALL 1 80#define VREG_BC_ALL 1
75#define VREG_BC_REF 2 81#define VREG_BC_REF 2
@@ -87,6 +93,17 @@ struct twlreg_info {
87#define TWL6030_CFG_STATE_APP(v) (((v) & TWL6030_CFG_STATE_APP_MASK) >>\ 93#define TWL6030_CFG_STATE_APP(v) (((v) & TWL6030_CFG_STATE_APP_MASK) >>\
88 TWL6030_CFG_STATE_APP_SHIFT) 94 TWL6030_CFG_STATE_APP_SHIFT)
89 95
96/* Flags for SMPS Voltage reading */
97#define SMPS_OFFSET_EN BIT(0)
98#define SMPS_EXTENDED_EN BIT(1)
99
100/* twl6025 SMPS EPROM values */
101#define TWL6030_SMPS_OFFSET 0xB0
102#define TWL6030_SMPS_MULT 0xB3
103#define SMPS_MULTOFFSET_SMPS4 BIT(0)
104#define SMPS_MULTOFFSET_VIO BIT(1)
105#define SMPS_MULTOFFSET_SMPS3 BIT(6)
106
90static inline int 107static inline int
91twlreg_read(struct twlreg_info *info, unsigned slave_subgp, unsigned offset) 108twlreg_read(struct twlreg_info *info, unsigned slave_subgp, unsigned offset)
92{ 109{
@@ -142,13 +159,17 @@ static int twl4030reg_is_enabled(struct regulator_dev *rdev)
142static int twl6030reg_is_enabled(struct regulator_dev *rdev) 159static int twl6030reg_is_enabled(struct regulator_dev *rdev)
143{ 160{
144 struct twlreg_info *info = rdev_get_drvdata(rdev); 161 struct twlreg_info *info = rdev_get_drvdata(rdev);
145 int grp, val; 162 int grp = 0, val;
146 163
147 grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); 164 if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
165 grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
148 if (grp < 0) 166 if (grp < 0)
149 return grp; 167 return grp;
150 168
151 grp &= P1_GRP_6030; 169 if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
170 grp &= P1_GRP_6030;
171 else
172 grp = 1;
152 173
153 val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE); 174 val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
154 val = TWL6030_CFG_STATE_APP(val); 175 val = TWL6030_CFG_STATE_APP(val);
@@ -178,10 +199,11 @@ static int twl4030reg_enable(struct regulator_dev *rdev)
178static int twl6030reg_enable(struct regulator_dev *rdev) 199static int twl6030reg_enable(struct regulator_dev *rdev)
179{ 200{
180 struct twlreg_info *info = rdev_get_drvdata(rdev); 201 struct twlreg_info *info = rdev_get_drvdata(rdev);
181 int grp; 202 int grp = 0;
182 int ret; 203 int ret;
183 204
184 grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); 205 if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
206 grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
185 if (grp < 0) 207 if (grp < 0)
186 return grp; 208 return grp;
187 209
@@ -217,7 +239,8 @@ static int twl6030reg_disable(struct regulator_dev *rdev)
217 int grp = 0; 239 int grp = 0;
218 int ret; 240 int ret;
219 241
220 grp = P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030; 242 if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
243 grp = P1_GRP_6030 | P2_GRP_6030 | P3_GRP_6030;
221 244
222 /* For 6030, set the off state for all grps enabled */ 245 /* For 6030, set the off state for all grps enabled */
223 ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE, 246 ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE,
@@ -307,10 +330,11 @@ static int twl4030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
307static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode) 330static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
308{ 331{
309 struct twlreg_info *info = rdev_get_drvdata(rdev); 332 struct twlreg_info *info = rdev_get_drvdata(rdev);
310 int grp; 333 int grp = 0;
311 int val; 334 int val;
312 335
313 grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP); 336 if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
337 grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
314 338
315 if (grp < 0) 339 if (grp < 0)
316 return grp; 340 return grp;
@@ -602,6 +626,209 @@ static struct regulator_ops twl6030_fixed_resource = {
602 .get_status = twl6030reg_get_status, 626 .get_status = twl6030reg_get_status,
603}; 627};
604 628
629/*
630 * SMPS status and control
631 */
632
633static int twl6030smps_list_voltage(struct regulator_dev *rdev, unsigned index)
634{
635 struct twlreg_info *info = rdev_get_drvdata(rdev);
636
637 int voltage = 0;
638
639 switch (info->flags) {
640 case SMPS_OFFSET_EN:
641 voltage = 100000;
642 /* fall through */
643 case 0:
644 switch (index) {
645 case 0:
646 voltage = 0;
647 break;
648 case 58:
649 voltage = 1350 * 1000;
650 break;
651 case 59:
652 voltage = 1500 * 1000;
653 break;
654 case 60:
655 voltage = 1800 * 1000;
656 break;
657 case 61:
658 voltage = 1900 * 1000;
659 break;
660 case 62:
661 voltage = 2100 * 1000;
662 break;
663 default:
664 voltage += (600000 + (12500 * (index - 1)));
665 }
666 break;
667 case SMPS_EXTENDED_EN:
668 switch (index) {
669 case 0:
670 voltage = 0;
671 break;
672 case 58:
673 voltage = 2084 * 1000;
674 break;
675 case 59:
676 voltage = 2315 * 1000;
677 break;
678 case 60:
679 voltage = 2778 * 1000;
680 break;
681 case 61:
682 voltage = 2932 * 1000;
683 break;
684 case 62:
685 voltage = 3241 * 1000;
686 break;
687 default:
688 voltage = (1852000 + (38600 * (index - 1)));
689 }
690 break;
691 case SMPS_OFFSET_EN | SMPS_EXTENDED_EN:
692 switch (index) {
693 case 0:
694 voltage = 0;
695 break;
696 case 58:
697 voltage = 4167 * 1000;
698 break;
699 case 59:
700 voltage = 2315 * 1000;
701 break;
702 case 60:
703 voltage = 2778 * 1000;
704 break;
705 case 61:
706 voltage = 2932 * 1000;
707 break;
708 case 62:
709 voltage = 3241 * 1000;
710 break;
711 default:
712 voltage = (2161000 + (38600 * (index - 1)));
713 }
714 break;
715 }
716
717 return voltage;
718}
719
720static int
721twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
722 unsigned int *selector)
723{
724 struct twlreg_info *info = rdev_get_drvdata(rdev);
725 int vsel = 0;
726
727 switch (info->flags) {
728 case 0:
729 if (min_uV == 0)
730 vsel = 0;
731 else if ((min_uV >= 600000) && (max_uV <= 1300000)) {
732 vsel = (min_uV - 600000) / 125;
733 if (vsel % 100)
734 vsel += 100;
735 vsel /= 100;
736 vsel++;
737 }
738 /* Values 1..57 for vsel are linear and can be calculated
739 * values 58..62 are non linear.
740 */
741 else if ((min_uV > 1900000) && (max_uV >= 2100000))
742 vsel = 62;
743 else if ((min_uV > 1800000) && (max_uV >= 1900000))
744 vsel = 61;
745 else if ((min_uV > 1500000) && (max_uV >= 1800000))
746 vsel = 60;
747 else if ((min_uV > 1350000) && (max_uV >= 1500000))
748 vsel = 59;
749 else if ((min_uV > 1300000) && (max_uV >= 1350000))
750 vsel = 58;
751 else
752 return -EINVAL;
753 break;
754 case SMPS_OFFSET_EN:
755 if (min_uV == 0)
756 vsel = 0;
757 else if ((min_uV >= 700000) && (max_uV <= 1420000)) {
758 vsel = (min_uV - 700000) / 125;
759 if (vsel % 100)
760 vsel += 100;
761 vsel /= 100;
762 vsel++;
763 }
764 /* Values 1..57 for vsel are linear and can be calculated
765 * values 58..62 are non linear.
766 */
767 else if ((min_uV > 1900000) && (max_uV >= 2100000))
768 vsel = 62;
769 else if ((min_uV > 1800000) && (max_uV >= 1900000))
770 vsel = 61;
771 else if ((min_uV > 1350000) && (max_uV >= 1800000))
772 vsel = 60;
773 else if ((min_uV > 1350000) && (max_uV >= 1500000))
774 vsel = 59;
775 else if ((min_uV > 1300000) && (max_uV >= 1350000))
776 vsel = 58;
777 else
778 return -EINVAL;
779 break;
780 case SMPS_EXTENDED_EN:
781 if (min_uV == 0)
782 vsel = 0;
783 else if ((min_uV >= 1852000) && (max_uV <= 4013600)) {
784 vsel = (min_uV - 1852000) / 386;
785 if (vsel % 100)
786 vsel += 100;
787 vsel /= 100;
788 vsel++;
789 }
790 break;
791 case SMPS_OFFSET_EN|SMPS_EXTENDED_EN:
792 if (min_uV == 0)
793 vsel = 0;
794 else if ((min_uV >= 2161000) && (max_uV <= 4321000)) {
795 vsel = (min_uV - 1852000) / 386;
796 if (vsel % 100)
797 vsel += 100;
798 vsel /= 100;
799 vsel++;
800 }
801 break;
802 }
803
804 *selector = vsel;
805
806 return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS,
807 vsel);
808}
809
810static int twl6030smps_get_voltage_sel(struct regulator_dev *rdev)
811{
812 struct twlreg_info *info = rdev_get_drvdata(rdev);
813
814 return twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS);
815}
816
817static struct regulator_ops twlsmps_ops = {
818 .list_voltage = twl6030smps_list_voltage,
819
820 .set_voltage = twl6030smps_set_voltage,
821 .get_voltage_sel = twl6030smps_get_voltage_sel,
822
823 .enable = twl6030reg_enable,
824 .disable = twl6030reg_disable,
825 .is_enabled = twl6030reg_is_enabled,
826
827 .set_mode = twl6030reg_set_mode,
828
829 .get_status = twl6030reg_get_status,
830};
831
605/*----------------------------------------------------------------------*/ 832/*----------------------------------------------------------------------*/
606 833
607#define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \ 834#define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
@@ -644,6 +871,20 @@ static struct regulator_ops twl6030_fixed_resource = {
644 }, \ 871 }, \
645 } 872 }
646 873
874#define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num) { \
875 .base = offset, \
876 .id = num, \
877 .min_mV = min_mVolts, \
878 .max_mV = max_mVolts, \
879 .desc = { \
880 .name = #label, \
881 .id = TWL6025_REG_##label, \
882 .n_voltages = ((max_mVolts - min_mVolts)/100) + 1, \
883 .ops = &twl6030ldo_ops, \
884 .type = REGULATOR_VOLTAGE, \
885 .owner = THIS_MODULE, \
886 }, \
887 }
647 888
648#define TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, remap_conf, \ 889#define TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, remap_conf, \
649 family, operations) { \ 890 family, operations) { \
@@ -675,6 +916,21 @@ static struct regulator_ops twl6030_fixed_resource = {
675 }, \ 916 }, \
676 } 917 }
677 918
919#define TWL6025_ADJUSTABLE_SMPS(label, offset, num) { \
920 .base = offset, \
921 .id = num, \
922 .min_mV = 600, \
923 .max_mV = 2100, \
924 .desc = { \
925 .name = #label, \
926 .id = TWL6025_REG_##label, \
927 .n_voltages = 63, \
928 .ops = &twlsmps_ops, \
929 .type = REGULATOR_VOLTAGE, \
930 .owner = THIS_MODULE, \
931 }, \
932 }
933
678/* 934/*
679 * We list regulators here if systems need some level of 935 * We list regulators here if systems need some level of
680 * software control over them after boot. 936 * software control over them after boot.
@@ -716,8 +972,41 @@ static struct twlreg_info twl_regs[] = {
716 TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0), 972 TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0),
717 TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0), 973 TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0),
718 TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 48, 0), 974 TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 48, 0),
975
976 /* 6025 are renamed compared to 6030 versions */
977 TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300, 1),
978 TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300, 2),
979 TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300, 3),
980 TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300, 4),
981 TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300, 5),
982 TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300, 7),
983 TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300, 16),
984 TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300, 17),
985 TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300, 18),
986
987 TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34, 1),
988 TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10, 2),
989 TWL6025_ADJUSTABLE_SMPS(VIO, 0x16, 3),
719}; 990};
720 991
992static u8 twl_get_smps_offset(void)
993{
994 u8 value;
995
996 twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &value,
997 TWL6030_SMPS_OFFSET);
998 return value;
999}
1000
1001static u8 twl_get_smps_mult(void)
1002{
1003 u8 value;
1004
1005 twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &value,
1006 TWL6030_SMPS_MULT);
1007 return value;
1008}
1009
721static int __devinit twlreg_probe(struct platform_device *pdev) 1010static int __devinit twlreg_probe(struct platform_device *pdev)
722{ 1011{
723 int i; 1012 int i;
@@ -739,6 +1028,9 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
739 if (!initdata) 1028 if (!initdata)
740 return -EINVAL; 1029 return -EINVAL;
741 1030
1031 /* copy the features into regulator data */
1032 info->features = (unsigned long)initdata->driver_data;
1033
742 /* Constrain board-specific capabilities according to what 1034 /* Constrain board-specific capabilities according to what
743 * this driver and the chip itself can actually do. 1035 * this driver and the chip itself can actually do.
744 */ 1036 */
@@ -761,6 +1053,27 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
761 break; 1053 break;
762 } 1054 }
763 1055
1056 switch (pdev->id) {
1057 case TWL6025_REG_SMPS3:
1058 if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS3)
1059 info->flags |= SMPS_EXTENDED_EN;
1060 if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS3)
1061 info->flags |= SMPS_OFFSET_EN;
1062 break;
1063 case TWL6025_REG_SMPS4:
1064 if (twl_get_smps_mult() & SMPS_MULTOFFSET_SMPS4)
1065 info->flags |= SMPS_EXTENDED_EN;
1066 if (twl_get_smps_offset() & SMPS_MULTOFFSET_SMPS4)
1067 info->flags |= SMPS_OFFSET_EN;
1068 break;
1069 case TWL6025_REG_VIO:
1070 if (twl_get_smps_mult() & SMPS_MULTOFFSET_VIO)
1071 info->flags |= SMPS_EXTENDED_EN;
1072 if (twl_get_smps_offset() & SMPS_MULTOFFSET_VIO)
1073 info->flags |= SMPS_OFFSET_EN;
1074 break;
1075 }
1076
764 rdev = regulator_register(&info->desc, &pdev->dev, initdata, info); 1077 rdev = regulator_register(&info->desc, &pdev->dev, initdata, info);
765 if (IS_ERR(rdev)) { 1078 if (IS_ERR(rdev)) {
766 dev_err(&pdev->dev, "can't register %s, %ld\n", 1079 dev_err(&pdev->dev, "can't register %s, %ld\n",