1 /*
2 * Copyright (C) 2020 allwinnertech Ltd.
3 */
4
5 #include <ffs.h>
6 #include <log.h>
7 #include <stddef.h>
8 #include <sunxi_hal_regulator.h>
9 #include <sunxi_hal_regulator_private.h>
10
voltage2val(struct regulator_desc * info,int voltage,u8 * reg_val)11 static int voltage2val(struct regulator_desc *info, int voltage, u8 *reg_val)
12 {
13 const struct regulator_linear_range *range;
14 int i;
15
16 if (!info->linear_ranges) {
17 *reg_val = (voltage - info->min_uv + info->step1_uv - 1)
18 / info->step1_uv;
19 return 0;
20 }
21
22 for (i = 0; i < info->n_linear_ranges; i++) {
23 int linear_max_uV;
24
25 range = &info->linear_ranges[i];
26 linear_max_uV = range->min_uV +
27 (range->max_sel - range->min_sel) * range->uV_step;
28
29 if (!(voltage <= linear_max_uV && voltage >= range->min_uV))
30 continue;
31
32 /* range->uV_step == 0 means fixed voltage range */
33 if (range->uV_step == 0) {
34 *reg_val = 0;
35 } else {
36 *reg_val = (voltage - range->min_uV) / range->uV_step;
37 }
38
39 *reg_val += range->min_sel;
40 return 0;
41 }
42
43 return -1;
44 }
45
val2voltage(struct regulator_desc * info,u8 reg_val,int * voltage)46 static int val2voltage(struct regulator_desc *info, u8 reg_val, int *voltage)
47 {
48 const struct regulator_linear_range *range = info->linear_ranges;
49 int i;
50
51 if (!info->linear_ranges) {
52 *voltage = info->min_uv + info->step1_uv * reg_val;
53 return 0;
54 }
55
56 for (i = 0; i < info->n_linear_ranges; i++, range++) {
57 if (!(reg_val <= range->max_sel && reg_val >= range->min_sel))
58 continue;
59
60 *voltage = (reg_val - range->min_sel) * range->uV_step +
61 range->min_uV;
62 return 0;
63 }
64
65 return -1;
66 }
67
axp_regulator_set_voltage(struct regulator_dev * rdev,int target_uV)68 static int axp_regulator_set_voltage(struct regulator_dev *rdev, int target_uV)
69 {
70 unsigned char id = REGULATOR_ID(rdev->flag);
71 struct regulator_desc *pd = (struct regulator_desc *)rdev->private;
72 struct regulator_desc *info = &pd[id];
73 u8 val;
74
75 if (voltage2val(info, target_uV, &val))
76 return -1;
77
78 val <<= ffs(info->vol_mask) - 1;
79 return hal_axp_byte_update(rdev, info->vol_reg, val, info->vol_mask);
80 }
81
axp_regulator_get_voltage(struct regulator_dev * rdev,int * vol_uV)82 static int axp_regulator_get_voltage(struct regulator_dev *rdev, int *vol_uV)
83 {
84 unsigned char id = REGULATOR_ID(rdev->flag);
85 struct regulator_desc *pd = (struct regulator_desc *)rdev->private;
86 struct regulator_desc *info = &pd[id];
87 u8 val;
88 int ret;
89
90 ret = hal_axp_byte_read(rdev, info->vol_reg, &val);
91 if (ret)
92 return ret;
93
94 val &= info->vol_mask;
95 val >>= ffs(info->vol_mask) - 1;
96 if (val2voltage(info, val, vol_uV))
97 return -1;
98
99 return 0;
100 }
101
axp_regulator_enable(struct regulator_dev * rdev)102 static int axp_regulator_enable(struct regulator_dev *rdev)
103 {
104 unsigned char id = REGULATOR_ID(rdev->flag);
105 struct regulator_desc *pd = (struct regulator_desc *)rdev->private;
106 struct regulator_desc *info = &pd[id];
107 u8 reg_val = 0;
108
109 reg_val = info->enable_val;
110 if (!reg_val)
111 reg_val = info->enable_mask;
112
113 return hal_axp_byte_update(rdev, info->enable_reg,
114 reg_val, info->enable_mask);
115 }
116
axp_regulator_disable(struct regulator_dev * rdev)117 static int axp_regulator_disable(struct regulator_dev *rdev)
118 {
119 unsigned char id = REGULATOR_ID(rdev->flag);
120 struct regulator_desc *pd = (struct regulator_desc *)rdev->private;
121 struct regulator_desc *info = &pd[id];
122 u8 reg_val = 0;
123
124 reg_val = info->disable_val;
125 if (!reg_val)
126 reg_val = ~info->enable_mask;
127
128 return hal_axp_byte_update(rdev, info->enable_reg,
129 reg_val, info->enable_mask);
130 }
131
132 struct regulator_ops axp_regulator_ops = {
133 .set_voltage = axp_regulator_set_voltage,
134 .get_voltage = axp_regulator_get_voltage,
135 .enable = axp_regulator_enable,
136 .disable = axp_regulator_disable,
137 };
138