diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 8f9940f40baa..1da360c51d66 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -280,9 +280,9 @@ config ACPI_CPPC_LIB config ACPI_PROCESSOR tristate "Processor" - depends on X86 || IA64 || ARM64 + depends on X86 || IA64 || ARM64 || LOONGARCH select ACPI_PROCESSOR_IDLE - select ACPI_CPU_FREQ_PSS if X86 || IA64 + select ACPI_CPU_FREQ_PSS if X86 || IA64 || LOONGARCH default y help This driver adds support for the ACPI Processor package. It is required diff --git a/drivers/acpi/acpi_configfs.c b/drivers/acpi/acpi_configfs.c index 76b83b181356..c970792b11a4 100644 --- a/drivers/acpi/acpi_configfs.c +++ b/drivers/acpi/acpi_configfs.c @@ -70,7 +70,7 @@ static inline struct acpi_table_header *get_header(struct config_item *cfg) if (!table->header) pr_err("table not loaded\n"); - return table->header; + return table->header ?: ERR_PTR(-EINVAL); } static ssize_t acpi_table_aml_read(struct config_item *cfg, @@ -78,8 +78,8 @@ static ssize_t acpi_table_aml_read(struct config_item *cfg, { struct acpi_table_header *h = get_header(cfg); - if (!h) - return -EINVAL; + if (IS_ERR(h)) + return PTR_ERR(h); if (data) memcpy(data, h, h->length); @@ -100,60 +100,60 @@ static ssize_t acpi_table_signature_show(struct config_item *cfg, char *str) { struct acpi_table_header *h = get_header(cfg); - if (!h) - return -EINVAL; + if (IS_ERR(h)) + return PTR_ERR(h); - return sprintf(str, "%.*s\n", ACPI_NAMESEG_SIZE, h->signature); + return sysfs_emit(str, "%.*s\n", ACPI_NAMESEG_SIZE, h->signature); } static ssize_t acpi_table_length_show(struct config_item *cfg, char *str) { struct acpi_table_header *h = get_header(cfg); - if (!h) - return -EINVAL; + if (IS_ERR(h)) + return PTR_ERR(h); - return sprintf(str, "%d\n", h->length); + return sysfs_emit(str, "%d\n", h->length); } static ssize_t acpi_table_revision_show(struct config_item *cfg, char *str) { struct acpi_table_header *h = get_header(cfg); - if (!h) - return -EINVAL; + if (IS_ERR(h)) + return PTR_ERR(h); - return sprintf(str, "%d\n", h->revision); + return sysfs_emit(str, "%d\n", h->revision); } static ssize_t acpi_table_oem_id_show(struct config_item *cfg, char *str) { struct acpi_table_header *h = get_header(cfg); - if (!h) - return -EINVAL; + if (IS_ERR(h)) + return PTR_ERR(h); - return sprintf(str, "%.*s\n", ACPI_OEM_ID_SIZE, h->oem_id); + return sysfs_emit(str, "%.*s\n", ACPI_OEM_ID_SIZE, h->oem_id); } static ssize_t acpi_table_oem_table_id_show(struct config_item *cfg, char *str) { struct acpi_table_header *h = get_header(cfg); - if (!h) - return -EINVAL; + if (IS_ERR(h)) + return PTR_ERR(h); - return sprintf(str, "%.*s\n", ACPI_OEM_TABLE_ID_SIZE, h->oem_table_id); + return sysfs_emit(str, "%.*s\n", ACPI_OEM_TABLE_ID_SIZE, h->oem_table_id); } static ssize_t acpi_table_oem_revision_show(struct config_item *cfg, char *str) { struct acpi_table_header *h = get_header(cfg); - if (!h) - return -EINVAL; + if (IS_ERR(h)) + return PTR_ERR(h); - return sprintf(str, "%d\n", h->oem_revision); + return sysfs_emit(str, "%d\n", h->oem_revision); } static ssize_t acpi_table_asl_compiler_id_show(struct config_item *cfg, @@ -161,10 +161,10 @@ static ssize_t acpi_table_asl_compiler_id_show(struct config_item *cfg, { struct acpi_table_header *h = get_header(cfg); - if (!h) - return -EINVAL; + if (IS_ERR(h)) + return PTR_ERR(h); - return sprintf(str, "%.*s\n", ACPI_NAMESEG_SIZE, h->asl_compiler_id); + return sysfs_emit(str, "%.*s\n", ACPI_NAMESEG_SIZE, h->asl_compiler_id); } static ssize_t acpi_table_asl_compiler_revision_show(struct config_item *cfg, @@ -172,10 +172,10 @@ static ssize_t acpi_table_asl_compiler_revision_show(struct config_item *cfg, { struct acpi_table_header *h = get_header(cfg); - if (!h) - return -EINVAL; + if (IS_ERR(h)) + return PTR_ERR(h); - return sprintf(str, "%d\n", h->asl_compiler_revision); + return sysfs_emit(str, "%d\n", h->asl_compiler_revision); } CONFIGFS_ATTR_RO(acpi_table_, signature); diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index f854bcb8d010..3abb4373d11b 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -498,24 +498,24 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data) acpi_evaluate_ost(handle, type, ost_code, NULL); } -static void acpi_device_notify(acpi_handle handle, u32 event, void *data) +static void acpi_notify_device(acpi_handle handle, u32 event, void *data) { struct acpi_device *device = data; device->driver->ops.notify(device, event); } -static void acpi_device_notify_fixed(void *data) +static void acpi_notify_device_fixed(void *data) { struct acpi_device *device = data; /* Fixed hardware devices have no handles */ - acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device); + acpi_notify_device(NULL, ACPI_FIXED_HARDWARE_EVENT, device); } static u32 acpi_device_fixed_event(void *data) { - acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_device_notify_fixed, data); + acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_notify_device_fixed, data); return ACPI_INTERRUPT_HANDLED; } @@ -536,7 +536,7 @@ static int acpi_device_install_notify_handler(struct acpi_device *device) else status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, - acpi_device_notify, + acpi_notify_device, device); if (ACPI_FAILURE(status)) @@ -554,7 +554,7 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device) acpi_device_fixed_event); else acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, - acpi_device_notify); + acpi_notify_device); } /* Handle events targeting \_SB device (at present only graceful shutdown) */ diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index fce3f3bba714..7a33a6d985f8 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -285,29 +285,27 @@ int acpi_unbind_one(struct device *dev) } EXPORT_SYMBOL_GPL(acpi_unbind_one); -static int acpi_device_notify(struct device *dev) +void acpi_device_notify(struct device *dev) { struct acpi_bus_type *type = acpi_get_bus_type(dev); struct acpi_device *adev; int ret; ret = acpi_bind_one(dev, NULL); - if (ret && type) { - struct acpi_device *adev; + if (ret) { + if (!type) + goto err; adev = type->find_companion(dev); if (!adev) { - pr_debug("Unable to get handle for %s\n", dev_name(dev)); - ret = -ENODEV; - goto out; + dev_dbg(dev, "ACPI companion not found\n"); + goto err; } ret = acpi_bind_one(dev, adev); if (ret) - goto out; + goto err; } adev = ACPI_COMPANION(dev); - if (!adev) - goto out; if (dev_is_platform(dev)) acpi_configure_pmsi_domain(dev); @@ -317,27 +315,22 @@ static int acpi_device_notify(struct device *dev) else if (adev->handler && adev->handler->bind) adev->handler->bind(dev); - out: - if (!ret) { - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + acpi_handle_debug(ACPI_HANDLE(dev), "Bound to device %s\n", + dev_name(dev)); - acpi_get_name(ACPI_HANDLE(dev), ACPI_FULL_PATHNAME, &buffer); - pr_debug("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer); - kfree(buffer.pointer); - } else { - pr_debug("Device %s -> No ACPI support\n", dev_name(dev)); - } + return; - return ret; +err: + dev_dbg(dev, "No ACPI support\n"); } -static int acpi_device_notify_remove(struct device *dev) +void acpi_device_notify_remove(struct device *dev) { struct acpi_device *adev = ACPI_COMPANION(dev); struct acpi_bus_type *type; if (!adev) - return 0; + return; type = acpi_get_bus_type(dev); if (type && type->cleanup) @@ -346,20 +339,4 @@ static int acpi_device_notify_remove(struct device *dev) adev->handler->unbind(dev); acpi_unbind_one(dev); - return 0; -} - -int acpi_platform_notify(struct device *dev, enum kobject_action action) -{ - switch (action) { - case KOBJ_ADD: - acpi_device_notify(dev); - break; - case KOBJ_REMOVE: - acpi_device_notify_remove(dev); - break; - default: - break; - } - return 0; } diff --git a/drivers/acpi/numa/Kconfig b/drivers/acpi/numa/Kconfig index fcf2e556d69d..39b1f34c21df 100644 --- a/drivers/acpi/numa/Kconfig +++ b/drivers/acpi/numa/Kconfig @@ -2,7 +2,7 @@ config ACPI_NUMA bool "NUMA support" depends on NUMA - depends on (X86 || IA64 || ARM64) + depends on (X86 || IA64 || ARM64 || LOONGARCH) default y if IA64 || ARM64 config ACPI_HMAT diff --git a/drivers/acpi/numa/srat.c b/drivers/acpi/numa/srat.c index 6021a1013442..b8795fc49097 100644 --- a/drivers/acpi/numa/srat.c +++ b/drivers/acpi/numa/srat.c @@ -206,7 +206,7 @@ int __init srat_disabled(void) return acpi_numa < 0; } -#if defined(CONFIG_X86) || defined(CONFIG_ARM64) +#if defined(CONFIG_X86) || defined(CONFIG_ARM64) || defined(CONFIG_LOONGARCH) /* * Callback for SLIT parsing. pxm_to_node() returns NUMA_NO_NODE for * I/O localities since SRAT does not list them. I/O localities are diff --git a/drivers/acpi/pmic/intel_pmic_xpower.c b/drivers/acpi/pmic/intel_pmic_xpower.c index a091d5a8392c..cbe08e600fa3 100644 --- a/drivers/acpi/pmic/intel_pmic_xpower.c +++ b/drivers/acpi/pmic/intel_pmic_xpower.c @@ -178,15 +178,17 @@ static int intel_xpower_pmic_update_power(struct regmap *regmap, int reg, { int data, ret; - /* GPIO1 LDO regulator needs special handling */ - if (reg == XPOWER_GPI1_CTRL) - return regmap_update_bits(regmap, reg, GPI1_LDO_MASK, - on ? GPI1_LDO_ON : GPI1_LDO_OFF); - ret = iosf_mbi_block_punit_i2c_access(); if (ret) return ret; + /* GPIO1 LDO regulator needs special handling */ + if (reg == XPOWER_GPI1_CTRL) { + ret = regmap_update_bits(regmap, reg, GPI1_LDO_MASK, + on ? GPI1_LDO_ON : GPI1_LDO_OFF); + goto out; + } + if (regmap_read(regmap, reg, &data)) { ret = -EIO; goto out; @@ -234,6 +236,11 @@ static int intel_xpower_pmic_get_raw_temp(struct regmap *regmap, int reg) return ret; if (adc_ts_pin_ctrl & AXP288_ADC_TS_CURRENT_ON_OFF_MASK) { + /* + * AXP288_ADC_TS_PIN_CTRL reads are cached by the regmap, so + * this does to a single I2C-transfer, and thus there is no + * need to explicitly call iosf_mbi_block_punit_i2c_access(). + */ ret = regmap_update_bits(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_CURRENT_ON_OFF_MASK, AXP288_ADC_TS_CURRENT_ON_ONDEMAND); @@ -244,6 +251,10 @@ static int intel_xpower_pmic_get_raw_temp(struct regmap *regmap, int reg) usleep_range(6000, 10000); } + ret = iosf_mbi_block_punit_i2c_access(); + if (ret) + return ret; + ret = regmap_bulk_read(regmap, AXP288_GP_ADC_H, buf, 2); if (ret == 0) ret = (buf[0] << 4) + ((buf[1] >> 4) & 0x0f); @@ -254,6 +265,31 @@ static int intel_xpower_pmic_get_raw_temp(struct regmap *regmap, int reg) AXP288_ADC_TS_CURRENT_ON); } + iosf_mbi_unblock_punit_i2c_access(); + + return ret; +} + +static int intel_xpower_exec_mipi_pmic_seq_element(struct regmap *regmap, + u16 i2c_address, u32 reg_address, + u32 value, u32 mask) +{ + int ret; + + if (i2c_address != 0x34) { + pr_err("%s: Unexpected i2c-addr: 0x%02x (reg-addr 0x%x value 0x%x mask 0x%x)\n", + __func__, i2c_address, reg_address, value, mask); + return -ENXIO; + } + + ret = iosf_mbi_block_punit_i2c_access(); + if (ret) + return ret; + + ret = regmap_update_bits(regmap, reg_address, mask, value); + + iosf_mbi_unblock_punit_i2c_access(); + return ret; } @@ -261,6 +297,7 @@ static struct intel_pmic_opregion_data intel_xpower_pmic_opregion_data = { .get_power = intel_xpower_pmic_get_power, .update_power = intel_xpower_pmic_update_power, .get_raw_temp = intel_xpower_pmic_get_raw_temp, + .exec_mipi_pmic_seq_element = intel_xpower_exec_mipi_pmic_seq_element, .power_table = power_table, .power_table_count = ARRAY_SIZE(power_table), .thermal_table = thermal_table, diff --git a/drivers/base/base.h b/drivers/base/base.h index 404db83ee5ec..2882af26392a 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -202,3 +202,6 @@ int devtmpfs_delete_node(struct device *dev); static inline int devtmpfs_create_node(struct device *dev) { return 0; } static inline int devtmpfs_delete_node(struct device *dev) { return 0; } #endif + +void software_node_notify(struct device *dev); +void software_node_notify_remove(struct device *dev); diff --git a/drivers/base/core.c b/drivers/base/core.c index 6c0ef9d55a34..3a72241b87c6 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2002,24 +2002,24 @@ static inline int device_is_not_partition(struct device *dev) } #endif -static int -device_platform_notify(struct device *dev, enum kobject_action action) +static void device_platform_notify(struct device *dev) { - int ret; + acpi_device_notify(dev); - ret = acpi_platform_notify(dev, action); - if (ret) - return ret; + software_node_notify(dev); - ret = software_node_notify(dev, action); - if (ret) - return ret; - - if (platform_notify && action == KOBJ_ADD) + if (platform_notify) platform_notify(dev); - else if (platform_notify_remove && action == KOBJ_REMOVE) +} + +static void device_platform_notify_remove(struct device *dev) +{ + acpi_device_notify_remove(dev); + + software_node_notify_remove(dev); + + if (platform_notify_remove) platform_notify_remove(dev); - return 0; } /** @@ -3292,9 +3292,7 @@ int device_add(struct device *dev) } /* notify platform of device entry */ - error = device_platform_notify(dev, KOBJ_ADD); - if (error) - goto platform_error; + device_platform_notify(dev); error = device_create_file(dev, &dev_attr_uevent); if (error) @@ -3397,8 +3395,7 @@ done: SymlinkError: device_remove_file(dev, &dev_attr_uevent); attrError: - device_platform_notify(dev, KOBJ_REMOVE); -platform_error: + device_platform_notify_remove(dev); kobject_uevent(&dev->kobj, KOBJ_REMOVE); glue_dir = get_glue_dir(dev); kobject_del(&dev->kobj); @@ -3543,7 +3540,7 @@ void device_del(struct device *dev) bus_remove_device(dev); device_pm_remove(dev); driver_deferred_probe_del(dev); - device_platform_notify(dev, KOBJ_REMOVE); + device_platform_notify_remove(dev); device_remove_properties(dev); device_links_purge(dev); diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c index d1f1a8240120..7bd0f3cfb7eb 100644 --- a/drivers/base/swnode.c +++ b/drivers/base/swnode.c @@ -11,6 +11,8 @@ #include #include +#include "base.h" + struct swnode { struct kobject kobj; struct fwnode_handle fwnode; @@ -1053,7 +1055,7 @@ int device_add_software_node(struct device *dev, const struct software_node *nod * balance. */ if (device_is_registered(dev)) - software_node_notify(dev, KOBJ_ADD); + software_node_notify(dev); return 0; } @@ -1074,7 +1076,8 @@ void device_remove_software_node(struct device *dev) return; if (device_is_registered(dev)) - software_node_notify(dev, KOBJ_REMOVE); + software_node_notify_remove(dev); + set_secondary_fwnode(dev, NULL); kobject_put(&swnode->kobj); } @@ -1117,44 +1120,44 @@ int device_create_managed_software_node(struct device *dev, } EXPORT_SYMBOL_GPL(device_create_managed_software_node); -int software_node_notify(struct device *dev, unsigned long action) +void software_node_notify(struct device *dev) { struct swnode *swnode; int ret; swnode = dev_to_swnode(dev); if (!swnode) - return 0; + return; - switch (action) { - case KOBJ_ADD: - ret = sysfs_create_link(&dev->kobj, &swnode->kobj, "software_node"); - if (ret) - break; + ret = sysfs_create_link(&dev->kobj, &swnode->kobj, "software_node"); + if (ret) + return; - ret = sysfs_create_link(&swnode->kobj, &dev->kobj, - dev_name(dev)); - if (ret) { - sysfs_remove_link(&dev->kobj, "software_node"); - break; - } - kobject_get(&swnode->kobj); - break; - case KOBJ_REMOVE: - sysfs_remove_link(&swnode->kobj, dev_name(dev)); + ret = sysfs_create_link(&swnode->kobj, &dev->kobj, dev_name(dev)); + if (ret) { sysfs_remove_link(&dev->kobj, "software_node"); - kobject_put(&swnode->kobj); - - if (swnode->managed) { - set_secondary_fwnode(dev, NULL); - kobject_put(&swnode->kobj); - } - break; - default: - break; + return; } - return 0; + kobject_get(&swnode->kobj); +} + +void software_node_notify_remove(struct device *dev) +{ + struct swnode *swnode; + + swnode = dev_to_swnode(dev); + if (!swnode) + return; + + sysfs_remove_link(&swnode->kobj, dev_name(dev)); + sysfs_remove_link(&dev->kobj, "software_node"); + kobject_put(&swnode->kobj); + + if (swnode->managed) { + set_secondary_fwnode(dev, NULL); + kobject_put(&swnode->kobj); + } } static int __init software_node_init(void) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 72e4f7fd268c..974d497a897d 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -249,7 +249,7 @@ void acpi_table_print_madt_entry (struct acpi_subtable_header *madt); /* the following numa functions are architecture-dependent */ void acpi_numa_slit_init (struct acpi_table_slit *slit); -#if defined(CONFIG_X86) || defined(CONFIG_IA64) +#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_LOONGARCH) void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa); #else static inline void @@ -1380,13 +1380,11 @@ static inline int find_acpi_cpu_cache_topology(unsigned int cpu, int level) #endif #ifdef CONFIG_ACPI -extern int acpi_platform_notify(struct device *dev, enum kobject_action action); +extern void acpi_device_notify(struct device *dev); +extern void acpi_device_notify_remove(struct device *dev); #else -static inline int -acpi_platform_notify(struct device *dev, enum kobject_action action) -{ - return 0; -} +static inline void acpi_device_notify(struct device *dev) { } +static inline void acpi_device_notify_remove(struct device *dev) { } #endif #endif /*_LINUX_ACPI_H*/ diff --git a/include/linux/property.h b/include/linux/property.h index 073e680c35e2..357513a977e5 100644 --- a/include/linux/property.h +++ b/include/linux/property.h @@ -484,8 +484,6 @@ void software_node_unregister_node_group(const struct software_node **node_group int software_node_register(const struct software_node *node); void software_node_unregister(const struct software_node *node); -int software_node_notify(struct device *dev, unsigned long action); - struct fwnode_handle * fwnode_create_software_node(const struct property_entry *properties, const struct fwnode_handle *parent);