File Index
Files and directories
Sign in
FILE

hp6xx_apm.c

File preview with syntax highlighting.

linux-6.19.14/arch/sh/boards/mach-hp6xx/hp6xx_apm.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * bios-less APM driver for hp680
  4 *
  5 * Copyright 2005 (c) Andriy Skulysh <askulysh@gmail.com>
  6 * Copyright 2008 (c) Kristoffer Ericson <kristoffer.ericson@gmail.com>
  7 */
  8#include <linux/module.h>
  9#include <linux/kernel.h>
 10#include <linux/init.h>
 11#include <linux/interrupt.h>
 12#include <linux/apm-emulation.h>
 13#include <linux/io.h>
 14#include <asm/adc.h>
 15#include <mach/hp6xx.h>
 16
 17/* percentage values */
 18#define APM_CRITICAL			10
 19#define APM_LOW				30
 20
 21/* resonably sane values */
 22#define HP680_BATTERY_MAX		898
 23#define HP680_BATTERY_MIN		486
 24#define HP680_BATTERY_AC_ON		1023
 25
 26#define MODNAME "hp6x0_apm"
 27
 28#define PGDR	0xa400012c
 29
 30static void hp6x0_apm_get_power_status(struct apm_power_info *info)
 31{
 32	int battery, backup, charging, percentage;
 33	u8 pgdr;
 34
 35	battery		= adc_single(ADC_CHANNEL_BATTERY);
 36	backup		= adc_single(ADC_CHANNEL_BACKUP);
 37	charging	= adc_single(ADC_CHANNEL_CHARGE);
 38
 39	percentage = 100 * (battery - HP680_BATTERY_MIN) /
 40			   (HP680_BATTERY_MAX - HP680_BATTERY_MIN);
 41
 42	/* % of full battery */
 43	info->battery_life = percentage;
 44
 45	/* We want our estimates in minutes */
 46	info->units = 0;
 47
 48	/* Extremely(!!) rough estimate, we will replace this with a datalist later on */
 49	info->time = (2 * battery);
 50
 51	info->ac_line_status = (battery > HP680_BATTERY_AC_ON) ?
 52			 APM_AC_ONLINE : APM_AC_OFFLINE;
 53
 54	pgdr = __raw_readb(PGDR);
 55	if (pgdr & PGDR_MAIN_BATTERY_OUT) {
 56		info->battery_status	= APM_BATTERY_STATUS_NOT_PRESENT;
 57		info->battery_flag	= 0x80;
 58	} else if (charging < 8) {
 59		info->battery_status	= APM_BATTERY_STATUS_CHARGING;
 60		info->battery_flag	= 0x08;
 61		info->ac_line_status	= 0x01;
 62	} else if (percentage <= APM_CRITICAL) {
 63		info->battery_status	= APM_BATTERY_STATUS_CRITICAL;
 64		info->battery_flag	= 0x04;
 65	} else if (percentage <= APM_LOW) {
 66		info->battery_status	= APM_BATTERY_STATUS_LOW;
 67		info->battery_flag	= 0x02;
 68	} else {
 69		info->battery_status	= APM_BATTERY_STATUS_HIGH;
 70		info->battery_flag	= 0x01;
 71	}
 72}
 73
 74static irqreturn_t hp6x0_apm_interrupt(int irq, void *dev)
 75{
 76	if (!APM_DISABLED)
 77		apm_queue_event(APM_USER_SUSPEND);
 78
 79	return IRQ_HANDLED;
 80}
 81
 82static int __init hp6x0_apm_init(void)
 83{
 84	int ret;
 85
 86	ret = request_irq(HP680_BTN_IRQ, hp6x0_apm_interrupt,
 87			  0, MODNAME, NULL);
 88	if (unlikely(ret < 0)) {
 89		printk(KERN_ERR MODNAME ": IRQ %d request failed\n",
 90		       HP680_BTN_IRQ);
 91		return ret;
 92	}
 93
 94	apm_get_power_status = hp6x0_apm_get_power_status;
 95
 96	return ret;
 97}
 98
 99static void __exit hp6x0_apm_exit(void)
100{
101	free_irq(HP680_BTN_IRQ, 0);
102}
103
104module_init(hp6x0_apm_init);
105module_exit(hp6x0_apm_exit);
106
107MODULE_AUTHOR("Adriy Skulysh");
108MODULE_DESCRIPTION("hp6xx Advanced Power Management");
109MODULE_LICENSE("GPL");
~/ Read-only file preview.