1 /*
2 * Copyright (C) 2022 Unionman Technology Co., Ltd.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
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 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include <linux/init.h>
20 #include <linux/module.h>
21 #include <linux/power_supply.h>
22
23 struct ac_data {
24 struct power_supply_desc psd;
25 struct power_supply *psy;
26 };
27
28 struct battery_data {
29 struct power_supply_desc psd;
30 struct power_supply *psy;
31 };
32
33 static enum power_supply_property ac_props[] = {
34 POWER_SUPPLY_PROP_ONLINE,
35 };
36
37 static enum power_supply_property battery_props[] = {
38 POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_PRESENT,
39 POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_CHARGE_COUNTER, POWER_SUPPLY_PROP_CHARGE_NOW,
40 POWER_SUPPLY_PROP_CHARGE_FULL, POWER_SUPPLY_PROP_CURRENT_AVG, POWER_SUPPLY_PROP_CURRENT_NOW,
41 POWER_SUPPLY_PROP_CURRENT_MAX, POWER_SUPPLY_PROP_VOLTAGE_MAX, POWER_SUPPLY_PROP_VOLTAGE_NOW,
42 POWER_SUPPLY_PROP_VOLTAGE_AVG, POWER_SUPPLY_PROP_TECHNOLOGY, POWER_SUPPLY_PROP_TEMP,
43 POWER_SUPPLY_PROP_TEMP_MIN, POWER_SUPPLY_PROP_TEMP_MAX,
44 };
45
ac_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)46 static int ac_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val)
47 {
48 int ret = 0;
49
50 switch (psp) {
51 case POWER_SUPPLY_PROP_ONLINE:
52 val->intval = 1;
53 break;
54 default:
55 ret = -EINVAL;
56 break;
57 }
58
59 return ret;
60 }
61
battery_get_property(struct power_supply * psy,enum power_supply_property psp,union power_supply_propval * val)62 static int battery_get_property(struct power_supply *psy, enum power_supply_property psp,
63 union power_supply_propval *val)
64 {
65 int ret = 0;
66
67 if (psp == POWER_SUPPLY_PROP_STATUS) {
68 val->intval = POWER_SUPPLY_STATUS_CHARGING;
69 } else if (psp == POWER_SUPPLY_PROP_HEALTH) {
70 val->intval = POWER_SUPPLY_HEALTH_GOOD;
71 } else if (psp == POWER_SUPPLY_PROP_PRESENT) {
72 val->intval = 0;
73 } else if (psp == POWER_SUPPLY_PROP_CAPACITY) {
74 val->intval = 100L;
75 } else if ((psp == POWER_SUPPLY_PROP_CHARGE_COUNTER) || (psp == POWER_SUPPLY_PROP_CHARGE_FULL)) {
76 val->intval = 3000L * 1000L;
77 } else if (psp == POWER_SUPPLY_PROP_CHARGE_NOW) {
78 val->intval = 3000L * 1000L;
79 } else if ((psp == POWER_SUPPLY_PROP_VOLTAGE_NOW) || (psp == POWER_SUPPLY_PROP_VOLTAGE_AVG)) {
80 val->intval = 4200L * 1000L;
81 } else if (psp == POWER_SUPPLY_PROP_TEMP) {
82 val->intval = 25L;
83 } else if (psp == POWER_SUPPLY_PROP_TEMP_MIN) {
84 val->intval = -40L;
85 } else if (psp == POWER_SUPPLY_PROP_TEMP_MAX) {
86 val->intval = 100L;
87 } else if (psp == POWER_SUPPLY_PROP_CURRENT_AVG) {
88 val->intval = 4200L * 1000L;
89 } else if (psp == POWER_SUPPLY_PROP_CURRENT_NOW) {
90 val->intval = 100L * 1000L;
91 } else if (psp == POWER_SUPPLY_PROP_CURRENT_MAX) {
92 val->intval = 3000000L;
93 } else if (psp == POWER_SUPPLY_PROP_VOLTAGE_MAX) {
94 val->intval = 5000000L;
95 } else if (psp == POWER_SUPPLY_PROP_TECHNOLOGY) {
96 val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO;
97 } else {
98 ret = -EINVAL;
99 }
100
101 return ret;
102 }
103
104 static struct ac_data ac_main = {
105 .psd =
106 {
107 .name = "ac",
108 .type = POWER_SUPPLY_TYPE_MAINS,
109 .properties = ac_props,
110 .num_properties = ARRAY_SIZE(ac_props),
111 .get_property = ac_get_property,
112 },
113 };
114
115 static struct battery_data battery_main = {
116 .psd =
117 {
118 .name = "battery",
119 .type = POWER_SUPPLY_TYPE_BATTERY,
120 .properties = battery_props,
121 .num_properties = ARRAY_SIZE(battery_props),
122 .get_property = battery_get_property,
123 },
124 };
125
aml_battery_init(void)126 static int __init aml_battery_init(void)
127 {
128 ac_main.psy = power_supply_register(NULL, &ac_main.psd, NULL);
129 if (IS_ERR(ac_main.psy)) {
130 pr_debug("[%s] power_supply_register AC Fail !!\n", __func__);
131 return -1;
132 }
133
134 battery_main.psy = power_supply_register(NULL, &battery_main.psd, NULL);
135 if (IS_ERR(battery_main.psy)) {
136 pr_debug("[%s] power_supply_register Battery Fail !!\n", __func__);
137 return -1;
138 }
139
140 pr_debug("power_supply_register AC/Battery Success !!\n");
141
142 return 0;
143 }
144
aml_battery_exit(void)145 static void __exit aml_battery_exit(void)
146 {
147 power_supply_unregister(battery_main.psy);
148 }
149
150 module_init(aml_battery_init);
151 module_exit(aml_battery_exit);
152
153 MODULE_AUTHOR("AlgoIdeas <yu19881234@163.com>");
154 MODULE_LICENSE("GPL");
155 MODULE_DESCRIPTION("Battery driver for Amlogic");