Blame view

drivers/acpi/acpi_cmos_rtc.c 1.95 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
2fa97feb4   Lan Tianyu   ACPI: Add CMOS RT...
2
3
4
5
6
  /*
   * ACPI support for CMOS RTC Address Space access
   *
   * Copyright (C) 2013, Intel Corporation
   * Authors: Lan Tianyu <tianyu.lan@intel.com>
2fa97feb4   Lan Tianyu   ACPI: Add CMOS RT...
7
8
9
10
11
12
13
   */
  
  #include <linux/acpi.h>
  #include <linux/device.h>
  #include <linux/err.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
463a86304   Arnd Bergmann   char/genrtc: x86:...
14
  #include <linux/mc146818rtc.h>
2fa97feb4   Lan Tianyu   ACPI: Add CMOS RT...
15
16
  
  #include "internal.h"
2fa97feb4   Lan Tianyu   ACPI: Add CMOS RT...
17
18
19
20
21
22
23
24
25
26
27
28
29
  static const struct acpi_device_id acpi_cmos_rtc_ids[] = {
  	{ "PNP0B00" },
  	{ "PNP0B01" },
  	{ "PNP0B02" },
  	{}
  };
  
  static acpi_status
  acpi_cmos_rtc_space_handler(u32 function, acpi_physical_address address,
  		      u32 bits, u64 *value64,
  		      void *handler_context, void *region_context)
  {
  	int i;
9389f46e9   Lee, Chun-Yi   ACPI / RTC: Fix C...
30
  	u8 *value = (u8 *)value64;
2fa97feb4   Lan Tianyu   ACPI: Add CMOS RT...
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
  
  	if (address > 0xff || !value64)
  		return AE_BAD_PARAMETER;
  
  	if (function != ACPI_WRITE && function != ACPI_READ)
  		return AE_BAD_PARAMETER;
  
  	spin_lock_irq(&rtc_lock);
  
  	for (i = 0; i < DIV_ROUND_UP(bits, 8); ++i, ++address, ++value)
  		if (function == ACPI_READ)
  			*value = CMOS_READ(address);
  		else
  			CMOS_WRITE(*value, address);
  
  	spin_unlock_irq(&rtc_lock);
  
  	return AE_OK;
  }
  
  static int acpi_install_cmos_rtc_space_handler(struct acpi_device *adev,
  		const struct acpi_device_id *id)
  {
  	acpi_status status;
  
  	status = acpi_install_address_space_handler(adev->handle,
  			ACPI_ADR_SPACE_CMOS,
  			&acpi_cmos_rtc_space_handler,
  			NULL, NULL);
  	if (ACPI_FAILURE(status)) {
  		pr_err(PREFIX "Error installing CMOS-RTC region handler
  ");
  		return -ENODEV;
  	}
eec15edbb   Zhang Rui   ACPI / PNP: use d...
65
  	return 1;
2fa97feb4   Lan Tianyu   ACPI: Add CMOS RT...
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
  }
  
  static void acpi_remove_cmos_rtc_space_handler(struct acpi_device *adev)
  {
  	if (ACPI_FAILURE(acpi_remove_address_space_handler(adev->handle,
  			ACPI_ADR_SPACE_CMOS, &acpi_cmos_rtc_space_handler)))
  		pr_err(PREFIX "Error removing CMOS-RTC region handler
  ");
  }
  
  static struct acpi_scan_handler cmos_rtc_handler = {
  	.ids = acpi_cmos_rtc_ids,
  	.attach = acpi_install_cmos_rtc_space_handler,
  	.detach = acpi_remove_cmos_rtc_space_handler,
  };
  
  void __init acpi_cmos_rtc_init(void)
  {
  	acpi_scan_add_handler(&cmos_rtc_handler);
  }