Skip to content

Commit adfe8d7

Browse files
committed
Merge branch 'pci/hotplug'
- Add driver for Ampere Altra Attention Indicators (D Scott Phillips) * pci/hotplug: PCI: hotplug: Add Ampere Altra Attention Indicator extension driver PCI: acpiphp: Allow built-in drivers for Attention Indicators
2 parents 553b84b + 820f59e commit adfe8d7

File tree

4 files changed

+141
-2
lines changed

4 files changed

+141
-2
lines changed

drivers/pci/hotplug/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,18 @@ config HOTPLUG_PCI_ACPI
6161

6262
When in doubt, say N.
6363

64+
config HOTPLUG_PCI_ACPI_AMPERE_ALTRA
65+
tristate "ACPI PCI Hotplug driver Ampere Altra extensions"
66+
depends on HOTPLUG_PCI_ACPI
67+
depends on HAVE_ARM_SMCCC_DISCOVERY
68+
help
69+
Say Y here if you have an Ampere Altra system.
70+
71+
To compile this driver as a module, choose M here: the
72+
module will be called acpiphp_ampere_altra.
73+
74+
When in doubt, say N.
75+
6476
config HOTPLUG_PCI_ACPI_IBM
6577
tristate "ACPI PCI Hotplug driver IBM extensions"
6678
depends on HOTPLUG_PCI_ACPI

drivers/pci/hotplug/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ obj-$(CONFIG_HOTPLUG_PCI_S390) += s390_pci_hpc.o
2323

2424
# acpiphp_ibm extends acpiphp, so should be linked afterwards.
2525

26+
obj-$(CONFIG_HOTPLUG_PCI_ACPI_AMPERE_ALTRA) += acpiphp_ampere_altra.o
2627
obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o
2728

2829
pci_hotplug-objs := pci_hotplug_core.o
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* ACPI PCI Hot Plug Extension for Ampere Altra. Allows control of
4+
* attention LEDs via requests to system firmware.
5+
*
6+
* Copyright (C) 2023 Ampere Computing LLC
7+
*/
8+
9+
#define pr_fmt(fmt) "acpiphp_ampere_altra: " fmt
10+
11+
#include <linux/init.h>
12+
#include <linux/module.h>
13+
#include <linux/pci.h>
14+
#include <linux/pci_hotplug.h>
15+
#include <linux/platform_device.h>
16+
17+
#include "acpiphp.h"
18+
19+
#define HANDLE_OPEN 0xb0200000
20+
#define HANDLE_CLOSE 0xb0300000
21+
#define REQUEST 0xf0700000
22+
#define LED_CMD 0x00000004
23+
#define LED_ATTENTION 0x00000002
24+
#define LED_SET_ON 0x00000001
25+
#define LED_SET_OFF 0x00000002
26+
#define LED_SET_BLINK 0x00000003
27+
28+
static u32 led_service_id[4];
29+
30+
static int led_status(u8 status)
31+
{
32+
switch (status) {
33+
case 1: return LED_SET_ON;
34+
case 2: return LED_SET_BLINK;
35+
default: return LED_SET_OFF;
36+
}
37+
}
38+
39+
static int set_attention_status(struct hotplug_slot *slot, u8 status)
40+
{
41+
struct arm_smccc_res res;
42+
struct pci_bus *bus;
43+
struct pci_dev *root_port;
44+
unsigned long flags;
45+
u32 handle;
46+
int ret = 0;
47+
48+
bus = slot->pci_slot->bus;
49+
root_port = pcie_find_root_port(bus->self);
50+
if (!root_port)
51+
return -ENODEV;
52+
53+
local_irq_save(flags);
54+
arm_smccc_smc(HANDLE_OPEN, led_service_id[0], led_service_id[1],
55+
led_service_id[2], led_service_id[3], 0, 0, 0, &res);
56+
if (res.a0) {
57+
ret = -ENODEV;
58+
goto out;
59+
}
60+
handle = res.a1 & 0xffff0000;
61+
62+
arm_smccc_smc(REQUEST, LED_CMD, led_status(status), LED_ATTENTION,
63+
(PCI_SLOT(root_port->devfn) << 4) | (pci_domain_nr(bus) & 0xf),
64+
0, 0, handle, &res);
65+
if (res.a0)
66+
ret = -ENODEV;
67+
68+
arm_smccc_smc(HANDLE_CLOSE, handle, 0, 0, 0, 0, 0, 0, &res);
69+
70+
out:
71+
local_irq_restore(flags);
72+
return ret;
73+
}
74+
75+
static int get_attention_status(struct hotplug_slot *slot, u8 *status)
76+
{
77+
return -EINVAL;
78+
}
79+
80+
static struct acpiphp_attention_info ampere_altra_attn = {
81+
.set_attn = set_attention_status,
82+
.get_attn = get_attention_status,
83+
.owner = THIS_MODULE,
84+
};
85+
86+
static int altra_led_probe(struct platform_device *pdev)
87+
{
88+
struct fwnode_handle *fwnode = dev_fwnode(&pdev->dev);
89+
int ret;
90+
91+
ret = fwnode_property_read_u32_array(fwnode, "uuid", led_service_id, 4);
92+
if (ret) {
93+
dev_err(&pdev->dev, "can't find uuid\n");
94+
return ret;
95+
}
96+
97+
ret = acpiphp_register_attention(&ampere_altra_attn);
98+
if (ret) {
99+
dev_err(&pdev->dev, "can't register driver\n");
100+
return ret;
101+
}
102+
return 0;
103+
}
104+
105+
static void altra_led_remove(struct platform_device *pdev)
106+
{
107+
acpiphp_unregister_attention(&ampere_altra_attn);
108+
}
109+
110+
static const struct acpi_device_id altra_led_ids[] = {
111+
{ "AMPC0008", 0 },
112+
{ }
113+
};
114+
MODULE_DEVICE_TABLE(acpi, altra_led_ids);
115+
116+
static struct platform_driver altra_led_driver = {
117+
.driver = {
118+
.name = "ampere-altra-leds",
119+
.acpi_match_table = altra_led_ids,
120+
},
121+
.probe = altra_led_probe,
122+
.remove_new = altra_led_remove,
123+
};
124+
module_platform_driver(altra_led_driver);
125+
126+
MODULE_AUTHOR("D Scott Phillips <[email protected]>");
127+
MODULE_LICENSE("GPL");

drivers/pci/hotplug/acpiphp_core.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ int acpiphp_register_attention(struct acpiphp_attention_info *info)
7878
{
7979
int retval = -EINVAL;
8080

81-
if (info && info->owner && info->set_attn &&
82-
info->get_attn && !attention_info) {
81+
if (info && info->set_attn && info->get_attn && !attention_info) {
8382
retval = 0;
8483
attention_info = info;
8584
}

0 commit comments

Comments
 (0)