1515#include <linux/kernel.h>
1616#include <linux/module.h>
1717#include <linux/platform_device.h>
18+ #include <linux/power_supply.h>
19+ #include <acpi/battery.h>
1820
1921#define AYANEO_PWM_ENABLE_REG 0x4A
2022#define AYANEO_PWM_REG 0x4B
2325
2426#define AYANEO_FAN_REG 0x76
2527
28+ #define EC_CHARGE_CONTROL_BEHAVIOURS \
29+ (BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO) | \
30+ BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE))
31+ #define AYANEO_CHARGE_REG 0x1e
32+ #define AYANEO_CHARGE_VAL_AUTO 0xaa
33+ #define AYANEO_CHARGE_VAL_INHIBIT 0x55
34+
2635struct ayaneo_ec_quirk {
2736 bool has_fan_control ;
37+ bool has_charge_control ;
2838};
2939
3040struct ayaneo_ec_platform_data {
3141 struct platform_device * pdev ;
3242 struct ayaneo_ec_quirk * quirks ;
43+ struct acpi_battery_hook battery_hook ;
3344};
3445
3546static const struct ayaneo_ec_quirk quirk_ayaneo3 = {
3647 .has_fan_control = true,
48+ .has_charge_control = true,
3749};
3850
3951static const struct dmi_system_id dmi_table [] = {
@@ -164,11 +176,102 @@ static const struct hwmon_chip_info ayaneo_ec_chip_info = {
164176 .info = ayaneo_ec_sensors ,
165177};
166178
179+ static int ayaneo_psy_ext_get_prop (struct power_supply * psy ,
180+ const struct power_supply_ext * ext ,
181+ void * data ,
182+ enum power_supply_property psp ,
183+ union power_supply_propval * val )
184+ {
185+ int ret ;
186+ u8 tmp ;
187+
188+ switch (psp ) {
189+ case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR :
190+ ret = ec_read (AYANEO_CHARGE_REG , & tmp );
191+ if (ret )
192+ return ret ;
193+
194+ if (tmp == AYANEO_CHARGE_VAL_INHIBIT )
195+ val -> intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE ;
196+ else
197+ val -> intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO ;
198+ return 0 ;
199+ default :
200+ return - EINVAL ;
201+ }
202+ }
203+
204+ static int ayaneo_psy_ext_set_prop (struct power_supply * psy ,
205+ const struct power_supply_ext * ext ,
206+ void * data ,
207+ enum power_supply_property psp ,
208+ const union power_supply_propval * val )
209+ {
210+ u8 raw_val ;
211+
212+ switch (psp ) {
213+ case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR :
214+ switch (val -> intval ) {
215+ case POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO :
216+ raw_val = AYANEO_CHARGE_VAL_AUTO ;
217+ break ;
218+ case POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE :
219+ raw_val = AYANEO_CHARGE_VAL_INHIBIT ;
220+ break ;
221+ default :
222+ return - EINVAL ;
223+ }
224+ return ec_write (AYANEO_CHARGE_REG , raw_val );
225+ default :
226+ return - EINVAL ;
227+ }
228+ }
229+
230+ static int ayaneo_psy_prop_is_writeable (struct power_supply * psy ,
231+ const struct power_supply_ext * ext ,
232+ void * data ,
233+ enum power_supply_property psp )
234+ {
235+ return true;
236+ }
237+
238+ static const enum power_supply_property ayaneo_psy_ext_props [] = {
239+ POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR ,
240+ };
241+
242+ static const struct power_supply_ext ayaneo_psy_ext = {
243+ .name = "ayaneo-charge-control" ,
244+ .properties = ayaneo_psy_ext_props ,
245+ .num_properties = ARRAY_SIZE (ayaneo_psy_ext_props ),
246+ .charge_behaviours = EC_CHARGE_CONTROL_BEHAVIOURS ,
247+ .get_property = ayaneo_psy_ext_get_prop ,
248+ .set_property = ayaneo_psy_ext_set_prop ,
249+ .property_is_writeable = ayaneo_psy_prop_is_writeable ,
250+ };
251+
252+ static int ayaneo_add_battery (struct power_supply * battery ,
253+ struct acpi_battery_hook * hook )
254+ {
255+ struct ayaneo_ec_platform_data * data =
256+ container_of (hook , struct ayaneo_ec_platform_data , battery_hook );
257+
258+ return power_supply_register_extension (battery , & ayaneo_psy_ext ,
259+ & data -> pdev -> dev , NULL );
260+ }
261+
262+ static int ayaneo_remove_battery (struct power_supply * battery ,
263+ struct acpi_battery_hook * hook )
264+ {
265+ power_supply_unregister_extension (battery , & ayaneo_psy_ext );
266+ return 0 ;
267+ }
268+
167269static int ayaneo_ec_probe (struct platform_device * pdev )
168270{
169271 const struct dmi_system_id * dmi_entry ;
170272 struct ayaneo_ec_platform_data * data ;
171273 struct device * hwdev ;
274+ int ret ;
172275
173276 dmi_entry = dmi_first_match (dmi_table );
174277 if (!dmi_entry )
@@ -189,6 +292,15 @@ static int ayaneo_ec_probe(struct platform_device *pdev)
189292 return PTR_ERR (hwdev );
190293 }
191294
295+ if (data -> quirks -> has_charge_control ) {
296+ data -> battery_hook .add_battery = ayaneo_add_battery ;
297+ data -> battery_hook .remove_battery = ayaneo_remove_battery ;
298+ data -> battery_hook .name = "Ayaneo Battery" ;
299+ ret = devm_battery_hook_register (& pdev -> dev , & data -> battery_hook );
300+ if (ret )
301+ return ret ;
302+ }
303+
192304 return 0 ;
193305}
194306
0 commit comments