diff options
author | Johannes Berg <johannes.berg@intel.com> | 2023-10-05 22:57:34 +0200 |
---|---|---|
committer | Kalle Valo <kvalo@kernel.org> | 2023-10-06 17:08:47 +0300 |
commit | 7d6904bf26b96ef087514cb7a8c50b62a4911c99 (patch) | |
tree | 2feaff8495d88c2102dc2e017b7afc5c58db02d6 /drivers | |
parent | 9418edf8ff01e7a4904aac1aca4864ecdea37593 (diff) | |
parent | 22061bfc57fe08c77141dc876b4af75603c4d61d (diff) |
Merge wireless into wireless-next
Resolve several conflicts, mostly between changes/fixes in
wireless and the locking rework in wireless-next. One of
the conflicts actually shows a bug in wireless that we'll
want to fix separately.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Diffstat (limited to 'drivers')
950 files changed, 24545 insertions, 12955 deletions
diff --git a/drivers/Makefile b/drivers/Makefile index 7241d80a7b29..a7459e77df37 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -195,3 +195,5 @@ obj-$(CONFIG_PECI) += peci/ obj-$(CONFIG_HTE) += hte/ obj-$(CONFIG_DRM_ACCEL) += accel/ obj-$(CONFIG_CDX_BUS) += cdx/ + +obj-$(CONFIG_S390) += s390/ diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 00dd309b6682..cee82b473dc5 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -581,7 +581,7 @@ config ACPI_VIOT config ACPI_PRMT bool "Platform Runtime Mechanism Support" - depends on EFI && (X86_64 || ARM64) + depends on EFI_RUNTIME_WRAPPERS && (X86_64 || ARM64) default y help Platform Runtime Mechanism (PRM) is a firmware interface exposing a diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 3fc5a0d54f6e..eaa09bf52f17 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -50,7 +50,6 @@ acpi-$(CONFIG_PCI) += acpi_lpss.o acpi-y += acpi_apd.o acpi-y += acpi_platform.o acpi-y += acpi_pnp.o -acpi-$(CONFIG_ARM_AMBA) += acpi_amba.o acpi-y += power.o acpi-y += event.o acpi-y += evged.o diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 1ace70b831cd..225dc6818751 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -34,7 +34,7 @@ MODULE_LICENSE("GPL"); static int acpi_ac_add(struct acpi_device *device); static void acpi_ac_remove(struct acpi_device *device); -static void acpi_ac_notify(struct acpi_device *device, u32 event); +static void acpi_ac_notify(acpi_handle handle, u32 event, void *data); static const struct acpi_device_id ac_device_ids[] = { {"ACPI0003", 0}, @@ -54,11 +54,9 @@ static struct acpi_driver acpi_ac_driver = { .name = "ac", .class = ACPI_AC_CLASS, .ids = ac_device_ids, - .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, .ops = { .add = acpi_ac_add, .remove = acpi_ac_remove, - .notify = acpi_ac_notify, }, .drv.pm = &acpi_ac_pm, }; @@ -128,8 +126,9 @@ static enum power_supply_property ac_props[] = { }; /* Driver Model */ -static void acpi_ac_notify(struct acpi_device *device, u32 event) +static void acpi_ac_notify(acpi_handle handle, u32 event, void *data) { + struct acpi_device *device = data; struct acpi_ac *ac = acpi_driver_data(device); if (!ac) @@ -235,7 +234,7 @@ static int acpi_ac_add(struct acpi_device *device) result = acpi_ac_get_state(ac); if (result) - goto end; + goto err_release_ac; psy_cfg.drv_data = ac; @@ -248,7 +247,7 @@ static int acpi_ac_add(struct acpi_device *device) &ac->charger_desc, &psy_cfg); if (IS_ERR(ac->charger)) { result = PTR_ERR(ac->charger); - goto end; + goto err_release_ac; } pr_info("%s [%s] (%s)\n", acpi_device_name(device), @@ -256,9 +255,19 @@ static int acpi_ac_add(struct acpi_device *device) ac->battery_nb.notifier_call = acpi_ac_battery_notify; register_acpi_notifier(&ac->battery_nb); -end: + + result = acpi_dev_install_notify_handler(device, ACPI_ALL_NOTIFY, + acpi_ac_notify); if (result) - kfree(ac); + goto err_unregister; + + return 0; + +err_unregister: + power_supply_unregister(ac->charger); + unregister_acpi_notifier(&ac->battery_nb); +err_release_ac: + kfree(ac); return result; } @@ -297,6 +306,8 @@ static void acpi_ac_remove(struct acpi_device *device) ac = acpi_driver_data(device); + acpi_dev_remove_notify_handler(device, ACPI_ALL_NOTIFY, + acpi_ac_notify); power_supply_unregister(ac->charger); unregister_acpi_notifier(&ac->battery_nb); diff --git a/drivers/acpi/acpi_cmos_rtc.c b/drivers/acpi/acpi_cmos_rtc.c index 4cf4aef7ce0c..9b55d1593d16 100644 --- a/drivers/acpi/acpi_cmos_rtc.c +++ b/drivers/acpi/acpi_cmos_rtc.c @@ -51,12 +51,11 @@ acpi_cmos_rtc_space_handler(u32 function, acpi_physical_address address, return AE_OK; } -static int acpi_install_cmos_rtc_space_handler(struct acpi_device *adev, - const struct acpi_device_id *id) +int acpi_install_cmos_rtc_space_handler(acpi_handle handle) { acpi_status status; - status = acpi_install_address_space_handler(adev->handle, + status = acpi_install_address_space_handler(handle, ACPI_ADR_SPACE_CMOS, &acpi_cmos_rtc_space_handler, NULL, NULL); @@ -67,18 +66,30 @@ static int acpi_install_cmos_rtc_space_handler(struct acpi_device *adev, return 1; } +EXPORT_SYMBOL_GPL(acpi_install_cmos_rtc_space_handler); -static void acpi_remove_cmos_rtc_space_handler(struct acpi_device *adev) +void acpi_remove_cmos_rtc_space_handler(acpi_handle handle) { - if (ACPI_FAILURE(acpi_remove_address_space_handler(adev->handle, + if (ACPI_FAILURE(acpi_remove_address_space_handler(handle, ACPI_ADR_SPACE_CMOS, &acpi_cmos_rtc_space_handler))) pr_err("Error removing CMOS-RTC region handler\n"); } +EXPORT_SYMBOL_GPL(acpi_remove_cmos_rtc_space_handler); + +static int acpi_cmos_rtc_attach_handler(struct acpi_device *adev, const struct acpi_device_id *id) +{ + return acpi_install_cmos_rtc_space_handler(adev->handle); +} + +static void acpi_cmos_rtc_detach_handler(struct acpi_device *adev) +{ + acpi_remove_cmos_rtc_space_handler(adev->handle); +} 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, + .attach = acpi_cmos_rtc_attach_handler, + .detach = acpi_cmos_rtc_detach_handler, }; void __init acpi_cmos_rtc_init(void) diff --git a/drivers/acpi/acpi_extlog.c b/drivers/acpi/acpi_extlog.c index e648158368a7..e120a96e1eae 100644 --- a/drivers/acpi/acpi_extlog.c +++ b/drivers/acpi/acpi_extlog.c @@ -172,7 +172,7 @@ static int extlog_print(struct notifier_block *nb, unsigned long val, fru_text = ""; sec_type = (guid_t *)gdata->section_type; if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM)) { - struct cper_sec_mem_err *mem = (void *)(gdata + 1); + struct cper_sec_mem_err *mem = acpi_hest_get_payload(gdata); if (gdata->error_data_length >= sizeof(*mem)) trace_extlog_mem_event(mem, err_seq, fru_id, fru_text, diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index f9aa02cac6d1..c711db8a9c33 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -9,9 +9,11 @@ * Copyright (C) 2013, Intel Corporation * Rafael J. Wysocki <rafael.j.wysocki@intel.com> */ +#define pr_fmt(fmt) "ACPI: " fmt #include <linux/acpi.h> #include <linux/device.h> +#include <linux/dmi.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> @@ -21,6 +23,8 @@ #include <asm/cpu.h> +#include <xen/xen.h> + #include "internal.h" DEFINE_PER_CPU(struct acpi_processor *, processors); @@ -508,54 +512,110 @@ static void acpi_processor_remove(struct acpi_device *device) } #endif /* CONFIG_ACPI_HOTPLUG_CPU */ -#ifdef CONFIG_X86 -static bool acpi_hwp_native_thermal_lvt_set; -static acpi_status __init acpi_hwp_native_thermal_lvt_osc(acpi_handle handle, - u32 lvl, - void *context, - void **rv) +#ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC +bool __init processor_physically_present(acpi_handle handle) +{ + int cpuid, type; + u32 acpi_id; + acpi_status status; + acpi_object_type acpi_type; + unsigned long long tmp; + union acpi_object object = {}; + struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; + + status = acpi_get_type(handle, &acpi_type); + if (ACPI_FAILURE(status)) + return false; + + switch (acpi_type) { + case ACPI_TYPE_PROCESSOR: + status = acpi_evaluate_object(handle, NULL, NULL, &buffer); + if (ACPI_FAILURE(status)) + return false; + acpi_id = object.processor.proc_id; + break; + case ACPI_TYPE_DEVICE: + status = acpi_evaluate_integer(handle, METHOD_NAME__UID, + NULL, &tmp); + if (ACPI_FAILURE(status)) + return false; + acpi_id = tmp; + break; + default: + return false; + } + + if (xen_initial_domain()) + /* + * When running as a Xen dom0 the number of processors Linux + * sees can be different from the real number of processors on + * the system, and we still need to execute _PDC or _OSC for + * all of them. + */ + return xen_processor_present(acpi_id); + + type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0; + cpuid = acpi_get_cpuid(handle, type, acpi_id); + + return !invalid_logical_cpuid(cpuid); +} + +/* vendor specific UUID indicating an Intel platform */ +static u8 sb_uuid_str[] = "4077A616-290C-47BE-9EBD-D87058713953"; + +static acpi_status __init acpi_processor_osc(acpi_handle handle, u32 lvl, + void *context, void **rv) { - u8 sb_uuid_str[] = "4077A616-290C-47BE-9EBD-D87058713953"; - u32 capbuf[2]; + u32 capbuf[2] = {}; struct acpi_osc_context osc_context = { .uuid_str = sb_uuid_str, .rev = 1, .cap.length = 8, .cap.pointer = capbuf, }; + acpi_status status; - if (acpi_hwp_native_thermal_lvt_set) - return AE_CTRL_TERMINATE; + if (!processor_physically_present(handle)) + return AE_OK; - capbuf[0] = 0x0000; - capbuf[1] = 0x1000; /* set bit 12 */ + arch_acpi_set_proc_cap_bits(&capbuf[OSC_SUPPORT_DWORD]); - if (ACPI_SUCCESS(acpi_run_osc(handle, &osc_context))) { - if (osc_context.ret.pointer && osc_context.ret.length > 1) { - u32 *capbuf_ret = osc_context.ret.pointer; + status = acpi_run_osc(handle, &osc_context); + if (ACPI_FAILURE(status)) + return status; - if (capbuf_ret[1] & 0x1000) { - acpi_handle_info(handle, - "_OSC native thermal LVT Acked\n"); - acpi_hwp_native_thermal_lvt_set = true; - } - } - kfree(osc_context.ret.pointer); - } + kfree(osc_context.ret.pointer); return AE_OK; } -void __init acpi_early_processor_osc(void) +static bool __init acpi_early_processor_osc(void) { - if (boot_cpu_has(X86_FEATURE_HWP)) { - acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, - acpi_hwp_native_thermal_lvt_osc, - NULL, NULL, NULL); - acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, - acpi_hwp_native_thermal_lvt_osc, - NULL, NULL); + acpi_status status; + + acpi_proc_quirk_mwait_check(); + + status = acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, acpi_processor_osc, NULL, + NULL, NULL); + if (ACPI_FAILURE(status)) + return false; + + status = acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, acpi_processor_osc, + NULL, NULL); + if (ACPI_FAILURE(status)) + return false; + + return true; +} + +void __init acpi_early_processor_control_setup(void) +{ + if (acpi_early_processor_osc()) { + pr_info("_OSC evaluated successfully for all CPUs\n"); + } else { + pr_info("_OSC evaluation for CPUs failed, trying _PDC\n"); + acpi_early_processor_set_pdc(); } } #endif diff --git a/drivers/acpi/acpi_tad.c b/drivers/acpi/acpi_tad.c index e9b8e8305e23..33c3b16af556 100644 --- a/drivers/acpi/acpi_tad.c +++ b/drivers/acpi/acpi_tad.c @@ -557,6 +557,7 @@ static int acpi_tad_disable_timer(struct device *dev, u32 timer_id) static int acpi_tad_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; + acpi_handle handle = ACPI_HANDLE(dev); struct acpi_tad_driver_data *dd = dev_get_drvdata(dev); device_init_wakeup(dev, false); @@ -577,6 +578,7 @@ static int acpi_tad_remove(struct platform_device *pdev) pm_runtime_put_sync(dev); pm_runtime_disable(dev); + acpi_remove_cmos_rtc_space_handler(handle); return 0; } @@ -589,6 +591,11 @@ static int acpi_tad_probe(struct platform_device *pdev) unsigned long long caps; int ret; + ret = acpi_install_cmos_rtc_space_handler(handle); + if (ret < 0) { + dev_info(dev, "Unable to install space handler\n"); + return -ENODEV; + } /* * Initialization failure messages are mostly about firmware issues, so * print them at the "info" level. @@ -596,22 +603,27 @@ static int acpi_tad_probe(struct platform_device *pdev) status = acpi_evaluate_integer(handle, "_GCP", NULL, &caps); if (ACPI_FAILURE(status)) { dev_info(dev, "Unable to get capabilities\n"); - return -ENODEV; + ret = -ENODEV; + goto remove_handler; } if (!(caps & ACPI_TAD_AC_WAKE)) { dev_info(dev, "Unsupported capabilities\n"); - return -ENODEV; + ret = -ENODEV; + goto remove_handler; } if (!acpi_has_method(handle, "_PRW")) { dev_info(dev, "Missing _PRW\n"); - return -ENODEV; + ret = -ENODEV; + goto remove_handler; } dd = devm_kzalloc(dev, sizeof(*dd), GFP_KERNEL); - if (!dd) - return -ENOMEM; + if (!dd) { + ret = -ENOMEM; + goto remove_handler; + } dd->capabilities = caps; dev_set_drvdata(dev, dd); @@ -653,6 +665,11 @@ static int acpi_tad_probe(struct platform_device *pdev) fail: acpi_tad_remove(pdev); + /* Don't fallthrough because cmos rtc space handler is removed in acpi_tad_remove() */ + return ret; + +remove_handler: + acpi_remove_cmos_rtc_space_handler(handle); return ret; } diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index 62f4364e4460..948e31f7ce6e 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -77,7 +77,7 @@ static DEFINE_MUTEX(video_list_lock); static LIST_HEAD(video_bus_head); static int acpi_video_bus_add(struct acpi_device *device); static void acpi_video_bus_remove(struct acpi_device *device); -static void acpi_video_bus_notify(struct acpi_device *device, u32 event); +static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data); /* * Indices in the _BCL method response: the first two items are special, @@ -104,7 +104,6 @@ static struct acpi_driver acpi_video_bus = { .ops = { .add = acpi_video_bus_add, .remove = acpi_video_bus_remove, - .notify = acpi_video_bus_notify, }, }; @@ -1527,8 +1526,9 @@ static int acpi_video_bus_stop_devices(struct acpi_video_bus *video) acpi_osi_is_win8() ? 0 : 1); } -static void acpi_video_bus_notify(struct acpi_device *device, u32 event) +static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) { + struct acpi_device *device = data; struct acpi_video_bus *video = acpi_driver_data(device); struct input_dev *input; int keycode = 0; @@ -2027,6 +2027,12 @@ static int acpi_video_bus_add(struct acpi_device *device) if (error) goto err_put_video; + /* + * HP ZBook Fury 16 G10 requires ACPI video's child devices have _PS0 + * evaluated to have functional panel brightness control. + */ + acpi_device_fix_up_power_extended(device); + pr_info("%s [%s] (multi-head: %s rom: %s post: %s)\n", ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), video->flags.multihead ? "yes" : "no", @@ -2053,8 +2059,19 @@ static int acpi_video_bus_add(struct acpi_device *device) acpi_video_bus_add_notify_handler(video); + error = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY, + acpi_video_bus_notify); + if (error) + goto err_remove; + return 0; +err_remove: + mutex_lock(&video_list_lock); + list_del(&video->entry); + mutex_unlock(&video_list_lock); + acpi_video_bus_remove_notify_handler(video); + acpi_video_bus_unregister_backlight(video); err_put_video: acpi_video_bus_put_devices(video); kfree(video->attached_array); @@ -2075,6 +2092,9 @@ static void acpi_video_bus_remove(struct acpi_device *device) video = acpi_driver_data(device); + acpi_dev_remove_notify_handler(device, ACPI_DEVICE_NOTIFY, + acpi_video_bus_notify); + mutex_lock(&video_list_lock); list_del(&video->entry); mutex_unlock(&video_list_lock); diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 22f1f7a9e5a3..911875c5a5f1 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -287,4 +287,6 @@ struct acpi_namespace_node *acpi_db_local_ns_lookup(char *name); void acpi_db_uint32_to_hex_string(u32 value, char *buffer); +void acpi_db_generate_interrupt(char *gsiv_arg); + #endif /* __ACDEBUG_H__ */ diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 778241173ed4..f4c90fc99be2 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -129,6 +129,7 @@ ACPI_GLOBAL(acpi_table_handler, acpi_gbl_table_handler); ACPI_GLOBAL(void *, acpi_gbl_table_handler_context); ACPI_GLOBAL(acpi_interface_handler, acpi_gbl_interface_handler); ACPI_GLOBAL(struct acpi_sci_handler_info *, acpi_gbl_sci_handler_list); +ACPI_GLOBAL(struct acpi_ged_handler_info *, acpi_gbl_ged_handler_list); /* Owner ID support */ diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 12d4a024f029..82563b44af35 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -543,6 +543,14 @@ struct acpi_field_info { u32 pkg_length; }; +/* Information about the interrupt ID and _EVT of a GED device */ + +struct acpi_ged_handler_info { + struct acpi_ged_handler_info *next; + u32 int_id; /* The interrupt ID that triggers the execution ofthe evt_method. */ + struct acpi_namespace_node *evt_method; /* The _EVT method to be executed when an interrupt with ID = int_ID is received */ +}; + /***************************************************************************** * * Generic "state" object for stacks @@ -560,25 +568,28 @@ struct acpi_field_info { u8 descriptor_type; /* To differentiate various internal objs */\ u8 flags; \ u16 value; \ - u16 state; + u16 state /* There are 2 bytes available here until the next natural alignment boundary */ struct acpi_common_state { -ACPI_STATE_COMMON}; + ACPI_STATE_COMMON; +}; /* * Update state - used to traverse complex objects such as packages */ struct acpi_update_state { - ACPI_STATE_COMMON union acpi_operand_object *object; + ACPI_STATE_COMMON; + union acpi_operand_object *object; }; /* * Pkg state - used to traverse nested package structures */ struct acpi_pkg_state { - ACPI_STATE_COMMON u32 index; + ACPI_STATE_COMMON; + u32 index; union acpi_operand_object *source_object; union acpi_operand_object *dest_object; struct acpi_walk_state *walk_state; @@ -591,7 +602,8 @@ struct acpi_pkg_state { * Allows nesting of these constructs */ struct acpi_control_state { - ACPI_STATE_COMMON u16 opcode; + ACPI_STATE_COMMON; + u16 opcode; union acpi_parse_object *predicate_op; u8 *aml_predicate_start; /* Start of if/while predicate */ u8 *package_end; /* End of if/while block */ @@ -602,11 +614,13 @@ struct acpi_control_state { * Scope state - current scope during namespace lookups */ struct acpi_scope_state { - ACPI_STATE_COMMON struct acpi_namespace_node *node; + ACPI_STATE_COMMON; + struct acpi_namespace_node *node; }; struct acpi_pscope_state { - ACPI_STATE_COMMON u32 arg_count; /* Number of fixed arguments */ + ACPI_STATE_COMMON; + u32 arg_count; /* Number of fixed arguments */ union acpi_parse_object *op; /* Current op being parsed */ u8 *arg_end; /* Current argument end */ u8 *pkg_end; /* Current package end */ @@ -618,7 +632,8 @@ struct acpi_pscope_state { * states are created when there are nested control methods executing. */ struct acpi_thread_state { - ACPI_STATE_COMMON u8 current_sync_level; /* Mutex Sync (nested acquire) level */ + ACPI_STATE_COMMON; + u8 current_sync_level; /* Mutex Sync (nested acquire) level */ struct acpi_walk_state *walk_state_list; /* Head of list of walk_states for this thread */ union acpi_operand_object *acquired_mutex_list; /* List of all currently acquired mutexes */ acpi_thread_id thread_id; /* Running thread ID */ @@ -629,8 +644,8 @@ struct acpi_thread_state { * AML arguments */ struct acpi_result_values { - ACPI_STATE_COMMON - union acpi_operand_object *obj_desc[ACPI_RESULTS_FRAME_OBJ_NUM]; + ACPI_STATE_COMMON; + union acpi_operand_object *obj_desc[ACPI_RESULTS_FRAME_OBJ_NUM]; }; typedef @@ -652,7 +667,8 @@ struct acpi_global_notify_handler { * handler/dispatcher. */ struct acpi_notify_info { - ACPI_STATE_COMMON u8 handler_list_id; + ACPI_STATE_COMMON; + u8 handler_list_id; struct acpi_namespace_node *node; union acpi_operand_object *handler_list_head; struct acpi_global_notify_handler *global; diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h index e64aabe3d33a..2e442f5a3123 100644 --- a/drivers/acpi/acpica/acpredef.h +++ b/drivers/acpi/acpica/acpredef.h @@ -440,6 +440,9 @@ const union acpi_predefined_info acpi_gbl_predefined_methods[] = { {{"_DOS", METHOD_1ARGS(ACPI_TYPE_INTEGER), METHOD_NO_RETURN_VALUE}}, + {{"_DSC", METHOD_0ARGS, + METHOD_RETURNS(ACPI_RTYPE_INTEGER)}}, + {{"_DSD", METHOD_0ARGS, /* ACPI 6.0 */ METHOD_RETURNS(ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each: 1 Buf, 1 Pkg */ PACKAGE_INFO(ACPI_PTYPE2_UUID_PAIR, ACPI_RTYPE_BUFFER, 1, diff --git a/drivers/acpi/acpica/dbcmds.c b/drivers/acpi/acpica/dbcmds.c index 9eb68e0751c7..3d99a9048585 100644 --- a/drivers/acpi/acpica/dbcmds.c +++ b/drivers/acpi/acpica/dbcmds.c @@ -1010,6 +1010,64 @@ void acpi_db_display_resources(char *object_arg) acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); } +/******************************************************************************* + * + * FUNCTION: acpi_db_generate_ged + * + * PARAMETERS: ged_arg - Raw GED number, ascii string + * + * RETURN: None + * + * DESCRIPTION: Simulate firing of a GED + * + ******************************************************************************/ + +void acpi_db_generate_interrupt(char *gsiv_arg) +{ + u32 gsiv_number; + struct acpi_ged_handler_info *ged_info = acpi_gbl_ged_handler_list; + + if (!ged_info) { + acpi_os_printf("No GED handling present\n"); + } + + gsiv_number = strtoul(gsiv_arg, NULL, 0); + + while (ged_info) { + + if (ged_info->int_id == gsiv_number) { + struct acpi_object_list arg_list; + union acpi_object arg0; + acpi_handle evt_handle = ged_info->evt_method; + acpi_status status; + + acpi_os_printf("Evaluate GED _EVT (GSIV=%d)\n", + gsiv_number); + + if (!evt_handle) { + acpi_os_printf("Undefined _EVT method\n"); + return; + } + + arg0.integer.type = ACPI_TYPE_INTEGER; + arg0.integer.value = gsiv_number; + + arg_list.count = 1; + arg_list.pointer = &arg0; + + status = + acpi_evaluate_object(evt_handle, NULL, &arg_list, + NULL); + if (ACPI_FAILURE(status)) { + acpi_os_printf("Could not evaluate _EVT\n"); + return; + } + + } + ged_info = ged_info->next; + } +} + #if (!ACPI_REDUCED_HARDWARE) /******************************************************************************* * diff --git a/drivers/acpi/acpica/dbinput.c b/drivers/acpi/acpica/dbinput.c index b8a48923064f..861b12c334ab 100644 --- a/drivers/acpi/acpica/dbinput.c +++ b/drivers/acpi/acpica/dbinput.c @@ -106,6 +106,7 @@ enum acpi_ex_debugger_commands { CMD_THREADS, CMD_TEST, + CMD_INTERRUPT, #endif }; @@ -185,6 +186,7 @@ static const struct acpi_db_command_info acpi_gbl_db_commands[] = { {"THREADS", 3}, {"TEST", 1}, + {"INTERRUPT", 1}, #endif {NULL, 0} }; @@ -318,6 +320,7 @@ static const struct acpi_db_command_help acpi_gbl_db_command_help[] = { {1, " Gpes", "Display info on all GPE devices\n"}, {1, " Sci", "Generate an SCI\n"}, {1, " Sleep [SleepState]", "Simulate sleep/wake sequence(s) (0-5)\n"}, + {1, " Interrupt <GSIV>", "Simulate an interrupt\n"}, #endif {0, NULL, NULL} }; @@ -1064,6 +1067,11 @@ acpi_db_command_dispatch(char *input_buffer, acpi_os_printf("Event command not implemented\n"); break; + case CMD_INTERRUPT: + + acpi_db_generate_interrupt(acpi_gbl_db_args[1]); + break; + case CMD_GPE: acpi_db_generate_gpe(acpi_gbl_db_args[1], acpi_gbl_db_args[2]); diff --git a/drivers/acpi/acpica/dswstate.c b/drivers/acpi/acpica/dswstate.c index d3841ded3a81..75338a13c802 100644 --- a/drivers/acpi/acpica/dswstate.c +++ b/drivers/acpi/acpica/dswstate.c @@ -146,8 +146,8 @@ acpi_ds_result_push(union acpi_operand_object *object, if (!object) { ACPI_ERROR((AE_INFO, - "Null Object! Obj=%p State=%p Num=%u", - object, walk_state, walk_state->result_count)); + "Null Object! State=%p Num=%u", + walk_state, walk_state->result_count)); return (AE_BAD_PARAMETER); } diff --git a/drivers/acpi/acpica/exserial.c b/drivers/acpi/acpica/exserial.c index 5d99b1a76c83..5241f4c01c76 100644 --- a/drivers/acpi/acpica/exserial.c +++ b/drivers/acpi/acpica/exserial.c @@ -343,8 +343,7 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc, /* Copy the input buffer data to the transfer buffer */ buffer = buffer_desc->buffer.pointer; - data_length = (buffer_length < source_desc->buffer.length ? - buffer_length : source_desc->buffer.length); + data_length = ACPI_MIN(buffer_length, source_desc->buffer.length); memcpy(buffer, source_desc->buffer.pointer, data_length); /* Lock entire transaction if requested */ diff --git a/drivers/acpi/acpica/psopcode.c b/drivers/acpi/acpica/psopcode.c index 09029fe545f1..39e31030e5f4 100644 --- a/drivers/acpi/acpica/psopcode.c +++ b/drivers/acpi/acpica/psopcode.c @@ -603,7 +603,7 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { /* 7E */ ACPI_OP("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R, - AML_FLAGS_EXEC_0A_0T_1R), + AML_FLAGS_EXEC_0A_0T_1R | AML_NO_OPERAND_RESOLVE), /* ACPI 5.0 opcodes */ diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index 1bbba8585fa6..c5f6c85a3a09 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -37,7 +37,12 @@ void acpi_ut_init_stack_ptr_trace(void) { acpi_size current_sp; +#pragma GCC diagnostic push +#if defined(__GNUC__) && __GNUC__ >= 12 +#pragma GCC diagnostic ignored "-Wdangling-pointer=" +#endif acpi_gbl_entry_stack_pointer = ¤t_sp; +#pragma GCC diagnostic pop } /******************************************************************************* diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile index f81fe24894b2..143debc1ba4a 100644 --- a/drivers/acpi/arm64/Makefile +++ b/drivers/acpi/arm64/Makefile @@ -3,4 +3,5 @@ obj-$(CONFIG_ACPI_AGDI) += agdi.o obj-$(CONFIG_ACPI_IORT) += iort.o obj-$(CONFIG_ACPI_GTDT) += gtdt.o obj-$(CONFIG_ACPI_APMT) += apmt.o +obj-$(CONFIG_ARM_AMBA) += amba.o obj-y += dma.o init.o diff --git a/drivers/acpi/acpi_amba.c b/drivers/acpi/arm64/amba.c index f5b443ab01c2..b2a7631d7ac7 100644 --- a/drivers/acpi/acpi_amba.c +++ b/drivers/acpi/arm64/amba.c @@ -17,7 +17,7 @@ #include <linux/kernel.h> #include <linux/module.h> -#include "internal.h" +#include "init.h" static const struct acpi_device_id amba_id_list[] = { {"ARMH0061", 0}, /* PL061 GPIO Device */ diff --git a/drivers/acpi/arm64/init.c b/drivers/acpi/arm64/init.c index d3ce53dda122..d0c8aed90fd1 100644 --- a/drivers/acpi/arm64/init.c +++ b/drivers/acpi/arm64/init.c @@ -10,4 +10,6 @@ void __init acpi_arm_init(void) acpi_apmt_init(); if (IS_ENABLED(CONFIG_ACPI_IORT)) acpi_iort_init(); + if (IS_ENABLED(CONFIG_ARM_AMBA)) + acpi_amba_init(); } diff --git a/drivers/acpi/arm64/init.h b/drivers/acpi/arm64/init.h index a1715a2a34e9..dcc277977194 100644 --- a/drivers/acpi/arm64/init.h +++ b/drivers/acpi/arm64/init.h @@ -4,3 +4,4 @@ void __init acpi_agdi_init(void); void __init acpi_apmt_init(void); void __init acpi_iort_init(void); +void __init acpi_amba_init(void); diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c index 56d887323ae5..6496ff5a6ba2 100644 --- a/drivers/acpi/arm64/iort.c +++ b/drivers/acpi/arm64/iort.c @@ -1708,7 +1708,10 @@ static void __init arm_smmu_v3_pmcg_init_resources(struct resource *res, static struct acpi_platform_list pmcg_plat_info[] __initdata = { /* HiSilicon Hip08 Platform */ {"HISI ", "HIP08 ", 0, ACPI_SIG_IORT, greater_than_or_equal, - "Erratum #162001800", IORT_SMMU_V3_PMCG_HISI_HIP08}, + "Erratum #162001800, Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP08}, + /* HiSilicon Hip09 Platform */ + {"HISI ", "HIP09 ", 0, ACPI_SIG_IORT, greater_than_or_equal, + "Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09}, { } }; diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 9c67ed02d797..969bf81e8d54 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -1034,8 +1034,9 @@ static void acpi_battery_refresh(struct acpi_battery *battery) } /* Driver Interface */ -static void acpi_battery_notify(struct acpi_device *device, u32 event) +static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) { + struct acpi_device *device = data; struct acpi_battery *battery = acpi_driver_data(device); struct power_supply *old; @@ -1212,13 +1213,22 @@ static int acpi_battery_add(struct acpi_device *device) device_init_wakeup(&device->dev, 1); - return result; + result = acpi_dev_install_notify_handler(device, ACPI_ALL_NOTIFY, + acpi_battery_notify); + if (result) + goto fail_pm; + + return 0; +fail_pm: + device_init_wakeup(&device->dev, 0); + unregister_pm_notifier(&battery->pm_nb); fail: sysfs_remove_battery(battery); mutex_destroy(&battery->lock); mutex_destroy(&battery->sysfs_lock); kfree(battery); + return result; } @@ -1228,10 +1238,16 @@ static void acpi_battery_remove(struct acpi_device *device) if (!device || !acpi_driver_data(device)) return; - device_init_wakeup(&device->dev, 0); + battery = acpi_driver_data(device); + + acpi_dev_remove_notify_handler(device, ACPI_ALL_NOTIFY, + acpi_battery_notify); + + device_init_wakeup(&device->dev, 0); unregister_pm_notifier(&battery->pm_nb); sysfs_remove_battery(battery); + mutex_destroy(&battery->lock); mutex_destroy(&battery->sysfs_lock); kfree(battery); @@ -1264,11 +1280,9 @@ static struct acpi_driver acpi_battery_driver = { .name = "battery", .class = ACPI_BATTERY_CLASS, .ids = battery_device_ids, - .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, .ops = { .add = acpi_battery_add, .remove = acpi_battery_remove, - .notify = acpi_battery_notify, }, .drv.pm = &acpi_battery_pm, }; diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 2fc2b43a4ed3..f41dda2d3493 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -554,6 +554,30 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device, acpi_os_wait_events_complete(); } +int acpi_dev_install_notify_handler(struct acpi_device *adev, + u32 handler_type, + acpi_notify_handler handler) +{ + acpi_status status; + + status = acpi_install_notify_handler(adev->handle, handler_type, + handler, adev); + if (ACPI_FAILURE(status)) + return -ENODEV; + + return 0; +} +EXPORT_SYMBOL_GPL(acpi_dev_install_notify_handler); + +void acpi_dev_remove_notify_handler(struct acpi_device *adev, + u32 handler_type, + acpi_notify_handler handler) +{ + acpi_remove_notify_handler(adev->handle, handler_type, handler); + acpi_os_wait_events_complete(); +} +EXPORT_SYMBOL_GPL(acpi_dev_remove_notify_handler); + /* Handle events targeting \_SB device (at present only graceful shutdown) */ #define ACPI_SB_NOTIFY_SHUTDOWN_REQUEST 0x81 @@ -1005,8 +1029,10 @@ static int acpi_device_probe(struct device *dev) return -ENOSYS; ret = acpi_drv->ops.add(acpi_dev); - if (ret) + if (ret) { + acpi_dev->driver_data = NULL; return ret; + } pr_debug("Driver [%s] successfully bound to device [%s]\n", acpi_drv->name, acpi_dev->pnp.bus_id); @@ -1296,9 +1322,6 @@ static int __init acpi_bus_init(void) goto error1; } - /* Set capability bits for _OSC under processor scope */ - acpi_early_processor_osc(); - /* * _OSC method may exist in module level code, * so it must be run after ACPI_FULL_INITIALIZATION @@ -1314,7 +1337,7 @@ static int __init acpi_bus_init(void) acpi_sysfs_init(); - acpi_early_processor_set_pdc(); + acpi_early_processor_control_setup(); /* * Maybe EC region is required at bus_scan/acpi_get_devices. So it diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c index 78d44e3fe129..46c6f8c35b43 100644 --- a/drivers/acpi/hed.c +++ b/drivers/acpi/hed.c @@ -42,22 +42,32 @@ EXPORT_SYMBOL_GPL(unregister_acpi_hed_notifier); * it is used by HEST Generic Hardware Error Source with notify type * SCI. */ -static void acpi_hed_notify(struct acpi_device *device, u32 event) +static void acpi_hed_notify(acpi_handle handle, u32 event, void *data) { blocking_notifier_call_chain(&acpi_hed_notify_list, 0, NULL); } static int acpi_hed_add(struct acpi_device *device) { + int err; + /* Only one hardware error device */ if (hed_handle) return -EINVAL; hed_handle = device->handle; - return 0; + + err = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY, + acpi_hed_notify); + if (err) + hed_handle = NULL; + + return err; } static void acpi_hed_remove(struct acpi_device *device) { + acpi_dev_remove_notify_handler(device, ACPI_DEVICE_NOTIFY, + acpi_hed_notify); hed_handle = NULL; } @@ -68,7 +78,6 @@ static struct acpi_driver acpi_hed_driver = { .ops = { .add = acpi_hed_add, .remove = acpi_hed_remove, - .notify = acpi_hed_notify, }, }; module_acpi_driver(acpi_hed_driver); diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index f4148dc50b9c..866c7c4ed233 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -28,11 +28,6 @@ void acpi_processor_init(void); void acpi_platform_init(void); void acpi_pnp_init(void); void acpi_int340x_thermal_init(void); -#ifdef CONFIG_ARM_AMBA -void acpi_amba_init(void); -#else -static inline void acpi_amba_init(void) {} -#endif int acpi_sysfs_init(void); void acpi_gpe_apply_masked_gpes(void); void acpi_container_init(void); @@ -128,7 +123,6 @@ int __acpi_device_uevent_modalias(const struct acpi_device *adev, /* -------------------------------------------------------------------------- Power Resource -------------------------------------------------------------------------- */ -int acpi_power_init(void); void acpi_power_resources_list_free(struct list_head *list); int acpi_extract_power_resources(union acpi_object *package, unsigned int start, struct list_head *list); @@ -152,15 +146,13 @@ int acpi_wakeup_device_init(void); Processor -------------------------------------------------------------------------- */ #ifdef CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC +void acpi_early_processor_control_setup(void); void acpi_early_processor_set_pdc(void); -#else -static inline void acpi_early_processor_set_pdc(void) {} -#endif -#ifdef CONFIG_X86 -void acpi_early_processor_osc(void); +void acpi_proc_quirk_mwait_check(void); +bool processor_physically_present(acpi_handle handle); #else -static inline void acpi_early_processor_osc(void) {} +static inline void acpi_early_processor_control_setup(void) {} #endif /* -------------------------------------------------------------------------- diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index 07204d482968..f0e6738ae3c9 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -3282,6 +3282,23 @@ static void acpi_nfit_put_table(void *table) acpi_put_table(table); } +static void acpi_nfit_notify(acpi_handle handle, u32 event, void *data) +{ + struct acpi_device *adev = data; + + device_lock(&adev->dev); + __acpi_nfit_notify(&adev->dev, handle, event); + device_unlock(&adev->dev); +} + +static void acpi_nfit_remove_notify_handler(void *data) +{ + struct acpi_device *adev = data; + + acpi_dev_remove_notify_handler(adev, ACPI_DEVICE_NOTIFY, + acpi_nfit_notify); +} + void acpi_nfit_shutdown(void *data) { struct acpi_nfit_desc *acpi_desc = data; @@ -3368,12 +3385,18 @@ static int acpi_nfit_add(struct acpi_device *adev) if (rc) return rc; - return devm_add_action_or_reset(dev, acpi_nfit_shutdown, acpi_desc); -} -static void acpi_nfit_remove(struct acpi_device *adev) -{ - /* see acpi_nfit_unregister */ + rc = devm_add_action_or_reset(dev, acpi_nfit_shutdown, acpi_desc); + if (rc) + return rc; + + rc = acpi_dev_install_notify_handler(adev, ACPI_DEVICE_NOTIFY, + acpi_nfit_notify); + if (rc) + return rc; + + return devm_add_action_or_reset(dev, acpi_nfit_remove_notify_handler, + adev); } static void acpi_nfit_update_notify(struct device *dev, acpi_handle handle) @@ -3446,13 +3469,6 @@ void __acpi_nfit_notify(struct device *dev, acpi_handle handle, u32 event) } EXPORT_SYMBOL_GPL(__acpi_nfit_notify); -static void acpi_nfit_notify(struct acpi_device *adev, u32 event) -{ - device_lock(&adev->dev); - __acpi_nfit_notify(&adev->dev, adev->handle, event); - device_unlock(&adev->dev); -} - static const struct acpi_device_id acpi_nfit_ids[] = { { "ACPI0012", 0 }, { "", 0 }, @@ -3464,8 +3480,6 @@ static struct acpi_driver acpi_nfit_driver = { .ids = acpi_nfit_ids, .ops = { .add = acpi_nfit_add, - .remove = acpi_nfit_remove, - .notify = acpi_nfit_notify, }, }; diff --git a/drivers/acpi/prmt.c b/drivers/acpi/prmt.c index 3d4c4620f9f9..7020584096bf 100644 --- a/drivers/acpi/prmt.c +++ b/drivers/acpi/prmt.c @@ -53,7 +53,7 @@ static LIST_HEAD(prm_module_list); struct prm_handler_info { guid_t guid; - void *handler_addr; + efi_status_t (__efiapi *handler_addr)(u64, void *); u64 static_data_buffer_addr; u64 acpi_param_buffer_addr; @@ -260,9 +260,9 @@ static acpi_status acpi_platformrt_space_handler(u32 function, context.static_data_buffer = handler->static_data_buffer_addr; context.mmio_ranges = module->mmio_info; - status = efi_call_virt_pointer(handler, handler_addr, - handler->acpi_param_buffer_addr, - &context); + status = efi_call_acpi_prm_handler(handler->handler_addr, + handler->acpi_param_buffer_addr, + &context); if (status == EFI_SUCCESS) { buffer->prm_status = PRM_HANDLER_SUCCESS; } else { diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index d6606a9f2da6..7dd6dbaa98c3 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -132,6 +132,30 @@ static int map_rintc_hartid(struct acpi_subtable_header *entry, return -EINVAL; } +/* + * Retrieve LoongArch CPU physical id + */ +static int map_core_pic_id(struct acpi_subtable_header *entry, + int device_declaration, u32 acpi_id, phys_cpuid_t *phys_id) +{ + struct acpi_madt_core_pic *core_pic = + container_of(entry, struct acpi_madt_core_pic, header); + + if (!(core_pic->flags & ACPI_MADT_ENABLED)) + return -ENODEV; + + /* device_declaration means Device object in DSDT, in LoongArch + * system, logical processor acpi_id is required in _UID property + * of DSDT table, so we should check device_declaration here + */ + if (device_declaration && (core_pic->processor_id == acpi_id)) { + *phys_id = core_pic->core_id; + return 0; + } + + return -EINVAL; +} + static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt, int type, u32 acpi_id) { @@ -165,6 +189,9 @@ static phys_cpuid_t map_madt_entry(struct acpi_table_madt *madt, } else if (header->type == ACPI_MADT_TYPE_RINTC) { if (!map_rintc_hartid(header, type, acpi_id, &phys_id)) break; + } else if (header->type == ACPI_MADT_TYPE_CORE_PIC) { + if (!map_core_pic_id(header, type, acpi_id, &phys_id)) + break; } entry += header->length; } @@ -216,6 +243,8 @@ static phys_cpuid_t map_mat_entry(acpi_handle handle, int type, u32 acpi_id) map_x2apic_id(header, type, acpi_id, &phys_id); else if (header->type == ACPI_MADT_TYPE_GENERIC_INTERRUPT) map_gicc_mpidr(header, type, acpi_id, &phys_id); + else if (header->type == ACPI_MADT_TYPE_CORE_PIC) + map_core_pic_id(header, type, acpi_id, &phys_id); exit: kfree(buffer.pointer); diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 18fb04523f93..1a8591e9a9bf 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -9,71 +9,19 @@ #define pr_fmt(fmt) "ACPI: " fmt -#include <linux/dmi.h> #include <linux/slab.h> #include <linux/acpi.h> #include <acpi/processor.h> -#include <xen/xen.h> - #include "internal.h" -static bool __init processor_physically_present(acpi_handle handle) -{ - int cpuid, type; - u32 acpi_id; - acpi_status status; - acpi_object_type acpi_type; - unsigned long long tmp; - union acpi_object object = { 0 }; - struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; - - status = acpi_get_type(handle, &acpi_type); - if (ACPI_FAILURE(status)) - return false; - - switch (acpi_type) { - case ACPI_TYPE_PROCESSOR: - status = acpi_evaluate_object(handle, NULL, NULL, &buffer); - if (ACPI_FAILURE(status)) - return false; - acpi_id = object.processor.proc_id; - break; - case ACPI_TYPE_DEVICE: - status = acpi_evaluate_integer(handle, "_UID", NULL, &tmp); - if (ACPI_FAILURE(status)) - return false; - acpi_id = tmp; - break; - default: - return false; - } - - if (xen_initial_domain()) - /* - * When running as a Xen dom0 the number of processors Linux - * sees can be different from the real number of processors on - * the system, and we still need to execute _PDC for all of - * them. - */ - return xen_processor_present(acpi_id); - - type = (acpi_type == ACPI_TYPE_DEVICE) ? 1 : 0; - cpuid = acpi_get_cpuid(handle, type, acpi_id); - - return !invalid_logical_cpuid(cpuid); -} - static void acpi_set_pdc_bits(u32 *buf) { buf[0] = ACPI_PDC_REVISION_ID; buf[1] = 1; - /* Enable coordination with firmware's _TSD info */ - buf[2] = ACPI_PDC_SMP_T_SWCOORD; - /* Twiddle arch-specific bits needed for _PDC */ - arch_acpi_set_pdc_bits(buf); + arch_acpi_set_proc_cap_bits(&buf[2]); } static struct acpi_object_list *acpi_processor_alloc_pdc(void) @@ -123,20 +71,6 @@ acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) { acpi_status status = AE_OK; - if (boot_option_idle_override == IDLE_NOMWAIT) { - /* - * If mwait is disabled for CPU C-states, the C2C3_FFH access - * mode will be disabled in the parameter of _PDC object. - * Of course C1_FFH access mode will also be disabled. - */ - union acpi_object *obj; - u32 *buffer = NULL; - - obj = pdc_in->pointer; - buffer = (u32 *)(obj->buffer.pointer); - buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); - - } status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL); if (ACPI_FAILURE(status)) @@ -174,36 +108,9 @@ early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; } -static int __init set_no_mwait(const struct dmi_system_id *id) -{ - pr_notice("%s detected - disabling mwait for CPU C-states\n", - id->ident); - boot_option_idle_override = IDLE_NOMWAIT; - return 0; -} - -static const struct dmi_system_id processor_idle_dmi_table[] __initconst = { - { - set_no_mwait, "Extensa 5220", { - DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), - DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL}, - {}, -}; - -static void __init processor_dmi_check(void) -{ - /* - * Check whether the system is DMI table. If yes, OSPM - * should not use mwait for CPU-states. - */ - dmi_check_system(processor_idle_dmi_table); -} - void __init acpi_early_processor_set_pdc(void) { - processor_dmi_check(); + acpi_proc_quirk_mwait_check(); acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 87e385542576..531a9e3df717 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -795,6 +795,9 @@ static const char * const acpi_ignore_dep_ids[] = { /* List of HIDs for which we honor deps of matching ACPI devs, when checking _DEP lists. */ static const char * const acpi_honor_dep_ids[] = { "INT3472", /* Camera sensor PMIC / clk and regulator info */ + "INTC1059", /* IVSC (TGL) driver must be loaded to allow i2c access to camera sensors */ + "INTC1095", /* IVSC (ADL) driver must be loaded to allow i2c access to camera sensors */ + "INTC100A", /* IVSC (RPL) driver must be loaded to allow i2c access to camera sensors */ NULL }; @@ -2616,7 +2619,6 @@ void __init acpi_scan_init(void) acpi_watchdog_init(); acpi_pnp_init(); acpi_int340x_thermal_init(); - acpi_amba_init(); acpi_init_lpit(); acpi_scan_add_handler(&generic_device_handler); diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index f9f6ebb08fdb..419590f41ed5 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -82,10 +82,6 @@ static int tzp; module_param(tzp, int, 0444); MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds."); -static int nocrt; -module_param(nocrt, int, 0); -MODULE_PARM_DESC(nocrt, "Set to take no action upon ACPI thermal zone critical trips points."); - static int off; module_param(off, int, 0); MODULE_PARM_DESC(off, "Set to disable ACPI thermal support."); @@ -96,35 +92,27 @@ MODULE_PARM_DESC(psv, "Disable or override all passive trip points."); static struct workqueue_struct *acpi_thermal_pm_queue; -struct acpi_thermal_critical { - unsigned long temperature; - bool valid; -}; - -struct acpi_thermal_hot { +struct acpi_thermal_trip { unsigned long temperature; bool valid; }; struct acpi_thermal_passive { + struct acpi_thermal_trip trip; struct acpi_handle_list devices; - unsigned long temperature; unsigned long tc1; unsigned long tc2; unsigned long tsp; - bool valid; }; struct acpi_thermal_active { + struct acpi_thermal_trip trip; struct acpi_handle_list devices; - unsigned long temperature; - bool valid; - bool enabled; }; struct acpi_thermal_trips { - struct acpi_thermal_critical critical; - struct acpi_thermal_hot hot; + struct acpi_thermal_trip critical; + struct acpi_thermal_trip hot; struct acpi_thermal_passive passive; struct acpi_thermal_active active[ACPI_THERMAL_MAX_ACTIVE]; }; @@ -137,6 +125,7 @@ struct acpi_thermal { unsigned long polling_frequency; volatile u8 zombie; struct acpi_thermal_trips trips; + struct thermal_trip *trip_table; struct acpi_handle_list devices; struct thermal_zone_device *thermal_zone; int kelvin_offset; /* in millidegrees */ @@ -190,7 +179,16 @@ static int acpi_thermal_get_polling_frequency(struct acpi_thermal *tz) return 0; } -static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) +static int acpi_thermal_temp(struct acpi_thermal *tz, int temp_deci_k) +{ + if (temp_deci_k == THERMAL_TEMP_INVALID) + return THERMAL_TEMP_INVALID; + + return deci_kelvin_to_millicelsius_with_offset(temp_deci_k, + tz->kelvin_offset); +} + +static void __acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) { acpi_status status; unsigned long long tmp; @@ -255,9 +253,9 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) } /* Passive (optional) */ - if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.valid) || + if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.trip.valid) || flag == ACPI_TRIPS_INIT) { - valid = tz->trips.passive.valid; + valid = tz->trips.passive.trip.valid; if (psv == -1) { status = AE_SUPPORT; } else if (psv > 0) { @@ -269,44 +267,44 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) } if (ACPI_FAILURE(status)) { - tz->trips.passive.valid = false; + tz->trips.passive.trip.valid = false; } else { - tz->trips.passive.temperature = tmp; - tz->trips.passive.valid = true; + tz->trips.passive.trip.temperature = tmp; + tz->trips.passive.trip.valid = true; if (flag == ACPI_TRIPS_INIT) { status = acpi_evaluate_integer(tz->device->handle, "_TC1", NULL, &tmp); if (ACPI_FAILURE(status)) - tz->trips.passive.valid = false; + tz->trips.passive.trip.valid = false; else tz->trips.passive.tc1 = tmp; status = acpi_evaluate_integer(tz->device->handle, "_TC2", NULL, &tmp); if (ACPI_FAILURE(status)) - tz->trips.passive.valid = false; + tz->trips.passive.trip.valid = false; else tz->trips.passive.tc2 = tmp; status = acpi_evaluate_integer(tz->device->handle, "_TSP", NULL, &tmp); if (ACPI_FAILURE(status)) - tz->trips.passive.valid = false; + tz->trips.passive.trip.valid = false; else tz->trips.passive.tsp = tmp; } } } - if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.valid) { + if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.trip.valid) { memset(&devices, 0, sizeof(struct acpi_handle_list)); status = acpi_evaluate_reference(tz->device->handle, "_PSL", NULL, &devices); if (ACPI_FAILURE(status)) { acpi_handle_info(tz->device->handle, "Invalid passive threshold\n"); - tz->trips.passive.valid = false; + tz->trips.passive.trip.valid = false; } else { - tz->trips.passive.valid = true; + tz->trips.passive.trip.valid = true; } if (memcmp(&tz->trips.passive.devices, &devices, @@ -317,24 +315,24 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) } } if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) { - if (valid != tz->trips.passive.valid) + if (valid != tz->trips.passive.trip.valid) ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state"); } /* Active (optional) */ for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { char name[5] = { '_', 'A', 'C', ('0' + i), '\0' }; - valid = tz->trips.active[i].valid; + valid = tz->trips.active[i].trip.valid; if (act == -1) break; /* disable all active trip points */ if (flag == ACPI_TRIPS_INIT || ((flag & ACPI_TRIPS_ACTIVE) && - tz->trips.active[i].valid)) { + tz->trips.active[i].trip.valid)) { status = acpi_evaluate_integer(tz->device->handle, name, NULL, &tmp); if (ACPI_FAILURE(status)) { - tz->trips.active[i].valid = false; + tz->trips.active[i].trip.valid = false; if (i == 0) break; @@ -342,35 +340,36 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) break; if (i == 1) - tz->trips.active[0].temperature = celsius_to_deci_kelvin(act); + tz->trips.active[0].trip.temperature = + celsius_to_deci_kelvin(act); else /* * Don't allow override higher than * the next higher trip point */ - tz->trips.active[i-1].temperature = + tz->trips.active[i-1].trip.temperature = min_t(unsigned long, - tz->trips.active[i-2].temperature, + tz->trips.active[i-2].trip.temperature, celsius_to_deci_kelvin(act)); break; } else { - tz->trips.active[i].temperature = tmp; - tz->trips.active[i].valid = true; + tz->trips.active[i].trip.temperature = tmp; + tz->trips.active[i].trip.valid = true; } } name[2] = 'L'; - if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].valid) { + if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].trip.valid) { memset(&devices, 0, sizeof(struct acpi_handle_list)); status = acpi_evaluate_reference(tz->device->handle, name, NULL, &devices); if (ACPI_FAILURE(status)) { acpi_handle_info(tz->device->handle, "Invalid active%d threshold\n", i); - tz->trips.active[i].valid = false; + tz->trips.active[i].trip.valid = false; } else { - tz->trips.active[i].valid = true; + tz->trips.active[i].trip.valid = true; } if (memcmp(&tz->trips.active[i].devices, &devices, @@ -381,10 +380,10 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) } } if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES)) - if (valid != tz->trips.active[i].valid) + if (valid != tz->trips.active[i].trip.valid) ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "state"); - if (!tz->trips.active[i].valid) + if (!tz->trips.active[i].trip.valid) break; } @@ -398,24 +397,73 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) ACPI_THERMAL_TRIPS_EXCEPTION(flag, tz, "device"); } } +} + +static int acpi_thermal_adjust_trip(struct thermal_trip *trip, void *data) +{ + struct acpi_thermal_trip *acpi_trip = trip->priv; + struct acpi_thermal *tz = data; + + if (!acpi_trip) + return 0; + + if (acpi_trip->valid) + trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); + else + trip->temperature = THERMAL_TEMP_INVALID; return 0; } +static void acpi_thermal_adjust_thermal_zone(struct thermal_zone_device *thermal, + unsigned long data) +{ + struct acpi_thermal *tz = thermal_zone_device_priv(thermal); + int flag = data == ACPI_THERMAL_NOTIFY_THRESHOLDS ? + ACPI_TRIPS_THRESHOLDS : ACPI_TRIPS_DEVICES; + + __acpi_thermal_trips_update(tz, flag); + + for_each_thermal_trip(tz->thermal_zone, acpi_thermal_adjust_trip, tz); +} + +static void acpi_queue_thermal_check(struct acpi_thermal *tz) +{ + if (!work_pending(&tz->thermal_check_work)) + queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work); +} + +static void acpi_thermal_trips_update(struct acpi_thermal *tz, u32 event) +{ + struct acpi_device *adev = tz->device; + + /* + * Use thermal_zone_device_exec() to carry out the trip points + * update, so as to protect thermal_get_trend() from getting stale + * trip point temperatures and to prevent thermal_zone_device_update() + * invoked from acpi_thermal_check_fn() from producing inconsistent + * results. + */ + thermal_zone_device_exec(tz->thermal_zone, + acpi_thermal_adjust_thermal_zone, event); + acpi_queue_thermal_check(tz); + acpi_bus_generate_netlink_event(adev->pnp.device_class, + dev_name(&adev->dev), event, 0); +} + static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) { - int i, ret = acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); bool valid; + int i; - if (ret) - return ret; + __acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); valid = tz->trips.critical.valid | tz->trips.hot.valid | - tz->trips.passive.valid; + tz->trips.passive.trip.valid; for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) - valid = valid || tz->trips.active[i].valid; + valid = valid || tz->trips.active[i].trip.valid; if (!valid) { pr_warn(FW_BUG "No valid trip found\n"); @@ -443,159 +491,55 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp) return 0; } -static int thermal_get_trip_type(struct thermal_zone_device *thermal, - int trip, enum thermal_trip_type *type) +static int thermal_get_trend(struct thermal_zone_device *thermal, + int trip_index, enum thermal_trend *trend) { struct acpi_thermal *tz = thermal_zone_device_priv(thermal); - int i; + struct acpi_thermal_trip *acpi_trip; + int t, i; - if (!tz || trip < 0) + if (!tz || trip_index < 0) return -EINVAL; - if (tz->trips.critical.valid) { - if (!trip) { - *type = THERMAL_TRIP_CRITICAL; - return 0; - } - trip--; - } - - if (tz->trips.hot.valid) { - if (!trip) { - *type = THERMAL_TRIP_HOT; - return 0; - } - trip--; - } - - if (tz->trips.passive.valid) { - if (!trip) { - *type = THERMAL_TRIP_PASSIVE; - return 0; - } - trip--; - } - - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].valid; i++) { - if (!trip) { - *type = THERMAL_TRIP_ACTIVE; - return 0; - } - trip--; - } - - return -EINVAL; -} + if (tz->trips.critical.valid) + trip_index--; -static int thermal_get_trip_temp(struct thermal_zone_device *thermal, - int trip, int *temp) -{ - struct acpi_thermal *tz = thermal_zone_device_priv(thermal); - int i; + if (tz->trips.hot.valid) + trip_index--; - if (!tz || trip < 0) + if (trip_index < 0) return -EINVAL; - if (tz->trips.critical.valid) { - if (!trip) { - *temp = deci_kelvin_to_millicelsius_with_offset( - tz->trips.critical.temperature, - tz->kelvin_offset); - return 0; - } - trip--; - } - - if (tz->trips.hot.valid) { - if (!trip) { - *temp = deci_kelvin_to_millicelsius_with_offset( - tz->trips.hot.temperature, - tz->kelvin_offset); - return 0; - } - trip--; - } - - if (tz->trips.passive.valid) { - if (!trip) { - *temp = deci_kelvin_to_millicelsius_with_offset( - tz->trips.passive.temperature, - tz->kelvin_offset); - return 0; - } - trip--; - } - - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && - tz->trips.active[i].valid; i++) { - if (!trip) { - *temp = deci_kelvin_to_millicelsius_with_offset( - tz->trips.active[i].temperature, - tz->kelvin_offset); - return 0; - } - trip--; - } - - return -EINVAL; -} - -static int thermal_get_crit_temp(struct thermal_zone_device *thermal, - int *temperature) -{ - struct acpi_thermal *tz = thermal_zone_device_priv(thermal); + acpi_trip = &tz->trips.passive.trip; + if (acpi_trip->valid && !trip_index--) { + t = tz->trips.passive.tc1 * (tz->temperature - + tz->last_temperature) + + tz->trips.passive.tc2 * (tz->temperature - + acpi_trip->temperature); + if (t > 0) + *trend = THERMAL_TREND_RAISING; + else if (t < 0) + *trend = THERMAL_TREND_DROPPING; + else + *trend = THERMAL_TREND_STABLE; - if (tz->trips.critical.valid) { - *temperature = deci_kelvin_to_millicelsius_with_offset( - tz->trips.critical.temperature, - tz->kelvin_offset); return 0; } - return -EINVAL; -} - -static int thermal_get_trend(struct thermal_zone_device *thermal, - int trip, enum thermal_trend *trend) -{ - struct acpi_thermal *tz = thermal_zone_device_priv(thermal); - enum thermal_trip_type type; - int i; - - if (thermal_get_trip_type(thermal, trip, &type)) - return -EINVAL; - - if (type == THERMAL_TRIP_ACTIVE) { - int trip_temp; - int temp = deci_kelvin_to_millicelsius_with_offset( - tz->temperature, tz->kelvin_offset); - if (thermal_get_trip_temp(thermal, trip, &trip_temp)) - return -EINVAL; + t = acpi_thermal_temp(tz, tz->temperature); - if (temp > trip_temp) { - *trend = THERMAL_TREND_RAISING; - return 0; - } else { - /* Fall back on default trend */ - return -EINVAL; + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { + acpi_trip = &tz->trips.active[i].trip; + if (acpi_trip->valid && !trip_index--) { + if (t > acpi_thermal_temp(tz, acpi_trip->temperature)) { + *trend = THERMAL_TREND_RAISING; + return 0; + } + break; } } - /* - * tz->temperature has already been updated by generic thermal layer, - * before this callback being invoked - */ - i = tz->trips.passive.tc1 * (tz->temperature - tz->last_temperature) + - tz->trips.passive.tc2 * (tz->temperature - tz->trips.passive.temperature); - - if (i > 0) - *trend = THERMAL_TREND_RAISING; - else if (i < 0) - *trend = THERMAL_TREND_DROPPING; - else - *trend = THERMAL_TREND_STABLE; - - return 0; + return -EINVAL; } static void acpi_thermal_zone_device_hot(struct thermal_zone_device *thermal) @@ -637,7 +581,7 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, if (tz->trips.hot.valid) trip++; - if (tz->trips.passive.valid) { + if (tz->trips.passive.trip.valid) { trip++; for (i = 0; i < tz->trips.passive.devices.count; i++) { handle = tz->trips.passive.devices.handles[i]; @@ -662,7 +606,7 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, } for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - if (!tz->trips.active[i].valid) + if (!tz->trips.active[i].trip.valid) break; trip++; @@ -709,9 +653,6 @@ static struct thermal_zone_device_ops acpi_thermal_zone_ops = { .bind = acpi_thermal_bind_cooling_device, .unbind = acpi_thermal_unbind_cooling_device, .get_temp = thermal_get_temp, - .get_trip_type = thermal_get_trip_type, - .get_trip_temp = thermal_get_trip_temp, - .get_crit_temp = thermal_get_crit_temp, .get_trend = thermal_get_trend, .hot = acpi_thermal_zone_device_hot, .critical = acpi_thermal_zone_device_critical, @@ -745,63 +686,97 @@ static void acpi_thermal_zone_sysfs_remove(struct acpi_thermal *tz) static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) { - int trips = 0; + struct acpi_thermal_trip *acpi_trip; + struct thermal_trip *trip; + int passive_delay = 0; + int trip_count = 0; int result; - acpi_status status; int i; if (tz->trips.critical.valid) - trips++; + trip_count++; if (tz->trips.hot.valid) - trips++; + trip_count++; + + if (tz->trips.passive.trip.valid) { + trip_count++; + passive_delay = tz->trips.passive.tsp * 100; + } - if (tz->trips.passive.valid) - trips++; + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].trip.valid; i++) + trip_count++; - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].valid; - i++, trips++); + trip = kcalloc(trip_count, sizeof(*trip), GFP_KERNEL); + if (!trip) + return -ENOMEM; - if (tz->trips.passive.valid) - tz->thermal_zone = thermal_zone_device_register("acpitz", trips, 0, tz, - &acpi_thermal_zone_ops, NULL, - tz->trips.passive.tsp * 100, - tz->polling_frequency * 100); - else - tz->thermal_zone = - thermal_zone_device_register("acpitz", trips, 0, tz, - &acpi_thermal_zone_ops, NULL, - 0, tz->polling_frequency * 100); + tz->trip_table = trip; - if (IS_ERR(tz->thermal_zone)) - return -ENODEV; + if (tz->trips.critical.valid) { + trip->type = THERMAL_TRIP_CRITICAL; + trip->temperature = acpi_thermal_temp(tz, tz->trips.critical.temperature); + trip++; + } + + if (tz->trips.hot.valid) { + trip->type = THERMAL_TRIP_HOT; + trip->temperature = acpi_thermal_temp(tz, tz->trips.hot.temperature); + trip++; + } + + acpi_trip = &tz->trips.passive.trip; + if (acpi_trip->valid) { + trip->type = THERMAL_TRIP_PASSIVE; + trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); + trip->priv = acpi_trip; + trip++; + } + + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { + acpi_trip = &tz->trips.active[i].trip; + + if (!acpi_trip->valid) + break; + + trip->type = THERMAL_TRIP_ACTIVE; + trip->temperature = acpi_thermal_temp(tz, acpi_trip->temperature); + trip->priv = acpi_trip; + trip++; + } + + tz->thermal_zone = thermal_zone_device_register_with_trips("acpitz", + tz->trip_table, + trip_count, + 0, tz, + &acpi_thermal_zone_ops, + NULL, + passive_delay, + tz->polling_frequency * 100); + if (IS_ERR(tz->thermal_zone)) { + result = PTR_ERR(tz->thermal_zone); + goto free_trip_table; + } result = acpi_thermal_zone_sysfs_add(tz); if (result) goto unregister_tzd; - status = acpi_bus_attach_private_data(tz->device->handle, - tz->thermal_zone); - if (ACPI_FAILURE(status)) { - result = -ENODEV; - goto remove_links; - } - result = thermal_zone_device_enable(tz->thermal_zone); if (result) - goto acpi_bus_detach; + goto remove_links; dev_info(&tz->device->dev, "registered as thermal_zone%d\n", thermal_zone_device_id(tz->thermal_zone)); return 0; -acpi_bus_detach: - acpi_bus_detach_private_data(tz->device->handle); remove_links: acpi_thermal_zone_sysfs_remove(tz); unregister_tzd: thermal_zone_device_unregister(tz->thermal_zone); +free_trip_table: + kfree(tz->trip_table); return result; } @@ -810,8 +785,8 @@ static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz) { acpi_thermal_zone_sysfs_remove(tz); thermal_zone_device_unregister(tz->thermal_zone); + kfree(tz->trip_table); tz->thermal_zone = NULL; - acpi_bus_detach_private_data(tz->device->handle); } @@ -819,14 +794,9 @@ static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz) Driver Interface -------------------------------------------------------------------------- */ -static void acpi_queue_thermal_check(struct acpi_thermal *tz) -{ - if (!work_pending(&tz->thermal_check_work)) - queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work); -} - -static void acpi_thermal_notify(struct acpi_device *device, u32 event) +static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data) { + struct acpi_device *device = data; struct acpi_thermal *tz = acpi_driver_data(device); if (!tz) @@ -837,16 +807,8 @@ static void acpi_thermal_notify(struct acpi_device *device, u32 event) acpi_queue_thermal_check(tz); break; case ACPI_THERMAL_NOTIFY_THRESHOLDS: - acpi_thermal_trips_update(tz, ACPI_TRIPS_THRESHOLDS); - acpi_queue_thermal_check(tz); - acpi_bus_generate_netlink_event(device->pnp.device_class, - dev_name(&device->dev), event, 0); - break; case ACPI_THERMAL_NOTIFY_DEVICES: - acpi_thermal_trips_update(tz, ACPI_TRIPS_DEVICES); - acpi_queue_thermal_check(tz); - acpi_bus_generate_netlink_event(device->pnp.device_class, - dev_name(&device->dev), event, 0); + acpi_thermal_trips_update(tz, event); break; default: acpi_handle_debug(device->handle, "Unsupported event [0x%x]\n", @@ -997,11 +959,20 @@ static int acpi_thermal_add(struct acpi_device *device) pr_info("%s [%s] (%ld C)\n", acpi_device_name(device), acpi_device_bid(device), deci_kelvin_to_celsius(tz->temperature)); - goto end; + result = acpi_dev_install_notify_handler(device, ACPI_DEVICE_NOTIFY, + acpi_thermal_notify); + if (result) + goto flush_wq; + + return 0; + +flush_wq: + flush_workqueue(acpi_thermal_pm_queue); + acpi_thermal_unregister_thermal_zone(tz); free_memory: kfree(tz); -end: + return result; } @@ -1012,10 +983,14 @@ static void acpi_thermal_remove(struct acpi_device *device) if (!device || !acpi_driver_data(device)) return; - flush_workqueue(acpi_thermal_pm_queue); tz = acpi_driver_data(device); + acpi_dev_remove_notify_handler(device, ACPI_DEVICE_NOTIFY, + acpi_thermal_notify); + + flush_workqueue(acpi_thermal_pm_queue); acpi_thermal_unregister_thermal_zone(tz); + kfree(tz); } @@ -1030,7 +1005,7 @@ static int acpi_thermal_suspend(struct device *dev) static int acpi_thermal_resume(struct device *dev) { struct acpi_thermal *tz; - int i, j, power_state, result; + int i, j, power_state; if (!dev) return -EINVAL; @@ -1040,18 +1015,12 @@ static int acpi_thermal_resume(struct device *dev) return -EINVAL; for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - if (!tz->trips.active[i].valid) + if (!tz->trips.active[i].trip.valid) break; - tz->trips.active[i].enabled = true; for (j = 0; j < tz->trips.active[i].devices.count; j++) { - result = acpi_bus_update_power( - tz->trips.active[i].devices.handles[j], - &power_state); - if (result || (power_state != ACPI_STATE_D0)) { - tz->trips.active[i].enabled = false; - break; - } + acpi_bus_update_power(tz->trips.active[i].devices.handles[j], + &power_state); } } @@ -1078,7 +1047,6 @@ static struct acpi_driver acpi_thermal_driver = { .ops = { .add = acpi_thermal_add, .remove = acpi_thermal_remove, - .notify = acpi_thermal_notify, }, .drv.pm = &acpi_thermal_pm, }; @@ -1094,7 +1062,7 @@ static int thermal_act(const struct dmi_system_id *d) { static int thermal_nocrt(const struct dmi_system_id *d) { pr_notice("%s detected: disabling all critical thermal trip point actions.\n", d->ident); - nocrt = 1; + crt = -1; return 0; } static int thermal_tzp(const struct dmi_system_id *d) { diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 18cc08c858cf..442396f6ed1f 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -446,6 +446,15 @@ static const struct dmi_system_id video_detect_dmi_table[] = { }, }, { + /* https://bugzilla.suse.com/show_bug.cgi?id=1208724 */ + .callback = video_detect_force_native, + /* Lenovo Ideapad Z470 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "IdeaPad Z470"), + }, + }, + { /* https://bugzilla.redhat.com/show_bug.cgi?id=1187004 */ .callback = video_detect_force_native, /* Lenovo Ideapad Z570 */ @@ -487,6 +496,24 @@ static const struct dmi_system_id video_detect_dmi_table[] = { }, }, { + /* https://gitlab.freedesktop.org/drm/amd/-/issues/1838 */ + .callback = video_detect_force_native, + /* Apple iMac12,1 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "iMac12,1"), + }, + }, + { + /* https://gitlab.freedesktop.org/drm/amd/-/issues/2753 */ + .callback = video_detect_force_native, + /* Apple iMac12,2 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "iMac12,2"), + }, + }, + { /* https://bugzilla.redhat.com/show_bug.cgi?id=1217249 */ .callback = video_detect_force_native, /* Apple MacBook Pro 12,1 */ diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c index ce62e61a9605..08f7c6708206 100644 --- a/drivers/acpi/x86/s2idle.c +++ b/drivers/acpi/x86/s2idle.c @@ -94,6 +94,11 @@ static struct lpi_constraints *lpi_constraints_table; static int lpi_constraints_table_size; static int rev_id; +#define for_each_lpi_constraint(entry) \ + for (int i = 0; \ + entry = &lpi_constraints_table[i], i < lpi_constraints_table_size; \ + i++) + static void lpi_device_get_constraints_amd(void) { union acpi_object *out_obj; @@ -113,6 +118,12 @@ static void lpi_device_get_constraints_amd(void) union acpi_object *package = &out_obj->package.elements[i]; if (package->type == ACPI_TYPE_PACKAGE) { + if (lpi_constraints_table) { + acpi_handle_err(lps0_device_handle, + "Duplicate constraints list\n"); + goto free_acpi_buffer; + } + lpi_constraints_table = kcalloc(package->package.count, sizeof(*lpi_constraints_table), GFP_KERNEL); @@ -123,17 +134,16 @@ static void lpi_device_get_constraints_amd(void) acpi_handle_debug(lps0_device_handle, "LPI: constraints list begin:\n"); - for (j = 0; j < package->package.count; ++j) { + for (j = 0; j < package->package.count; j++) { union acpi_object *info_obj = &package->package.elements[j]; struct lpi_device_constraint_amd dev_info = {}; struct lpi_constraints *list; acpi_status status; - for (k = 0; k < info_obj->package.count; ++k) { - union acpi_object *obj = &info_obj->package.elements[k]; + list = &lpi_constraints_table[lpi_constraints_table_size]; - list = &lpi_constraints_table[lpi_constraints_table_size]; - list->min_dstate = -1; + for (k = 0; k < info_obj->package.count; k++) { + union acpi_object *obj = &info_obj->package.elements[k]; switch (k) { case 0: @@ -149,27 +159,25 @@ static void lpi_device_get_constraints_amd(void) dev_info.min_dstate = obj->integer.value; break; } + } - if (!dev_info.enabled || !dev_info.name || - !dev_info.min_dstate) - continue; + acpi_handle_debug(lps0_device_handle, + "Name:%s, Enabled: %d, States: %d, MinDstate: %d\n", + dev_info.name, + dev_info.enabled, + dev_info.function_states, + dev_info.min_dstate); - status = acpi_get_handle(NULL, dev_info.name, - &list->handle); - if (ACPI_FAILURE(status)) - continue; + if (!dev_info.enabled || !dev_info.name || + !dev_info.min_dstate) + continue; - acpi_handle_debug(lps0_device_handle, - "Name:%s\n", dev_info.name); + status = acpi_get_handle(NULL, dev_info.name, &list->handle); + if (ACPI_FAILURE(status)) + continue; - list->min_dstate = dev_info.min_dstate; + list->min_dstate = dev_info.min_dstate; - if (list->min_dstate < 0) { - acpi_handle_debug(lps0_device_handle, - "Incomplete constraint defined\n"); - continue; - } - } lpi_constraints_table_size++; } } @@ -214,7 +222,7 @@ static void lpi_device_get_constraints(void) if (!package) continue; - for (j = 0; j < package->package.count; ++j) { + for (j = 0; j < package->package.count; j++) { union acpi_object *element = &(package->package.elements[j]); @@ -246,7 +254,7 @@ static void lpi_device_get_constraints(void) constraint->min_dstate = -1; - for (j = 0; j < package_count; ++j) { + for (j = 0; j < package_count; j++) { union acpi_object *info_obj = &info.package[j]; union acpi_object *cnstr_pkg; union acpi_object *obj; @@ -291,32 +299,55 @@ free_acpi_buffer: ACPI_FREE(out_obj); } +/** + * acpi_get_lps0_constraint - Get the LPS0 constraint for a device. + * @adev: Device to get the constraint for. + * + * The LPS0 constraint is the shallowest (minimum) power state in which the + * device can be so as to allow the platform as a whole to achieve additional + * energy conservation by utilizing a system-wide low-power state. + * + * Returns: + * - ACPI power state value of the constraint for @adev on success. + * - Otherwise, ACPI_STATE_UNKNOWN. + */ +int acpi_get_lps0_constraint(struct acpi_device *adev) +{ + struct lpi_constraints *entry; + + for_each_lpi_constraint(entry) { + if (adev->handle == entry->handle) + return entry->min_dstate; + } + + return ACPI_STATE_UNKNOWN; +} + static void lpi_check_constraints(void) { - int i; + struct lpi_constraints *entry; - for (i = 0; i < lpi_constraints_table_size; ++i) { - acpi_handle handle = lpi_constraints_table[i].handle; - struct acpi_device *adev = acpi_fetch_acpi_dev(handle); + for_each_lpi_constraint(entry) { + struct acpi_device *adev = acpi_fetch_acpi_dev(entry->handle); if (!adev) continue; - acpi_handle_debug(handle, + acpi_handle_debug(entry->handle, "LPI: required min power state:%s current power state:%s\n", - acpi_power_state_string(lpi_constraints_table[i].min_dstate), + acpi_power_state_string(entry->min_dstate), acpi_power_state_string(adev->power.state)); if (!adev->flags.power_manageable) { - acpi_handle_info(handle, "LPI: Device not power manageable\n"); - lpi_constraints_table[i].handle = NULL; + acpi_handle_info(entry->handle, "LPI: Device not power manageable\n"); + entry->handle = NULL; continue; } - if (adev->power.state < lpi_constraints_table[i].min_dstate) - acpi_handle_info(handle, + if (adev->power.state < entry->min_dstate) + acpi_handle_info(entry->handle, "LPI: Constraint not met; min power state:%s current power state:%s\n", - acpi_power_state_string(lpi_constraints_table[i].min_dstate), + acpi_power_state_string(entry->min_dstate), acpi_power_state_string(adev->power.state)); } } diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c index c2b925f8cd4e..63d834dd3811 100644 --- a/drivers/acpi/x86/utils.c +++ b/drivers/acpi/x86/utils.c @@ -518,3 +518,38 @@ bool acpi_quirk_skip_acpi_ac_and_battery(void) return false; } EXPORT_SYMBOL_GPL(acpi_quirk_skip_acpi_ac_and_battery); + +/* This section provides a workaround for a specific x86 system + * which requires disabling of mwait to work correctly. + */ +static int __init acpi_proc_quirk_set_no_mwait(const struct dmi_system_id *id) +{ + pr_notice("%s detected - disabling mwait for CPU C-states\n", + id->ident); + boot_option_idle_override = IDLE_NOMWAIT; + return 0; +} + +static const struct dmi_system_id acpi_proc_quirk_mwait_dmi_table[] __initconst = { + { + .callback = acpi_proc_quirk_set_no_mwait, + .ident = "Extensa 5220", + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), + DMI_MATCH(DMI_BOARD_NAME, "Columbia"), + }, + .driver_data = NULL, + }, + {} +}; + +void __init acpi_proc_quirk_mwait_check(void) +{ + /* + * Check whether the system is DMI table. If yes, OSPM + * should not use mwait for CPU-states. + */ + dmi_check_system(acpi_proc_quirk_mwait_dmi_table); +} diff --git a/drivers/android/binderfs.c b/drivers/android/binderfs.c index 76e7d6676657..faebe9f5412a 100644 --- a/drivers/android/binderfs.c +++ b/drivers/android/binderfs.c @@ -153,7 +153,7 @@ static int binderfs_binder_device_create(struct inode *ref_inode, goto err; inode->i_ino = minor + INODE_OFFSET; - inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); + inode->i_mtime = inode->i_atime = inode_set_ctime_current(inode); init_special_inode(inode, S_IFCHR | 0600, MKDEV(MAJOR(binderfs_dev), minor)); inode->i_fop = &binder_fops; @@ -432,7 +432,7 @@ static int binderfs_binder_ctl_create(struct super_block *sb) } inode->i_ino = SECOND_INODE; - inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); + inode->i_mtime = inode->i_atime = inode_set_ctime_current(inode); init_special_inode(inode, S_IFCHR | 0600, MKDEV(MAJOR(binderfs_dev), minor)); inode->i_fop = &binder_ctl_fops; @@ -474,7 +474,7 @@ static struct inode *binderfs_make_inode(struct super_block *sb, int mode) if (ret) { ret->i_ino = iunique(sb, BINDERFS_MAX_MINOR + INODE_OFFSET); ret->i_mode = mode; - ret->i_atime = ret->i_mtime = ret->i_ctime = current_time(ret); + ret->i_atime = ret->i_mtime = inode_set_ctime_current(ret); } return ret; } @@ -703,7 +703,7 @@ static int binderfs_fill_super(struct super_block *sb, struct fs_context *fc) inode->i_ino = FIRST_INODE; inode->i_fop = &simple_dir_operations; inode->i_mode = S_IFDIR | 0755; - inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode); + inode->i_mtime = inode->i_atime = inode_set_ctime_current(inode); inode->i_op = &binderfs_dir_inode_operations; set_nlink(inode, 2); diff --git a/drivers/auxdisplay/hd44780_common.c b/drivers/auxdisplay/hd44780_common.c index 3934c2eebf33..7cbf375b0fa5 100644 --- a/drivers/auxdisplay/hd44780_common.c +++ b/drivers/auxdisplay/hd44780_common.c @@ -82,7 +82,15 @@ int hd44780_common_clear_display(struct charlcd *lcd) hdc->write_cmd(hdc, LCD_CMD_DISPLAY_CLEAR); /* datasheet says to wait 1,64 milliseconds */ long_sleep(2); - return 0; + + /* + * The Hitachi HD44780 controller (and compatible ones) reset the DDRAM + * address when executing the DISPLAY_CLEAR command, thus the + * following call is not required. However, other controllers do not + * (e.g. NewHaven NHD-0220DZW-AG5), thus move the cursor to home + * unconditionally to support both. + */ + return hd44780_common_home(lcd); } EXPORT_SYMBOL_GPL(hd44780_common_clear_display); diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig index 0db2021f7477..b1affac70d5d 100644 --- a/drivers/base/regmap/Kconfig +++ b/drivers/base/regmap/Kconfig @@ -4,7 +4,7 @@ # subsystems should select the appropriate symbols. config REGMAP - bool "Register Map support" if KUNIT_ALL_TESTS + bool default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SOUNDWIRE_MBQ || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM || REGMAP_MDIO || REGMAP_FSI) select IRQ_DOMAIN if REGMAP_IRQ select MDIO_BUS if REGMAP_MDIO @@ -23,6 +23,16 @@ config REGMAP_KUNIT default KUNIT_ALL_TESTS select REGMAP_RAM +config REGMAP_BUILD + bool "Enable regmap build" + depends on KUNIT + select REGMAP + help + This option exists purely to allow the regmap KUnit tests to + be enabled without having to enable some driver that uses + regmap due to unfortunate issues with how KUnit tests are + normally enabled. + config REGMAP_AC97 tristate diff --git a/drivers/base/regmap/regcache-maple.c b/drivers/base/regmap/regcache-maple.c index 283c2e02a298..41edd6a430eb 100644 --- a/drivers/base/regmap/regcache-maple.c +++ b/drivers/base/regmap/regcache-maple.c @@ -74,7 +74,7 @@ static int regcache_maple_write(struct regmap *map, unsigned int reg, rcu_read_unlock(); entry = kmalloc((last - index + 1) * sizeof(unsigned long), - GFP_KERNEL); + map->alloc_flags); if (!entry) return -ENOMEM; @@ -92,7 +92,7 @@ static int regcache_maple_write(struct regmap *map, unsigned int reg, mas_lock(&mas); mas_set_range(&mas, index, last); - ret = mas_store_gfp(&mas, entry, GFP_KERNEL); + ret = mas_store_gfp(&mas, entry, map->alloc_flags); mas_unlock(&mas); @@ -134,7 +134,7 @@ static int regcache_maple_drop(struct regmap *map, unsigned int min, lower = kmemdup(entry, ((min - mas.index) * sizeof(unsigned long)), - GFP_KERNEL); + map->alloc_flags); if (!lower) { ret = -ENOMEM; goto out_unlocked; @@ -148,7 +148,7 @@ static int regcache_maple_drop(struct regmap *map, unsigned int min, upper = kmemdup(&entry[max + 1], ((mas.last - max) * sizeof(unsigned long)), - GFP_KERNEL); + map->alloc_flags); if (!upper) { ret = -ENOMEM; goto out_unlocked; @@ -162,7 +162,7 @@ static int regcache_maple_drop(struct regmap *map, unsigned int min, /* Insert new nodes with the saved data */ if (lower) { mas_set_range(&mas, lower_index, lower_last); - ret = mas_store_gfp(&mas, lower, GFP_KERNEL); + ret = mas_store_gfp(&mas, lower, map->alloc_flags); if (ret != 0) goto out; lower = NULL; @@ -170,7 +170,7 @@ static int regcache_maple_drop(struct regmap *map, unsigned int min, if (upper) { mas_set_range(&mas, upper_index, upper_last); - ret = mas_store_gfp(&mas, upper, GFP_KERNEL); + ret = mas_store_gfp(&mas, upper, map->alloc_flags); if (ret != 0) goto out; upper = NULL; @@ -320,7 +320,7 @@ static int regcache_maple_insert_block(struct regmap *map, int first, unsigned long *entry; int i, ret; - entry = kcalloc(last - first + 1, sizeof(unsigned long), GFP_KERNEL); + entry = kcalloc(last - first + 1, sizeof(unsigned long), map->alloc_flags); if (!entry) return -ENOMEM; @@ -331,7 +331,7 @@ static int regcache_maple_insert_block(struct regmap *map, int first, mas_set_range(&mas, map->reg_defaults[first].reg, map->reg_defaults[last].reg); - ret = mas_store_gfp(&mas, entry, GFP_KERNEL); + ret = mas_store_gfp(&mas, entry, map->alloc_flags); mas_unlock(&mas); diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c index 584bcc55f56e..db716ffd083e 100644 --- a/drivers/base/regmap/regcache-rbtree.c +++ b/drivers/base/regmap/regcache-rbtree.c @@ -22,7 +22,7 @@ struct regcache_rbtree_node { /* block of adjacent registers */ void *block; /* Which registers are present */ - long *cache_present; + unsigned long *cache_present; /* base register handled by this block */ unsigned int base_reg; /* number of registers available in the block */ @@ -277,7 +277,7 @@ static int regcache_rbtree_insert_to_block(struct regmap *map, blk = krealloc(rbnode->block, blklen * map->cache_word_size, - GFP_KERNEL); + map->alloc_flags); if (!blk) return -ENOMEM; @@ -286,7 +286,7 @@ static int regcache_rbtree_insert_to_block(struct regmap *map, if (BITS_TO_LONGS(blklen) > BITS_TO_LONGS(rbnode->blklen)) { present = krealloc(rbnode->cache_present, BITS_TO_LONGS(blklen) * sizeof(*present), - GFP_KERNEL); + map->alloc_flags); if (!present) return -ENOMEM; @@ -320,7 +320,7 @@ regcache_rbtree_node_alloc(struct regmap *map, unsigned int reg) const struct regmap_range *range; int i; - rbnode = kzalloc(sizeof(*rbnode), GFP_KERNEL); + rbnode = kzalloc(sizeof(*rbnode), map->alloc_flags); if (!rbnode) return NULL; @@ -346,13 +346,13 @@ regcache_rbtree_node_alloc(struct regmap *map, unsigned int reg) } rbnode->block = kmalloc_array(rbnode->blklen, map->cache_word_size, - GFP_KERNEL); + map->alloc_flags); if (!rbnode->block) goto err_free; rbnode->cache_present = kcalloc(BITS_TO_LONGS(rbnode->blklen), sizeof(*rbnode->cache_present), - GFP_KERNEL); + map->alloc_flags); if (!rbnode->cache_present) goto err_free_block; diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 7d3e47436056..c5d151e9c481 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -558,6 +558,29 @@ void regcache_cache_bypass(struct regmap *map, bool enable) } EXPORT_SYMBOL_GPL(regcache_cache_bypass); +/** + * regcache_reg_cached - Check if a register is cached + * + * @map: map to check + * @reg: register to check + * + * Reports if a register is cached. + */ +bool regcache_reg_cached(struct regmap *map, unsigned int reg) +{ + unsigned int val; + int ret; + + map->lock(map->lock_arg); + + ret = regcache_read(map, reg, &val); + + map->unlock(map->lock_arg); + + return ret == 0; +} +EXPORT_SYMBOL_GPL(regcache_reg_cached); + void regcache_set_val(struct regmap *map, void *base, unsigned int idx, unsigned int val) { @@ -587,14 +610,6 @@ void regcache_set_val(struct regmap *map, void *base, unsigned int idx, cache[idx] = val; break; } -#ifdef CONFIG_64BIT - case 8: { - u64 *cache = base; - - cache[idx] = val; - break; - } -#endif default: BUG(); } @@ -627,13 +642,6 @@ unsigned int regcache_get_val(struct regmap *map, const void *base, return cache[idx]; } -#ifdef CONFIG_64BIT - case 8: { - const u64 *cache = base; - - return cache[idx]; - } -#endif default: BUG(); } diff --git a/drivers/base/regmap/regmap-kunit.c b/drivers/base/regmap/regmap-kunit.c index 9ff3018a46aa..264d29b3fced 100644 --- a/drivers/base/regmap/regmap-kunit.c +++ b/drivers/base/regmap/regmap-kunit.c @@ -836,6 +836,45 @@ static void cache_drop(struct kunit *test) regmap_exit(map); } +static void cache_present(struct kunit *test) +{ + struct regcache_types *t = (struct regcache_types *)test->param_value; + struct regmap *map; + struct regmap_config config; + struct regmap_ram_data *data; + unsigned int val; + int i; + + config = test_regmap_config; + config.cache_type = t->type; + + map = gen_regmap(&config, &data); + KUNIT_ASSERT_FALSE(test, IS_ERR(map)); + if (IS_ERR(map)) + return; + + for (i = 0; i < BLOCK_TEST_SIZE; i++) + data->read[i] = false; + + /* No defaults so no registers cached. */ + for (i = 0; i < BLOCK_TEST_SIZE; i++) + KUNIT_ASSERT_FALSE(test, regcache_reg_cached(map, i)); + + /* We didn't trigger any reads */ + for (i = 0; i < BLOCK_TEST_SIZE; i++) + KUNIT_ASSERT_FALSE(test, data->read[i]); + + /* Fill the cache */ + for (i = 0; i < BLOCK_TEST_SIZE; i++) + KUNIT_EXPECT_EQ(test, 0, regmap_read(map, i, &val)); + + /* Now everything should be cached */ + for (i = 0; i < BLOCK_TEST_SIZE; i++) + KUNIT_ASSERT_TRUE(test, regcache_reg_cached(map, i)); + + regmap_exit(map); +} + struct raw_test_types { const char *name; @@ -1177,6 +1216,7 @@ static struct kunit_case regmap_test_cases[] = { KUNIT_CASE_PARAM(cache_sync_readonly, real_cache_types_gen_params), KUNIT_CASE_PARAM(cache_sync_patch, real_cache_types_gen_params), KUNIT_CASE_PARAM(cache_drop, sparse_cache_types_gen_params), + KUNIT_CASE_PARAM(cache_present, sparse_cache_types_gen_params), KUNIT_CASE_PARAM(raw_read_defaults_single, raw_test_types_gen_params), KUNIT_CASE_PARAM(raw_read_defaults, raw_test_types_gen_params), diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index 8132b5c101c4..99d7fd85ca7d 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c @@ -202,15 +202,6 @@ static int regmap_mmio_noinc_write(void *context, unsigned int reg, writel(swab32(valp[i]), ctx->regs + reg); goto out_clk; } -#ifdef CONFIG_64BIT - case 8: - { - const u64 *valp = (const u64 *)val; - for (i = 0; i < val_count; i++) - writeq(swab64(valp[i]), ctx->regs + reg); - goto out_clk; - } -#endif default: ret = -EINVAL; goto out_clk; @@ -227,11 +218,6 @@ static int regmap_mmio_noinc_write(void *context, unsigned int reg, case 4: writesl(ctx->regs + reg, (const u32 *)val, val_count); break; -#ifdef CONFIG_64BIT - case 8: - writesq(ctx->regs + reg, (const u64 *)val, val_count); - break; -#endif default: ret = -EINVAL; break; @@ -363,11 +349,6 @@ static int regmap_mmio_noinc_read(void *context, unsigned int reg, case 4: readsl(ctx->regs + reg, (u32 *)val, val_count); break; -#ifdef CONFIG_64BIT - case 8: - readsq(ctx->regs + reg, (u64 *)val, val_count); - break; -#endif default: ret = -EINVAL; goto out_clk; @@ -387,11 +368,6 @@ static int regmap_mmio_noinc_read(void *context, unsigned int reg, case 4: swab32_array(val, val_count); break; -#ifdef CONFIG_64BIT - case 8: - swab64_array(val, val_count); - break; -#endif default: ret = -EINVAL; break; diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 1bfd1727b4da..884cb51c8f67 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -311,26 +311,6 @@ static void regmap_format_32_native(void *buf, unsigned int val, memcpy(buf, &v, sizeof(v)); } -#ifdef CONFIG_64BIT -static void regmap_format_64_be(void *buf, unsigned int val, unsigned int shift) -{ - put_unaligned_be64((u64) val << shift, buf); -} - -static void regmap_format_64_le(void *buf, unsigned int val, unsigned int shift) -{ - put_unaligned_le64((u64) val << shift, buf); -} - -static void regmap_format_64_native(void *buf, unsigned int val, - unsigned int shift) -{ - u64 v = (u64) val << shift; - - memcpy(buf, &v, sizeof(v)); -} -#endif - static void regmap_parse_inplace_noop(void *buf) { } @@ -411,40 +391,6 @@ static unsigned int regmap_parse_32_native(const void *buf) return v; } -#ifdef CONFIG_64BIT -static unsigned int regmap_parse_64_be(const void *buf) -{ - return get_unaligned_be64(buf); -} - -static unsigned int regmap_parse_64_le(const void *buf) -{ - return get_unaligned_le64(buf); -} - -static void regmap_parse_64_be_inplace(void *buf) -{ - u64 v = get_unaligned_be64(buf); - - memcpy(buf, &v, sizeof(v)); -} - -static void regmap_parse_64_le_inplace(void *buf) -{ - u64 v = get_unaligned_le64(buf); - - memcpy(buf, &v, sizeof(v)); -} - -static unsigned int regmap_parse_64_native(const void *buf) -{ - u64 v; - - memcpy(&v, buf, sizeof(v)); - return v; -} -#endif - static void regmap_lock_hwlock(void *__map) { struct regmap *map = __map; @@ -1005,24 +951,6 @@ struct regmap *__regmap_init(struct device *dev, } break; -#ifdef CONFIG_64BIT - case 64: - switch (reg_endian) { - case REGMAP_ENDIAN_BIG: - map->format.format_reg = regmap_format_64_be; - break; - case REGMAP_ENDIAN_LITTLE: - map->format.format_reg = regmap_format_64_le; - break; - case REGMAP_ENDIAN_NATIVE: - map->format.format_reg = regmap_format_64_native; - break; - default: - goto err_hwlock; - } - break; -#endif - default: goto err_hwlock; } @@ -1086,28 +1014,6 @@ struct regmap *__regmap_init(struct device *dev, goto err_hwlock; } break; -#ifdef CONFIG_64BIT - case 64: - switch (val_endian) { - case REGMAP_ENDIAN_BIG: - map->format.format_val = regmap_format_64_be; - map->format.parse_val = regmap_parse_64_be; - map->format.parse_inplace = regmap_parse_64_be_inplace; - break; - case REGMAP_ENDIAN_LITTLE: - map->format.format_val = regmap_format_64_le; - map->format.parse_val = regmap_parse_64_le; - map->format.parse_inplace = regmap_parse_64_le_inplace; - break; - case REGMAP_ENDIAN_NATIVE: - map->format.format_val = regmap_format_64_native; - map->format.parse_val = regmap_parse_64_native; - break; - default: - goto err_hwlock; - } - break; -#endif } if (map->format.format_write) { @@ -2158,9 +2064,6 @@ static int regmap_noinc_readwrite(struct regmap *map, unsigned int reg, u8 *u8p; u16 *u16p; u32 *u32p; -#ifdef CONFIG_64BIT - u64 *u64p; -#endif int ret; int i; @@ -2180,13 +2083,6 @@ static int regmap_noinc_readwrite(struct regmap *map, unsigned int reg, if (write) lastval = (unsigned int)u32p[val_count - 1]; break; -#ifdef CONFIG_64BIT - case 8: - u64p = val; - if (write) - lastval = (unsigned int)u64p[val_count - 1]; - break; -#endif default: return -EINVAL; } @@ -2224,11 +2120,6 @@ static int regmap_noinc_readwrite(struct regmap *map, unsigned int reg, case 4: pr_cont("%x", u32p[i]); break; -#ifdef CONFIG_64BIT - case 8: - pr_cont("%llx", u64p[i]); - break; -#endif default: break; } @@ -2436,11 +2327,6 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, case 4: ival = *(u32 *)(val + (i * val_bytes)); break; -#ifdef CONFIG_64BIT - case 8: - ival = *(u64 *)(val + (i * val_bytes)); - break; -#endif default: ret = -EINVAL; goto out; @@ -3205,9 +3091,6 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, for (i = 0; i < val_count * val_bytes; i += val_bytes) map->format.parse_inplace(val + i); } else { -#ifdef CONFIG_64BIT - u64 *u64 = val; -#endif u32 *u32 = val; u16 *u16 = val; u8 *u8 = val; @@ -3223,11 +3106,6 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, goto out; switch (map->format.val_bytes) { -#ifdef CONFIG_64BIT - case 8: - u64[i] = ival; - break; -#endif case 4: u32[i] = ival; break; diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index e460c9799d9f..2b98114a9fe0 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -1547,7 +1547,6 @@ static int fd_locked_ioctl(struct block_device *bdev, blk_mode_t mode, rel_fdc(); return -EBUSY; } - fsync_bdev(bdev); if (fd_motor_on(drive) == 0) { rel_fdc(); return -ENODEV; diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 2db9b186b977..ea4eb88a2e45 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3255,7 +3255,7 @@ static int set_geometry(unsigned int cmd, struct floppy_struct *g, if (!disk || ITYPE(drive_state[cnt].fd_device) != type) continue; - __invalidate_device(disk->part0, true); + disk_force_media_change(disk); } mutex_unlock(&open_lock); } else { diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 637c5bda2387..9f2d412fc560 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -603,7 +603,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, goto out_err; /* and ... switch */ - disk_force_media_change(lo->lo_disk, DISK_EVENT_MEDIA_CHANGE); + disk_force_media_change(lo->lo_disk); blk_mq_freeze_queue(lo->lo_queue); mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask); lo->lo_backing_file = file; @@ -1067,7 +1067,7 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode, /* suppress uevents while reconfiguring the device */ dev_set_uevent_suppress(disk_to_dev(lo->lo_disk), 1); - disk_force_media_change(lo->lo_disk, DISK_EVENT_MEDIA_CHANGE); + disk_force_media_change(lo->lo_disk); set_disk_ro(lo->lo_disk, (lo->lo_flags & LO_FLAGS_READ_ONLY) != 0); lo->use_dio = lo->lo_flags & LO_FLAGS_DIRECT_IO; @@ -1171,7 +1171,7 @@ static void __loop_clr_fd(struct loop_device *lo, bool release) if (!release) blk_mq_unfreeze_queue(lo->lo_queue); - disk_force_media_change(lo->lo_disk, DISK_EVENT_MEDIA_CHANGE); + disk_force_media_change(lo->lo_disk); if (lo->lo_flags & LO_FLAGS_PARTSCAN) { int err; diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 8576d696c7a2..42e0159bb258 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -1434,12 +1434,10 @@ static int nbd_start_device_ioctl(struct nbd_device *nbd) return ret; } -static void nbd_clear_sock_ioctl(struct nbd_device *nbd, - struct block_device *bdev) +static void nbd_clear_sock_ioctl(struct nbd_device *nbd) { + blk_mark_disk_dead(nbd->disk); nbd_clear_sock(nbd); - __invalidate_device(bdev, true); - nbd_bdev_reset(nbd); if (test_and_clear_bit(NBD_RT_HAS_CONFIG_REF, &nbd->config->runtime_flags)) nbd_config_put(nbd); @@ -1465,7 +1463,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, case NBD_DISCONNECT: return nbd_disconnect(nbd); case NBD_CLEAR_SOCK: - nbd_clear_sock_ioctl(nbd, bdev); + nbd_clear_sock_ioctl(nbd); return 0; case NBD_SET_SOCK: return nbd_add_socket(nbd, arg, false); diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index e0b3786ca51b..8de74dcfa18c 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -37,7 +37,7 @@ config HW_RANDOM_TIMERIOMEM config HW_RANDOM_INTEL tristate "Intel HW Random Number Generator support" - depends on (X86 || IA64) && PCI + depends on (X86 || IA64 || COMPILE_TEST) && PCI default HW_RANDOM help This driver provides kernel-side support for the Random Number @@ -50,7 +50,8 @@ config HW_RANDOM_INTEL config HW_RANDOM_AMD tristate "AMD HW Random Number Generator support" - depends on (X86 || PPC_MAPLE) && PCI + depends on (X86 || PPC_MAPLE || COMPILE_TEST) + depends on PCI && HAS_IOPORT_MAP default HW_RANDOM help This driver provides kernel-side support for the Random Number @@ -63,7 +64,7 @@ config HW_RANDOM_AMD config HW_RANDOM_ATMEL tristate "Atmel Random Number Generator support" - depends on (ARCH_AT91 || COMPILE_TEST) && HAVE_CLK && OF + depends on (ARCH_AT91 || COMPILE_TEST) default HW_RANDOM help This driver provides kernel-side support for the Random Number @@ -113,7 +114,8 @@ config HW_RANDOM_IPROC_RNG200 config HW_RANDOM_GEODE tristate "AMD Geode HW Random Number Generator support" - depends on X86_32 && PCI + depends on (X86_32 || COMPILE_TEST) + depends on PCI default HW_RANDOM help This driver provides kernel-side support for the Random Number @@ -205,7 +207,7 @@ config HW_RANDOM_OCTEON config HW_RANDOM_PASEMI tristate "PA Semi HW Random Number Generator support" - depends on PPC_PASEMI + depends on PPC_PASEMI || (PPC && COMPILE_TEST) default HW_RANDOM help This driver provides kernel-side support for the Random Number @@ -228,7 +230,7 @@ config HW_RANDOM_VIRTIO config HW_RANDOM_MXC_RNGA tristate "Freescale i.MX RNGA Random Number Generator" - depends on SOC_IMX31 + depends on SOC_IMX31 || COMPILE_TEST default HW_RANDOM help This driver provides kernel-side support for the Random Number @@ -241,7 +243,7 @@ config HW_RANDOM_MXC_RNGA config HW_RANDOM_IMX_RNGC tristate "Freescale i.MX RNGC Random Number Generator" - depends on HAS_IOMEM && HAVE_CLK + depends on HAS_IOMEM depends on SOC_IMX25 || SOC_IMX6SL || SOC_IMX6SLL || SOC_IMX6UL || COMPILE_TEST default HW_RANDOM help @@ -256,8 +258,7 @@ config HW_RANDOM_IMX_RNGC config HW_RANDOM_INGENIC_RNG tristate "Ingenic Random Number Generator support" - depends on HW_RANDOM - depends on MACH_JZ4780 || MACH_X1000 + depends on MACH_JZ4780 || MACH_X1000 || COMPILE_TEST default HW_RANDOM help This driver provides kernel-side support for the Random Number Generator @@ -271,8 +272,7 @@ config HW_RANDOM_INGENIC_RNG config HW_RANDOM_INGENIC_TRNG tristate "Ingenic True Random Number Generator support" - depends on HW_RANDOM - depends on MACH_X1830 + depends on MACH_X1830 || COMPILE_TEST default HW_RANDOM help This driver provides kernel-side support for the True Random Number Generator @@ -324,7 +324,7 @@ config HW_RANDOM_POWERNV config HW_RANDOM_HISI tristate "Hisilicon Random Number Generator support" - depends on HW_RANDOM && ARCH_HISI + depends on ARCH_HISI || COMPILE_TEST default HW_RANDOM help This driver provides kernel-side support for the Random Number @@ -348,7 +348,7 @@ config HW_RANDOM_HISTB config HW_RANDOM_ST tristate "ST Microelectronics HW Random Number Generator support" - depends on HW_RANDOM && (ARCH_STI || COMPILE_TEST) + depends on ARCH_STI || COMPILE_TEST help This driver provides kernel-side support for the Random Number Generator hardware found on STi series of SoCs. @@ -358,7 +358,7 @@ config HW_RANDOM_ST config HW_RANDOM_XGENE tristate "APM X-Gene True Random Number Generator (TRNG) support" - depends on HW_RANDOM && ARCH_XGENE + depends on ARCH_XGENE || COMPILE_TEST default HW_RANDOM help This driver provides kernel-side support for the Random Number @@ -371,7 +371,7 @@ config HW_RANDOM_XGENE config HW_RANDOM_STM32 tristate "STMicroelectronics STM32 random number generator" - depends on HW_RANDOM && (ARCH_STM32 || COMPILE_TEST) + depends on ARCH_STM32 || COMPILE_TEST depends on HAS_IOMEM default HW_RANDOM help @@ -385,8 +385,8 @@ config HW_RANDOM_STM32 config HW_RANDOM_PIC32 tristate "Microchip PIC32 Random Number Generator support" - depends on HW_RANDOM && MACH_PIC32 - default y + depends on MACH_PIC32 || COMPILE_TEST + default HW_RANDOM if MACH_PIC32 help This driver provides kernel-side support for the Random Number Generator hardware found on a PIC32. @@ -425,7 +425,8 @@ config HW_RANDOM_MESON config HW_RANDOM_CAVIUM tristate "Cavium ThunderX Random Number Generator support" - depends on HW_RANDOM && PCI && ARCH_THUNDER + depends on PCI + depends on ARCH_THUNDER || (ARM64 && COMPILE_TEST) default HW_RANDOM help This driver provides kernel-side support for the Random Number diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c index 0555e3838bce..86162a13681e 100644 --- a/drivers/char/hw_random/amd-rng.c +++ b/drivers/char/hw_random/amd-rng.c @@ -26,6 +26,7 @@ #include <linux/delay.h> #include <linux/hw_random.h> +#include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> diff --git a/drivers/char/hw_random/arm_smccc_trng.c b/drivers/char/hw_random/arm_smccc_trng.c index e34c3ea692b6..7e954341b09f 100644 --- a/drivers/char/hw_random/arm_smccc_trng.c +++ b/drivers/char/hw_random/arm_smccc_trng.c @@ -105,8 +105,6 @@ static int smccc_trng_probe(struct platform_device *pdev) trng->name = "smccc_trng"; trng->read = smccc_trng_read; - platform_set_drvdata(pdev, trng); - return devm_hwrng_register(&pdev->dev, trng); } diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c index b8effe77d80f..a37367ebcbac 100644 --- a/drivers/char/hw_random/atmel-rng.c +++ b/drivers/char/hw_random/atmel-rng.c @@ -15,7 +15,7 @@ #include <linux/io.h> #include <linux/iopoll.h> #include <linux/hw_random.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> diff --git a/drivers/char/hw_random/ba431-rng.c b/drivers/char/hw_random/ba431-rng.c index 5b7ca0416490..9de7466e6896 100644 --- a/drivers/char/hw_random/ba431-rng.c +++ b/drivers/char/hw_random/ba431-rng.c @@ -189,13 +189,9 @@ static int ba431_trng_probe(struct platform_device *pdev) ba431->rng.cleanup = ba431_trng_cleanup; ba431->rng.read = ba431_trng_read; - platform_set_drvdata(pdev, ba431); - ret = devm_hwrng_register(&pdev->dev, &ba431->rng); - if (ret) { - dev_err(&pdev->dev, "BA431 registration failed (%d)\n", ret); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "BA431 registration failed\n"); dev_info(&pdev->dev, "BA431 TRNG registered\n"); @@ -203,7 +199,7 @@ static int ba431_trng_probe(struct platform_device *pdev) } static const struct of_device_id ba431_trng_dt_ids[] = { - { .compatible = "silex-insight,ba431-rng", .data = NULL }, + { .compatible = "silex-insight,ba431-rng" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, ba431_trng_dt_ids); diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c index e98fcac578d6..e19b0f9f48b9 100644 --- a/drivers/char/hw_random/bcm2835-rng.c +++ b/drivers/char/hw_random/bcm2835-rng.c @@ -8,8 +8,7 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_address.h> -#include <linux/of_platform.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/printk.h> #include <linux/clk.h> diff --git a/drivers/char/hw_random/cctrng.c b/drivers/char/hw_random/cctrng.c index 302ffa354c2f..1abbff04a015 100644 --- a/drivers/char/hw_random/cctrng.c +++ b/drivers/char/hw_random/cctrng.c @@ -455,35 +455,6 @@ static void cc_trng_startwork_handler(struct work_struct *w) cc_trng_hw_trigger(drvdata); } - -static int cc_trng_clk_init(struct cctrng_drvdata *drvdata) -{ - struct clk *clk; - struct device *dev = &(drvdata->pdev->dev); - int rc = 0; - - clk = devm_clk_get_optional(dev, NULL); - if (IS_ERR(clk)) - return dev_err_probe(dev, PTR_ERR(clk), - "Error getting clock\n"); - - drvdata->clk = clk; - - rc = clk_prepare_enable(drvdata->clk); - if (rc) { - dev_err(dev, "Failed to enable clock\n"); - return rc; - } - - return 0; -} - -static void cc_trng_clk_fini(struct cctrng_drvdata *drvdata) -{ - clk_disable_unprepare(drvdata->clk); -} - - static int cctrng_probe(struct platform_device *pdev) { struct cctrng_drvdata *drvdata; @@ -492,6 +463,10 @@ static int cctrng_probe(struct platform_device *pdev) u32 val; int irq; + /* Compile time assertion checks */ + BUILD_BUG_ON(CCTRNG_DATA_BUF_WORDS < 6); + BUILD_BUG_ON((CCTRNG_DATA_BUF_WORDS & (CCTRNG_DATA_BUF_WORDS-1)) != 0); + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; @@ -510,10 +485,8 @@ static int cctrng_probe(struct platform_device *pdev) drvdata->circ.buf = (char *)drvdata->data_buf; drvdata->cc_base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(drvdata->cc_base)) { - dev_err(dev, "Failed to ioremap registers"); - return PTR_ERR(drvdata->cc_base); - } + if (IS_ERR(drvdata->cc_base)) + return dev_err_probe(dev, PTR_ERR(drvdata->cc_base), "Failed to ioremap registers"); /* Then IRQ */ irq = platform_get_irq(pdev, 0); @@ -522,16 +495,13 @@ static int cctrng_probe(struct platform_device *pdev) /* parse sampling rate from device tree */ rc = cc_trng_parse_sampling_ratio(drvdata); - if (rc) { - dev_err(dev, "Failed to get legal sampling ratio for rosc\n"); - return rc; - } + if (rc) + return dev_err_probe(dev, rc, "Failed to get legal sampling ratio for rosc\n"); - rc = cc_trng_clk_init(drvdata); - if (rc) { - dev_err(dev, "cc_trng_clk_init failed\n"); - return rc; - } + drvdata->clk = devm_clk_get_optional_enabled(dev, NULL); + if (IS_ERR(drvdata->clk)) + return dev_err_probe(dev, PTR_ERR(drvdata->clk), + "Failed to get or enable the clock\n"); INIT_WORK(&drvdata->compwork, cc_trng_compwork_handler); INIT_WORK(&drvdata->startwork, cc_trng_startwork_handler); @@ -539,10 +509,8 @@ static int cctrng_probe(struct platform_device *pdev) /* register the driver isr function */ rc = devm_request_irq(dev, irq, cc_isr, IRQF_SHARED, "cctrng", drvdata); - if (rc) { - dev_err(dev, "Could not register to interrupt %d\n", irq); - goto post_clk_err; - } + if (rc) + return dev_err_probe(dev, rc, "Could not register to interrupt %d\n", irq); dev_dbg(dev, "Registered to IRQ: %d\n", irq); /* Clear all pending interrupts */ @@ -557,17 +525,13 @@ static int cctrng_probe(struct platform_device *pdev) /* init PM */ rc = cc_trng_pm_init(drvdata); - if (rc) { - dev_err(dev, "cc_trng_pm_init failed\n"); - goto post_clk_err; - } + if (rc) + return dev_err_probe(dev, rc, "cc_trng_pm_init failed\n"); /* increment device's usage counter */ rc = cc_trng_pm_get(dev); - if (rc) { - dev_err(dev, "cc_trng_pm_get returned %x\n", rc); - goto post_pm_err; - } + if (rc) + return dev_err_probe(dev, rc, "cc_trng_pm_get returned %x\n", rc); /* set pending_hw to verify that HW won't be triggered from read */ atomic_set(&drvdata->pending_hw, 1); @@ -593,9 +557,6 @@ static int cctrng_probe(struct platform_device *pdev) post_pm_err: cc_trng_pm_fini(drvdata); -post_clk_err: - cc_trng_clk_fini(drvdata); - return rc; } @@ -608,8 +569,6 @@ static int cctrng_remove(struct platform_device *pdev) cc_trng_pm_fini(drvdata); - cc_trng_clk_fini(drvdata); - dev_info(dev, "ARM cctrng device terminated\n"); return 0; @@ -698,21 +657,7 @@ static struct platform_driver cctrng_driver = { .remove = cctrng_remove, }; -static int __init cctrng_mod_init(void) -{ - /* Compile time assertion checks */ - BUILD_BUG_ON(CCTRNG_DATA_BUF_WORDS < 6); - BUILD_BUG_ON((CCTRNG_DATA_BUF_WORDS & (CCTRNG_DATA_BUF_WORDS-1)) != 0); - - return platform_driver_register(&cctrng_driver); -} -module_init(cctrng_mod_init); - -static void __exit cctrng_mod_exit(void) -{ - platform_driver_unregister(&cctrng_driver); -} -module_exit(cctrng_mod_exit); +module_platform_driver(cctrng_driver); /* Module description */ MODULE_DESCRIPTION("ARM CryptoCell TRNG Driver"); diff --git a/drivers/char/hw_random/cn10k-rng.c b/drivers/char/hw_random/cn10k-rng.c index 0cd7e1a8e499..31935316a160 100644 --- a/drivers/char/hw_random/cn10k-rng.c +++ b/drivers/char/hw_random/cn10k-rng.c @@ -187,10 +187,8 @@ static int cn10k_rng_probe(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_drvdata(pdev, rng); rng->reg_base = pcim_iomap(pdev, 0, 0); - if (!rng->reg_base) { - dev_err(&pdev->dev, "Error while mapping CSRs, exiting\n"); - return -ENOMEM; - } + if (!rng->reg_base) + return dev_err_probe(&pdev->dev, -ENOMEM, "Error while mapping CSRs, exiting\n"); rng->ops.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "cn10k-rng-%s", dev_name(&pdev->dev)); @@ -205,19 +203,12 @@ static int cn10k_rng_probe(struct pci_dev *pdev, const struct pci_device_id *id) reset_rng_health_state(rng); err = devm_hwrng_register(&pdev->dev, &rng->ops); - if (err) { - dev_err(&pdev->dev, "Could not register hwrng device.\n"); - return err; - } + if (err) + return dev_err_probe(&pdev->dev, err, "Could not register hwrng device.\n"); return 0; } -static void cn10k_rng_remove(struct pci_dev *pdev) -{ - /* Nothing to do */ -} - static const struct pci_device_id cn10k_rng_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xA098) }, /* RNG PF */ {0,}, @@ -229,7 +220,6 @@ static struct pci_driver cn10k_rng_driver = { .name = "cn10k_rng", .id_table = cn10k_rng_id_table, .probe = cn10k_rng_probe, - .remove = cn10k_rng_remove, }; module_pci_driver(cn10k_rng_driver); diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index f34d356fe2c0..e3598ec9cfca 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -15,14 +15,13 @@ #include <linux/err.h> #include <linux/fs.h> #include <linux/hw_random.h> -#include <linux/random.h> #include <linux/kernel.h> #include <linux/kthread.h> -#include <linux/sched/signal.h> #include <linux/miscdevice.h> #include <linux/module.h> #include <linux/random.h> #include <linux/sched.h> +#include <linux/sched/signal.h> #include <linux/slab.h> #include <linux/uaccess.h> diff --git a/drivers/char/hw_random/exynos-trng.c b/drivers/char/hw_random/exynos-trng.c index 9cc3d542dd0f..30207b7ac5f4 100644 --- a/drivers/char/hw_random/exynos-trng.c +++ b/drivers/char/hw_random/exynos-trng.c @@ -185,14 +185,14 @@ static int exynos_trng_remove(struct platform_device *pdev) return 0; } -static int __maybe_unused exynos_trng_suspend(struct device *dev) +static int exynos_trng_suspend(struct device *dev) { pm_runtime_put_sync(dev); return 0; } -static int __maybe_unused exynos_trng_resume(struct device *dev) +static int exynos_trng_resume(struct device *dev) { int ret; @@ -205,7 +205,7 @@ static int __maybe_unused exynos_trng_resume(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(exynos_trng_pm_ops, exynos_trng_suspend, +static DEFINE_SIMPLE_DEV_PM_OPS(exynos_trng_pm_ops, exynos_trng_suspend, exynos_trng_resume); static const struct of_device_id exynos_trng_dt_match[] = { @@ -219,7 +219,7 @@ MODULE_DEVICE_TABLE(of, exynos_trng_dt_match); static struct platform_driver exynos_trng_driver = { .driver = { .name = "exynos-trng", - .pm = &exynos_trng_pm_ops, + .pm = pm_sleep_ptr(&exynos_trng_pm_ops), .of_match_table = exynos_trng_dt_match, }, .probe = exynos_trng_probe, diff --git a/drivers/char/hw_random/imx-rngc.c b/drivers/char/hw_random/imx-rngc.c index bf07f17f78c8..e4b385b01b11 100644 --- a/drivers/char/hw_random/imx-rngc.c +++ b/drivers/char/hw_random/imx-rngc.c @@ -239,10 +239,8 @@ static int __init imx_rngc_probe(struct platform_device *pdev) return PTR_ERR(rngc->base); rngc->clk = devm_clk_get_enabled(&pdev->dev, NULL); - if (IS_ERR(rngc->clk)) { - dev_err(&pdev->dev, "Can not get rng_clk\n"); - return PTR_ERR(rngc->clk); - } + if (IS_ERR(rngc->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(rngc->clk), "Cannot get rng_clk\n"); irq = platform_get_irq(pdev, 0); if (irq < 0) @@ -272,24 +270,18 @@ static int __init imx_rngc_probe(struct platform_device *pdev) ret = devm_request_irq(&pdev->dev, irq, imx_rngc_irq, 0, pdev->name, (void *)rngc); - if (ret) { - dev_err(rngc->dev, "Can't get interrupt working.\n"); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "Can't get interrupt working.\n"); if (self_test) { ret = imx_rngc_self_test(rngc); - if (ret) { - dev_err(rngc->dev, "self test failed\n"); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "self test failed\n"); } ret = devm_hwrng_register(&pdev->dev, &rngc->rng); - if (ret) { - dev_err(&pdev->dev, "hwrng registration failed\n"); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "hwrng registration failed\n"); dev_info(&pdev->dev, "Freescale RNG%c registered (HW revision %d.%02d)\n", diff --git a/drivers/char/hw_random/ingenic-rng.c b/drivers/char/hw_random/ingenic-rng.c index 055cfe59f519..4f18c3fa5427 100644 --- a/drivers/char/hw_random/ingenic-rng.c +++ b/drivers/char/hw_random/ingenic-rng.c @@ -95,7 +95,7 @@ static int ingenic_rng_probe(struct platform_device *pdev) return PTR_ERR(priv->base); } - priv->version = (enum ingenic_rng_version)of_device_get_match_data(&pdev->dev); + priv->version = (enum ingenic_rng_version)(uintptr_t)of_device_get_match_data(&pdev->dev); priv->rng.name = pdev->name; priv->rng.init = ingenic_rng_init; diff --git a/drivers/char/hw_random/ingenic-trng.c b/drivers/char/hw_random/ingenic-trng.c index 0eb80f786f4d..1672320e7d3d 100644 --- a/drivers/char/hw_random/ingenic-trng.c +++ b/drivers/char/hw_random/ingenic-trng.c @@ -11,8 +11,8 @@ #include <linux/hw_random.h> #include <linux/io.h> #include <linux/iopoll.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/slab.h> @@ -22,8 +22,6 @@ #define TRNG_REG_STATUS_OFFSET 0x08 /* bits within the CFG register */ -#define CFG_RDY_CLR BIT(12) -#define CFG_INT_MASK BIT(11) #define CFG_GEN_EN BIT(0) /* bits within the STATUS register */ @@ -31,7 +29,6 @@ struct ingenic_trng { void __iomem *base; - struct clk *clk; struct hwrng rng; }; @@ -79,6 +76,7 @@ static int ingenic_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait static int ingenic_trng_probe(struct platform_device *pdev) { struct ingenic_trng *trng; + struct clk *clk; int ret; trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL); @@ -86,60 +84,28 @@ static int ingenic_trng_probe(struct platform_device *pdev) return -ENOMEM; trng->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(trng->base)) { - pr_err("%s: Failed to map DTRNG registers\n", __func__); - ret = PTR_ERR(trng->base); - return PTR_ERR(trng->base); - } + if (IS_ERR(trng->base)) + return dev_err_probe(&pdev->dev, PTR_ERR(trng->base), + "%s: Failed to map DTRNG registers\n", __func__); - trng->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(trng->clk)) { - ret = PTR_ERR(trng->clk); - pr_crit("%s: Cannot get DTRNG clock\n", __func__); - return PTR_ERR(trng->clk); - } - - ret = clk_prepare_enable(trng->clk); - if (ret) { - pr_crit("%s: Unable to enable DTRNG clock\n", __func__); - return ret; - } + clk = devm_clk_get_enabled(&pdev->dev, NULL); + if (IS_ERR(clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(clk), + "%s: Cannot get and enable DTRNG clock\n", __func__); trng->rng.name = pdev->name; trng->rng.init = ingenic_trng_init; trng->rng.cleanup = ingenic_trng_cleanup; trng->rng.read = ingenic_trng_read; - ret = hwrng_register(&trng->rng); - if (ret) { - dev_err(&pdev->dev, "Failed to register hwrng\n"); - goto err_unprepare_clk; - } + ret = devm_hwrng_register(&pdev->dev, &trng->rng); + if (ret) + return dev_err_probe(&pdev->dev, ret, "Failed to register hwrng\n"); platform_set_drvdata(pdev, trng); dev_info(&pdev->dev, "Ingenic DTRNG driver registered\n"); return 0; - -err_unprepare_clk: - clk_disable_unprepare(trng->clk); - return ret; -} - -static int ingenic_trng_remove(struct platform_device *pdev) -{ - struct ingenic_trng *trng = platform_get_drvdata(pdev); - unsigned int ctrl; - - hwrng_unregister(&trng->rng); - - ctrl = readl(trng->base + TRNG_REG_CFG_OFFSET); - ctrl &= ~CFG_GEN_EN; - writel(ctrl, trng->base + TRNG_REG_CFG_OFFSET); - - clk_disable_unprepare(trng->clk); - - return 0; } static const struct of_device_id ingenic_trng_of_match[] = { @@ -150,7 +116,6 @@ MODULE_DEVICE_TABLE(of, ingenic_trng_of_match); static struct platform_driver ingenic_trng_driver = { .probe = ingenic_trng_probe, - .remove = ingenic_trng_remove, .driver = { .name = "ingenic-trng", .of_match_table = ingenic_trng_of_match, diff --git a/drivers/char/hw_random/iproc-rng200.c b/drivers/char/hw_random/iproc-rng200.c index 06bc060534d8..440fe28bddc0 100644 --- a/drivers/char/hw_random/iproc-rng200.c +++ b/drivers/char/hw_random/iproc-rng200.c @@ -12,8 +12,7 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_address.h> -#include <linux/of_platform.h> +#include <linux/mod_devicetable.h> #include <linux/platform_device.h> #include <linux/delay.h> @@ -182,6 +181,8 @@ static int iproc_rng200_probe(struct platform_device *pdev) return PTR_ERR(priv->base); } + dev_set_drvdata(dev, priv); + priv->rng.name = "iproc-rng200"; priv->rng.read = iproc_rng200_read; priv->rng.init = iproc_rng200_init; @@ -199,6 +200,28 @@ static int iproc_rng200_probe(struct platform_device *pdev) return 0; } +static int __maybe_unused iproc_rng200_suspend(struct device *dev) +{ + struct iproc_rng200_dev *priv = dev_get_drvdata(dev); + + iproc_rng200_cleanup(&priv->rng); + + return 0; +} + +static int __maybe_unused iproc_rng200_resume(struct device *dev) +{ + struct iproc_rng200_dev *priv = dev_get_drvdata(dev); + + iproc_rng200_init(&priv->rng); + + return 0; +} + +static const struct dev_pm_ops iproc_rng200_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(iproc_rng200_suspend, iproc_rng200_resume) +}; + static const struct of_device_id iproc_rng200_of_match[] = { { .compatible = "brcm,bcm2711-rng200", }, { .compatible = "brcm,bcm7211-rng200", }, @@ -212,6 +235,7 @@ static struct platform_driver iproc_rng200_driver = { .driver = { .name = "iproc-rng200", .of_match_table = iproc_rng200_of_match, + .pm = &iproc_rng200_pm_ops, }, .probe = iproc_rng200_probe, }; diff --git a/drivers/char/hw_random/nomadik-rng.c b/drivers/char/hw_random/nomadik-rng.c index e8f9621e7954..8c6a40d6ce3d 100644 --- a/drivers/char/hw_random/nomadik-rng.c +++ b/drivers/char/hw_random/nomadik-rng.c @@ -13,8 +13,6 @@ #include <linux/clk.h> #include <linux/err.h> -static struct clk *rng_clk; - static int nmk_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) { void __iomem *base = (void __iomem *)rng->priv; @@ -36,21 +34,17 @@ static struct hwrng nmk_rng = { static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id) { + struct clk *rng_clk; void __iomem *base; int ret; - rng_clk = devm_clk_get(&dev->dev, NULL); - if (IS_ERR(rng_clk)) { - dev_err(&dev->dev, "could not get rng clock\n"); - ret = PTR_ERR(rng_clk); - return ret; - } - - clk_prepare_enable(rng_clk); + rng_clk = devm_clk_get_enabled(&dev->dev, NULL); + if (IS_ERR(rng_clk)) + return dev_err_probe(&dev->dev, PTR_ERR(rng_clk), "could not get rng clock\n"); ret = amba_request_regions(dev, dev->dev.init_name); if (ret) - goto out_clk; + return ret; ret = -ENOMEM; base = devm_ioremap(&dev->dev, dev->res.start, resource_size(&dev->res)); @@ -64,15 +58,12 @@ static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id) out_release: amba_release_regions(dev); -out_clk: - clk_disable_unprepare(rng_clk); return ret; } static void nmk_rng_remove(struct amba_device *dev) { amba_release_regions(dev); - clk_disable_unprepare(rng_clk); } static const struct amba_id nmk_rng_ids[] = { diff --git a/drivers/char/hw_random/npcm-rng.c b/drivers/char/hw_random/npcm-rng.c index 9903d0357e06..8a304b754217 100644 --- a/drivers/char/hw_random/npcm-rng.c +++ b/drivers/char/hw_random/npcm-rng.c @@ -8,12 +8,11 @@ #include <linux/init.h> #include <linux/random.h> #include <linux/err.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/hw_random.h> #include <linux/delay.h> -#include <linux/of_irq.h> #include <linux/pm_runtime.h> -#include <linux/of_device.h> #define NPCM_RNGCS_REG 0x00 /* Control and status register */ #define NPCM_RNGD_REG 0x04 /* Data register */ diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index 00ff96703dd2..be03f76a2a80 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c @@ -26,8 +26,6 @@ #include <linux/slab.h> #include <linux/pm_runtime.h> #include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_address.h> #include <linux/interrupt.h> #include <linux/clk.h> #include <linux/io.h> diff --git a/drivers/char/hw_random/omap3-rom-rng.c b/drivers/char/hw_random/omap3-rom-rng.c index f06e4f95114f..18dc46b1b58e 100644 --- a/drivers/char/hw_random/omap3-rom-rng.c +++ b/drivers/char/hw_random/omap3-rom-rng.c @@ -20,7 +20,6 @@ #include <linux/err.h> #include <linux/io.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c index 2498d4ef9fe2..6959d6edd44c 100644 --- a/drivers/char/hw_random/pasemi-rng.c +++ b/drivers/char/hw_random/pasemi-rng.c @@ -9,11 +9,10 @@ #include <linux/module.h> #include <linux/kernel.h> +#include <linux/mod_devicetable.h> #include <linux/platform_device.h> #include <linux/hw_random.h> #include <linux/delay.h> -#include <linux/of_address.h> -#include <linux/of_platform.h> #include <linux/io.h> #define SDCRNG_CTL_REG 0x00 diff --git a/drivers/char/hw_random/pic32-rng.c b/drivers/char/hw_random/pic32-rng.c index 99c8bd0859a1..888e6f5cec1f 100644 --- a/drivers/char/hw_random/pic32-rng.c +++ b/drivers/char/hw_random/pic32-rng.c @@ -12,31 +12,22 @@ #include <linux/hw_random.h> #include <linux/io.h> #include <linux/kernel.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/slab.h> #define RNGCON 0x04 -#define TRNGEN BIT(8) -#define PRNGEN BIT(9) -#define PRNGCONT BIT(10) -#define TRNGMOD BIT(11) -#define SEEDLOAD BIT(12) -#define RNGPOLY1 0x08 -#define RNGPOLY2 0x0C -#define RNGNUMGEN1 0x10 -#define RNGNUMGEN2 0x14 +#define TRNGEN BIT(8) +#define TRNGMOD BIT(11) #define RNGSEED1 0x18 #define RNGSEED2 0x1C #define RNGRCNT 0x20 -#define RCNT_MASK 0x7F +#define RCNT_MASK 0x7F struct pic32_rng { void __iomem *base; struct hwrng rng; - struct clk *clk; }; /* @@ -46,6 +37,15 @@ struct pic32_rng { */ #define RNG_TIMEOUT 500 +static int pic32_rng_init(struct hwrng *rng) +{ + struct pic32_rng *priv = container_of(rng, struct pic32_rng, rng); + + /* enable TRNG in enhanced mode */ + writel(TRNGEN | TRNGMOD, priv->base + RNGCON); + return 0; +} + static int pic32_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) { @@ -67,11 +67,17 @@ static int pic32_rng_read(struct hwrng *rng, void *buf, size_t max, return -EIO; } +static void pic32_rng_cleanup(struct hwrng *rng) +{ + struct pic32_rng *priv = container_of(rng, struct pic32_rng, rng); + + writel(0, priv->base + RNGCON); +} + static int pic32_rng_probe(struct platform_device *pdev) { struct pic32_rng *priv; - u32 v; - int ret; + struct clk *clk; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -81,41 +87,16 @@ static int pic32_rng_probe(struct platform_device *pdev) if (IS_ERR(priv->base)) return PTR_ERR(priv->base); - priv->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(priv->clk)) - return PTR_ERR(priv->clk); - - ret = clk_prepare_enable(priv->clk); - if (ret) - return ret; - - /* enable TRNG in enhanced mode */ - v = TRNGEN | TRNGMOD; - writel(v, priv->base + RNGCON); + clk = devm_clk_get_enabled(&pdev->dev, NULL); + if (IS_ERR(clk)) + return PTR_ERR(clk); priv->rng.name = pdev->name; + priv->rng.init = pic32_rng_init; priv->rng.read = pic32_rng_read; + priv->rng.cleanup = pic32_rng_cleanup; - ret = devm_hwrng_register(&pdev->dev, &priv->rng); - if (ret) - goto err_register; - - platform_set_drvdata(pdev, priv); - - return 0; - -err_register: - clk_disable_unprepare(priv->clk); - return ret; -} - -static int pic32_rng_remove(struct platform_device *pdev) -{ - struct pic32_rng *rng = platform_get_drvdata(pdev); - - writel(0, rng->base + RNGCON); - clk_disable_unprepare(rng->clk); - return 0; + return devm_hwrng_register(&pdev->dev, &priv->rng); } static const struct of_device_id pic32_rng_of_match[] __maybe_unused = { @@ -126,10 +107,9 @@ MODULE_DEVICE_TABLE(of, pic32_rng_of_match); static struct platform_driver pic32_rng_driver = { .probe = pic32_rng_probe, - .remove = pic32_rng_remove, .driver = { .name = "pic32-rng", - .of_match_table = of_match_ptr(pic32_rng_of_match), + .of_match_table = pic32_rng_of_match, }, }; diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c index a6731cf0627a..efb6a9f9a11b 100644 --- a/drivers/char/hw_random/stm32-rng.c +++ b/drivers/char/hw_random/stm32-rng.c @@ -10,8 +10,9 @@ #include <linux/iopoll.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/reset.h> #include <linux/slab.h> diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c index 26f322d19a88..3db9d868efb1 100644 --- a/drivers/char/hw_random/timeriomem-rng.c +++ b/drivers/char/hw_random/timeriomem-rng.c @@ -113,16 +113,6 @@ static int timeriomem_rng_probe(struct platform_device *pdev) return -EINVAL; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENXIO; - - if (res->start % 4 != 0 || resource_size(res) < 4) { - dev_err(&pdev->dev, - "address must be at least four bytes wide and 32-bit aligned\n"); - return -EINVAL; - } - /* Allocate memory for the device structure (and zero it) */ priv = devm_kzalloc(&pdev->dev, sizeof(struct timeriomem_rng_private), GFP_KERNEL); @@ -131,6 +121,16 @@ static int timeriomem_rng_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); + priv->io_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(priv->io_base)) + return PTR_ERR(priv->io_base); + + if (res->start % 4 != 0 || resource_size(res) < 4) { + dev_err(&pdev->dev, + "address must be at least four bytes wide and 32-bit aligned\n"); + return -EINVAL; + } + if (pdev->dev.of_node) { int i; @@ -158,11 +158,6 @@ static int timeriomem_rng_probe(struct platform_device *pdev) priv->rng_ops.name = dev_name(&pdev->dev); priv->rng_ops.read = timeriomem_rng_read; - priv->io_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(priv->io_base)) { - return PTR_ERR(priv->io_base); - } - /* Assume random data is already available. */ priv->present = 1; complete(&priv->completion); diff --git a/drivers/char/hw_random/xgene-rng.c b/drivers/char/hw_random/xgene-rng.c index 7c8f3cb7c6af..99f4e86ac3e9 100644 --- a/drivers/char/hw_random/xgene-rng.c +++ b/drivers/char/hw_random/xgene-rng.c @@ -14,10 +14,10 @@ #include <linux/hw_random.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/io.h> #include <linux/module.h> -#include <linux/of_platform.h> -#include <linux/of_irq.h> -#include <linux/of_address.h> +#include <linux/mod_devicetable.h> +#include <linux/platform_device.h> #include <linux/timer.h> #define RNG_MAX_DATUM 4 diff --git a/drivers/char/hw_random/xiphera-trng.c b/drivers/char/hw_random/xiphera-trng.c index 2a9fea72b2e0..2c586d1fe8a9 100644 --- a/drivers/char/hw_random/xiphera-trng.c +++ b/drivers/char/hw_random/xiphera-trng.c @@ -7,7 +7,6 @@ #include <linux/err.h> #include <linux/io.h> #include <linux/hw_random.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/delay.h> diff --git a/drivers/char/tpm/eventlog/tpm1.c b/drivers/char/tpm/eventlog/tpm1.c index 8aa9057601d6..12ee42a31c71 100644 --- a/drivers/char/tpm/eventlog/tpm1.c +++ b/drivers/char/tpm/eventlog/tpm1.c @@ -251,7 +251,6 @@ static int tpm1_binary_bios_measurements_show(struct seq_file *m, void *v) static int tpm1_ascii_bios_measurements_show(struct seq_file *m, void *v) { - int len = 0; char *eventname; struct tcpa_event *event = v; unsigned char *event_entry = @@ -273,7 +272,7 @@ static int tpm1_ascii_bios_measurements_show(struct seq_file *m, void *v) /* 3rd: event type identifier */ seq_printf(m, " %02x", do_endian_conversion(event->event_type)); - len += get_event_name(eventname, event, event_entry); + get_event_name(eventname, event, event_entry); /* 4th: eventname <= max + \'0' delimiter */ seq_printf(m, " %s\n", eventname); diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 7fa3d91042b2..077fdb73740c 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -27,7 +27,6 @@ #include <linux/of.h> #include <linux/of_device.h> #include <linux/kernel.h> -#include <linux/dmi.h> #include "tpm.h" #include "tpm_tis_core.h" @@ -89,8 +88,8 @@ static inline void tpm_tis_iowrite32(u32 b, void __iomem *iobase, u32 addr) tpm_tis_flush(iobase); } -static int interrupts; -module_param(interrupts, int, 0444); +static bool interrupts; +module_param(interrupts, bool, 0444); MODULE_PARM_DESC(interrupts, "Enable interrupts"); static bool itpm; @@ -103,92 +102,6 @@ module_param(force, bool, 0444); MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry"); #endif -static int tpm_tis_disable_irq(const struct dmi_system_id *d) -{ - if (interrupts == -1) { - pr_notice("tpm_tis: %s detected: disabling interrupts.\n", d->ident); - interrupts = 0; - } - - return 0; -} - -static const struct dmi_system_id tpm_tis_dmi_table[] = { - { - .callback = tpm_tis_disable_irq, - .ident = "Framework Laptop (12th Gen Intel Core)", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Framework"), - DMI_MATCH(DMI_PRODUCT_NAME, "Laptop (12th Gen Intel Core)"), - }, - }, - { - .callback = tpm_tis_disable_irq, - .ident = "Framework Laptop (13th Gen Intel Core)", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Framework"), - DMI_MATCH(DMI_PRODUCT_NAME, "Laptop (13th Gen Intel Core)"), - }, - }, - { - .callback = tpm_tis_disable_irq, - .ident = "ThinkPad T490s", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T490s"), - }, - }, - { - .callback = tpm_tis_disable_irq, - .ident = "ThinkStation P360 Tiny", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkStation P360 Tiny"), - }, - }, - { - .callback = tpm_tis_disable_irq, - .ident = "ThinkPad L490", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L490"), - }, - }, - { - .callback = tpm_tis_disable_irq, - .ident = "ThinkPad L590", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L590"), - }, - }, - { - .callback = tpm_tis_disable_irq, - .ident = "ThinkStation P620", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkStation P620"), - }, - }, - { - .callback = tpm_tis_disable_irq, - .ident = "TUXEDO InfinityBook S 15/17 Gen7", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "TUXEDO"), - DMI_MATCH(DMI_PRODUCT_NAME, "TUXEDO InfinityBook S 15/17 Gen7"), - }, - }, - { - .callback = tpm_tis_disable_irq, - .ident = "UPX-TGL", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), - DMI_MATCH(DMI_PRODUCT_NAME, "UPX-TGL01"), - }, - }, - {} -}; - #if defined(CONFIG_PNP) && defined(CONFIG_ACPI) static int has_hid(struct acpi_device *dev, const char *hid) { @@ -312,8 +225,6 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info) int irq = -1; int rc; - dmi_check_system(tpm_tis_dmi_table); - rc = check_acpi_tpm2(dev); if (rc) return rc; diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index b95963095729..1b350412d8a6 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -340,7 +340,7 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) return size; } -static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) +static int tpm_tis_try_recv(struct tpm_chip *chip, u8 *buf, size_t count) { struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); int size = 0; @@ -348,11 +348,6 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) u32 expected; int rc; - if (count < TPM_HEADER_SIZE) { - size = -EIO; - goto out; - } - size = recv_data(chip, buf, TPM_HEADER_SIZE); /* read first 10 bytes, including tag, paramsize, and result */ if (size < TPM_HEADER_SIZE) { @@ -385,7 +380,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) goto out; } status = tpm_tis_status(chip); - if (status & TPM_STS_DATA_AVAIL) { /* retry? */ + if (status & TPM_STS_DATA_AVAIL) { dev_err(&chip->dev, "Error left over data\n"); size = -EIO; goto out; @@ -399,10 +394,36 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) } out: - tpm_tis_ready(chip); return size; } +static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) +{ + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); + unsigned int try; + int rc = 0; + + if (count < TPM_HEADER_SIZE) + return -EIO; + + for (try = 0; try < TPM_RETRY; try++) { + rc = tpm_tis_try_recv(chip, buf, count); + + if (rc == -EIO) + /* Data transfer errors, indicated by EIO, can be + * recovered by rereading the response. + */ + tpm_tis_write8(priv, TPM_STS(priv->locality), + TPM_STS_RESPONSE_RETRY); + else + break; + } + + tpm_tis_ready(chip); + + return rc; +} + /* * If interrupts are used (signaled by an irq set in the vendor structure) * tpm.c can skip polling for the data to be available as the interrupt is @@ -469,6 +490,12 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len) goto out_err; } + rc = tpm_tis_verify_crc(priv, len, buf); + if (rc < 0) { + dev_err(&chip->dev, "CRC mismatch for command.\n"); + goto out_err; + } + return 0; out_err: @@ -512,15 +539,16 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len) int rc; u32 ordinal; unsigned long dur; + unsigned int try; - rc = tpm_tis_send_data(chip, buf, len); - if (rc < 0) - return rc; - - rc = tpm_tis_verify_crc(priv, len, buf); - if (rc < 0) { - dev_err(&chip->dev, "CRC mismatch for command.\n"); - return rc; + for (try = 0; try < TPM_RETRY; try++) { + rc = tpm_tis_send_data(chip, buf, len); + if (rc >= 0) + /* Data transfer done successfully */ + break; + else if (rc != -EIO) + /* Data transfer failed, not recoverable */ + return rc; } /* go and do it */ diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h index b1a169d7d1ca..13e99cf65efe 100644 --- a/drivers/char/tpm/tpm_tis_core.h +++ b/drivers/char/tpm/tpm_tis_core.h @@ -34,6 +34,7 @@ enum tis_status { TPM_STS_GO = 0x20, TPM_STS_DATA_AVAIL = 0x10, TPM_STS_DATA_EXPECT = 0x08, + TPM_STS_RESPONSE_RETRY = 0x02, TPM_STS_READ_ZERO = 0x23, /* bits that must be zero on read */ }; diff --git a/drivers/char/tpm/tpm_tis_spi_main.c b/drivers/char/tpm/tpm_tis_spi_main.c index 9bfaba092a06..a62f5c7f38d3 100644 --- a/drivers/char/tpm/tpm_tis_spi_main.c +++ b/drivers/char/tpm/tpm_tis_spi_main.c @@ -71,8 +71,74 @@ static int tpm_tis_spi_flow_control(struct tpm_tis_spi_phy *phy, return 0; } -int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, - u8 *in, const u8 *out) +/* + * Half duplex controller with support for TPM wait state detection like + * Tegra QSPI need CMD, ADDR & DATA sent in single message to manage HW flow + * control. Each phase sent in different transfer for controller to idenity + * phase. + */ +static int tpm_tis_spi_transfer_half(struct tpm_tis_data *data, u32 addr, + u16 len, u8 *in, const u8 *out) +{ + struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); + struct spi_transfer spi_xfer[3]; + struct spi_message m; + u8 transfer_len; + int ret; + + while (len) { + transfer_len = min_t(u16, len, MAX_SPI_FRAMESIZE); + + spi_message_init(&m); + phy->iobuf[0] = (in ? 0x80 : 0) | (transfer_len - 1); + phy->iobuf[1] = 0xd4; + phy->iobuf[2] = addr >> 8; + phy->iobuf[3] = addr; + + memset(&spi_xfer, 0, sizeof(spi_xfer)); + + spi_xfer[0].tx_buf = phy->iobuf; + spi_xfer[0].len = 1; + spi_message_add_tail(&spi_xfer[0], &m); + + spi_xfer[1].tx_buf = phy->iobuf + 1; + spi_xfer[1].len = 3; + spi_message_add_tail(&spi_xfer[1], &m); + + if (out) { + spi_xfer[2].tx_buf = &phy->iobuf[4]; + spi_xfer[2].rx_buf = NULL; + memcpy(&phy->iobuf[4], out, transfer_len); + out += transfer_len; + } + + if (in) { + spi_xfer[2].tx_buf = NULL; + spi_xfer[2].rx_buf = &phy->iobuf[4]; + } + + spi_xfer[2].len = transfer_len; + spi_message_add_tail(&spi_xfer[2], &m); + + reinit_completion(&phy->ready); + + ret = spi_sync(phy->spi_device, &m); + if (ret < 0) + return ret; + + if (in) { + memcpy(in, &phy->iobuf[4], transfer_len); + in += transfer_len; + } + + len -= transfer_len; + } + + return ret; +} + +static int tpm_tis_spi_transfer_full(struct tpm_tis_data *data, u32 addr, + u16 len, u8 *in, const u8 *out) { struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); int ret = 0; @@ -148,6 +214,24 @@ exit: return ret; } +int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len, + u8 *in, const u8 *out) +{ + struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); + struct spi_controller *ctlr = phy->spi_device->controller; + + /* + * TPM flow control over SPI requires full duplex support. + * Send entire message to a half duplex controller to handle + * wait polling in controller. + * Set TPM HW flow control flag.. + */ + if (ctlr->flags & SPI_CONTROLLER_HALF_DUPLEX) + return tpm_tis_spi_transfer_half(data, addr, len, in, out); + else + return tpm_tis_spi_transfer_full(data, addr, len, in, out); +} + static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, u8 *result, enum tpm_tis_io_mode io_mode) { @@ -189,6 +273,9 @@ static int tpm_tis_spi_probe(struct spi_device *dev) phy->flow_control = tpm_tis_spi_flow_control; + if (dev->controller->flags & SPI_CONTROLLER_HALF_DUPLEX) + dev->mode |= SPI_TPM_HW_FLOW; + /* If the SPI device has an IRQ then use that */ if (dev->irq > 0) irq = dev->irq; diff --git a/drivers/char/tpm/tpm_tis_synquacer.c b/drivers/char/tpm/tpm_tis_synquacer.c index 49278746b0e2..f7d5e76b505e 100644 --- a/drivers/char/tpm/tpm_tis_synquacer.c +++ b/drivers/char/tpm/tpm_tis_synquacer.c @@ -162,23 +162,7 @@ static struct platform_driver tis_synquacer_drv = { }, }; -static int __init tpm_tis_synquacer_module_init(void) -{ - int rc; - - rc = platform_driver_register(&tis_synquacer_drv); - if (rc) - return rc; - - return 0; -} - -static void __exit tpm_tis_synquacer_module_exit(void) -{ - platform_driver_unregister(&tis_synquacer_drv); -} +module_platform_driver(tis_synquacer_drv); -module_init(tpm_tis_synquacer_module_init); -module_exit(tpm_tis_synquacer_module_exit); MODULE_DESCRIPTION("TPM MMIO Driver for Socionext SynQuacer platform"); MODULE_LICENSE("GPL"); diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c index 4fb4fd4b06bd..737aa70e2cb3 100644 --- a/drivers/clk/clk-devres.c +++ b/drivers/clk/clk-devres.c @@ -205,18 +205,19 @@ EXPORT_SYMBOL(devm_clk_put); struct clk *devm_get_clk_from_child(struct device *dev, struct device_node *np, const char *con_id) { - struct clk **ptr, *clk; + struct devm_clk_state *state; + struct clk *clk; - ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) + state = devres_alloc(devm_clk_release, sizeof(*state), GFP_KERNEL); + if (!state) return ERR_PTR(-ENOMEM); clk = of_clk_get_by_name(np, con_id); if (!IS_ERR(clk)) { - *ptr = clk; - devres_add(dev, ptr); + state->clk = clk; + devres_add(dev, state); } else { - devres_free(ptr); + devres_free(state); } return clk; diff --git a/drivers/clk/keystone/syscon-clk.c b/drivers/clk/keystone/syscon-clk.c index d33f74119488..935d9a2d8c2b 100644 --- a/drivers/clk/keystone/syscon-clk.c +++ b/drivers/clk/keystone/syscon-clk.c @@ -151,8 +151,10 @@ static int ti_syscon_gate_clk_probe(struct platform_device *pdev) data[i].name); } - return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, - hw_data); + if (num_clks == 1) + return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, + hw_data->hws[0]); + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, hw_data); } #define TI_SYSCON_CLK_GATE(_name, _offset, _bit_idx) \ diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index b2f05d27167e..37f1cdf46d29 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -1011,22 +1011,20 @@ static int __init acpi_cpufreq_probe(struct platform_device *pdev) return ret; } -static int acpi_cpufreq_remove(struct platform_device *pdev) +static void acpi_cpufreq_remove(struct platform_device *pdev) { pr_debug("%s\n", __func__); cpufreq_unregister_driver(&acpi_cpufreq_driver); free_acpi_perf_data(); - - return 0; } static struct platform_driver acpi_cpufreq_platdrv = { .driver = { .name = "acpi-cpufreq", }, - .remove = acpi_cpufreq_remove, + .remove_new = acpi_cpufreq_remove, }; static int __init acpi_cpufreq_init(void) diff --git a/drivers/cpufreq/amd-pstate-ut.c b/drivers/cpufreq/amd-pstate-ut.c index 7f3fe2048981..f04ae67dda37 100644 --- a/drivers/cpufreq/amd-pstate-ut.c +++ b/drivers/cpufreq/amd-pstate-ut.c @@ -64,27 +64,9 @@ static struct amd_pstate_ut_struct amd_pstate_ut_cases[] = { static bool get_shared_mem(void) { bool result = false; - char path[] = "/sys/module/amd_pstate/parameters/shared_mem"; - char buf[5] = {0}; - struct file *filp = NULL; - loff_t pos = 0; - ssize_t ret; - - if (!boot_cpu_has(X86_FEATURE_CPPC)) { - filp = filp_open(path, O_RDONLY, 0); - if (IS_ERR(filp)) - pr_err("%s unable to open %s file!\n", __func__, path); - else { - ret = kernel_read(filp, &buf, sizeof(buf), &pos); - if (ret < 0) - pr_err("%s read %s file fail ret=%ld!\n", - __func__, path, (long)ret); - filp_close(filp, NULL); - } - if ('Y' == *buf) - result = true; - } + if (!boot_cpu_has(X86_FEATURE_CPPC)) + result = true; return result; } @@ -145,8 +127,6 @@ static void amd_pstate_ut_check_perf(u32 index) struct cpufreq_policy *policy = NULL; struct amd_cpudata *cpudata = NULL; - highest_perf = amd_get_highest_perf(); - for_each_possible_cpu(cpu) { policy = cpufreq_cpu_get(cpu); if (!policy) @@ -158,9 +138,10 @@ static void amd_pstate_ut_check_perf(u32 index) if (ret) { amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL; pr_err("%s cppc_get_perf_caps ret=%d error!\n", __func__, ret); - return; + goto skip_test; } + highest_perf = cppc_perf.highest_perf; nominal_perf = cppc_perf.nominal_perf; lowest_nonlinear_perf = cppc_perf.lowest_nonlinear_perf; lowest_perf = cppc_perf.lowest_perf; @@ -169,9 +150,10 @@ static void amd_pstate_ut_check_perf(u32 index) if (ret) { amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL; pr_err("%s read CPPC_CAP1 ret=%d error!\n", __func__, ret); - return; + goto skip_test; } + highest_perf = AMD_CPPC_HIGHEST_PERF(cap1); nominal_perf = AMD_CPPC_NOMINAL_PERF(cap1); lowest_nonlinear_perf = AMD_CPPC_LOWNONLIN_PERF(cap1); lowest_perf = AMD_CPPC_LOWEST_PERF(cap1); @@ -187,7 +169,7 @@ static void amd_pstate_ut_check_perf(u32 index) nominal_perf, cpudata->nominal_perf, lowest_nonlinear_perf, cpudata->lowest_nonlinear_perf, lowest_perf, cpudata->lowest_perf); - return; + goto skip_test; } if (!((highest_perf >= nominal_perf) && @@ -198,11 +180,15 @@ static void amd_pstate_ut_check_perf(u32 index) pr_err("%s cpu%d highest=%d >= nominal=%d > lowest_nonlinear=%d > lowest=%d > 0, the formula is incorrect!\n", __func__, cpu, highest_perf, nominal_perf, lowest_nonlinear_perf, lowest_perf); - return; + goto skip_test; } + cpufreq_cpu_put(policy); } amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_PASS; + return; +skip_test: + cpufreq_cpu_put(policy); } /* @@ -230,14 +216,14 @@ static void amd_pstate_ut_check_freq(u32 index) pr_err("%s cpu%d max=%d >= nominal=%d > lowest_nonlinear=%d > min=%d > 0, the formula is incorrect!\n", __func__, cpu, cpudata->max_freq, cpudata->nominal_freq, cpudata->lowest_nonlinear_freq, cpudata->min_freq); - return; + goto skip_test; } if (cpudata->min_freq != policy->min) { amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL; pr_err("%s cpu%d cpudata_min_freq=%d policy_min=%d, they should be equal!\n", __func__, cpu, cpudata->min_freq, policy->min); - return; + goto skip_test; } if (cpudata->boost_supported) { @@ -249,16 +235,20 @@ static void amd_pstate_ut_check_freq(u32 index) pr_err("%s cpu%d policy_max=%d should be equal cpu_max=%d or cpu_nominal=%d !\n", __func__, cpu, policy->max, cpudata->max_freq, cpudata->nominal_freq); - return; + goto skip_test; } } else { amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL; pr_err("%s cpu%d must support boost!\n", __func__, cpu); - return; + goto skip_test; } + cpufreq_cpu_put(policy); } amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_PASS; + return; +skip_test: + cpufreq_cpu_put(policy); } static int __init amd_pstate_ut_init(void) diff --git a/drivers/cpufreq/armada-37xx-cpufreq.c b/drivers/cpufreq/armada-37xx-cpufreq.c index b74289a95a17..bea41ccabf1f 100644 --- a/drivers/cpufreq/armada-37xx-cpufreq.c +++ b/drivers/cpufreq/armada-37xx-cpufreq.c @@ -14,10 +14,8 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/mfd/syscon.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> #include <linux/platform_device.h> #include <linux/pm_opp.h> #include <linux/regmap.h> diff --git a/drivers/cpufreq/brcmstb-avs-cpufreq.c b/drivers/cpufreq/brcmstb-avs-cpufreq.c index ffea6402189d..35fb3a559ea9 100644 --- a/drivers/cpufreq/brcmstb-avs-cpufreq.c +++ b/drivers/cpufreq/brcmstb-avs-cpufreq.c @@ -434,7 +434,11 @@ brcm_avs_get_freq_table(struct device *dev, struct private_data *priv) if (ret) return ERR_PTR(ret); - table = devm_kcalloc(dev, AVS_PSTATE_MAX + 1, sizeof(*table), + /* + * We allocate space for the 5 different P-STATES AVS, + * plus extra space for a terminating element. + */ + table = devm_kcalloc(dev, AVS_PSTATE_MAX + 1 + 1, sizeof(*table), GFP_KERNEL); if (!table) return ERR_PTR(-ENOMEM); @@ -749,13 +753,11 @@ static int brcm_avs_cpufreq_probe(struct platform_device *pdev) return ret; } -static int brcm_avs_cpufreq_remove(struct platform_device *pdev) +static void brcm_avs_cpufreq_remove(struct platform_device *pdev) { cpufreq_unregister_driver(&brcm_avs_driver); brcm_avs_prepare_uninit(pdev); - - return 0; } static const struct of_device_id brcm_avs_cpufreq_match[] = { @@ -770,7 +772,7 @@ static struct platform_driver brcm_avs_cpufreq_platdrv = { .of_match_table = brcm_avs_cpufreq_match, }, .probe = brcm_avs_cpufreq_probe, - .remove = brcm_avs_cpufreq_remove, + .remove_new = brcm_avs_cpufreq_remove, }; module_platform_driver(brcm_avs_cpufreq_platdrv); diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index 022e3555407c..fe08ca419b3d 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -249,15 +249,19 @@ static void __init cppc_freq_invariance_init(void) return; kworker_fie = kthread_create_worker(0, "cppc_fie"); - if (IS_ERR(kworker_fie)) + if (IS_ERR(kworker_fie)) { + pr_warn("%s: failed to create kworker_fie: %ld\n", __func__, + PTR_ERR(kworker_fie)); + fie_disabled = FIE_DISABLED; return; + } ret = sched_setattr_nocheck(kworker_fie->task, &attr); if (ret) { pr_warn("%s: failed to set SCHED_DEADLINE: %d\n", __func__, ret); kthread_destroy_worker(kworker_fie); - return; + fie_disabled = FIE_DISABLED; } } @@ -267,7 +271,6 @@ static void cppc_freq_invariance_exit(void) return; kthread_destroy_worker(kworker_fie); - kworker_fie = NULL; } #else @@ -849,13 +852,13 @@ static unsigned int cppc_cpufreq_get_rate(unsigned int cpu) ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t0); if (ret) - return ret; + return 0; udelay(2); /* 2usec delay between sampling */ ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t1); if (ret) - return ret; + return 0; delivered_perf = cppc_perf_from_fbctrs(cpu_data, &fb_ctrs_t0, &fb_ctrs_t1); diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index e2b20080de3a..fb2875ce1fdd 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -143,14 +143,19 @@ static const struct of_device_id blocklist[] __initconst = { { .compatible = "qcom,apq8096", }, { .compatible = "qcom,msm8996", }, + { .compatible = "qcom,msm8998", }, + { .compatible = "qcom,qcm2290", }, { .compatible = "qcom,qcs404", }, + { .compatible = "qcom,qdu1000", }, { .compatible = "qcom,sa8155p" }, { .compatible = "qcom,sa8540p" }, + { .compatible = "qcom,sa8775p" }, { .compatible = "qcom,sc7180", }, { .compatible = "qcom,sc7280", }, { .compatible = "qcom,sc8180x", }, { .compatible = "qcom,sc8280xp", }, { .compatible = "qcom,sdm845", }, + { .compatible = "qcom,sdx75", }, { .compatible = "qcom,sm6115", }, { .compatible = "qcom,sm6350", }, { .compatible = "qcom,sm6375", }, @@ -158,6 +163,8 @@ static const struct of_device_id blocklist[] __initconst = { { .compatible = "qcom,sm8150", }, { .compatible = "qcom,sm8250", }, { .compatible = "qcom,sm8350", }, + { .compatible = "qcom,sm8450", }, + { .compatible = "qcom,sm8550", }, { .compatible = "st,stih407", }, { .compatible = "st,stih410", }, diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index 4aec4b2a5225..8bd6e5e8f121 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -349,11 +349,10 @@ err: return ret; } -static int dt_cpufreq_remove(struct platform_device *pdev) +static void dt_cpufreq_remove(struct platform_device *pdev) { cpufreq_unregister_driver(&dt_cpufreq_driver); dt_cpufreq_release(); - return 0; } static struct platform_driver dt_cpufreq_platdrv = { @@ -361,7 +360,7 @@ static struct platform_driver dt_cpufreq_platdrv = { .name = "cpufreq-dt", }, .probe = dt_cpufreq_probe, - .remove = dt_cpufreq_remove, + .remove_new = dt_cpufreq_remove, }; module_platform_driver(dt_cpufreq_platdrv); diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 50bbc969ffe5..a757f90aa9d6 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1234,16 +1234,16 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu) ret = freq_qos_add_notifier(&policy->constraints, FREQ_QOS_MIN, &policy->nb_min); if (ret) { - dev_err(dev, "Failed to register MIN QoS notifier: %d (%*pbl)\n", - ret, cpumask_pr_args(policy->cpus)); + dev_err(dev, "Failed to register MIN QoS notifier: %d (CPU%u)\n", + ret, cpu); goto err_kobj_remove; } ret = freq_qos_add_notifier(&policy->constraints, FREQ_QOS_MAX, &policy->nb_max); if (ret) { - dev_err(dev, "Failed to register MAX QoS notifier: %d (%*pbl)\n", - ret, cpumask_pr_args(policy->cpus)); + dev_err(dev, "Failed to register MAX QoS notifier: %d (CPU%u)\n", + ret, cpu); goto err_min_qos_notifier; } diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 55c7ffd37d1c..a33df3c66c88 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -243,7 +243,8 @@ void cpufreq_stats_create_table(struct cpufreq_policy *policy) /* Find valid-unique entries */ cpufreq_for_each_valid_entry(pos, policy->freq_table) - if (freq_table_get_index(stats, pos->frequency) == -1) + if (policy->freq_table_sorted != CPUFREQ_TABLE_UNSORTED || + freq_table_get_index(stats, pos->frequency) == -1) stats->freq_table[i++] = pos->frequency; stats->state_num = i; diff --git a/drivers/cpufreq/davinci-cpufreq.c b/drivers/cpufreq/davinci-cpufreq.c index ebb3a8102681..7d2754411d8c 100644 --- a/drivers/cpufreq/davinci-cpufreq.c +++ b/drivers/cpufreq/davinci-cpufreq.c @@ -131,7 +131,7 @@ static int __init davinci_cpufreq_probe(struct platform_device *pdev) return cpufreq_register_driver(&davinci_driver); } -static int __exit davinci_cpufreq_remove(struct platform_device *pdev) +static void __exit davinci_cpufreq_remove(struct platform_device *pdev) { cpufreq_unregister_driver(&davinci_driver); @@ -139,15 +139,13 @@ static int __exit davinci_cpufreq_remove(struct platform_device *pdev) if (cpufreq.asyncclk) clk_put(cpufreq.asyncclk); - - return 0; } static struct platform_driver davinci_cpufreq_driver = { .driver = { .name = "cpufreq-davinci", }, - .remove = __exit_p(davinci_cpufreq_remove), + .remove_new = __exit_p(davinci_cpufreq_remove), }; int __init davinci_cpufreq_init(void) diff --git a/drivers/cpufreq/imx-cpufreq-dt.c b/drivers/cpufreq/imx-cpufreq-dt.c index 535867a7dfdd..577bb9e2f112 100644 --- a/drivers/cpufreq/imx-cpufreq-dt.c +++ b/drivers/cpufreq/imx-cpufreq-dt.c @@ -172,20 +172,18 @@ static int imx_cpufreq_dt_probe(struct platform_device *pdev) return 0; } -static int imx_cpufreq_dt_remove(struct platform_device *pdev) +static void imx_cpufreq_dt_remove(struct platform_device *pdev) { platform_device_unregister(cpufreq_dt_pdev); if (!of_machine_is_compatible("fsl,imx7ulp")) dev_pm_opp_put_supported_hw(cpufreq_opp_token); else clk_bulk_put(ARRAY_SIZE(imx7ulp_clks), imx7ulp_clks); - - return 0; } static struct platform_driver imx_cpufreq_dt_driver = { .probe = imx_cpufreq_dt_probe, - .remove = imx_cpufreq_dt_remove, + .remove_new = imx_cpufreq_dt_remove, .driver = { .name = "imx-cpufreq-dt", }, diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index 9fb1501033bb..494d044b9e72 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -519,7 +519,7 @@ put_node: return ret; } -static int imx6q_cpufreq_remove(struct platform_device *pdev) +static void imx6q_cpufreq_remove(struct platform_device *pdev) { cpufreq_unregister_driver(&imx6q_cpufreq_driver); dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); @@ -530,8 +530,6 @@ static int imx6q_cpufreq_remove(struct platform_device *pdev) regulator_put(soc_reg); clk_bulk_put(num_clks, clks); - - return 0; } static struct platform_driver imx6q_cpufreq_platdrv = { @@ -539,7 +537,7 @@ static struct platform_driver imx6q_cpufreq_platdrv = { .name = "imx6q-cpufreq", }, .probe = imx6q_cpufreq_probe, - .remove = imx6q_cpufreq_remove, + .remove_new = imx6q_cpufreq_remove, }; module_platform_driver(imx6q_cpufreq_platdrv); diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 8ca2bce4341a..dc50c9fb488d 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -2609,6 +2609,11 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) intel_pstate_clear_update_util_hook(policy->cpu); intel_pstate_hwp_set(policy->cpu); } + /* + * policy->cur is never updated with the intel_pstate driver, but it + * is used as a stale frequency value. So, keep it within limits. + */ + policy->cur = policy->min; mutex_unlock(&intel_pstate_limits_lock); diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c index 95588101efbd..fd20b986d1f2 100644 --- a/drivers/cpufreq/kirkwood-cpufreq.c +++ b/drivers/cpufreq/kirkwood-cpufreq.c @@ -178,20 +178,18 @@ out_node: return err; } -static int kirkwood_cpufreq_remove(struct platform_device *pdev) +static void kirkwood_cpufreq_remove(struct platform_device *pdev) { cpufreq_unregister_driver(&kirkwood_cpufreq_driver); clk_disable_unprepare(priv.powersave_clk); clk_disable_unprepare(priv.ddr_clk); clk_disable_unprepare(priv.cpu_clk); - - return 0; } static struct platform_driver kirkwood_cpufreq_platform_driver = { .probe = kirkwood_cpufreq_probe, - .remove = kirkwood_cpufreq_remove, + .remove_new = kirkwood_cpufreq_remove, .driver = { .name = "kirkwood-cpufreq", }, diff --git a/drivers/cpufreq/mediatek-cpufreq-hw.c b/drivers/cpufreq/mediatek-cpufreq-hw.c index b22f5cc8a463..d46afb3c0092 100644 --- a/drivers/cpufreq/mediatek-cpufreq-hw.c +++ b/drivers/cpufreq/mediatek-cpufreq-hw.c @@ -10,8 +10,9 @@ #include <linux/iopoll.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_address.h> +#include <linux/of.h> #include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/slab.h> #define LUT_MAX_ENTRIES 32U @@ -315,11 +316,9 @@ static int mtk_cpufreq_hw_driver_probe(struct platform_device *pdev) return ret; } -static int mtk_cpufreq_hw_driver_remove(struct platform_device *pdev) +static void mtk_cpufreq_hw_driver_remove(struct platform_device *pdev) { cpufreq_unregister_driver(&cpufreq_mtk_hw_driver); - - return 0; } static const struct of_device_id mtk_cpufreq_hw_match[] = { @@ -330,7 +329,7 @@ MODULE_DEVICE_TABLE(of, mtk_cpufreq_hw_match); static struct platform_driver mtk_cpufreq_hw_driver = { .probe = mtk_cpufreq_hw_driver_probe, - .remove = mtk_cpufreq_hw_driver_remove, + .remove_new = mtk_cpufreq_hw_driver_remove, .driver = { .name = "mtk-cpufreq-hw", .of_match_table = mtk_cpufreq_hw_match, diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c index fef68cb2b38f..a0a61919bc4c 100644 --- a/drivers/cpufreq/mediatek-cpufreq.c +++ b/drivers/cpufreq/mediatek-cpufreq.c @@ -313,8 +313,6 @@ out: return ret; } -#define DYNAMIC_POWER "dynamic-power-coefficient" - static int mtk_cpufreq_opp_notifier(struct notifier_block *nb, unsigned long event, void *data) { diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index 81649a1969b6..895690856665 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -182,11 +182,9 @@ static int omap_cpufreq_probe(struct platform_device *pdev) return cpufreq_register_driver(&omap_driver); } -static int omap_cpufreq_remove(struct platform_device *pdev) +static void omap_cpufreq_remove(struct platform_device *pdev) { cpufreq_unregister_driver(&omap_driver); - - return 0; } static struct platform_driver omap_cpufreq_platdrv = { @@ -194,7 +192,7 @@ static struct platform_driver omap_cpufreq_platdrv = { .name = "omap-cpufreq", }, .probe = omap_cpufreq_probe, - .remove = omap_cpufreq_remove, + .remove_new = omap_cpufreq_remove, }; module_platform_driver(omap_cpufreq_platdrv); diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c index 73efbcf5513b..84fe37def0f1 100644 --- a/drivers/cpufreq/pcc-cpufreq.c +++ b/drivers/cpufreq/pcc-cpufreq.c @@ -608,22 +608,20 @@ static int __init pcc_cpufreq_probe(struct platform_device *pdev) return ret; } -static int pcc_cpufreq_remove(struct platform_device *pdev) +static void pcc_cpufreq_remove(struct platform_device *pdev) { cpufreq_unregister_driver(&pcc_cpufreq_driver); pcc_clear_mapping(); free_percpu(pcc_cpu_info); - - return 0; } static struct platform_driver pcc_cpufreq_platdrv = { .driver = { .name = "pcc-cpufreq", }, - .remove = pcc_cpufreq_remove, + .remove_new = pcc_cpufreq_remove, }; static int __init pcc_cpufreq_init(void) diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index d289036beff2..b10f7a1b77f1 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1101,7 +1101,8 @@ static int powernowk8_cpu_exit(struct cpufreq_policy *pol) kfree(data->powernow_table); kfree(data); - for_each_cpu(cpu, pol->cpus) + /* pol->cpus will be empty here, use related_cpus instead. */ + for_each_cpu(cpu, pol->related_cpus) per_cpu(powernow_data, cpu) = NULL; return 0; diff --git a/drivers/cpufreq/ppc_cbe_cpufreq.c b/drivers/cpufreq/ppc_cbe_cpufreq.c index e3313ce63b38..88afc49941b7 100644 --- a/drivers/cpufreq/ppc_cbe_cpufreq.c +++ b/drivers/cpufreq/ppc_cbe_cpufreq.c @@ -9,7 +9,7 @@ #include <linux/cpufreq.h> #include <linux/module.h> -#include <linux/of_platform.h> +#include <linux/of.h> #include <asm/machdep.h> #include <asm/cell-regs.h> diff --git a/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c b/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c index 4fba3637b115..6f0c32592416 100644 --- a/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c +++ b/drivers/cpufreq/ppc_cbe_cpufreq_pmi.c @@ -11,7 +11,6 @@ #include <linux/types.h> #include <linux/timer.h> #include <linux/init.h> -#include <linux/of_platform.h> #include <linux/pm_qos.h> #include <linux/slab.h> diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c index f2830371d25f..70b0f21968a0 100644 --- a/drivers/cpufreq/qcom-cpufreq-hw.c +++ b/drivers/cpufreq/qcom-cpufreq-hw.c @@ -28,7 +28,7 @@ #define GT_IRQ_STATUS BIT(2) -#define MAX_FREQ_DOMAINS 3 +#define MAX_FREQ_DOMAINS 4 struct qcom_cpufreq_soc_data { u32 reg_enable; @@ -730,16 +730,14 @@ static int qcom_cpufreq_hw_driver_probe(struct platform_device *pdev) return ret; } -static int qcom_cpufreq_hw_driver_remove(struct platform_device *pdev) +static void qcom_cpufreq_hw_driver_remove(struct platform_device *pdev) { cpufreq_unregister_driver(&cpufreq_qcom_hw_driver); - - return 0; } static struct platform_driver qcom_cpufreq_hw_driver = { .probe = qcom_cpufreq_hw_driver_probe, - .remove = qcom_cpufreq_hw_driver_remove, + .remove_new = qcom_cpufreq_hw_driver_remove, .driver = { .name = "qcom-cpufreq-hw", .of_match_table = qcom_cpufreq_hw_match, diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c index a88b6fe5db50..84d7033e5efe 100644 --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c @@ -22,7 +22,6 @@ #include <linux/module.h> #include <linux/nvmem-consumer.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/pm_opp.h> @@ -334,7 +333,7 @@ free_drv: return ret; } -static int qcom_cpufreq_remove(struct platform_device *pdev) +static void qcom_cpufreq_remove(struct platform_device *pdev) { struct qcom_cpufreq_drv *drv = platform_get_drvdata(pdev); unsigned int cpu; @@ -346,13 +345,11 @@ static int qcom_cpufreq_remove(struct platform_device *pdev) kfree(drv->opp_tokens); kfree(drv); - - return 0; } static struct platform_driver qcom_cpufreq_driver = { .probe = qcom_cpufreq_probe, - .remove = qcom_cpufreq_remove, + .remove_new = qcom_cpufreq_remove, .driver = { .name = "qcom-cpufreq-nvmem", }, diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c index 573b417e1483..0aecaecbb0e6 100644 --- a/drivers/cpufreq/qoriq-cpufreq.c +++ b/drivers/cpufreq/qoriq-cpufreq.c @@ -288,11 +288,9 @@ static int qoriq_cpufreq_probe(struct platform_device *pdev) return 0; } -static int qoriq_cpufreq_remove(struct platform_device *pdev) +static void qoriq_cpufreq_remove(struct platform_device *pdev) { cpufreq_unregister_driver(&qoriq_cpufreq_driver); - - return 0; } static struct platform_driver qoriq_cpufreq_platform_driver = { @@ -300,7 +298,7 @@ static struct platform_driver qoriq_cpufreq_platform_driver = { .name = "qoriq-cpufreq", }, .probe = qoriq_cpufreq_probe, - .remove = qoriq_cpufreq_remove, + .remove_new = qoriq_cpufreq_remove, }; module_platform_driver(qoriq_cpufreq_platform_driver); diff --git a/drivers/cpufreq/raspberrypi-cpufreq.c b/drivers/cpufreq/raspberrypi-cpufreq.c index 2bc7d9734272..e0705cc9a57d 100644 --- a/drivers/cpufreq/raspberrypi-cpufreq.c +++ b/drivers/cpufreq/raspberrypi-cpufreq.c @@ -65,7 +65,7 @@ remove_opp: return ret; } -static int raspberrypi_cpufreq_remove(struct platform_device *pdev) +static void raspberrypi_cpufreq_remove(struct platform_device *pdev) { struct device *cpu_dev; @@ -74,8 +74,6 @@ static int raspberrypi_cpufreq_remove(struct platform_device *pdev) dev_pm_opp_remove_all_dynamic(cpu_dev); platform_device_unregister(cpufreq_dt); - - return 0; } /* @@ -87,7 +85,7 @@ static struct platform_driver raspberrypi_cpufreq_driver = { .name = "raspberrypi-cpufreq", }, .probe = raspberrypi_cpufreq_probe, - .remove = raspberrypi_cpufreq_remove, + .remove_new = raspberrypi_cpufreq_remove, }; module_platform_driver(raspberrypi_cpufreq_driver); diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c index fd2c16821d54..d33be56983ed 100644 --- a/drivers/cpufreq/scpi-cpufreq.c +++ b/drivers/cpufreq/scpi-cpufreq.c @@ -14,7 +14,7 @@ #include <linux/cpumask.h> #include <linux/export.h> #include <linux/module.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/pm_opp.h> #include <linux/scpi_protocol.h> #include <linux/slab.h> @@ -208,11 +208,10 @@ static int scpi_cpufreq_probe(struct platform_device *pdev) return ret; } -static int scpi_cpufreq_remove(struct platform_device *pdev) +static void scpi_cpufreq_remove(struct platform_device *pdev) { cpufreq_unregister_driver(&scpi_cpufreq_driver); scpi_ops = NULL; - return 0; } static struct platform_driver scpi_cpufreq_platdrv = { @@ -220,7 +219,7 @@ static struct platform_driver scpi_cpufreq_platdrv = { .name = "scpi-cpufreq", }, .probe = scpi_cpufreq_probe, - .remove = scpi_cpufreq_remove, + .remove_new = scpi_cpufreq_remove, }; module_platform_driver(scpi_cpufreq_platdrv); diff --git a/drivers/cpufreq/sti-cpufreq.c b/drivers/cpufreq/sti-cpufreq.c index 1a63aeea8711..9c542e723a15 100644 --- a/drivers/cpufreq/sti-cpufreq.c +++ b/drivers/cpufreq/sti-cpufreq.c @@ -13,7 +13,7 @@ #include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/pm_opp.h> #include <linux/regmap.h> diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c index 4321d7bbe769..32a9c88f8ff6 100644 --- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c +++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c @@ -137,7 +137,7 @@ free_opp: return ret; } -static int sun50i_cpufreq_nvmem_remove(struct platform_device *pdev) +static void sun50i_cpufreq_nvmem_remove(struct platform_device *pdev) { int *opp_tokens = platform_get_drvdata(pdev); unsigned int cpu; @@ -148,13 +148,11 @@ static int sun50i_cpufreq_nvmem_remove(struct platform_device *pdev) dev_pm_opp_put_prop_name(opp_tokens[cpu]); kfree(opp_tokens); - - return 0; } static struct platform_driver sun50i_cpufreq_driver = { .probe = sun50i_cpufreq_nvmem_probe, - .remove = sun50i_cpufreq_nvmem_remove, + .remove_new = sun50i_cpufreq_nvmem_remove, .driver = { .name = "sun50i-cpufreq-nvmem", }, diff --git a/drivers/cpufreq/tegra186-cpufreq.c b/drivers/cpufreq/tegra186-cpufreq.c index f98f53bf1011..7b8fcfa55038 100644 --- a/drivers/cpufreq/tegra186-cpufreq.c +++ b/drivers/cpufreq/tegra186-cpufreq.c @@ -259,11 +259,9 @@ put_bpmp: return err; } -static int tegra186_cpufreq_remove(struct platform_device *pdev) +static void tegra186_cpufreq_remove(struct platform_device *pdev) { cpufreq_unregister_driver(&tegra186_cpufreq_driver); - - return 0; } static const struct of_device_id tegra186_cpufreq_of_match[] = { @@ -278,7 +276,7 @@ static struct platform_driver tegra186_cpufreq_platform_driver = { .of_match_table = tegra186_cpufreq_of_match, }, .probe = tegra186_cpufreq_probe, - .remove = tegra186_cpufreq_remove, + .remove_new = tegra186_cpufreq_remove, }; module_platform_driver(tegra186_cpufreq_platform_driver); diff --git a/drivers/cpufreq/tegra194-cpufreq.c b/drivers/cpufreq/tegra194-cpufreq.c index 36dad5ea5947..88ef5e57ccd0 100644 --- a/drivers/cpufreq/tegra194-cpufreq.c +++ b/drivers/cpufreq/tegra194-cpufreq.c @@ -508,6 +508,32 @@ static int tegra194_cpufreq_init(struct cpufreq_policy *policy) return 0; } +static int tegra194_cpufreq_online(struct cpufreq_policy *policy) +{ + /* We did light-weight tear down earlier, nothing to do here */ + return 0; +} + +static int tegra194_cpufreq_offline(struct cpufreq_policy *policy) +{ + /* + * Preserve policy->driver_data and don't free resources on light-weight + * tear down. + */ + + return 0; +} + +static int tegra194_cpufreq_exit(struct cpufreq_policy *policy) +{ + struct device *cpu_dev = get_cpu_device(policy->cpu); + + dev_pm_opp_remove_all_dynamic(cpu_dev); + dev_pm_opp_of_cpumask_remove_table(policy->related_cpus); + + return 0; +} + static int tegra194_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index) { @@ -535,6 +561,9 @@ static struct cpufreq_driver tegra194_cpufreq_driver = { .target_index = tegra194_cpufreq_set_target, .get = tegra194_get_speed, .init = tegra194_cpufreq_init, + .exit = tegra194_cpufreq_exit, + .online = tegra194_cpufreq_online, + .offline = tegra194_cpufreq_offline, .attr = cpufreq_generic_attr, }; @@ -708,12 +737,10 @@ put_bpmp: return err; } -static int tegra194_cpufreq_remove(struct platform_device *pdev) +static void tegra194_cpufreq_remove(struct platform_device *pdev) { cpufreq_unregister_driver(&tegra194_cpufreq_driver); tegra194_cpufreq_free_resources(); - - return 0; } static const struct of_device_id tegra194_cpufreq_of_match[] = { @@ -730,7 +757,7 @@ static struct platform_driver tegra194_ccplex_driver = { .of_match_table = tegra194_cpufreq_of_match, }, .probe = tegra194_cpufreq_probe, - .remove = tegra194_cpufreq_remove, + .remove_new = tegra194_cpufreq_remove, }; module_platform_driver(tegra194_ccplex_driver); diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c index d5cd2fd25cad..3c37d7899660 100644 --- a/drivers/cpufreq/ti-cpufreq.c +++ b/drivers/cpufreq/ti-cpufreq.c @@ -12,7 +12,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/of.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/pm_opp.h> #include <linux/regmap.h> #include <linux/slab.h> diff --git a/drivers/cpufreq/vexpress-spc-cpufreq.c b/drivers/cpufreq/vexpress-spc-cpufreq.c index d295f405c4bb..9ac4ea50b874 100644 --- a/drivers/cpufreq/vexpress-spc-cpufreq.c +++ b/drivers/cpufreq/vexpress-spc-cpufreq.c @@ -18,7 +18,6 @@ #include <linux/device.h> #include <linux/module.h> #include <linux/mutex.h> -#include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/pm_opp.h> #include <linux/slab.h> @@ -552,7 +551,7 @@ static int ve_spc_cpufreq_probe(struct platform_device *pdev) return ret; } -static int ve_spc_cpufreq_remove(struct platform_device *pdev) +static void ve_spc_cpufreq_remove(struct platform_device *pdev) { bL_switcher_get_enabled(); __bLs_unregister_notifier(); @@ -560,7 +559,6 @@ static int ve_spc_cpufreq_remove(struct platform_device *pdev) bL_switcher_put_enabled(); pr_info("%s: Un-registered platform driver: %s\n", __func__, ve_spc_cpufreq_driver.name); - return 0; } static struct platform_driver ve_spc_cpufreq_platdrv = { @@ -568,7 +566,7 @@ static struct platform_driver ve_spc_cpufreq_platdrv = { .name = "vexpress-spc-cpufreq", }, .probe = ve_spc_cpufreq_probe, - .remove = ve_spc_cpufreq_remove, + .remove_new = ve_spc_cpufreq_remove, }; module_platform_driver(ve_spc_cpufreq_platdrv); diff --git a/drivers/cpuidle/governors/gov.h b/drivers/cpuidle/governors/gov.h new file mode 100644 index 000000000000..99e067d9668c --- /dev/null +++ b/drivers/cpuidle/governors/gov.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* Common definitions for cpuidle governors. */ + +#ifndef __CPUIDLE_GOVERNOR_H +#define __CPUIDLE_GOVERNOR_H + +/* + * Idle state target residency threshold used for deciding whether or not to + * check the time till the closest expected timer event. + */ +#define RESIDENCY_THRESHOLD_NS (15 * NSEC_PER_USEC) + +#endif /* __CPUIDLE_GOVERNOR_H */ diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index c4922684f305..b96e3da0fedd 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -19,6 +19,8 @@ #include <linux/sched/stat.h> #include <linux/math64.h> +#include "gov.h" + #define BUCKETS 12 #define INTERVAL_SHIFT 3 #define INTERVALS (1UL << INTERVAL_SHIFT) @@ -166,8 +168,7 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev); * of points is below a threshold. If it is... then use the * average of these 8 points as the estimated value. */ -static unsigned int get_typical_interval(struct menu_device *data, - unsigned int predicted_us) +static unsigned int get_typical_interval(struct menu_device *data) { int i, divisor; unsigned int min, max, thresh, avg; @@ -195,11 +196,7 @@ again: } } - /* - * If the result of the computation is going to be discarded anyway, - * avoid the computation altogether. - */ - if (min >= predicted_us) + if (!max) return UINT_MAX; if (divisor == INTERVALS) @@ -267,7 +264,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, { struct menu_device *data = this_cpu_ptr(&menu_devices); s64 latency_req = cpuidle_governor_latency_req(dev->cpu); - unsigned int predicted_us; u64 predicted_ns; u64 interactivity_req; unsigned int nr_iowaiters; @@ -279,16 +275,41 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, data->needs_update = 0; } - /* determine the expected residency time, round up */ - delta = tick_nohz_get_sleep_length(&delta_tick); - if (unlikely(delta < 0)) { - delta = 0; - delta_tick = 0; - } - data->next_timer_ns = delta; - nr_iowaiters = nr_iowait_cpu(dev->cpu); - data->bucket = which_bucket(data->next_timer_ns, nr_iowaiters); + + /* Find the shortest expected idle interval. */ + predicted_ns = get_typical_interval(data) * NSEC_PER_USEC; + if (predicted_ns > RESIDENCY_THRESHOLD_NS) { + unsigned int timer_us; + + /* Determine the time till the closest timer. */ + delta = tick_nohz_get_sleep_length(&delta_tick); + if (unlikely(delta < 0)) { + delta = 0; + delta_tick = 0; + } + + data->next_timer_ns = delta; + data->bucket = which_bucket(data->next_timer_ns, nr_iowaiters); + + /* Round up the result for half microseconds. */ + timer_us = div_u64((RESOLUTION * DECAY * NSEC_PER_USEC) / 2 + + data->next_timer_ns * + data->correction_factor[data->bucket], + RESOLUTION * DECAY * NSEC_PER_USEC); + /* Use the lowest expected idle interval to pick the idle state. */ + predicted_ns = min((u64)timer_us * NSEC_PER_USEC, predicted_ns); + } else { + /* + * Because the next timer event is not going to be determined + * in this case, assume that without the tick the closest timer + * will be in distant future and that the closest tick will occur + * after 1/2 of the tick period. + */ + data->next_timer_ns = KTIME_MAX; + delta_tick = TICK_NSEC / 2; + data->bucket = which_bucket(KTIME_MAX, nr_iowaiters); + } if (unlikely(drv->state_count <= 1 || latency_req == 0) || ((data->next_timer_ns < drv->states[1].target_residency_ns || @@ -303,16 +324,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, return 0; } - /* Round up the result for half microseconds. */ - predicted_us = div_u64(data->next_timer_ns * - data->correction_factor[data->bucket] + - (RESOLUTION * DECAY * NSEC_PER_USEC) / 2, - RESOLUTION * DECAY * NSEC_PER_USEC); - /* Use the lowest expected idle interval to pick the idle state. */ - predicted_ns = (u64)min(predicted_us, - get_typical_interval(data, predicted_us)) * - NSEC_PER_USEC; - if (tick_nohz_tick_stopped()) { /* * If the tick is already stopped, the cost of possible short diff --git a/drivers/cpuidle/governors/teo.c b/drivers/cpuidle/governors/teo.c index 987fc5f3997d..7244f71c59c5 100644 --- a/drivers/cpuidle/governors/teo.c +++ b/drivers/cpuidle/governors/teo.c @@ -140,6 +140,8 @@ #include <linux/sched/topology.h> #include <linux/tick.h> +#include "gov.h" + /* * The number of bits to shift the CPU's capacity by in order to determine * the utilized threshold. @@ -152,7 +154,6 @@ */ #define UTIL_THRESHOLD_SHIFT 6 - /* * The PULSE value is added to metrics when they grow and the DECAY_SHIFT value * is used for decreasing metrics on a regular basis. @@ -186,8 +187,8 @@ struct teo_bin { * @total: Grand total of the "intercepts" and "hits" metrics for all bins. * @next_recent_idx: Index of the next @recent_idx entry to update. * @recent_idx: Indices of bins corresponding to recent "intercepts". + * @tick_hits: Number of "hits" after TICK_NSEC. * @util_threshold: Threshold above which the CPU is considered utilized - * @utilized: Whether the last sleep on the CPU happened while utilized */ struct teo_cpu { s64 time_span_ns; @@ -196,8 +197,8 @@ struct teo_cpu { unsigned int total; int next_recent_idx; int recent_idx[NR_RECENT]; + unsigned int tick_hits; unsigned long util_threshold; - bool utilized; }; static DEFINE_PER_CPU(struct teo_cpu, teo_cpus); @@ -228,6 +229,7 @@ static void teo_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) { struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu); int i, idx_timer = 0, idx_duration = 0; + s64 target_residency_ns; u64 measured_ns; if (cpu_data->time_span_ns >= cpu_data->sleep_length_ns) { @@ -268,7 +270,6 @@ static void teo_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) * fall into. */ for (i = 0; i < drv->state_count; i++) { - s64 target_residency_ns = drv->states[i].target_residency_ns; struct teo_bin *bin = &cpu_data->state_bins[i]; bin->hits -= bin->hits >> DECAY_SHIFT; @@ -276,6 +277,8 @@ static void teo_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) cpu_data->total += bin->hits + bin->intercepts; + target_residency_ns = drv->states[i].target_residency_ns; + if (target_residency_ns <= cpu_data->sleep_length_ns) { idx_timer = i; if (target_residency_ns <= measured_ns) @@ -291,6 +294,26 @@ static void teo_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) cpu_data->state_bins[cpu_data->recent_idx[i]].recent--; /* + * If the deepest state's target residency is below the tick length, + * make a record of it to help teo_select() decide whether or not + * to stop the tick. This effectively adds an extra hits-only bin + * beyond the last state-related one. + */ + if (target_residency_ns < TICK_NSEC) { + cpu_data->tick_hits -= cpu_data->tick_hits >> DECAY_SHIFT; + + cpu_data->total += cpu_data->tick_hits; + + if (TICK_NSEC <= cpu_data->sleep_length_ns) { + idx_timer = drv->state_count; + if (TICK_NSEC <= measured_ns) { + cpu_data->tick_hits += PULSE; + goto end; + } + } + } + + /* * If the measured idle duration falls into the same bin as the sleep * length, this is a "hit", so update the "hits" metric for that bin. * Otherwise, update the "intercepts" metric for the bin fallen into by @@ -305,18 +328,14 @@ static void teo_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) cpu_data->recent_idx[i] = idx_duration; } +end: cpu_data->total += PULSE; } -static bool teo_time_ok(u64 interval_ns) +static bool teo_state_ok(int i, struct cpuidle_driver *drv) { - return !tick_nohz_tick_stopped() || interval_ns >= TICK_NSEC; -} - -static s64 teo_middle_of_bin(int idx, struct cpuidle_driver *drv) -{ - return (drv->states[idx].target_residency_ns + - drv->states[idx+1].target_residency_ns) / 2; + return !tick_nohz_tick_stopped() || + drv->states[i].target_residency_ns >= TICK_NSEC; } /** @@ -356,6 +375,8 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, { struct teo_cpu *cpu_data = per_cpu_ptr(&teo_cpus, dev->cpu); s64 latency_req = cpuidle_governor_latency_req(dev->cpu); + ktime_t delta_tick = TICK_NSEC / 2; + unsigned int tick_intercept_sum = 0; unsigned int idx_intercept_sum = 0; unsigned int intercept_sum = 0; unsigned int idx_recent_sum = 0; @@ -365,7 +386,7 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, int constraint_idx = 0; int idx0 = 0, idx = -1; bool alt_intercepts, alt_recent; - ktime_t delta_tick; + bool cpu_utilized; s64 duration_ns; int i; @@ -375,44 +396,48 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, } cpu_data->time_span_ns = local_clock(); - - duration_ns = tick_nohz_get_sleep_length(&delta_tick); - cpu_data->sleep_length_ns = duration_ns; + /* + * Set the expected sleep length to infinity in case of an early + * return. + */ + cpu_data->sleep_length_ns = KTIME_MAX; /* Check if there is any choice in the first place. */ if (drv->state_count < 2) { idx = 0; - goto end; + goto out_tick; } - if (!dev->states_usage[0].disable) { + + if (!dev->states_usage[0].disable) idx = 0; - if (drv->states[1].target_residency_ns > duration_ns) - goto end; - } - cpu_data->utilized = teo_cpu_is_utilized(dev->cpu, cpu_data); + cpu_utilized = teo_cpu_is_utilized(dev->cpu, cpu_data); /* * If the CPU is being utilized over the threshold and there are only 2 * states to choose from, the metrics need not be considered, so choose * the shallowest non-polling state and exit. */ - if (drv->state_count < 3 && cpu_data->utilized) { - for (i = 0; i < drv->state_count; ++i) { - if (!dev->states_usage[i].disable && - !(drv->states[i].flags & CPUIDLE_FLAG_POLLING)) { - idx = i; - goto end; - } + if (drv->state_count < 3 && cpu_utilized) { + /* + * If state 0 is enabled and it is not a polling one, select it + * right away unless the scheduler tick has been stopped, in + * which case care needs to be taken to leave the CPU in a deep + * enough state in case it is not woken up any time soon after + * all. If state 1 is disabled, though, state 0 must be used + * anyway. + */ + if ((!idx && !(drv->states[0].flags & CPUIDLE_FLAG_POLLING) && + teo_state_ok(0, drv)) || dev->states_usage[1].disable) { + idx = 0; + goto out_tick; } + /* Assume that state 1 is not a polling one and use it. */ + idx = 1; + duration_ns = drv->states[1].target_residency_ns; + goto end; } - /* - * Find the deepest idle state whose target residency does not exceed - * the current sleep length and the deepest idle state not deeper than - * the former whose exit latency does not exceed the current latency - * constraint. Compute the sums of metrics for early wakeup pattern - * detection. - */ + /* Compute the sums of metrics for early wakeup pattern detection. */ for (i = 1; i < drv->state_count; i++) { struct teo_bin *prev_bin = &cpu_data->state_bins[i-1]; struct cpuidle_state *s = &drv->states[i]; @@ -428,19 +453,15 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, if (dev->states_usage[i].disable) continue; - if (idx < 0) { - idx = i; /* first enabled state */ - idx0 = i; - } - - if (s->target_residency_ns > duration_ns) - break; + if (idx < 0) + idx0 = i; /* first enabled state */ idx = i; if (s->exit_latency_ns <= latency_req) constraint_idx = i; + /* Save the sums for the current state. */ idx_intercept_sum = intercept_sum; idx_hit_sum = hit_sum; idx_recent_sum = recent_sum; @@ -449,11 +470,21 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, /* Avoid unnecessary overhead. */ if (idx < 0) { idx = 0; /* No states enabled, must use 0. */ - goto end; - } else if (idx == idx0) { + goto out_tick; + } + + if (idx == idx0) { + /* + * Only one idle state is enabled, so use it, but do not + * allow the tick to be stopped it is shallow enough. + */ + duration_ns = drv->states[idx].target_residency_ns; goto end; } + tick_intercept_sum = intercept_sum + + cpu_data->state_bins[drv->state_count-1].intercepts; + /* * If the sum of the intercepts metric for all of the idle states * shallower than the current candidate one (idx) is greater than the @@ -461,13 +492,11 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, * all of the deeper states, or the sum of the numbers of recent * intercepts over all of the states shallower than the candidate one * is greater than a half of the number of recent events taken into - * account, the CPU is likely to wake up early, so find an alternative - * idle state to select. + * account, a shallower idle state is likely to be a better choice. */ alt_intercepts = 2 * idx_intercept_sum > cpu_data->total - idx_hit_sum; alt_recent = idx_recent_sum > NR_RECENT / 2; if (alt_recent || alt_intercepts) { - s64 first_suitable_span_ns = duration_ns; int first_suitable_idx = idx; /* @@ -476,44 +505,39 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, * cases (both with respect to intercepts overall and with * respect to the recent intercepts only) in the past. * - * Take the possible latency constraint and duration limitation - * present if the tick has been stopped already into account. + * Take the possible duration limitation present if the tick + * has been stopped already into account. */ intercept_sum = 0; recent_sum = 0; for (i = idx - 1; i >= 0; i--) { struct teo_bin *bin = &cpu_data->state_bins[i]; - s64 span_ns; intercept_sum += bin->intercepts; recent_sum += bin->recent; - span_ns = teo_middle_of_bin(i, drv); - if ((!alt_recent || 2 * recent_sum > idx_recent_sum) && (!alt_intercepts || 2 * intercept_sum > idx_intercept_sum)) { - if (teo_time_ok(span_ns) && - !dev->states_usage[i].disable) { + /* + * Use the current state unless it is too + * shallow or disabled, in which case take the + * first enabled state that is deep enough. + */ + if (teo_state_ok(i, drv) && + !dev->states_usage[i].disable) idx = i; - duration_ns = span_ns; - } else { - /* - * The current state is too shallow or - * disabled, so take the first enabled - * deeper state with suitable time span. - */ + else idx = first_suitable_idx; - duration_ns = first_suitable_span_ns; - } + break; } if (dev->states_usage[i].disable) continue; - if (!teo_time_ok(span_ns)) { + if (!teo_state_ok(i, drv)) { /* * The current state is too shallow, but if an * alternative candidate state has been found, @@ -525,7 +549,6 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, break; } - first_suitable_span_ns = span_ns; first_suitable_idx = i; } } @@ -539,31 +562,75 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev, /* * If the CPU is being utilized over the threshold, choose a shallower - * non-polling state to improve latency + * non-polling state to improve latency, unless the scheduler tick has + * been stopped already and the shallower state's target residency is + * not sufficiently large. */ - if (cpu_data->utilized) - idx = teo_find_shallower_state(drv, dev, idx, duration_ns, true); + if (cpu_utilized) { + i = teo_find_shallower_state(drv, dev, idx, KTIME_MAX, true); + if (teo_state_ok(i, drv)) + idx = i; + } -end: /* - * Don't stop the tick if the selected state is a polling one or if the - * expected idle duration is shorter than the tick period length. + * Skip the timers check if state 0 is the current candidate one, + * because an immediate non-timer wakeup is expected in that case. */ - if (((drv->states[idx].flags & CPUIDLE_FLAG_POLLING) || - duration_ns < TICK_NSEC) && !tick_nohz_tick_stopped()) { - *stop_tick = false; + if (!idx) + goto out_tick; - /* - * The tick is not going to be stopped, so if the target - * residency of the state to be returned is not within the time - * till the closest timer including the tick, try to correct - * that. - */ - if (idx > idx0 && - drv->states[idx].target_residency_ns > delta_tick) - idx = teo_find_shallower_state(drv, dev, idx, delta_tick, false); + /* + * If state 0 is a polling one, check if the target residency of + * the current candidate state is low enough and skip the timers + * check in that case too. + */ + if ((drv->states[0].flags & CPUIDLE_FLAG_POLLING) && + drv->states[idx].target_residency_ns < RESIDENCY_THRESHOLD_NS) + goto out_tick; + + duration_ns = tick_nohz_get_sleep_length(&delta_tick); + cpu_data->sleep_length_ns = duration_ns; + + /* + * If the closest expected timer is before the terget residency of the + * candidate state, a shallower one needs to be found. + */ + if (drv->states[idx].target_residency_ns > duration_ns) { + i = teo_find_shallower_state(drv, dev, idx, duration_ns, false); + if (teo_state_ok(i, drv)) + idx = i; } + /* + * If the selected state's target residency is below the tick length + * and intercepts occurring before the tick length are the majority of + * total wakeup events, do not stop the tick. + */ + if (drv->states[idx].target_residency_ns < TICK_NSEC && + tick_intercept_sum > cpu_data->total / 2 + cpu_data->total / 8) + duration_ns = TICK_NSEC / 2; + +end: + /* + * Allow the tick to be stopped unless the selected state is a polling + * one or the expected idle duration is shorter than the tick period + * length. + */ + if ((!(drv->states[idx].flags & CPUIDLE_FLAG_POLLING) && + duration_ns >= TICK_NSEC) || tick_nohz_tick_stopped()) + return idx; + + /* + * The tick is not going to be stopped, so if the target residency of + * the state to be returned is not within the time till the closest + * timer including the tick, try to correct that. + */ + if (idx > idx0 && + drv->states[idx].target_residency_ns > delta_tick) + idx = teo_find_shallower_state(drv, dev, idx, delta_tick, false); + +out_tick: + *stop_tick = false; return idx; } diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 44e44b8d9ce6..c761952f0dc6 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -70,10 +70,9 @@ config ZCRYPT select HW_RANDOM help Select this option if you want to enable support for - s390 cryptographic adapters like: - + Crypto Express 2 up to 7 Coprocessor (CEXxC) - + Crypto Express 2 up to 7 Accelerator (CEXxA) - + Crypto Express 4 up to 7 EP11 Coprocessor (CEXxP) + s390 cryptographic adapters like Crypto Express 4 up + to 8 in Coprocessor (CEXxC), EP11 Coprocessor (CEXxP) + or Accelerator (CEXxA) mode. config ZCRYPT_DEBUG bool "Enable debug features for s390 cryptographic adapters" diff --git a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c index 51a3a7b5b985..3bcfcfc37084 100644 --- a/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c +++ b/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c @@ -14,7 +14,6 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <crypto/scatterwalk.h> #include <linux/scatterlist.h> diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c index c13550090785..8d4c42863a62 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-cipher.c @@ -29,7 +29,7 @@ static int sun8i_ce_cipher_need_fallback(struct skcipher_request *areq) struct sun8i_ce_alg_template *algt; unsigned int todo, len; - algt = container_of(alg, struct sun8i_ce_alg_template, alg.skcipher); + algt = container_of(alg, struct sun8i_ce_alg_template, alg.skcipher.base); if (sg_nents_for_len(areq->src, areq->cryptlen) > MAX_SG || sg_nents_for_len(areq->dst, areq->cryptlen) > MAX_SG) { @@ -92,13 +92,18 @@ static int sun8i_ce_cipher_fallback(struct skcipher_request *areq) struct sun8i_cipher_tfm_ctx *op = crypto_skcipher_ctx(tfm); struct sun8i_cipher_req_ctx *rctx = skcipher_request_ctx(areq); int err; -#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG - struct skcipher_alg *alg = crypto_skcipher_alg(tfm); - struct sun8i_ce_alg_template *algt; - algt = container_of(alg, struct sun8i_ce_alg_template, alg.skcipher); - algt->stat_fb++; + if (IS_ENABLED(CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG)) { + struct skcipher_alg *alg = crypto_skcipher_alg(tfm); + struct sun8i_ce_alg_template *algt __maybe_unused; + + algt = container_of(alg, struct sun8i_ce_alg_template, + alg.skcipher.base); + +#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG + algt->stat_fb++; #endif + } skcipher_request_set_tfm(&rctx->fallback_req, op->fallback_tfm); skcipher_request_set_callback(&rctx->fallback_req, areq->base.flags, @@ -133,7 +138,7 @@ static int sun8i_ce_cipher_prepare(struct crypto_engine *engine, void *async_req int ns = sg_nents_for_len(areq->src, areq->cryptlen); int nd = sg_nents_for_len(areq->dst, areq->cryptlen); - algt = container_of(alg, struct sun8i_ce_alg_template, alg.skcipher); + algt = container_of(alg, struct sun8i_ce_alg_template, alg.skcipher.base); dev_dbg(ce->dev, "%s %s %u %x IV(%p %u) key=%u\n", __func__, crypto_tfm_alg_name(areq->base.tfm), @@ -294,7 +299,7 @@ theend: return err; } -static int sun8i_ce_cipher_run(struct crypto_engine *engine, void *areq) +static void sun8i_ce_cipher_run(struct crypto_engine *engine, void *areq) { struct skcipher_request *breq = container_of(areq, struct skcipher_request, base); struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(breq); @@ -308,10 +313,10 @@ static int sun8i_ce_cipher_run(struct crypto_engine *engine, void *areq) local_bh_disable(); crypto_finalize_skcipher_request(engine, breq, err); local_bh_enable(); - return 0; } -static int sun8i_ce_cipher_unprepare(struct crypto_engine *engine, void *async_req) +static void sun8i_ce_cipher_unprepare(struct crypto_engine *engine, + void *async_req) { struct skcipher_request *areq = container_of(async_req, struct skcipher_request, base); struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); @@ -353,7 +358,17 @@ static int sun8i_ce_cipher_unprepare(struct crypto_engine *engine, void *async_r } dma_unmap_single(ce->dev, rctx->addr_key, op->keylen, DMA_TO_DEVICE); +} + +int sun8i_ce_cipher_do_one(struct crypto_engine *engine, void *areq) +{ + int err = sun8i_ce_cipher_prepare(engine, areq); + if (err) + return err; + + sun8i_ce_cipher_run(engine, areq); + sun8i_ce_cipher_unprepare(engine, areq); return 0; } @@ -406,7 +421,7 @@ int sun8i_ce_cipher_init(struct crypto_tfm *tfm) memset(op, 0, sizeof(struct sun8i_cipher_tfm_ctx)); - algt = container_of(alg, struct sun8i_ce_alg_template, alg.skcipher); + algt = container_of(alg, struct sun8i_ce_alg_template, alg.skcipher.base); op->ce = algt->ce; op->fallback_tfm = crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); @@ -423,10 +438,6 @@ int sun8i_ce_cipher_init(struct crypto_tfm *tfm) crypto_tfm_alg_driver_name(crypto_skcipher_tfm(op->fallback_tfm)), CRYPTO_MAX_ALG_NAME); - op->enginectx.op.do_one_request = sun8i_ce_cipher_run; - op->enginectx.op.prepare_request = sun8i_ce_cipher_prepare; - op->enginectx.op.unprepare_request = sun8i_ce_cipher_unprepare; - err = pm_runtime_get_sync(op->ce->dev); if (err < 0) goto error_pm; diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c index 07ea0cc82b16..d4ccd5254280 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c @@ -9,21 +9,24 @@ * * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst */ + +#include <crypto/engine.h> +#include <crypto/internal/hash.h> +#include <crypto/internal/rng.h> +#include <crypto/internal/skcipher.h> #include <linux/clk.h> -#include <linux/crypto.h> #include <linux/delay.h> #include <linux/dma-mapping.h> +#include <linux/err.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/irq.h> +#include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/reset.h> -#include <crypto/internal/rng.h> -#include <crypto/internal/skcipher.h> #include "sun8i-ce.h" @@ -277,7 +280,7 @@ static struct sun8i_ce_alg_template ce_algs[] = { .type = CRYPTO_ALG_TYPE_SKCIPHER, .ce_algo_id = CE_ID_CIPHER_AES, .ce_blockmode = CE_ID_OP_CBC, - .alg.skcipher = { + .alg.skcipher.base = { .base = { .cra_name = "cbc(aes)", .cra_driver_name = "cbc-aes-sun8i-ce", @@ -298,13 +301,16 @@ static struct sun8i_ce_alg_template ce_algs[] = { .setkey = sun8i_ce_aes_setkey, .encrypt = sun8i_ce_skencrypt, .decrypt = sun8i_ce_skdecrypt, - } + }, + .alg.skcipher.op = { + .do_one_request = sun8i_ce_cipher_do_one, + }, }, { .type = CRYPTO_ALG_TYPE_SKCIPHER, .ce_algo_id = CE_ID_CIPHER_AES, .ce_blockmode = CE_ID_OP_ECB, - .alg.skcipher = { + .alg.skcipher.base = { .base = { .cra_name = "ecb(aes)", .cra_driver_name = "ecb-aes-sun8i-ce", @@ -324,13 +330,16 @@ static struct sun8i_ce_alg_template ce_algs[] = { .setkey = sun8i_ce_aes_setkey, .encrypt = sun8i_ce_skencrypt, .decrypt = sun8i_ce_skdecrypt, - } + }, + .alg.skcipher.op = { + .do_one_request = sun8i_ce_cipher_do_one, + }, }, { .type = CRYPTO_ALG_TYPE_SKCIPHER, .ce_algo_id = CE_ID_CIPHER_DES3, .ce_blockmode = CE_ID_OP_CBC, - .alg.skcipher = { + .alg.skcipher.base = { .base = { .cra_name = "cbc(des3_ede)", .cra_driver_name = "cbc-des3-sun8i-ce", @@ -351,13 +360,16 @@ static struct sun8i_ce_alg_template ce_algs[] = { .setkey = sun8i_ce_des3_setkey, .encrypt = sun8i_ce_skencrypt, .decrypt = sun8i_ce_skdecrypt, - } + }, + .alg.skcipher.op = { + .do_one_request = sun8i_ce_cipher_do_one, + }, }, { .type = CRYPTO_ALG_TYPE_SKCIPHER, .ce_algo_id = CE_ID_CIPHER_DES3, .ce_blockmode = CE_ID_OP_ECB, - .alg.skcipher = { + .alg.skcipher.base = { .base = { .cra_name = "ecb(des3_ede)", .cra_driver_name = "ecb-des3-sun8i-ce", @@ -377,12 +389,15 @@ static struct sun8i_ce_alg_template ce_algs[] = { .setkey = sun8i_ce_des3_setkey, .encrypt = sun8i_ce_skencrypt, .decrypt = sun8i_ce_skdecrypt, - } + }, + .alg.skcipher.op = { + .do_one_request = sun8i_ce_cipher_do_one, + }, }, #ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_HASH { .type = CRYPTO_ALG_TYPE_AHASH, .ce_algo_id = CE_ID_HASH_MD5, - .alg.hash = { + .alg.hash.base = { .init = sun8i_ce_hash_init, .update = sun8i_ce_hash_update, .final = sun8i_ce_hash_final, @@ -390,6 +405,8 @@ static struct sun8i_ce_alg_template ce_algs[] = { .digest = sun8i_ce_hash_digest, .export = sun8i_ce_hash_export, .import = sun8i_ce_hash_import, + .init_tfm = sun8i_ce_hash_init_tfm, + .exit_tfm = sun8i_ce_hash_exit_tfm, .halg = { .digestsize = MD5_DIGEST_SIZE, .statesize = sizeof(struct md5_state), @@ -404,15 +421,17 @@ static struct sun8i_ce_alg_template ce_algs[] = { .cra_blocksize = MD5_HMAC_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sun8i_ce_hash_tfm_ctx), .cra_module = THIS_MODULE, - .cra_init = sun8i_ce_hash_crainit, - .cra_exit = sun8i_ce_hash_craexit, } } - } + }, + .alg.hash.op = { + .do_one_request = sun8i_ce_hash_run, + }, + }, { .type = CRYPTO_ALG_TYPE_AHASH, .ce_algo_id = CE_ID_HASH_SHA1, - .alg.hash = { + .alg.hash.base = { .init = sun8i_ce_hash_init, .update = sun8i_ce_hash_update, .final = sun8i_ce_hash_final, @@ -420,6 +439,8 @@ static struct sun8i_ce_alg_template ce_algs[] = { .digest = sun8i_ce_hash_digest, .export = sun8i_ce_hash_export, .import = sun8i_ce_hash_import, + .init_tfm = sun8i_ce_hash_init_tfm, + .exit_tfm = sun8i_ce_hash_exit_tfm, .halg = { .digestsize = SHA1_DIGEST_SIZE, .statesize = sizeof(struct sha1_state), @@ -434,15 +455,16 @@ static struct sun8i_ce_alg_template ce_algs[] = { .cra_blocksize = SHA1_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sun8i_ce_hash_tfm_ctx), .cra_module = THIS_MODULE, - .cra_init = sun8i_ce_hash_crainit, - .cra_exit = sun8i_ce_hash_craexit, } } - } + }, + .alg.hash.op = { + .do_one_request = sun8i_ce_hash_run, + }, }, { .type = CRYPTO_ALG_TYPE_AHASH, .ce_algo_id = CE_ID_HASH_SHA224, - .alg.hash = { + .alg.hash.base = { .init = sun8i_ce_hash_init, .update = sun8i_ce_hash_update, .final = sun8i_ce_hash_final, @@ -450,6 +472,8 @@ static struct sun8i_ce_alg_template ce_algs[] = { .digest = sun8i_ce_hash_digest, .export = sun8i_ce_hash_export, .import = sun8i_ce_hash_import, + .init_tfm = sun8i_ce_hash_init_tfm, + .exit_tfm = sun8i_ce_hash_exit_tfm, .halg = { .digestsize = SHA224_DIGEST_SIZE, .statesize = sizeof(struct sha256_state), @@ -464,15 +488,16 @@ static struct sun8i_ce_alg_template ce_algs[] = { .cra_blocksize = SHA224_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sun8i_ce_hash_tfm_ctx), .cra_module = THIS_MODULE, - .cra_init = sun8i_ce_hash_crainit, - .cra_exit = sun8i_ce_hash_craexit, } } - } + }, + .alg.hash.op = { + .do_one_request = sun8i_ce_hash_run, + }, }, { .type = CRYPTO_ALG_TYPE_AHASH, .ce_algo_id = CE_ID_HASH_SHA256, - .alg.hash = { + .alg.hash.base = { .init = sun8i_ce_hash_init, .update = sun8i_ce_hash_update, .final = sun8i_ce_hash_final, @@ -480,6 +505,8 @@ static struct sun8i_ce_alg_template ce_algs[] = { .digest = sun8i_ce_hash_digest, .export = sun8i_ce_hash_export, .import = sun8i_ce_hash_import, + .init_tfm = sun8i_ce_hash_init_tfm, + .exit_tfm = sun8i_ce_hash_exit_tfm, .halg = { .digestsize = SHA256_DIGEST_SIZE, .statesize = sizeof(struct sha256_state), @@ -494,15 +521,16 @@ static struct sun8i_ce_alg_template ce_algs[] = { .cra_blocksize = SHA256_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sun8i_ce_hash_tfm_ctx), .cra_module = THIS_MODULE, - .cra_init = sun8i_ce_hash_crainit, - .cra_exit = sun8i_ce_hash_craexit, } } - } + }, + .alg.hash.op = { + .do_one_request = sun8i_ce_hash_run, + }, }, { .type = CRYPTO_ALG_TYPE_AHASH, .ce_algo_id = CE_ID_HASH_SHA384, - .alg.hash = { + .alg.hash.base = { .init = sun8i_ce_hash_init, .update = sun8i_ce_hash_update, .final = sun8i_ce_hash_final, @@ -510,6 +538,8 @@ static struct sun8i_ce_alg_template ce_algs[] = { .digest = sun8i_ce_hash_digest, .export = sun8i_ce_hash_export, .import = sun8i_ce_hash_import, + .init_tfm = sun8i_ce_hash_init_tfm, + .exit_tfm = sun8i_ce_hash_exit_tfm, .halg = { .digestsize = SHA384_DIGEST_SIZE, .statesize = sizeof(struct sha512_state), @@ -524,15 +554,16 @@ static struct sun8i_ce_alg_template ce_algs[] = { .cra_blocksize = SHA384_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sun8i_ce_hash_tfm_ctx), .cra_module = THIS_MODULE, - .cra_init = sun8i_ce_hash_crainit, - .cra_exit = sun8i_ce_hash_craexit, } } - } + }, + .alg.hash.op = { + .do_one_request = sun8i_ce_hash_run, + }, }, { .type = CRYPTO_ALG_TYPE_AHASH, .ce_algo_id = CE_ID_HASH_SHA512, - .alg.hash = { + .alg.hash.base = { .init = sun8i_ce_hash_init, .update = sun8i_ce_hash_update, .final = sun8i_ce_hash_final, @@ -540,6 +571,8 @@ static struct sun8i_ce_alg_template ce_algs[] = { .digest = sun8i_ce_hash_digest, .export = sun8i_ce_hash_export, .import = sun8i_ce_hash_import, + .init_tfm = sun8i_ce_hash_init_tfm, + .exit_tfm = sun8i_ce_hash_exit_tfm, .halg = { .digestsize = SHA512_DIGEST_SIZE, .statesize = sizeof(struct sha512_state), @@ -554,11 +587,12 @@ static struct sun8i_ce_alg_template ce_algs[] = { .cra_blocksize = SHA512_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sun8i_ce_hash_tfm_ctx), .cra_module = THIS_MODULE, - .cra_init = sun8i_ce_hash_crainit, - .cra_exit = sun8i_ce_hash_craexit, } } - } + }, + .alg.hash.op = { + .do_one_request = sun8i_ce_hash_run, + }, }, #endif #ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_PRNG @@ -582,14 +616,18 @@ static struct sun8i_ce_alg_template ce_algs[] = { #endif }; -#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG static int sun8i_ce_debugfs_show(struct seq_file *seq, void *v) { - struct sun8i_ce_dev *ce = seq->private; + struct sun8i_ce_dev *ce __maybe_unused = seq->private; unsigned int i; for (i = 0; i < MAXFLOW; i++) - seq_printf(seq, "Channel %d: nreq %lu\n", i, ce->chanlist[i].stat_req); + seq_printf(seq, "Channel %d: nreq %lu\n", i, +#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG + ce->chanlist[i].stat_req); +#else + 0ul); +#endif for (i = 0; i < ARRAY_SIZE(ce_algs); i++) { if (!ce_algs[i].ce) @@ -597,8 +635,8 @@ static int sun8i_ce_debugfs_show(struct seq_file *seq, void *v) switch (ce_algs[i].type) { case CRYPTO_ALG_TYPE_SKCIPHER: seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n", - ce_algs[i].alg.skcipher.base.cra_driver_name, - ce_algs[i].alg.skcipher.base.cra_name, + ce_algs[i].alg.skcipher.base.base.cra_driver_name, + ce_algs[i].alg.skcipher.base.base.cra_name, ce_algs[i].stat_req, ce_algs[i].stat_fb); seq_printf(seq, "\tLast fallback is: %s\n", ce_algs[i].fbname); @@ -621,8 +659,8 @@ static int sun8i_ce_debugfs_show(struct seq_file *seq, void *v) break; case CRYPTO_ALG_TYPE_AHASH: seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n", - ce_algs[i].alg.hash.halg.base.cra_driver_name, - ce_algs[i].alg.hash.halg.base.cra_name, + ce_algs[i].alg.hash.base.halg.base.cra_driver_name, + ce_algs[i].alg.hash.base.halg.base.cra_name, ce_algs[i].stat_req, ce_algs[i].stat_fb); seq_printf(seq, "\tLast fallback is: %s\n", ce_algs[i].fbname); @@ -643,7 +681,8 @@ static int sun8i_ce_debugfs_show(struct seq_file *seq, void *v) break; } } -#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_TRNG +#if defined(CONFIG_CRYPTO_DEV_SUN8I_CE_TRNG) && \ + defined(CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG) seq_printf(seq, "HWRNG %lu %lu\n", ce->hwrng_stat_req, ce->hwrng_stat_bytes); #endif @@ -651,7 +690,6 @@ static int sun8i_ce_debugfs_show(struct seq_file *seq, void *v) } DEFINE_SHOW_ATTRIBUTE(sun8i_ce_debugfs); -#endif static void sun8i_ce_free_chanlist(struct sun8i_ce_dev *ce, int i) { @@ -839,7 +877,7 @@ static int sun8i_ce_register_algs(struct sun8i_ce_dev *ce) if (ce_method == CE_ID_NOTSUPP) { dev_dbg(ce->dev, "DEBUG: Algo of %s not supported\n", - ce_algs[i].alg.skcipher.base.cra_name); + ce_algs[i].alg.skcipher.base.base.cra_name); ce_algs[i].ce = NULL; break; } @@ -847,16 +885,16 @@ static int sun8i_ce_register_algs(struct sun8i_ce_dev *ce) ce_method = ce->variant->op_mode[id]; if (ce_method == CE_ID_NOTSUPP) { dev_dbg(ce->dev, "DEBUG: Blockmode of %s not supported\n", - ce_algs[i].alg.skcipher.base.cra_name); + ce_algs[i].alg.skcipher.base.base.cra_name); ce_algs[i].ce = NULL; break; } dev_info(ce->dev, "Register %s\n", - ce_algs[i].alg.skcipher.base.cra_name); - err = crypto_register_skcipher(&ce_algs[i].alg.skcipher); + ce_algs[i].alg.skcipher.base.base.cra_name); + err = crypto_engine_register_skcipher(&ce_algs[i].alg.skcipher); if (err) { dev_err(ce->dev, "ERROR: Fail to register %s\n", - ce_algs[i].alg.skcipher.base.cra_name); + ce_algs[i].alg.skcipher.base.base.cra_name); ce_algs[i].ce = NULL; return err; } @@ -867,16 +905,16 @@ static int sun8i_ce_register_algs(struct sun8i_ce_dev *ce) if (ce_method == CE_ID_NOTSUPP) { dev_info(ce->dev, "DEBUG: Algo of %s not supported\n", - ce_algs[i].alg.hash.halg.base.cra_name); + ce_algs[i].alg.hash.base.halg.base.cra_name); ce_algs[i].ce = NULL; break; } dev_info(ce->dev, "Register %s\n", - ce_algs[i].alg.hash.halg.base.cra_name); - err = crypto_register_ahash(&ce_algs[i].alg.hash); + ce_algs[i].alg.hash.base.halg.base.cra_name); + err = crypto_engine_register_ahash(&ce_algs[i].alg.hash); if (err) { dev_err(ce->dev, "ERROR: Fail to register %s\n", - ce_algs[i].alg.hash.halg.base.cra_name); + ce_algs[i].alg.hash.base.halg.base.cra_name); ce_algs[i].ce = NULL; return err; } @@ -916,13 +954,13 @@ static void sun8i_ce_unregister_algs(struct sun8i_ce_dev *ce) switch (ce_algs[i].type) { case CRYPTO_ALG_TYPE_SKCIPHER: dev_info(ce->dev, "Unregister %d %s\n", i, - ce_algs[i].alg.skcipher.base.cra_name); - crypto_unregister_skcipher(&ce_algs[i].alg.skcipher); + ce_algs[i].alg.skcipher.base.base.cra_name); + crypto_engine_unregister_skcipher(&ce_algs[i].alg.skcipher); break; case CRYPTO_ALG_TYPE_AHASH: dev_info(ce->dev, "Unregister %d %s\n", i, - ce_algs[i].alg.hash.halg.base.cra_name); - crypto_unregister_ahash(&ce_algs[i].alg.hash); + ce_algs[i].alg.hash.base.halg.base.cra_name); + crypto_engine_unregister_ahash(&ce_algs[i].alg.hash); break; case CRYPTO_ALG_TYPE_RNG: dev_info(ce->dev, "Unregister %d %s\n", i, @@ -1007,13 +1045,21 @@ static int sun8i_ce_probe(struct platform_device *pdev) pm_runtime_put_sync(ce->dev); + if (IS_ENABLED(CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG)) { + struct dentry *dbgfs_dir __maybe_unused; + struct dentry *dbgfs_stats __maybe_unused; + + /* Ignore error of debugfs */ + dbgfs_dir = debugfs_create_dir("sun8i-ce", NULL); + dbgfs_stats = debugfs_create_file("stats", 0444, + dbgfs_dir, ce, + &sun8i_ce_debugfs_fops); + #ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG - /* Ignore error of debugfs */ - ce->dbgfs_dir = debugfs_create_dir("sun8i-ce", NULL); - ce->dbgfs_stats = debugfs_create_file("stats", 0444, - ce->dbgfs_dir, ce, - &sun8i_ce_debugfs_fops); + ce->dbgfs_dir = dbgfs_dir; + ce->dbgfs_stats = dbgfs_stats; #endif + } return 0; error_alg: diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c index 930ad157004c..d358334e5981 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-hash.c @@ -9,48 +9,46 @@ * * You could find the datasheet in Documentation/arch/arm/sunxi.rst */ + +#include <crypto/internal/hash.h> +#include <crypto/md5.h> +#include <crypto/sha1.h> +#include <crypto/sha2.h> #include <linux/bottom_half.h> #include <linux/dma-mapping.h> +#include <linux/kernel.h> #include <linux/pm_runtime.h> #include <linux/scatterlist.h> -#include <crypto/internal/hash.h> -#include <crypto/sha1.h> -#include <crypto/sha2.h> -#include <crypto/md5.h> +#include <linux/slab.h> +#include <linux/string.h> #include "sun8i-ce.h" -int sun8i_ce_hash_crainit(struct crypto_tfm *tfm) +int sun8i_ce_hash_init_tfm(struct crypto_ahash *tfm) { - struct sun8i_ce_hash_tfm_ctx *op = crypto_tfm_ctx(tfm); - struct ahash_alg *alg = __crypto_ahash_alg(tfm->__crt_alg); + struct sun8i_ce_hash_tfm_ctx *op = crypto_ahash_ctx(tfm); + struct ahash_alg *alg = crypto_ahash_alg(tfm); struct sun8i_ce_alg_template *algt; int err; - memset(op, 0, sizeof(struct sun8i_ce_hash_tfm_ctx)); - - algt = container_of(alg, struct sun8i_ce_alg_template, alg.hash); + algt = container_of(alg, struct sun8i_ce_alg_template, alg.hash.base); op->ce = algt->ce; - op->enginectx.op.do_one_request = sun8i_ce_hash_run; - op->enginectx.op.prepare_request = NULL; - op->enginectx.op.unprepare_request = NULL; - /* FALLBACK */ - op->fallback_tfm = crypto_alloc_ahash(crypto_tfm_alg_name(tfm), 0, + op->fallback_tfm = crypto_alloc_ahash(crypto_ahash_alg_name(tfm), 0, CRYPTO_ALG_NEED_FALLBACK); if (IS_ERR(op->fallback_tfm)) { dev_err(algt->ce->dev, "Fallback driver could no be loaded\n"); return PTR_ERR(op->fallback_tfm); } - if (algt->alg.hash.halg.statesize < crypto_ahash_statesize(op->fallback_tfm)) - algt->alg.hash.halg.statesize = crypto_ahash_statesize(op->fallback_tfm); + crypto_ahash_set_statesize(tfm, + crypto_ahash_statesize(op->fallback_tfm)); - crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), + crypto_ahash_set_reqsize(tfm, sizeof(struct sun8i_ce_hash_reqctx) + crypto_ahash_reqsize(op->fallback_tfm)); - memcpy(algt->fbname, crypto_tfm_alg_driver_name(&op->fallback_tfm->base), + memcpy(algt->fbname, crypto_ahash_driver_name(op->fallback_tfm), CRYPTO_MAX_ALG_NAME); err = pm_runtime_get_sync(op->ce->dev); @@ -63,9 +61,9 @@ error_pm: return err; } -void sun8i_ce_hash_craexit(struct crypto_tfm *tfm) +void sun8i_ce_hash_exit_tfm(struct crypto_ahash *tfm) { - struct sun8i_ce_hash_tfm_ctx *tfmctx = crypto_tfm_ctx(tfm); + struct sun8i_ce_hash_tfm_ctx *tfmctx = crypto_ahash_ctx(tfm); crypto_free_ahash(tfmctx->fallback_tfm); pm_runtime_put_sync_suspend(tfmctx->ce->dev); @@ -114,20 +112,22 @@ int sun8i_ce_hash_final(struct ahash_request *areq) struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx(areq); struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); struct sun8i_ce_hash_tfm_ctx *tfmctx = crypto_ahash_ctx(tfm); -#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG - struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg); - struct sun8i_ce_alg_template *algt; -#endif ahash_request_set_tfm(&rctx->fallback_req, tfmctx->fallback_tfm); rctx->fallback_req.base.flags = areq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP; rctx->fallback_req.result = areq->result; + if (IS_ENABLED(CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG)) { + struct sun8i_ce_alg_template *algt __maybe_unused; + struct ahash_alg *alg = crypto_ahash_alg(tfm); + + algt = container_of(alg, struct sun8i_ce_alg_template, + alg.hash.base); #ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG - algt = container_of(alg, struct sun8i_ce_alg_template, alg.hash); - algt->stat_fb++; + algt->stat_fb++; #endif + } return crypto_ahash_final(&rctx->fallback_req); } @@ -152,10 +152,6 @@ int sun8i_ce_hash_finup(struct ahash_request *areq) struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx(areq); struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); struct sun8i_ce_hash_tfm_ctx *tfmctx = crypto_ahash_ctx(tfm); -#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG - struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg); - struct sun8i_ce_alg_template *algt; -#endif ahash_request_set_tfm(&rctx->fallback_req, tfmctx->fallback_tfm); rctx->fallback_req.base.flags = areq->base.flags & @@ -164,10 +160,17 @@ int sun8i_ce_hash_finup(struct ahash_request *areq) rctx->fallback_req.nbytes = areq->nbytes; rctx->fallback_req.src = areq->src; rctx->fallback_req.result = areq->result; + + if (IS_ENABLED(CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG)) { + struct sun8i_ce_alg_template *algt __maybe_unused; + struct ahash_alg *alg = crypto_ahash_alg(tfm); + + algt = container_of(alg, struct sun8i_ce_alg_template, + alg.hash.base); #ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG - algt = container_of(alg, struct sun8i_ce_alg_template, alg.hash); - algt->stat_fb++; + algt->stat_fb++; #endif + } return crypto_ahash_finup(&rctx->fallback_req); } @@ -177,10 +180,6 @@ static int sun8i_ce_hash_digest_fb(struct ahash_request *areq) struct sun8i_ce_hash_reqctx *rctx = ahash_request_ctx(areq); struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); struct sun8i_ce_hash_tfm_ctx *tfmctx = crypto_ahash_ctx(tfm); -#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG - struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg); - struct sun8i_ce_alg_template *algt; -#endif ahash_request_set_tfm(&rctx->fallback_req, tfmctx->fallback_tfm); rctx->fallback_req.base.flags = areq->base.flags & @@ -189,10 +188,17 @@ static int sun8i_ce_hash_digest_fb(struct ahash_request *areq) rctx->fallback_req.nbytes = areq->nbytes; rctx->fallback_req.src = areq->src; rctx->fallback_req.result = areq->result; + + if (IS_ENABLED(CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG)) { + struct sun8i_ce_alg_template *algt __maybe_unused; + struct ahash_alg *alg = crypto_ahash_alg(tfm); + + algt = container_of(alg, struct sun8i_ce_alg_template, + alg.hash.base); #ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG - algt = container_of(alg, struct sun8i_ce_alg_template, alg.hash); - algt->stat_fb++; + algt->stat_fb++; #endif + } return crypto_ahash_digest(&rctx->fallback_req); } @@ -204,7 +210,7 @@ static bool sun8i_ce_hash_need_fallback(struct ahash_request *areq) struct sun8i_ce_alg_template *algt; struct scatterlist *sg; - algt = container_of(alg, struct sun8i_ce_alg_template, alg.hash); + algt = container_of(alg, struct sun8i_ce_alg_template, alg.hash.base); if (areq->nbytes == 0) { algt->stat_fb_len0++; @@ -253,7 +259,7 @@ int sun8i_ce_hash_digest(struct ahash_request *areq) return sun8i_ce_hash_digest_fb(areq); } - algt = container_of(alg, struct sun8i_ce_alg_template, alg.hash); + algt = container_of(alg, struct sun8i_ce_alg_template, alg.hash.base); ce = algt->ce; e = sun8i_ce_get_engine_number(ce); @@ -345,11 +351,11 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq) dma_addr_t addr_res, addr_pad; int ns = sg_nents_for_len(areq->src, areq->nbytes); - algt = container_of(alg, struct sun8i_ce_alg_template, alg.hash); + algt = container_of(alg, struct sun8i_ce_alg_template, alg.hash.base); ce = algt->ce; - bs = algt->alg.hash.halg.base.cra_blocksize; - digestsize = algt->alg.hash.halg.digestsize; + bs = algt->alg.hash.base.halg.base.cra_blocksize; + digestsize = algt->alg.hash.base.halg.digestsize; if (digestsize == SHA224_DIGEST_SIZE) digestsize = SHA256_DIGEST_SIZE; if (digestsize == SHA384_DIGEST_SIZE) @@ -454,14 +460,14 @@ int sun8i_ce_hash_run(struct crypto_engine *engine, void *breq) chan->timeout = areq->nbytes; - err = sun8i_ce_run_task(ce, flow, crypto_tfm_alg_name(areq->base.tfm)); + err = sun8i_ce_run_task(ce, flow, crypto_ahash_alg_name(tfm)); dma_unmap_single(ce->dev, addr_pad, j * 4, DMA_TO_DEVICE); dma_unmap_sg(ce->dev, areq->src, ns, DMA_TO_DEVICE); dma_unmap_single(ce->dev, addr_res, digestsize, DMA_FROM_DEVICE); - memcpy(areq->result, result, algt->alg.hash.halg.digestsize); + memcpy(areq->result, result, algt->alg.hash.base.halg.digestsize); theend: kfree(buf); kfree(result); diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h index 27029fb77e29..93d4985def87 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h @@ -265,14 +265,12 @@ struct sun8i_cipher_req_ctx { /* * struct sun8i_cipher_tfm_ctx - context for a skcipher TFM - * @enginectx: crypto_engine used by this TFM * @key: pointer to key data * @keylen: len of the key * @ce: pointer to the private data of driver handling this TFM * @fallback_tfm: pointer to the fallback TFM */ struct sun8i_cipher_tfm_ctx { - struct crypto_engine_ctx enginectx; u32 *key; u32 keylen; struct sun8i_ce_dev *ce; @@ -281,12 +279,10 @@ struct sun8i_cipher_tfm_ctx { /* * struct sun8i_ce_hash_tfm_ctx - context for an ahash TFM - * @enginectx: crypto_engine used by this TFM * @ce: pointer to the private data of driver handling this TFM * @fallback_tfm: pointer to the fallback TFM */ struct sun8i_ce_hash_tfm_ctx { - struct crypto_engine_ctx enginectx; struct sun8i_ce_dev *ce; struct crypto_ahash *fallback_tfm; }; @@ -329,8 +325,8 @@ struct sun8i_ce_alg_template { u32 ce_blockmode; struct sun8i_ce_dev *ce; union { - struct skcipher_alg skcipher; - struct ahash_alg hash; + struct skcipher_engine_alg skcipher; + struct ahash_engine_alg hash; struct rng_alg rng; } alg; unsigned long stat_req; @@ -347,14 +343,13 @@ struct sun8i_ce_alg_template { char fbname[CRYPTO_MAX_ALG_NAME]; }; -int sun8i_ce_enqueue(struct crypto_async_request *areq, u32 type); - int sun8i_ce_aes_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen); int sun8i_ce_des3_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen); int sun8i_ce_cipher_init(struct crypto_tfm *tfm); void sun8i_ce_cipher_exit(struct crypto_tfm *tfm); +int sun8i_ce_cipher_do_one(struct crypto_engine *engine, void *areq); int sun8i_ce_skdecrypt(struct skcipher_request *areq); int sun8i_ce_skencrypt(struct skcipher_request *areq); @@ -362,12 +357,11 @@ int sun8i_ce_get_engine_number(struct sun8i_ce_dev *ce); int sun8i_ce_run_task(struct sun8i_ce_dev *ce, int flow, const char *name); -int sun8i_ce_hash_crainit(struct crypto_tfm *tfm); -void sun8i_ce_hash_craexit(struct crypto_tfm *tfm); +int sun8i_ce_hash_init_tfm(struct crypto_ahash *tfm); +void sun8i_ce_hash_exit_tfm(struct crypto_ahash *tfm); int sun8i_ce_hash_init(struct ahash_request *areq); int sun8i_ce_hash_export(struct ahash_request *areq, void *out); int sun8i_ce_hash_import(struct ahash_request *areq, const void *in); -int sun8i_ce_hash(struct ahash_request *areq); int sun8i_ce_hash_final(struct ahash_request *areq); int sun8i_ce_hash_update(struct ahash_request *areq); int sun8i_ce_hash_finup(struct ahash_request *areq); diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c index 381a90fbeaff..7fa359725ec7 100644 --- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c +++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-cipher.c @@ -24,7 +24,7 @@ static bool sun8i_ss_need_fallback(struct skcipher_request *areq) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(areq); struct skcipher_alg *alg = crypto_skcipher_alg(tfm); - struct sun8i_ss_alg_template *algt = container_of(alg, struct sun8i_ss_alg_template, alg.skcipher); + struct sun8i_ss_alg_template *algt = container_of(alg, struct sun8i_ss_alg_template, alg.skcipher.base); struct scatterlist *in_sg = areq->src; struct scatterlist *out_sg = areq->dst; struct scatterlist *sg; @@ -93,13 +93,18 @@ static int sun8i_ss_cipher_fallback(struct skcipher_request *areq) struct sun8i_cipher_req_ctx *rctx = skcipher_request_ctx(areq); int err; -#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG - struct skcipher_alg *alg = crypto_skcipher_alg(tfm); - struct sun8i_ss_alg_template *algt; + if (IS_ENABLED(CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG)) { + struct skcipher_alg *alg = crypto_skcipher_alg(tfm); + struct sun8i_ss_alg_template *algt __maybe_unused; + + algt = container_of(alg, struct sun8i_ss_alg_template, + alg.skcipher.base); - algt = container_of(alg, struct sun8i_ss_alg_template, alg.skcipher); - algt->stat_fb++; +#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG + algt->stat_fb++; #endif + } + skcipher_request_set_tfm(&rctx->fallback_req, op->fallback_tfm); skcipher_request_set_callback(&rctx->fallback_req, areq->base.flags, areq->base.complete, areq->base.data); @@ -193,7 +198,7 @@ static int sun8i_ss_cipher(struct skcipher_request *areq) int nsgd = sg_nents_for_len(areq->dst, areq->cryptlen); int i; - algt = container_of(alg, struct sun8i_ss_alg_template, alg.skcipher); + algt = container_of(alg, struct sun8i_ss_alg_template, alg.skcipher.base); dev_dbg(ss->dev, "%s %s %u %x IV(%p %u) key=%u\n", __func__, crypto_tfm_alg_name(areq->base.tfm), @@ -324,7 +329,7 @@ theend: return err; } -static int sun8i_ss_handle_cipher_request(struct crypto_engine *engine, void *areq) +int sun8i_ss_handle_cipher_request(struct crypto_engine *engine, void *areq) { int err; struct skcipher_request *breq = container_of(areq, struct skcipher_request, base); @@ -390,7 +395,7 @@ int sun8i_ss_cipher_init(struct crypto_tfm *tfm) memset(op, 0, sizeof(struct sun8i_cipher_tfm_ctx)); - algt = container_of(alg, struct sun8i_ss_alg_template, alg.skcipher); + algt = container_of(alg, struct sun8i_ss_alg_template, alg.skcipher.base); op->ss = algt->ss; op->fallback_tfm = crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); @@ -408,10 +413,6 @@ int sun8i_ss_cipher_init(struct crypto_tfm *tfm) crypto_tfm_alg_driver_name(crypto_skcipher_tfm(op->fallback_tfm)), CRYPTO_MAX_ALG_NAME); - op->enginectx.op.do_one_request = sun8i_ss_handle_cipher_request; - op->enginectx.op.prepare_request = NULL; - op->enginectx.op.unprepare_request = NULL; - err = pm_runtime_resume_and_get(op->ss->dev); if (err < 0) { dev_err(op->ss->dev, "pm error %d\n", err); diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c index 3dd844b40ff7..4a9587285c04 100644 --- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c +++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c @@ -9,22 +9,23 @@ * * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst */ + +#include <crypto/engine.h> +#include <crypto/internal/rng.h> +#include <crypto/internal/skcipher.h> #include <linux/clk.h> -#include <linux/crypto.h> #include <linux/delay.h> #include <linux/dma-mapping.h> +#include <linux/err.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/irq.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/reset.h> -#include <crypto/internal/rng.h> -#include <crypto/internal/skcipher.h> #include "sun8i-ss.h" @@ -168,7 +169,7 @@ static struct sun8i_ss_alg_template ss_algs[] = { .type = CRYPTO_ALG_TYPE_SKCIPHER, .ss_algo_id = SS_ID_CIPHER_AES, .ss_blockmode = SS_ID_OP_CBC, - .alg.skcipher = { + .alg.skcipher.base = { .base = { .cra_name = "cbc(aes)", .cra_driver_name = "cbc-aes-sun8i-ss", @@ -189,13 +190,16 @@ static struct sun8i_ss_alg_template ss_algs[] = { .setkey = sun8i_ss_aes_setkey, .encrypt = sun8i_ss_skencrypt, .decrypt = sun8i_ss_skdecrypt, - } + }, + .alg.skcipher.op = { + .do_one_request = sun8i_ss_handle_cipher_request, + }, }, { .type = CRYPTO_ALG_TYPE_SKCIPHER, .ss_algo_id = SS_ID_CIPHER_AES, .ss_blockmode = SS_ID_OP_ECB, - .alg.skcipher = { + .alg.skcipher.base = { .base = { .cra_name = "ecb(aes)", .cra_driver_name = "ecb-aes-sun8i-ss", @@ -215,13 +219,16 @@ static struct sun8i_ss_alg_template ss_algs[] = { .setkey = sun8i_ss_aes_setkey, .encrypt = sun8i_ss_skencrypt, .decrypt = sun8i_ss_skdecrypt, - } + }, + .alg.skcipher.op = { + .do_one_request = sun8i_ss_handle_cipher_request, + }, }, { .type = CRYPTO_ALG_TYPE_SKCIPHER, .ss_algo_id = SS_ID_CIPHER_DES3, .ss_blockmode = SS_ID_OP_CBC, - .alg.skcipher = { + .alg.skcipher.base = { .base = { .cra_name = "cbc(des3_ede)", .cra_driver_name = "cbc-des3-sun8i-ss", @@ -242,13 +249,16 @@ static struct sun8i_ss_alg_template ss_algs[] = { .setkey = sun8i_ss_des3_setkey, .encrypt = sun8i_ss_skencrypt, .decrypt = sun8i_ss_skdecrypt, - } + }, + .alg.skcipher.op = { + .do_one_request = sun8i_ss_handle_cipher_request, + }, }, { .type = CRYPTO_ALG_TYPE_SKCIPHER, .ss_algo_id = SS_ID_CIPHER_DES3, .ss_blockmode = SS_ID_OP_ECB, - .alg.skcipher = { + .alg.skcipher.base = { .base = { .cra_name = "ecb(des3_ede)", .cra_driver_name = "ecb-des3-sun8i-ss", @@ -268,7 +278,10 @@ static struct sun8i_ss_alg_template ss_algs[] = { .setkey = sun8i_ss_des3_setkey, .encrypt = sun8i_ss_skencrypt, .decrypt = sun8i_ss_skdecrypt, - } + }, + .alg.skcipher.op = { + .do_one_request = sun8i_ss_handle_cipher_request, + }, }, #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_PRNG { @@ -292,7 +305,7 @@ static struct sun8i_ss_alg_template ss_algs[] = { #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_HASH { .type = CRYPTO_ALG_TYPE_AHASH, .ss_algo_id = SS_ID_HASH_MD5, - .alg.hash = { + .alg.hash.base = { .init = sun8i_ss_hash_init, .update = sun8i_ss_hash_update, .final = sun8i_ss_hash_final, @@ -300,6 +313,8 @@ static struct sun8i_ss_alg_template ss_algs[] = { .digest = sun8i_ss_hash_digest, .export = sun8i_ss_hash_export, .import = sun8i_ss_hash_import, + .init_tfm = sun8i_ss_hash_init_tfm, + .exit_tfm = sun8i_ss_hash_exit_tfm, .halg = { .digestsize = MD5_DIGEST_SIZE, .statesize = sizeof(struct md5_state), @@ -314,15 +329,16 @@ static struct sun8i_ss_alg_template ss_algs[] = { .cra_blocksize = MD5_HMAC_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sun8i_ss_hash_tfm_ctx), .cra_module = THIS_MODULE, - .cra_init = sun8i_ss_hash_crainit, - .cra_exit = sun8i_ss_hash_craexit, } } - } + }, + .alg.hash.op = { + .do_one_request = sun8i_ss_hash_run, + }, }, { .type = CRYPTO_ALG_TYPE_AHASH, .ss_algo_id = SS_ID_HASH_SHA1, - .alg.hash = { + .alg.hash.base = { .init = sun8i_ss_hash_init, .update = sun8i_ss_hash_update, .final = sun8i_ss_hash_final, @@ -330,6 +346,8 @@ static struct sun8i_ss_alg_template ss_algs[] = { .digest = sun8i_ss_hash_digest, .export = sun8i_ss_hash_export, .import = sun8i_ss_hash_import, + .init_tfm = sun8i_ss_hash_init_tfm, + .exit_tfm = sun8i_ss_hash_exit_tfm, .halg = { .digestsize = SHA1_DIGEST_SIZE, .statesize = sizeof(struct sha1_state), @@ -344,15 +362,16 @@ static struct sun8i_ss_alg_template ss_algs[] = { .cra_blocksize = SHA1_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sun8i_ss_hash_tfm_ctx), .cra_module = THIS_MODULE, - .cra_init = sun8i_ss_hash_crainit, - .cra_exit = sun8i_ss_hash_craexit, } } - } + }, + .alg.hash.op = { + .do_one_request = sun8i_ss_hash_run, + }, }, { .type = CRYPTO_ALG_TYPE_AHASH, .ss_algo_id = SS_ID_HASH_SHA224, - .alg.hash = { + .alg.hash.base = { .init = sun8i_ss_hash_init, .update = sun8i_ss_hash_update, .final = sun8i_ss_hash_final, @@ -360,6 +379,8 @@ static struct sun8i_ss_alg_template ss_algs[] = { .digest = sun8i_ss_hash_digest, .export = sun8i_ss_hash_export, .import = sun8i_ss_hash_import, + .init_tfm = sun8i_ss_hash_init_tfm, + .exit_tfm = sun8i_ss_hash_exit_tfm, .halg = { .digestsize = SHA224_DIGEST_SIZE, .statesize = sizeof(struct sha256_state), @@ -374,15 +395,16 @@ static struct sun8i_ss_alg_template ss_algs[] = { .cra_blocksize = SHA224_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sun8i_ss_hash_tfm_ctx), .cra_module = THIS_MODULE, - .cra_init = sun8i_ss_hash_crainit, - .cra_exit = sun8i_ss_hash_craexit, } } - } + }, + .alg.hash.op = { + .do_one_request = sun8i_ss_hash_run, + }, }, { .type = CRYPTO_ALG_TYPE_AHASH, .ss_algo_id = SS_ID_HASH_SHA256, - .alg.hash = { + .alg.hash.base = { .init = sun8i_ss_hash_init, .update = sun8i_ss_hash_update, .final = sun8i_ss_hash_final, @@ -390,6 +412,8 @@ static struct sun8i_ss_alg_template ss_algs[] = { .digest = sun8i_ss_hash_digest, .export = sun8i_ss_hash_export, .import = sun8i_ss_hash_import, + .init_tfm = sun8i_ss_hash_init_tfm, + .exit_tfm = sun8i_ss_hash_exit_tfm, .halg = { .digestsize = SHA256_DIGEST_SIZE, .statesize = sizeof(struct sha256_state), @@ -404,15 +428,16 @@ static struct sun8i_ss_alg_template ss_algs[] = { .cra_blocksize = SHA256_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sun8i_ss_hash_tfm_ctx), .cra_module = THIS_MODULE, - .cra_init = sun8i_ss_hash_crainit, - .cra_exit = sun8i_ss_hash_craexit, } } - } + }, + .alg.hash.op = { + .do_one_request = sun8i_ss_hash_run, + }, }, { .type = CRYPTO_ALG_TYPE_AHASH, .ss_algo_id = SS_ID_HASH_SHA1, - .alg.hash = { + .alg.hash.base = { .init = sun8i_ss_hash_init, .update = sun8i_ss_hash_update, .final = sun8i_ss_hash_final, @@ -420,6 +445,8 @@ static struct sun8i_ss_alg_template ss_algs[] = { .digest = sun8i_ss_hash_digest, .export = sun8i_ss_hash_export, .import = sun8i_ss_hash_import, + .init_tfm = sun8i_ss_hash_init_tfm, + .exit_tfm = sun8i_ss_hash_exit_tfm, .setkey = sun8i_ss_hmac_setkey, .halg = { .digestsize = SHA1_DIGEST_SIZE, @@ -435,23 +462,28 @@ static struct sun8i_ss_alg_template ss_algs[] = { .cra_blocksize = SHA1_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sun8i_ss_hash_tfm_ctx), .cra_module = THIS_MODULE, - .cra_init = sun8i_ss_hash_crainit, - .cra_exit = sun8i_ss_hash_craexit, } } - } + }, + .alg.hash.op = { + .do_one_request = sun8i_ss_hash_run, + }, }, #endif }; -#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG static int sun8i_ss_debugfs_show(struct seq_file *seq, void *v) { - struct sun8i_ss_dev *ss = seq->private; + struct sun8i_ss_dev *ss __maybe_unused = seq->private; unsigned int i; for (i = 0; i < MAXFLOW; i++) - seq_printf(seq, "Channel %d: nreq %lu\n", i, ss->flows[i].stat_req); + seq_printf(seq, "Channel %d: nreq %lu\n", i, +#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG + ss->flows[i].stat_req); +#else + 0ul); +#endif for (i = 0; i < ARRAY_SIZE(ss_algs); i++) { if (!ss_algs[i].ss) @@ -459,8 +491,8 @@ static int sun8i_ss_debugfs_show(struct seq_file *seq, void *v) switch (ss_algs[i].type) { case CRYPTO_ALG_TYPE_SKCIPHER: seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n", - ss_algs[i].alg.skcipher.base.cra_driver_name, - ss_algs[i].alg.skcipher.base.cra_name, + ss_algs[i].alg.skcipher.base.base.cra_driver_name, + ss_algs[i].alg.skcipher.base.base.cra_name, ss_algs[i].stat_req, ss_algs[i].stat_fb); seq_printf(seq, "\tLast fallback is: %s\n", @@ -482,8 +514,8 @@ static int sun8i_ss_debugfs_show(struct seq_file *seq, void *v) break; case CRYPTO_ALG_TYPE_AHASH: seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n", - ss_algs[i].alg.hash.halg.base.cra_driver_name, - ss_algs[i].alg.hash.halg.base.cra_name, + ss_algs[i].alg.hash.base.halg.base.cra_driver_name, + ss_algs[i].alg.hash.base.halg.base.cra_name, ss_algs[i].stat_req, ss_algs[i].stat_fb); seq_printf(seq, "\tLast fallback is: %s\n", ss_algs[i].fbname); @@ -502,7 +534,6 @@ static int sun8i_ss_debugfs_show(struct seq_file *seq, void *v) } DEFINE_SHOW_ATTRIBUTE(sun8i_ss_debugfs); -#endif static void sun8i_ss_free_flows(struct sun8i_ss_dev *ss, int i) { @@ -659,7 +690,7 @@ static int sun8i_ss_register_algs(struct sun8i_ss_dev *ss) if (ss_method == SS_ID_NOTSUPP) { dev_info(ss->dev, "DEBUG: Algo of %s not supported\n", - ss_algs[i].alg.skcipher.base.cra_name); + ss_algs[i].alg.skcipher.base.base.cra_name); ss_algs[i].ss = NULL; break; } @@ -667,16 +698,16 @@ static int sun8i_ss_register_algs(struct sun8i_ss_dev *ss) ss_method = ss->variant->op_mode[id]; if (ss_method == SS_ID_NOTSUPP) { dev_info(ss->dev, "DEBUG: Blockmode of %s not supported\n", - ss_algs[i].alg.skcipher.base.cra_name); + ss_algs[i].alg.skcipher.base.base.cra_name); ss_algs[i].ss = NULL; break; } dev_info(ss->dev, "DEBUG: Register %s\n", - ss_algs[i].alg.skcipher.base.cra_name); - err = crypto_register_skcipher(&ss_algs[i].alg.skcipher); + ss_algs[i].alg.skcipher.base.base.cra_name); + err = crypto_engine_register_skcipher(&ss_algs[i].alg.skcipher); if (err) { dev_err(ss->dev, "Fail to register %s\n", - ss_algs[i].alg.skcipher.base.cra_name); + ss_algs[i].alg.skcipher.base.base.cra_name); ss_algs[i].ss = NULL; return err; } @@ -695,16 +726,16 @@ static int sun8i_ss_register_algs(struct sun8i_ss_dev *ss) if (ss_method == SS_ID_NOTSUPP) { dev_info(ss->dev, "DEBUG: Algo of %s not supported\n", - ss_algs[i].alg.hash.halg.base.cra_name); + ss_algs[i].alg.hash.base.halg.base.cra_name); ss_algs[i].ss = NULL; break; } dev_info(ss->dev, "Register %s\n", - ss_algs[i].alg.hash.halg.base.cra_name); - err = crypto_register_ahash(&ss_algs[i].alg.hash); + ss_algs[i].alg.hash.base.halg.base.cra_name); + err = crypto_engine_register_ahash(&ss_algs[i].alg.hash); if (err) { dev_err(ss->dev, "ERROR: Fail to register %s\n", - ss_algs[i].alg.hash.halg.base.cra_name); + ss_algs[i].alg.hash.base.halg.base.cra_name); ss_algs[i].ss = NULL; return err; } @@ -727,8 +758,8 @@ static void sun8i_ss_unregister_algs(struct sun8i_ss_dev *ss) switch (ss_algs[i].type) { case CRYPTO_ALG_TYPE_SKCIPHER: dev_info(ss->dev, "Unregister %d %s\n", i, - ss_algs[i].alg.skcipher.base.cra_name); - crypto_unregister_skcipher(&ss_algs[i].alg.skcipher); + ss_algs[i].alg.skcipher.base.base.cra_name); + crypto_engine_unregister_skcipher(&ss_algs[i].alg.skcipher); break; case CRYPTO_ALG_TYPE_RNG: dev_info(ss->dev, "Unregister %d %s\n", i, @@ -737,8 +768,8 @@ static void sun8i_ss_unregister_algs(struct sun8i_ss_dev *ss) break; case CRYPTO_ALG_TYPE_AHASH: dev_info(ss->dev, "Unregister %d %s\n", i, - ss_algs[i].alg.hash.halg.base.cra_name); - crypto_unregister_ahash(&ss_algs[i].alg.hash); + ss_algs[i].alg.hash.base.halg.base.cra_name); + crypto_engine_unregister_ahash(&ss_algs[i].alg.hash); break; } } @@ -851,13 +882,21 @@ static int sun8i_ss_probe(struct platform_device *pdev) pm_runtime_put_sync(ss->dev); + if (IS_ENABLED(CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG)) { + struct dentry *dbgfs_dir __maybe_unused; + struct dentry *dbgfs_stats __maybe_unused; + + /* Ignore error of debugfs */ + dbgfs_dir = debugfs_create_dir("sun8i-ss", NULL); + dbgfs_stats = debugfs_create_file("stats", 0444, + dbgfs_dir, ss, + &sun8i_ss_debugfs_fops); + #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG - /* Ignore error of debugfs */ - ss->dbgfs_dir = debugfs_create_dir("sun8i-ss", NULL); - ss->dbgfs_stats = debugfs_create_file("stats", 0444, - ss->dbgfs_dir, ss, - &sun8i_ss_debugfs_fops); + ss->dbgfs_dir = dbgfs_dir; + ss->dbgfs_stats = dbgfs_stats; #endif + } return 0; error_alg: diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c index a4b67d130d11..d70b105dcfa1 100644 --- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c +++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss-hash.c @@ -9,16 +9,21 @@ * * You could find the datasheet in Documentation/arch/arm/sunxi.rst */ -#include <linux/bottom_half.h> -#include <linux/dma-mapping.h> -#include <linux/pm_runtime.h> -#include <linux/scatterlist.h> -#include <crypto/internal/hash.h> + #include <crypto/hmac.h> +#include <crypto/internal/hash.h> +#include <crypto/md5.h> #include <crypto/scatterwalk.h> #include <crypto/sha1.h> #include <crypto/sha2.h> -#include <crypto/md5.h> +#include <linux/bottom_half.h> +#include <linux/dma-mapping.h> +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/pm_runtime.h> +#include <linux/scatterlist.h> +#include <linux/slab.h> +#include <linux/string.h> #include "sun8i-ss.h" static int sun8i_ss_hashkey(struct sun8i_ss_hash_tfm_ctx *tfmctx, const u8 *key, @@ -60,14 +65,11 @@ int sun8i_ss_hmac_setkey(struct crypto_ahash *ahash, const u8 *key, unsigned int keylen) { struct sun8i_ss_hash_tfm_ctx *tfmctx = crypto_ahash_ctx(ahash); - struct ahash_alg *alg = __crypto_ahash_alg(ahash->base.__crt_alg); - struct sun8i_ss_alg_template *algt; int digestsize, i; int bs = crypto_ahash_blocksize(ahash); int ret; - algt = container_of(alg, struct sun8i_ss_alg_template, alg.hash); - digestsize = algt->alg.hash.halg.digestsize; + digestsize = crypto_ahash_digestsize(ahash); if (keylen > bs) { ret = sun8i_ss_hashkey(tfmctx, key, keylen); @@ -107,38 +109,33 @@ err_opad: return ret; } -int sun8i_ss_hash_crainit(struct crypto_tfm *tfm) +int sun8i_ss_hash_init_tfm(struct crypto_ahash *tfm) { - struct sun8i_ss_hash_tfm_ctx *op = crypto_tfm_ctx(tfm); - struct ahash_alg *alg = __crypto_ahash_alg(tfm->__crt_alg); + struct sun8i_ss_hash_tfm_ctx *op = crypto_ahash_ctx(tfm); + struct ahash_alg *alg = crypto_ahash_alg(tfm); struct sun8i_ss_alg_template *algt; int err; - memset(op, 0, sizeof(struct sun8i_ss_hash_tfm_ctx)); - - algt = container_of(alg, struct sun8i_ss_alg_template, alg.hash); + algt = container_of(alg, struct sun8i_ss_alg_template, alg.hash.base); op->ss = algt->ss; - op->enginectx.op.do_one_request = sun8i_ss_hash_run; - op->enginectx.op.prepare_request = NULL; - op->enginectx.op.unprepare_request = NULL; - /* FALLBACK */ - op->fallback_tfm = crypto_alloc_ahash(crypto_tfm_alg_name(tfm), 0, + op->fallback_tfm = crypto_alloc_ahash(crypto_ahash_alg_name(tfm), 0, CRYPTO_ALG_NEED_FALLBACK); if (IS_ERR(op->fallback_tfm)) { dev_err(algt->ss->dev, "Fallback driver could no be loaded\n"); return PTR_ERR(op->fallback_tfm); } - if (algt->alg.hash.halg.statesize < crypto_ahash_statesize(op->fallback_tfm)) - algt->alg.hash.halg.statesize = crypto_ahash_statesize(op->fallback_tfm); + crypto_ahash_set_statesize(tfm, + crypto_ahash_statesize(op->fallback_tfm)); - crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), + crypto_ahash_set_reqsize(tfm, sizeof(struct sun8i_ss_hash_reqctx) + crypto_ahash_reqsize(op->fallback_tfm)); - memcpy(algt->fbname, crypto_tfm_alg_driver_name(&op->fallback_tfm->base), CRYPTO_MAX_ALG_NAME); + memcpy(algt->fbname, crypto_ahash_driver_name(op->fallback_tfm), + CRYPTO_MAX_ALG_NAME); err = pm_runtime_get_sync(op->ss->dev); if (err < 0) @@ -150,9 +147,9 @@ error_pm: return err; } -void sun8i_ss_hash_craexit(struct crypto_tfm *tfm) +void sun8i_ss_hash_exit_tfm(struct crypto_ahash *tfm) { - struct sun8i_ss_hash_tfm_ctx *tfmctx = crypto_tfm_ctx(tfm); + struct sun8i_ss_hash_tfm_ctx *tfmctx = crypto_ahash_ctx(tfm); kfree_sensitive(tfmctx->ipad); kfree_sensitive(tfmctx->opad); @@ -204,20 +201,23 @@ int sun8i_ss_hash_final(struct ahash_request *areq) struct sun8i_ss_hash_reqctx *rctx = ahash_request_ctx(areq); struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); struct sun8i_ss_hash_tfm_ctx *tfmctx = crypto_ahash_ctx(tfm); -#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG - struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg); - struct sun8i_ss_alg_template *algt; -#endif ahash_request_set_tfm(&rctx->fallback_req, tfmctx->fallback_tfm); rctx->fallback_req.base.flags = areq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP; rctx->fallback_req.result = areq->result; + if (IS_ENABLED(CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG)) { + struct ahash_alg *alg = crypto_ahash_alg(tfm); + struct sun8i_ss_alg_template *algt __maybe_unused; + + algt = container_of(alg, struct sun8i_ss_alg_template, + alg.hash.base); + #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG - algt = container_of(alg, struct sun8i_ss_alg_template, alg.hash); - algt->stat_fb++; + algt->stat_fb++; #endif + } return crypto_ahash_final(&rctx->fallback_req); } @@ -242,10 +242,6 @@ int sun8i_ss_hash_finup(struct ahash_request *areq) struct sun8i_ss_hash_reqctx *rctx = ahash_request_ctx(areq); struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); struct sun8i_ss_hash_tfm_ctx *tfmctx = crypto_ahash_ctx(tfm); -#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG - struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg); - struct sun8i_ss_alg_template *algt; -#endif ahash_request_set_tfm(&rctx->fallback_req, tfmctx->fallback_tfm); rctx->fallback_req.base.flags = areq->base.flags & @@ -254,10 +250,18 @@ int sun8i_ss_hash_finup(struct ahash_request *areq) rctx->fallback_req.nbytes = areq->nbytes; rctx->fallback_req.src = areq->src; rctx->fallback_req.result = areq->result; + + if (IS_ENABLED(CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG)) { + struct ahash_alg *alg = crypto_ahash_alg(tfm); + struct sun8i_ss_alg_template *algt __maybe_unused; + + algt = container_of(alg, struct sun8i_ss_alg_template, + alg.hash.base); + #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG - algt = container_of(alg, struct sun8i_ss_alg_template, alg.hash); - algt->stat_fb++; + algt->stat_fb++; #endif + } return crypto_ahash_finup(&rctx->fallback_req); } @@ -267,10 +271,6 @@ static int sun8i_ss_hash_digest_fb(struct ahash_request *areq) struct sun8i_ss_hash_reqctx *rctx = ahash_request_ctx(areq); struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); struct sun8i_ss_hash_tfm_ctx *tfmctx = crypto_ahash_ctx(tfm); -#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG - struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg); - struct sun8i_ss_alg_template *algt; -#endif ahash_request_set_tfm(&rctx->fallback_req, tfmctx->fallback_tfm); rctx->fallback_req.base.flags = areq->base.flags & @@ -279,10 +279,18 @@ static int sun8i_ss_hash_digest_fb(struct ahash_request *areq) rctx->fallback_req.nbytes = areq->nbytes; rctx->fallback_req.src = areq->src; rctx->fallback_req.result = areq->result; + + if (IS_ENABLED(CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG)) { + struct ahash_alg *alg = crypto_ahash_alg(tfm); + struct sun8i_ss_alg_template *algt __maybe_unused; + + algt = container_of(alg, struct sun8i_ss_alg_template, + alg.hash.base); + #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG - algt = container_of(alg, struct sun8i_ss_alg_template, alg.hash); - algt->stat_fb++; + algt->stat_fb++; #endif + } return crypto_ahash_digest(&rctx->fallback_req); } @@ -349,11 +357,11 @@ static int sun8i_ss_run_hash_task(struct sun8i_ss_dev *ss, static bool sun8i_ss_hash_need_fallback(struct ahash_request *areq) { struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); - struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg); + struct ahash_alg *alg = crypto_ahash_alg(tfm); struct sun8i_ss_alg_template *algt; struct scatterlist *sg; - algt = container_of(alg, struct sun8i_ss_alg_template, alg.hash); + algt = container_of(alg, struct sun8i_ss_alg_template, alg.hash.base); if (areq->nbytes == 0) { algt->stat_fb_len++; @@ -398,8 +406,8 @@ static bool sun8i_ss_hash_need_fallback(struct ahash_request *areq) int sun8i_ss_hash_digest(struct ahash_request *areq) { struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); - struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg); struct sun8i_ss_hash_reqctx *rctx = ahash_request_ctx(areq); + struct ahash_alg *alg = crypto_ahash_alg(tfm); struct sun8i_ss_alg_template *algt; struct sun8i_ss_dev *ss; struct crypto_engine *engine; @@ -408,7 +416,7 @@ int sun8i_ss_hash_digest(struct ahash_request *areq) if (sun8i_ss_hash_need_fallback(areq)) return sun8i_ss_hash_digest_fb(areq); - algt = container_of(alg, struct sun8i_ss_alg_template, alg.hash); + algt = container_of(alg, struct sun8i_ss_alg_template, alg.hash.base); ss = algt->ss; e = sun8i_ss_get_engine_number(ss); @@ -484,8 +492,8 @@ int sun8i_ss_hash_run(struct crypto_engine *engine, void *breq) struct ahash_request *areq = container_of(breq, struct ahash_request, base); struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); struct sun8i_ss_hash_tfm_ctx *tfmctx = crypto_ahash_ctx(tfm); - struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg); struct sun8i_ss_hash_reqctx *rctx = ahash_request_ctx(areq); + struct ahash_alg *alg = crypto_ahash_alg(tfm); struct sun8i_ss_alg_template *algt; struct sun8i_ss_dev *ss; struct scatterlist *sg; @@ -504,10 +512,10 @@ int sun8i_ss_hash_run(struct crypto_engine *engine, void *breq) */ int hmac = 0; - algt = container_of(alg, struct sun8i_ss_alg_template, alg.hash); + algt = container_of(alg, struct sun8i_ss_alg_template, alg.hash.base); ss = algt->ss; - digestsize = algt->alg.hash.halg.digestsize; + digestsize = crypto_ahash_digestsize(tfm); if (digestsize == SHA224_DIGEST_SIZE) digestsize = SHA256_DIGEST_SIZE; @@ -700,7 +708,7 @@ err_dma_result: } if (!err) - memcpy(areq->result, result, algt->alg.hash.halg.digestsize); + memcpy(areq->result, result, crypto_ahash_digestsize(tfm)); theend: local_bh_disable(); crypto_finalize_hash_request(engine, breq, err); diff --git a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h index df6f08f6092f..ae66eb45fb24 100644 --- a/drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h +++ b/drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h @@ -201,16 +201,12 @@ struct sun8i_cipher_req_ctx { /* * struct sun8i_cipher_tfm_ctx - context for a skcipher TFM - * @enginectx: crypto_engine used by this TFM * @key: pointer to key data * @keylen: len of the key * @ss: pointer to the private data of driver handling this TFM * @fallback_tfm: pointer to the fallback TFM - * - * enginectx must be the first element */ struct sun8i_cipher_tfm_ctx { - struct crypto_engine_ctx enginectx; u32 *key; u32 keylen; struct sun8i_ss_dev *ss; @@ -229,14 +225,10 @@ struct sun8i_ss_rng_tfm_ctx { /* * struct sun8i_ss_hash_tfm_ctx - context for an ahash TFM - * @enginectx: crypto_engine used by this TFM * @fallback_tfm: pointer to the fallback TFM * @ss: pointer to the private data of driver handling this TFM - * - * enginectx must be the first element */ struct sun8i_ss_hash_tfm_ctx { - struct crypto_engine_ctx enginectx; struct crypto_ahash *fallback_tfm; struct sun8i_ss_dev *ss; u8 *ipad; @@ -279,9 +271,9 @@ struct sun8i_ss_alg_template { u32 ss_blockmode; struct sun8i_ss_dev *ss; union { - struct skcipher_alg skcipher; + struct skcipher_engine_alg skcipher; struct rng_alg rng; - struct ahash_alg hash; + struct ahash_engine_alg hash; } alg; unsigned long stat_req; unsigned long stat_fb; @@ -293,14 +285,13 @@ struct sun8i_ss_alg_template { char fbname[CRYPTO_MAX_ALG_NAME]; }; -int sun8i_ss_enqueue(struct crypto_async_request *areq, u32 type); - int sun8i_ss_aes_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen); int sun8i_ss_des3_setkey(struct crypto_skcipher *tfm, const u8 *key, unsigned int keylen); int sun8i_ss_cipher_init(struct crypto_tfm *tfm); void sun8i_ss_cipher_exit(struct crypto_tfm *tfm); +int sun8i_ss_handle_cipher_request(struct crypto_engine *engine, void *areq); int sun8i_ss_skdecrypt(struct skcipher_request *areq); int sun8i_ss_skencrypt(struct skcipher_request *areq); @@ -313,8 +304,8 @@ int sun8i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen int sun8i_ss_prng_init(struct crypto_tfm *tfm); void sun8i_ss_prng_exit(struct crypto_tfm *tfm); -int sun8i_ss_hash_crainit(struct crypto_tfm *tfm); -void sun8i_ss_hash_craexit(struct crypto_tfm *tfm); +int sun8i_ss_hash_init_tfm(struct crypto_ahash *tfm); +void sun8i_ss_hash_exit_tfm(struct crypto_ahash *tfm); int sun8i_ss_hash_init(struct ahash_request *areq); int sun8i_ss_hash_export(struct ahash_request *areq, void *out); int sun8i_ss_hash_import(struct ahash_request *areq, const void *in); diff --git a/drivers/crypto/amlogic/amlogic-gxl-cipher.c b/drivers/crypto/amlogic/amlogic-gxl-cipher.c index af017a087ebf..3308406612fc 100644 --- a/drivers/crypto/amlogic/amlogic-gxl-cipher.c +++ b/drivers/crypto/amlogic/amlogic-gxl-cipher.c @@ -65,7 +65,7 @@ static int meson_cipher_do_fallback(struct skcipher_request *areq) struct skcipher_alg *alg = crypto_skcipher_alg(tfm); struct meson_alg_template *algt; - algt = container_of(alg, struct meson_alg_template, alg.skcipher); + algt = container_of(alg, struct meson_alg_template, alg.skcipher.base); algt->stat_fb++; #endif skcipher_request_set_tfm(&rctx->fallback_req, op->fallback_tfm); @@ -101,7 +101,7 @@ static int meson_cipher(struct skcipher_request *areq) void *backup_iv = NULL, *bkeyiv; u32 v; - algt = container_of(alg, struct meson_alg_template, alg.skcipher); + algt = container_of(alg, struct meson_alg_template, alg.skcipher.base); dev_dbg(mc->dev, "%s %s %u %x IV(%u) key=%u flow=%d\n", __func__, crypto_tfm_alg_name(areq->base.tfm), @@ -258,8 +258,7 @@ theend: return err; } -static int meson_handle_cipher_request(struct crypto_engine *engine, - void *areq) +int meson_handle_cipher_request(struct crypto_engine *engine, void *areq) { int err; struct skcipher_request *breq = container_of(areq, struct skcipher_request, base); @@ -318,7 +317,7 @@ int meson_cipher_init(struct crypto_tfm *tfm) memset(op, 0, sizeof(struct meson_cipher_tfm_ctx)); - algt = container_of(alg, struct meson_alg_template, alg.skcipher); + algt = container_of(alg, struct meson_alg_template, alg.skcipher.base); op->mc = algt->mc; op->fallback_tfm = crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); @@ -331,10 +330,6 @@ int meson_cipher_init(struct crypto_tfm *tfm) sktfm->reqsize = sizeof(struct meson_cipher_req_ctx) + crypto_skcipher_reqsize(op->fallback_tfm); - op->enginectx.op.do_one_request = meson_handle_cipher_request; - op->enginectx.op.prepare_request = NULL; - op->enginectx.op.unprepare_request = NULL; - return 0; } diff --git a/drivers/crypto/amlogic/amlogic-gxl-core.c b/drivers/crypto/amlogic/amlogic-gxl-core.c index 937187027ad5..da6dfe0f9ac3 100644 --- a/drivers/crypto/amlogic/amlogic-gxl-core.c +++ b/drivers/crypto/amlogic/amlogic-gxl-core.c @@ -6,17 +6,19 @@ * * Core file which registers crypto algorithms supported by the hardware. */ + +#include <crypto/engine.h> +#include <crypto/internal/skcipher.h> #include <linux/clk.h> -#include <linux/crypto.h> -#include <linux/io.h> +#include <linux/dma-mapping.h> +#include <linux/err.h> #include <linux/interrupt.h> +#include <linux/io.h> #include <linux/irq.h> +#include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> -#include <crypto/internal/skcipher.h> -#include <linux/dma-mapping.h> #include "amlogic-gxl.h" @@ -47,7 +49,7 @@ static struct meson_alg_template mc_algs[] = { { .type = CRYPTO_ALG_TYPE_SKCIPHER, .blockmode = MESON_OPMODE_CBC, - .alg.skcipher = { + .alg.skcipher.base = { .base = { .cra_name = "cbc(aes)", .cra_driver_name = "cbc-aes-gxl", @@ -68,12 +70,15 @@ static struct meson_alg_template mc_algs[] = { .setkey = meson_aes_setkey, .encrypt = meson_skencrypt, .decrypt = meson_skdecrypt, - } + }, + .alg.skcipher.op = { + .do_one_request = meson_handle_cipher_request, + }, }, { .type = CRYPTO_ALG_TYPE_SKCIPHER, .blockmode = MESON_OPMODE_ECB, - .alg.skcipher = { + .alg.skcipher.base = { .base = { .cra_name = "ecb(aes)", .cra_driver_name = "ecb-aes-gxl", @@ -93,33 +98,43 @@ static struct meson_alg_template mc_algs[] = { .setkey = meson_aes_setkey, .encrypt = meson_skencrypt, .decrypt = meson_skdecrypt, - } + }, + .alg.skcipher.op = { + .do_one_request = meson_handle_cipher_request, + }, }, }; -#ifdef CONFIG_CRYPTO_DEV_AMLOGIC_GXL_DEBUG static int meson_debugfs_show(struct seq_file *seq, void *v) { - struct meson_dev *mc = seq->private; + struct meson_dev *mc __maybe_unused = seq->private; int i; for (i = 0; i < MAXFLOW; i++) - seq_printf(seq, "Channel %d: nreq %lu\n", i, mc->chanlist[i].stat_req); + seq_printf(seq, "Channel %d: nreq %lu\n", i, +#ifdef CONFIG_CRYPTO_DEV_AMLOGIC_GXL_DEBUG + mc->chanlist[i].stat_req); +#else + 0ul); +#endif for (i = 0; i < ARRAY_SIZE(mc_algs); i++) { switch (mc_algs[i].type) { case CRYPTO_ALG_TYPE_SKCIPHER: seq_printf(seq, "%s %s %lu %lu\n", - mc_algs[i].alg.skcipher.base.cra_driver_name, - mc_algs[i].alg.skcipher.base.cra_name, + mc_algs[i].alg.skcipher.base.base.cra_driver_name, + mc_algs[i].alg.skcipher.base.base.cra_name, +#ifdef CONFIG_CRYPTO_DEV_AMLOGIC_GXL_DEBUG mc_algs[i].stat_req, mc_algs[i].stat_fb); +#else + 0ul, 0ul); +#endif break; } } return 0; } DEFINE_SHOW_ATTRIBUTE(meson_debugfs); -#endif static void meson_free_chanlist(struct meson_dev *mc, int i) { @@ -183,10 +198,10 @@ static int meson_register_algs(struct meson_dev *mc) mc_algs[i].mc = mc; switch (mc_algs[i].type) { case CRYPTO_ALG_TYPE_SKCIPHER: - err = crypto_register_skcipher(&mc_algs[i].alg.skcipher); + err = crypto_engine_register_skcipher(&mc_algs[i].alg.skcipher); if (err) { dev_err(mc->dev, "Fail to register %s\n", - mc_algs[i].alg.skcipher.base.cra_name); + mc_algs[i].alg.skcipher.base.base.cra_name); mc_algs[i].mc = NULL; return err; } @@ -206,7 +221,7 @@ static void meson_unregister_algs(struct meson_dev *mc) continue; switch (mc_algs[i].type) { case CRYPTO_ALG_TYPE_SKCIPHER: - crypto_unregister_skcipher(&mc_algs[i].alg.skcipher); + crypto_engine_unregister_skcipher(&mc_algs[i].alg.skcipher); break; } } @@ -264,10 +279,16 @@ static int meson_crypto_probe(struct platform_device *pdev) if (err) goto error_alg; + if (IS_ENABLED(CONFIG_CRYPTO_DEV_AMLOGIC_GXL_DEBUG)) { + struct dentry *dbgfs_dir; + + dbgfs_dir = debugfs_create_dir("gxl-crypto", NULL); + debugfs_create_file("stats", 0444, dbgfs_dir, mc, &meson_debugfs_fops); + #ifdef CONFIG_CRYPTO_DEV_AMLOGIC_GXL_DEBUG - mc->dbgfs_dir = debugfs_create_dir("gxl-crypto", NULL); - debugfs_create_file("stats", 0444, mc->dbgfs_dir, mc, &meson_debugfs_fops); + mc->dbgfs_dir = dbgfs_dir; #endif + } return 0; error_alg: diff --git a/drivers/crypto/amlogic/amlogic-gxl.h b/drivers/crypto/amlogic/amlogic-gxl.h index 8c0746a1d6d4..1013a666c932 100644 --- a/drivers/crypto/amlogic/amlogic-gxl.h +++ b/drivers/crypto/amlogic/amlogic-gxl.h @@ -114,7 +114,6 @@ struct meson_cipher_req_ctx { /* * struct meson_cipher_tfm_ctx - context for a skcipher TFM - * @enginectx: crypto_engine used by this TFM * @key: pointer to key data * @keylen: len of the key * @keymode: The keymode(type and size of key) associated with this TFM @@ -122,7 +121,6 @@ struct meson_cipher_req_ctx { * @fallback_tfm: pointer to the fallback TFM */ struct meson_cipher_tfm_ctx { - struct crypto_engine_ctx enginectx; u32 *key; u32 keylen; u32 keymode; @@ -143,7 +141,7 @@ struct meson_alg_template { u32 type; u32 blockmode; union { - struct skcipher_alg skcipher; + struct skcipher_engine_alg skcipher; } alg; struct meson_dev *mc; #ifdef CONFIG_CRYPTO_DEV_AMLOGIC_GXL_DEBUG @@ -160,3 +158,4 @@ int meson_cipher_init(struct crypto_tfm *tfm); void meson_cipher_exit(struct crypto_tfm *tfm); int meson_skdecrypt(struct skcipher_request *areq); int meson_skencrypt(struct skcipher_request *areq); +int meson_handle_cipher_request(struct crypto_engine *engine, void *areq); diff --git a/drivers/crypto/aspeed/aspeed-acry.c b/drivers/crypto/aspeed/aspeed-acry.c index 470122c87fea..247c568aa8df 100644 --- a/drivers/crypto/aspeed/aspeed-acry.c +++ b/drivers/crypto/aspeed/aspeed-acry.c @@ -2,25 +2,23 @@ /* * Copyright 2021 Aspeed Technology Inc. */ -#include <crypto/akcipher.h> -#include <crypto/algapi.h> #include <crypto/engine.h> #include <crypto/internal/akcipher.h> #include <crypto/internal/rsa.h> #include <crypto/scatterwalk.h> #include <linux/clk.h> -#include <linux/platform_device.h> -#include <linux/module.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/mfd/syscon.h> -#include <linux/interrupt.h> #include <linux/count_zeros.h> -#include <linux/err.h> #include <linux/dma-mapping.h> +#include <linux/err.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/regmap.h> +#include <linux/slab.h> +#include <linux/string.h> #ifdef CONFIG_CRYPTO_DEV_ASPEED_DEBUG #define ACRY_DBG(d, fmt, ...) \ @@ -112,7 +110,6 @@ struct aspeed_acry_dev { }; struct aspeed_acry_ctx { - struct crypto_engine_ctx enginectx; struct aspeed_acry_dev *acry_dev; struct rsa_key key; @@ -131,7 +128,7 @@ struct aspeed_acry_ctx { struct aspeed_acry_alg { struct aspeed_acry_dev *acry_dev; - struct akcipher_alg akcipher; + struct akcipher_engine_alg akcipher; }; enum aspeed_rsa_key_mode { @@ -577,7 +574,7 @@ static int aspeed_acry_rsa_init_tfm(struct crypto_akcipher *tfm) const char *name = crypto_tfm_alg_name(&tfm->base); struct aspeed_acry_alg *acry_alg; - acry_alg = container_of(alg, struct aspeed_acry_alg, akcipher); + acry_alg = container_of(alg, struct aspeed_acry_alg, akcipher.base); ctx->acry_dev = acry_alg->acry_dev; @@ -589,10 +586,6 @@ static int aspeed_acry_rsa_init_tfm(struct crypto_akcipher *tfm) return PTR_ERR(ctx->fallback_tfm); } - ctx->enginectx.op.do_one_request = aspeed_acry_do_request; - ctx->enginectx.op.prepare_request = NULL; - ctx->enginectx.op.unprepare_request = NULL; - return 0; } @@ -605,7 +598,7 @@ static void aspeed_acry_rsa_exit_tfm(struct crypto_akcipher *tfm) static struct aspeed_acry_alg aspeed_acry_akcipher_algs[] = { { - .akcipher = { + .akcipher.base = { .encrypt = aspeed_acry_rsa_enc, .decrypt = aspeed_acry_rsa_dec, .sign = aspeed_acry_rsa_dec, @@ -627,6 +620,9 @@ static struct aspeed_acry_alg aspeed_acry_akcipher_algs[] = { .cra_ctxsize = sizeof(struct aspeed_acry_ctx), }, }, + .akcipher.op = { + .do_one_request = aspeed_acry_do_request, + }, }, }; @@ -636,10 +632,10 @@ static void aspeed_acry_register(struct aspeed_acry_dev *acry_dev) for (i = 0; i < ARRAY_SIZE(aspeed_acry_akcipher_algs); i++) { aspeed_acry_akcipher_algs[i].acry_dev = acry_dev; - rc = crypto_register_akcipher(&aspeed_acry_akcipher_algs[i].akcipher); + rc = crypto_engine_register_akcipher(&aspeed_acry_akcipher_algs[i].akcipher); if (rc) { ACRY_DBG(acry_dev, "Failed to register %s\n", - aspeed_acry_akcipher_algs[i].akcipher.base.cra_name); + aspeed_acry_akcipher_algs[i].akcipher.base.base.cra_name); } } } @@ -649,7 +645,7 @@ static void aspeed_acry_unregister(struct aspeed_acry_dev *acry_dev) int i; for (i = 0; i < ARRAY_SIZE(aspeed_acry_akcipher_algs); i++) - crypto_unregister_akcipher(&aspeed_acry_akcipher_algs[i].akcipher); + crypto_engine_unregister_akcipher(&aspeed_acry_akcipher_algs[i].akcipher); } /* ACRY interrupt service routine. */ diff --git a/drivers/crypto/aspeed/aspeed-hace-crypto.c b/drivers/crypto/aspeed/aspeed-hace-crypto.c index ef73b0028b4d..f0eddb7854e5 100644 --- a/drivers/crypto/aspeed/aspeed-hace-crypto.c +++ b/drivers/crypto/aspeed/aspeed-hace-crypto.c @@ -4,6 +4,17 @@ */ #include "aspeed-hace.h" +#include <crypto/des.h> +#include <crypto/engine.h> +#include <crypto/internal/des.h> +#include <crypto/internal/skcipher.h> +#include <linux/dma-mapping.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/scatterlist.h> +#include <linux/string.h> #ifdef CONFIG_CRYPTO_DEV_ASPEED_HACE_CRYPTO_DEBUG #define CIPHER_DBG(h, fmt, ...) \ @@ -696,7 +707,7 @@ static int aspeed_crypto_cra_init(struct crypto_skcipher *tfm) struct aspeed_hace_alg *crypto_alg; - crypto_alg = container_of(alg, struct aspeed_hace_alg, alg.skcipher); + crypto_alg = container_of(alg, struct aspeed_hace_alg, alg.skcipher.base); ctx->hace_dev = crypto_alg->hace_dev; ctx->start = aspeed_hace_skcipher_trigger; @@ -713,10 +724,6 @@ static int aspeed_crypto_cra_init(struct crypto_skcipher *tfm) crypto_skcipher_set_reqsize(tfm, sizeof(struct aspeed_cipher_reqctx) + crypto_skcipher_reqsize(ctx->fallback_tfm)); - ctx->enginectx.op.do_one_request = aspeed_crypto_do_request; - ctx->enginectx.op.prepare_request = NULL; - ctx->enginectx.op.unprepare_request = NULL; - return 0; } @@ -731,7 +738,7 @@ static void aspeed_crypto_cra_exit(struct crypto_skcipher *tfm) static struct aspeed_hace_alg aspeed_crypto_algs[] = { { - .alg.skcipher = { + .alg.skcipher.base = { .min_keysize = AES_MIN_KEY_SIZE, .max_keysize = AES_MAX_KEY_SIZE, .setkey = aspeed_aes_setkey, @@ -751,10 +758,13 @@ static struct aspeed_hace_alg aspeed_crypto_algs[] = { .cra_alignmask = 0x0f, .cra_module = THIS_MODULE, } - } + }, + .alg.skcipher.op = { + .do_one_request = aspeed_crypto_do_request, + }, }, { - .alg.skcipher = { + .alg.skcipher.base = { .ivsize = AES_BLOCK_SIZE, .min_keysize = AES_MIN_KEY_SIZE, .max_keysize = AES_MAX_KEY_SIZE, @@ -775,10 +785,13 @@ static struct aspeed_hace_alg aspeed_crypto_algs[] = { .cra_alignmask = 0x0f, .cra_module = THIS_MODULE, } - } + }, + .alg.skcipher.op = { + .do_one_request = aspeed_crypto_do_request, + }, }, { - .alg.skcipher = { + .alg.skcipher.base = { .ivsize = AES_BLOCK_SIZE, .min_keysize = AES_MIN_KEY_SIZE, .max_keysize = AES_MAX_KEY_SIZE, @@ -799,10 +812,13 @@ static struct aspeed_hace_alg aspeed_crypto_algs[] = { .cra_alignmask = 0x0f, .cra_module = THIS_MODULE, } - } + }, + .alg.skcipher.op = { + .do_one_request = aspeed_crypto_do_request, + }, }, { - .alg.skcipher = { + .alg.skcipher.base = { .ivsize = AES_BLOCK_SIZE, .min_keysize = AES_MIN_KEY_SIZE, .max_keysize = AES_MAX_KEY_SIZE, @@ -823,10 +839,13 @@ static struct aspeed_hace_alg aspeed_crypto_algs[] = { .cra_alignmask = 0x0f, .cra_module = THIS_MODULE, } - } + }, + .alg.skcipher.op = { + .do_one_request = aspeed_crypto_do_request, + }, }, { - .alg.skcipher = { + .alg.skcipher.base = { .min_keysize = DES_KEY_SIZE, .max_keysize = DES_KEY_SIZE, .setkey = aspeed_des_setkey, @@ -846,10 +865,13 @@ static struct aspeed_hace_alg aspeed_crypto_algs[] = { .cra_alignmask = 0x0f, .cra_module = THIS_MODULE, } - } + }, + .alg.skcipher.op = { + .do_one_request = aspeed_crypto_do_request, + }, }, { - .alg.skcipher = { + .alg.skcipher.base = { .ivsize = DES_BLOCK_SIZE, .min_keysize = DES_KEY_SIZE, .max_keysize = DES_KEY_SIZE, @@ -870,10 +892,13 @@ static struct aspeed_hace_alg aspeed_crypto_algs[] = { .cra_alignmask = 0x0f, .cra_module = THIS_MODULE, } - } + }, + .alg.skcipher.op = { + .do_one_request = aspeed_crypto_do_request, + }, }, { - .alg.skcipher = { + .alg.skcipher.base = { .ivsize = DES_BLOCK_SIZE, .min_keysize = DES_KEY_SIZE, .max_keysize = DES_KEY_SIZE, @@ -894,10 +919,13 @@ static struct aspeed_hace_alg aspeed_crypto_algs[] = { .cra_alignmask = 0x0f, .cra_module = THIS_MODULE, } - } + }, + .alg.skcipher.op = { + .do_one_request = aspeed_crypto_do_request, + }, }, { - .alg.skcipher = { + .alg.skcipher.base = { .ivsize = DES_BLOCK_SIZE, .min_keysize = DES_KEY_SIZE, .max_keysize = DES_KEY_SIZE, @@ -918,10 +946,13 @@ static struct aspeed_hace_alg aspeed_crypto_algs[] = { .cra_alignmask = 0x0f, .cra_module = THIS_MODULE, } - } + }, + .alg.skcipher.op = { + .do_one_request = aspeed_crypto_do_request, + }, }, { - .alg.skcipher = { + .alg.skcipher.base = { .min_keysize = DES3_EDE_KEY_SIZE, .max_keysize = DES3_EDE_KEY_SIZE, .setkey = aspeed_des_setkey, @@ -941,10 +972,13 @@ static struct aspeed_hace_alg aspeed_crypto_algs[] = { .cra_alignmask = 0x0f, .cra_module = THIS_MODULE, } - } + }, + .alg.skcipher.op = { + .do_one_request = aspeed_crypto_do_request, + }, }, { - .alg.skcipher = { + .alg.skcipher.base = { .ivsize = DES_BLOCK_SIZE, .min_keysize = DES3_EDE_KEY_SIZE, .max_keysize = DES3_EDE_KEY_SIZE, @@ -965,10 +999,13 @@ static struct aspeed_hace_alg aspeed_crypto_algs[] = { .cra_alignmask = 0x0f, .cra_module = THIS_MODULE, } - } + }, + .alg.skcipher.op = { + .do_one_request = aspeed_crypto_do_request, + }, }, { - .alg.skcipher = { + .alg.skcipher.base = { .ivsize = DES_BLOCK_SIZE, .min_keysize = DES3_EDE_KEY_SIZE, .max_keysize = DES3_EDE_KEY_SIZE, @@ -989,10 +1026,13 @@ static struct aspeed_hace_alg aspeed_crypto_algs[] = { .cra_alignmask = 0x0f, .cra_module = THIS_MODULE, } - } + }, + .alg.skcipher.op = { + .do_one_request = aspeed_crypto_do_request, + }, }, { - .alg.skcipher = { + .alg.skcipher.base = { .ivsize = DES_BLOCK_SIZE, .min_keysize = DES3_EDE_KEY_SIZE, .max_keysize = DES3_EDE_KEY_SIZE, @@ -1013,13 +1053,16 @@ static struct aspeed_hace_alg aspeed_crypto_algs[] = { .cra_alignmask = 0x0f, .cra_module = THIS_MODULE, } - } + }, + .alg.skcipher.op = { + .do_one_request = aspeed_crypto_do_request, + }, }, }; static struct aspeed_hace_alg aspeed_crypto_algs_g6[] = { { - .alg.skcipher = { + .alg.skcipher.base = { .ivsize = AES_BLOCK_SIZE, .min_keysize = AES_MIN_KEY_SIZE, .max_keysize = AES_MAX_KEY_SIZE, @@ -1039,10 +1082,13 @@ static struct aspeed_hace_alg aspeed_crypto_algs_g6[] = { .cra_alignmask = 0x0f, .cra_module = THIS_MODULE, } - } + }, + .alg.skcipher.op = { + .do_one_request = aspeed_crypto_do_request, + }, }, { - .alg.skcipher = { + .alg.skcipher.base = { .ivsize = DES_BLOCK_SIZE, .min_keysize = DES_KEY_SIZE, .max_keysize = DES_KEY_SIZE, @@ -1062,10 +1108,13 @@ static struct aspeed_hace_alg aspeed_crypto_algs_g6[] = { .cra_alignmask = 0x0f, .cra_module = THIS_MODULE, } - } + }, + .alg.skcipher.op = { + .do_one_request = aspeed_crypto_do_request, + }, }, { - .alg.skcipher = { + .alg.skcipher.base = { .ivsize = DES_BLOCK_SIZE, .min_keysize = DES3_EDE_KEY_SIZE, .max_keysize = DES3_EDE_KEY_SIZE, @@ -1085,7 +1134,10 @@ static struct aspeed_hace_alg aspeed_crypto_algs_g6[] = { .cra_alignmask = 0x0f, .cra_module = THIS_MODULE, } - } + }, + .alg.skcipher.op = { + .do_one_request = aspeed_crypto_do_request, + }, }, }; @@ -1095,13 +1147,13 @@ void aspeed_unregister_hace_crypto_algs(struct aspeed_hace_dev *hace_dev) int i; for (i = 0; i < ARRAY_SIZE(aspeed_crypto_algs); i++) - crypto_unregister_skcipher(&aspeed_crypto_algs[i].alg.skcipher); + crypto_engine_unregister_skcipher(&aspeed_crypto_algs[i].alg.skcipher); if (hace_dev->version != AST2600_VERSION) return; for (i = 0; i < ARRAY_SIZE(aspeed_crypto_algs_g6); i++) - crypto_unregister_skcipher(&aspeed_crypto_algs_g6[i].alg.skcipher); + crypto_engine_unregister_skcipher(&aspeed_crypto_algs_g6[i].alg.skcipher); } void aspeed_register_hace_crypto_algs(struct aspeed_hace_dev *hace_dev) @@ -1112,10 +1164,10 @@ void aspeed_register_hace_crypto_algs(struct aspeed_hace_dev *hace_dev) for (i = 0; i < ARRAY_SIZE(aspeed_crypto_algs); i++) { aspeed_crypto_algs[i].hace_dev = hace_dev; - rc = crypto_register_skcipher(&aspeed_crypto_algs[i].alg.skcipher); + rc = crypto_engine_register_skcipher(&aspeed_crypto_algs[i].alg.skcipher); if (rc) { CIPHER_DBG(hace_dev, "Failed to register %s\n", - aspeed_crypto_algs[i].alg.skcipher.base.cra_name); + aspeed_crypto_algs[i].alg.skcipher.base.base.cra_name); } } @@ -1124,10 +1176,10 @@ void aspeed_register_hace_crypto_algs(struct aspeed_hace_dev *hace_dev) for (i = 0; i < ARRAY_SIZE(aspeed_crypto_algs_g6); i++) { aspeed_crypto_algs_g6[i].hace_dev = hace_dev; - rc = crypto_register_skcipher(&aspeed_crypto_algs_g6[i].alg.skcipher); + rc = crypto_engine_register_skcipher(&aspeed_crypto_algs_g6[i].alg.skcipher); if (rc) { CIPHER_DBG(hace_dev, "Failed to register %s\n", - aspeed_crypto_algs_g6[i].alg.skcipher.base.cra_name); + aspeed_crypto_algs_g6[i].alg.skcipher.base.base.cra_name); } } } diff --git a/drivers/crypto/aspeed/aspeed-hace-hash.c b/drivers/crypto/aspeed/aspeed-hace-hash.c index 935135229ebd..0b6e49c06eff 100644 --- a/drivers/crypto/aspeed/aspeed-hace-hash.c +++ b/drivers/crypto/aspeed/aspeed-hace-hash.c @@ -4,6 +4,17 @@ */ #include "aspeed-hace.h" +#include <crypto/engine.h> +#include <crypto/hmac.h> +#include <crypto/internal/hash.h> +#include <crypto/scatterwalk.h> +#include <crypto/sha1.h> +#include <crypto/sha2.h> +#include <linux/dma-mapping.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/string.h> #ifdef CONFIG_CRYPTO_DEV_ASPEED_DEBUG #define AHASH_DBG(h, fmt, ...) \ @@ -48,28 +59,6 @@ static const __be64 sha512_iv[8] = { cpu_to_be64(SHA512_H6), cpu_to_be64(SHA512_H7) }; -static const __be32 sha512_224_iv[16] = { - cpu_to_be32(0xC8373D8CUL), cpu_to_be32(0xA24D5419UL), - cpu_to_be32(0x6699E173UL), cpu_to_be32(0xD6D4DC89UL), - cpu_to_be32(0xAEB7FA1DUL), cpu_to_be32(0x829CFF32UL), - cpu_to_be32(0x14D59D67UL), cpu_to_be32(0xCF9F2F58UL), - cpu_to_be32(0x692B6D0FUL), cpu_to_be32(0xA84DD47BUL), - cpu_to_be32(0x736FE377UL), cpu_to_be32(0x4289C404UL), - cpu_to_be32(0xA8859D3FUL), cpu_to_be32(0xC8361D6AUL), - cpu_to_be32(0xADE61211UL), cpu_to_be32(0xA192D691UL) -}; - -static const __be32 sha512_256_iv[16] = { - cpu_to_be32(0x94213122UL), cpu_to_be32(0x2CF72BFCUL), - cpu_to_be32(0xA35F559FUL), cpu_to_be32(0xC2644CC8UL), - cpu_to_be32(0x6BB89323UL), cpu_to_be32(0x51B1536FUL), - cpu_to_be32(0x19773896UL), cpu_to_be32(0xBDEA4059UL), - cpu_to_be32(0xE23E2896UL), cpu_to_be32(0xE3FF8EA8UL), - cpu_to_be32(0x251E5EBEUL), cpu_to_be32(0x92398653UL), - cpu_to_be32(0xFC99012BUL), cpu_to_be32(0xAAB8852CUL), - cpu_to_be32(0xDC2DB70EUL), cpu_to_be32(0xA22CC581UL) -}; - /* The purpose of this padding is to ensure that the padded message is a * multiple of 512 bits (SHA1/SHA224/SHA256) or 1024 bits (SHA384/SHA512). * The bit "1" is appended at the end of the message followed by @@ -565,8 +554,8 @@ static int aspeed_ahash_do_request(struct crypto_engine *engine, void *areq) return 0; } -static int aspeed_ahash_prepare_request(struct crypto_engine *engine, - void *areq) +static void aspeed_ahash_prepare_request(struct crypto_engine *engine, + void *areq) { struct ahash_request *req = ahash_request_cast(areq); struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); @@ -581,8 +570,12 @@ static int aspeed_ahash_prepare_request(struct crypto_engine *engine, hash_engine->dma_prepare = aspeed_ahash_dma_prepare_sg; else hash_engine->dma_prepare = aspeed_ahash_dma_prepare; +} - return 0; +static int aspeed_ahash_do_one(struct crypto_engine *engine, void *areq) +{ + aspeed_ahash_prepare_request(engine, areq); + return aspeed_ahash_do_request(engine, areq); } static int aspeed_sham_update(struct ahash_request *req) @@ -750,62 +743,6 @@ static int aspeed_sham_init(struct ahash_request *req) return 0; } -static int aspeed_sha512s_init(struct ahash_request *req) -{ - struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req); - struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); - struct aspeed_sham_ctx *tctx = crypto_ahash_ctx(tfm); - struct aspeed_hace_dev *hace_dev = tctx->hace_dev; - struct aspeed_sha_hmac_ctx *bctx = tctx->base; - - AHASH_DBG(hace_dev, "digest size: %d\n", crypto_ahash_digestsize(tfm)); - - rctx->cmd = HASH_CMD_ACC_MODE; - rctx->flags = 0; - - switch (crypto_ahash_digestsize(tfm)) { - case SHA224_DIGEST_SIZE: - rctx->cmd |= HASH_CMD_SHA512_SER | HASH_CMD_SHA512_224 | - HASH_CMD_SHA_SWAP; - rctx->flags |= SHA_FLAGS_SHA512_224; - rctx->digsize = SHA224_DIGEST_SIZE; - rctx->block_size = SHA512_BLOCK_SIZE; - rctx->sha_iv = sha512_224_iv; - rctx->ivsize = 64; - memcpy(rctx->digest, sha512_224_iv, rctx->ivsize); - break; - case SHA256_DIGEST_SIZE: - rctx->cmd |= HASH_CMD_SHA512_SER | HASH_CMD_SHA512_256 | - HASH_CMD_SHA_SWAP; - rctx->flags |= SHA_FLAGS_SHA512_256; - rctx->digsize = SHA256_DIGEST_SIZE; - rctx->block_size = SHA512_BLOCK_SIZE; - rctx->sha_iv = sha512_256_iv; - rctx->ivsize = 64; - memcpy(rctx->digest, sha512_256_iv, rctx->ivsize); - break; - default: - dev_warn(tctx->hace_dev->dev, "digest size %d not support\n", - crypto_ahash_digestsize(tfm)); - return -EINVAL; - } - - rctx->bufcnt = 0; - rctx->total = 0; - rctx->digcnt[0] = 0; - rctx->digcnt[1] = 0; - - /* HMAC init */ - if (tctx->flags & SHA_FLAGS_HMAC) { - rctx->digcnt[0] = rctx->block_size; - rctx->bufcnt = rctx->block_size; - memcpy(rctx->buffer, bctx->ipad, rctx->block_size); - rctx->flags |= SHA_FLAGS_HMAC; - } - - return 0; -} - static int aspeed_sham_digest(struct ahash_request *req) { return aspeed_sham_init(req) ? : aspeed_sham_finup(req); @@ -854,7 +791,7 @@ static int aspeed_sham_cra_init(struct crypto_tfm *tfm) struct aspeed_sham_ctx *tctx = crypto_tfm_ctx(tfm); struct aspeed_hace_alg *ast_alg; - ast_alg = container_of(alg, struct aspeed_hace_alg, alg.ahash); + ast_alg = container_of(alg, struct aspeed_hace_alg, alg.ahash.base); tctx->hace_dev = ast_alg->hace_dev; tctx->flags = 0; @@ -876,10 +813,6 @@ static int aspeed_sham_cra_init(struct crypto_tfm *tfm) } } - tctx->enginectx.op.do_one_request = aspeed_ahash_do_request; - tctx->enginectx.op.prepare_request = aspeed_ahash_prepare_request; - tctx->enginectx.op.unprepare_request = NULL; - return 0; } @@ -917,7 +850,7 @@ static int aspeed_sham_import(struct ahash_request *req, const void *in) static struct aspeed_hace_alg aspeed_ahash_algs[] = { { - .alg.ahash = { + .alg.ahash.base = { .init = aspeed_sham_init, .update = aspeed_sham_update, .final = aspeed_sham_final, @@ -944,9 +877,12 @@ static struct aspeed_hace_alg aspeed_ahash_algs[] = { } } }, + .alg.ahash.op = { + .do_one_request = aspeed_ahash_do_one, + }, }, { - .alg.ahash = { + .alg.ahash.base = { .init = aspeed_sham_init, .update = aspeed_sham_update, .final = aspeed_sham_final, @@ -973,9 +909,12 @@ static struct aspeed_hace_alg aspeed_ahash_algs[] = { } } }, + .alg.ahash.op = { + .do_one_request = aspeed_ahash_do_one, + }, }, { - .alg.ahash = { + .alg.ahash.base = { .init = aspeed_sham_init, .update = aspeed_sham_update, .final = aspeed_sham_final, @@ -1002,10 +941,13 @@ static struct aspeed_hace_alg aspeed_ahash_algs[] = { } } }, + .alg.ahash.op = { + .do_one_request = aspeed_ahash_do_one, + }, }, { .alg_base = "sha1", - .alg.ahash = { + .alg.ahash.base = { .init = aspeed_sham_init, .update = aspeed_sham_update, .final = aspeed_sham_final, @@ -1034,10 +976,13 @@ static struct aspeed_hace_alg aspeed_ahash_algs[] = { } } }, + .alg.ahash.op = { + .do_one_request = aspeed_ahash_do_one, + }, }, { .alg_base = "sha224", - .alg.ahash = { + .alg.ahash.base = { .init = aspeed_sham_init, .update = aspeed_sham_update, .final = aspeed_sham_final, @@ -1066,10 +1011,13 @@ static struct aspeed_hace_alg aspeed_ahash_algs[] = { } } }, + .alg.ahash.op = { + .do_one_request = aspeed_ahash_do_one, + }, }, { .alg_base = "sha256", - .alg.ahash = { + .alg.ahash.base = { .init = aspeed_sham_init, .update = aspeed_sham_update, .final = aspeed_sham_final, @@ -1098,12 +1046,15 @@ static struct aspeed_hace_alg aspeed_ahash_algs[] = { } } }, + .alg.ahash.op = { + .do_one_request = aspeed_ahash_do_one, + }, }, }; static struct aspeed_hace_alg aspeed_ahash_algs_g6[] = { { - .alg.ahash = { + .alg.ahash.base = { .init = aspeed_sham_init, .update = aspeed_sham_update, .final = aspeed_sham_final, @@ -1130,9 +1081,12 @@ static struct aspeed_hace_alg aspeed_ahash_algs_g6[] = { } } }, + .alg.ahash.op = { + .do_one_request = aspeed_ahash_do_one, + }, }, { - .alg.ahash = { + .alg.ahash.base = { .init = aspeed_sham_init, .update = aspeed_sham_update, .final = aspeed_sham_final, @@ -1159,68 +1113,13 @@ static struct aspeed_hace_alg aspeed_ahash_algs_g6[] = { } } }, - }, - { - .alg.ahash = { - .init = aspeed_sha512s_init, - .update = aspeed_sham_update, - .final = aspeed_sham_final, - .finup = aspeed_sham_finup, - .digest = aspeed_sham_digest, - .export = aspeed_sham_export, - .import = aspeed_sham_import, - .halg = { - .digestsize = SHA224_DIGEST_SIZE, - .statesize = sizeof(struct aspeed_sham_reqctx), - .base = { - .cra_name = "sha512_224", - .cra_driver_name = "aspeed-sha512_224", - .cra_priority = 300, - .cra_flags = CRYPTO_ALG_TYPE_AHASH | - CRYPTO_ALG_ASYNC | - CRYPTO_ALG_KERN_DRIVER_ONLY, - .cra_blocksize = SHA512_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct aspeed_sham_ctx), - .cra_alignmask = 0, - .cra_module = THIS_MODULE, - .cra_init = aspeed_sham_cra_init, - .cra_exit = aspeed_sham_cra_exit, - } - } - }, - }, - { - .alg.ahash = { - .init = aspeed_sha512s_init, - .update = aspeed_sham_update, - .final = aspeed_sham_final, - .finup = aspeed_sham_finup, - .digest = aspeed_sham_digest, - .export = aspeed_sham_export, - .import = aspeed_sham_import, - .halg = { - .digestsize = SHA256_DIGEST_SIZE, - .statesize = sizeof(struct aspeed_sham_reqctx), - .base = { - .cra_name = "sha512_256", - .cra_driver_name = "aspeed-sha512_256", - .cra_priority = 300, - .cra_flags = CRYPTO_ALG_TYPE_AHASH | - CRYPTO_ALG_ASYNC | - CRYPTO_ALG_KERN_DRIVER_ONLY, - .cra_blocksize = SHA512_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct aspeed_sham_ctx), - .cra_alignmask = 0, - .cra_module = THIS_MODULE, - .cra_init = aspeed_sham_cra_init, - .cra_exit = aspeed_sham_cra_exit, - } - } + .alg.ahash.op = { + .do_one_request = aspeed_ahash_do_one, }, }, { .alg_base = "sha384", - .alg.ahash = { + .alg.ahash.base = { .init = aspeed_sham_init, .update = aspeed_sham_update, .final = aspeed_sham_final, @@ -1249,10 +1148,13 @@ static struct aspeed_hace_alg aspeed_ahash_algs_g6[] = { } } }, + .alg.ahash.op = { + .do_one_request = aspeed_ahash_do_one, + }, }, { .alg_base = "sha512", - .alg.ahash = { + .alg.ahash.base = { .init = aspeed_sham_init, .update = aspeed_sham_update, .final = aspeed_sham_final, @@ -1281,69 +1183,8 @@ static struct aspeed_hace_alg aspeed_ahash_algs_g6[] = { } } }, - }, - { - .alg_base = "sha512_224", - .alg.ahash = { - .init = aspeed_sha512s_init, - .update = aspeed_sham_update, - .final = aspeed_sham_final, - .finup = aspeed_sham_finup, - .digest = aspeed_sham_digest, - .setkey = aspeed_sham_setkey, - .export = aspeed_sham_export, - .import = aspeed_sham_import, - .halg = { - .digestsize = SHA224_DIGEST_SIZE, - .statesize = sizeof(struct aspeed_sham_reqctx), - .base = { - .cra_name = "hmac(sha512_224)", - .cra_driver_name = "aspeed-hmac-sha512_224", - .cra_priority = 300, - .cra_flags = CRYPTO_ALG_TYPE_AHASH | - CRYPTO_ALG_ASYNC | - CRYPTO_ALG_KERN_DRIVER_ONLY, - .cra_blocksize = SHA512_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct aspeed_sham_ctx) + - sizeof(struct aspeed_sha_hmac_ctx), - .cra_alignmask = 0, - .cra_module = THIS_MODULE, - .cra_init = aspeed_sham_cra_init, - .cra_exit = aspeed_sham_cra_exit, - } - } - }, - }, - { - .alg_base = "sha512_256", - .alg.ahash = { - .init = aspeed_sha512s_init, - .update = aspeed_sham_update, - .final = aspeed_sham_final, - .finup = aspeed_sham_finup, - .digest = aspeed_sham_digest, - .setkey = aspeed_sham_setkey, - .export = aspeed_sham_export, - .import = aspeed_sham_import, - .halg = { - .digestsize = SHA256_DIGEST_SIZE, - .statesize = sizeof(struct aspeed_sham_reqctx), - .base = { - .cra_name = "hmac(sha512_256)", - .cra_driver_name = "aspeed-hmac-sha512_256", - .cra_priority = 300, - .cra_flags = CRYPTO_ALG_TYPE_AHASH | - CRYPTO_ALG_ASYNC | - CRYPTO_ALG_KERN_DRIVER_ONLY, - .cra_blocksize = SHA512_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct aspeed_sham_ctx) + - sizeof(struct aspeed_sha_hmac_ctx), - .cra_alignmask = 0, - .cra_module = THIS_MODULE, - .cra_init = aspeed_sham_cra_init, - .cra_exit = aspeed_sham_cra_exit, - } - } + .alg.ahash.op = { + .do_one_request = aspeed_ahash_do_one, }, }, }; @@ -1353,13 +1194,13 @@ void aspeed_unregister_hace_hash_algs(struct aspeed_hace_dev *hace_dev) int i; for (i = 0; i < ARRAY_SIZE(aspeed_ahash_algs); i++) - crypto_unregister_ahash(&aspeed_ahash_algs[i].alg.ahash); + crypto_engine_unregister_ahash(&aspeed_ahash_algs[i].alg.ahash); if (hace_dev->version != AST2600_VERSION) return; for (i = 0; i < ARRAY_SIZE(aspeed_ahash_algs_g6); i++) - crypto_unregister_ahash(&aspeed_ahash_algs_g6[i].alg.ahash); + crypto_engine_unregister_ahash(&aspeed_ahash_algs_g6[i].alg.ahash); } void aspeed_register_hace_hash_algs(struct aspeed_hace_dev *hace_dev) @@ -1370,10 +1211,10 @@ void aspeed_register_hace_hash_algs(struct aspeed_hace_dev *hace_dev) for (i = 0; i < ARRAY_SIZE(aspeed_ahash_algs); i++) { aspeed_ahash_algs[i].hace_dev = hace_dev; - rc = crypto_register_ahash(&aspeed_ahash_algs[i].alg.ahash); + rc = crypto_engine_register_ahash(&aspeed_ahash_algs[i].alg.ahash); if (rc) { AHASH_DBG(hace_dev, "Failed to register %s\n", - aspeed_ahash_algs[i].alg.ahash.halg.base.cra_name); + aspeed_ahash_algs[i].alg.ahash.base.halg.base.cra_name); } } @@ -1382,10 +1223,10 @@ void aspeed_register_hace_hash_algs(struct aspeed_hace_dev *hace_dev) for (i = 0; i < ARRAY_SIZE(aspeed_ahash_algs_g6); i++) { aspeed_ahash_algs_g6[i].hace_dev = hace_dev; - rc = crypto_register_ahash(&aspeed_ahash_algs_g6[i].alg.ahash); + rc = crypto_engine_register_ahash(&aspeed_ahash_algs_g6[i].alg.ahash); if (rc) { AHASH_DBG(hace_dev, "Failed to register %s\n", - aspeed_ahash_algs_g6[i].alg.ahash.halg.base.cra_name); + aspeed_ahash_algs_g6[i].alg.ahash.base.halg.base.cra_name); } } } diff --git a/drivers/crypto/aspeed/aspeed-hace.c b/drivers/crypto/aspeed/aspeed-hace.c index d2871e1de9c2..8f7aab82e1d8 100644 --- a/drivers/crypto/aspeed/aspeed-hace.c +++ b/drivers/crypto/aspeed/aspeed-hace.c @@ -3,7 +3,14 @@ * Copyright (c) 2021 Aspeed Technology Inc. */ +#include "aspeed-hace.h" +#include <crypto/engine.h> #include <linux/clk.h> +#include <linux/dma-mapping.h> +#include <linux/err.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/kernel.h> #include <linux/module.h> #include <linux/of_address.h> #include <linux/of_device.h> @@ -11,8 +18,6 @@ #include <linux/of.h> #include <linux/platform_device.h> -#include "aspeed-hace.h" - #ifdef CONFIG_CRYPTO_DEV_ASPEED_DEBUG #define HACE_DBG(d, fmt, ...) \ dev_info((d)->dev, "%s() " fmt, __func__, ##__VA_ARGS__) diff --git a/drivers/crypto/aspeed/aspeed-hace.h b/drivers/crypto/aspeed/aspeed-hace.h index 05d0a15d546d..68f70e01fccb 100644 --- a/drivers/crypto/aspeed/aspeed-hace.h +++ b/drivers/crypto/aspeed/aspeed-hace.h @@ -2,25 +2,14 @@ #ifndef __ASPEED_HACE_H__ #define __ASPEED_HACE_H__ -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/fips.h> -#include <linux/dma-mapping.h> #include <crypto/aes.h> -#include <crypto/des.h> -#include <crypto/scatterwalk.h> -#include <crypto/internal/aead.h> -#include <crypto/internal/akcipher.h> -#include <crypto/internal/des.h> -#include <crypto/internal/hash.h> -#include <crypto/internal/kpp.h> -#include <crypto/internal/skcipher.h> -#include <crypto/algapi.h> #include <crypto/engine.h> -#include <crypto/hmac.h> -#include <crypto/sha1.h> +#include <crypto/hash.h> #include <crypto/sha2.h> +#include <linux/bits.h> +#include <linux/compiler_attributes.h> +#include <linux/interrupt.h> +#include <linux/types.h> /***************************** * * @@ -144,6 +133,7 @@ HACE_CMD_OFB | HACE_CMD_CTR) struct aspeed_hace_dev; +struct scatterlist; typedef int (*aspeed_hace_fn_t)(struct aspeed_hace_dev *); @@ -178,8 +168,6 @@ struct aspeed_sha_hmac_ctx { }; struct aspeed_sham_ctx { - struct crypto_engine_ctx enginectx; - struct aspeed_hace_dev *hace_dev; unsigned long flags; /* hmac flag */ @@ -235,8 +223,6 @@ struct aspeed_engine_crypto { }; struct aspeed_cipher_ctx { - struct crypto_engine_ctx enginectx; - struct aspeed_hace_dev *hace_dev; int key_len; u8 key[AES_MAX_KEYLENGTH]; @@ -275,8 +261,8 @@ struct aspeed_hace_alg { const char *alg_base; union { - struct skcipher_alg skcipher; - struct ahash_alg ahash; + struct skcipher_engine_alg skcipher; + struct ahash_engine_alg ahash; } alg; }; diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c index 143d33fbb316..55b5f577b01c 100644 --- a/drivers/crypto/atmel-aes.c +++ b/drivers/crypto/atmel-aes.c @@ -28,7 +28,7 @@ #include <linux/irq.h> #include <linux/scatterlist.h> #include <linux/dma-mapping.h> -#include <linux/of_device.h> +#include <linux/mod_devicetable.h> #include <linux/delay.h> #include <linux/crypto.h> #include <crypto/scatterwalk.h> @@ -2533,13 +2533,11 @@ static void atmel_aes_get_cap(struct atmel_aes_dev *dd) } } -#if defined(CONFIG_OF) static const struct of_device_id atmel_aes_dt_ids[] = { { .compatible = "atmel,at91sam9g46-aes" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, atmel_aes_dt_ids); -#endif static int atmel_aes_probe(struct platform_device *pdev) { @@ -2566,11 +2564,9 @@ static int atmel_aes_probe(struct platform_device *pdev) crypto_init_queue(&aes_dd->queue, ATMEL_AES_QUEUE_LENGTH); - /* Get the base address */ - aes_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!aes_res) { - dev_err(dev, "no MEM resource info\n"); - err = -ENODEV; + aes_dd->io_base = devm_platform_get_and_ioremap_resource(pdev, 0, &aes_res); + if (IS_ERR(aes_dd->io_base)) { + err = PTR_ERR(aes_dd->io_base); goto err_tasklet_kill; } aes_dd->phys_base = aes_res->start; @@ -2597,13 +2593,6 @@ static int atmel_aes_probe(struct platform_device *pdev) goto err_tasklet_kill; } - aes_dd->io_base = devm_ioremap_resource(&pdev->dev, aes_res); - if (IS_ERR(aes_dd->io_base)) { - dev_err(dev, "can't ioremap\n"); - err = PTR_ERR(aes_dd->io_base); - goto err_tasklet_kill; - } - err = clk_prepare(aes_dd->iclk); if (err) goto err_tasklet_kill; @@ -2687,7 +2676,7 @@ static struct platform_driver atmel_aes_driver = { .remove = atmel_aes_remove, .driver = { .name = "atmel_aes", - .of_match_table = of_match_ptr(atmel_aes_dt_ids), + .of_match_table = atmel_aes_dt_ids, }, }; diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c index 432beabd79e6..590ea984c622 100644 --- a/drivers/crypto/atmel-ecc.c +++ b/drivers/crypto/atmel-ecc.c @@ -14,7 +14,7 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/scatterlist.h> #include <linux/slab.h> #include <linux/workqueue.h> diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c index 6bef634d3c86..3622120add62 100644 --- a/drivers/crypto/atmel-sha.c +++ b/drivers/crypto/atmel-sha.c @@ -28,7 +28,7 @@ #include <linux/irq.h> #include <linux/scatterlist.h> #include <linux/dma-mapping.h> -#include <linux/of_device.h> +#include <linux/mod_devicetable.h> #include <linux/delay.h> #include <linux/crypto.h> #include <crypto/scatterwalk.h> @@ -1770,7 +1770,8 @@ static int atmel_sha_hmac_compute_ipad_hash(struct atmel_sha_dev *dd) size_t bs = ctx->block_size; size_t i, num_words = bs / sizeof(u32); - memcpy(hmac->opad, hmac->ipad, bs); + unsafe_memcpy(hmac->opad, hmac->ipad, bs, + "fortified memcpy causes -Wrestrict warning"); for (i = 0; i < num_words; ++i) { hmac->ipad[i] ^= 0x36363636; hmac->opad[i] ^= 0x5c5c5c5c; @@ -2499,8 +2500,8 @@ static int atmel_sha_dma_init(struct atmel_sha_dev *dd) { dd->dma_lch_in.chan = dma_request_chan(dd->dev, "tx"); if (IS_ERR(dd->dma_lch_in.chan)) { - dev_err(dd->dev, "DMA channel is not available\n"); - return PTR_ERR(dd->dma_lch_in.chan); + return dev_err_probe(dd->dev, PTR_ERR(dd->dma_lch_in.chan), + "DMA channel is not available\n"); } dd->dma_lch_in.dma_conf.dst_addr = dd->phys_base + @@ -2570,14 +2571,12 @@ static void atmel_sha_get_cap(struct atmel_sha_dev *dd) } } -#if defined(CONFIG_OF) static const struct of_device_id atmel_sha_dt_ids[] = { { .compatible = "atmel,at91sam9g46-sha" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, atmel_sha_dt_ids); -#endif static int atmel_sha_probe(struct platform_device *pdev) { @@ -2604,11 +2603,9 @@ static int atmel_sha_probe(struct platform_device *pdev) crypto_init_queue(&sha_dd->queue, ATMEL_SHA_QUEUE_LENGTH); - /* Get the base address */ - sha_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!sha_res) { - dev_err(dev, "no MEM resource info\n"); - err = -ENODEV; + sha_dd->io_base = devm_platform_get_and_ioremap_resource(pdev, 0, &sha_res); + if (IS_ERR(sha_dd->io_base)) { + err = PTR_ERR(sha_dd->io_base); goto err_tasklet_kill; } sha_dd->phys_base = sha_res->start; @@ -2635,13 +2632,6 @@ static int atmel_sha_probe(struct platform_device *pdev) goto err_tasklet_kill; } - sha_dd->io_base = devm_ioremap_resource(&pdev->dev, sha_res); - if (IS_ERR(sha_dd->io_base)) { - dev_err(dev, "can't ioremap\n"); - err = PTR_ERR(sha_dd->io_base); - goto err_tasklet_kill; - } - err = clk_prepare(sha_dd->iclk); if (err) goto err_tasklet_kill; @@ -2716,7 +2706,7 @@ static struct platform_driver atmel_sha_driver = { .remove = atmel_sha_remove, .driver = { .name = "atmel_sha", - .of_match_table = of_match_ptr(atmel_sha_dt_ids), + .of_match_table = atmel_sha_dt_ids, }, }; diff --git a/drivers/crypto/atmel-tdes.c b/drivers/crypto/atmel-tdes.c index c9ded8be9c39..099b32a10dd7 100644 --- a/drivers/crypto/atmel-tdes.c +++ b/drivers/crypto/atmel-tdes.c @@ -28,7 +28,7 @@ #include <linux/irq.h> #include <linux/scatterlist.h> #include <linux/dma-mapping.h> -#include <linux/of_device.h> +#include <linux/mod_devicetable.h> #include <linux/delay.h> #include <linux/crypto.h> #include <crypto/scatterwalk.h> @@ -1139,13 +1139,11 @@ static void atmel_tdes_get_cap(struct atmel_tdes_dev *dd) } } -#if defined(CONFIG_OF) static const struct of_device_id atmel_tdes_dt_ids[] = { { .compatible = "atmel,at91sam9g46-tdes" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, atmel_tdes_dt_ids); -#endif static int atmel_tdes_probe(struct platform_device *pdev) { @@ -1172,11 +1170,9 @@ static int atmel_tdes_probe(struct platform_device *pdev) crypto_init_queue(&tdes_dd->queue, ATMEL_TDES_QUEUE_LENGTH); - /* Get the base address */ - tdes_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!tdes_res) { - dev_err(dev, "no MEM resource info\n"); - err = -ENODEV; + tdes_dd->io_base = devm_platform_get_and_ioremap_resource(pdev, 0, &tdes_res); + if (IS_ERR(tdes_dd->io_base)) { + err = PTR_ERR(tdes_dd->io_base); goto err_tasklet_kill; } tdes_dd->phys_base = tdes_res->start; @@ -1203,12 +1199,6 @@ static int atmel_tdes_probe(struct platform_device *pdev) goto err_tasklet_kill; } - tdes_dd->io_base = devm_ioremap_resource(&pdev->dev, tdes_res); - if (IS_ERR(tdes_dd->io_base)) { - err = PTR_ERR(tdes_dd->io_base); - goto err_tasklet_kill; - } - err = atmel_tdes_hw_version_init(tdes_dd); if (err) goto err_tasklet_kill; @@ -1282,7 +1272,7 @@ static struct platform_driver atmel_tdes_driver = { .remove = atmel_tdes_remove, .driver = { .name = "atmel_tdes", - .of_match_table = of_match_ptr(atmel_tdes_dt_ids), + .of_match_table = atmel_tdes_dt_ids, }, }; diff --git a/drivers/crypto/bcm/cipher.c b/drivers/crypto/bcm/cipher.c index 70b911baab26..689be70d69c1 100644 --- a/drivers/crypto/bcm/cipher.c +++ b/drivers/crypto/bcm/cipher.c @@ -15,8 +15,7 @@ #include <linux/kthread.h> #include <linux/rtnetlink.h> #include <linux/sched.h> -#include <linux/of_address.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/io.h> #include <linux/bitops.h> @@ -2397,7 +2396,8 @@ static int ahash_hmac_setkey(struct crypto_ahash *ahash, const u8 *key, memset(ctx->ipad + ctx->authkeylen, 0, blocksize - ctx->authkeylen); ctx->authkeylen = 0; - memcpy(ctx->opad, ctx->ipad, blocksize); + unsafe_memcpy(ctx->opad, ctx->ipad, blocksize, + "fortified memcpy causes -Wrestrict warning"); for (index = 0; index < blocksize; index++) { ctx->ipad[index] ^= HMAC_IPAD_VALUE; diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index feb86013dbf6..eba2d750c3b0 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -56,12 +56,15 @@ #include "sg_sw_sec4.h" #include "key_gen.h" #include "caamalg_desc.h" -#include <crypto/engine.h> -#include <crypto/xts.h> #include <asm/unaligned.h> +#include <crypto/internal/aead.h> +#include <crypto/internal/engine.h> +#include <crypto/internal/skcipher.h> +#include <crypto/xts.h> #include <linux/dma-mapping.h> #include <linux/device.h> #include <linux/err.h> +#include <linux/module.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/string.h> @@ -95,13 +98,13 @@ struct caam_alg_entry { }; struct caam_aead_alg { - struct aead_alg aead; + struct aead_engine_alg aead; struct caam_alg_entry caam; bool registered; }; struct caam_skcipher_alg { - struct skcipher_alg skcipher; + struct skcipher_engine_alg skcipher; struct caam_alg_entry caam; bool registered; }; @@ -110,7 +113,6 @@ struct caam_skcipher_alg { * per-session context */ struct caam_ctx { - struct crypto_engine_ctx enginectx; u32 sh_desc_enc[DESC_MAX_USED_LEN]; u32 sh_desc_dec[DESC_MAX_USED_LEN]; u8 key[CAAM_MAX_KEY_SIZE]; @@ -188,7 +190,8 @@ static int aead_null_set_sh_desc(struct crypto_aead *aead) static int aead_set_sh_desc(struct crypto_aead *aead) { struct caam_aead_alg *alg = container_of(crypto_aead_alg(aead), - struct caam_aead_alg, aead); + struct caam_aead_alg, + aead.base); unsigned int ivsize = crypto_aead_ivsize(aead); struct caam_ctx *ctx = crypto_aead_ctx_dma(aead); struct device *jrdev = ctx->jrdev; @@ -738,7 +741,7 @@ static int skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, struct caam_ctx *ctx = crypto_skcipher_ctx_dma(skcipher); struct caam_skcipher_alg *alg = container_of(crypto_skcipher_alg(skcipher), typeof(*alg), - skcipher); + skcipher.base); struct device *jrdev = ctx->jrdev; unsigned int ivsize = crypto_skcipher_ivsize(skcipher); u32 *desc; @@ -1195,7 +1198,8 @@ static void init_authenc_job(struct aead_request *req, { struct crypto_aead *aead = crypto_aead_reqtfm(req); struct caam_aead_alg *alg = container_of(crypto_aead_alg(aead), - struct caam_aead_alg, aead); + struct caam_aead_alg, + aead.base); unsigned int ivsize = crypto_aead_ivsize(aead); struct caam_ctx *ctx = crypto_aead_ctx_dma(aead); struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctx->jrdev->parent); @@ -1881,7 +1885,7 @@ static int skcipher_decrypt(struct skcipher_request *req) static struct caam_skcipher_alg driver_algs[] = { { - .skcipher = { + .skcipher.base = { .base = { .cra_name = "cbc(aes)", .cra_driver_name = "cbc-aes-caam", @@ -1894,10 +1898,13 @@ static struct caam_skcipher_alg driver_algs[] = { .max_keysize = AES_MAX_KEY_SIZE, .ivsize = AES_BLOCK_SIZE, }, + .skcipher.op = { + .do_one_request = skcipher_do_one_req, + }, .caam.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, }, { - .skcipher = { + .skcipher.base = { .base = { .cra_name = "cbc(des3_ede)", .cra_driver_name = "cbc-3des-caam", @@ -1910,10 +1917,13 @@ static struct caam_skcipher_alg driver_algs[] = { .max_keysize = DES3_EDE_KEY_SIZE, .ivsize = DES3_EDE_BLOCK_SIZE, }, + .skcipher.op = { + .do_one_request = skcipher_do_one_req, + }, .caam.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, }, { - .skcipher = { + .skcipher.base = { .base = { .cra_name = "cbc(des)", .cra_driver_name = "cbc-des-caam", @@ -1926,10 +1936,13 @@ static struct caam_skcipher_alg driver_algs[] = { .max_keysize = DES_KEY_SIZE, .ivsize = DES_BLOCK_SIZE, }, + .skcipher.op = { + .do_one_request = skcipher_do_one_req, + }, .caam.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, }, { - .skcipher = { + .skcipher.base = { .base = { .cra_name = "ctr(aes)", .cra_driver_name = "ctr-aes-caam", @@ -1943,11 +1956,14 @@ static struct caam_skcipher_alg driver_algs[] = { .ivsize = AES_BLOCK_SIZE, .chunksize = AES_BLOCK_SIZE, }, + .skcipher.op = { + .do_one_request = skcipher_do_one_req, + }, .caam.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128, }, { - .skcipher = { + .skcipher.base = { .base = { .cra_name = "rfc3686(ctr(aes))", .cra_driver_name = "rfc3686-ctr-aes-caam", @@ -1963,6 +1979,9 @@ static struct caam_skcipher_alg driver_algs[] = { .ivsize = CTR_RFC3686_IV_SIZE, .chunksize = AES_BLOCK_SIZE, }, + .skcipher.op = { + .do_one_request = skcipher_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128, @@ -1970,7 +1989,7 @@ static struct caam_skcipher_alg driver_algs[] = { }, }, { - .skcipher = { + .skcipher.base = { .base = { .cra_name = "xts(aes)", .cra_driver_name = "xts-aes-caam", @@ -1984,10 +2003,13 @@ static struct caam_skcipher_alg driver_algs[] = { .max_keysize = 2 * AES_MAX_KEY_SIZE, .ivsize = AES_BLOCK_SIZE, }, + .skcipher.op = { + .do_one_request = skcipher_do_one_req, + }, .caam.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_XTS, }, { - .skcipher = { + .skcipher.base = { .base = { .cra_name = "ecb(des)", .cra_driver_name = "ecb-des-caam", @@ -1999,10 +2021,13 @@ static struct caam_skcipher_alg driver_algs[] = { .min_keysize = DES_KEY_SIZE, .max_keysize = DES_KEY_SIZE, }, + .skcipher.op = { + .do_one_request = skcipher_do_one_req, + }, .caam.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_ECB, }, { - .skcipher = { + .skcipher.base = { .base = { .cra_name = "ecb(aes)", .cra_driver_name = "ecb-aes-caam", @@ -2014,10 +2039,13 @@ static struct caam_skcipher_alg driver_algs[] = { .min_keysize = AES_MIN_KEY_SIZE, .max_keysize = AES_MAX_KEY_SIZE, }, + .skcipher.op = { + .do_one_request = skcipher_do_one_req, + }, .caam.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_ECB, }, { - .skcipher = { + .skcipher.base = { .base = { .cra_name = "ecb(des3_ede)", .cra_driver_name = "ecb-des3-caam", @@ -2029,13 +2057,16 @@ static struct caam_skcipher_alg driver_algs[] = { .min_keysize = DES3_EDE_KEY_SIZE, .max_keysize = DES3_EDE_KEY_SIZE, }, + .skcipher.op = { + .do_one_request = skcipher_do_one_req, + }, .caam.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_ECB, }, }; static struct caam_aead_alg driver_aeads[] = { { - .aead = { + .aead.base = { .base = { .cra_name = "rfc4106(gcm(aes))", .cra_driver_name = "rfc4106-gcm-aes-caam", @@ -2048,13 +2079,16 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = GCM_RFC4106_IV_SIZE, .maxauthsize = AES_BLOCK_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM, .nodkp = true, }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "rfc4543(gcm(aes))", .cra_driver_name = "rfc4543-gcm-aes-caam", @@ -2067,6 +2101,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = GCM_RFC4543_IV_SIZE, .maxauthsize = AES_BLOCK_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM, .nodkp = true, @@ -2074,7 +2111,7 @@ static struct caam_aead_alg driver_aeads[] = { }, /* Galois Counter Mode */ { - .aead = { + .aead.base = { .base = { .cra_name = "gcm(aes)", .cra_driver_name = "gcm-aes-caam", @@ -2087,6 +2124,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = GCM_AES_IV_SIZE, .maxauthsize = AES_BLOCK_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM, .nodkp = true, @@ -2094,7 +2134,7 @@ static struct caam_aead_alg driver_aeads[] = { }, /* single-pass ipsec_esp descriptor */ { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(md5)," "ecb(cipher_null))", @@ -2109,13 +2149,16 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = NULL_IV_SIZE, .maxauthsize = MD5_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP, }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha1)," "ecb(cipher_null))", @@ -2130,13 +2173,16 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = NULL_IV_SIZE, .maxauthsize = SHA1_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP, }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha224)," "ecb(cipher_null))", @@ -2151,13 +2197,16 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = NULL_IV_SIZE, .maxauthsize = SHA224_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class2_alg_type = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC_PRECOMP, }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha256)," "ecb(cipher_null))", @@ -2172,13 +2221,16 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = NULL_IV_SIZE, .maxauthsize = SHA256_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class2_alg_type = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC_PRECOMP, }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha384)," "ecb(cipher_null))", @@ -2193,13 +2245,16 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = NULL_IV_SIZE, .maxauthsize = SHA384_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class2_alg_type = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC_PRECOMP, }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha512)," "ecb(cipher_null))", @@ -2214,13 +2269,16 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = NULL_IV_SIZE, .maxauthsize = SHA512_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class2_alg_type = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC_PRECOMP, }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(md5),cbc(aes))", .cra_driver_name = "authenc-hmac-md5-" @@ -2234,6 +2292,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = AES_BLOCK_SIZE, .maxauthsize = MD5_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_MD5 | @@ -2241,7 +2302,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "echainiv(authenc(hmac(md5)," "cbc(aes)))", @@ -2256,6 +2317,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = AES_BLOCK_SIZE, .maxauthsize = MD5_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_MD5 | @@ -2264,7 +2328,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha1),cbc(aes))", .cra_driver_name = "authenc-hmac-sha1-" @@ -2278,6 +2342,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA1_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA1 | @@ -2285,7 +2352,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "echainiv(authenc(hmac(sha1)," "cbc(aes)))", @@ -2300,6 +2367,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA1_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA1 | @@ -2308,7 +2378,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha224),cbc(aes))", .cra_driver_name = "authenc-hmac-sha224-" @@ -2322,6 +2392,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA224_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA224 | @@ -2329,7 +2402,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "echainiv(authenc(hmac(sha224)," "cbc(aes)))", @@ -2344,6 +2417,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA224_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA224 | @@ -2352,7 +2428,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha256),cbc(aes))", .cra_driver_name = "authenc-hmac-sha256-" @@ -2366,6 +2442,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA256_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA256 | @@ -2373,7 +2452,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "echainiv(authenc(hmac(sha256)," "cbc(aes)))", @@ -2388,6 +2467,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA256_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA256 | @@ -2396,7 +2478,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha384),cbc(aes))", .cra_driver_name = "authenc-hmac-sha384-" @@ -2410,6 +2492,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA384_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA384 | @@ -2417,7 +2502,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "echainiv(authenc(hmac(sha384)," "cbc(aes)))", @@ -2432,6 +2517,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA384_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA384 | @@ -2440,7 +2528,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha512),cbc(aes))", .cra_driver_name = "authenc-hmac-sha512-" @@ -2454,6 +2542,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA512_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA512 | @@ -2461,7 +2552,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "echainiv(authenc(hmac(sha512)," "cbc(aes)))", @@ -2476,6 +2567,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = AES_BLOCK_SIZE, .maxauthsize = SHA512_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA512 | @@ -2484,7 +2578,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(md5),cbc(des3_ede))", .cra_driver_name = "authenc-hmac-md5-" @@ -2498,6 +2592,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES3_EDE_BLOCK_SIZE, .maxauthsize = MD5_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_MD5 | @@ -2505,7 +2602,7 @@ static struct caam_aead_alg driver_aeads[] = { } }, { - .aead = { + .aead.base = { .base = { .cra_name = "echainiv(authenc(hmac(md5)," "cbc(des3_ede)))", @@ -2520,6 +2617,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES3_EDE_BLOCK_SIZE, .maxauthsize = MD5_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_MD5 | @@ -2528,7 +2628,7 @@ static struct caam_aead_alg driver_aeads[] = { } }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha1)," "cbc(des3_ede))", @@ -2543,6 +2643,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES3_EDE_BLOCK_SIZE, .maxauthsize = SHA1_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA1 | @@ -2550,7 +2653,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "echainiv(authenc(hmac(sha1)," "cbc(des3_ede)))", @@ -2566,6 +2669,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES3_EDE_BLOCK_SIZE, .maxauthsize = SHA1_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA1 | @@ -2574,7 +2680,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha224)," "cbc(des3_ede))", @@ -2589,6 +2695,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES3_EDE_BLOCK_SIZE, .maxauthsize = SHA224_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA224 | @@ -2596,7 +2705,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "echainiv(authenc(hmac(sha224)," "cbc(des3_ede)))", @@ -2612,6 +2721,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES3_EDE_BLOCK_SIZE, .maxauthsize = SHA224_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA224 | @@ -2620,7 +2732,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha256)," "cbc(des3_ede))", @@ -2635,6 +2747,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES3_EDE_BLOCK_SIZE, .maxauthsize = SHA256_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA256 | @@ -2642,7 +2757,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "echainiv(authenc(hmac(sha256)," "cbc(des3_ede)))", @@ -2658,6 +2773,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES3_EDE_BLOCK_SIZE, .maxauthsize = SHA256_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA256 | @@ -2666,7 +2784,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha384)," "cbc(des3_ede))", @@ -2681,6 +2799,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES3_EDE_BLOCK_SIZE, .maxauthsize = SHA384_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA384 | @@ -2688,7 +2809,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "echainiv(authenc(hmac(sha384)," "cbc(des3_ede)))", @@ -2704,6 +2825,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES3_EDE_BLOCK_SIZE, .maxauthsize = SHA384_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA384 | @@ -2712,7 +2836,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha512)," "cbc(des3_ede))", @@ -2727,6 +2851,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES3_EDE_BLOCK_SIZE, .maxauthsize = SHA512_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA512 | @@ -2734,7 +2861,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "echainiv(authenc(hmac(sha512)," "cbc(des3_ede)))", @@ -2750,6 +2877,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES3_EDE_BLOCK_SIZE, .maxauthsize = SHA512_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA512 | @@ -2758,7 +2888,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(md5),cbc(des))", .cra_driver_name = "authenc-hmac-md5-" @@ -2772,6 +2902,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES_BLOCK_SIZE, .maxauthsize = MD5_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_MD5 | @@ -2779,7 +2912,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "echainiv(authenc(hmac(md5)," "cbc(des)))", @@ -2794,6 +2927,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES_BLOCK_SIZE, .maxauthsize = MD5_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_MD5 | @@ -2802,7 +2938,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha1),cbc(des))", .cra_driver_name = "authenc-hmac-sha1-" @@ -2816,6 +2952,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES_BLOCK_SIZE, .maxauthsize = SHA1_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA1 | @@ -2823,7 +2962,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "echainiv(authenc(hmac(sha1)," "cbc(des)))", @@ -2838,6 +2977,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES_BLOCK_SIZE, .maxauthsize = SHA1_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA1 | @@ -2846,7 +2988,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha224),cbc(des))", .cra_driver_name = "authenc-hmac-sha224-" @@ -2860,6 +3002,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES_BLOCK_SIZE, .maxauthsize = SHA224_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA224 | @@ -2867,7 +3012,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "echainiv(authenc(hmac(sha224)," "cbc(des)))", @@ -2882,6 +3027,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES_BLOCK_SIZE, .maxauthsize = SHA224_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA224 | @@ -2890,7 +3038,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha256),cbc(des))", .cra_driver_name = "authenc-hmac-sha256-" @@ -2904,6 +3052,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES_BLOCK_SIZE, .maxauthsize = SHA256_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA256 | @@ -2911,7 +3062,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "echainiv(authenc(hmac(sha256)," "cbc(des)))", @@ -2926,6 +3077,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES_BLOCK_SIZE, .maxauthsize = SHA256_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA256 | @@ -2934,7 +3088,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha384),cbc(des))", .cra_driver_name = "authenc-hmac-sha384-" @@ -2948,6 +3102,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES_BLOCK_SIZE, .maxauthsize = SHA384_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA384 | @@ -2955,7 +3112,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "echainiv(authenc(hmac(sha384)," "cbc(des)))", @@ -2970,6 +3127,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES_BLOCK_SIZE, .maxauthsize = SHA384_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA384 | @@ -2978,7 +3138,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha512),cbc(des))", .cra_driver_name = "authenc-hmac-sha512-" @@ -2992,6 +3152,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES_BLOCK_SIZE, .maxauthsize = SHA512_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA512 | @@ -2999,7 +3162,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "echainiv(authenc(hmac(sha512)," "cbc(des)))", @@ -3014,6 +3177,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = DES_BLOCK_SIZE, .maxauthsize = SHA512_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, .class2_alg_type = OP_ALG_ALGSEL_SHA512 | @@ -3022,7 +3188,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(md5)," "rfc3686(ctr(aes)))", @@ -3037,6 +3203,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = MD5_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128, @@ -3046,7 +3215,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "seqiv(authenc(" "hmac(md5),rfc3686(ctr(aes))))", @@ -3061,6 +3230,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = MD5_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128, @@ -3071,7 +3243,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha1)," "rfc3686(ctr(aes)))", @@ -3086,6 +3258,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = SHA1_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128, @@ -3095,7 +3270,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "seqiv(authenc(" "hmac(sha1),rfc3686(ctr(aes))))", @@ -3110,6 +3285,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = SHA1_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128, @@ -3120,7 +3298,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha224)," "rfc3686(ctr(aes)))", @@ -3135,6 +3313,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = SHA224_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128, @@ -3144,7 +3325,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "seqiv(authenc(" "hmac(sha224),rfc3686(ctr(aes))))", @@ -3159,6 +3340,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = SHA224_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128, @@ -3169,7 +3353,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha256)," "rfc3686(ctr(aes)))", @@ -3184,6 +3368,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = SHA256_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128, @@ -3193,7 +3380,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "seqiv(authenc(hmac(sha256)," "rfc3686(ctr(aes))))", @@ -3208,6 +3395,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = SHA256_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128, @@ -3218,7 +3408,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha384)," "rfc3686(ctr(aes)))", @@ -3233,6 +3423,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = SHA384_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128, @@ -3242,7 +3435,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "seqiv(authenc(hmac(sha384)," "rfc3686(ctr(aes))))", @@ -3257,6 +3450,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = SHA384_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128, @@ -3267,7 +3463,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "authenc(hmac(sha512)," "rfc3686(ctr(aes)))", @@ -3282,6 +3478,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = SHA512_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128, @@ -3291,7 +3490,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "seqiv(authenc(hmac(sha512)," "rfc3686(ctr(aes))))", @@ -3306,6 +3505,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = CTR_RFC3686_IV_SIZE, .maxauthsize = SHA512_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CTR_MOD128, @@ -3316,7 +3518,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "rfc7539(chacha20,poly1305)", .cra_driver_name = "rfc7539-chacha20-poly1305-" @@ -3330,6 +3532,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = CHACHAPOLY_IV_SIZE, .maxauthsize = POLY1305_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_CHACHA20 | OP_ALG_AAI_AEAD, @@ -3339,7 +3544,7 @@ static struct caam_aead_alg driver_aeads[] = { }, }, { - .aead = { + .aead.base = { .base = { .cra_name = "rfc7539esp(chacha20,poly1305)", .cra_driver_name = "rfc7539esp-chacha20-" @@ -3353,6 +3558,9 @@ static struct caam_aead_alg driver_aeads[] = { .ivsize = 8, .maxauthsize = POLY1305_DIGEST_SIZE, }, + .aead.op = { + .do_one_request = aead_do_one_req, + }, .caam = { .class1_alg_type = OP_ALG_ALGSEL_CHACHA20 | OP_ALG_AAI_AEAD, @@ -3412,13 +3620,11 @@ static int caam_cra_init(struct crypto_skcipher *tfm) { struct skcipher_alg *alg = crypto_skcipher_alg(tfm); struct caam_skcipher_alg *caam_alg = - container_of(alg, typeof(*caam_alg), skcipher); + container_of(alg, typeof(*caam_alg), skcipher.base); struct caam_ctx *ctx = crypto_skcipher_ctx_dma(tfm); u32 alg_aai = caam_alg->caam.class1_alg_type & OP_ALG_AAI_MASK; int ret = 0; - ctx->enginectx.op.do_one_request = skcipher_do_one_req; - if (alg_aai == OP_ALG_AAI_XTS) { const char *tfm_name = crypto_tfm_alg_name(&tfm->base); struct crypto_skcipher *fallback; @@ -3449,13 +3655,11 @@ static int caam_aead_init(struct crypto_aead *tfm) { struct aead_alg *alg = crypto_aead_alg(tfm); struct caam_aead_alg *caam_alg = - container_of(alg, struct caam_aead_alg, aead); + container_of(alg, struct caam_aead_alg, aead.base); struct caam_ctx *ctx = crypto_aead_ctx_dma(tfm); crypto_aead_set_reqsize(tfm, sizeof(struct caam_aead_req_ctx)); - ctx->enginectx.op.do_one_request = aead_do_one_req; - return caam_init_common(ctx, &caam_alg->caam, !caam_alg->caam.nodkp); } @@ -3490,20 +3694,20 @@ void caam_algapi_exit(void) struct caam_aead_alg *t_alg = driver_aeads + i; if (t_alg->registered) - crypto_unregister_aead(&t_alg->aead); + crypto_engine_unregister_aead(&t_alg->aead); } for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { struct caam_skcipher_alg *t_alg = driver_algs + i; if (t_alg->registered) - crypto_unregister_skcipher(&t_alg->skcipher); + crypto_engine_unregister_skcipher(&t_alg->skcipher); } } static void caam_skcipher_alg_init(struct caam_skcipher_alg *t_alg) { - struct skcipher_alg *alg = &t_alg->skcipher; + struct skcipher_alg *alg = &t_alg->skcipher.base; alg->base.cra_module = THIS_MODULE; alg->base.cra_priority = CAAM_CRA_PRIORITY; @@ -3517,7 +3721,7 @@ static void caam_skcipher_alg_init(struct caam_skcipher_alg *t_alg) static void caam_aead_alg_init(struct caam_aead_alg *t_alg) { - struct aead_alg *alg = &t_alg->aead; + struct aead_alg *alg = &t_alg->aead.base; alg->base.cra_module = THIS_MODULE; alg->base.cra_priority = CAAM_CRA_PRIORITY; @@ -3607,10 +3811,10 @@ int caam_algapi_init(struct device *ctrldev) caam_skcipher_alg_init(t_alg); - err = crypto_register_skcipher(&t_alg->skcipher); + err = crypto_engine_register_skcipher(&t_alg->skcipher); if (err) { pr_warn("%s alg registration failed\n", - t_alg->skcipher.base.cra_driver_name); + t_alg->skcipher.base.base.cra_driver_name); continue; } @@ -3654,15 +3858,15 @@ int caam_algapi_init(struct device *ctrldev) * if MD or MD size is not supported by device. */ if (is_mdha(c2_alg_sel) && - (!md_inst || t_alg->aead.maxauthsize > md_limit)) + (!md_inst || t_alg->aead.base.maxauthsize > md_limit)) continue; caam_aead_alg_init(t_alg); - err = crypto_register_aead(&t_alg->aead); + err = crypto_engine_register_aead(&t_alg->aead); if (err) { pr_warn("%s alg registration failed\n", - t_alg->aead.base.cra_driver_name); + t_alg->aead.base.base.cra_driver_name); continue; } diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c index 80deb003f0a5..290c8500c247 100644 --- a/drivers/crypto/caam/caamhash.c +++ b/drivers/crypto/caam/caamhash.c @@ -65,9 +65,13 @@ #include "sg_sw_sec4.h" #include "key_gen.h" #include "caamhash_desc.h" -#include <crypto/engine.h> +#include <crypto/internal/engine.h> +#include <crypto/internal/hash.h> #include <linux/dma-mapping.h> +#include <linux/err.h> #include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/string.h> #define CAAM_CRA_PRIORITY 3000 @@ -89,7 +93,6 @@ static struct list_head hash_list; /* ahash per-session context */ struct caam_hash_ctx { - struct crypto_engine_ctx enginectx; u32 sh_desc_update[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned; u32 sh_desc_update_first[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned; u32 sh_desc_fin[DESC_HASH_MAX_USED_LEN] ____cacheline_aligned; @@ -368,10 +371,8 @@ static int hash_digest_key(struct caam_hash_ctx *ctx, u32 *keylen, u8 *key, int ret; desc = kmalloc(CAAM_CMD_SZ * 8 + CAAM_PTR_SZ * 2, GFP_KERNEL); - if (!desc) { - dev_err(jrdev, "unable to allocate key input memory\n"); + if (!desc) return -ENOMEM; - } init_job_desc(desc, 0); @@ -702,19 +703,14 @@ static struct ahash_edesc *ahash_edesc_alloc(struct ahash_request *req, int sg_num, u32 *sh_desc, dma_addr_t sh_desc_dma) { - struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); - struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash); struct caam_hash_state *state = ahash_request_ctx_dma(req); gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? GFP_KERNEL : GFP_ATOMIC; struct ahash_edesc *edesc; - unsigned int sg_size = sg_num * sizeof(struct sec4_sg_entry); - edesc = kzalloc(sizeof(*edesc) + sg_size, flags); - if (!edesc) { - dev_err(ctx->jrdev, "could not allocate extended descriptor\n"); + edesc = kzalloc(struct_size(edesc, sec4_sg, sg_num), flags); + if (!edesc) return NULL; - } state->edesc = edesc; @@ -1757,7 +1753,7 @@ static struct caam_hash_template driver_hash[] = { struct caam_hash_alg { struct list_head entry; int alg_type; - struct ahash_alg ahash_alg; + struct ahash_engine_alg ahash_alg; }; static int caam_hash_cra_init(struct crypto_tfm *tfm) @@ -1769,7 +1765,7 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm) struct ahash_alg *alg = container_of(halg, struct ahash_alg, halg); struct caam_hash_alg *caam_hash = - container_of(alg, struct caam_hash_alg, ahash_alg); + container_of(alg, struct caam_hash_alg, ahash_alg.base); struct caam_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash); /* Sizes for MDHA running digests: MD5, SHA1, 224, 256, 384, 512 */ static const u8 runninglen[] = { HASH_MSG_LEN + MD5_DIGEST_SIZE, @@ -1860,8 +1856,6 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm) sh_desc_digest) - sh_desc_update_offset; - ctx->enginectx.op.do_one_request = ahash_do_one_req; - crypto_ahash_set_reqsize_dma(ahash, sizeof(struct caam_hash_state)); /* @@ -1894,7 +1888,7 @@ void caam_algapi_hash_exit(void) return; list_for_each_entry_safe(t_alg, n, &hash_list, entry) { - crypto_unregister_ahash(&t_alg->ahash_alg); + crypto_engine_unregister_ahash(&t_alg->ahash_alg); list_del(&t_alg->entry); kfree(t_alg); } @@ -1909,13 +1903,11 @@ caam_hash_alloc(struct caam_hash_template *template, struct crypto_alg *alg; t_alg = kzalloc(sizeof(*t_alg), GFP_KERNEL); - if (!t_alg) { - pr_err("failed to allocate t_alg\n"); + if (!t_alg) return ERR_PTR(-ENOMEM); - } - t_alg->ahash_alg = template->template_ahash; - halg = &t_alg->ahash_alg; + t_alg->ahash_alg.base = template->template_ahash; + halg = &t_alg->ahash_alg.base; alg = &halg->halg.base; if (keyed) { @@ -1928,7 +1920,7 @@ caam_hash_alloc(struct caam_hash_template *template, template->name); snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", template->driver_name); - t_alg->ahash_alg.setkey = NULL; + halg->setkey = NULL; } alg->cra_module = THIS_MODULE; alg->cra_init = caam_hash_cra_init; @@ -1940,6 +1932,7 @@ caam_hash_alloc(struct caam_hash_template *template, alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY; t_alg->alg_type = template->alg_type; + t_alg->ahash_alg.op.do_one_request = ahash_do_one_req; return t_alg; } @@ -2001,10 +1994,10 @@ int caam_algapi_hash_init(struct device *ctrldev) continue; } - err = crypto_register_ahash(&t_alg->ahash_alg); + err = crypto_engine_register_ahash(&t_alg->ahash_alg); if (err) { pr_warn("%s alg registration failed: %d\n", - t_alg->ahash_alg.halg.base.cra_driver_name, + t_alg->ahash_alg.base.halg.base.cra_driver_name, err); kfree(t_alg); } else @@ -2021,10 +2014,10 @@ int caam_algapi_hash_init(struct device *ctrldev) continue; } - err = crypto_register_ahash(&t_alg->ahash_alg); + err = crypto_engine_register_ahash(&t_alg->ahash_alg); if (err) { pr_warn("%s alg registration failed: %d\n", - t_alg->ahash_alg.halg.base.cra_driver_name, + t_alg->ahash_alg.base.halg.base.cra_driver_name, err); kfree(t_alg); } else diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c index 72afc249d42f..887a5f2fb927 100644 --- a/drivers/crypto/caam/caampkc.c +++ b/drivers/crypto/caam/caampkc.c @@ -16,8 +16,12 @@ #include "desc_constr.h" #include "sg_sw_sec4.h" #include "caampkc.h" +#include <crypto/internal/engine.h> #include <linux/dma-mapping.h> +#include <linux/err.h> #include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/string.h> #define DESC_RSA_PUB_LEN (2 * CAAM_CMD_SZ + SIZEOF_RSA_PUB_PDB) #define DESC_RSA_PRIV_F1_LEN (2 * CAAM_CMD_SZ + \ @@ -38,7 +42,7 @@ static u8 *zero_buffer; static bool init_done; struct caam_akcipher_alg { - struct akcipher_alg akcipher; + struct akcipher_engine_alg akcipher; bool registered; }; @@ -225,7 +229,9 @@ static int caam_rsa_count_leading_zeros(struct scatterlist *sgl, if (len && *buff) break; - sg_miter_next(&miter); + if (!sg_miter_next(&miter)) + break; + buff = miter.addr; len = miter.length; @@ -1121,8 +1127,6 @@ static int caam_rsa_init_tfm(struct crypto_akcipher *tfm) return -ENOMEM; } - ctx->enginectx.op.do_one_request = akcipher_do_one_req; - return 0; } @@ -1139,7 +1143,7 @@ static void caam_rsa_exit_tfm(struct crypto_akcipher *tfm) } static struct caam_akcipher_alg caam_rsa = { - .akcipher = { + .akcipher.base = { .encrypt = caam_rsa_enc, .decrypt = caam_rsa_dec, .set_pub_key = caam_rsa_set_pub_key, @@ -1155,7 +1159,10 @@ static struct caam_akcipher_alg caam_rsa = { .cra_ctxsize = sizeof(struct caam_rsa_ctx) + CRYPTO_DMA_PADDING, }, - } + }, + .akcipher.op = { + .do_one_request = akcipher_do_one_req, + }, }; /* Public Key Cryptography module initialization handler */ @@ -1193,12 +1200,12 @@ int caam_pkc_init(struct device *ctrldev) if (!zero_buffer) return -ENOMEM; - err = crypto_register_akcipher(&caam_rsa.akcipher); + err = crypto_engine_register_akcipher(&caam_rsa.akcipher); if (err) { kfree(zero_buffer); dev_warn(ctrldev, "%s alg registration failed\n", - caam_rsa.akcipher.base.cra_driver_name); + caam_rsa.akcipher.base.base.cra_driver_name); } else { init_done = true; caam_rsa.registered = true; @@ -1214,7 +1221,7 @@ void caam_pkc_exit(void) return; if (caam_rsa.registered) - crypto_unregister_akcipher(&caam_rsa.akcipher); + crypto_engine_unregister_akcipher(&caam_rsa.akcipher); kfree(zero_buffer); } diff --git a/drivers/crypto/caam/caampkc.h b/drivers/crypto/caam/caampkc.h index cc889a525e2f..96d03704c9be 100644 --- a/drivers/crypto/caam/caampkc.h +++ b/drivers/crypto/caam/caampkc.h @@ -12,7 +12,6 @@ #define _PKC_DESC_H_ #include "compat.h" #include "pdb.h" -#include <crypto/engine.h> /** * caam_priv_key_form - CAAM RSA private key representation @@ -88,13 +87,11 @@ struct caam_rsa_key { /** * caam_rsa_ctx - per session context. - * @enginectx : crypto engine context * @key : RSA key in DMA zone * @dev : device structure * @padding_dma : dma address of padding, for adding it to the input */ struct caam_rsa_ctx { - struct crypto_engine_ctx enginectx; struct caam_rsa_key key; struct device *dev; dma_addr_t padding_dma; diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c index 68e73775392d..bdf367f3f679 100644 --- a/drivers/crypto/caam/ctrl.c +++ b/drivers/crypto/caam/ctrl.c @@ -9,6 +9,7 @@ #include <linux/device.h> #include <linux/of_address.h> #include <linux/of_irq.h> +#include <linux/platform_device.h> #include <linux/sys_soc.h> #include <linux/fsl/mc.h> @@ -740,6 +741,109 @@ static int caam_ctrl_rng_init(struct device *dev) return 0; } +/* Indicate if the internal state of the CAAM is lost during PM */ +static int caam_off_during_pm(void) +{ + bool not_off_during_pm = of_machine_is_compatible("fsl,imx6q") || + of_machine_is_compatible("fsl,imx6qp") || + of_machine_is_compatible("fsl,imx6dl"); + + return not_off_during_pm ? 0 : 1; +} + +static void caam_state_save(struct device *dev) +{ + struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev); + struct caam_ctl_state *state = &ctrlpriv->state; + struct caam_ctrl __iomem *ctrl = ctrlpriv->ctrl; + u32 deco_inst, jr_inst; + int i; + + state->mcr = rd_reg32(&ctrl->mcr); + state->scfgr = rd_reg32(&ctrl->scfgr); + + deco_inst = (rd_reg32(&ctrl->perfmon.cha_num_ms) & + CHA_ID_MS_DECO_MASK) >> CHA_ID_MS_DECO_SHIFT; + for (i = 0; i < deco_inst; i++) { + state->deco_mid[i].liodn_ms = + rd_reg32(&ctrl->deco_mid[i].liodn_ms); + state->deco_mid[i].liodn_ls = + rd_reg32(&ctrl->deco_mid[i].liodn_ls); + } + + jr_inst = (rd_reg32(&ctrl->perfmon.cha_num_ms) & + CHA_ID_MS_JR_MASK) >> CHA_ID_MS_JR_SHIFT; + for (i = 0; i < jr_inst; i++) { + state->jr_mid[i].liodn_ms = + rd_reg32(&ctrl->jr_mid[i].liodn_ms); + state->jr_mid[i].liodn_ls = + rd_reg32(&ctrl->jr_mid[i].liodn_ls); + } +} + +static void caam_state_restore(const struct device *dev) +{ + const struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev); + const struct caam_ctl_state *state = &ctrlpriv->state; + struct caam_ctrl __iomem *ctrl = ctrlpriv->ctrl; + u32 deco_inst, jr_inst; + int i; + + wr_reg32(&ctrl->mcr, state->mcr); + wr_reg32(&ctrl->scfgr, state->scfgr); + + deco_inst = (rd_reg32(&ctrl->perfmon.cha_num_ms) & + CHA_ID_MS_DECO_MASK) >> CHA_ID_MS_DECO_SHIFT; + for (i = 0; i < deco_inst; i++) { + wr_reg32(&ctrl->deco_mid[i].liodn_ms, + state->deco_mid[i].liodn_ms); + wr_reg32(&ctrl->deco_mid[i].liodn_ls, + state->deco_mid[i].liodn_ls); + } + + jr_inst = (rd_reg32(&ctrl->perfmon.cha_num_ms) & + CHA_ID_MS_JR_MASK) >> CHA_ID_MS_JR_SHIFT; + for (i = 0; i < jr_inst; i++) { + wr_reg32(&ctrl->jr_mid[i].liodn_ms, + state->jr_mid[i].liodn_ms); + wr_reg32(&ctrl->jr_mid[i].liodn_ls, + state->jr_mid[i].liodn_ls); + } + + if (ctrlpriv->virt_en == 1) + clrsetbits_32(&ctrl->jrstart, 0, JRSTART_JR0_START | + JRSTART_JR1_START | JRSTART_JR2_START | + JRSTART_JR3_START); +} + +static int caam_ctrl_suspend(struct device *dev) +{ + const struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev); + + if (ctrlpriv->caam_off_during_pm && !ctrlpriv->optee_en) + caam_state_save(dev); + + return 0; +} + +static int caam_ctrl_resume(struct device *dev) +{ + struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev); + int ret = 0; + + if (ctrlpriv->caam_off_during_pm && !ctrlpriv->optee_en) { + caam_state_restore(dev); + + /* HW and rng will be reset so deinstantiation can be removed */ + devm_remove_action(dev, devm_deinstantiate_rng, dev); + ret = caam_ctrl_rng_init(dev); + } + + return ret; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(caam_ctrl_pm_ops, caam_ctrl_suspend, caam_ctrl_resume); + /* Probe routine for CAAM top (controller) level */ static int caam_probe(struct platform_device *pdev) { @@ -771,6 +875,8 @@ static int caam_probe(struct platform_device *pdev) caam_imx = (bool)imx_soc_match; + ctrlpriv->caam_off_during_pm = caam_imx && caam_off_during_pm(); + if (imx_soc_match) { /* * Until Layerscape and i.MX OP-TEE get in sync, @@ -1033,6 +1139,7 @@ static struct platform_driver caam_driver = { .driver = { .name = "caam", .of_match_table = caam_match, + .pm = pm_ptr(&caam_ctrl_pm_ops), }, .probe = caam_probe, }; diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h index b4f7bf77f487..e51320150872 100644 --- a/drivers/crypto/caam/intern.h +++ b/drivers/crypto/caam/intern.h @@ -4,7 +4,7 @@ * Private/internal definitions between modules * * Copyright 2008-2011 Freescale Semiconductor, Inc. - * Copyright 2019 NXP + * Copyright 2019, 2023 NXP */ #ifndef INTERN_H @@ -47,6 +47,16 @@ struct caam_jrentry_info { u32 desc_size; /* Stored size for postprocessing, header derived */ }; +struct caam_jr_state { + dma_addr_t inpbusaddr; + dma_addr_t outbusaddr; +}; + +struct caam_jr_dequeue_params { + struct device *dev; + int enable_itr; +}; + /* Private sub-storage for a single JobR */ struct caam_drv_private_jr { struct list_head list_node; /* Job Ring device list */ @@ -54,6 +64,7 @@ struct caam_drv_private_jr { int ridx; struct caam_job_ring __iomem *rregs; /* JobR's register space */ struct tasklet_struct irqtask; + struct caam_jr_dequeue_params tasklet_params; int irq; /* One per queue */ bool hwrng; @@ -71,6 +82,15 @@ struct caam_drv_private_jr { int tail; /* entinfo (s/w ring) tail index */ void *outring; /* Base of output ring, DMA-safe */ struct crypto_engine *engine; + + struct caam_jr_state state; /* State of the JR during PM */ +}; + +struct caam_ctl_state { + struct masterid deco_mid[16]; + struct masterid jr_mid[4]; + u32 mcr; + u32 scfgr; }; /* @@ -116,6 +136,9 @@ struct caam_drv_private { struct dentry *ctl; /* controller dir */ struct debugfs_blob_wrapper ctl_kek_wrap, ctl_tkek_wrap, ctl_tdsk_wrap; #endif + + int caam_off_during_pm; /* If the CAAM is reset after suspend */ + struct caam_ctl_state state; /* State of the CTL during PM */ }; #ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c index 96dea5304d22..b1f1b393b98e 100644 --- a/drivers/crypto/caam/jr.c +++ b/drivers/crypto/caam/jr.c @@ -9,6 +9,7 @@ #include <linux/of_irq.h> #include <linux/of_address.h> +#include <linux/platform_device.h> #include "compat.h" #include "ctrl.h" @@ -117,6 +118,23 @@ static int caam_jr_flush(struct device *dev) return caam_jr_stop_processing(dev, JRCR_RESET); } +/* The resume can be used after a park or a flush if CAAM has not been reset */ +static int caam_jr_restart_processing(struct device *dev) +{ + struct caam_drv_private_jr *jrp = dev_get_drvdata(dev); + u32 halt_status = rd_reg32(&jrp->rregs->jrintstatus) & + JRINT_ERR_HALT_MASK; + + /* Check that the flush/park is completed */ + if (halt_status != JRINT_ERR_HALT_COMPLETE) + return -1; + + /* Resume processing of jobs */ + clrsetbits_32(&jrp->rregs->jrintstatus, 0, JRINT_ERR_HALT_COMPLETE); + + return 0; +} + static int caam_reset_hw_jr(struct device *dev) { struct caam_drv_private_jr *jrp = dev_get_drvdata(dev); @@ -215,7 +233,7 @@ static irqreturn_t caam_jr_interrupt(int irq, void *st_dev) * tasklet if jobs done. */ irqstate = rd_reg32(&jrp->rregs->jrintstatus); - if (!irqstate) + if (!(irqstate & JRINT_JR_INT)) return IRQ_NONE; /* @@ -245,7 +263,8 @@ static irqreturn_t caam_jr_interrupt(int irq, void *st_dev) static void caam_jr_dequeue(unsigned long devarg) { int hw_idx, sw_idx, i, head, tail; - struct device *dev = (struct device *)devarg; + struct caam_jr_dequeue_params *params = (void *)devarg; + struct device *dev = params->dev; struct caam_drv_private_jr *jrp = dev_get_drvdata(dev); void (*usercall)(struct device *dev, u32 *desc, u32 status, void *arg); u32 *userdesc, userstatus; @@ -319,8 +338,9 @@ static void caam_jr_dequeue(unsigned long devarg) outring_used--; } - /* reenable / unmask IRQs */ - clrsetbits_32(&jrp->rregs->rconfig_lo, JRCFG_IMSK, 0); + if (params->enable_itr) + /* reenable / unmask IRQs */ + clrsetbits_32(&jrp->rregs->rconfig_lo, JRCFG_IMSK, 0); } /** @@ -445,8 +465,16 @@ int caam_jr_enqueue(struct device *dev, u32 *desc, * Guarantee that the descriptor's DMA address has been written to * the next slot in the ring before the write index is updated, since * other cores may update this index independently. + * + * Under heavy DDR load, smp_wmb() or dma_wmb() fail to make the input + * ring be updated before the CAAM starts reading it. So, CAAM will + * process, again, an old descriptor address and will put it in the + * output ring. This will make caam_jr_dequeue() to fail, since this + * old descriptor is not in the software ring. + * To fix this, use wmb() which works on the full system instead of + * inner/outer shareable domains. */ - smp_wmb(); + wmb(); jrp->head = (head + 1) & (JOBR_DEPTH - 1); @@ -470,6 +498,29 @@ int caam_jr_enqueue(struct device *dev, u32 *desc, } EXPORT_SYMBOL(caam_jr_enqueue); +static void caam_jr_init_hw(struct device *dev, dma_addr_t inpbusaddr, + dma_addr_t outbusaddr) +{ + struct caam_drv_private_jr *jrp = dev_get_drvdata(dev); + + wr_reg64(&jrp->rregs->inpring_base, inpbusaddr); + wr_reg64(&jrp->rregs->outring_base, outbusaddr); + wr_reg32(&jrp->rregs->inpring_size, JOBR_DEPTH); + wr_reg32(&jrp->rregs->outring_size, JOBR_DEPTH); + + /* Select interrupt coalescing parameters */ + clrsetbits_32(&jrp->rregs->rconfig_lo, 0, JOBR_INTC | + (JOBR_INTC_COUNT_THLD << JRCFG_ICDCT_SHIFT) | + (JOBR_INTC_TIME_THLD << JRCFG_ICTT_SHIFT)); +} + +static void caam_jr_reset_index(struct caam_drv_private_jr *jrp) +{ + jrp->out_ring_read_index = 0; + jrp->head = 0; + jrp->tail = 0; +} + /* * Init JobR independent of platform property detection */ @@ -506,25 +557,16 @@ static int caam_jr_init(struct device *dev) jrp->entinfo[i].desc_addr_dma = !0; /* Setup rings */ - jrp->out_ring_read_index = 0; - jrp->head = 0; - jrp->tail = 0; - - wr_reg64(&jrp->rregs->inpring_base, inpbusaddr); - wr_reg64(&jrp->rregs->outring_base, outbusaddr); - wr_reg32(&jrp->rregs->inpring_size, JOBR_DEPTH); - wr_reg32(&jrp->rregs->outring_size, JOBR_DEPTH); - + caam_jr_reset_index(jrp); jrp->inpring_avail = JOBR_DEPTH; + caam_jr_init_hw(dev, inpbusaddr, outbusaddr); spin_lock_init(&jrp->inplock); - /* Select interrupt coalescing parameters */ - clrsetbits_32(&jrp->rregs->rconfig_lo, 0, JOBR_INTC | - (JOBR_INTC_COUNT_THLD << JRCFG_ICDCT_SHIFT) | - (JOBR_INTC_TIME_THLD << JRCFG_ICTT_SHIFT)); - - tasklet_init(&jrp->irqtask, caam_jr_dequeue, (unsigned long)dev); + jrp->tasklet_params.dev = dev; + jrp->tasklet_params.enable_itr = 1; + tasklet_init(&jrp->irqtask, caam_jr_dequeue, + (unsigned long)&jrp->tasklet_params); /* Connect job ring interrupt handler. */ error = devm_request_irq(dev, jrp->irq, caam_jr_interrupt, IRQF_SHARED, @@ -635,11 +677,134 @@ static int caam_jr_probe(struct platform_device *pdev) atomic_set(&jrpriv->tfm_count, 0); + device_init_wakeup(&pdev->dev, 1); + device_set_wakeup_enable(&pdev->dev, false); + register_algs(jrpriv, jrdev->parent); return 0; } +static void caam_jr_get_hw_state(struct device *dev) +{ + struct caam_drv_private_jr *jrp = dev_get_drvdata(dev); + + jrp->state.inpbusaddr = rd_reg64(&jrp->rregs->inpring_base); + jrp->state.outbusaddr = rd_reg64(&jrp->rregs->outring_base); +} + +static int caam_jr_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct caam_drv_private_jr *jrpriv = platform_get_drvdata(pdev); + struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev->parent); + struct caam_jr_dequeue_params suspend_params = { + .dev = dev, + .enable_itr = 0, + }; + + /* Remove the node from Physical JobR list maintained by driver */ + spin_lock(&driver_data.jr_alloc_lock); + list_del(&jrpriv->list_node); + spin_unlock(&driver_data.jr_alloc_lock); + + if (jrpriv->hwrng) + caam_rng_exit(dev->parent); + + if (ctrlpriv->caam_off_during_pm) { + int err; + + tasklet_disable(&jrpriv->irqtask); + + /* mask itr to call flush */ + clrsetbits_32(&jrpriv->rregs->rconfig_lo, 0, JRCFG_IMSK); + + /* Invalid job in process */ + err = caam_jr_flush(dev); + if (err) { + dev_err(dev, "Failed to flush\n"); + return err; + } + + /* Dequeing jobs flushed */ + caam_jr_dequeue((unsigned long)&suspend_params); + + /* Save state */ + caam_jr_get_hw_state(dev); + } else if (device_may_wakeup(&pdev->dev)) { + enable_irq_wake(jrpriv->irq); + } + + return 0; +} + +static int caam_jr_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct caam_drv_private_jr *jrpriv = platform_get_drvdata(pdev); + struct caam_drv_private *ctrlpriv = dev_get_drvdata(dev->parent); + + if (ctrlpriv->caam_off_during_pm) { + u64 inp_addr; + int err; + + /* + * Check if the CAAM has been resetted checking the address of + * the input ring + */ + inp_addr = rd_reg64(&jrpriv->rregs->inpring_base); + if (inp_addr != 0) { + /* JR still has some configuration */ + if (inp_addr == jrpriv->state.inpbusaddr) { + /* JR has not been resetted */ + err = caam_jr_restart_processing(dev); + if (err) { + dev_err(dev, + "Restart processing failed\n"); + return err; + } + + tasklet_enable(&jrpriv->irqtask); + + clrsetbits_32(&jrpriv->rregs->rconfig_lo, + JRCFG_IMSK, 0); + + goto add_jr; + } else if (ctrlpriv->optee_en) { + /* JR has been used by OPTEE, reset it */ + err = caam_reset_hw_jr(dev); + if (err) { + dev_err(dev, "Failed to reset JR\n"); + return err; + } + } else { + /* No explanation, return error */ + return -EIO; + } + } + + caam_jr_reset_index(jrpriv); + caam_jr_init_hw(dev, jrpriv->state.inpbusaddr, + jrpriv->state.outbusaddr); + + tasklet_enable(&jrpriv->irqtask); + } else if (device_may_wakeup(&pdev->dev)) { + disable_irq_wake(jrpriv->irq); + } + +add_jr: + spin_lock(&driver_data.jr_alloc_lock); + list_add_tail(&jrpriv->list_node, &driver_data.jr_list); + spin_unlock(&driver_data.jr_alloc_lock); + + if (jrpriv->hwrng) + jrpriv->hwrng = !caam_rng_init(dev->parent); + + return 0; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(caam_jr_pm_ops, caam_jr_suspend, caam_jr_resume); + static const struct of_device_id caam_jr_match[] = { { .compatible = "fsl,sec-v4.0-job-ring", @@ -655,6 +820,7 @@ static struct platform_driver caam_jr_driver = { .driver = { .name = "caam_jr", .of_match_table = caam_jr_match, + .pm = pm_ptr(&caam_jr_pm_ops), }, .probe = caam_jr_probe, .remove = caam_jr_remove, diff --git a/drivers/crypto/caam/qi.c b/drivers/crypto/caam/qi.c index 2ad2c1035856..46a083849a8e 100644 --- a/drivers/crypto/caam/qi.c +++ b/drivers/crypto/caam/qi.c @@ -13,6 +13,7 @@ #include <linux/kernel.h> #include <linux/kthread.h> #include <linux/netdevice.h> +#include <linux/platform_device.h> #include <linux/slab.h> #include <linux/string.h> #include <soc/fsl/qman.h> diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h index 189e74c21f0c..873df9de9890 100644 --- a/drivers/crypto/caam/regs.h +++ b/drivers/crypto/caam/regs.h @@ -459,12 +459,6 @@ struct masterid { u32 liodn_ls; /* LIODN for non-sequence and seq access */ }; -/* Partition ID for DMA configuration */ -struct partid { - u32 rsvd1; - u32 pidr; /* partition ID, DECO */ -}; - /* RNGB test mode (replicated twice in some configurations) */ /* Padded out to 0x100 */ struct rngtst { @@ -590,8 +584,7 @@ struct caam_ctrl { u32 deco_rsr; /* DECORSR - Deco Request Source */ u32 rsvd11; u32 deco_rq; /* DECORR - DECO Request */ - struct partid deco_mid[5]; /* DECOxLIODNR - 1 per DECO */ - u32 rsvd5[22]; + struct masterid deco_mid[16]; /* DECOxLIODNR - 1 per DECO */ /* DECO Availability/Reset Section 120-3ff */ u32 deco_avail; /* DAR - DECO availability */ diff --git a/drivers/crypto/ccp/Makefile b/drivers/crypto/ccp/Makefile index f6196495e862..aa0ba2d17e1e 100644 --- a/drivers/crypto/ccp/Makefile +++ b/drivers/crypto/ccp/Makefile @@ -11,7 +11,8 @@ ccp-$(CONFIG_PCI) += sp-pci.o ccp-$(CONFIG_CRYPTO_DEV_SP_PSP) += psp-dev.o \ sev-dev.o \ tee-dev.o \ - platform-access.o + platform-access.o \ + dbc.o obj-$(CONFIG_CRYPTO_DEV_CCP_CRYPTO) += ccp-crypto.o ccp-crypto-objs := ccp-crypto-main.o \ diff --git a/drivers/crypto/ccp/dbc.c b/drivers/crypto/ccp/dbc.c new file mode 100644 index 000000000000..839ea14b9a85 --- /dev/null +++ b/drivers/crypto/ccp/dbc.c @@ -0,0 +1,250 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * AMD Secure Processor Dynamic Boost Control interface + * + * Copyright (C) 2023 Advanced Micro Devices, Inc. + * + * Author: Mario Limonciello <mario.limonciello@amd.com> + */ + +#include "dbc.h" + +struct error_map { + u32 psp; + int ret; +}; + +#define DBC_ERROR_ACCESS_DENIED 0x0001 +#define DBC_ERROR_EXCESS_DATA 0x0004 +#define DBC_ERROR_BAD_PARAMETERS 0x0006 +#define DBC_ERROR_BAD_STATE 0x0007 +#define DBC_ERROR_NOT_IMPLEMENTED 0x0009 +#define DBC_ERROR_BUSY 0x000D +#define DBC_ERROR_MESSAGE_FAILURE 0x0307 +#define DBC_ERROR_OVERFLOW 0x300F +#define DBC_ERROR_SIGNATURE_INVALID 0x3072 + +static struct error_map error_codes[] = { + {DBC_ERROR_ACCESS_DENIED, -EACCES}, + {DBC_ERROR_EXCESS_DATA, -E2BIG}, + {DBC_ERROR_BAD_PARAMETERS, -EINVAL}, + {DBC_ERROR_BAD_STATE, -EAGAIN}, + {DBC_ERROR_MESSAGE_FAILURE, -ENOENT}, + {DBC_ERROR_NOT_IMPLEMENTED, -ENOENT}, + {DBC_ERROR_BUSY, -EBUSY}, + {DBC_ERROR_OVERFLOW, -ENFILE}, + {DBC_ERROR_SIGNATURE_INVALID, -EPERM}, + {0x0, 0x0}, +}; + +static int send_dbc_cmd(struct psp_dbc_device *dbc_dev, + enum psp_platform_access_msg msg) +{ + int ret; + + dbc_dev->mbox->req.header.status = 0; + ret = psp_send_platform_access_msg(msg, (struct psp_request *)dbc_dev->mbox); + if (ret == -EIO) { + int i; + + dev_dbg(dbc_dev->dev, + "msg 0x%x failed with PSP error: 0x%x\n", + msg, dbc_dev->mbox->req.header.status); + + for (i = 0; error_codes[i].psp; i++) { + if (dbc_dev->mbox->req.header.status == error_codes[i].psp) + return error_codes[i].ret; + } + } + + return ret; +} + +static int send_dbc_nonce(struct psp_dbc_device *dbc_dev) +{ + int ret; + + dbc_dev->mbox->req.header.payload_size = sizeof(dbc_dev->mbox->dbc_nonce); + ret = send_dbc_cmd(dbc_dev, PSP_DYNAMIC_BOOST_GET_NONCE); + if (ret == -EAGAIN) { + dev_dbg(dbc_dev->dev, "retrying get nonce\n"); + ret = send_dbc_cmd(dbc_dev, PSP_DYNAMIC_BOOST_GET_NONCE); + } + + return ret; +} + +static int send_dbc_parameter(struct psp_dbc_device *dbc_dev) +{ + dbc_dev->mbox->req.header.payload_size = sizeof(dbc_dev->mbox->dbc_param); + + switch (dbc_dev->mbox->dbc_param.user.msg_index) { + case PARAM_SET_FMAX_CAP: + case PARAM_SET_PWR_CAP: + case PARAM_SET_GFX_MODE: + return send_dbc_cmd(dbc_dev, PSP_DYNAMIC_BOOST_SET_PARAMETER); + case PARAM_GET_FMAX_CAP: + case PARAM_GET_PWR_CAP: + case PARAM_GET_CURR_TEMP: + case PARAM_GET_FMAX_MAX: + case PARAM_GET_FMAX_MIN: + case PARAM_GET_SOC_PWR_MAX: + case PARAM_GET_SOC_PWR_MIN: + case PARAM_GET_SOC_PWR_CUR: + case PARAM_GET_GFX_MODE: + return send_dbc_cmd(dbc_dev, PSP_DYNAMIC_BOOST_GET_PARAMETER); + } + + return -EINVAL; +} + +void dbc_dev_destroy(struct psp_device *psp) +{ + struct psp_dbc_device *dbc_dev = psp->dbc_data; + + if (!dbc_dev) + return; + + misc_deregister(&dbc_dev->char_dev); + mutex_destroy(&dbc_dev->ioctl_mutex); + psp->dbc_data = NULL; +} + +static long dbc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct psp_device *psp_master = psp_get_master_device(); + void __user *argp = (void __user *)arg; + struct psp_dbc_device *dbc_dev; + int ret; + + if (!psp_master || !psp_master->dbc_data) + return -ENODEV; + dbc_dev = psp_master->dbc_data; + + mutex_lock(&dbc_dev->ioctl_mutex); + + switch (cmd) { + case DBCIOCNONCE: + if (copy_from_user(&dbc_dev->mbox->dbc_nonce.user, argp, + sizeof(struct dbc_user_nonce))) { + ret = -EFAULT; + goto unlock; + } + + ret = send_dbc_nonce(dbc_dev); + if (ret) + goto unlock; + + if (copy_to_user(argp, &dbc_dev->mbox->dbc_nonce.user, + sizeof(struct dbc_user_nonce))) { + ret = -EFAULT; + goto unlock; + } + break; + case DBCIOCUID: + dbc_dev->mbox->req.header.payload_size = sizeof(dbc_dev->mbox->dbc_set_uid); + if (copy_from_user(&dbc_dev->mbox->dbc_set_uid.user, argp, + sizeof(struct dbc_user_setuid))) { + ret = -EFAULT; + goto unlock; + } + + ret = send_dbc_cmd(dbc_dev, PSP_DYNAMIC_BOOST_SET_UID); + if (ret) + goto unlock; + + if (copy_to_user(argp, &dbc_dev->mbox->dbc_set_uid.user, + sizeof(struct dbc_user_setuid))) { + ret = -EFAULT; + goto unlock; + } + break; + case DBCIOCPARAM: + if (copy_from_user(&dbc_dev->mbox->dbc_param.user, argp, + sizeof(struct dbc_user_param))) { + ret = -EFAULT; + goto unlock; + } + + ret = send_dbc_parameter(dbc_dev); + if (ret) + goto unlock; + + if (copy_to_user(argp, &dbc_dev->mbox->dbc_param.user, + sizeof(struct dbc_user_param))) { + ret = -EFAULT; + goto unlock; + } + break; + default: + ret = -EINVAL; + + } +unlock: + mutex_unlock(&dbc_dev->ioctl_mutex); + + return ret; +} + +static const struct file_operations dbc_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = dbc_ioctl, +}; + +int dbc_dev_init(struct psp_device *psp) +{ + struct device *dev = psp->dev; + struct psp_dbc_device *dbc_dev; + int ret; + + if (!PSP_FEATURE(psp, DBC)) + return 0; + + dbc_dev = devm_kzalloc(dev, sizeof(*dbc_dev), GFP_KERNEL); + if (!dbc_dev) + return -ENOMEM; + + BUILD_BUG_ON(sizeof(union dbc_buffer) > PAGE_SIZE); + dbc_dev->mbox = (void *)devm_get_free_pages(dev, GFP_KERNEL, 0); + if (!dbc_dev->mbox) { + ret = -ENOMEM; + goto cleanup_dev; + } + + psp->dbc_data = dbc_dev; + dbc_dev->dev = dev; + + ret = send_dbc_nonce(dbc_dev); + if (ret == -EACCES) { + dev_dbg(dbc_dev->dev, + "dynamic boost control was previously authenticated\n"); + ret = 0; + } + dev_dbg(dbc_dev->dev, "dynamic boost control is %savailable\n", + ret ? "un" : ""); + if (ret) { + ret = 0; + goto cleanup_mbox; + } + + dbc_dev->char_dev.minor = MISC_DYNAMIC_MINOR; + dbc_dev->char_dev.name = "dbc"; + dbc_dev->char_dev.fops = &dbc_fops; + dbc_dev->char_dev.mode = 0600; + ret = misc_register(&dbc_dev->char_dev); + if (ret) + goto cleanup_mbox; + + mutex_init(&dbc_dev->ioctl_mutex); + + return 0; + +cleanup_mbox: + devm_free_pages(dev, (unsigned long)dbc_dev->mbox); + +cleanup_dev: + psp->dbc_data = NULL; + devm_kfree(dev, dbc_dev); + + return ret; +} diff --git a/drivers/crypto/ccp/dbc.h b/drivers/crypto/ccp/dbc.h new file mode 100644 index 000000000000..e963099ca38e --- /dev/null +++ b/drivers/crypto/ccp/dbc.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * AMD Platform Security Processor (PSP) Dynamic Boost Control support + * + * Copyright (C) 2023 Advanced Micro Devices, Inc. + * + * Author: Mario Limonciello <mario.limonciello@amd.com> + */ + +#ifndef __DBC_H__ +#define __DBC_H__ + +#include <uapi/linux/psp-dbc.h> + +#include <linux/device.h> +#include <linux/miscdevice.h> +#include <linux/psp-platform-access.h> + +#include "psp-dev.h" + +struct psp_dbc_device { + struct device *dev; + + union dbc_buffer *mbox; + + struct mutex ioctl_mutex; + + struct miscdevice char_dev; +}; + +struct dbc_nonce { + struct psp_req_buffer_hdr header; + struct dbc_user_nonce user; +} __packed; + +struct dbc_set_uid { + struct psp_req_buffer_hdr header; + struct dbc_user_setuid user; +} __packed; + +struct dbc_param { + struct psp_req_buffer_hdr header; + struct dbc_user_param user; +} __packed; + +union dbc_buffer { + struct psp_request req; + struct dbc_nonce dbc_nonce; + struct dbc_set_uid dbc_set_uid; + struct dbc_param dbc_param; +}; + +void dbc_dev_destroy(struct psp_device *psp); +int dbc_dev_init(struct psp_device *psp); + +#endif /* __DBC_H */ diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/psp-dev.c index e3d6955d3265..d42d7bc62352 100644 --- a/drivers/crypto/ccp/psp-dev.c +++ b/drivers/crypto/ccp/psp-dev.c @@ -15,6 +15,7 @@ #include "sev-dev.h" #include "tee-dev.h" #include "platform-access.h" +#include "dbc.h" struct psp_device *psp_master; @@ -112,6 +113,12 @@ static void psp_init_platform_access(struct psp_device *psp) dev_warn(psp->dev, "platform access init failed: %d\n", ret); return; } + + /* dbc must come after platform access as it tests the feature */ + ret = dbc_dev_init(psp); + if (ret) + dev_warn(psp->dev, "failed to init dynamic boost control: %d\n", + ret); } static int psp_init(struct psp_device *psp) @@ -173,13 +180,14 @@ int psp_dev_init(struct sp_device *sp) goto e_err; } + /* master device must be set for platform access */ + if (psp->sp->set_psp_master_device) + psp->sp->set_psp_master_device(psp->sp); + ret = psp_init(psp); if (ret) goto e_irq; - if (sp->set_psp_master_device) - sp->set_psp_master_device(sp); - /* Enable interrupt */ iowrite32(-1, psp->io_regs + psp->vdata->inten_reg); @@ -188,6 +196,9 @@ int psp_dev_init(struct sp_device *sp) return 0; e_irq: + if (sp->clear_psp_master_device) + sp->clear_psp_master_device(sp); + sp_free_psp_irq(psp->sp, psp); e_err: sp->psp_data = NULL; @@ -213,6 +224,8 @@ void psp_dev_destroy(struct sp_device *sp) tee_dev_destroy(psp); + dbc_dev_destroy(psp); + platform_access_dev_destroy(psp); sp_free_psp_irq(sp, psp); diff --git a/drivers/crypto/ccp/psp-dev.h b/drivers/crypto/ccp/psp-dev.h index 505e4bdeaca8..8a4de69399c5 100644 --- a/drivers/crypto/ccp/psp-dev.h +++ b/drivers/crypto/ccp/psp-dev.h @@ -40,6 +40,7 @@ struct psp_device { void *sev_data; void *tee_data; void *platform_access_data; + void *dbc_data; unsigned int capability; }; diff --git a/drivers/crypto/ccp/sp-dev.h b/drivers/crypto/ccp/sp-dev.h index 1253a0217985..2329ad524b49 100644 --- a/drivers/crypto/ccp/sp-dev.h +++ b/drivers/crypto/ccp/sp-dev.h @@ -28,6 +28,10 @@ #define CACHE_NONE 0x00 #define CACHE_WB_NO_ALLOC 0xb7 +#define PLATFORM_FEATURE_DBC 0x1 + +#define PSP_FEATURE(psp, feat) (psp->vdata && psp->vdata->platform_features & PLATFORM_FEATURE_##feat) + /* Structure to hold CCP device data */ struct ccp_device; struct ccp_vdata { @@ -51,6 +55,7 @@ struct tee_vdata { const unsigned int cmdbuff_addr_hi_reg; const unsigned int ring_wptr_reg; const unsigned int ring_rptr_reg; + const unsigned int info_reg; }; struct platform_access_vdata { @@ -69,6 +74,8 @@ struct psp_vdata { const unsigned int feature_reg; const unsigned int inten_reg; const unsigned int intsts_reg; + const unsigned int bootloader_info_reg; + const unsigned int platform_features; }; /* Structure to hold SP device data */ diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c index b603ad9b8341..b6ab56abeb68 100644 --- a/drivers/crypto/ccp/sp-pci.c +++ b/drivers/crypto/ccp/sp-pci.c @@ -8,6 +8,7 @@ * Author: Gary R Hook <gary.hook@amd.com> */ +#include <linux/bitfield.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/device.h> @@ -24,6 +25,12 @@ #include "ccp-dev.h" #include "psp-dev.h" +/* used for version string AA.BB.CC.DD */ +#define AA GENMASK(31, 24) +#define BB GENMASK(23, 16) +#define CC GENMASK(15, 8) +#define DD GENMASK(7, 0) + #define MSIX_VECTORS 2 struct sp_pci { @@ -32,7 +39,7 @@ struct sp_pci { }; static struct sp_device *sp_dev_master; -#define attribute_show(name, def) \ +#define security_attribute_show(name, def) \ static ssize_t name##_show(struct device *d, struct device_attribute *attr, \ char *buf) \ { \ @@ -42,24 +49,24 @@ static ssize_t name##_show(struct device *d, struct device_attribute *attr, \ return sysfs_emit(buf, "%d\n", (psp->capability & bit) > 0); \ } -attribute_show(fused_part, FUSED_PART) +security_attribute_show(fused_part, FUSED_PART) static DEVICE_ATTR_RO(fused_part); -attribute_show(debug_lock_on, DEBUG_LOCK_ON) +security_attribute_show(debug_lock_on, DEBUG_LOCK_ON) static DEVICE_ATTR_RO(debug_lock_on); -attribute_show(tsme_status, TSME_STATUS) +security_attribute_show(tsme_status, TSME_STATUS) static DEVICE_ATTR_RO(tsme_status); -attribute_show(anti_rollback_status, ANTI_ROLLBACK_STATUS) +security_attribute_show(anti_rollback_status, ANTI_ROLLBACK_STATUS) static DEVICE_ATTR_RO(anti_rollback_status); -attribute_show(rpmc_production_enabled, RPMC_PRODUCTION_ENABLED) +security_attribute_show(rpmc_production_enabled, RPMC_PRODUCTION_ENABLED) static DEVICE_ATTR_RO(rpmc_production_enabled); -attribute_show(rpmc_spirom_available, RPMC_SPIROM_AVAILABLE) +security_attribute_show(rpmc_spirom_available, RPMC_SPIROM_AVAILABLE) static DEVICE_ATTR_RO(rpmc_spirom_available); -attribute_show(hsp_tpm_available, HSP_TPM_AVAILABLE) +security_attribute_show(hsp_tpm_available, HSP_TPM_AVAILABLE) static DEVICE_ATTR_RO(hsp_tpm_available); -attribute_show(rom_armor_enforced, ROM_ARMOR_ENFORCED) +security_attribute_show(rom_armor_enforced, ROM_ARMOR_ENFORCED) static DEVICE_ATTR_RO(rom_armor_enforced); -static struct attribute *psp_attrs[] = { +static struct attribute *psp_security_attrs[] = { &dev_attr_fused_part.attr, &dev_attr_debug_lock_on.attr, &dev_attr_tsme_status.attr, @@ -83,13 +90,70 @@ static umode_t psp_security_is_visible(struct kobject *kobj, struct attribute *a return 0; } -static struct attribute_group psp_attr_group = { - .attrs = psp_attrs, +static struct attribute_group psp_security_attr_group = { + .attrs = psp_security_attrs, .is_visible = psp_security_is_visible, }; +#define version_attribute_show(name, _offset) \ +static ssize_t name##_show(struct device *d, struct device_attribute *attr, \ + char *buf) \ +{ \ + struct sp_device *sp = dev_get_drvdata(d); \ + struct psp_device *psp = sp->psp_data; \ + unsigned int val = ioread32(psp->io_regs + _offset); \ + return sysfs_emit(buf, "%02lx.%02lx.%02lx.%02lx\n", \ + FIELD_GET(AA, val), \ + FIELD_GET(BB, val), \ + FIELD_GET(CC, val), \ + FIELD_GET(DD, val)); \ +} + +version_attribute_show(bootloader_version, psp->vdata->bootloader_info_reg) +static DEVICE_ATTR_RO(bootloader_version); +version_attribute_show(tee_version, psp->vdata->tee->info_reg) +static DEVICE_ATTR_RO(tee_version); + +static struct attribute *psp_firmware_attrs[] = { + &dev_attr_bootloader_version.attr, + &dev_attr_tee_version.attr, + NULL, +}; + +static umode_t psp_firmware_is_visible(struct kobject *kobj, struct attribute *attr, int idx) +{ + struct device *dev = kobj_to_dev(kobj); + struct sp_device *sp = dev_get_drvdata(dev); + struct psp_device *psp = sp->psp_data; + unsigned int val = 0xffffffff; + + if (!psp) + return 0; + + if (attr == &dev_attr_bootloader_version.attr && + psp->vdata->bootloader_info_reg) + val = ioread32(psp->io_regs + psp->vdata->bootloader_info_reg); + + if (attr == &dev_attr_tee_version.attr && + psp->capability & PSP_CAPABILITY_TEE && + psp->vdata->tee->info_reg) + val = ioread32(psp->io_regs + psp->vdata->tee->info_reg); + + /* If platform disallows accessing this register it will be all f's */ + if (val != 0xffffffff) + return 0444; + + return 0; +} + +static struct attribute_group psp_firmware_attr_group = { + .attrs = psp_firmware_attrs, + .is_visible = psp_firmware_is_visible, +}; + static const struct attribute_group *psp_groups[] = { - &psp_attr_group, + &psp_security_attr_group, + &psp_firmware_attr_group, NULL, }; @@ -359,6 +423,7 @@ static const struct tee_vdata teev1 = { .cmdbuff_addr_hi_reg = 0x1054c, /* C2PMSG_19 */ .ring_wptr_reg = 0x10550, /* C2PMSG_20 */ .ring_rptr_reg = 0x10554, /* C2PMSG_21 */ + .info_reg = 0x109e8, /* C2PMSG_58 */ }; static const struct tee_vdata teev2 = { @@ -384,6 +449,7 @@ static const struct platform_access_vdata pa_v2 = { static const struct psp_vdata pspv1 = { .sev = &sevv1, + .bootloader_info_reg = 0x105ec, /* C2PMSG_59 */ .feature_reg = 0x105fc, /* C2PMSG_63 */ .inten_reg = 0x10610, /* P2CMSG_INTEN */ .intsts_reg = 0x10614, /* P2CMSG_INTSTS */ @@ -391,6 +457,7 @@ static const struct psp_vdata pspv1 = { static const struct psp_vdata pspv2 = { .sev = &sevv2, + .bootloader_info_reg = 0x109ec, /* C2PMSG_59 */ .feature_reg = 0x109fc, /* C2PMSG_63 */ .inten_reg = 0x10690, /* P2CMSG_INTEN */ .intsts_reg = 0x10694, /* P2CMSG_INTSTS */ @@ -399,14 +466,17 @@ static const struct psp_vdata pspv2 = { static const struct psp_vdata pspv3 = { .tee = &teev1, .platform_access = &pa_v1, + .bootloader_info_reg = 0x109ec, /* C2PMSG_59 */ .feature_reg = 0x109fc, /* C2PMSG_63 */ .inten_reg = 0x10690, /* P2CMSG_INTEN */ .intsts_reg = 0x10694, /* P2CMSG_INTSTS */ + .platform_features = PLATFORM_FEATURE_DBC, }; static const struct psp_vdata pspv4 = { .sev = &sevv2, .tee = &teev1, + .bootloader_info_reg = 0x109ec, /* C2PMSG_59 */ .feature_reg = 0x109fc, /* C2PMSG_63 */ .inten_reg = 0x10690, /* P2CMSG_INTEN */ .intsts_reg = 0x10694, /* P2CMSG_INTSTS */ diff --git a/drivers/crypto/ccree/cc_driver.c b/drivers/crypto/ccree/cc_driver.c index c57f929805d5..0f0694037dd7 100644 --- a/drivers/crypto/ccree/cc_driver.c +++ b/drivers/crypto/ccree/cc_driver.c @@ -14,7 +14,6 @@ #include <linux/of.h> #include <linux/clk.h> #include <linux/of_address.h> -#include <linux/of_device.h> #include <linux/pm_runtime.h> #include "cc_driver.h" diff --git a/drivers/crypto/chelsio/chcr_algo.c b/drivers/crypto/chelsio/chcr_algo.c index 0eade4fa6695..16298ae4a00b 100644 --- a/drivers/crypto/chelsio/chcr_algo.c +++ b/drivers/crypto/chelsio/chcr_algo.c @@ -2216,7 +2216,8 @@ static int chcr_ahash_setkey(struct crypto_ahash *tfm, const u8 *key, memcpy(hmacctx->ipad, key, keylen); } memset(hmacctx->ipad + keylen, 0, bs - keylen); - memcpy(hmacctx->opad, hmacctx->ipad, bs); + unsafe_memcpy(hmacctx->opad, hmacctx->ipad, bs, + "fortified memcpy causes -Wrestrict warning"); for (i = 0; i < bs / sizeof(int); i++) { *((unsigned int *)(&hmacctx->ipad) + i) ^= IPAD_DATA; diff --git a/drivers/crypto/chelsio/chcr_core.h b/drivers/crypto/chelsio/chcr_core.h index f7c8bb95a71b..5e9d568131fe 100644 --- a/drivers/crypto/chelsio/chcr_core.h +++ b/drivers/crypto/chelsio/chcr_core.h @@ -133,7 +133,6 @@ int start_crypto(void); int stop_crypto(void); int chcr_uld_rx_handler(void *handle, const __be64 *rsp, const struct pkt_gl *pgl); -int chcr_uld_tx_handler(struct sk_buff *skb, struct net_device *dev); int chcr_handle_resp(struct crypto_async_request *req, unsigned char *input, int err); #endif /* __CHCR_CORE_H__ */ diff --git a/drivers/crypto/chelsio/chcr_crypto.h b/drivers/crypto/chelsio/chcr_crypto.h index 7f88ddb08631..1d693b8436e6 100644 --- a/drivers/crypto/chelsio/chcr_crypto.h +++ b/drivers/crypto/chelsio/chcr_crypto.h @@ -344,7 +344,6 @@ void chcr_add_cipher_dst_ent(struct skcipher_request *req, struct cpl_rx_phys_dsgl *phys_cpl, struct cipher_wr_param *wrparam, unsigned short qid); -int sg_nents_len_skip(struct scatterlist *sg, u64 len, u64 skip); void chcr_add_hash_src_ent(struct ahash_request *req, struct ulptx_sgl *ulptx, struct hash_wr_param *param); int chcr_hash_dma_map(struct device *dev, struct ahash_request *req); diff --git a/drivers/crypto/exynos-rng.c b/drivers/crypto/exynos-rng.c index cbd8ca6e52ee..5d60a4bcb511 100644 --- a/drivers/crypto/exynos-rng.c +++ b/drivers/crypto/exynos-rng.c @@ -15,7 +15,7 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/mutex.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <crypto/internal/rng.h> @@ -277,7 +277,7 @@ static int exynos_rng_probe(struct platform_device *pdev) if (!rng) return -ENOMEM; - rng->type = (enum exynos_prng_type)of_device_get_match_data(&pdev->dev); + rng->type = (uintptr_t)of_device_get_match_data(&pdev->dev); mutex_init(&rng->lock); diff --git a/drivers/crypto/gemini/sl3516-ce-cipher.c b/drivers/crypto/gemini/sl3516-ce-cipher.c index 14d0d83d388d..49dce9e0a834 100644 --- a/drivers/crypto/gemini/sl3516-ce-cipher.c +++ b/drivers/crypto/gemini/sl3516-ce-cipher.c @@ -8,13 +8,17 @@ * ECB mode. */ -#include <linux/crypto.h> +#include <crypto/engine.h> +#include <crypto/internal/skcipher.h> +#include <crypto/scatterwalk.h> #include <linux/dma-mapping.h> #include <linux/delay.h> +#include <linux/err.h> #include <linux/io.h> +#include <linux/kernel.h> #include <linux/pm_runtime.h> -#include <crypto/scatterwalk.h> -#include <crypto/internal/skcipher.h> +#include <linux/slab.h> +#include <linux/string.h> #include "sl3516-ce.h" /* sl3516_ce_need_fallback - check if a request can be handled by the CE */ @@ -105,7 +109,7 @@ static int sl3516_ce_cipher_fallback(struct skcipher_request *areq) struct sl3516_ce_alg_template *algt; int err; - algt = container_of(alg, struct sl3516_ce_alg_template, alg.skcipher); + algt = container_of(alg, struct sl3516_ce_alg_template, alg.skcipher.base); algt->stat_fb++; skcipher_request_set_tfm(&rctx->fallback_req, op->fallback_tfm); @@ -136,7 +140,7 @@ static int sl3516_ce_cipher(struct skcipher_request *areq) int err = 0; int i; - algt = container_of(alg, struct sl3516_ce_alg_template, alg.skcipher); + algt = container_of(alg, struct sl3516_ce_alg_template, alg.skcipher.base); dev_dbg(ce->dev, "%s %s %u %x IV(%p %u) key=%u\n", __func__, crypto_tfm_alg_name(areq->base.tfm), @@ -258,7 +262,7 @@ theend: return err; } -static int sl3516_ce_handle_cipher_request(struct crypto_engine *engine, void *areq) +int sl3516_ce_handle_cipher_request(struct crypto_engine *engine, void *areq) { int err; struct skcipher_request *breq = container_of(areq, struct skcipher_request, base); @@ -318,7 +322,7 @@ int sl3516_ce_cipher_init(struct crypto_tfm *tfm) memset(op, 0, sizeof(struct sl3516_ce_cipher_tfm_ctx)); - algt = container_of(alg, struct sl3516_ce_alg_template, alg.skcipher); + algt = container_of(alg, struct sl3516_ce_alg_template, alg.skcipher.base); op->ce = algt->ce; op->fallback_tfm = crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); @@ -335,10 +339,6 @@ int sl3516_ce_cipher_init(struct crypto_tfm *tfm) crypto_tfm_alg_driver_name(&sktfm->base), crypto_tfm_alg_driver_name(crypto_skcipher_tfm(op->fallback_tfm))); - op->enginectx.op.do_one_request = sl3516_ce_handle_cipher_request; - op->enginectx.op.prepare_request = NULL; - op->enginectx.op.unprepare_request = NULL; - err = pm_runtime_get_sync(op->ce->dev); if (err < 0) goto error_pm; diff --git a/drivers/crypto/gemini/sl3516-ce-core.c b/drivers/crypto/gemini/sl3516-ce-core.c index b7524b649068..0f43c6e39bb9 100644 --- a/drivers/crypto/gemini/sl3516-ce-core.c +++ b/drivers/crypto/gemini/sl3516-ce-core.c @@ -6,22 +6,24 @@ * * Core file which registers crypto algorithms supported by the CryptoEngine */ + +#include <crypto/engine.h> +#include <crypto/internal/rng.h> +#include <crypto/internal/skcipher.h> #include <linux/clk.h> -#include <linux/crypto.h> #include <linux/debugfs.h> #include <linux/dev_printk.h> #include <linux/dma-mapping.h> +#include <linux/err.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/irq.h> +#include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/reset.h> -#include <crypto/internal/rng.h> -#include <crypto/internal/skcipher.h> #include "sl3516-ce.h" @@ -217,7 +219,7 @@ static struct sl3516_ce_alg_template ce_algs[] = { { .type = CRYPTO_ALG_TYPE_SKCIPHER, .mode = ECB_AES, - .alg.skcipher = { + .alg.skcipher.base = { .base = { .cra_name = "ecb(aes)", .cra_driver_name = "ecb-aes-sl3516", @@ -236,11 +238,13 @@ static struct sl3516_ce_alg_template ce_algs[] = { .setkey = sl3516_ce_aes_setkey, .encrypt = sl3516_ce_skencrypt, .decrypt = sl3516_ce_skdecrypt, - } + }, + .alg.skcipher.op = { + .do_one_request = sl3516_ce_handle_cipher_request, + }, }, }; -#ifdef CONFIG_CRYPTO_DEV_SL3516_DEBUG static int sl3516_ce_debugfs_show(struct seq_file *seq, void *v) { struct sl3516_ce_dev *ce = seq->private; @@ -264,8 +268,8 @@ static int sl3516_ce_debugfs_show(struct seq_file *seq, void *v) switch (ce_algs[i].type) { case CRYPTO_ALG_TYPE_SKCIPHER: seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n", - ce_algs[i].alg.skcipher.base.cra_driver_name, - ce_algs[i].alg.skcipher.base.cra_name, + ce_algs[i].alg.skcipher.base.base.cra_driver_name, + ce_algs[i].alg.skcipher.base.base.cra_name, ce_algs[i].stat_req, ce_algs[i].stat_fb); break; } @@ -274,7 +278,6 @@ static int sl3516_ce_debugfs_show(struct seq_file *seq, void *v) } DEFINE_SHOW_ATTRIBUTE(sl3516_ce_debugfs); -#endif static int sl3516_ce_register_algs(struct sl3516_ce_dev *ce) { @@ -286,11 +289,11 @@ static int sl3516_ce_register_algs(struct sl3516_ce_dev *ce) switch (ce_algs[i].type) { case CRYPTO_ALG_TYPE_SKCIPHER: dev_info(ce->dev, "DEBUG: Register %s\n", - ce_algs[i].alg.skcipher.base.cra_name); - err = crypto_register_skcipher(&ce_algs[i].alg.skcipher); + ce_algs[i].alg.skcipher.base.base.cra_name); + err = crypto_engine_register_skcipher(&ce_algs[i].alg.skcipher); if (err) { dev_err(ce->dev, "Fail to register %s\n", - ce_algs[i].alg.skcipher.base.cra_name); + ce_algs[i].alg.skcipher.base.base.cra_name); ce_algs[i].ce = NULL; return err; } @@ -313,8 +316,8 @@ static void sl3516_ce_unregister_algs(struct sl3516_ce_dev *ce) switch (ce_algs[i].type) { case CRYPTO_ALG_TYPE_SKCIPHER: dev_info(ce->dev, "Unregister %d %s\n", i, - ce_algs[i].alg.skcipher.base.cra_name); - crypto_unregister_skcipher(&ce_algs[i].alg.skcipher); + ce_algs[i].alg.skcipher.base.base.cra_name); + crypto_engine_unregister_skcipher(&ce_algs[i].alg.skcipher); break; } } @@ -473,13 +476,20 @@ static int sl3516_ce_probe(struct platform_device *pdev) pm_runtime_put_sync(ce->dev); + if (IS_ENABLED(CONFIG_CRYPTO_DEV_SL3516_DEBUG)) { + struct dentry *dbgfs_dir __maybe_unused; + struct dentry *dbgfs_stats __maybe_unused; + + /* Ignore error of debugfs */ + dbgfs_dir = debugfs_create_dir("sl3516", NULL); + dbgfs_stats = debugfs_create_file("stats", 0444, + dbgfs_dir, ce, + &sl3516_ce_debugfs_fops); #ifdef CONFIG_CRYPTO_DEV_SL3516_DEBUG - /* Ignore error of debugfs */ - ce->dbgfs_dir = debugfs_create_dir("sl3516", NULL); - ce->dbgfs_stats = debugfs_create_file("stats", 0444, - ce->dbgfs_dir, ce, - &sl3516_ce_debugfs_fops); + ce->dbgfs_dir = dbgfs_dir; + ce->dbgfs_stats = dbgfs_stats; #endif + } return 0; error_pmuse: diff --git a/drivers/crypto/gemini/sl3516-ce.h b/drivers/crypto/gemini/sl3516-ce.h index 4c0ec6c920d1..9e1a7e7f8961 100644 --- a/drivers/crypto/gemini/sl3516-ce.h +++ b/drivers/crypto/gemini/sl3516-ce.h @@ -17,7 +17,6 @@ #include <crypto/engine.h> #include <crypto/scatterwalk.h> #include <crypto/skcipher.h> -#include <linux/crypto.h> #include <linux/debugfs.h> #include <linux/hw_random.h> @@ -292,16 +291,12 @@ struct sl3516_ce_cipher_req_ctx { /* * struct sl3516_ce_cipher_tfm_ctx - context for a skcipher TFM - * @enginectx: crypto_engine used by this TFM * @key: pointer to key data * @keylen: len of the key * @ce: pointer to the private data of driver handling this TFM * @fallback_tfm: pointer to the fallback TFM - * - * enginectx must be the first element */ struct sl3516_ce_cipher_tfm_ctx { - struct crypto_engine_ctx enginectx; u32 *key; u32 keylen; struct sl3516_ce_dev *ce; @@ -324,7 +319,7 @@ struct sl3516_ce_alg_template { u32 mode; struct sl3516_ce_dev *ce; union { - struct skcipher_alg skcipher; + struct skcipher_engine_alg skcipher; } alg; unsigned long stat_req; unsigned long stat_fb; @@ -345,3 +340,4 @@ int sl3516_ce_run_task(struct sl3516_ce_dev *ce, int sl3516_ce_rng_register(struct sl3516_ce_dev *ce); void sl3516_ce_rng_unregister(struct sl3516_ce_dev *ce); +int sl3516_ce_handle_cipher_request(struct crypto_engine *engine, void *areq); diff --git a/drivers/crypto/hisilicon/hpre/hpre_crypto.c b/drivers/crypto/hisilicon/hpre/hpre_crypto.c index 8ede77310dc5..9a1c61be32cc 100644 --- a/drivers/crypto/hisilicon/hpre/hpre_crypto.c +++ b/drivers/crypto/hisilicon/hpre/hpre_crypto.c @@ -1392,9 +1392,9 @@ static int hpre_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, unsigned int len) { struct hpre_ctx *ctx = kpp_tfm_ctx(tfm); + unsigned int sz, sz_shift, curve_sz; struct device *dev = ctx->dev; char key[HPRE_ECC_MAX_KSZ]; - unsigned int sz, sz_shift; struct ecdh params; int ret; @@ -1406,7 +1406,13 @@ static int hpre_ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, /* Use stdrng to generate private key */ if (!params.key || !params.key_size) { params.key = key; - params.key_size = hpre_ecdh_get_curvesz(ctx->curve_id); + curve_sz = hpre_ecdh_get_curvesz(ctx->curve_id); + if (!curve_sz) { + dev_err(dev, "Invalid curve size!\n"); + return -EINVAL; + } + + params.key_size = curve_sz - 1; ret = ecdh_gen_privkey(ctx, ¶ms); if (ret) return ret; diff --git a/drivers/crypto/hisilicon/hpre/hpre_main.c b/drivers/crypto/hisilicon/hpre/hpre_main.c index 5d0adfb54a34..39297ce70f44 100644 --- a/drivers/crypto/hisilicon/hpre/hpre_main.c +++ b/drivers/crypto/hisilicon/hpre/hpre_main.c @@ -209,7 +209,7 @@ static const struct hisi_qm_cap_info hpre_basic_info[] = { {HPRE_QM_RESET_MASK_CAP, 0x3128, 0, GENMASK(31, 0), 0x0, 0xC37, 0x6C37}, {HPRE_QM_OOO_SHUTDOWN_MASK_CAP, 0x3128, 0, GENMASK(31, 0), 0x0, 0x4, 0x6C37}, {HPRE_QM_CE_MASK_CAP, 0x312C, 0, GENMASK(31, 0), 0x0, 0x8, 0x8}, - {HPRE_NFE_MASK_CAP, 0x3130, 0, GENMASK(31, 0), 0x0, 0x3FFFFE, 0xFFFFFE}, + {HPRE_NFE_MASK_CAP, 0x3130, 0, GENMASK(31, 0), 0x0, 0x3FFFFE, 0x1FFFFFE}, {HPRE_RESET_MASK_CAP, 0x3134, 0, GENMASK(31, 0), 0x0, 0x3FFFFE, 0xBFFFFE}, {HPRE_OOO_SHUTDOWN_MASK_CAP, 0x3134, 0, GENMASK(31, 0), 0x0, 0x22, 0xBFFFFE}, {HPRE_CE_MASK_CAP, 0x3138, 0, GENMASK(31, 0), 0x0, 0x1, 0x1}, @@ -276,6 +276,9 @@ static const struct hpre_hw_error hpre_hw_errors[] = { .int_msk = BIT(23), .msg = "sva_fsm_timeout_int_set" }, { + .int_msk = BIT(24), + .msg = "sva_int_set" + }, { /* sentinel */ } }; diff --git a/drivers/crypto/hisilicon/qm.c b/drivers/crypto/hisilicon/qm.c index edc6fd44e7ca..a99fd589445c 100644 --- a/drivers/crypto/hisilicon/qm.c +++ b/drivers/crypto/hisilicon/qm.c @@ -88,6 +88,8 @@ #define QM_DB_PRIORITY_SHIFT_V1 48 #define QM_PAGE_SIZE 0x0034 #define QM_QP_DB_INTERVAL 0x10000 +#define QM_DB_TIMEOUT_CFG 0x100074 +#define QM_DB_TIMEOUT_SET 0x1fffff #define QM_MEM_START_INIT 0x100040 #define QM_MEM_INIT_DONE 0x100044 @@ -954,6 +956,11 @@ static irqreturn_t qm_mb_cmd_irq(int irq, void *data) if (!val) return IRQ_NONE; + if (test_bit(QM_DRIVER_REMOVING, &qm->misc_ctl)) { + dev_warn(&qm->pdev->dev, "Driver is down, message cannot be processed!\n"); + return IRQ_HANDLED; + } + schedule_work(&qm->cmd_process); return IRQ_HANDLED; @@ -997,7 +1004,7 @@ static void qm_reset_function(struct hisi_qm *qm) return; } - ret = hisi_qm_stop(qm, QM_FLR); + ret = hisi_qm_stop(qm, QM_DOWN); if (ret) { dev_err(dev, "failed to stop qm when reset function\n"); goto clear_bit; @@ -2743,6 +2750,9 @@ void hisi_qm_wait_task_finish(struct hisi_qm *qm, struct hisi_qm_list *qm_list) test_bit(QM_RESETTING, &qm->misc_ctl)) msleep(WAIT_PERIOD); + if (test_bit(QM_SUPPORT_MB_COMMAND, &qm->caps)) + flush_work(&qm->cmd_process); + udelay(REMOVE_WAIT_DELAY); } EXPORT_SYMBOL_GPL(hisi_qm_wait_task_finish); @@ -3243,7 +3253,7 @@ int hisi_qm_stop(struct hisi_qm *qm, enum qm_stop_reason r) } if (qm->status.stop_reason == QM_SOFT_RESET || - qm->status.stop_reason == QM_FLR) { + qm->status.stop_reason == QM_DOWN) { hisi_qm_set_hw_reset(qm, QM_RESET_STOP_TX_OFFSET); ret = qm_stop_started_qp(qm); if (ret < 0) { @@ -4539,11 +4549,11 @@ void hisi_qm_reset_prepare(struct pci_dev *pdev) if (qm->fun_type == QM_HW_PF) qm_cmd_uninit(qm); - ret = qm_try_stop_vfs(qm, QM_PF_FLR_PREPARE, QM_FLR); + ret = qm_try_stop_vfs(qm, QM_PF_FLR_PREPARE, QM_DOWN); if (ret) pci_err(pdev, "failed to stop vfs by pf in FLR.\n"); - ret = hisi_qm_stop(qm, QM_FLR); + ret = hisi_qm_stop(qm, QM_DOWN); if (ret) { pci_err(pdev, "Failed to stop QM, ret = %d.\n", ret); hisi_qm_set_hw_reset(qm, QM_RESET_STOP_TX_OFFSET); @@ -4641,9 +4651,11 @@ void hisi_qm_dev_shutdown(struct pci_dev *pdev) struct hisi_qm *qm = pci_get_drvdata(pdev); int ret; - ret = hisi_qm_stop(qm, QM_NORMAL); + ret = hisi_qm_stop(qm, QM_DOWN); if (ret) dev_err(&pdev->dev, "Fail to stop qm in shutdown!\n"); + + hisi_qm_cache_wb(qm); } EXPORT_SYMBOL_GPL(hisi_qm_dev_shutdown); @@ -4807,7 +4819,7 @@ static void qm_handle_cmd_msg(struct hisi_qm *qm, u32 fun_num) cmd = msg & QM_MB_CMD_DATA_MASK; switch (cmd) { case QM_PF_FLR_PREPARE: - qm_pf_reset_vf_process(qm, QM_FLR); + qm_pf_reset_vf_process(qm, QM_DOWN); break; case QM_PF_SRST_PREPARE: qm_pf_reset_vf_process(qm, QM_SOFT_RESET); @@ -5371,6 +5383,8 @@ int hisi_qm_init(struct hisi_qm *qm) goto err_pci_init; if (qm->fun_type == QM_HW_PF) { + /* Set the doorbell timeout to QM_DB_TIMEOUT_CFG ns. */ + writel(QM_DB_TIMEOUT_SET, qm->io_base + QM_DB_TIMEOUT_CFG); qm_disable_clock_gate(qm); ret = qm_dev_mem_reset(qm); if (ret) { @@ -5538,6 +5552,8 @@ static int qm_rebuild_for_resume(struct hisi_qm *qm) qm_cmd_init(qm); hisi_qm_dev_err_init(qm); + /* Set the doorbell timeout to QM_DB_TIMEOUT_CFG ns. */ + writel(QM_DB_TIMEOUT_SET, qm->io_base + QM_DB_TIMEOUT_CFG); qm_disable_clock_gate(qm); ret = qm_dev_mem_reset(qm); if (ret) diff --git a/drivers/crypto/hisilicon/sec/sec_drv.c b/drivers/crypto/hisilicon/sec/sec_drv.c index e75851326c1e..e1e08993de12 100644 --- a/drivers/crypto/hisilicon/sec/sec_drv.c +++ b/drivers/crypto/hisilicon/sec/sec_drv.c @@ -1107,8 +1107,8 @@ static int sec_queue_res_cfg(struct sec_queue *queue) } queue->task_irq = platform_get_irq(to_platform_device(dev), queue->queue_id * 2 + 1); - if (queue->task_irq <= 0) { - ret = -EINVAL; + if (queue->task_irq < 0) { + ret = queue->task_irq; goto err_free_ring_db; } diff --git a/drivers/crypto/img-hash.c b/drivers/crypto/img-hash.c index 359aa2b41016..45063693859c 100644 --- a/drivers/crypto/img-hash.c +++ b/drivers/crypto/img-hash.c @@ -13,7 +13,7 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/mod_devicetable.h> #include <linux/platform_device.h> #include <linux/scatterlist.h> @@ -1105,7 +1105,7 @@ static struct platform_driver img_hash_driver = { .driver = { .name = "img-hash-accelerator", .pm = &img_hash_pm_ops, - .of_match_table = of_match_ptr(img_hash_match), + .of_match_table = img_hash_match, } }; module_platform_driver(img_hash_driver); diff --git a/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c b/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c index ae31be00357a..1e2fd9a754ec 100644 --- a/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c +++ b/drivers/crypto/intel/keembay/keembay-ocs-aes-core.c @@ -5,24 +5,23 @@ * Copyright (C) 2018-2020 Intel Corporation */ +#include <crypto/aes.h> +#include <crypto/engine.h> +#include <crypto/gcm.h> +#include <crypto/internal/aead.h> +#include <crypto/internal/skcipher.h> +#include <crypto/scatterwalk.h> #include <linux/clk.h> #include <linux/completion.h> -#include <linux/crypto.h> #include <linux/dma-mapping.h> +#include <linux/err.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> -#include <linux/types.h> - -#include <crypto/aes.h> -#include <crypto/engine.h> -#include <crypto/gcm.h> -#include <crypto/scatterwalk.h> - -#include <crypto/internal/aead.h> -#include <crypto/internal/skcipher.h> +#include <linux/string.h> #include "ocs-aes.h" @@ -38,7 +37,6 @@ /** * struct ocs_aes_tctx - OCS AES Transform context - * @engine_ctx: Engine context. * @aes_dev: The OCS AES device. * @key: AES/SM4 key. * @key_len: The length (in bytes) of @key. @@ -47,7 +45,6 @@ * @use_fallback: Whether or not fallback cipher should be used. */ struct ocs_aes_tctx { - struct crypto_engine_ctx engine_ctx; struct ocs_aes_dev *aes_dev; u8 key[OCS_AES_KEYSIZE_256]; unsigned int key_len; @@ -1148,15 +1145,6 @@ static int kmb_ocs_sm4_ccm_decrypt(struct aead_request *req) return kmb_ocs_aead_common(req, OCS_SM4, OCS_DECRYPT, OCS_MODE_CCM); } -static inline int ocs_common_init(struct ocs_aes_tctx *tctx) -{ - tctx->engine_ctx.op.prepare_request = NULL; - tctx->engine_ctx.op.do_one_request = kmb_ocs_aes_sk_do_one_request; - tctx->engine_ctx.op.unprepare_request = NULL; - - return 0; -} - static int ocs_aes_init_tfm(struct crypto_skcipher *tfm) { const char *alg_name = crypto_tfm_alg_name(&tfm->base); @@ -1172,16 +1160,14 @@ static int ocs_aes_init_tfm(struct crypto_skcipher *tfm) crypto_skcipher_set_reqsize(tfm, sizeof(struct ocs_aes_rctx)); - return ocs_common_init(tctx); + return 0; } static int ocs_sm4_init_tfm(struct crypto_skcipher *tfm) { - struct ocs_aes_tctx *tctx = crypto_skcipher_ctx(tfm); - crypto_skcipher_set_reqsize(tfm, sizeof(struct ocs_aes_rctx)); - return ocs_common_init(tctx); + return 0; } static inline void clear_key(struct ocs_aes_tctx *tctx) @@ -1206,15 +1192,6 @@ static void ocs_exit_tfm(struct crypto_skcipher *tfm) } } -static inline int ocs_common_aead_init(struct ocs_aes_tctx *tctx) -{ - tctx->engine_ctx.op.prepare_request = NULL; - tctx->engine_ctx.op.do_one_request = kmb_ocs_aes_aead_do_one_request; - tctx->engine_ctx.op.unprepare_request = NULL; - - return 0; -} - static int ocs_aes_aead_cra_init(struct crypto_aead *tfm) { const char *alg_name = crypto_tfm_alg_name(&tfm->base); @@ -1233,7 +1210,7 @@ static int ocs_aes_aead_cra_init(struct crypto_aead *tfm) (sizeof(struct aead_request) + crypto_aead_reqsize(tctx->sw_cipher.aead)))); - return ocs_common_aead_init(tctx); + return 0; } static int kmb_ocs_aead_ccm_setauthsize(struct crypto_aead *tfm, @@ -1261,11 +1238,9 @@ static int kmb_ocs_aead_gcm_setauthsize(struct crypto_aead *tfm, static int ocs_sm4_aead_cra_init(struct crypto_aead *tfm) { - struct ocs_aes_tctx *tctx = crypto_aead_ctx(tfm); - crypto_aead_set_reqsize(tfm, sizeof(struct ocs_aes_rctx)); - return ocs_common_aead_init(tctx); + return 0; } static void ocs_aead_cra_exit(struct crypto_aead *tfm) @@ -1280,182 +1255,190 @@ static void ocs_aead_cra_exit(struct crypto_aead *tfm) } } -static struct skcipher_alg algs[] = { +static struct skcipher_engine_alg algs[] = { #ifdef CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_ECB { - .base.cra_name = "ecb(aes)", - .base.cra_driver_name = "ecb-aes-keembay-ocs", - .base.cra_priority = KMB_OCS_PRIORITY, - .base.cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_KERN_DRIVER_ONLY | - CRYPTO_ALG_NEED_FALLBACK, - .base.cra_blocksize = AES_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct ocs_aes_tctx), - .base.cra_module = THIS_MODULE, - .base.cra_alignmask = 0, - - .min_keysize = OCS_AES_MIN_KEY_SIZE, - .max_keysize = OCS_AES_MAX_KEY_SIZE, - .setkey = kmb_ocs_aes_set_key, - .encrypt = kmb_ocs_aes_ecb_encrypt, - .decrypt = kmb_ocs_aes_ecb_decrypt, - .init = ocs_aes_init_tfm, - .exit = ocs_exit_tfm, + .base.base.cra_name = "ecb(aes)", + .base.base.cra_driver_name = "ecb-aes-keembay-ocs", + .base.base.cra_priority = KMB_OCS_PRIORITY, + .base.base.cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_NEED_FALLBACK, + .base.base.cra_blocksize = AES_BLOCK_SIZE, + .base.base.cra_ctxsize = sizeof(struct ocs_aes_tctx), + .base.base.cra_module = THIS_MODULE, + .base.base.cra_alignmask = 0, + + .base.min_keysize = OCS_AES_MIN_KEY_SIZE, + .base.max_keysize = OCS_AES_MAX_KEY_SIZE, + .base.setkey = kmb_ocs_aes_set_key, + .base.encrypt = kmb_ocs_aes_ecb_encrypt, + .base.decrypt = kmb_ocs_aes_ecb_decrypt, + .base.init = ocs_aes_init_tfm, + .base.exit = ocs_exit_tfm, + .op.do_one_request = kmb_ocs_aes_sk_do_one_request, }, #endif /* CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_ECB */ { - .base.cra_name = "cbc(aes)", - .base.cra_driver_name = "cbc-aes-keembay-ocs", - .base.cra_priority = KMB_OCS_PRIORITY, - .base.cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_KERN_DRIVER_ONLY | - CRYPTO_ALG_NEED_FALLBACK, - .base.cra_blocksize = AES_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct ocs_aes_tctx), - .base.cra_module = THIS_MODULE, - .base.cra_alignmask = 0, - - .min_keysize = OCS_AES_MIN_KEY_SIZE, - .max_keysize = OCS_AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = kmb_ocs_aes_set_key, - .encrypt = kmb_ocs_aes_cbc_encrypt, - .decrypt = kmb_ocs_aes_cbc_decrypt, - .init = ocs_aes_init_tfm, - .exit = ocs_exit_tfm, + .base.base.cra_name = "cbc(aes)", + .base.base.cra_driver_name = "cbc-aes-keembay-ocs", + .base.base.cra_priority = KMB_OCS_PRIORITY, + .base.base.cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_NEED_FALLBACK, + .base.base.cra_blocksize = AES_BLOCK_SIZE, + .base.base.cra_ctxsize = sizeof(struct ocs_aes_tctx), + .base.base.cra_module = THIS_MODULE, + .base.base.cra_alignmask = 0, + + .base.min_keysize = OCS_AES_MIN_KEY_SIZE, + .base.max_keysize = OCS_AES_MAX_KEY_SIZE, + .base.ivsize = AES_BLOCK_SIZE, + .base.setkey = kmb_ocs_aes_set_key, + .base.encrypt = kmb_ocs_aes_cbc_encrypt, + .base.decrypt = kmb_ocs_aes_cbc_decrypt, + .base.init = ocs_aes_init_tfm, + .base.exit = ocs_exit_tfm, + .op.do_one_request = kmb_ocs_aes_sk_do_one_request, }, { - .base.cra_name = "ctr(aes)", - .base.cra_driver_name = "ctr-aes-keembay-ocs", - .base.cra_priority = KMB_OCS_PRIORITY, - .base.cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_KERN_DRIVER_ONLY | - CRYPTO_ALG_NEED_FALLBACK, - .base.cra_blocksize = 1, - .base.cra_ctxsize = sizeof(struct ocs_aes_tctx), - .base.cra_module = THIS_MODULE, - .base.cra_alignmask = 0, - - .min_keysize = OCS_AES_MIN_KEY_SIZE, - .max_keysize = OCS_AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = kmb_ocs_aes_set_key, - .encrypt = kmb_ocs_aes_ctr_encrypt, - .decrypt = kmb_ocs_aes_ctr_decrypt, - .init = ocs_aes_init_tfm, - .exit = ocs_exit_tfm, + .base.base.cra_name = "ctr(aes)", + .base.base.cra_driver_name = "ctr-aes-keembay-ocs", + .base.base.cra_priority = KMB_OCS_PRIORITY, + .base.base.cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_NEED_FALLBACK, + .base.base.cra_blocksize = 1, + .base.base.cra_ctxsize = sizeof(struct ocs_aes_tctx), + .base.base.cra_module = THIS_MODULE, + .base.base.cra_alignmask = 0, + + .base.min_keysize = OCS_AES_MIN_KEY_SIZE, + .base.max_keysize = OCS_AES_MAX_KEY_SIZE, + .base.ivsize = AES_BLOCK_SIZE, + .base.setkey = kmb_ocs_aes_set_key, + .base.encrypt = kmb_ocs_aes_ctr_encrypt, + .base.decrypt = kmb_ocs_aes_ctr_decrypt, + .base.init = ocs_aes_init_tfm, + .base.exit = ocs_exit_tfm, + .op.do_one_request = kmb_ocs_aes_sk_do_one_request, }, #ifdef CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_CTS { - .base.cra_name = "cts(cbc(aes))", - .base.cra_driver_name = "cts-aes-keembay-ocs", - .base.cra_priority = KMB_OCS_PRIORITY, - .base.cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_KERN_DRIVER_ONLY | - CRYPTO_ALG_NEED_FALLBACK, - .base.cra_blocksize = AES_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct ocs_aes_tctx), - .base.cra_module = THIS_MODULE, - .base.cra_alignmask = 0, - - .min_keysize = OCS_AES_MIN_KEY_SIZE, - .max_keysize = OCS_AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = kmb_ocs_aes_set_key, - .encrypt = kmb_ocs_aes_cts_encrypt, - .decrypt = kmb_ocs_aes_cts_decrypt, - .init = ocs_aes_init_tfm, - .exit = ocs_exit_tfm, + .base.base.cra_name = "cts(cbc(aes))", + .base.base.cra_driver_name = "cts-aes-keembay-ocs", + .base.base.cra_priority = KMB_OCS_PRIORITY, + .base.base.cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_NEED_FALLBACK, + .base.base.cra_blocksize = AES_BLOCK_SIZE, + .base.base.cra_ctxsize = sizeof(struct ocs_aes_tctx), + .base.base.cra_module = THIS_MODULE, + .base.base.cra_alignmask = 0, + + .base.min_keysize = OCS_AES_MIN_KEY_SIZE, + .base.max_keysize = OCS_AES_MAX_KEY_SIZE, + .base.ivsize = AES_BLOCK_SIZE, + .base.setkey = kmb_ocs_aes_set_key, + .base.encrypt = kmb_ocs_aes_cts_encrypt, + .base.decrypt = kmb_ocs_aes_cts_decrypt, + .base.init = ocs_aes_init_tfm, + .base.exit = ocs_exit_tfm, + .op.do_one_request = kmb_ocs_aes_sk_do_one_request, }, #endif /* CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_CTS */ #ifdef CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_ECB { - .base.cra_name = "ecb(sm4)", - .base.cra_driver_name = "ecb-sm4-keembay-ocs", - .base.cra_priority = KMB_OCS_PRIORITY, - .base.cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_KERN_DRIVER_ONLY, - .base.cra_blocksize = AES_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct ocs_aes_tctx), - .base.cra_module = THIS_MODULE, - .base.cra_alignmask = 0, - - .min_keysize = OCS_SM4_KEY_SIZE, - .max_keysize = OCS_SM4_KEY_SIZE, - .setkey = kmb_ocs_sm4_set_key, - .encrypt = kmb_ocs_sm4_ecb_encrypt, - .decrypt = kmb_ocs_sm4_ecb_decrypt, - .init = ocs_sm4_init_tfm, - .exit = ocs_exit_tfm, + .base.base.cra_name = "ecb(sm4)", + .base.base.cra_driver_name = "ecb-sm4-keembay-ocs", + .base.base.cra_priority = KMB_OCS_PRIORITY, + .base.base.cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .base.base.cra_blocksize = AES_BLOCK_SIZE, + .base.base.cra_ctxsize = sizeof(struct ocs_aes_tctx), + .base.base.cra_module = THIS_MODULE, + .base.base.cra_alignmask = 0, + + .base.min_keysize = OCS_SM4_KEY_SIZE, + .base.max_keysize = OCS_SM4_KEY_SIZE, + .base.setkey = kmb_ocs_sm4_set_key, + .base.encrypt = kmb_ocs_sm4_ecb_encrypt, + .base.decrypt = kmb_ocs_sm4_ecb_decrypt, + .base.init = ocs_sm4_init_tfm, + .base.exit = ocs_exit_tfm, + .op.do_one_request = kmb_ocs_aes_sk_do_one_request, }, #endif /* CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_ECB */ { - .base.cra_name = "cbc(sm4)", - .base.cra_driver_name = "cbc-sm4-keembay-ocs", - .base.cra_priority = KMB_OCS_PRIORITY, - .base.cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_KERN_DRIVER_ONLY, - .base.cra_blocksize = AES_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct ocs_aes_tctx), - .base.cra_module = THIS_MODULE, - .base.cra_alignmask = 0, - - .min_keysize = OCS_SM4_KEY_SIZE, - .max_keysize = OCS_SM4_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = kmb_ocs_sm4_set_key, - .encrypt = kmb_ocs_sm4_cbc_encrypt, - .decrypt = kmb_ocs_sm4_cbc_decrypt, - .init = ocs_sm4_init_tfm, - .exit = ocs_exit_tfm, + .base.base.cra_name = "cbc(sm4)", + .base.base.cra_driver_name = "cbc-sm4-keembay-ocs", + .base.base.cra_priority = KMB_OCS_PRIORITY, + .base.base.cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .base.base.cra_blocksize = AES_BLOCK_SIZE, + .base.base.cra_ctxsize = sizeof(struct ocs_aes_tctx), + .base.base.cra_module = THIS_MODULE, + .base.base.cra_alignmask = 0, + + .base.min_keysize = OCS_SM4_KEY_SIZE, + .base.max_keysize = OCS_SM4_KEY_SIZE, + .base.ivsize = AES_BLOCK_SIZE, + .base.setkey = kmb_ocs_sm4_set_key, + .base.encrypt = kmb_ocs_sm4_cbc_encrypt, + .base.decrypt = kmb_ocs_sm4_cbc_decrypt, + .base.init = ocs_sm4_init_tfm, + .base.exit = ocs_exit_tfm, + .op.do_one_request = kmb_ocs_aes_sk_do_one_request, }, { - .base.cra_name = "ctr(sm4)", - .base.cra_driver_name = "ctr-sm4-keembay-ocs", - .base.cra_priority = KMB_OCS_PRIORITY, - .base.cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_KERN_DRIVER_ONLY, - .base.cra_blocksize = 1, - .base.cra_ctxsize = sizeof(struct ocs_aes_tctx), - .base.cra_module = THIS_MODULE, - .base.cra_alignmask = 0, - - .min_keysize = OCS_SM4_KEY_SIZE, - .max_keysize = OCS_SM4_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = kmb_ocs_sm4_set_key, - .encrypt = kmb_ocs_sm4_ctr_encrypt, - .decrypt = kmb_ocs_sm4_ctr_decrypt, - .init = ocs_sm4_init_tfm, - .exit = ocs_exit_tfm, + .base.base.cra_name = "ctr(sm4)", + .base.base.cra_driver_name = "ctr-sm4-keembay-ocs", + .base.base.cra_priority = KMB_OCS_PRIORITY, + .base.base.cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .base.base.cra_blocksize = 1, + .base.base.cra_ctxsize = sizeof(struct ocs_aes_tctx), + .base.base.cra_module = THIS_MODULE, + .base.base.cra_alignmask = 0, + + .base.min_keysize = OCS_SM4_KEY_SIZE, + .base.max_keysize = OCS_SM4_KEY_SIZE, + .base.ivsize = AES_BLOCK_SIZE, + .base.setkey = kmb_ocs_sm4_set_key, + .base.encrypt = kmb_ocs_sm4_ctr_encrypt, + .base.decrypt = kmb_ocs_sm4_ctr_decrypt, + .base.init = ocs_sm4_init_tfm, + .base.exit = ocs_exit_tfm, + .op.do_one_request = kmb_ocs_aes_sk_do_one_request, }, #ifdef CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_CTS { - .base.cra_name = "cts(cbc(sm4))", - .base.cra_driver_name = "cts-sm4-keembay-ocs", - .base.cra_priority = KMB_OCS_PRIORITY, - .base.cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_KERN_DRIVER_ONLY, - .base.cra_blocksize = AES_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct ocs_aes_tctx), - .base.cra_module = THIS_MODULE, - .base.cra_alignmask = 0, - - .min_keysize = OCS_SM4_KEY_SIZE, - .max_keysize = OCS_SM4_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = kmb_ocs_sm4_set_key, - .encrypt = kmb_ocs_sm4_cts_encrypt, - .decrypt = kmb_ocs_sm4_cts_decrypt, - .init = ocs_sm4_init_tfm, - .exit = ocs_exit_tfm, + .base.base.cra_name = "cts(cbc(sm4))", + .base.base.cra_driver_name = "cts-sm4-keembay-ocs", + .base.base.cra_priority = KMB_OCS_PRIORITY, + .base.base.cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .base.base.cra_blocksize = AES_BLOCK_SIZE, + .base.base.cra_ctxsize = sizeof(struct ocs_aes_tctx), + .base.base.cra_module = THIS_MODULE, + .base.base.cra_alignmask = 0, + + .base.min_keysize = OCS_SM4_KEY_SIZE, + .base.max_keysize = OCS_SM4_KEY_SIZE, + .base.ivsize = AES_BLOCK_SIZE, + .base.setkey = kmb_ocs_sm4_set_key, + .base.encrypt = kmb_ocs_sm4_cts_encrypt, + .base.decrypt = kmb_ocs_sm4_cts_decrypt, + .base.init = ocs_sm4_init_tfm, + .base.exit = ocs_exit_tfm, + .op.do_one_request = kmb_ocs_aes_sk_do_one_request, } #endif /* CONFIG_CRYPTO_DEV_KEEMBAY_OCS_AES_SM4_CTS */ }; -static struct aead_alg algs_aead[] = { +static struct aead_engine_alg algs_aead[] = { { - .base = { + .base.base = { .cra_name = "gcm(aes)", .cra_driver_name = "gcm-aes-keembay-ocs", .cra_priority = KMB_OCS_PRIORITY, @@ -1467,17 +1450,18 @@ static struct aead_alg algs_aead[] = { .cra_alignmask = 0, .cra_module = THIS_MODULE, }, - .init = ocs_aes_aead_cra_init, - .exit = ocs_aead_cra_exit, - .ivsize = GCM_AES_IV_SIZE, - .maxauthsize = AES_BLOCK_SIZE, - .setauthsize = kmb_ocs_aead_gcm_setauthsize, - .setkey = kmb_ocs_aes_aead_set_key, - .encrypt = kmb_ocs_aes_gcm_encrypt, - .decrypt = kmb_ocs_aes_gcm_decrypt, + .base.init = ocs_aes_aead_cra_init, + .base.exit = ocs_aead_cra_exit, + .base.ivsize = GCM_AES_IV_SIZE, + .base.maxauthsize = AES_BLOCK_SIZE, + .base.setauthsize = kmb_ocs_aead_gcm_setauthsize, + .base.setkey = kmb_ocs_aes_aead_set_key, + .base.encrypt = kmb_ocs_aes_gcm_encrypt, + .base.decrypt = kmb_ocs_aes_gcm_decrypt, + .op.do_one_request = kmb_ocs_aes_aead_do_one_request, }, { - .base = { + .base.base = { .cra_name = "ccm(aes)", .cra_driver_name = "ccm-aes-keembay-ocs", .cra_priority = KMB_OCS_PRIORITY, @@ -1489,17 +1473,18 @@ static struct aead_alg algs_aead[] = { .cra_alignmask = 0, .cra_module = THIS_MODULE, }, - .init = ocs_aes_aead_cra_init, - .exit = ocs_aead_cra_exit, - .ivsize = AES_BLOCK_SIZE, - .maxauthsize = AES_BLOCK_SIZE, - .setauthsize = kmb_ocs_aead_ccm_setauthsize, - .setkey = kmb_ocs_aes_aead_set_key, - .encrypt = kmb_ocs_aes_ccm_encrypt, - .decrypt = kmb_ocs_aes_ccm_decrypt, + .base.init = ocs_aes_aead_cra_init, + .base.exit = ocs_aead_cra_exit, + .base.ivsize = AES_BLOCK_SIZE, + .base.maxauthsize = AES_BLOCK_SIZE, + .base.setauthsize = kmb_ocs_aead_ccm_setauthsize, + .base.setkey = kmb_ocs_aes_aead_set_key, + .base.encrypt = kmb_ocs_aes_ccm_encrypt, + .base.decrypt = kmb_ocs_aes_ccm_decrypt, + .op.do_one_request = kmb_ocs_aes_aead_do_one_request, }, { - .base = { + .base.base = { .cra_name = "gcm(sm4)", .cra_driver_name = "gcm-sm4-keembay-ocs", .cra_priority = KMB_OCS_PRIORITY, @@ -1510,17 +1495,18 @@ static struct aead_alg algs_aead[] = { .cra_alignmask = 0, .cra_module = THIS_MODULE, }, - .init = ocs_sm4_aead_cra_init, - .exit = ocs_aead_cra_exit, - .ivsize = GCM_AES_IV_SIZE, - .maxauthsize = AES_BLOCK_SIZE, - .setauthsize = kmb_ocs_aead_gcm_setauthsize, - .setkey = kmb_ocs_sm4_aead_set_key, - .encrypt = kmb_ocs_sm4_gcm_encrypt, - .decrypt = kmb_ocs_sm4_gcm_decrypt, + .base.init = ocs_sm4_aead_cra_init, + .base.exit = ocs_aead_cra_exit, + .base.ivsize = GCM_AES_IV_SIZE, + .base.maxauthsize = AES_BLOCK_SIZE, + .base.setauthsize = kmb_ocs_aead_gcm_setauthsize, + .base.setkey = kmb_ocs_sm4_aead_set_key, + .base.encrypt = kmb_ocs_sm4_gcm_encrypt, + .base.decrypt = kmb_ocs_sm4_gcm_decrypt, + .op.do_one_request = kmb_ocs_aes_aead_do_one_request, }, { - .base = { + .base.base = { .cra_name = "ccm(sm4)", .cra_driver_name = "ccm-sm4-keembay-ocs", .cra_priority = KMB_OCS_PRIORITY, @@ -1531,21 +1517,22 @@ static struct aead_alg algs_aead[] = { .cra_alignmask = 0, .cra_module = THIS_MODULE, }, - .init = ocs_sm4_aead_cra_init, - .exit = ocs_aead_cra_exit, - .ivsize = AES_BLOCK_SIZE, - .maxauthsize = AES_BLOCK_SIZE, - .setauthsize = kmb_ocs_aead_ccm_setauthsize, - .setkey = kmb_ocs_sm4_aead_set_key, - .encrypt = kmb_ocs_sm4_ccm_encrypt, - .decrypt = kmb_ocs_sm4_ccm_decrypt, + .base.init = ocs_sm4_aead_cra_init, + .base.exit = ocs_aead_cra_exit, + .base.ivsize = AES_BLOCK_SIZE, + .base.maxauthsize = AES_BLOCK_SIZE, + .base.setauthsize = kmb_ocs_aead_ccm_setauthsize, + .base.setkey = kmb_ocs_sm4_aead_set_key, + .base.encrypt = kmb_ocs_sm4_ccm_encrypt, + .base.decrypt = kmb_ocs_sm4_ccm_decrypt, + .op.do_one_request = kmb_ocs_aes_aead_do_one_request, } }; static void unregister_aes_algs(struct ocs_aes_dev *aes_dev) { - crypto_unregister_aeads(algs_aead, ARRAY_SIZE(algs_aead)); - crypto_unregister_skciphers(algs, ARRAY_SIZE(algs)); + crypto_engine_unregister_aeads(algs_aead, ARRAY_SIZE(algs_aead)); + crypto_engine_unregister_skciphers(algs, ARRAY_SIZE(algs)); } static int register_aes_algs(struct ocs_aes_dev *aes_dev) @@ -1556,13 +1543,13 @@ static int register_aes_algs(struct ocs_aes_dev *aes_dev) * If any algorithm fails to register, all preceding algorithms that * were successfully registered will be automatically unregistered. */ - ret = crypto_register_aeads(algs_aead, ARRAY_SIZE(algs_aead)); + ret = crypto_engine_register_aeads(algs_aead, ARRAY_SIZE(algs_aead)); if (ret) return ret; - ret = crypto_register_skciphers(algs, ARRAY_SIZE(algs)); + ret = crypto_engine_register_skciphers(algs, ARRAY_SIZE(algs)); if (ret) - crypto_unregister_aeads(algs_aead, ARRAY_SIZE(algs)); + crypto_engine_unregister_aeads(algs_aead, ARRAY_SIZE(algs)); return ret; } diff --git a/drivers/crypto/intel/keembay/keembay-ocs-ecc.c b/drivers/crypto/intel/keembay/keembay-ocs-ecc.c index 2269df17514c..fb95deed9057 100644 --- a/drivers/crypto/intel/keembay/keembay-ocs-ecc.c +++ b/drivers/crypto/intel/keembay/keembay-ocs-ecc.c @@ -7,30 +7,27 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include <crypto/ecc_curve.h> +#include <crypto/ecdh.h> +#include <crypto/engine.h> +#include <crypto/internal/ecc.h> +#include <crypto/internal/kpp.h> +#include <crypto/kpp.h> +#include <crypto/rng.h> #include <linux/clk.h> #include <linux/completion.h> -#include <linux/crypto.h> -#include <linux/delay.h> +#include <linux/err.h> #include <linux/fips.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/iopoll.h> #include <linux/irq.h> +#include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/scatterlist.h> -#include <linux/slab.h> -#include <linux/types.h> - -#include <crypto/ecc_curve.h> -#include <crypto/ecdh.h> -#include <crypto/engine.h> -#include <crypto/kpp.h> -#include <crypto/rng.h> - -#include <crypto/internal/ecc.h> -#include <crypto/internal/kpp.h> +#include <linux/string.h> #define DRV_NAME "keembay-ocs-ecc" @@ -95,13 +92,11 @@ struct ocs_ecc_dev { /** * struct ocs_ecc_ctx - Transformation context. - * @engine_ctx: Crypto engine ctx. * @ecc_dev: The ECC driver associated with this context. * @curve: The elliptic curve used by this transformation. * @private_key: The private key. */ struct ocs_ecc_ctx { - struct crypto_engine_ctx engine_ctx; struct ocs_ecc_dev *ecc_dev; const struct ecc_curve *curve; u64 private_key[KMB_ECC_VLI_MAX_DIGITS]; @@ -794,10 +789,6 @@ static int kmb_ecc_tctx_init(struct ocs_ecc_ctx *tctx, unsigned int curve_id) if (!tctx->curve) return -EOPNOTSUPP; - tctx->engine_ctx.op.prepare_request = NULL; - tctx->engine_ctx.op.do_one_request = kmb_ocs_ecc_do_one_request; - tctx->engine_ctx.op.unprepare_request = NULL; - return 0; } @@ -830,36 +821,38 @@ static unsigned int kmb_ocs_ecdh_max_size(struct crypto_kpp *tfm) return digits_to_bytes(tctx->curve->g.ndigits) * 2; } -static struct kpp_alg ocs_ecdh_p256 = { - .set_secret = kmb_ocs_ecdh_set_secret, - .generate_public_key = kmb_ocs_ecdh_generate_public_key, - .compute_shared_secret = kmb_ocs_ecdh_compute_shared_secret, - .init = kmb_ocs_ecdh_nist_p256_init_tfm, - .exit = kmb_ocs_ecdh_exit_tfm, - .max_size = kmb_ocs_ecdh_max_size, - .base = { +static struct kpp_engine_alg ocs_ecdh_p256 = { + .base.set_secret = kmb_ocs_ecdh_set_secret, + .base.generate_public_key = kmb_ocs_ecdh_generate_public_key, + .base.compute_shared_secret = kmb_ocs_ecdh_compute_shared_secret, + .base.init = kmb_ocs_ecdh_nist_p256_init_tfm, + .base.exit = kmb_ocs_ecdh_exit_tfm, + .base.max_size = kmb_ocs_ecdh_max_size, + .base.base = { .cra_name = "ecdh-nist-p256", .cra_driver_name = "ecdh-nist-p256-keembay-ocs", .cra_priority = KMB_OCS_ECC_PRIORITY, .cra_module = THIS_MODULE, .cra_ctxsize = sizeof(struct ocs_ecc_ctx), }, + .op.do_one_request = kmb_ocs_ecc_do_one_request, }; -static struct kpp_alg ocs_ecdh_p384 = { - .set_secret = kmb_ocs_ecdh_set_secret, - .generate_public_key = kmb_ocs_ecdh_generate_public_key, - .compute_shared_secret = kmb_ocs_ecdh_compute_shared_secret, - .init = kmb_ocs_ecdh_nist_p384_init_tfm, - .exit = kmb_ocs_ecdh_exit_tfm, - .max_size = kmb_ocs_ecdh_max_size, - .base = { +static struct kpp_engine_alg ocs_ecdh_p384 = { + .base.set_secret = kmb_ocs_ecdh_set_secret, + .base.generate_public_key = kmb_ocs_ecdh_generate_public_key, + .base.compute_shared_secret = kmb_ocs_ecdh_compute_shared_secret, + .base.init = kmb_ocs_ecdh_nist_p384_init_tfm, + .base.exit = kmb_ocs_ecdh_exit_tfm, + .base.max_size = kmb_ocs_ecdh_max_size, + .base.base = { .cra_name = "ecdh-nist-p384", .cra_driver_name = "ecdh-nist-p384-keembay-ocs", .cra_priority = KMB_OCS_ECC_PRIORITY, .cra_module = THIS_MODULE, .cra_ctxsize = sizeof(struct ocs_ecc_ctx), }, + .op.do_one_request = kmb_ocs_ecc_do_one_request, }; static irqreturn_t ocs_ecc_irq_handler(int irq, void *dev_id) @@ -941,14 +934,14 @@ static int kmb_ocs_ecc_probe(struct platform_device *pdev) } /* Register the KPP algo. */ - rc = crypto_register_kpp(&ocs_ecdh_p256); + rc = crypto_engine_register_kpp(&ocs_ecdh_p256); if (rc) { dev_err(dev, "Could not register OCS algorithms with Crypto API\n"); goto cleanup; } - rc = crypto_register_kpp(&ocs_ecdh_p384); + rc = crypto_engine_register_kpp(&ocs_ecdh_p384); if (rc) { dev_err(dev, "Could not register OCS algorithms with Crypto API\n"); @@ -958,7 +951,7 @@ static int kmb_ocs_ecc_probe(struct platform_device *pdev) return 0; ocs_ecdh_p384_error: - crypto_unregister_kpp(&ocs_ecdh_p256); + crypto_engine_unregister_kpp(&ocs_ecdh_p256); cleanup: crypto_engine_exit(ecc_dev->engine); @@ -977,8 +970,8 @@ static int kmb_ocs_ecc_remove(struct platform_device *pdev) ecc_dev = platform_get_drvdata(pdev); - crypto_unregister_kpp(&ocs_ecdh_p384); - crypto_unregister_kpp(&ocs_ecdh_p256); + crypto_engine_unregister_kpp(&ocs_ecdh_p384); + crypto_engine_unregister_kpp(&ocs_ecdh_p256); spin_lock(&ocs_ecc.lock); list_del(&ecc_dev->list); diff --git a/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c b/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c index d4bcbed1f546..daba8ca05dbe 100644 --- a/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c +++ b/drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c @@ -5,19 +5,21 @@ * Copyright (C) 2018-2020 Intel Corporation */ -#include <linux/completion.h> -#include <linux/delay.h> -#include <linux/dma-mapping.h> -#include <linux/interrupt.h> -#include <linux/module.h> -#include <linux/of_device.h> - #include <crypto/engine.h> +#include <crypto/hmac.h> +#include <crypto/internal/hash.h> #include <crypto/scatterwalk.h> #include <crypto/sha2.h> #include <crypto/sm3.h> -#include <crypto/hmac.h> -#include <crypto/internal/hash.h> +#include <linux/completion.h> +#include <linux/dma-mapping.h> +#include <linux/err.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/string.h> #include "ocs-hcu.h" @@ -34,7 +36,6 @@ /** * struct ocs_hcu_ctx: OCS HCU Transform context. - * @engine_ctx: Crypto Engine context. * @hcu_dev: The OCS HCU device used by the transformation. * @key: The key (used only for HMAC transformations). * @key_len: The length of the key. @@ -42,7 +43,6 @@ * @is_hmac_tfm: Whether or not this is a HMAC transformation. */ struct ocs_hcu_ctx { - struct crypto_engine_ctx engine_ctx; struct ocs_hcu_dev *hcu_dev; u8 key[SHA512_BLOCK_SIZE]; size_t key_len; @@ -824,11 +824,6 @@ static void __cra_init(struct crypto_tfm *tfm, struct ocs_hcu_ctx *ctx) { crypto_ahash_set_reqsize_dma(__crypto_ahash_cast(tfm), sizeof(struct ocs_hcu_rctx)); - - /* Init context to 0. */ - memzero_explicit(ctx, sizeof(*ctx)); - /* Set engine ops. */ - ctx->engine_ctx.op.do_one_request = kmb_ocs_hcu_do_one_request; } static int kmb_ocs_hcu_sha_cra_init(struct crypto_tfm *tfm) @@ -883,17 +878,17 @@ static void kmb_ocs_hcu_hmac_cra_exit(struct crypto_tfm *tfm) memzero_explicit(ctx->key, sizeof(ctx->key)); } -static struct ahash_alg ocs_hcu_algs[] = { +static struct ahash_engine_alg ocs_hcu_algs[] = { #ifdef CONFIG_CRYPTO_DEV_KEEMBAY_OCS_HCU_HMAC_SHA224 { - .init = kmb_ocs_hcu_init, - .update = kmb_ocs_hcu_update, - .final = kmb_ocs_hcu_final, - .finup = kmb_ocs_hcu_finup, - .digest = kmb_ocs_hcu_digest, - .export = kmb_ocs_hcu_export, - .import = kmb_ocs_hcu_import, - .halg = { + .base.init = kmb_ocs_hcu_init, + .base.update = kmb_ocs_hcu_update, + .base.final = kmb_ocs_hcu_final, + .base.finup = kmb_ocs_hcu_finup, + .base.digest = kmb_ocs_hcu_digest, + .base.export = kmb_ocs_hcu_export, + .base.import = kmb_ocs_hcu_import, + .base.halg = { .digestsize = SHA224_DIGEST_SIZE, .statesize = sizeof(struct ocs_hcu_rctx), .base = { @@ -907,18 +902,19 @@ static struct ahash_alg ocs_hcu_algs[] = { .cra_module = THIS_MODULE, .cra_init = kmb_ocs_hcu_sha_cra_init, } - } + }, + .op.do_one_request = kmb_ocs_hcu_do_one_request, }, { - .init = kmb_ocs_hcu_init, - .update = kmb_ocs_hcu_update, - .final = kmb_ocs_hcu_final, - .finup = kmb_ocs_hcu_finup, - .digest = kmb_ocs_hcu_digest, - .export = kmb_ocs_hcu_export, - .import = kmb_ocs_hcu_import, - .setkey = kmb_ocs_hcu_setkey, - .halg = { + .base.init = kmb_ocs_hcu_init, + .base.update = kmb_ocs_hcu_update, + .base.final = kmb_ocs_hcu_final, + .base.finup = kmb_ocs_hcu_finup, + .base.digest = kmb_ocs_hcu_digest, + .base.export = kmb_ocs_hcu_export, + .base.import = kmb_ocs_hcu_import, + .base.setkey = kmb_ocs_hcu_setkey, + .base.halg = { .digestsize = SHA224_DIGEST_SIZE, .statesize = sizeof(struct ocs_hcu_rctx), .base = { @@ -933,18 +929,19 @@ static struct ahash_alg ocs_hcu_algs[] = { .cra_init = kmb_ocs_hcu_hmac_cra_init, .cra_exit = kmb_ocs_hcu_hmac_cra_exit, } - } + }, + .op.do_one_request = kmb_ocs_hcu_do_one_request, }, #endif /* CONFIG_CRYPTO_DEV_KEEMBAY_OCS_HCU_HMAC_SHA224 */ { - .init = kmb_ocs_hcu_init, - .update = kmb_ocs_hcu_update, - .final = kmb_ocs_hcu_final, - .finup = kmb_ocs_hcu_finup, - .digest = kmb_ocs_hcu_digest, - .export = kmb_ocs_hcu_export, - .import = kmb_ocs_hcu_import, - .halg = { + .base.init = kmb_ocs_hcu_init, + .base.update = kmb_ocs_hcu_update, + .base.final = kmb_ocs_hcu_final, + .base.finup = kmb_ocs_hcu_finup, + .base.digest = kmb_ocs_hcu_digest, + .base.export = kmb_ocs_hcu_export, + .base.import = kmb_ocs_hcu_import, + .base.halg = { .digestsize = SHA256_DIGEST_SIZE, .statesize = sizeof(struct ocs_hcu_rctx), .base = { @@ -958,18 +955,19 @@ static struct ahash_alg ocs_hcu_algs[] = { .cra_module = THIS_MODULE, .cra_init = kmb_ocs_hcu_sha_cra_init, } - } + }, + .op.do_one_request = kmb_ocs_hcu_do_one_request, }, { - .init = kmb_ocs_hcu_init, - .update = kmb_ocs_hcu_update, - .final = kmb_ocs_hcu_final, - .finup = kmb_ocs_hcu_finup, - .digest = kmb_ocs_hcu_digest, - .export = kmb_ocs_hcu_export, - .import = kmb_ocs_hcu_import, - .setkey = kmb_ocs_hcu_setkey, - .halg = { + .base.init = kmb_ocs_hcu_init, + .base.update = kmb_ocs_hcu_update, + .base.final = kmb_ocs_hcu_final, + .base.finup = kmb_ocs_hcu_finup, + .base.digest = kmb_ocs_hcu_digest, + .base.export = kmb_ocs_hcu_export, + .base.import = kmb_ocs_hcu_import, + .base.setkey = kmb_ocs_hcu_setkey, + .base.halg = { .digestsize = SHA256_DIGEST_SIZE, .statesize = sizeof(struct ocs_hcu_rctx), .base = { @@ -984,17 +982,18 @@ static struct ahash_alg ocs_hcu_algs[] = { .cra_init = kmb_ocs_hcu_hmac_cra_init, .cra_exit = kmb_ocs_hcu_hmac_cra_exit, } - } + }, + .op.do_one_request = kmb_ocs_hcu_do_one_request, }, { - .init = kmb_ocs_hcu_init, - .update = kmb_ocs_hcu_update, - .final = kmb_ocs_hcu_final, - .finup = kmb_ocs_hcu_finup, - .digest = kmb_ocs_hcu_digest, - .export = kmb_ocs_hcu_export, - .import = kmb_ocs_hcu_import, - .halg = { + .base.init = kmb_ocs_hcu_init, + .base.update = kmb_ocs_hcu_update, + .base.final = kmb_ocs_hcu_final, + .base.finup = kmb_ocs_hcu_finup, + .base.digest = kmb_ocs_hcu_digest, + .base.export = kmb_ocs_hcu_export, + .base.import = kmb_ocs_hcu_import, + .base.halg = { .digestsize = SM3_DIGEST_SIZE, .statesize = sizeof(struct ocs_hcu_rctx), .base = { @@ -1008,18 +1007,19 @@ static struct ahash_alg ocs_hcu_algs[] = { .cra_module = THIS_MODULE, .cra_init = kmb_ocs_hcu_sm3_cra_init, } - } + }, + .op.do_one_request = kmb_ocs_hcu_do_one_request, }, { - .init = kmb_ocs_hcu_init, - .update = kmb_ocs_hcu_update, - .final = kmb_ocs_hcu_final, - .finup = kmb_ocs_hcu_finup, - .digest = kmb_ocs_hcu_digest, - .export = kmb_ocs_hcu_export, - .import = kmb_ocs_hcu_import, - .setkey = kmb_ocs_hcu_setkey, - .halg = { + .base.init = kmb_ocs_hcu_init, + .base.update = kmb_ocs_hcu_update, + .base.final = kmb_ocs_hcu_final, + .base.finup = kmb_ocs_hcu_finup, + .base.digest = kmb_ocs_hcu_digest, + .base.export = kmb_ocs_hcu_export, + .base.import = kmb_ocs_hcu_import, + .base.setkey = kmb_ocs_hcu_setkey, + .base.halg = { .digestsize = SM3_DIGEST_SIZE, .statesize = sizeof(struct ocs_hcu_rctx), .base = { @@ -1034,17 +1034,18 @@ static struct ahash_alg ocs_hcu_algs[] = { .cra_init = kmb_ocs_hcu_hmac_sm3_cra_init, .cra_exit = kmb_ocs_hcu_hmac_cra_exit, } - } + }, + .op.do_one_request = kmb_ocs_hcu_do_one_request, }, { - .init = kmb_ocs_hcu_init, - .update = kmb_ocs_hcu_update, - .final = kmb_ocs_hcu_final, - .finup = kmb_ocs_hcu_finup, - .digest = kmb_ocs_hcu_digest, - .export = kmb_ocs_hcu_export, - .import = kmb_ocs_hcu_import, - .halg = { + .base.init = kmb_ocs_hcu_init, + .base.update = kmb_ocs_hcu_update, + .base.final = kmb_ocs_hcu_final, + .base.finup = kmb_ocs_hcu_finup, + .base.digest = kmb_ocs_hcu_digest, + .base.export = kmb_ocs_hcu_export, + .base.import = kmb_ocs_hcu_import, + .base.halg = { .digestsize = SHA384_DIGEST_SIZE, .statesize = sizeof(struct ocs_hcu_rctx), .base = { @@ -1058,18 +1059,19 @@ static struct ahash_alg ocs_hcu_algs[] = { .cra_module = THIS_MODULE, .cra_init = kmb_ocs_hcu_sha_cra_init, } - } + }, + .op.do_one_request = kmb_ocs_hcu_do_one_request, }, { - .init = kmb_ocs_hcu_init, - .update = kmb_ocs_hcu_update, - .final = kmb_ocs_hcu_final, - .finup = kmb_ocs_hcu_finup, - .digest = kmb_ocs_hcu_digest, - .export = kmb_ocs_hcu_export, - .import = kmb_ocs_hcu_import, - .setkey = kmb_ocs_hcu_setkey, - .halg = { + .base.init = kmb_ocs_hcu_init, + .base.update = kmb_ocs_hcu_update, + .base.final = kmb_ocs_hcu_final, + .base.finup = kmb_ocs_hcu_finup, + .base.digest = kmb_ocs_hcu_digest, + .base.export = kmb_ocs_hcu_export, + .base.import = kmb_ocs_hcu_import, + .base.setkey = kmb_ocs_hcu_setkey, + .base.halg = { .digestsize = SHA384_DIGEST_SIZE, .statesize = sizeof(struct ocs_hcu_rctx), .base = { @@ -1084,17 +1086,18 @@ static struct ahash_alg ocs_hcu_algs[] = { .cra_init = kmb_ocs_hcu_hmac_cra_init, .cra_exit = kmb_ocs_hcu_hmac_cra_exit, } - } + }, + .op.do_one_request = kmb_ocs_hcu_do_one_request, }, { - .init = kmb_ocs_hcu_init, - .update = kmb_ocs_hcu_update, - .final = kmb_ocs_hcu_final, - .finup = kmb_ocs_hcu_finup, - .digest = kmb_ocs_hcu_digest, - .export = kmb_ocs_hcu_export, - .import = kmb_ocs_hcu_import, - .halg = { + .base.init = kmb_ocs_hcu_init, + .base.update = kmb_ocs_hcu_update, + .base.final = kmb_ocs_hcu_final, + .base.finup = kmb_ocs_hcu_finup, + .base.digest = kmb_ocs_hcu_digest, + .base.export = kmb_ocs_hcu_export, + .base.import = kmb_ocs_hcu_import, + .base.halg = { .digestsize = SHA512_DIGEST_SIZE, .statesize = sizeof(struct ocs_hcu_rctx), .base = { @@ -1108,18 +1111,19 @@ static struct ahash_alg ocs_hcu_algs[] = { .cra_module = THIS_MODULE, .cra_init = kmb_ocs_hcu_sha_cra_init, } - } + }, + .op.do_one_request = kmb_ocs_hcu_do_one_request, }, { - .init = kmb_ocs_hcu_init, - .update = kmb_ocs_hcu_update, - .final = kmb_ocs_hcu_final, - .finup = kmb_ocs_hcu_finup, - .digest = kmb_ocs_hcu_digest, - .export = kmb_ocs_hcu_export, - .import = kmb_ocs_hcu_import, - .setkey = kmb_ocs_hcu_setkey, - .halg = { + .base.init = kmb_ocs_hcu_init, + .base.update = kmb_ocs_hcu_update, + .base.final = kmb_ocs_hcu_final, + .base.finup = kmb_ocs_hcu_finup, + .base.digest = kmb_ocs_hcu_digest, + .base.export = kmb_ocs_hcu_export, + .base.import = kmb_ocs_hcu_import, + .base.setkey = kmb_ocs_hcu_setkey, + .base.halg = { .digestsize = SHA512_DIGEST_SIZE, .statesize = sizeof(struct ocs_hcu_rctx), .base = { @@ -1134,7 +1138,8 @@ static struct ahash_alg ocs_hcu_algs[] = { .cra_init = kmb_ocs_hcu_hmac_cra_init, .cra_exit = kmb_ocs_hcu_hmac_cra_exit, } - } + }, + .op.do_one_request = kmb_ocs_hcu_do_one_request, }, }; @@ -1155,7 +1160,7 @@ static int kmb_ocs_hcu_remove(struct platform_device *pdev) if (!hcu_dev) return -ENODEV; - crypto_unregister_ahashes(ocs_hcu_algs, ARRAY_SIZE(ocs_hcu_algs)); + crypto_engine_unregister_ahashes(ocs_hcu_algs, ARRAY_SIZE(ocs_hcu_algs)); rc = crypto_engine_exit(hcu_dev->engine); @@ -1170,7 +1175,6 @@ static int kmb_ocs_hcu_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct ocs_hcu_dev *hcu_dev; - struct resource *hcu_mem; int rc; hcu_dev = devm_kzalloc(dev, sizeof(*hcu_dev), GFP_KERNEL); @@ -1184,14 +1188,7 @@ static int kmb_ocs_hcu_probe(struct platform_device *pdev) if (rc) return rc; - /* Get the memory address and remap. */ - hcu_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!hcu_mem) { - dev_err(dev, "Could not retrieve io mem resource.\n"); - return -ENODEV; - } - - hcu_dev->io_base = devm_ioremap_resource(dev, hcu_mem); + hcu_dev->io_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(hcu_dev->io_base)) return PTR_ERR(hcu_dev->io_base); @@ -1231,7 +1228,7 @@ static int kmb_ocs_hcu_probe(struct platform_device *pdev) /* Security infrastructure guarantees OCS clock is enabled. */ - rc = crypto_register_ahashes(ocs_hcu_algs, ARRAY_SIZE(ocs_hcu_algs)); + rc = crypto_engine_register_ahashes(ocs_hcu_algs, ARRAY_SIZE(ocs_hcu_algs)); if (rc) { dev_err(dev, "Could not register algorithms.\n"); goto cleanup; diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c index e543a9e24a06..dd4464b7e00b 100644 --- a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c +++ b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c @@ -3,11 +3,13 @@ #include <linux/iopoll.h> #include <adf_accel_devices.h> #include <adf_cfg.h> +#include <adf_clock.h> #include <adf_common_drv.h> #include <adf_gen4_dc.h> #include <adf_gen4_hw_data.h> #include <adf_gen4_pfvf.h> #include <adf_gen4_pm.h> +#include <adf_gen4_timer.h> #include "adf_4xxx_hw_data.h" #include "icp_qat_hw.h" @@ -223,6 +225,8 @@ static u32 get_accel_cap(struct adf_accel_dev *accel_dev) ICP_ACCEL_CAPABILITIES_HKDF | ICP_ACCEL_CAPABILITIES_CHACHA_POLY | ICP_ACCEL_CAPABILITIES_AESGCM_SPC | + ICP_ACCEL_CAPABILITIES_SM3 | + ICP_ACCEL_CAPABILITIES_SM4 | ICP_ACCEL_CAPABILITIES_AES_V2; /* A set bit in fusectl1 means the feature is OFF in this SKU */ @@ -246,12 +250,19 @@ static u32 get_accel_cap(struct adf_accel_dev *accel_dev) capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_CIPHER; } + if (fusectl1 & ICP_ACCEL_4XXX_MASK_SMX_SLICE) { + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_SM3; + capabilities_sym &= ~ICP_ACCEL_CAPABILITIES_SM4; + } + capabilities_asym = ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | ICP_ACCEL_CAPABILITIES_CIPHER | + ICP_ACCEL_CAPABILITIES_SM2 | ICP_ACCEL_CAPABILITIES_ECEDMONT; if (fusectl1 & ICP_ACCEL_4XXX_MASK_PKE_SLICE) { capabilities_asym &= ~ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; + capabilities_asym &= ~ICP_ACCEL_CAPABILITIES_SM2; capabilities_asym &= ~ICP_ACCEL_CAPABILITIES_ECEDMONT; } @@ -317,6 +328,14 @@ static void get_admin_info(struct admin_info *admin_csrs_info) admin_csrs_info->admin_msg_lr = ADF_4XXX_ADMINMSGLR_OFFSET; } +static u32 get_heartbeat_clock(struct adf_hw_device_data *self) +{ + /* + * 4XXX uses KPT counter for HB + */ + return ADF_4XXX_KPT_COUNTER_FREQ; +} + static void adf_enable_error_correction(struct adf_accel_dev *accel_dev) { struct adf_bar *misc_bar = &GET_BARS(accel_dev)[ADF_4XXX_PMISC_BAR]; @@ -508,6 +527,10 @@ void adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data, u32 dev_id) hw_data->enable_pm = adf_gen4_enable_pm; hw_data->handle_pm_interrupt = adf_gen4_handle_pm_interrupt; hw_data->dev_config = adf_gen4_dev_config; + hw_data->start_timer = adf_gen4_timer_start; + hw_data->stop_timer = adf_gen4_timer_stop; + hw_data->get_hb_clock = get_heartbeat_clock; + hw_data->num_hb_ctrs = ADF_NUM_HB_CNT_PER_AE; adf_gen4_init_hw_csr_ops(&hw_data->csr_ops); adf_gen4_init_pf_pfvf_ops(&hw_data->pfvf_ops); diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h index e5b314d2b60e..bb3d95a8fb21 100644 --- a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h +++ b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.h @@ -3,6 +3,7 @@ #ifndef ADF_4XXX_HW_DATA_H_ #define ADF_4XXX_HW_DATA_H_ +#include <linux/units.h> #include <adf_accel_devices.h> /* PCIe configuration space */ @@ -64,6 +65,9 @@ #define ADF_402XX_ASYM_OBJ "qat_402xx_asym.bin" #define ADF_402XX_ADMIN_OBJ "qat_402xx_admin.bin" +/* Clocks frequency */ +#define ADF_4XXX_KPT_COUNTER_FREQ (100 * HZ_PER_MHZ) + /* qat_4xxx fuse bits are different from old GENs, redefine them */ enum icp_qat_4xxx_slice_mask { ICP_ACCEL_4XXX_MASK_CIPHER_SLICE = BIT(0), diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c index 1a15600361d0..6d4e2e139ffa 100644 --- a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c +++ b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c @@ -8,6 +8,7 @@ #include <adf_cfg.h> #include <adf_common_drv.h> #include <adf_dbgfs.h> +#include <adf_heartbeat.h> #include "adf_4xxx_hw_data.h" #include "qat_compression.h" @@ -77,6 +78,8 @@ static int adf_cfg_dev_init(struct adf_accel_dev *accel_dev) if (ret) return ret; + adf_heartbeat_save_cfg_param(accel_dev, ADF_CFG_HB_TIMER_MIN_MS); + return 0; } diff --git a/drivers/crypto/intel/qat/qat_c3xxx/adf_c3xxx_hw_data.c b/drivers/crypto/intel/qat/qat_c3xxx/adf_c3xxx_hw_data.c index 475643654e64..9c00c441b602 100644 --- a/drivers/crypto/intel/qat/qat_c3xxx/adf_c3xxx_hw_data.c +++ b/drivers/crypto/intel/qat/qat_c3xxx/adf_c3xxx_hw_data.c @@ -1,12 +1,14 @@ // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) /* Copyright(c) 2014 - 2021 Intel Corporation */ #include <adf_accel_devices.h> +#include <adf_clock.h> #include <adf_common_drv.h> #include <adf_gen2_config.h> #include <adf_gen2_dc.h> #include <adf_gen2_hw_data.h> #include <adf_gen2_pfvf.h> #include "adf_c3xxx_hw_data.h" +#include "adf_heartbeat.h" #include "icp_qat_hw.h" /* Worker thread to service arbiter mappings */ @@ -50,6 +52,28 @@ static u32 get_ae_mask(struct adf_hw_device_data *self) return ~(fuses | straps) & ADF_C3XXX_ACCELENGINES_MASK; } +static u32 get_ts_clock(struct adf_hw_device_data *self) +{ + /* + * Timestamp update interval is 16 AE clock ticks for c3xxx. + */ + return self->clock_frequency / 16; +} + +static int measure_clock(struct adf_accel_dev *accel_dev) +{ + u32 frequency; + int ret; + + ret = adf_dev_measure_clock(accel_dev, &frequency, ADF_C3XXX_MIN_AE_FREQ, + ADF_C3XXX_MAX_AE_FREQ); + if (ret) + return ret; + + accel_dev->hw_device->clock_frequency = frequency; + return 0; +} + static u32 get_misc_bar_id(struct adf_hw_device_data *self) { return ADF_C3XXX_PMISC_BAR; @@ -127,6 +151,10 @@ void adf_init_hw_data_c3xxx(struct adf_hw_device_data *hw_data) hw_data->set_ssm_wdtimer = adf_gen2_set_ssm_wdtimer; hw_data->disable_iov = adf_disable_sriov; hw_data->dev_config = adf_gen2_dev_config; + hw_data->measure_clock = measure_clock; + hw_data->get_hb_clock = get_ts_clock; + hw_data->num_hb_ctrs = ADF_NUM_HB_CNT_PER_AE; + hw_data->check_hb_ctrs = adf_heartbeat_check_ctrs; adf_gen2_init_pf_pfvf_ops(&hw_data->pfvf_ops); adf_gen2_init_hw_csr_ops(&hw_data->csr_ops); diff --git a/drivers/crypto/intel/qat/qat_c3xxx/adf_c3xxx_hw_data.h b/drivers/crypto/intel/qat/qat_c3xxx/adf_c3xxx_hw_data.h index 336a06f11dbd..690c6a1aa172 100644 --- a/drivers/crypto/intel/qat/qat_c3xxx/adf_c3xxx_hw_data.h +++ b/drivers/crypto/intel/qat/qat_c3xxx/adf_c3xxx_hw_data.h @@ -3,6 +3,8 @@ #ifndef ADF_C3XXX_HW_DATA_H_ #define ADF_C3XXX_HW_DATA_H_ +#include <linux/units.h> + /* PCIe configuration space */ #define ADF_C3XXX_PMISC_BAR 0 #define ADF_C3XXX_ETR_BAR 1 @@ -19,6 +21,11 @@ #define ADF_C3XXX_AE2FUNC_MAP_GRP_A_NUM_REGS 48 #define ADF_C3XXX_AE2FUNC_MAP_GRP_B_NUM_REGS 6 +/* Clocks frequency */ +#define ADF_C3XXX_AE_FREQ (685 * HZ_PER_MHZ) +#define ADF_C3XXX_MIN_AE_FREQ (533 * HZ_PER_MHZ) +#define ADF_C3XXX_MAX_AE_FREQ (685 * HZ_PER_MHZ) + /* Firmware Binary */ #define ADF_C3XXX_FW "qat_c3xxx.bin" #define ADF_C3XXX_MMP "qat_c3xxx_mmp.bin" diff --git a/drivers/crypto/intel/qat/qat_c62x/adf_c62x_hw_data.c b/drivers/crypto/intel/qat/qat_c62x/adf_c62x_hw_data.c index e14270703670..355a781693eb 100644 --- a/drivers/crypto/intel/qat/qat_c62x/adf_c62x_hw_data.c +++ b/drivers/crypto/intel/qat/qat_c62x/adf_c62x_hw_data.c @@ -1,12 +1,14 @@ // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) /* Copyright(c) 2014 - 2021 Intel Corporation */ #include <adf_accel_devices.h> +#include <adf_clock.h> #include <adf_common_drv.h> #include <adf_gen2_config.h> #include <adf_gen2_dc.h> #include <adf_gen2_hw_data.h> #include <adf_gen2_pfvf.h> #include "adf_c62x_hw_data.h" +#include "adf_heartbeat.h" #include "icp_qat_hw.h" /* Worker thread to service arbiter mappings */ @@ -50,6 +52,28 @@ static u32 get_ae_mask(struct adf_hw_device_data *self) return ~(fuses | straps) & ADF_C62X_ACCELENGINES_MASK; } +static u32 get_ts_clock(struct adf_hw_device_data *self) +{ + /* + * Timestamp update interval is 16 AE clock ticks for c62x. + */ + return self->clock_frequency / 16; +} + +static int measure_clock(struct adf_accel_dev *accel_dev) +{ + u32 frequency; + int ret; + + ret = adf_dev_measure_clock(accel_dev, &frequency, ADF_C62X_MIN_AE_FREQ, + ADF_C62X_MAX_AE_FREQ); + if (ret) + return ret; + + accel_dev->hw_device->clock_frequency = frequency; + return 0; +} + static u32 get_misc_bar_id(struct adf_hw_device_data *self) { return ADF_C62X_PMISC_BAR; @@ -129,6 +153,10 @@ void adf_init_hw_data_c62x(struct adf_hw_device_data *hw_data) hw_data->set_ssm_wdtimer = adf_gen2_set_ssm_wdtimer; hw_data->disable_iov = adf_disable_sriov; hw_data->dev_config = adf_gen2_dev_config; + hw_data->measure_clock = measure_clock; + hw_data->get_hb_clock = get_ts_clock; + hw_data->num_hb_ctrs = ADF_NUM_HB_CNT_PER_AE; + hw_data->check_hb_ctrs = adf_heartbeat_check_ctrs; adf_gen2_init_pf_pfvf_ops(&hw_data->pfvf_ops); adf_gen2_init_hw_csr_ops(&hw_data->csr_ops); diff --git a/drivers/crypto/intel/qat/qat_c62x/adf_c62x_hw_data.h b/drivers/crypto/intel/qat/qat_c62x/adf_c62x_hw_data.h index 008c0a3a9769..13e6ebf6fd91 100644 --- a/drivers/crypto/intel/qat/qat_c62x/adf_c62x_hw_data.h +++ b/drivers/crypto/intel/qat/qat_c62x/adf_c62x_hw_data.h @@ -3,6 +3,8 @@ #ifndef ADF_C62X_HW_DATA_H_ #define ADF_C62X_HW_DATA_H_ +#include <linux/units.h> + /* PCIe configuration space */ #define ADF_C62X_SRAM_BAR 0 #define ADF_C62X_PMISC_BAR 1 @@ -19,6 +21,11 @@ #define ADF_C62X_AE2FUNC_MAP_GRP_A_NUM_REGS 80 #define ADF_C62X_AE2FUNC_MAP_GRP_B_NUM_REGS 10 +/* Clocks frequency */ +#define ADF_C62X_AE_FREQ (685 * HZ_PER_MHZ) +#define ADF_C62X_MIN_AE_FREQ (533 * HZ_PER_MHZ) +#define ADF_C62X_MAX_AE_FREQ (800 * HZ_PER_MHZ) + /* Firmware Binary */ #define ADF_C62X_FW "qat_c62x.bin" #define ADF_C62X_MMP "qat_c62x_mmp.bin" diff --git a/drivers/crypto/intel/qat/qat_common/Makefile b/drivers/crypto/intel/qat/qat_common/Makefile index 38de3aba6e8c..43622c7fca71 100644 --- a/drivers/crypto/intel/qat/qat_common/Makefile +++ b/drivers/crypto/intel/qat/qat_common/Makefile @@ -17,6 +17,8 @@ intel_qat-objs := adf_cfg.o \ adf_gen4_pm.o \ adf_gen2_dc.o \ adf_gen4_dc.o \ + adf_gen4_timer.o \ + adf_clock.o \ qat_crypto.o \ qat_compression.o \ qat_comp_algs.o \ @@ -28,6 +30,9 @@ intel_qat-objs := adf_cfg.o \ qat_bl.o intel_qat-$(CONFIG_DEBUG_FS) += adf_transport_debug.o \ + adf_fw_counters.o \ + adf_heartbeat.o \ + adf_heartbeat_dbgfs.o \ adf_dbgfs.o intel_qat-$(CONFIG_PCI_IOV) += adf_sriov.o adf_vf_isr.o adf_pfvf_utils.o \ diff --git a/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h b/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h index 0399417b91fc..e57abde66f4f 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h +++ b/drivers/crypto/intel/qat/qat_common/adf_accel_devices.h @@ -188,6 +188,11 @@ struct adf_hw_device_data { int (*init_admin_comms)(struct adf_accel_dev *accel_dev); void (*exit_admin_comms)(struct adf_accel_dev *accel_dev); int (*send_admin_init)(struct adf_accel_dev *accel_dev); + int (*start_timer)(struct adf_accel_dev *accel_dev); + void (*stop_timer)(struct adf_accel_dev *accel_dev); + void (*check_hb_ctrs)(struct adf_accel_dev *accel_dev); + uint32_t (*get_hb_clock)(struct adf_hw_device_data *self); + int (*measure_clock)(struct adf_accel_dev *accel_dev); int (*init_arb)(struct adf_accel_dev *accel_dev); void (*exit_arb)(struct adf_accel_dev *accel_dev); const u32 *(*get_arb_mapping)(struct adf_accel_dev *accel_dev); @@ -229,6 +234,7 @@ struct adf_hw_device_data { u8 num_accel; u8 num_logical_accel; u8 num_engines; + u32 num_hb_ctrs; }; /* CSR write macro */ @@ -241,6 +247,11 @@ struct adf_hw_device_data { #define ADF_CFG_NUM_SERVICES 4 #define ADF_SRV_TYPE_BIT_LEN 3 #define ADF_SRV_TYPE_MASK 0x7 +#define ADF_AE_ADMIN_THREAD 7 +#define ADF_NUM_THREADS_PER_AE 8 +#define ADF_NUM_PKE_STRAND 2 +#define ADF_AE_STRAND0_THREAD 8 +#define ADF_AE_STRAND1_THREAD 9 #define GET_DEV(accel_dev) ((accel_dev)->accel_pci_dev.pci_dev->dev) #define GET_BARS(accel_dev) ((accel_dev)->accel_pci_dev.pci_bars) @@ -292,9 +303,12 @@ struct adf_accel_dev { unsigned long status; atomic_t ref_count; struct dentry *debugfs_dir; + struct dentry *fw_cntr_dbgfile; struct list_head list; struct module *owner; struct adf_accel_pci accel_pci_dev; + struct adf_timer *timer; + struct adf_heartbeat *heartbeat; union { struct { /* protects VF2PF interrupts access */ diff --git a/drivers/crypto/intel/qat/qat_common/adf_admin.c b/drivers/crypto/intel/qat/qat_common/adf_admin.c index 118775ee02f2..ff790823b868 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_admin.c +++ b/drivers/crypto/intel/qat/qat_common/adf_admin.c @@ -8,6 +8,7 @@ #include <linux/dma-mapping.h> #include "adf_accel_devices.h" #include "adf_common_drv.h" +#include "adf_heartbeat.h" #include "icp_qat_fw_init_admin.h" #define ADF_ADMIN_MAILBOX_STRIDE 0x1000 @@ -15,6 +16,7 @@ #define ADF_CONST_TABLE_SIZE 1024 #define ADF_ADMIN_POLL_DELAY_US 20 #define ADF_ADMIN_POLL_TIMEOUT_US (5 * USEC_PER_SEC) +#define ADF_ONE_AE 1 static const u8 const_tab[1024] __aligned(1024) = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -194,6 +196,22 @@ static int adf_set_fw_constants(struct adf_accel_dev *accel_dev) return adf_send_admin(accel_dev, &req, &resp, ae_mask); } +int adf_get_fw_timestamp(struct adf_accel_dev *accel_dev, u64 *timestamp) +{ + struct icp_qat_fw_init_admin_req req = { }; + struct icp_qat_fw_init_admin_resp resp; + unsigned int ae_mask = ADF_ONE_AE; + int ret; + + req.cmd_id = ICP_QAT_FW_TIMER_GET; + ret = adf_send_admin(accel_dev, &req, &resp, ae_mask); + if (ret) + return ret; + + *timestamp = resp.timestamp; + return 0; +} + static int adf_get_dc_capabilities(struct adf_accel_dev *accel_dev, u32 *capabilities) { @@ -223,6 +241,49 @@ static int adf_get_dc_capabilities(struct adf_accel_dev *accel_dev, return 0; } +int adf_get_ae_fw_counters(struct adf_accel_dev *accel_dev, u16 ae, u64 *reqs, u64 *resps) +{ + struct icp_qat_fw_init_admin_resp resp = { }; + struct icp_qat_fw_init_admin_req req = { }; + int ret; + + req.cmd_id = ICP_QAT_FW_COUNTERS_GET; + + ret = adf_put_admin_msg_sync(accel_dev, ae, &req, &resp); + if (ret || resp.status) + return -EFAULT; + + *reqs = resp.req_rec_count; + *resps = resp.resp_sent_count; + + return 0; +} + +int adf_send_admin_tim_sync(struct adf_accel_dev *accel_dev, u32 cnt) +{ + u32 ae_mask = accel_dev->hw_device->ae_mask; + struct icp_qat_fw_init_admin_req req = { }; + struct icp_qat_fw_init_admin_resp resp = { }; + + req.cmd_id = ICP_QAT_FW_SYNC; + req.int_timer_ticks = cnt; + + return adf_send_admin(accel_dev, &req, &resp, ae_mask); +} + +int adf_send_admin_hb_timer(struct adf_accel_dev *accel_dev, uint32_t ticks) +{ + u32 ae_mask = accel_dev->hw_device->ae_mask; + struct icp_qat_fw_init_admin_req req = { }; + struct icp_qat_fw_init_admin_resp resp; + + req.cmd_id = ICP_QAT_FW_HEARTBEAT_TIMER_SET; + req.init_cfg_ptr = accel_dev->heartbeat->dma.phy_addr; + req.heartbeat_ticks = ticks; + + return adf_send_admin(accel_dev, &req, &resp, ae_mask); +} + /** * adf_send_admin_init() - Function sends init message to FW * @accel_dev: Pointer to acceleration device. diff --git a/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h b/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h index 3ae1e5caee0e..6066dc637352 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h +++ b/drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h @@ -47,4 +47,6 @@ #define ADF_ETRMGR_CORE_AFFINITY_FORMAT \ ADF_ETRMGR_BANK "%d" ADF_ETRMGR_CORE_AFFINITY #define ADF_ACCEL_STR "Accelerator%d" +#define ADF_HEARTBEAT_TIMER "HeartbeatTimer" + #endif diff --git a/drivers/crypto/intel/qat/qat_common/adf_clock.c b/drivers/crypto/intel/qat/qat_common/adf_clock.c new file mode 100644 index 000000000000..dc0778691eb0 --- /dev/null +++ b/drivers/crypto/intel/qat/qat_common/adf_clock.c @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2023 Intel Corporation */ + +#include <linux/delay.h> +#include <linux/dev_printk.h> +#include <linux/export.h> +#include <linux/math.h> +#include <linux/minmax.h> +#include <linux/time64.h> +#include <linux/types.h> +#include <linux/units.h> +#include <asm/errno.h> +#include "adf_accel_devices.h" +#include "adf_clock.h" +#include "adf_common_drv.h" + +#define MEASURE_CLOCK_RETRIES 10 +#define MEASURE_CLOCK_DELAY_US 10000 +#define ME_CLK_DIVIDER 16 +#define MEASURE_CLOCK_DELTA_THRESHOLD_US 100 + +static inline u64 timespec_to_us(const struct timespec64 *ts) +{ + return (u64)DIV_ROUND_CLOSEST_ULL(timespec64_to_ns(ts), NSEC_PER_USEC); +} + +static inline u64 timespec_to_ms(const struct timespec64 *ts) +{ + return (u64)DIV_ROUND_CLOSEST_ULL(timespec64_to_ns(ts), NSEC_PER_MSEC); +} + +u64 adf_clock_get_current_time(void) +{ + struct timespec64 ts; + + ktime_get_real_ts64(&ts); + return timespec_to_ms(&ts); +} + +static int measure_clock(struct adf_accel_dev *accel_dev, u32 *frequency) +{ + struct timespec64 ts1, ts2, ts3, ts4; + u64 timestamp1, timestamp2, temp; + u32 delta_us, tries; + int ret; + + tries = MEASURE_CLOCK_RETRIES; + do { + ktime_get_real_ts64(&ts1); + ret = adf_get_fw_timestamp(accel_dev, ×tamp1); + if (ret) { + dev_err(&GET_DEV(accel_dev), + "Failed to get fw timestamp\n"); + return ret; + } + ktime_get_real_ts64(&ts2); + delta_us = timespec_to_us(&ts2) - timespec_to_us(&ts1); + } while (delta_us > MEASURE_CLOCK_DELTA_THRESHOLD_US && --tries); + + if (!tries) { + dev_err(&GET_DEV(accel_dev), "Excessive clock measure delay\n"); + return -ETIMEDOUT; + } + + fsleep(MEASURE_CLOCK_DELAY_US); + + tries = MEASURE_CLOCK_RETRIES; + do { + ktime_get_real_ts64(&ts3); + if (adf_get_fw_timestamp(accel_dev, ×tamp2)) { + dev_err(&GET_DEV(accel_dev), + "Failed to get fw timestamp\n"); + return -EIO; + } + ktime_get_real_ts64(&ts4); + delta_us = timespec_to_us(&ts4) - timespec_to_us(&ts3); + } while (delta_us > MEASURE_CLOCK_DELTA_THRESHOLD_US && --tries); + + if (!tries) { + dev_err(&GET_DEV(accel_dev), "Excessive clock measure delay\n"); + return -ETIMEDOUT; + } + + delta_us = timespec_to_us(&ts3) - timespec_to_us(&ts1); + temp = (timestamp2 - timestamp1) * ME_CLK_DIVIDER * 10; + temp = DIV_ROUND_CLOSEST_ULL(temp, delta_us); + /* + * Enclose the division to allow the preprocessor to precalculate it, + * and avoid promoting r-value to 64-bit before division. + */ + *frequency = temp * (HZ_PER_MHZ / 10); + + return 0; +} + +/** + * adf_dev_measure_clock() - measures device clock frequency + * @accel_dev: Pointer to acceleration device. + * @frequency: Pointer to variable where result will be stored + * @min: Minimal allowed frequency value + * @max: Maximal allowed frequency value + * + * If the measurement result will go beyond the min/max thresholds the value + * will take the value of the crossed threshold. + * + * This algorithm compares the device firmware timestamp with the kernel + * timestamp. So we can't expect too high accuracy from this measurement. + * + * Return: + * * 0 - measurement succeed + * * -ETIMEDOUT - measurement failed + */ +int adf_dev_measure_clock(struct adf_accel_dev *accel_dev, + u32 *frequency, u32 min, u32 max) +{ + int ret; + u32 freq; + + ret = measure_clock(accel_dev, &freq); + if (ret) + return ret; + + *frequency = clamp(freq, min, max); + + if (*frequency != freq) + dev_warn(&GET_DEV(accel_dev), + "Measured clock %d Hz is out of range, assuming %d\n", + freq, *frequency); + return 0; +} +EXPORT_SYMBOL_GPL(adf_dev_measure_clock); diff --git a/drivers/crypto/intel/qat/qat_common/adf_clock.h b/drivers/crypto/intel/qat/qat_common/adf_clock.h new file mode 100644 index 000000000000..e309bc0dc35c --- /dev/null +++ b/drivers/crypto/intel/qat/qat_common/adf_clock.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright(c) 2023 Intel Corporation */ +#ifndef ADF_CLOCK_H +#define ADF_CLOCK_H + +#include <linux/types.h> + +struct adf_accel_dev; + +int adf_dev_measure_clock(struct adf_accel_dev *accel_dev, u32 *frequency, + u32 min, u32 max); +u64 adf_clock_get_current_time(void); + +#endif diff --git a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h index b8132eb9bc2a..673b5044c62a 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_common_drv.h +++ b/drivers/crypto/intel/qat/qat_common/adf_common_drv.h @@ -58,12 +58,6 @@ int adf_dev_restart(struct adf_accel_dev *accel_dev); void adf_devmgr_update_class_index(struct adf_hw_device_data *hw_data); void adf_clean_vf_map(bool); - -int adf_ctl_dev_register(void); -void adf_ctl_dev_unregister(void); -int adf_processes_dev_register(void); -void adf_processes_dev_unregister(void); - int adf_devmgr_add_dev(struct adf_accel_dev *accel_dev, struct adf_accel_dev *pf); void adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev, @@ -94,7 +88,11 @@ void adf_exit_aer(void); int adf_init_admin_comms(struct adf_accel_dev *accel_dev); void adf_exit_admin_comms(struct adf_accel_dev *accel_dev); int adf_send_admin_init(struct adf_accel_dev *accel_dev); +int adf_get_ae_fw_counters(struct adf_accel_dev *accel_dev, u16 ae, u64 *reqs, u64 *resps); int adf_init_admin_pm(struct adf_accel_dev *accel_dev, u32 idle_delay); +int adf_send_admin_tim_sync(struct adf_accel_dev *accel_dev, u32 cnt); +int adf_send_admin_hb_timer(struct adf_accel_dev *accel_dev, uint32_t ticks); +int adf_get_fw_timestamp(struct adf_accel_dev *accel_dev, u64 *timestamp); int adf_init_arb(struct adf_accel_dev *accel_dev); void adf_exit_arb(struct adf_accel_dev *accel_dev); void adf_update_ring_arb(struct adf_etr_ring_data *ring); @@ -178,8 +176,6 @@ int qat_hal_init_rd_xfer(struct icp_qat_fw_loader_handle *handle, int qat_hal_init_nn(struct icp_qat_fw_loader_handle *handle, unsigned char ae, unsigned long ctx_mask, unsigned short reg_num, unsigned int regdata); -int qat_hal_wr_lm(struct icp_qat_fw_loader_handle *handle, - unsigned char ae, unsigned short lm_addr, unsigned int value); void qat_hal_set_ae_tindex_mode(struct icp_qat_fw_loader_handle *handle, unsigned char ae, unsigned char mode); int qat_uclo_wr_all_uimage(struct icp_qat_fw_loader_handle *handle); @@ -193,6 +189,8 @@ int qat_uclo_set_cfg_ae_mask(struct icp_qat_fw_loader_handle *handle, int adf_init_misc_wq(void); void adf_exit_misc_wq(void); bool adf_misc_wq_queue_work(struct work_struct *work); +bool adf_misc_wq_queue_delayed_work(struct delayed_work *work, + unsigned long delay); #if defined(CONFIG_PCI_IOV) int adf_sriov_configure(struct pci_dev *pdev, int numvfs); void adf_disable_sriov(struct adf_accel_dev *accel_dev); diff --git a/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c index d0a2f892e6eb..04845f8d72be 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c +++ b/drivers/crypto/intel/qat/qat_common/adf_dbgfs.c @@ -6,6 +6,8 @@ #include "adf_cfg.h" #include "adf_common_drv.h" #include "adf_dbgfs.h" +#include "adf_fw_counters.h" +#include "adf_heartbeat_dbgfs.h" /** * adf_dbgfs_init() - add persistent debugfs entries @@ -56,6 +58,11 @@ void adf_dbgfs_add(struct adf_accel_dev *accel_dev) { if (!accel_dev->debugfs_dir) return; + + if (!accel_dev->is_vf) { + adf_fw_counters_dbgfs_add(accel_dev); + adf_heartbeat_dbgfs_add(accel_dev); + } } /** @@ -66,4 +73,9 @@ void adf_dbgfs_rm(struct adf_accel_dev *accel_dev) { if (!accel_dev->debugfs_dir) return; + + if (!accel_dev->is_vf) { + adf_heartbeat_dbgfs_rm(accel_dev); + adf_fw_counters_dbgfs_rm(accel_dev); + } } diff --git a/drivers/crypto/intel/qat/qat_common/adf_fw_counters.c b/drivers/crypto/intel/qat/qat_common/adf_fw_counters.c new file mode 100644 index 000000000000..cb6e09ef5c9f --- /dev/null +++ b/drivers/crypto/intel/qat/qat_common/adf_fw_counters.c @@ -0,0 +1,264 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2023 Intel Corporation */ +#include <linux/bitops.h> +#include <linux/debugfs.h> +#include <linux/err.h> +#include <linux/fs.h> +#include <linux/kernel.h> +#include <linux/seq_file.h> +#include <linux/types.h> + +#include "adf_accel_devices.h" +#include "adf_common_drv.h" +#include "adf_fw_counters.h" + +#define ADF_FW_COUNTERS_MAX_PADDING 16 + +enum adf_fw_counters_types { + ADF_FW_REQUESTS, + ADF_FW_RESPONSES, + ADF_FW_COUNTERS_COUNT +}; + +static const char * const adf_fw_counter_names[] = { + [ADF_FW_REQUESTS] = "Requests", + [ADF_FW_RESPONSES] = "Responses", +}; + +static_assert(ARRAY_SIZE(adf_fw_counter_names) == ADF_FW_COUNTERS_COUNT); + +struct adf_ae_counters { + u16 ae; + u64 values[ADF_FW_COUNTERS_COUNT]; +}; + +struct adf_fw_counters { + u16 ae_count; + struct adf_ae_counters ae_counters[]; +}; + +static void adf_fw_counters_parse_ae_values(struct adf_ae_counters *ae_counters, u32 ae, + u64 req_count, u64 resp_count) +{ + ae_counters->ae = ae; + ae_counters->values[ADF_FW_REQUESTS] = req_count; + ae_counters->values[ADF_FW_RESPONSES] = resp_count; +} + +static int adf_fw_counters_load_from_device(struct adf_accel_dev *accel_dev, + struct adf_fw_counters *fw_counters) +{ + struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev); + unsigned long ae_mask; + unsigned int i; + unsigned long ae; + + /* Ignore the admin AEs */ + ae_mask = hw_data->ae_mask & ~hw_data->admin_ae_mask; + + if (hweight_long(ae_mask) > fw_counters->ae_count) + return -EINVAL; + + i = 0; + for_each_set_bit(ae, &ae_mask, GET_MAX_ACCELENGINES(accel_dev)) { + u64 req_count, resp_count; + int ret; + + ret = adf_get_ae_fw_counters(accel_dev, ae, &req_count, &resp_count); + if (ret) + return ret; + + adf_fw_counters_parse_ae_values(&fw_counters->ae_counters[i++], ae, + req_count, resp_count); + } + + return 0; +} + +static struct adf_fw_counters *adf_fw_counters_allocate(unsigned long ae_count) +{ + struct adf_fw_counters *fw_counters; + + if (unlikely(!ae_count)) + return ERR_PTR(-EINVAL); + + fw_counters = kmalloc(struct_size(fw_counters, ae_counters, ae_count), GFP_KERNEL); + if (!fw_counters) + return ERR_PTR(-ENOMEM); + + fw_counters->ae_count = ae_count; + + return fw_counters; +} + +/** + * adf_fw_counters_get() - Return FW counters for the provided device. + * @accel_dev: Pointer to a QAT acceleration device + * + * Allocates and returns a table of counters containing execution statistics + * for each non-admin AE available through the supplied acceleration device. + * The caller becomes the owner of such memory and is responsible for + * the deallocation through a call to kfree(). + * + * Returns: a pointer to a dynamically allocated struct adf_fw_counters + * on success, or a negative value on error. + */ +static struct adf_fw_counters *adf_fw_counters_get(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev); + struct adf_fw_counters *fw_counters; + unsigned long ae_count; + int ret; + + if (!adf_dev_started(accel_dev)) { + dev_err(&GET_DEV(accel_dev), "QAT Device not started\n"); + return ERR_PTR(-EFAULT); + } + + /* Ignore the admin AEs */ + ae_count = hweight_long(hw_data->ae_mask & ~hw_data->admin_ae_mask); + + fw_counters = adf_fw_counters_allocate(ae_count); + if (IS_ERR(fw_counters)) + return fw_counters; + + ret = adf_fw_counters_load_from_device(accel_dev, fw_counters); + if (ret) { + kfree(fw_counters); + dev_err(&GET_DEV(accel_dev), + "Failed to create QAT fw_counters file table [%d].\n", ret); + return ERR_PTR(ret); + } + + return fw_counters; +} + +static void *qat_fw_counters_seq_start(struct seq_file *sfile, loff_t *pos) +{ + struct adf_fw_counters *fw_counters = sfile->private; + + if (*pos == 0) + return SEQ_START_TOKEN; + + if (*pos > fw_counters->ae_count) + return NULL; + + return &fw_counters->ae_counters[*pos - 1]; +} + +static void *qat_fw_counters_seq_next(struct seq_file *sfile, void *v, loff_t *pos) +{ + struct adf_fw_counters *fw_counters = sfile->private; + + (*pos)++; + + if (*pos > fw_counters->ae_count) + return NULL; + + return &fw_counters->ae_counters[*pos - 1]; +} + +static void qat_fw_counters_seq_stop(struct seq_file *sfile, void *v) {} + +static int qat_fw_counters_seq_show(struct seq_file *sfile, void *v) +{ + int i; + + if (v == SEQ_START_TOKEN) { + seq_puts(sfile, "AE "); + for (i = 0; i < ADF_FW_COUNTERS_COUNT; ++i) + seq_printf(sfile, " %*s", ADF_FW_COUNTERS_MAX_PADDING, + adf_fw_counter_names[i]); + } else { + struct adf_ae_counters *ae_counters = (struct adf_ae_counters *)v; + + seq_printf(sfile, "%2d:", ae_counters->ae); + for (i = 0; i < ADF_FW_COUNTERS_COUNT; ++i) + seq_printf(sfile, " %*llu", ADF_FW_COUNTERS_MAX_PADDING, + ae_counters->values[i]); + } + seq_putc(sfile, '\n'); + + return 0; +} + +static const struct seq_operations qat_fw_counters_sops = { + .start = qat_fw_counters_seq_start, + .next = qat_fw_counters_seq_next, + .stop = qat_fw_counters_seq_stop, + .show = qat_fw_counters_seq_show, +}; + +static int qat_fw_counters_file_open(struct inode *inode, struct file *file) +{ + struct adf_accel_dev *accel_dev = inode->i_private; + struct seq_file *fw_counters_seq_file; + struct adf_fw_counters *fw_counters; + int ret; + + fw_counters = adf_fw_counters_get(accel_dev); + if (IS_ERR(fw_counters)) + return PTR_ERR(fw_counters); + + ret = seq_open(file, &qat_fw_counters_sops); + if (unlikely(ret)) { + kfree(fw_counters); + return ret; + } + + fw_counters_seq_file = file->private_data; + fw_counters_seq_file->private = fw_counters; + return ret; +} + +static int qat_fw_counters_file_release(struct inode *inode, struct file *file) +{ + struct seq_file *seq = file->private_data; + + kfree(seq->private); + seq->private = NULL; + + return seq_release(inode, file); } + +static const struct file_operations qat_fw_counters_fops = { + .owner = THIS_MODULE, + .open = qat_fw_counters_file_open, + .read = seq_read, + .llseek = seq_lseek, + .release = qat_fw_counters_file_release, +}; + +/** + * adf_fw_counters_dbgfs_add() - Create a debugfs file containing FW + * execution counters. + * @accel_dev: Pointer to a QAT acceleration device + * + * Function creates a file to display a table with statistics for the given + * QAT acceleration device. The table stores device specific execution values + * for each AE, such as the number of requests sent to the FW and responses + * received from the FW. + * + * Return: void + */ +void adf_fw_counters_dbgfs_add(struct adf_accel_dev *accel_dev) +{ + accel_dev->fw_cntr_dbgfile = debugfs_create_file("fw_counters", 0400, + accel_dev->debugfs_dir, + accel_dev, + &qat_fw_counters_fops); +} + +/** + * adf_fw_counters_dbgfs_rm() - Remove the debugfs file containing FW counters. + * @accel_dev: Pointer to a QAT acceleration device. + * + * Function removes the file providing the table of statistics for the given + * QAT acceleration device. + * + * Return: void + */ +void adf_fw_counters_dbgfs_rm(struct adf_accel_dev *accel_dev) +{ + debugfs_remove(accel_dev->fw_cntr_dbgfile); + accel_dev->fw_cntr_dbgfile = NULL; +} diff --git a/drivers/crypto/intel/qat/qat_common/adf_fw_counters.h b/drivers/crypto/intel/qat/qat_common/adf_fw_counters.h new file mode 100644 index 000000000000..91b3b6a95f1f --- /dev/null +++ b/drivers/crypto/intel/qat/qat_common/adf_fw_counters.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright(c) 2023 Intel Corporation */ +#ifndef ADF_FW_COUNTERS_H +#define ADF_FW_COUNTERS_H + +struct adf_accel_dev; + +void adf_fw_counters_dbgfs_add(struct adf_accel_dev *accel_dev); +void adf_fw_counters_dbgfs_rm(struct adf_accel_dev *accel_dev); + +#endif diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen2_config.c b/drivers/crypto/intel/qat/qat_common/adf_gen2_config.c index eeb30da7587a..c27ff6d18e11 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_gen2_config.c +++ b/drivers/crypto/intel/qat/qat_common/adf_gen2_config.c @@ -7,6 +7,7 @@ #include "adf_common_drv.h" #include "qat_crypto.h" #include "qat_compression.h" +#include "adf_heartbeat.h" #include "adf_transport_access_macros.h" static int adf_gen2_crypto_dev_config(struct adf_accel_dev *accel_dev) @@ -195,6 +196,12 @@ int adf_gen2_dev_config(struct adf_accel_dev *accel_dev) if (ret) goto err; + ret = adf_cfg_section_add(accel_dev, ADF_GENERAL_SEC); + if (ret) + goto err; + + adf_heartbeat_save_cfg_param(accel_dev, ADF_CFG_HB_TIMER_DEFAULT_MS); + set_bit(ADF_STATUS_CONFIGURED, &accel_dev->status); return ret; diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen2_hw_data.h b/drivers/crypto/intel/qat/qat_common/adf_gen2_hw_data.h index e4bc07529be4..6bd341061de4 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_gen2_hw_data.h +++ b/drivers/crypto/intel/qat/qat_common/adf_gen2_hw_data.h @@ -145,6 +145,9 @@ do { \ #define ADF_GEN2_CERRSSMSH(i) ((i) * 0x4000 + 0x10) #define ADF_GEN2_ERRSSMSH_EN BIT(3) +/* Number of heartbeat counter pairs */ +#define ADF_NUM_HB_CNT_PER_AE ADF_NUM_THREADS_PER_AE + /* Interrupts */ #define ADF_GEN2_SMIAPF0_MASK_OFFSET (0x3A000 + 0x28) #define ADF_GEN2_SMIAPF1_MASK_OFFSET (0x3A000 + 0x30) diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h b/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h index 4fb4b3df5a18..02d7a019ebf8 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h +++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h @@ -136,6 +136,9 @@ do { \ #define ADF_GEN4_VFLNOTIFY BIT(7) +/* Number of heartbeat counter pairs */ +#define ADF_NUM_HB_CNT_PER_AE ADF_NUM_THREADS_PER_AE + void adf_gen4_set_ssm_wdtimer(struct adf_accel_dev *accel_dev); void adf_gen4_init_hw_csr_ops(struct adf_hw_csr_ops *csr_ops); int adf_gen4_ring_pair_reset(struct adf_accel_dev *accel_dev, u32 bank_number); diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h index dd112923e006..c2768762cca3 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h +++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h @@ -35,7 +35,7 @@ #define ADF_GEN4_PM_MSG_PENDING BIT(0) #define ADF_GEN4_PM_MSG_PAYLOAD_BIT_MASK GENMASK(28, 1) -#define ADF_GEN4_PM_DEFAULT_IDLE_FILTER (0x0) +#define ADF_GEN4_PM_DEFAULT_IDLE_FILTER (0x6) #define ADF_GEN4_PM_MAX_IDLE_FILTER (0x7) #define ADF_GEN4_PM_DEFAULT_IDLE_SUPPORT (0x1) diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_timer.c b/drivers/crypto/intel/qat/qat_common/adf_gen4_timer.c new file mode 100644 index 000000000000..646c57922fcd --- /dev/null +++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_timer.c @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2023 Intel Corporation */ + +#include <linux/container_of.h> +#include <linux/dev_printk.h> +#include <linux/export.h> +#include <linux/jiffies.h> +#include <linux/ktime.h> +#include <linux/slab.h> +#include <linux/workqueue.h> + +#include "adf_accel_devices.h" +#include "adf_common_drv.h" +#include "adf_gen4_timer.h" + +#define ADF_GEN4_TIMER_PERIOD_MS 200 + +/* This periodic update is used to trigger HB, RL & TL fw events */ +static void work_handler(struct work_struct *work) +{ + struct adf_accel_dev *accel_dev; + struct adf_timer *timer_ctx; + u32 time_periods; + + timer_ctx = container_of(to_delayed_work(work), struct adf_timer, work_ctx); + accel_dev = timer_ctx->accel_dev; + + adf_misc_wq_queue_delayed_work(&timer_ctx->work_ctx, + msecs_to_jiffies(ADF_GEN4_TIMER_PERIOD_MS)); + + time_periods = div_u64(ktime_ms_delta(ktime_get_real(), timer_ctx->initial_ktime), + ADF_GEN4_TIMER_PERIOD_MS); + + if (adf_send_admin_tim_sync(accel_dev, time_periods)) + dev_err(&GET_DEV(accel_dev), "Failed to synchronize qat timer\n"); +} + +int adf_gen4_timer_start(struct adf_accel_dev *accel_dev) +{ + struct adf_timer *timer_ctx; + + timer_ctx = kzalloc(sizeof(*timer_ctx), GFP_KERNEL); + if (!timer_ctx) + return -ENOMEM; + + timer_ctx->accel_dev = accel_dev; + accel_dev->timer = timer_ctx; + timer_ctx->initial_ktime = ktime_get_real(); + + INIT_DELAYED_WORK(&timer_ctx->work_ctx, work_handler); + adf_misc_wq_queue_delayed_work(&timer_ctx->work_ctx, + msecs_to_jiffies(ADF_GEN4_TIMER_PERIOD_MS)); + + return 0; +} +EXPORT_SYMBOL_GPL(adf_gen4_timer_start); + +void adf_gen4_timer_stop(struct adf_accel_dev *accel_dev) +{ + struct adf_timer *timer_ctx = accel_dev->timer; + + if (!timer_ctx) + return; + + cancel_delayed_work_sync(&timer_ctx->work_ctx); + + kfree(timer_ctx); + accel_dev->timer = NULL; +} +EXPORT_SYMBOL_GPL(adf_gen4_timer_stop); diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_timer.h b/drivers/crypto/intel/qat/qat_common/adf_gen4_timer.h new file mode 100644 index 000000000000..66a709e7b358 --- /dev/null +++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_timer.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright(c) 2023 Intel Corporation */ + +#ifndef ADF_GEN4_TIMER_H_ +#define ADF_GEN4_TIMER_H_ + +#include <linux/ktime.h> +#include <linux/workqueue.h> + +struct adf_accel_dev; + +struct adf_timer { + struct adf_accel_dev *accel_dev; + struct delayed_work work_ctx; + ktime_t initial_ktime; +}; + +int adf_gen4_timer_start(struct adf_accel_dev *accel_dev); +void adf_gen4_timer_stop(struct adf_accel_dev *accel_dev); + +#endif /* ADF_GEN4_TIMER_H_ */ diff --git a/drivers/crypto/intel/qat/qat_common/adf_heartbeat.c b/drivers/crypto/intel/qat/qat_common/adf_heartbeat.c new file mode 100644 index 000000000000..beef9a5f6c75 --- /dev/null +++ b/drivers/crypto/intel/qat/qat_common/adf_heartbeat.c @@ -0,0 +1,336 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2023 Intel Corporation */ + +#include <linux/dev_printk.h> +#include <linux/dma-mapping.h> +#include <linux/export.h> +#include <linux/kernel.h> +#include <linux/kstrtox.h> +#include <linux/overflow.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/types.h> +#include <asm/errno.h> +#include "adf_accel_devices.h" +#include "adf_cfg.h" +#include "adf_cfg_strings.h" +#include "adf_clock.h" +#include "adf_common_drv.h" +#include "adf_heartbeat.h" +#include "adf_transport_internal.h" +#include "icp_qat_fw_init_admin.h" + +#define ADF_HB_EMPTY_SIG 0xA5A5A5A5 + +/* Heartbeat counter pair */ +struct hb_cnt_pair { + __u16 resp_heartbeat_cnt; + __u16 req_heartbeat_cnt; +}; + +static int adf_hb_check_polling_freq(struct adf_accel_dev *accel_dev) +{ + u64 curr_time = adf_clock_get_current_time(); + u64 polling_time = curr_time - accel_dev->heartbeat->last_hb_check_time; + + if (polling_time < accel_dev->heartbeat->hb_timer) { + dev_warn(&GET_DEV(accel_dev), + "HB polling too frequent. Configured HB timer %d ms\n", + accel_dev->heartbeat->hb_timer); + return -EINVAL; + } + + accel_dev->heartbeat->last_hb_check_time = curr_time; + return 0; +} + +/** + * validate_hb_ctrs_cnt() - checks if the number of heartbeat counters should + * be updated by one to support the currently loaded firmware. + * @accel_dev: Pointer to acceleration device. + * + * Return: + * * true - hb_ctrs must increased by ADF_NUM_PKE_STRAND + * * false - no changes needed + */ +static bool validate_hb_ctrs_cnt(struct adf_accel_dev *accel_dev) +{ + const size_t hb_ctrs = accel_dev->hw_device->num_hb_ctrs; + const size_t max_aes = accel_dev->hw_device->num_engines; + const size_t hb_struct_size = sizeof(struct hb_cnt_pair); + const size_t exp_diff_size = array3_size(ADF_NUM_PKE_STRAND, max_aes, + hb_struct_size); + const size_t dev_ctrs = size_mul(max_aes, hb_ctrs); + const size_t stats_size = size_mul(dev_ctrs, hb_struct_size); + const u32 exp_diff_cnt = exp_diff_size / sizeof(u32); + const u32 stats_el_cnt = stats_size / sizeof(u32); + struct hb_cnt_pair *hb_stats = accel_dev->heartbeat->dma.virt_addr; + const u32 *mem_to_chk = (u32 *)(hb_stats + dev_ctrs); + u32 el_diff_cnt = 0; + int i; + + /* count how many bytes are different from pattern */ + for (i = 0; i < stats_el_cnt; i++) { + if (mem_to_chk[i] == ADF_HB_EMPTY_SIG) + break; + + el_diff_cnt++; + } + + return el_diff_cnt && el_diff_cnt == exp_diff_cnt; +} + +void adf_heartbeat_check_ctrs(struct adf_accel_dev *accel_dev) +{ + struct hb_cnt_pair *hb_stats = accel_dev->heartbeat->dma.virt_addr; + const size_t hb_ctrs = accel_dev->hw_device->num_hb_ctrs; + const size_t max_aes = accel_dev->hw_device->num_engines; + const size_t dev_ctrs = size_mul(max_aes, hb_ctrs); + const size_t stats_size = size_mul(dev_ctrs, sizeof(struct hb_cnt_pair)); + const size_t mem_items_to_fill = size_mul(stats_size, 2) / sizeof(u32); + + /* fill hb stats memory with pattern */ + memset32((uint32_t *)hb_stats, ADF_HB_EMPTY_SIG, mem_items_to_fill); + accel_dev->heartbeat->ctrs_cnt_checked = false; +} +EXPORT_SYMBOL_GPL(adf_heartbeat_check_ctrs); + +static int get_timer_ticks(struct adf_accel_dev *accel_dev, unsigned int *value) +{ + char timer_str[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { }; + u32 timer_ms = ADF_CFG_HB_TIMER_DEFAULT_MS; + int cfg_read_status; + u32 ticks; + int ret; + + cfg_read_status = adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, + ADF_HEARTBEAT_TIMER, timer_str); + if (cfg_read_status == 0) { + if (kstrtouint(timer_str, 10, &timer_ms)) + dev_dbg(&GET_DEV(accel_dev), + "kstrtouint failed to parse the %s, param value", + ADF_HEARTBEAT_TIMER); + } + + if (timer_ms < ADF_CFG_HB_TIMER_MIN_MS) { + dev_err(&GET_DEV(accel_dev), "Timer cannot be less than %u\n", + ADF_CFG_HB_TIMER_MIN_MS); + return -EINVAL; + } + + /* + * On 4xxx devices adf_timer is responsible for HB updates and + * its period is fixed to 200ms + */ + if (accel_dev->timer) + timer_ms = ADF_CFG_HB_TIMER_MIN_MS; + + ret = adf_heartbeat_ms_to_ticks(accel_dev, timer_ms, &ticks); + if (ret) + return ret; + + adf_heartbeat_save_cfg_param(accel_dev, timer_ms); + + accel_dev->heartbeat->hb_timer = timer_ms; + *value = ticks; + + return 0; +} + +static int check_ae(struct hb_cnt_pair *curr, struct hb_cnt_pair *prev, + u16 *count, const size_t hb_ctrs) +{ + size_t thr; + + /* loop through all threads in AE */ + for (thr = 0; thr < hb_ctrs; thr++) { + u16 req = curr[thr].req_heartbeat_cnt; + u16 resp = curr[thr].resp_heartbeat_cnt; + u16 last = prev[thr].resp_heartbeat_cnt; + + if ((thr == ADF_AE_ADMIN_THREAD || req != resp) && resp == last) { + u16 retry = ++count[thr]; + + if (retry >= ADF_CFG_HB_COUNT_THRESHOLD) + return -EIO; + + } else { + count[thr] = 0; + } + } + return 0; +} + +static int adf_hb_get_status(struct adf_accel_dev *accel_dev) +{ + struct adf_hw_device_data *hw_device = accel_dev->hw_device; + struct hb_cnt_pair *live_stats, *last_stats, *curr_stats; + const size_t hb_ctrs = hw_device->num_hb_ctrs; + const unsigned long ae_mask = hw_device->ae_mask; + const size_t max_aes = hw_device->num_engines; + const size_t dev_ctrs = size_mul(max_aes, hb_ctrs); + const size_t stats_size = size_mul(dev_ctrs, sizeof(*curr_stats)); + struct hb_cnt_pair *ae_curr_p, *ae_prev_p; + u16 *count_fails, *ae_count_p; + size_t ae_offset; + size_t ae = 0; + int ret = 0; + + if (!accel_dev->heartbeat->ctrs_cnt_checked) { + if (validate_hb_ctrs_cnt(accel_dev)) + hw_device->num_hb_ctrs += ADF_NUM_PKE_STRAND; + + accel_dev->heartbeat->ctrs_cnt_checked = true; + } + + live_stats = accel_dev->heartbeat->dma.virt_addr; + last_stats = live_stats + dev_ctrs; + count_fails = (u16 *)(last_stats + dev_ctrs); + + curr_stats = kmemdup(live_stats, stats_size, GFP_KERNEL); + if (!curr_stats) + return -ENOMEM; + + /* loop through active AEs */ + for_each_set_bit(ae, &ae_mask, max_aes) { + ae_offset = size_mul(ae, hb_ctrs); + ae_curr_p = curr_stats + ae_offset; + ae_prev_p = last_stats + ae_offset; + ae_count_p = count_fails + ae_offset; + + ret = check_ae(ae_curr_p, ae_prev_p, ae_count_p, hb_ctrs); + if (ret) + break; + } + + /* Copy current stats for the next iteration */ + memcpy(last_stats, curr_stats, stats_size); + kfree(curr_stats); + + return ret; +} + +void adf_heartbeat_status(struct adf_accel_dev *accel_dev, + enum adf_device_heartbeat_status *hb_status) +{ + struct adf_heartbeat *hb; + + if (!adf_dev_started(accel_dev) || + test_bit(ADF_STATUS_RESTARTING, &accel_dev->status)) { + *hb_status = HB_DEV_UNRESPONSIVE; + return; + } + + if (adf_hb_check_polling_freq(accel_dev) == -EINVAL) { + *hb_status = HB_DEV_UNSUPPORTED; + return; + } + + hb = accel_dev->heartbeat; + hb->hb_sent_counter++; + + if (adf_hb_get_status(accel_dev)) { + dev_err(&GET_DEV(accel_dev), + "Heartbeat ERROR: QAT is not responding.\n"); + *hb_status = HB_DEV_UNRESPONSIVE; + hb->hb_failed_counter++; + return; + } + + *hb_status = HB_DEV_ALIVE; +} + +int adf_heartbeat_ms_to_ticks(struct adf_accel_dev *accel_dev, unsigned int time_ms, + u32 *value) +{ + struct adf_hw_device_data *hw_data = accel_dev->hw_device; + u32 clk_per_sec; + + /* HB clock may be different than AE clock */ + if (!hw_data->get_hb_clock) + return -EINVAL; + + clk_per_sec = hw_data->get_hb_clock(hw_data); + *value = time_ms * (clk_per_sec / MSEC_PER_SEC); + + return 0; +} + +int adf_heartbeat_save_cfg_param(struct adf_accel_dev *accel_dev, + unsigned int timer_ms) +{ + char timer_str[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + + snprintf(timer_str, sizeof(timer_str), "%u", timer_ms); + return adf_cfg_add_key_value_param(accel_dev, ADF_GENERAL_SEC, + ADF_HEARTBEAT_TIMER, timer_str, + ADF_STR); +} +EXPORT_SYMBOL_GPL(adf_heartbeat_save_cfg_param); + +int adf_heartbeat_init(struct adf_accel_dev *accel_dev) +{ + struct adf_heartbeat *hb; + + hb = kzalloc(sizeof(*hb), GFP_KERNEL); + if (!hb) + goto err_ret; + + hb->dma.virt_addr = dma_alloc_coherent(&GET_DEV(accel_dev), PAGE_SIZE, + &hb->dma.phy_addr, GFP_KERNEL); + if (!hb->dma.virt_addr) + goto err_free; + + /* + * Default set this flag as true to avoid unnecessary checks, + * it will be reset on platforms that need such a check + */ + hb->ctrs_cnt_checked = true; + accel_dev->heartbeat = hb; + + return 0; + +err_free: + kfree(hb); +err_ret: + return -ENOMEM; +} + +int adf_heartbeat_start(struct adf_accel_dev *accel_dev) +{ + unsigned int timer_ticks; + int ret; + + if (!accel_dev->heartbeat) { + dev_warn(&GET_DEV(accel_dev), "Heartbeat instance not found!"); + return -EFAULT; + } + + if (accel_dev->hw_device->check_hb_ctrs) + accel_dev->hw_device->check_hb_ctrs(accel_dev); + + ret = get_timer_ticks(accel_dev, &timer_ticks); + if (ret) + return ret; + + ret = adf_send_admin_hb_timer(accel_dev, timer_ticks); + if (ret) + dev_warn(&GET_DEV(accel_dev), "Heartbeat not supported!"); + + return ret; +} + +void adf_heartbeat_shutdown(struct adf_accel_dev *accel_dev) +{ + struct adf_heartbeat *hb = accel_dev->heartbeat; + + if (!hb) + return; + + if (hb->dma.virt_addr) + dma_free_coherent(&GET_DEV(accel_dev), PAGE_SIZE, + hb->dma.virt_addr, hb->dma.phy_addr); + + kfree(hb); + accel_dev->heartbeat = NULL; +} diff --git a/drivers/crypto/intel/qat/qat_common/adf_heartbeat.h b/drivers/crypto/intel/qat/qat_common/adf_heartbeat.h new file mode 100644 index 000000000000..b22e3cb29798 --- /dev/null +++ b/drivers/crypto/intel/qat/qat_common/adf_heartbeat.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright(c) 2023 Intel Corporation */ + +#ifndef ADF_HEARTBEAT_H_ +#define ADF_HEARTBEAT_H_ + +#include <linux/types.h> + +struct adf_accel_dev; +struct dentry; + +#define ADF_CFG_HB_TIMER_MIN_MS 200 +#define ADF_CFG_HB_TIMER_DEFAULT_MS 500 +#define ADF_CFG_HB_COUNT_THRESHOLD 3 + +enum adf_device_heartbeat_status { + HB_DEV_UNRESPONSIVE = 0, + HB_DEV_ALIVE, + HB_DEV_UNSUPPORTED, +}; + +struct adf_heartbeat { + unsigned int hb_sent_counter; + unsigned int hb_failed_counter; + unsigned int hb_timer; + u64 last_hb_check_time; + bool ctrs_cnt_checked; + struct hb_dma_addr { + dma_addr_t phy_addr; + void *virt_addr; + } dma; + struct { + struct dentry *base_dir; + struct dentry *status; + struct dentry *cfg; + struct dentry *sent; + struct dentry *failed; + } dbgfs; +}; + +#ifdef CONFIG_DEBUG_FS +int adf_heartbeat_init(struct adf_accel_dev *accel_dev); +int adf_heartbeat_start(struct adf_accel_dev *accel_dev); +void adf_heartbeat_shutdown(struct adf_accel_dev *accel_dev); + +int adf_heartbeat_ms_to_ticks(struct adf_accel_dev *accel_dev, unsigned int time_ms, + uint32_t *value); +int adf_heartbeat_save_cfg_param(struct adf_accel_dev *accel_dev, + unsigned int timer_ms); +void adf_heartbeat_status(struct adf_accel_dev *accel_dev, + enum adf_device_heartbeat_status *hb_status); +void adf_heartbeat_check_ctrs(struct adf_accel_dev *accel_dev); + +#else +static inline int adf_heartbeat_init(struct adf_accel_dev *accel_dev) +{ + return 0; +} + +static inline int adf_heartbeat_start(struct adf_accel_dev *accel_dev) +{ + return 0; +} + +static inline void adf_heartbeat_shutdown(struct adf_accel_dev *accel_dev) +{ +} + +static inline int adf_heartbeat_save_cfg_param(struct adf_accel_dev *accel_dev, + unsigned int timer_ms) +{ + return 0; +} + +static inline void adf_heartbeat_check_ctrs(struct adf_accel_dev *accel_dev) +{ +} +#endif +#endif /* ADF_HEARTBEAT_H_ */ diff --git a/drivers/crypto/intel/qat/qat_common/adf_heartbeat_dbgfs.c b/drivers/crypto/intel/qat/qat_common/adf_heartbeat_dbgfs.c new file mode 100644 index 000000000000..803cbfd838f0 --- /dev/null +++ b/drivers/crypto/intel/qat/qat_common/adf_heartbeat_dbgfs.c @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2023 Intel Corporation */ + +#include <linux/debugfs.h> +#include <linux/errno.h> +#include <linux/export.h> +#include <linux/fs.h> +#include <linux/kernel.h> +#include <linux/kstrtox.h> +#include <linux/types.h> +#include "adf_cfg.h" +#include "adf_common_drv.h" +#include "adf_heartbeat.h" +#include "adf_heartbeat_dbgfs.h" + +#define HB_OK 0 +#define HB_ERROR -1 +#define HB_STATUS_MAX_STRLEN 4 +#define HB_STATS_MAX_STRLEN 16 + +static ssize_t adf_hb_stats_read(struct file *file, char __user *user_buffer, + size_t count, loff_t *ppos) +{ + char buf[HB_STATS_MAX_STRLEN]; + unsigned int *value; + int len; + + if (*ppos > 0) + return 0; + + value = file->private_data; + len = scnprintf(buf, sizeof(buf), "%u\n", *value); + + return simple_read_from_buffer(user_buffer, count, ppos, buf, len + 1); +} + +static const struct file_operations adf_hb_stats_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = adf_hb_stats_read, +}; + +static ssize_t adf_hb_status_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + enum adf_device_heartbeat_status hb_status; + char ret_str[HB_STATUS_MAX_STRLEN]; + struct adf_accel_dev *accel_dev; + int ret_code; + size_t len; + + if (*ppos > 0) + return 0; + + accel_dev = file->private_data; + ret_code = HB_OK; + + adf_heartbeat_status(accel_dev, &hb_status); + + if (hb_status != HB_DEV_ALIVE) + ret_code = HB_ERROR; + + len = scnprintf(ret_str, sizeof(ret_str), "%d\n", ret_code); + + return simple_read_from_buffer(user_buf, count, ppos, ret_str, len + 1); +} + +static const struct file_operations adf_hb_status_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = adf_hb_status_read, +}; + +static ssize_t adf_hb_cfg_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + char timer_str[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + struct adf_accel_dev *accel_dev; + unsigned int timer_ms; + int len; + + if (*ppos > 0) + return 0; + + accel_dev = file->private_data; + timer_ms = accel_dev->heartbeat->hb_timer; + len = scnprintf(timer_str, sizeof(timer_str), "%u\n", timer_ms); + + return simple_read_from_buffer(user_buf, count, ppos, timer_str, + len + 1); +} + +static ssize_t adf_hb_cfg_write(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + char input_str[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { }; + struct adf_accel_dev *accel_dev; + int ret, written_chars; + unsigned int timer_ms; + u32 ticks; + + accel_dev = file->private_data; + timer_ms = ADF_CFG_HB_TIMER_DEFAULT_MS; + + /* last byte left as string termination */ + if (count > sizeof(input_str) - 1) + return -EINVAL; + + written_chars = simple_write_to_buffer(input_str, sizeof(input_str) - 1, + ppos, user_buf, count); + if (written_chars > 0) { + ret = kstrtouint(input_str, 10, &timer_ms); + if (ret) { + dev_err(&GET_DEV(accel_dev), + "heartbeat_cfg: Invalid value\n"); + return ret; + } + + if (timer_ms < ADF_CFG_HB_TIMER_MIN_MS) { + dev_err(&GET_DEV(accel_dev), + "heartbeat_cfg: Invalid value\n"); + return -EINVAL; + } + + /* + * On 4xxx devices adf_timer is responsible for HB updates and + * its period is fixed to 200ms + */ + if (accel_dev->timer) + timer_ms = ADF_CFG_HB_TIMER_MIN_MS; + + ret = adf_heartbeat_save_cfg_param(accel_dev, timer_ms); + if (ret) + return ret; + + ret = adf_heartbeat_ms_to_ticks(accel_dev, timer_ms, &ticks); + if (ret) + return ret; + + ret = adf_send_admin_hb_timer(accel_dev, ticks); + if (ret) + return ret; + + accel_dev->heartbeat->hb_timer = timer_ms; + } + + return written_chars; +} + +static const struct file_operations adf_hb_cfg_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = adf_hb_cfg_read, + .write = adf_hb_cfg_write, +}; + +void adf_heartbeat_dbgfs_add(struct adf_accel_dev *accel_dev) +{ + struct adf_heartbeat *hb = accel_dev->heartbeat; + + if (!hb) + return; + + hb->dbgfs.base_dir = debugfs_create_dir("heartbeat", accel_dev->debugfs_dir); + hb->dbgfs.status = debugfs_create_file("status", 0400, hb->dbgfs.base_dir, + accel_dev, &adf_hb_status_fops); + hb->dbgfs.sent = debugfs_create_file("queries_sent", 0400, hb->dbgfs.base_dir, + &hb->hb_sent_counter, &adf_hb_stats_fops); + hb->dbgfs.failed = debugfs_create_file("queries_failed", 0400, hb->dbgfs.base_dir, + &hb->hb_failed_counter, &adf_hb_stats_fops); + hb->dbgfs.cfg = debugfs_create_file("config", 0600, hb->dbgfs.base_dir, + accel_dev, &adf_hb_cfg_fops); +} +EXPORT_SYMBOL_GPL(adf_heartbeat_dbgfs_add); + +void adf_heartbeat_dbgfs_rm(struct adf_accel_dev *accel_dev) +{ + struct adf_heartbeat *hb = accel_dev->heartbeat; + + if (!hb) + return; + + debugfs_remove(hb->dbgfs.status); + hb->dbgfs.status = NULL; + debugfs_remove(hb->dbgfs.sent); + hb->dbgfs.sent = NULL; + debugfs_remove(hb->dbgfs.failed); + hb->dbgfs.failed = NULL; + debugfs_remove(hb->dbgfs.cfg); + hb->dbgfs.cfg = NULL; + debugfs_remove(hb->dbgfs.base_dir); + hb->dbgfs.base_dir = NULL; +} +EXPORT_SYMBOL_GPL(adf_heartbeat_dbgfs_rm); diff --git a/drivers/crypto/intel/qat/qat_common/adf_heartbeat_dbgfs.h b/drivers/crypto/intel/qat/qat_common/adf_heartbeat_dbgfs.h new file mode 100644 index 000000000000..84dd29ea6454 --- /dev/null +++ b/drivers/crypto/intel/qat/qat_common/adf_heartbeat_dbgfs.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright(c) 2023 Intel Corporation */ + +#ifndef ADF_HEARTBEAT_DBGFS_H_ +#define ADF_HEARTBEAT_DBGFS_H_ + +struct adf_accel_dev; + +void adf_heartbeat_dbgfs_add(struct adf_accel_dev *accel_dev); +void adf_heartbeat_dbgfs_rm(struct adf_accel_dev *accel_dev); + +#endif /* ADF_HEARTBEAT_DBGFS_H_ */ diff --git a/drivers/crypto/intel/qat/qat_common/adf_init.c b/drivers/crypto/intel/qat/qat_common/adf_init.c index 826179c98524..89001fe92e76 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_init.c +++ b/drivers/crypto/intel/qat/qat_common/adf_init.c @@ -8,6 +8,7 @@ #include "adf_cfg.h" #include "adf_common_drv.h" #include "adf_dbgfs.h" +#include "adf_heartbeat.h" static LIST_HEAD(service_table); static DEFINE_MUTEX(service_lock); @@ -129,6 +130,8 @@ static int adf_dev_init(struct adf_accel_dev *accel_dev) return -EFAULT; } + adf_heartbeat_init(accel_dev); + /* * Subservice initialisation is divided into two stages: init and start. * This is to facilitate any ordering dependencies between services @@ -163,6 +166,7 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev) struct adf_hw_device_data *hw_data = accel_dev->hw_device; struct service_hndl *service; struct list_head *list_itr; + int ret; set_bit(ADF_STATUS_STARTING, &accel_dev->status); @@ -177,6 +181,14 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev) return -EFAULT; } + if (hw_data->measure_clock) { + ret = hw_data->measure_clock(accel_dev); + if (ret) { + dev_err(&GET_DEV(accel_dev), "Failed measure device clock\n"); + return ret; + } + } + /* Set ssm watch dog timer */ if (hw_data->set_ssm_wdtimer) hw_data->set_ssm_wdtimer(accel_dev); @@ -187,6 +199,16 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev) return -EFAULT; } + if (hw_data->start_timer) { + ret = hw_data->start_timer(accel_dev); + if (ret) { + dev_err(&GET_DEV(accel_dev), "Failed to start internal sync timer\n"); + return ret; + } + } + + adf_heartbeat_start(accel_dev); + list_for_each(list_itr, &service_table) { service = list_entry(list_itr, struct service_hndl, list); if (service->event_hld(accel_dev, ADF_EVENT_START)) { @@ -235,6 +257,7 @@ static int adf_dev_start(struct adf_accel_dev *accel_dev) */ static void adf_dev_stop(struct adf_accel_dev *accel_dev) { + struct adf_hw_device_data *hw_data = accel_dev->hw_device; struct service_hndl *service; struct list_head *list_itr; bool wait = false; @@ -270,6 +293,9 @@ static void adf_dev_stop(struct adf_accel_dev *accel_dev) } } + if (hw_data->stop_timer) + hw_data->stop_timer(accel_dev); + if (wait) msleep(100); @@ -326,6 +352,8 @@ static void adf_dev_shutdown(struct adf_accel_dev *accel_dev) clear_bit(accel_dev->accel_id, service->init_status); } + adf_heartbeat_shutdown(accel_dev); + hw_data->disable_iov(accel_dev); if (test_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status)) { diff --git a/drivers/crypto/intel/qat/qat_common/adf_isr.c b/drivers/crypto/intel/qat/qat_common/adf_isr.c index ad9e135b8560..2aba194a7c29 100644 --- a/drivers/crypto/intel/qat/qat_common/adf_isr.c +++ b/drivers/crypto/intel/qat/qat_common/adf_isr.c @@ -380,3 +380,9 @@ bool adf_misc_wq_queue_work(struct work_struct *work) { return queue_work(adf_misc_wq, work); } + +bool adf_misc_wq_queue_delayed_work(struct delayed_work *work, + unsigned long delay) +{ + return queue_delayed_work(adf_misc_wq, work, delay); +} diff --git a/drivers/crypto/intel/qat/qat_common/icp_qat_fw_init_admin.h b/drivers/crypto/intel/qat/qat_common/icp_qat_fw_init_admin.h index 56cb827f93ea..3e968a4bcc9c 100644 --- a/drivers/crypto/intel/qat/qat_common/icp_qat_fw_init_admin.h +++ b/drivers/crypto/intel/qat/qat_common/icp_qat_fw_init_admin.h @@ -16,6 +16,8 @@ enum icp_qat_fw_init_admin_cmd_id { ICP_QAT_FW_HEARTBEAT_SYNC = 7, ICP_QAT_FW_HEARTBEAT_GET = 8, ICP_QAT_FW_COMP_CAPABILITY_GET = 9, + ICP_QAT_FW_HEARTBEAT_TIMER_SET = 13, + ICP_QAT_FW_TIMER_GET = 19, ICP_QAT_FW_PM_STATE_CONFIG = 128, }; @@ -37,6 +39,12 @@ struct icp_qat_fw_init_admin_req { __u16 ibuf_size_in_kb; __u16 resrvd3; }; + struct { + __u32 int_timer_ticks; + }; + struct { + __u32 heartbeat_ticks; + }; __u32 idle_filter; }; @@ -97,19 +105,6 @@ struct icp_qat_fw_init_admin_resp { }; } __packed; -#define ICP_QAT_FW_COMN_HEARTBEAT_OK 0 -#define ICP_QAT_FW_COMN_HEARTBEAT_BLOCKED 1 -#define ICP_QAT_FW_COMN_HEARTBEAT_FLAG_BITPOS 0 -#define ICP_QAT_FW_COMN_HEARTBEAT_FLAG_MASK 0x1 -#define ICP_QAT_FW_COMN_STATUS_RESRVD_FLD_MASK 0xFE -#define ICP_QAT_FW_COMN_HEARTBEAT_HDR_FLAG_GET(hdr_t) \ - ICP_QAT_FW_COMN_HEARTBEAT_FLAG_GET(hdr_t.flags) - -#define ICP_QAT_FW_COMN_HEARTBEAT_HDR_FLAG_SET(hdr_t, val) \ - ICP_QAT_FW_COMN_HEARTBEAT_FLAG_SET(hdr_t, val) +#define ICP_QAT_FW_SYNC ICP_QAT_FW_HEARTBEAT_SYNC -#define ICP_QAT_FW_COMN_HEARTBEAT_FLAG_GET(flags) \ - QAT_FIELD_GET(flags, \ - ICP_QAT_FW_COMN_HEARTBEAT_FLAG_BITPOS, \ - ICP_QAT_FW_COMN_HEARTBEAT_FLAG_MASK) #endif diff --git a/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h b/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h index a65059e56248..0c8883e2ccc6 100644 --- a/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h +++ b/drivers/crypto/intel/qat/qat_common/icp_qat_hw.h @@ -97,7 +97,10 @@ enum icp_qat_capabilities_mask { ICP_ACCEL_CAPABILITIES_SHA3_EXT = BIT(15), ICP_ACCEL_CAPABILITIES_AESGCM_SPC = BIT(16), ICP_ACCEL_CAPABILITIES_CHACHA_POLY = BIT(17), - /* Bits 18-21 are currently reserved */ + ICP_ACCEL_CAPABILITIES_SM2 = BIT(18), + ICP_ACCEL_CAPABILITIES_SM3 = BIT(19), + ICP_ACCEL_CAPABILITIES_SM4 = BIT(20), + /* Bit 21 is currently reserved */ ICP_ACCEL_CAPABILITIES_CNV_INTEGRITY = BIT(22), ICP_ACCEL_CAPABILITIES_CNV_INTEGRITY64 = BIT(23), ICP_ACCEL_CAPABILITIES_LZ4_COMPRESSION = BIT(24), diff --git a/drivers/crypto/intel/qat/qat_common/qat_compression.c b/drivers/crypto/intel/qat/qat_common/qat_compression.c index 3f1f35283266..7842a9f22178 100644 --- a/drivers/crypto/intel/qat/qat_common/qat_compression.c +++ b/drivers/crypto/intel/qat/qat_common/qat_compression.c @@ -234,8 +234,7 @@ static void qat_free_dc_data(struct adf_accel_dev *accel_dev) dma_unmap_single(dev, dc_data->ovf_buff_p, dc_data->ovf_buff_sz, DMA_FROM_DEVICE); - memset(dc_data->ovf_buff, 0, dc_data->ovf_buff_sz); - kfree(dc_data->ovf_buff); + kfree_sensitive(dc_data->ovf_buff); devm_kfree(dev, dc_data); accel_dev->dc_data = NULL; } diff --git a/drivers/crypto/intel/qat/qat_common/qat_uclo.c b/drivers/crypto/intel/qat/qat_common/qat_uclo.c index ce837bcc1cab..4bd150d1441a 100644 --- a/drivers/crypto/intel/qat/qat_common/qat_uclo.c +++ b/drivers/crypto/intel/qat/qat_common/qat_uclo.c @@ -11,7 +11,7 @@ #include "icp_qat_hal.h" #include "icp_qat_fw_loader_handle.h" -#define UWORD_CPYBUF_SIZE 1024 +#define UWORD_CPYBUF_SIZE 1024U #define INVLD_UWORD 0xffffffffffull #define PID_MINOR_REV 0xf #define PID_MAJOR_REV (0xf << 4) @@ -1986,10 +1986,7 @@ static void qat_uclo_wr_uimage_raw_page(struct icp_qat_fw_loader_handle *handle, uw_relative_addr = 0; words_num = encap_page->micro_words_num; while (words_num) { - if (words_num < UWORD_CPYBUF_SIZE) - cpylen = words_num; - else - cpylen = UWORD_CPYBUF_SIZE; + cpylen = min(words_num, UWORD_CPYBUF_SIZE); /* load the buffer */ for (i = 0; i < cpylen; i++) diff --git a/drivers/crypto/intel/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c b/drivers/crypto/intel/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c index 1ebe0b351fae..09551f949126 100644 --- a/drivers/crypto/intel/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c +++ b/drivers/crypto/intel/qat/qat_dh895xcc/adf_dh895xcc_hw_data.c @@ -7,6 +7,7 @@ #include <adf_gen2_hw_data.h> #include <adf_gen2_pfvf.h> #include "adf_dh895xcc_hw_data.h" +#include "adf_heartbeat.h" #include "icp_qat_hw.h" #define ADF_DH895XCC_VF_MSK 0xFFFFFFFF @@ -44,6 +45,14 @@ static u32 get_misc_bar_id(struct adf_hw_device_data *self) return ADF_DH895XCC_PMISC_BAR; } +static u32 get_ts_clock(struct adf_hw_device_data *self) +{ + /* + * Timestamp update interval is 16 AE clock ticks for dh895xcc. + */ + return self->clock_frequency / 16; +} + static u32 get_etr_bar_id(struct adf_hw_device_data *self) { return ADF_DH895XCC_ETR_BAR; @@ -237,6 +246,10 @@ void adf_init_hw_data_dh895xcc(struct adf_hw_device_data *hw_data) hw_data->reset_device = adf_reset_sbr; hw_data->disable_iov = adf_disable_sriov; hw_data->dev_config = adf_gen2_dev_config; + hw_data->clock_frequency = ADF_DH895X_AE_FREQ; + hw_data->get_hb_clock = get_ts_clock; + hw_data->num_hb_ctrs = ADF_NUM_HB_CNT_PER_AE; + hw_data->check_hb_ctrs = adf_heartbeat_check_ctrs; adf_gen2_init_pf_pfvf_ops(&hw_data->pfvf_ops); hw_data->pfvf_ops.enable_vf2pf_interrupts = enable_vf2pf_interrupts; diff --git a/drivers/crypto/intel/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h b/drivers/crypto/intel/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h index 7b674bbe4192..cd3a21985455 100644 --- a/drivers/crypto/intel/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h +++ b/drivers/crypto/intel/qat/qat_dh895xcc/adf_dh895xcc_hw_data.h @@ -3,6 +3,8 @@ #ifndef ADF_DH895x_HW_DATA_H_ #define ADF_DH895x_HW_DATA_H_ +#include <linux/units.h> + /* PCIe configuration space */ #define ADF_DH895XCC_SRAM_BAR 0 #define ADF_DH895XCC_PMISC_BAR 1 @@ -30,6 +32,9 @@ #define ADF_DH895XCC_AE2FUNC_MAP_GRP_A_NUM_REGS 96 #define ADF_DH895XCC_AE2FUNC_MAP_GRP_B_NUM_REGS 12 +/* Clocks frequency */ +#define ADF_DH895X_AE_FREQ (933 * HZ_PER_MHZ) + /* FW names */ #define ADF_DH895XCC_FW "qat_895xcc.bin" #define ADF_DH895XCC_MMP "qat_895xcc_mmp.bin" diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c index 4f6ca229ee5e..d5a32d71a3e9 100644 --- a/drivers/crypto/n2_core.c +++ b/drivers/crypto/n2_core.c @@ -10,7 +10,7 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> #include <linux/cpumask.h> #include <linux/slab.h> #include <linux/interrupt.h> diff --git a/drivers/crypto/omap-aes-gcm.c b/drivers/crypto/omap-aes-gcm.c index 9f937bdc53a7..c498950402e8 100644 --- a/drivers/crypto/omap-aes-gcm.c +++ b/drivers/crypto/omap-aes-gcm.c @@ -7,18 +7,21 @@ * Copyright (c) 2016 Texas Instruments Incorporated */ +#include <crypto/aes.h> +#include <crypto/engine.h> +#include <crypto/gcm.h> +#include <crypto/internal/aead.h> +#include <crypto/scatterwalk.h> +#include <crypto/skcipher.h> #include <linux/errno.h> -#include <linux/scatterlist.h> #include <linux/dma-mapping.h> #include <linux/dmaengine.h> -#include <linux/omap-dma.h> #include <linux/interrupt.h> +#include <linux/kernel.h> +#include <linux/omap-dma.h> #include <linux/pm_runtime.h> -#include <crypto/aes.h> -#include <crypto/gcm.h> -#include <crypto/scatterwalk.h> -#include <crypto/skcipher.h> -#include <crypto/internal/aead.h> +#include <linux/scatterlist.h> +#include <linux/string.h> #include "omap-crypto.h" #include "omap-aes.h" @@ -212,12 +215,10 @@ static int omap_aes_gcm_handle_queue(struct omap_aes_dev *dd, return 0; } -static int omap_aes_gcm_prepare_req(struct crypto_engine *engine, void *areq) +static int omap_aes_gcm_prepare_req(struct aead_request *req, + struct omap_aes_dev *dd) { - struct aead_request *req = container_of(areq, struct aead_request, - base); struct omap_aes_reqctx *rctx = aead_request_ctx(req); - struct omap_aes_dev *dd = rctx->dd; struct omap_aes_gcm_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); int err; @@ -356,17 +357,21 @@ int omap_aes_4106gcm_setauthsize(struct crypto_aead *parent, return crypto_rfc4106_check_authsize(authsize); } -static int omap_aes_gcm_crypt_req(struct crypto_engine *engine, void *areq) +int omap_aes_gcm_crypt_req(struct crypto_engine *engine, void *areq) { struct aead_request *req = container_of(areq, struct aead_request, base); struct omap_aes_reqctx *rctx = aead_request_ctx(req); struct omap_aes_dev *dd = rctx->dd; - int ret = 0; + int ret; if (!dd) return -ENODEV; + ret = omap_aes_gcm_prepare_req(req, dd); + if (ret) + return ret; + if (dd->in_sg_len) ret = omap_aes_crypt_dma_start(dd); else @@ -377,12 +382,6 @@ static int omap_aes_gcm_crypt_req(struct crypto_engine *engine, void *areq) int omap_aes_gcm_cra_init(struct crypto_aead *tfm) { - struct omap_aes_ctx *ctx = crypto_aead_ctx(tfm); - - ctx->enginectx.op.prepare_request = omap_aes_gcm_prepare_req; - ctx->enginectx.op.unprepare_request = NULL; - ctx->enginectx.op.do_one_request = omap_aes_gcm_crypt_req; - crypto_aead_set_reqsize(tfm, sizeof(struct omap_aes_reqctx)); return 0; diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c index 67a99c760bc4..ed83023dd77a 100644 --- a/drivers/crypto/omap-aes.c +++ b/drivers/crypto/omap-aes.c @@ -13,28 +13,26 @@ #define prn(num) pr_debug(#num "=%d\n", num) #define prx(num) pr_debug(#num "=%x\n", num) +#include <crypto/aes.h> +#include <crypto/gcm.h> +#include <crypto/internal/aead.h> +#include <crypto/internal/engine.h> +#include <crypto/internal/skcipher.h> +#include <crypto/scatterwalk.h> +#include <linux/dma-mapping.h> +#include <linux/dmaengine.h> #include <linux/err.h> -#include <linux/module.h> #include <linux/init.h> -#include <linux/errno.h> +#include <linux/interrupt.h> +#include <linux/io.h> #include <linux/kernel.h> -#include <linux/platform_device.h> -#include <linux/scatterlist.h> -#include <linux/dma-mapping.h> -#include <linux/dmaengine.h> -#include <linux/pm_runtime.h> +#include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_address.h> -#include <linux/io.h> -#include <linux/crypto.h> -#include <linux/interrupt.h> -#include <crypto/scatterwalk.h> -#include <crypto/aes.h> -#include <crypto/gcm.h> -#include <crypto/engine.h> -#include <crypto/internal/skcipher.h> -#include <crypto/internal/aead.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/scatterlist.h> +#include <linux/string.h> #include "omap-crypto.h" #include "omap-aes.h" @@ -426,20 +424,15 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd, return 0; } -static int omap_aes_prepare_req(struct crypto_engine *engine, - void *areq) +static int omap_aes_prepare_req(struct skcipher_request *req, + struct omap_aes_dev *dd) { - struct skcipher_request *req = container_of(areq, struct skcipher_request, base); struct omap_aes_ctx *ctx = crypto_skcipher_ctx( crypto_skcipher_reqtfm(req)); struct omap_aes_reqctx *rctx = skcipher_request_ctx(req); - struct omap_aes_dev *dd = rctx->dd; int ret; u16 flags; - if (!dd) - return -ENODEV; - /* assign new request to device */ dd->req = req; dd->total = req->cryptlen; @@ -491,7 +484,8 @@ static int omap_aes_crypt_req(struct crypto_engine *engine, if (!dd) return -ENODEV; - return omap_aes_crypt_dma_start(dd); + return omap_aes_prepare_req(req, dd) ?: + omap_aes_crypt_dma_start(dd); } static void omap_aes_copy_ivout(struct omap_aes_dev *dd, u8 *ivbuf) @@ -629,11 +623,6 @@ static int omap_aes_ctr_decrypt(struct skcipher_request *req) return omap_aes_crypt(req, FLAGS_CTR); } -static int omap_aes_prepare_req(struct crypto_engine *engine, - void *req); -static int omap_aes_crypt_req(struct crypto_engine *engine, - void *req); - static int omap_aes_init_tfm(struct crypto_skcipher *tfm) { const char *name = crypto_tfm_alg_name(&tfm->base); @@ -649,10 +638,6 @@ static int omap_aes_init_tfm(struct crypto_skcipher *tfm) crypto_skcipher_set_reqsize(tfm, sizeof(struct omap_aes_reqctx) + crypto_skcipher_reqsize(blk)); - ctx->enginectx.op.prepare_request = omap_aes_prepare_req; - ctx->enginectx.op.unprepare_request = NULL; - ctx->enginectx.op.do_one_request = omap_aes_crypt_req; - return 0; } @@ -668,68 +653,77 @@ static void omap_aes_exit_tfm(struct crypto_skcipher *tfm) /* ********************** ALGS ************************************ */ -static struct skcipher_alg algs_ecb_cbc[] = { +static struct skcipher_engine_alg algs_ecb_cbc[] = { { - .base.cra_name = "ecb(aes)", - .base.cra_driver_name = "ecb-aes-omap", - .base.cra_priority = 300, - .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | - CRYPTO_ALG_ASYNC | - CRYPTO_ALG_NEED_FALLBACK, - .base.cra_blocksize = AES_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct omap_aes_ctx), - .base.cra_module = THIS_MODULE, - - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .setkey = omap_aes_setkey, - .encrypt = omap_aes_ecb_encrypt, - .decrypt = omap_aes_ecb_decrypt, - .init = omap_aes_init_tfm, - .exit = omap_aes_exit_tfm, + .base = { + .base.cra_name = "ecb(aes)", + .base.cra_driver_name = "ecb-aes-omap", + .base.cra_priority = 300, + .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_NEED_FALLBACK, + .base.cra_blocksize = AES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct omap_aes_ctx), + .base.cra_module = THIS_MODULE, + + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .setkey = omap_aes_setkey, + .encrypt = omap_aes_ecb_encrypt, + .decrypt = omap_aes_ecb_decrypt, + .init = omap_aes_init_tfm, + .exit = omap_aes_exit_tfm, + }, + .op.do_one_request = omap_aes_crypt_req, }, { - .base.cra_name = "cbc(aes)", - .base.cra_driver_name = "cbc-aes-omap", - .base.cra_priority = 300, - .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | - CRYPTO_ALG_ASYNC | - CRYPTO_ALG_NEED_FALLBACK, - .base.cra_blocksize = AES_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct omap_aes_ctx), - .base.cra_module = THIS_MODULE, - - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = omap_aes_setkey, - .encrypt = omap_aes_cbc_encrypt, - .decrypt = omap_aes_cbc_decrypt, - .init = omap_aes_init_tfm, - .exit = omap_aes_exit_tfm, + .base = { + .base.cra_name = "cbc(aes)", + .base.cra_driver_name = "cbc-aes-omap", + .base.cra_priority = 300, + .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_NEED_FALLBACK, + .base.cra_blocksize = AES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct omap_aes_ctx), + .base.cra_module = THIS_MODULE, + + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = omap_aes_setkey, + .encrypt = omap_aes_cbc_encrypt, + .decrypt = omap_aes_cbc_decrypt, + .init = omap_aes_init_tfm, + .exit = omap_aes_exit_tfm, + }, + .op.do_one_request = omap_aes_crypt_req, } }; -static struct skcipher_alg algs_ctr[] = { +static struct skcipher_engine_alg algs_ctr[] = { { - .base.cra_name = "ctr(aes)", - .base.cra_driver_name = "ctr-aes-omap", - .base.cra_priority = 300, - .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | - CRYPTO_ALG_ASYNC | - CRYPTO_ALG_NEED_FALLBACK, - .base.cra_blocksize = 1, - .base.cra_ctxsize = sizeof(struct omap_aes_ctx), - .base.cra_module = THIS_MODULE, - - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = omap_aes_setkey, - .encrypt = omap_aes_ctr_encrypt, - .decrypt = omap_aes_ctr_decrypt, - .init = omap_aes_init_tfm, - .exit = omap_aes_exit_tfm, + .base = { + .base.cra_name = "ctr(aes)", + .base.cra_driver_name = "ctr-aes-omap", + .base.cra_priority = 300, + .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_NEED_FALLBACK, + .base.cra_blocksize = 1, + .base.cra_ctxsize = sizeof(struct omap_aes_ctx), + .base.cra_module = THIS_MODULE, + + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = omap_aes_setkey, + .encrypt = omap_aes_ctr_encrypt, + .decrypt = omap_aes_ctr_decrypt, + .init = omap_aes_init_tfm, + .exit = omap_aes_exit_tfm, + }, + .op.do_one_request = omap_aes_crypt_req, } }; @@ -740,46 +734,52 @@ static struct omap_aes_algs_info omap_aes_algs_info_ecb_cbc[] = { }, }; -static struct aead_alg algs_aead_gcm[] = { +static struct aead_engine_alg algs_aead_gcm[] = { { .base = { - .cra_name = "gcm(aes)", - .cra_driver_name = "gcm-aes-omap", - .cra_priority = 300, - .cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_KERN_DRIVER_ONLY, - .cra_blocksize = 1, - .cra_ctxsize = sizeof(struct omap_aes_gcm_ctx), - .cra_alignmask = 0xf, - .cra_module = THIS_MODULE, + .base = { + .cra_name = "gcm(aes)", + .cra_driver_name = "gcm-aes-omap", + .cra_priority = 300, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct omap_aes_gcm_ctx), + .cra_alignmask = 0xf, + .cra_module = THIS_MODULE, + }, + .init = omap_aes_gcm_cra_init, + .ivsize = GCM_AES_IV_SIZE, + .maxauthsize = AES_BLOCK_SIZE, + .setkey = omap_aes_gcm_setkey, + .setauthsize = omap_aes_gcm_setauthsize, + .encrypt = omap_aes_gcm_encrypt, + .decrypt = omap_aes_gcm_decrypt, }, - .init = omap_aes_gcm_cra_init, - .ivsize = GCM_AES_IV_SIZE, - .maxauthsize = AES_BLOCK_SIZE, - .setkey = omap_aes_gcm_setkey, - .setauthsize = omap_aes_gcm_setauthsize, - .encrypt = omap_aes_gcm_encrypt, - .decrypt = omap_aes_gcm_decrypt, + .op.do_one_request = omap_aes_gcm_crypt_req, }, { .base = { - .cra_name = "rfc4106(gcm(aes))", - .cra_driver_name = "rfc4106-gcm-aes-omap", - .cra_priority = 300, - .cra_flags = CRYPTO_ALG_ASYNC | - CRYPTO_ALG_KERN_DRIVER_ONLY, - .cra_blocksize = 1, - .cra_ctxsize = sizeof(struct omap_aes_gcm_ctx), - .cra_alignmask = 0xf, - .cra_module = THIS_MODULE, + .base = { + .cra_name = "rfc4106(gcm(aes))", + .cra_driver_name = "rfc4106-gcm-aes-omap", + .cra_priority = 300, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct omap_aes_gcm_ctx), + .cra_alignmask = 0xf, + .cra_module = THIS_MODULE, + }, + .init = omap_aes_gcm_cra_init, + .maxauthsize = AES_BLOCK_SIZE, + .ivsize = GCM_RFC4106_IV_SIZE, + .setkey = omap_aes_4106gcm_setkey, + .setauthsize = omap_aes_4106gcm_setauthsize, + .encrypt = omap_aes_4106gcm_encrypt, + .decrypt = omap_aes_4106gcm_decrypt, }, - .init = omap_aes_gcm_cra_init, - .maxauthsize = AES_BLOCK_SIZE, - .ivsize = GCM_RFC4106_IV_SIZE, - .setkey = omap_aes_4106gcm_setkey, - .setauthsize = omap_aes_4106gcm_setauthsize, - .encrypt = omap_aes_4106gcm_encrypt, - .decrypt = omap_aes_4106gcm_decrypt, + .op.do_one_request = omap_aes_gcm_crypt_req, }, }; @@ -1101,8 +1101,8 @@ static int omap_aes_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct omap_aes_dev *dd; - struct skcipher_alg *algp; - struct aead_alg *aalg; + struct skcipher_engine_alg *algp; + struct aead_engine_alg *aalg; struct resource res; int err = -ENOMEM, i, j, irq = -1; u32 reg; @@ -1195,9 +1195,9 @@ static int omap_aes_probe(struct platform_device *pdev) for (j = 0; j < dd->pdata->algs_info[i].size; j++) { algp = &dd->pdata->algs_info[i].algs_list[j]; - pr_debug("reg alg: %s\n", algp->base.cra_name); + pr_debug("reg alg: %s\n", algp->base.base.cra_name); - err = crypto_register_skcipher(algp); + err = crypto_engine_register_skcipher(algp); if (err) goto err_algs; @@ -1211,9 +1211,9 @@ static int omap_aes_probe(struct platform_device *pdev) for (i = 0; i < dd->pdata->aead_algs_info->size; i++) { aalg = &dd->pdata->aead_algs_info->algs_list[i]; - pr_debug("reg alg: %s\n", aalg->base.cra_name); + pr_debug("reg alg: %s\n", aalg->base.base.cra_name); - err = crypto_register_aead(aalg); + err = crypto_engine_register_aead(aalg); if (err) goto err_aead_algs; @@ -1231,12 +1231,12 @@ static int omap_aes_probe(struct platform_device *pdev) err_aead_algs: for (i = dd->pdata->aead_algs_info->registered - 1; i >= 0; i--) { aalg = &dd->pdata->aead_algs_info->algs_list[i]; - crypto_unregister_aead(aalg); + crypto_engine_unregister_aead(aalg); } err_algs: for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) - crypto_unregister_skcipher( + crypto_engine_unregister_skcipher( &dd->pdata->algs_info[i].algs_list[j]); err_engine: @@ -1258,7 +1258,7 @@ err_data: static int omap_aes_remove(struct platform_device *pdev) { struct omap_aes_dev *dd = platform_get_drvdata(pdev); - struct aead_alg *aalg; + struct aead_engine_alg *aalg; int i, j; spin_lock_bh(&list_lock); @@ -1267,14 +1267,14 @@ static int omap_aes_remove(struct platform_device *pdev) for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) { - crypto_unregister_skcipher( + crypto_engine_unregister_skcipher( &dd->pdata->algs_info[i].algs_list[j]); dd->pdata->algs_info[i].registered--; } for (i = dd->pdata->aead_algs_info->registered - 1; i >= 0; i--) { aalg = &dd->pdata->aead_algs_info->algs_list[i]; - crypto_unregister_aead(aalg); + crypto_engine_unregister_aead(aalg); dd->pdata->aead_algs_info->registered--; } diff --git a/drivers/crypto/omap-aes.h b/drivers/crypto/omap-aes.h index 23d073e87bb8..0f35c9164764 100644 --- a/drivers/crypto/omap-aes.h +++ b/drivers/crypto/omap-aes.h @@ -10,7 +10,6 @@ #define __OMAP_AES_H__ #include <crypto/aes.h> -#include <crypto/engine.h> #define DST_MAXBURST 4 #define DMA_MIN (DST_MAXBURST * sizeof(u32)) @@ -93,7 +92,6 @@ struct omap_aes_gcm_result { }; struct omap_aes_ctx { - struct crypto_engine_ctx enginectx; int keylen; u32 key[AES_KEYSIZE_256 / sizeof(u32)]; u8 nonce[4]; @@ -117,15 +115,15 @@ struct omap_aes_reqctx { #define OMAP_AES_CACHE_SIZE 0 struct omap_aes_algs_info { - struct skcipher_alg *algs_list; - unsigned int size; - unsigned int registered; + struct skcipher_engine_alg *algs_list; + unsigned int size; + unsigned int registered; }; struct omap_aes_aead_algs { - struct aead_alg *algs_list; - unsigned int size; - unsigned int registered; + struct aead_engine_alg *algs_list; + unsigned int size; + unsigned int registered; }; struct omap_aes_pdata { @@ -218,5 +216,6 @@ int omap_aes_crypt_dma_start(struct omap_aes_dev *dd); int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd); void omap_aes_gcm_dma_out_callback(void *data); void omap_aes_clear_copy_flags(struct omap_aes_dev *dd); +int omap_aes_gcm_crypt_req(struct crypto_engine *engine, void *areq); #endif diff --git a/drivers/crypto/omap-des.c b/drivers/crypto/omap-des.c index f783769ea110..089dd45eaedd 100644 --- a/drivers/crypto/omap-des.c +++ b/drivers/crypto/omap-des.c @@ -16,27 +16,23 @@ #define prx(num) do { } while (0) #endif +#include <crypto/engine.h> +#include <crypto/internal/des.h> +#include <crypto/internal/skcipher.h> +#include <crypto/scatterwalk.h> +#include <linux/dma-mapping.h> +#include <linux/dmaengine.h> #include <linux/err.h> -#include <linux/module.h> #include <linux/init.h> -#include <linux/errno.h> +#include <linux/interrupt.h> +#include <linux/io.h> #include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> #include <linux/platform_device.h> -#include <linux/scatterlist.h> -#include <linux/dma-mapping.h> -#include <linux/dmaengine.h> #include <linux/pm_runtime.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_address.h> -#include <linux/io.h> -#include <linux/crypto.h> -#include <linux/interrupt.h> -#include <crypto/scatterwalk.h> -#include <crypto/internal/des.h> -#include <crypto/internal/skcipher.h> -#include <crypto/algapi.h> -#include <crypto/engine.h> +#include <linux/scatterlist.h> +#include <linux/string.h> #include "omap-crypto.h" @@ -83,7 +79,6 @@ #define FLAGS_OUT_DATA_ST_SHIFT 10 struct omap_des_ctx { - struct crypto_engine_ctx enginectx; struct omap_des_dev *dd; int keylen; @@ -99,9 +94,9 @@ struct omap_des_reqctx { #define OMAP_DES_CACHE_SIZE 0 struct omap_des_algs_info { - struct skcipher_alg *algs_list; - unsigned int size; - unsigned int registered; + struct skcipher_engine_alg *algs_list; + unsigned int size; + unsigned int registered; }; struct omap_des_pdata { @@ -522,20 +517,15 @@ static int omap_des_handle_queue(struct omap_des_dev *dd, return 0; } -static int omap_des_prepare_req(struct crypto_engine *engine, - void *areq) +static int omap_des_prepare_req(struct skcipher_request *req, + struct omap_des_dev *dd) { - struct skcipher_request *req = container_of(areq, struct skcipher_request, base); struct omap_des_ctx *ctx = crypto_skcipher_ctx( crypto_skcipher_reqtfm(req)); - struct omap_des_dev *dd = omap_des_find_dev(ctx); struct omap_des_reqctx *rctx; int ret; u16 flags; - if (!dd) - return -ENODEV; - /* assign new request to device */ dd->req = req; dd->total = req->cryptlen; @@ -590,7 +580,8 @@ static int omap_des_crypt_req(struct crypto_engine *engine, if (!dd) return -ENODEV; - return omap_des_crypt_dma_start(dd); + return omap_des_prepare_req(req, dd) ?: + omap_des_crypt_dma_start(dd); } static void omap_des_done_task(unsigned long data) @@ -709,98 +700,99 @@ static int omap_des_cbc_decrypt(struct skcipher_request *req) return omap_des_crypt(req, FLAGS_CBC); } -static int omap_des_prepare_req(struct crypto_engine *engine, - void *areq); -static int omap_des_crypt_req(struct crypto_engine *engine, - void *areq); - static int omap_des_init_tfm(struct crypto_skcipher *tfm) { - struct omap_des_ctx *ctx = crypto_skcipher_ctx(tfm); - pr_debug("enter\n"); crypto_skcipher_set_reqsize(tfm, sizeof(struct omap_des_reqctx)); - ctx->enginectx.op.prepare_request = omap_des_prepare_req; - ctx->enginectx.op.unprepare_request = NULL; - ctx->enginectx.op.do_one_request = omap_des_crypt_req; - return 0; } /* ********************** ALGS ************************************ */ -static struct skcipher_alg algs_ecb_cbc[] = { +static struct skcipher_engine_alg algs_ecb_cbc[] = { { - .base.cra_name = "ecb(des)", - .base.cra_driver_name = "ecb-des-omap", - .base.cra_priority = 300, - .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | - CRYPTO_ALG_ASYNC, - .base.cra_blocksize = DES_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct omap_des_ctx), - .base.cra_module = THIS_MODULE, - - .min_keysize = DES_KEY_SIZE, - .max_keysize = DES_KEY_SIZE, - .setkey = omap_des_setkey, - .encrypt = omap_des_ecb_encrypt, - .decrypt = omap_des_ecb_decrypt, - .init = omap_des_init_tfm, + .base = { + .base.cra_name = "ecb(des)", + .base.cra_driver_name = "ecb-des-omap", + .base.cra_priority = 300, + .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_ASYNC, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct omap_des_ctx), + .base.cra_module = THIS_MODULE, + + .min_keysize = DES_KEY_SIZE, + .max_keysize = DES_KEY_SIZE, + .setkey = omap_des_setkey, + .encrypt = omap_des_ecb_encrypt, + .decrypt = omap_des_ecb_decrypt, + .init = omap_des_init_tfm, + }, + .op.do_one_request = omap_des_crypt_req, }, { - .base.cra_name = "cbc(des)", - .base.cra_driver_name = "cbc-des-omap", - .base.cra_priority = 300, - .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | - CRYPTO_ALG_ASYNC, - .base.cra_blocksize = DES_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct omap_des_ctx), - .base.cra_module = THIS_MODULE, - - .min_keysize = DES_KEY_SIZE, - .max_keysize = DES_KEY_SIZE, - .ivsize = DES_BLOCK_SIZE, - .setkey = omap_des_setkey, - .encrypt = omap_des_cbc_encrypt, - .decrypt = omap_des_cbc_decrypt, - .init = omap_des_init_tfm, + .base = { + .base.cra_name = "cbc(des)", + .base.cra_driver_name = "cbc-des-omap", + .base.cra_priority = 300, + .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_ASYNC, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct omap_des_ctx), + .base.cra_module = THIS_MODULE, + + .min_keysize = DES_KEY_SIZE, + .max_keysize = DES_KEY_SIZE, + .ivsize = DES_BLOCK_SIZE, + .setkey = omap_des_setkey, + .encrypt = omap_des_cbc_encrypt, + .decrypt = omap_des_cbc_decrypt, + .init = omap_des_init_tfm, + }, + .op.do_one_request = omap_des_crypt_req, }, { - .base.cra_name = "ecb(des3_ede)", - .base.cra_driver_name = "ecb-des3-omap", - .base.cra_priority = 300, - .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | - CRYPTO_ALG_ASYNC, - .base.cra_blocksize = DES3_EDE_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct omap_des_ctx), - .base.cra_module = THIS_MODULE, - - .min_keysize = DES3_EDE_KEY_SIZE, - .max_keysize = DES3_EDE_KEY_SIZE, - .setkey = omap_des3_setkey, - .encrypt = omap_des_ecb_encrypt, - .decrypt = omap_des_ecb_decrypt, - .init = omap_des_init_tfm, + .base = { + .base.cra_name = "ecb(des3_ede)", + .base.cra_driver_name = "ecb-des3-omap", + .base.cra_priority = 300, + .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_ASYNC, + .base.cra_blocksize = DES3_EDE_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct omap_des_ctx), + .base.cra_module = THIS_MODULE, + + .min_keysize = DES3_EDE_KEY_SIZE, + .max_keysize = DES3_EDE_KEY_SIZE, + .setkey = omap_des3_setkey, + .encrypt = omap_des_ecb_encrypt, + .decrypt = omap_des_ecb_decrypt, + .init = omap_des_init_tfm, + }, + .op.do_one_request = omap_des_crypt_req, }, { - .base.cra_name = "cbc(des3_ede)", - .base.cra_driver_name = "cbc-des3-omap", - .base.cra_priority = 300, - .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | - CRYPTO_ALG_ASYNC, - .base.cra_blocksize = DES3_EDE_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct omap_des_ctx), - .base.cra_module = THIS_MODULE, - - .min_keysize = DES3_EDE_KEY_SIZE, - .max_keysize = DES3_EDE_KEY_SIZE, - .ivsize = DES3_EDE_BLOCK_SIZE, - .setkey = omap_des3_setkey, - .encrypt = omap_des_cbc_encrypt, - .decrypt = omap_des_cbc_decrypt, - .init = omap_des_init_tfm, + .base = { + .base.cra_name = "cbc(des3_ede)", + .base.cra_driver_name = "cbc-des3-omap", + .base.cra_priority = 300, + .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_ASYNC, + .base.cra_blocksize = DES3_EDE_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct omap_des_ctx), + .base.cra_module = THIS_MODULE, + + .min_keysize = DES3_EDE_KEY_SIZE, + .max_keysize = DES3_EDE_KEY_SIZE, + .ivsize = DES3_EDE_BLOCK_SIZE, + .setkey = omap_des3_setkey, + .encrypt = omap_des_cbc_encrypt, + .decrypt = omap_des_cbc_decrypt, + .init = omap_des_init_tfm, + }, + .op.do_one_request = omap_des_crypt_req, } }; @@ -958,7 +950,7 @@ static int omap_des_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct omap_des_dev *dd; - struct skcipher_alg *algp; + struct skcipher_engine_alg *algp; struct resource *res; int err = -ENOMEM, i, j, irq = -1; u32 reg; @@ -971,18 +963,12 @@ static int omap_des_probe(struct platform_device *pdev) dd->dev = dev; platform_set_drvdata(pdev, dd); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "no MEM resource info\n"); - goto err_res; - } - err = (dev->of_node) ? omap_des_get_of(dd, pdev) : omap_des_get_pdev(dd, pdev); if (err) goto err_res; - dd->io_base = devm_ioremap_resource(dev, res); + dd->io_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(dd->io_base)) { err = PTR_ERR(dd->io_base); goto err_res; @@ -1052,9 +1038,9 @@ static int omap_des_probe(struct platform_device *pdev) for (j = 0; j < dd->pdata->algs_info[i].size; j++) { algp = &dd->pdata->algs_info[i].algs_list[j]; - pr_debug("reg alg: %s\n", algp->base.cra_name); + pr_debug("reg alg: %s\n", algp->base.base.cra_name); - err = crypto_register_skcipher(algp); + err = crypto_engine_register_skcipher(algp); if (err) goto err_algs; @@ -1067,7 +1053,7 @@ static int omap_des_probe(struct platform_device *pdev) err_algs: for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) - crypto_unregister_skcipher( + crypto_engine_unregister_skcipher( &dd->pdata->algs_info[i].algs_list[j]); err_engine: @@ -1097,7 +1083,7 @@ static int omap_des_remove(struct platform_device *pdev) for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) - crypto_unregister_skcipher( + crypto_engine_unregister_skcipher( &dd->pdata->algs_info[i].algs_list[j]); tasklet_kill(&dd->done_task); diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c index cbeda59c6b19..a6b4a0b3ace3 100644 --- a/drivers/crypto/omap-sham.c +++ b/drivers/crypto/omap-sham.c @@ -13,34 +13,30 @@ #define pr_fmt(fmt) "%s: " fmt, __func__ +#include <crypto/engine.h> +#include <crypto/hmac.h> +#include <crypto/internal/hash.h> +#include <crypto/scatterwalk.h> +#include <crypto/sha1.h> +#include <crypto/sha2.h> #include <linux/err.h> #include <linux/device.h> -#include <linux/module.h> +#include <linux/dma-mapping.h> +#include <linux/dmaengine.h> #include <linux/init.h> -#include <linux/errno.h> #include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/irq.h> #include <linux/io.h> -#include <linux/platform_device.h> -#include <linux/scatterlist.h> -#include <linux/dma-mapping.h> -#include <linux/dmaengine.h> -#include <linux/pm_runtime.h> +#include <linux/irq.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_address.h> #include <linux/of_irq.h> -#include <linux/delay.h> -#include <linux/crypto.h> -#include <crypto/scatterwalk.h> -#include <crypto/algapi.h> -#include <crypto/sha1.h> -#include <crypto/sha2.h> -#include <crypto/hash.h> -#include <crypto/hmac.h> -#include <crypto/internal/hash.h> -#include <crypto/engine.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/scatterlist.h> +#include <linux/slab.h> +#include <linux/string.h> #define MD5_DIGEST_SIZE 16 @@ -168,7 +164,6 @@ struct omap_sham_hmac_ctx { }; struct omap_sham_ctx { - struct crypto_engine_ctx enginectx; unsigned long flags; /* fallback stuff */ @@ -180,7 +175,7 @@ struct omap_sham_ctx { #define OMAP_SHAM_QUEUE_LENGTH 10 struct omap_sham_algs_info { - struct ahash_alg *algs_list; + struct ahash_engine_alg *algs_list; unsigned int size; unsigned int registered; }; @@ -1074,6 +1069,10 @@ static int omap_sham_hash_one_req(struct crypto_engine *engine, void *areq) dev_dbg(dd->dev, "hash-one: op: %u, total: %u, digcnt: %zd, final: %d", ctx->op, ctx->total, ctx->digcnt, final); + err = omap_sham_prepare_request(engine, areq); + if (err) + return err; + err = pm_runtime_resume_and_get(dd->dev); if (err < 0) { dev_err(dd->dev, "failed to get sync: %d\n", err); @@ -1349,10 +1348,6 @@ static int omap_sham_cra_init_alg(struct crypto_tfm *tfm, const char *alg_base) } - tctx->enginectx.op.do_one_request = omap_sham_hash_one_req; - tctx->enginectx.op.prepare_request = omap_sham_prepare_request; - tctx->enginectx.op.unprepare_request = NULL; - return 0; } @@ -1423,15 +1418,15 @@ static int omap_sham_import(struct ahash_request *req, const void *in) return 0; } -static struct ahash_alg algs_sha1_md5[] = { +static struct ahash_engine_alg algs_sha1_md5[] = { { - .init = omap_sham_init, - .update = omap_sham_update, - .final = omap_sham_final, - .finup = omap_sham_finup, - .digest = omap_sham_digest, - .halg.digestsize = SHA1_DIGEST_SIZE, - .halg.base = { + .base.init = omap_sham_init, + .base.update = omap_sham_update, + .base.final = omap_sham_final, + .base.finup = omap_sham_finup, + .base.digest = omap_sham_digest, + .base.halg.digestsize = SHA1_DIGEST_SIZE, + .base.halg.base = { .cra_name = "sha1", .cra_driver_name = "omap-sha1", .cra_priority = 400, @@ -1444,16 +1439,17 @@ static struct ahash_alg algs_sha1_md5[] = { .cra_module = THIS_MODULE, .cra_init = omap_sham_cra_init, .cra_exit = omap_sham_cra_exit, - } + }, + .op.do_one_request = omap_sham_hash_one_req, }, { - .init = omap_sham_init, - .update = omap_sham_update, - .final = omap_sham_final, - .finup = omap_sham_finup, - .digest = omap_sham_digest, - .halg.digestsize = MD5_DIGEST_SIZE, - .halg.base = { + .base.init = omap_sham_init, + .base.update = omap_sham_update, + .base.final = omap_sham_final, + .base.finup = omap_sham_finup, + .base.digest = omap_sham_digest, + .base.halg.digestsize = MD5_DIGEST_SIZE, + .base.halg.base = { .cra_name = "md5", .cra_driver_name = "omap-md5", .cra_priority = 400, @@ -1466,17 +1462,18 @@ static struct ahash_alg algs_sha1_md5[] = { .cra_module = THIS_MODULE, .cra_init = omap_sham_cra_init, .cra_exit = omap_sham_cra_exit, - } + }, + .op.do_one_request = omap_sham_hash_one_req, }, { - .init = omap_sham_init, - .update = omap_sham_update, - .final = omap_sham_final, - .finup = omap_sham_finup, - .digest = omap_sham_digest, - .setkey = omap_sham_setkey, - .halg.digestsize = SHA1_DIGEST_SIZE, - .halg.base = { + .base.init = omap_sham_init, + .base.update = omap_sham_update, + .base.final = omap_sham_final, + .base.finup = omap_sham_finup, + .base.digest = omap_sham_digest, + .base.setkey = omap_sham_setkey, + .base.halg.digestsize = SHA1_DIGEST_SIZE, + .base.halg.base = { .cra_name = "hmac(sha1)", .cra_driver_name = "omap-hmac-sha1", .cra_priority = 400, @@ -1490,17 +1487,18 @@ static struct ahash_alg algs_sha1_md5[] = { .cra_module = THIS_MODULE, .cra_init = omap_sham_cra_sha1_init, .cra_exit = omap_sham_cra_exit, - } + }, + .op.do_one_request = omap_sham_hash_one_req, }, { - .init = omap_sham_init, - .update = omap_sham_update, - .final = omap_sham_final, - .finup = omap_sham_finup, - .digest = omap_sham_digest, - .setkey = omap_sham_setkey, - .halg.digestsize = MD5_DIGEST_SIZE, - .halg.base = { + .base.init = omap_sham_init, + .base.update = omap_sham_update, + .base.final = omap_sham_final, + .base.finup = omap_sham_finup, + .base.digest = omap_sham_digest, + .base.setkey = omap_sham_setkey, + .base.halg.digestsize = MD5_DIGEST_SIZE, + .base.halg.base = { .cra_name = "hmac(md5)", .cra_driver_name = "omap-hmac-md5", .cra_priority = 400, @@ -1514,20 +1512,21 @@ static struct ahash_alg algs_sha1_md5[] = { .cra_module = THIS_MODULE, .cra_init = omap_sham_cra_md5_init, .cra_exit = omap_sham_cra_exit, - } + }, + .op.do_one_request = omap_sham_hash_one_req, } }; /* OMAP4 has some algs in addition to what OMAP2 has */ -static struct ahash_alg algs_sha224_sha256[] = { -{ - .init = omap_sham_init, - .update = omap_sham_update, - .final = omap_sham_final, - .finup = omap_sham_finup, - .digest = omap_sham_digest, - .halg.digestsize = SHA224_DIGEST_SIZE, - .halg.base = { +static struct ahash_engine_alg algs_sha224_sha256[] = { +{ + .base.init = omap_sham_init, + .base.update = omap_sham_update, + .base.final = omap_sham_final, + .base.finup = omap_sham_finup, + .base.digest = omap_sham_digest, + .base.halg.digestsize = SHA224_DIGEST_SIZE, + .base.halg.base = { .cra_name = "sha224", .cra_driver_name = "omap-sha224", .cra_priority = 400, @@ -1540,16 +1539,17 @@ static struct ahash_alg algs_sha224_sha256[] = { .cra_module = THIS_MODULE, .cra_init = omap_sham_cra_init, .cra_exit = omap_sham_cra_exit, - } + }, + .op.do_one_request = omap_sham_hash_one_req, }, { - .init = omap_sham_init, - .update = omap_sham_update, - .final = omap_sham_final, - .finup = omap_sham_finup, - .digest = omap_sham_digest, - .halg.digestsize = SHA256_DIGEST_SIZE, - .halg.base = { + .base.init = omap_sham_init, + .base.update = omap_sham_update, + .base.final = omap_sham_final, + .base.finup = omap_sham_finup, + .base.digest = omap_sham_digest, + .base.halg.digestsize = SHA256_DIGEST_SIZE, + .base.halg.base = { .cra_name = "sha256", .cra_driver_name = "omap-sha256", .cra_priority = 400, @@ -1562,17 +1562,18 @@ static struct ahash_alg algs_sha224_sha256[] = { .cra_module = THIS_MODULE, .cra_init = omap_sham_cra_init, .cra_exit = omap_sham_cra_exit, - } + }, + .op.do_one_request = omap_sham_hash_one_req, }, { - .init = omap_sham_init, - .update = omap_sham_update, - .final = omap_sham_final, - .finup = omap_sham_finup, - .digest = omap_sham_digest, - .setkey = omap_sham_setkey, - .halg.digestsize = SHA224_DIGEST_SIZE, - .halg.base = { + .base.init = omap_sham_init, + .base.update = omap_sham_update, + .base.final = omap_sham_final, + .base.finup = omap_sham_finup, + .base.digest = omap_sham_digest, + .base.setkey = omap_sham_setkey, + .base.halg.digestsize = SHA224_DIGEST_SIZE, + .base.halg.base = { .cra_name = "hmac(sha224)", .cra_driver_name = "omap-hmac-sha224", .cra_priority = 400, @@ -1586,17 +1587,18 @@ static struct ahash_alg algs_sha224_sha256[] = { .cra_module = THIS_MODULE, .cra_init = omap_sham_cra_sha224_init, .cra_exit = omap_sham_cra_exit, - } + }, + .op.do_one_request = omap_sham_hash_one_req, }, { - .init = omap_sham_init, - .update = omap_sham_update, - .final = omap_sham_final, - .finup = omap_sham_finup, - .digest = omap_sham_digest, - .setkey = omap_sham_setkey, - .halg.digestsize = SHA256_DIGEST_SIZE, - .halg.base = { + .base.init = omap_sham_init, + .base.update = omap_sham_update, + .base.final = omap_sham_final, + .base.finup = omap_sham_finup, + .base.digest = omap_sham_digest, + .base.setkey = omap_sham_setkey, + .base.halg.digestsize = SHA256_DIGEST_SIZE, + .base.halg.base = { .cra_name = "hmac(sha256)", .cra_driver_name = "omap-hmac-sha256", .cra_priority = 400, @@ -1610,19 +1612,20 @@ static struct ahash_alg algs_sha224_sha256[] = { .cra_module = THIS_MODULE, .cra_init = omap_sham_cra_sha256_init, .cra_exit = omap_sham_cra_exit, - } + }, + .op.do_one_request = omap_sham_hash_one_req, }, }; -static struct ahash_alg algs_sha384_sha512[] = { +static struct ahash_engine_alg algs_sha384_sha512[] = { { - .init = omap_sham_init, - .update = omap_sham_update, - .final = omap_sham_final, - .finup = omap_sham_finup, - .digest = omap_sham_digest, - .halg.digestsize = SHA384_DIGEST_SIZE, - .halg.base = { + .base.init = omap_sham_init, + .base.update = omap_sham_update, + .base.final = omap_sham_final, + .base.finup = omap_sham_finup, + .base.digest = omap_sham_digest, + .base.halg.digestsize = SHA384_DIGEST_SIZE, + .base.halg.base = { .cra_name = "sha384", .cra_driver_name = "omap-sha384", .cra_priority = 400, @@ -1635,16 +1638,17 @@ static struct ahash_alg algs_sha384_sha512[] = { .cra_module = THIS_MODULE, .cra_init = omap_sham_cra_init, .cra_exit = omap_sham_cra_exit, - } + }, + .op.do_one_request = omap_sham_hash_one_req, }, { - .init = omap_sham_init, - .update = omap_sham_update, - .final = omap_sham_final, - .finup = omap_sham_finup, - .digest = omap_sham_digest, - .halg.digestsize = SHA512_DIGEST_SIZE, - .halg.base = { + .base.init = omap_sham_init, + .base.update = omap_sham_update, + .base.final = omap_sham_final, + .base.finup = omap_sham_finup, + .base.digest = omap_sham_digest, + .base.halg.digestsize = SHA512_DIGEST_SIZE, + .base.halg.base = { .cra_name = "sha512", .cra_driver_name = "omap-sha512", .cra_priority = 400, @@ -1657,17 +1661,18 @@ static struct ahash_alg algs_sha384_sha512[] = { .cra_module = THIS_MODULE, .cra_init = omap_sham_cra_init, .cra_exit = omap_sham_cra_exit, - } + }, + .op.do_one_request = omap_sham_hash_one_req, }, { - .init = omap_sham_init, - .update = omap_sham_update, - .final = omap_sham_final, - .finup = omap_sham_finup, - .digest = omap_sham_digest, - .setkey = omap_sham_setkey, - .halg.digestsize = SHA384_DIGEST_SIZE, - .halg.base = { + .base.init = omap_sham_init, + .base.update = omap_sham_update, + .base.final = omap_sham_final, + .base.finup = omap_sham_finup, + .base.digest = omap_sham_digest, + .base.setkey = omap_sham_setkey, + .base.halg.digestsize = SHA384_DIGEST_SIZE, + .base.halg.base = { .cra_name = "hmac(sha384)", .cra_driver_name = "omap-hmac-sha384", .cra_priority = 400, @@ -1681,17 +1686,18 @@ static struct ahash_alg algs_sha384_sha512[] = { .cra_module = THIS_MODULE, .cra_init = omap_sham_cra_sha384_init, .cra_exit = omap_sham_cra_exit, - } + }, + .op.do_one_request = omap_sham_hash_one_req, }, { - .init = omap_sham_init, - .update = omap_sham_update, - .final = omap_sham_final, - .finup = omap_sham_finup, - .digest = omap_sham_digest, - .setkey = omap_sham_setkey, - .halg.digestsize = SHA512_DIGEST_SIZE, - .halg.base = { + .base.init = omap_sham_init, + .base.update = omap_sham_update, + .base.final = omap_sham_final, + .base.finup = omap_sham_finup, + .base.digest = omap_sham_digest, + .base.setkey = omap_sham_setkey, + .base.halg.digestsize = SHA512_DIGEST_SIZE, + .base.halg.base = { .cra_name = "hmac(sha512)", .cra_driver_name = "omap-hmac-sha512", .cra_priority = 400, @@ -1705,7 +1711,8 @@ static struct ahash_alg algs_sha384_sha512[] = { .cra_module = THIS_MODULE, .cra_init = omap_sham_cra_sha512_init, .cra_exit = omap_sham_cra_exit, - } + }, + .op.do_one_request = omap_sham_hash_one_req, }, }; @@ -2146,14 +2153,16 @@ static int omap_sham_probe(struct platform_device *pdev) break; for (j = 0; j < dd->pdata->algs_info[i].size; j++) { + struct ahash_engine_alg *ealg; struct ahash_alg *alg; - alg = &dd->pdata->algs_info[i].algs_list[j]; + ealg = &dd->pdata->algs_info[i].algs_list[j]; + alg = &ealg->base; alg->export = omap_sham_export; alg->import = omap_sham_import; alg->halg.statesize = sizeof(struct omap_sham_reqctx) + BUFLEN; - err = crypto_register_ahash(alg); + err = crypto_engine_register_ahash(ealg); if (err) goto err_algs; @@ -2172,7 +2181,7 @@ static int omap_sham_probe(struct platform_device *pdev) err_algs: for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) - crypto_unregister_ahash( + crypto_engine_unregister_ahash( &dd->pdata->algs_info[i].algs_list[j]); err_engine_start: crypto_engine_exit(dd->engine); @@ -2203,7 +2212,7 @@ static int omap_sham_remove(struct platform_device *pdev) spin_unlock_bh(&sham.lock); for (i = dd->pdata->algs_info_size - 1; i >= 0; i--) for (j = dd->pdata->algs_info[i].registered - 1; j >= 0; j--) { - crypto_unregister_ahash( + crypto_engine_unregister_ahash( &dd->pdata->algs_info[i].algs_list[j]); dd->pdata->algs_info[i].registered--; } diff --git a/drivers/crypto/qcom-rng.c b/drivers/crypto/qcom-rng.c index 72dd1a4ebac4..825a729f205e 100644 --- a/drivers/crypto/qcom-rng.c +++ b/drivers/crypto/qcom-rng.c @@ -173,13 +173,9 @@ static int qcom_rng_probe(struct platform_device *pdev) if (IS_ERR(rng->base)) return PTR_ERR(rng->base); - /* ACPI systems have clk already on, so skip clk_get */ - if (!has_acpi_companion(&pdev->dev)) { - rng->clk = devm_clk_get(&pdev->dev, "core"); - if (IS_ERR(rng->clk)) - return PTR_ERR(rng->clk); - } - + rng->clk = devm_clk_get_optional(&pdev->dev, "core"); + if (IS_ERR(rng->clk)) + return PTR_ERR(rng->clk); rng->skip_init = (unsigned long)device_get_match_data(&pdev->dev); diff --git a/drivers/crypto/rockchip/rk3288_crypto.c b/drivers/crypto/rockchip/rk3288_crypto.c index 9f6ba770a90a..77d5705a5d96 100644 --- a/drivers/crypto/rockchip/rk3288_crypto.c +++ b/drivers/crypto/rockchip/rk3288_crypto.c @@ -10,14 +10,21 @@ */ #include "rk3288_crypto.h" +#include <crypto/engine.h> +#include <crypto/internal/hash.h> +#include <crypto/internal/skcipher.h> +#include <linux/clk.h> #include <linux/dma-mapping.h> +#include <linux/debugfs.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/io.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/of.h> -#include <linux/of_device.h> -#include <linux/clk.h> -#include <linux/crypto.h> #include <linux/reset.h> +#include <linux/spinlock.h> static struct rockchip_ip rocklist = { .dev_list = LIST_HEAD_INIT(rocklist.dev_list), @@ -184,7 +191,6 @@ static struct rk_crypto_tmp *rk_cipher_algs[] = { &rk_ahash_md5, }; -#ifdef CONFIG_CRYPTO_DEV_ROCKCHIP_DEBUG static int rk_crypto_debugfs_show(struct seq_file *seq, void *v) { struct rk_crypto_info *dd; @@ -204,8 +210,8 @@ static int rk_crypto_debugfs_show(struct seq_file *seq, void *v) switch (rk_cipher_algs[i]->type) { case CRYPTO_ALG_TYPE_SKCIPHER: seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n", - rk_cipher_algs[i]->alg.skcipher.base.cra_driver_name, - rk_cipher_algs[i]->alg.skcipher.base.cra_name, + rk_cipher_algs[i]->alg.skcipher.base.base.cra_driver_name, + rk_cipher_algs[i]->alg.skcipher.base.base.cra_name, rk_cipher_algs[i]->stat_req, rk_cipher_algs[i]->stat_fb); seq_printf(seq, "\tfallback due to length: %lu\n", rk_cipher_algs[i]->stat_fb_len); @@ -216,8 +222,8 @@ static int rk_crypto_debugfs_show(struct seq_file *seq, void *v) break; case CRYPTO_ALG_TYPE_AHASH: seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n", - rk_cipher_algs[i]->alg.hash.halg.base.cra_driver_name, - rk_cipher_algs[i]->alg.hash.halg.base.cra_name, + rk_cipher_algs[i]->alg.hash.base.halg.base.cra_driver_name, + rk_cipher_algs[i]->alg.hash.base.halg.base.cra_name, rk_cipher_algs[i]->stat_req, rk_cipher_algs[i]->stat_fb); break; } @@ -226,17 +232,20 @@ static int rk_crypto_debugfs_show(struct seq_file *seq, void *v) } DEFINE_SHOW_ATTRIBUTE(rk_crypto_debugfs); -#endif static void register_debugfs(struct rk_crypto_info *crypto_info) { -#ifdef CONFIG_CRYPTO_DEV_ROCKCHIP_DEBUG + struct dentry *dbgfs_dir __maybe_unused; + struct dentry *dbgfs_stats __maybe_unused; + /* Ignore error of debugfs */ - rocklist.dbgfs_dir = debugfs_create_dir("rk3288_crypto", NULL); - rocklist.dbgfs_stats = debugfs_create_file("stats", 0444, - rocklist.dbgfs_dir, - &rocklist, - &rk_crypto_debugfs_fops); + dbgfs_dir = debugfs_create_dir("rk3288_crypto", NULL); + dbgfs_stats = debugfs_create_file("stats", 0444, dbgfs_dir, &rocklist, + &rk_crypto_debugfs_fops); + +#ifdef CONFIG_CRYPTO_DEV_ROCKCHIP_DEBUG + rocklist.dbgfs_dir = dbgfs_dir; + rocklist.dbgfs_stats = dbgfs_stats; #endif } @@ -250,15 +259,15 @@ static int rk_crypto_register(struct rk_crypto_info *crypto_info) switch (rk_cipher_algs[i]->type) { case CRYPTO_ALG_TYPE_SKCIPHER: dev_info(crypto_info->dev, "Register %s as %s\n", - rk_cipher_algs[i]->alg.skcipher.base.cra_name, - rk_cipher_algs[i]->alg.skcipher.base.cra_driver_name); - err = crypto_register_skcipher(&rk_cipher_algs[i]->alg.skcipher); + rk_cipher_algs[i]->alg.skcipher.base.base.cra_name, + rk_cipher_algs[i]->alg.skcipher.base.base.cra_driver_name); + err = crypto_engine_register_skcipher(&rk_cipher_algs[i]->alg.skcipher); break; case CRYPTO_ALG_TYPE_AHASH: dev_info(crypto_info->dev, "Register %s as %s\n", - rk_cipher_algs[i]->alg.hash.halg.base.cra_name, - rk_cipher_algs[i]->alg.hash.halg.base.cra_driver_name); - err = crypto_register_ahash(&rk_cipher_algs[i]->alg.hash); + rk_cipher_algs[i]->alg.hash.base.halg.base.cra_name, + rk_cipher_algs[i]->alg.hash.base.halg.base.cra_driver_name); + err = crypto_engine_register_ahash(&rk_cipher_algs[i]->alg.hash); break; default: dev_err(crypto_info->dev, "unknown algorithm\n"); @@ -271,9 +280,9 @@ static int rk_crypto_register(struct rk_crypto_info *crypto_info) err_cipher_algs: for (k = 0; k < i; k++) { if (rk_cipher_algs[i]->type == CRYPTO_ALG_TYPE_SKCIPHER) - crypto_unregister_skcipher(&rk_cipher_algs[k]->alg.skcipher); + crypto_engine_unregister_skcipher(&rk_cipher_algs[k]->alg.skcipher); else - crypto_unregister_ahash(&rk_cipher_algs[i]->alg.hash); + crypto_engine_unregister_ahash(&rk_cipher_algs[i]->alg.hash); } return err; } @@ -284,9 +293,9 @@ static void rk_crypto_unregister(void) for (i = 0; i < ARRAY_SIZE(rk_cipher_algs); i++) { if (rk_cipher_algs[i]->type == CRYPTO_ALG_TYPE_SKCIPHER) - crypto_unregister_skcipher(&rk_cipher_algs[i]->alg.skcipher); + crypto_engine_unregister_skcipher(&rk_cipher_algs[i]->alg.skcipher); else - crypto_unregister_ahash(&rk_cipher_algs[i]->alg.hash); + crypto_engine_unregister_ahash(&rk_cipher_algs[i]->alg.hash); } } diff --git a/drivers/crypto/rockchip/rk3288_crypto.h b/drivers/crypto/rockchip/rk3288_crypto.h index b2695258cade..3aa03cbfb6be 100644 --- a/drivers/crypto/rockchip/rk3288_crypto.h +++ b/drivers/crypto/rockchip/rk3288_crypto.h @@ -3,21 +3,18 @@ #define __RK3288_CRYPTO_H__ #include <crypto/aes.h> -#include <crypto/internal/des.h> -#include <crypto/algapi.h> -#include <linux/dma-mapping.h> -#include <linux/interrupt.h> -#include <linux/debugfs.h> -#include <linux/delay.h> -#include <linux/pm_runtime.h> -#include <linux/scatterlist.h> #include <crypto/engine.h> +#include <crypto/internal/des.h> #include <crypto/internal/hash.h> #include <crypto/internal/skcipher.h> - #include <crypto/md5.h> #include <crypto/sha1.h> #include <crypto/sha2.h> +#include <linux/dma-mapping.h> +#include <linux/interrupt.h> +#include <linux/pm_runtime.h> +#include <linux/scatterlist.h> +#include <linux/types.h> #define _SBF(v, f) ((v) << (f)) @@ -231,7 +228,6 @@ struct rk_crypto_info { /* the private variable of hash */ struct rk_ahash_ctx { - struct crypto_engine_ctx enginectx; /* for fallback */ struct crypto_ahash *fallback_tfm; }; @@ -246,7 +242,6 @@ struct rk_ahash_rctx { /* the private variable of cipher */ struct rk_cipher_ctx { - struct crypto_engine_ctx enginectx; unsigned int keylen; u8 key[AES_MAX_KEY_SIZE]; u8 iv[AES_BLOCK_SIZE]; @@ -264,8 +259,8 @@ struct rk_crypto_tmp { u32 type; struct rk_crypto_info *dev; union { - struct skcipher_alg skcipher; - struct ahash_alg hash; + struct skcipher_engine_alg skcipher; + struct ahash_engine_alg hash; } alg; unsigned long stat_req; unsigned long stat_fb; diff --git a/drivers/crypto/rockchip/rk3288_crypto_ahash.c b/drivers/crypto/rockchip/rk3288_crypto_ahash.c index a78ff3dcd0b1..8c143180645e 100644 --- a/drivers/crypto/rockchip/rk3288_crypto_ahash.c +++ b/drivers/crypto/rockchip/rk3288_crypto_ahash.c @@ -8,9 +8,15 @@ * * Some ideas are from marvell/cesa.c and s5p-sss.c driver. */ -#include <linux/device.h> + #include <asm/unaligned.h> +#include <crypto/internal/hash.h> +#include <linux/device.h> +#include <linux/err.h> #include <linux/iopoll.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/string.h> #include "rk3288_crypto.h" /* @@ -40,8 +46,8 @@ static int rk_ahash_digest_fb(struct ahash_request *areq) struct rk_ahash_rctx *rctx = ahash_request_ctx(areq); struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); struct rk_ahash_ctx *tfmctx = crypto_ahash_ctx(tfm); - struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg); - struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.hash); + struct ahash_alg *alg = crypto_ahash_alg(tfm); + struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.hash.base); algt->stat_fb++; @@ -240,14 +246,13 @@ static int rk_hash_prepare(struct crypto_engine *engine, void *breq) return 0; } -static int rk_hash_unprepare(struct crypto_engine *engine, void *breq) +static void rk_hash_unprepare(struct crypto_engine *engine, void *breq) { struct ahash_request *areq = container_of(breq, struct ahash_request, base); struct rk_ahash_rctx *rctx = ahash_request_ctx(areq); struct rk_crypto_info *rkc = rctx->dev; dma_unmap_sg(rkc->dev, areq->src, rctx->nrsg, DMA_TO_DEVICE); - return 0; } static int rk_hash_run(struct crypto_engine *engine, void *breq) @@ -255,11 +260,11 @@ static int rk_hash_run(struct crypto_engine *engine, void *breq) struct ahash_request *areq = container_of(breq, struct ahash_request, base); struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq); struct rk_ahash_rctx *rctx = ahash_request_ctx(areq); - struct ahash_alg *alg = __crypto_ahash_alg(tfm->base.__crt_alg); - struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.hash); + struct ahash_alg *alg = crypto_ahash_alg(tfm); + struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.hash.base); struct scatterlist *sg = areq->src; struct rk_crypto_info *rkc = rctx->dev; - int err = 0; + int err; int i; u32 v; @@ -267,6 +272,10 @@ static int rk_hash_run(struct crypto_engine *engine, void *breq) if (err) return err; + err = rk_hash_prepare(engine, breq); + if (err) + goto theend; + rctx->mode = 0; algt->stat_req++; @@ -327,15 +336,17 @@ theend: crypto_finalize_hash_request(engine, breq, err); local_bh_enable(); + rk_hash_unprepare(engine, breq); + return 0; } -static int rk_cra_hash_init(struct crypto_tfm *tfm) +static int rk_hash_init_tfm(struct crypto_ahash *tfm) { - struct rk_ahash_ctx *tctx = crypto_tfm_ctx(tfm); - const char *alg_name = crypto_tfm_alg_name(tfm); - struct ahash_alg *alg = __crypto_ahash_alg(tfm->__crt_alg); - struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.hash); + struct rk_ahash_ctx *tctx = crypto_ahash_ctx(tfm); + const char *alg_name = crypto_ahash_alg_name(tfm); + struct ahash_alg *alg = crypto_ahash_alg(tfm); + struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.hash.base); /* for fallback */ tctx->fallback_tfm = crypto_alloc_ahash(alg_name, 0, @@ -345,27 +356,23 @@ static int rk_cra_hash_init(struct crypto_tfm *tfm) return PTR_ERR(tctx->fallback_tfm); } - crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), + crypto_ahash_set_reqsize(tfm, sizeof(struct rk_ahash_rctx) + crypto_ahash_reqsize(tctx->fallback_tfm)); - tctx->enginectx.op.do_one_request = rk_hash_run; - tctx->enginectx.op.prepare_request = rk_hash_prepare; - tctx->enginectx.op.unprepare_request = rk_hash_unprepare; - return 0; } -static void rk_cra_hash_exit(struct crypto_tfm *tfm) +static void rk_hash_exit_tfm(struct crypto_ahash *tfm) { - struct rk_ahash_ctx *tctx = crypto_tfm_ctx(tfm); + struct rk_ahash_ctx *tctx = crypto_ahash_ctx(tfm); crypto_free_ahash(tctx->fallback_tfm); } struct rk_crypto_tmp rk_ahash_sha1 = { .type = CRYPTO_ALG_TYPE_AHASH, - .alg.hash = { + .alg.hash.base = { .init = rk_ahash_init, .update = rk_ahash_update, .final = rk_ahash_final, @@ -373,6 +380,8 @@ struct rk_crypto_tmp rk_ahash_sha1 = { .export = rk_ahash_export, .import = rk_ahash_import, .digest = rk_ahash_digest, + .init_tfm = rk_hash_init_tfm, + .exit_tfm = rk_hash_exit_tfm, .halg = { .digestsize = SHA1_DIGEST_SIZE, .statesize = sizeof(struct sha1_state), @@ -385,17 +394,18 @@ struct rk_crypto_tmp rk_ahash_sha1 = { .cra_blocksize = SHA1_BLOCK_SIZE, .cra_ctxsize = sizeof(struct rk_ahash_ctx), .cra_alignmask = 3, - .cra_init = rk_cra_hash_init, - .cra_exit = rk_cra_hash_exit, .cra_module = THIS_MODULE, } } - } + }, + .alg.hash.op = { + .do_one_request = rk_hash_run, + }, }; struct rk_crypto_tmp rk_ahash_sha256 = { .type = CRYPTO_ALG_TYPE_AHASH, - .alg.hash = { + .alg.hash.base = { .init = rk_ahash_init, .update = rk_ahash_update, .final = rk_ahash_final, @@ -403,6 +413,8 @@ struct rk_crypto_tmp rk_ahash_sha256 = { .export = rk_ahash_export, .import = rk_ahash_import, .digest = rk_ahash_digest, + .init_tfm = rk_hash_init_tfm, + .exit_tfm = rk_hash_exit_tfm, .halg = { .digestsize = SHA256_DIGEST_SIZE, .statesize = sizeof(struct sha256_state), @@ -415,17 +427,18 @@ struct rk_crypto_tmp rk_ahash_sha256 = { .cra_blocksize = SHA256_BLOCK_SIZE, .cra_ctxsize = sizeof(struct rk_ahash_ctx), .cra_alignmask = 3, - .cra_init = rk_cra_hash_init, - .cra_exit = rk_cra_hash_exit, .cra_module = THIS_MODULE, } } - } + }, + .alg.hash.op = { + .do_one_request = rk_hash_run, + }, }; struct rk_crypto_tmp rk_ahash_md5 = { .type = CRYPTO_ALG_TYPE_AHASH, - .alg.hash = { + .alg.hash.base = { .init = rk_ahash_init, .update = rk_ahash_update, .final = rk_ahash_final, @@ -433,6 +446,8 @@ struct rk_crypto_tmp rk_ahash_md5 = { .export = rk_ahash_export, .import = rk_ahash_import, .digest = rk_ahash_digest, + .init_tfm = rk_hash_init_tfm, + .exit_tfm = rk_hash_exit_tfm, .halg = { .digestsize = MD5_DIGEST_SIZE, .statesize = sizeof(struct md5_state), @@ -445,10 +460,11 @@ struct rk_crypto_tmp rk_ahash_md5 = { .cra_blocksize = SHA1_BLOCK_SIZE, .cra_ctxsize = sizeof(struct rk_ahash_ctx), .cra_alignmask = 3, - .cra_init = rk_cra_hash_init, - .cra_exit = rk_cra_hash_exit, .cra_module = THIS_MODULE, } } - } + }, + .alg.hash.op = { + .do_one_request = rk_hash_run, + }, }; diff --git a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c index 59069457582b..da95747d973f 100644 --- a/drivers/crypto/rockchip/rk3288_crypto_skcipher.c +++ b/drivers/crypto/rockchip/rk3288_crypto_skcipher.c @@ -8,8 +8,14 @@ * * Some ideas are from marvell-cesa.c and s5p-sss.c driver. */ -#include <linux/device.h> + +#include <crypto/engine.h> +#include <crypto/internal/skcipher.h> #include <crypto/scatterwalk.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/string.h> #include "rk3288_crypto.h" #define RK_CRYPTO_DEC BIT(0) @@ -18,7 +24,7 @@ static int rk_cipher_need_fallback(struct skcipher_request *req) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct skcipher_alg *alg = crypto_skcipher_alg(tfm); - struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.skcipher); + struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.skcipher.base); struct scatterlist *sgs, *sgd; unsigned int stodo, dtodo, len; unsigned int bs = crypto_skcipher_blocksize(tfm); @@ -65,7 +71,7 @@ static int rk_cipher_fallback(struct skcipher_request *areq) struct rk_cipher_ctx *op = crypto_skcipher_ctx(tfm); struct rk_cipher_rctx *rctx = skcipher_request_ctx(areq); struct skcipher_alg *alg = crypto_skcipher_alg(tfm); - struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.skcipher); + struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.skcipher.base); int err; algt->stat_fb++; @@ -305,7 +311,7 @@ static int rk_cipher_run(struct crypto_engine *engine, void *async_req) unsigned int len = areq->cryptlen; unsigned int todo; struct skcipher_alg *alg = crypto_skcipher_alg(tfm); - struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.skcipher); + struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.skcipher.base); struct rk_crypto_info *rkc = rctx->dev; err = pm_runtime_resume_and_get(rkc->dev); @@ -430,7 +436,7 @@ static int rk_cipher_tfm_init(struct crypto_skcipher *tfm) struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); const char *name = crypto_tfm_alg_name(&tfm->base); struct skcipher_alg *alg = crypto_skcipher_alg(tfm); - struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.skcipher); + struct rk_crypto_tmp *algt = container_of(alg, struct rk_crypto_tmp, alg.skcipher.base); ctx->fallback_tfm = crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); if (IS_ERR(ctx->fallback_tfm)) { @@ -442,8 +448,6 @@ static int rk_cipher_tfm_init(struct crypto_skcipher *tfm) tfm->reqsize = sizeof(struct rk_cipher_rctx) + crypto_skcipher_reqsize(ctx->fallback_tfm); - ctx->enginectx.op.do_one_request = rk_cipher_run; - return 0; } @@ -457,7 +461,7 @@ static void rk_cipher_tfm_exit(struct crypto_skcipher *tfm) struct rk_crypto_tmp rk_ecb_aes_alg = { .type = CRYPTO_ALG_TYPE_SKCIPHER, - .alg.skcipher = { + .alg.skcipher.base = { .base.cra_name = "ecb(aes)", .base.cra_driver_name = "ecb-aes-rk", .base.cra_priority = 300, @@ -474,12 +478,15 @@ struct rk_crypto_tmp rk_ecb_aes_alg = { .setkey = rk_aes_setkey, .encrypt = rk_aes_ecb_encrypt, .decrypt = rk_aes_ecb_decrypt, - } + }, + .alg.skcipher.op = { + .do_one_request = rk_cipher_run, + }, }; struct rk_crypto_tmp rk_cbc_aes_alg = { .type = CRYPTO_ALG_TYPE_SKCIPHER, - .alg.skcipher = { + .alg.skcipher.base = { .base.cra_name = "cbc(aes)", .base.cra_driver_name = "cbc-aes-rk", .base.cra_priority = 300, @@ -497,12 +504,15 @@ struct rk_crypto_tmp rk_cbc_aes_alg = { .setkey = rk_aes_setkey, .encrypt = rk_aes_cbc_encrypt, .decrypt = rk_aes_cbc_decrypt, - } + }, + .alg.skcipher.op = { + .do_one_request = rk_cipher_run, + }, }; struct rk_crypto_tmp rk_ecb_des_alg = { .type = CRYPTO_ALG_TYPE_SKCIPHER, - .alg.skcipher = { + .alg.skcipher.base = { .base.cra_name = "ecb(des)", .base.cra_driver_name = "ecb-des-rk", .base.cra_priority = 300, @@ -519,12 +529,15 @@ struct rk_crypto_tmp rk_ecb_des_alg = { .setkey = rk_des_setkey, .encrypt = rk_des_ecb_encrypt, .decrypt = rk_des_ecb_decrypt, - } + }, + .alg.skcipher.op = { + .do_one_request = rk_cipher_run, + }, }; struct rk_crypto_tmp rk_cbc_des_alg = { .type = CRYPTO_ALG_TYPE_SKCIPHER, - .alg.skcipher = { + .alg.skcipher.base = { .base.cra_name = "cbc(des)", .base.cra_driver_name = "cbc-des-rk", .base.cra_priority = 300, @@ -542,12 +555,15 @@ struct rk_crypto_tmp rk_cbc_des_alg = { .setkey = rk_des_setkey, .encrypt = rk_des_cbc_encrypt, .decrypt = rk_des_cbc_decrypt, - } + }, + .alg.skcipher.op = { + .do_one_request = rk_cipher_run, + }, }; struct rk_crypto_tmp rk_ecb_des3_ede_alg = { .type = CRYPTO_ALG_TYPE_SKCIPHER, - .alg.skcipher = { + .alg.skcipher.base = { .base.cra_name = "ecb(des3_ede)", .base.cra_driver_name = "ecb-des3-ede-rk", .base.cra_priority = 300, @@ -564,12 +580,15 @@ struct rk_crypto_tmp rk_ecb_des3_ede_alg = { .setkey = rk_tdes_setkey, .encrypt = rk_des3_ede_ecb_encrypt, .decrypt = rk_des3_ede_ecb_decrypt, - } + }, + .alg.skcipher.op = { + .do_one_request = rk_cipher_run, + }, }; struct rk_crypto_tmp rk_cbc_des3_ede_alg = { .type = CRYPTO_ALG_TYPE_SKCIPHER, - .alg.skcipher = { + .alg.skcipher.base = { .base.cra_name = "cbc(des3_ede)", .base.cra_driver_name = "cbc-des3-ede-rk", .base.cra_priority = 300, @@ -587,5 +606,8 @@ struct rk_crypto_tmp rk_cbc_des3_ede_alg = { .setkey = rk_tdes_setkey, .encrypt = rk_des3_ede_cbc_encrypt, .decrypt = rk_des3_ede_cbc_decrypt, - } + }, + .alg.skcipher.op = { + .do_one_request = rk_cipher_run, + }, }; diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c index 1c4d5fb05d69..fe8cf9ba8005 100644 --- a/drivers/crypto/s5p-sss.c +++ b/drivers/crypto/s5p-sss.c @@ -20,7 +20,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/scatterlist.h> diff --git a/drivers/crypto/sa2ul.c b/drivers/crypto/sa2ul.c index df5f9d675c57..6238d34f8db2 100644 --- a/drivers/crypto/sa2ul.c +++ b/drivers/crypto/sa2ul.c @@ -15,7 +15,8 @@ #include <linux/dmapool.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c index 4c799df3e883..62d93526920f 100644 --- a/drivers/crypto/sahara.c +++ b/drivers/crypto/sahara.c @@ -27,7 +27,6 @@ #include <linux/kthread.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/spinlock.h> diff --git a/drivers/crypto/starfive/Kconfig b/drivers/crypto/starfive/Kconfig index df745fcb09df..2cb192502c1b 100644 --- a/drivers/crypto/starfive/Kconfig +++ b/drivers/crypto/starfive/Kconfig @@ -12,6 +12,8 @@ config CRYPTO_DEV_JH7110 select CRYPTO_SHA512 select CRYPTO_SM3_GENERIC select CRYPTO_RSA + select CRYPTO_AES + select CRYPTO_CCM help Support for StarFive JH7110 crypto hardware acceleration engine. This module provides acceleration for public key algo, diff --git a/drivers/crypto/starfive/Makefile b/drivers/crypto/starfive/Makefile index 98b01d2f1ccf..8c137afe58ad 100644 --- a/drivers/crypto/starfive/Makefile +++ b/drivers/crypto/starfive/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_CRYPTO_DEV_JH7110) += jh7110-crypto.o -jh7110-crypto-objs := jh7110-cryp.o jh7110-hash.o jh7110-rsa.o +jh7110-crypto-objs := jh7110-cryp.o jh7110-hash.o jh7110-rsa.o jh7110-aes.o diff --git a/drivers/crypto/starfive/jh7110-aes.c b/drivers/crypto/starfive/jh7110-aes.c new file mode 100644 index 000000000000..9378e6682f0e --- /dev/null +++ b/drivers/crypto/starfive/jh7110-aes.c @@ -0,0 +1,1024 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * StarFive AES acceleration driver + * + * Copyright (c) 2022 StarFive Technology + */ + +#include <crypto/engine.h> +#include <crypto/gcm.h> +#include <crypto/internal/aead.h> +#include <crypto/internal/skcipher.h> +#include <crypto/scatterwalk.h> +#include "jh7110-cryp.h" +#include <linux/err.h> +#include <linux/iopoll.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/string.h> + +#define STARFIVE_AES_REGS_OFFSET 0x100 +#define STARFIVE_AES_AESDIO0R (STARFIVE_AES_REGS_OFFSET + 0x0) +#define STARFIVE_AES_KEY0 (STARFIVE_AES_REGS_OFFSET + 0x4) +#define STARFIVE_AES_KEY1 (STARFIVE_AES_REGS_OFFSET + 0x8) +#define STARFIVE_AES_KEY2 (STARFIVE_AES_REGS_OFFSET + 0xC) +#define STARFIVE_AES_KEY3 (STARFIVE_AES_REGS_OFFSET + 0x10) +#define STARFIVE_AES_KEY4 (STARFIVE_AES_REGS_OFFSET + 0x14) +#define STARFIVE_AES_KEY5 (STARFIVE_AES_REGS_OFFSET + 0x18) +#define STARFIVE_AES_KEY6 (STARFIVE_AES_REGS_OFFSET + 0x1C) +#define STARFIVE_AES_KEY7 (STARFIVE_AES_REGS_OFFSET + 0x20) +#define STARFIVE_AES_CSR (STARFIVE_AES_REGS_OFFSET + 0x24) +#define STARFIVE_AES_IV0 (STARFIVE_AES_REGS_OFFSET + 0x28) +#define STARFIVE_AES_IV1 (STARFIVE_AES_REGS_OFFSET + 0x2C) +#define STARFIVE_AES_IV2 (STARFIVE_AES_REGS_OFFSET + 0x30) +#define STARFIVE_AES_IV3 (STARFIVE_AES_REGS_OFFSET + 0x34) +#define STARFIVE_AES_NONCE0 (STARFIVE_AES_REGS_OFFSET + 0x3C) +#define STARFIVE_AES_NONCE1 (STARFIVE_AES_REGS_OFFSET + 0x40) +#define STARFIVE_AES_NONCE2 (STARFIVE_AES_REGS_OFFSET + 0x44) +#define STARFIVE_AES_NONCE3 (STARFIVE_AES_REGS_OFFSET + 0x48) +#define STARFIVE_AES_ALEN0 (STARFIVE_AES_REGS_OFFSET + 0x4C) +#define STARFIVE_AES_ALEN1 (STARFIVE_AES_REGS_OFFSET + 0x50) +#define STARFIVE_AES_MLEN0 (STARFIVE_AES_REGS_OFFSET + 0x54) +#define STARFIVE_AES_MLEN1 (STARFIVE_AES_REGS_OFFSET + 0x58) +#define STARFIVE_AES_IVLEN (STARFIVE_AES_REGS_OFFSET + 0x5C) + +#define FLG_MODE_MASK GENMASK(2, 0) +#define FLG_ENCRYPT BIT(4) + +/* Misc */ +#define CCM_B0_ADATA 0x40 +#define AES_BLOCK_32 (AES_BLOCK_SIZE / sizeof(u32)) + +static inline int starfive_aes_wait_busy(struct starfive_cryp_dev *cryp) +{ + u32 status; + + return readl_relaxed_poll_timeout(cryp->base + STARFIVE_AES_CSR, status, + !(status & STARFIVE_AES_BUSY), 10, 100000); +} + +static inline int starfive_aes_wait_keydone(struct starfive_cryp_dev *cryp) +{ + u32 status; + + return readl_relaxed_poll_timeout(cryp->base + STARFIVE_AES_CSR, status, + (status & STARFIVE_AES_KEY_DONE), 10, 100000); +} + +static inline int starfive_aes_wait_gcmdone(struct starfive_cryp_dev *cryp) +{ + u32 status; + + return readl_relaxed_poll_timeout(cryp->base + STARFIVE_AES_CSR, status, + (status & STARFIVE_AES_GCM_DONE), 10, 100000); +} + +static inline int is_gcm(struct starfive_cryp_dev *cryp) +{ + return (cryp->flags & FLG_MODE_MASK) == STARFIVE_AES_MODE_GCM; +} + +static inline int is_encrypt(struct starfive_cryp_dev *cryp) +{ + return cryp->flags & FLG_ENCRYPT; +} + +static void starfive_aes_aead_hw_start(struct starfive_cryp_ctx *ctx, u32 hw_mode) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + unsigned int value; + + switch (hw_mode) { + case STARFIVE_AES_MODE_GCM: + value = readl(ctx->cryp->base + STARFIVE_AES_CSR); + value |= STARFIVE_AES_GCM_START; + writel(value, cryp->base + STARFIVE_AES_CSR); + starfive_aes_wait_gcmdone(cryp); + break; + case STARFIVE_AES_MODE_CCM: + value = readl(ctx->cryp->base + STARFIVE_AES_CSR); + value |= STARFIVE_AES_CCM_START; + writel(value, cryp->base + STARFIVE_AES_CSR); + break; + } +} + +static inline void starfive_aes_set_ivlen(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + + if (is_gcm(cryp)) + writel(GCM_AES_IV_SIZE, cryp->base + STARFIVE_AES_IVLEN); + else + writel(AES_BLOCK_SIZE, cryp->base + STARFIVE_AES_IVLEN); +} + +static inline void starfive_aes_set_alen(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + + writel(upper_32_bits(cryp->assoclen), cryp->base + STARFIVE_AES_ALEN0); + writel(lower_32_bits(cryp->assoclen), cryp->base + STARFIVE_AES_ALEN1); +} + +static inline void starfive_aes_set_mlen(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + + writel(upper_32_bits(cryp->total_in), cryp->base + STARFIVE_AES_MLEN0); + writel(lower_32_bits(cryp->total_in), cryp->base + STARFIVE_AES_MLEN1); +} + +static inline int starfive_aes_ccm_check_iv(const u8 *iv) +{ + /* 2 <= L <= 8, so 1 <= L' <= 7. */ + if (iv[0] < 1 || iv[0] > 7) + return -EINVAL; + + return 0; +} + +static int starfive_aes_write_iv(struct starfive_cryp_ctx *ctx, u32 *iv) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + + writel(iv[0], cryp->base + STARFIVE_AES_IV0); + writel(iv[1], cryp->base + STARFIVE_AES_IV1); + writel(iv[2], cryp->base + STARFIVE_AES_IV2); + + if (is_gcm(cryp)) { + if (starfive_aes_wait_gcmdone(cryp)) + return -ETIMEDOUT; + + return 0; + } + + writel(iv[3], cryp->base + STARFIVE_AES_IV3); + + return 0; +} + +static inline void starfive_aes_get_iv(struct starfive_cryp_dev *cryp, u32 *iv) +{ + iv[0] = readl(cryp->base + STARFIVE_AES_IV0); + iv[1] = readl(cryp->base + STARFIVE_AES_IV1); + iv[2] = readl(cryp->base + STARFIVE_AES_IV2); + iv[3] = readl(cryp->base + STARFIVE_AES_IV3); +} + +static inline void starfive_aes_write_nonce(struct starfive_cryp_ctx *ctx, u32 *nonce) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + + writel(nonce[0], cryp->base + STARFIVE_AES_NONCE0); + writel(nonce[1], cryp->base + STARFIVE_AES_NONCE1); + writel(nonce[2], cryp->base + STARFIVE_AES_NONCE2); + writel(nonce[3], cryp->base + STARFIVE_AES_NONCE3); +} + +static int starfive_aes_write_key(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + u32 *key = (u32 *)ctx->key; + + if (ctx->keylen >= AES_KEYSIZE_128) { + writel(key[0], cryp->base + STARFIVE_AES_KEY0); + writel(key[1], cryp->base + STARFIVE_AES_KEY1); + writel(key[2], cryp->base + STARFIVE_AES_KEY2); + writel(key[3], cryp->base + STARFIVE_AES_KEY3); + } + + if (ctx->keylen >= AES_KEYSIZE_192) { + writel(key[4], cryp->base + STARFIVE_AES_KEY4); + writel(key[5], cryp->base + STARFIVE_AES_KEY5); + } + + if (ctx->keylen >= AES_KEYSIZE_256) { + writel(key[6], cryp->base + STARFIVE_AES_KEY6); + writel(key[7], cryp->base + STARFIVE_AES_KEY7); + } + + if (starfive_aes_wait_keydone(cryp)) + return -ETIMEDOUT; + + return 0; +} + +static int starfive_aes_ccm_init(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + u8 iv[AES_BLOCK_SIZE], b0[AES_BLOCK_SIZE]; + unsigned int textlen; + + memcpy(iv, cryp->req.areq->iv, AES_BLOCK_SIZE); + memset(iv + AES_BLOCK_SIZE - 1 - iv[0], 0, iv[0] + 1); + + /* Build B0 */ + memcpy(b0, iv, AES_BLOCK_SIZE); + + b0[0] |= (8 * ((cryp->authsize - 2) / 2)); + + if (cryp->assoclen) + b0[0] |= CCM_B0_ADATA; + + textlen = cryp->total_in; + + b0[AES_BLOCK_SIZE - 2] = textlen >> 8; + b0[AES_BLOCK_SIZE - 1] = textlen & 0xFF; + + starfive_aes_write_nonce(ctx, (u32 *)b0); + + return 0; +} + +static int starfive_aes_hw_init(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_request_ctx *rctx = ctx->rctx; + struct starfive_cryp_dev *cryp = ctx->cryp; + u32 hw_mode; + + /* reset */ + rctx->csr.aes.v = 0; + rctx->csr.aes.aesrst = 1; + writel(rctx->csr.aes.v, cryp->base + STARFIVE_AES_CSR); + + /* csr setup */ + hw_mode = cryp->flags & FLG_MODE_MASK; + + rctx->csr.aes.v = 0; + + switch (ctx->keylen) { + case AES_KEYSIZE_128: + rctx->csr.aes.keymode = STARFIVE_AES_KEYMODE_128; + break; + case AES_KEYSIZE_192: + rctx->csr.aes.keymode = STARFIVE_AES_KEYMODE_192; + break; + case AES_KEYSIZE_256: + rctx->csr.aes.keymode = STARFIVE_AES_KEYMODE_256; + break; + } + + rctx->csr.aes.mode = hw_mode; + rctx->csr.aes.cmode = !is_encrypt(cryp); + rctx->csr.aes.ie = 1; + + if (hw_mode == STARFIVE_AES_MODE_CFB || + hw_mode == STARFIVE_AES_MODE_OFB) + rctx->csr.aes.stmode = STARFIVE_AES_MODE_XFB_128; + else + rctx->csr.aes.stmode = STARFIVE_AES_MODE_XFB_1; + + if (cryp->side_chan) { + rctx->csr.aes.delay_aes = 1; + rctx->csr.aes.vaes_start = 1; + } + + writel(rctx->csr.aes.v, cryp->base + STARFIVE_AES_CSR); + + cryp->err = starfive_aes_write_key(ctx); + if (cryp->err) + return cryp->err; + + switch (hw_mode) { + case STARFIVE_AES_MODE_GCM: + starfive_aes_set_alen(ctx); + starfive_aes_set_mlen(ctx); + starfive_aes_set_ivlen(ctx); + starfive_aes_aead_hw_start(ctx, hw_mode); + starfive_aes_write_iv(ctx, (void *)cryp->req.areq->iv); + break; + case STARFIVE_AES_MODE_CCM: + starfive_aes_set_alen(ctx); + starfive_aes_set_mlen(ctx); + starfive_aes_ccm_init(ctx); + starfive_aes_aead_hw_start(ctx, hw_mode); + break; + case STARFIVE_AES_MODE_OFB: + case STARFIVE_AES_MODE_CFB: + case STARFIVE_AES_MODE_CBC: + case STARFIVE_AES_MODE_CTR: + starfive_aes_write_iv(ctx, (void *)cryp->req.sreq->iv); + break; + default: + break; + } + + return cryp->err; +} + +static int starfive_aes_read_authtag(struct starfive_cryp_dev *cryp) +{ + int i, start_addr; + + if (starfive_aes_wait_busy(cryp)) + return dev_err_probe(cryp->dev, -ETIMEDOUT, + "Timeout waiting for tag generation."); + + start_addr = STARFIVE_AES_NONCE0; + + if (is_gcm(cryp)) + for (i = 0; i < AES_BLOCK_32; i++, start_addr += 4) + cryp->tag_out[i] = readl(cryp->base + start_addr); + else + for (i = 0; i < AES_BLOCK_32; i++) + cryp->tag_out[i] = readl(cryp->base + STARFIVE_AES_AESDIO0R); + + if (is_encrypt(cryp)) { + scatterwalk_copychunks(cryp->tag_out, &cryp->out_walk, cryp->authsize, 1); + } else { + scatterwalk_copychunks(cryp->tag_in, &cryp->in_walk, cryp->authsize, 0); + + if (crypto_memneq(cryp->tag_in, cryp->tag_out, cryp->authsize)) + return dev_err_probe(cryp->dev, -EBADMSG, "Failed tag verification\n"); + } + + return 0; +} + +static void starfive_aes_finish_req(struct starfive_cryp_dev *cryp) +{ + union starfive_aes_csr csr; + int err = cryp->err; + + if (!err && cryp->authsize) + err = starfive_aes_read_authtag(cryp); + + if (!err && ((cryp->flags & FLG_MODE_MASK) == STARFIVE_AES_MODE_CBC || + (cryp->flags & FLG_MODE_MASK) == STARFIVE_AES_MODE_CTR)) + starfive_aes_get_iv(cryp, (void *)cryp->req.sreq->iv); + + /* reset irq flags*/ + csr.v = 0; + csr.aesrst = 1; + writel(csr.v, cryp->base + STARFIVE_AES_CSR); + + if (cryp->authsize) + crypto_finalize_aead_request(cryp->engine, cryp->req.areq, err); + else + crypto_finalize_skcipher_request(cryp->engine, cryp->req.sreq, + err); +} + +void starfive_aes_done_task(unsigned long param) +{ + struct starfive_cryp_dev *cryp = (struct starfive_cryp_dev *)param; + u32 block[AES_BLOCK_32]; + u32 stat; + int i; + + for (i = 0; i < AES_BLOCK_32; i++) + block[i] = readl(cryp->base + STARFIVE_AES_AESDIO0R); + + scatterwalk_copychunks(block, &cryp->out_walk, min_t(size_t, AES_BLOCK_SIZE, + cryp->total_out), 1); + + cryp->total_out -= min_t(size_t, AES_BLOCK_SIZE, cryp->total_out); + + if (!cryp->total_out) { + starfive_aes_finish_req(cryp); + return; + } + + memset(block, 0, AES_BLOCK_SIZE); + scatterwalk_copychunks(block, &cryp->in_walk, min_t(size_t, AES_BLOCK_SIZE, + cryp->total_in), 0); + cryp->total_in -= min_t(size_t, AES_BLOCK_SIZE, cryp->total_in); + + for (i = 0; i < AES_BLOCK_32; i++) + writel(block[i], cryp->base + STARFIVE_AES_AESDIO0R); + + stat = readl(cryp->base + STARFIVE_IE_MASK_OFFSET); + stat &= ~STARFIVE_IE_MASK_AES_DONE; + writel(stat, cryp->base + STARFIVE_IE_MASK_OFFSET); +} + +static int starfive_aes_gcm_write_adata(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + struct starfive_cryp_request_ctx *rctx = ctx->rctx; + u32 *buffer; + int total_len, loop; + + total_len = ALIGN(cryp->assoclen, AES_BLOCK_SIZE) / sizeof(unsigned int); + buffer = (u32 *)rctx->adata; + + for (loop = 0; loop < total_len; loop += 4) { + writel(*buffer, cryp->base + STARFIVE_AES_NONCE0); + buffer++; + writel(*buffer, cryp->base + STARFIVE_AES_NONCE1); + buffer++; + writel(*buffer, cryp->base + STARFIVE_AES_NONCE2); + buffer++; + writel(*buffer, cryp->base + STARFIVE_AES_NONCE3); + buffer++; + } + + if (starfive_aes_wait_gcmdone(cryp)) + return dev_err_probe(cryp->dev, -ETIMEDOUT, + "Timeout processing gcm aad block"); + + return 0; +} + +static int starfive_aes_ccm_write_adata(struct starfive_cryp_ctx *ctx) +{ + struct starfive_cryp_dev *cryp = ctx->cryp; + struct starfive_cryp_request_ctx *rctx = ctx->rctx; + u32 *buffer; + u8 *ci; + int total_len, loop; + + total_len = cryp->assoclen; + + ci = rctx->adata; + writeb(*ci, cryp->base + STARFIVE_AES_AESDIO0R); + ci++; + writeb(*ci, cryp->base + STARFIVE_AES_AESDIO0R); + ci++; + total_len -= 2; + buffer = (u32 *)ci; + + for (loop = 0; loop < 3; loop++, buffer++) + writel(*buffer, cryp->base + STARFIVE_AES_AESDIO0R); + + total_len -= 12; + + while (total_len > 0) { + for (loop = 0; loop < AES_BLOCK_32; loop++, buffer++) + writel(*buffer, cryp->base + STARFIVE_AES_AESDIO0R); + + total_len -= AES_BLOCK_SIZE; + } + + if (starfive_aes_wait_busy(cryp)) + return dev_err_probe(cryp->dev, -ETIMEDOUT, + "Timeout processing ccm aad block"); + + return 0; +} + +static int starfive_aes_prepare_req(struct skcipher_request *req, + struct aead_request *areq) +{ + struct starfive_cryp_ctx *ctx; + struct starfive_cryp_request_ctx *rctx; + struct starfive_cryp_dev *cryp; + + if (!req && !areq) + return -EINVAL; + + ctx = req ? crypto_skcipher_ctx(crypto_skcipher_reqtfm(req)) : + crypto_aead_ctx(crypto_aead_reqtfm(areq)); + + cryp = ctx->cryp; + rctx = req ? skcipher_request_ctx(req) : aead_request_ctx(areq); + + if (req) { + cryp->req.sreq = req; + cryp->total_in = req->cryptlen; + cryp->total_out = req->cryptlen; + cryp->assoclen = 0; + cryp->authsize = 0; + } else { + cryp->req.areq = areq; + cryp->assoclen = areq->assoclen; + cryp->authsize = crypto_aead_authsize(crypto_aead_reqtfm(areq)); + if (is_encrypt(cryp)) { + cryp->total_in = areq->cryptlen; + cryp->total_out = areq->cryptlen; + } else { + cryp->total_in = areq->cryptlen - cryp->authsize; + cryp->total_out = cryp->total_in; + } + } + + rctx->in_sg = req ? req->src : areq->src; + scatterwalk_start(&cryp->in_walk, rctx->in_sg); + + rctx->out_sg = req ? req->dst : areq->dst; + scatterwalk_start(&cryp->out_walk, rctx->out_sg); + + if (cryp->assoclen) { + rctx->adata = kzalloc(ALIGN(cryp->assoclen, AES_BLOCK_SIZE), GFP_KERNEL); + if (!rctx->adata) + return dev_err_probe(cryp->dev, -ENOMEM, + "Failed to alloc memory for adata"); + + scatterwalk_copychunks(rctx->adata, &cryp->in_walk, cryp->assoclen, 0); + scatterwalk_copychunks(NULL, &cryp->out_walk, cryp->assoclen, 2); + } + + ctx->rctx = rctx; + + return starfive_aes_hw_init(ctx); +} + +static int starfive_aes_do_one_req(struct crypto_engine *engine, void *areq) +{ + struct skcipher_request *req = + container_of(areq, struct skcipher_request, base); + struct starfive_cryp_ctx *ctx = + crypto_skcipher_ctx(crypto_skcipher_reqtfm(req)); + struct starfive_cryp_dev *cryp = ctx->cryp; + u32 block[AES_BLOCK_32]; + u32 stat; + int err; + int i; + + err = starfive_aes_prepare_req(req, NULL); + if (err) + return err; + + /* + * Write first plain/ciphertext block to start the module + * then let irq tasklet handle the rest of the data blocks. + */ + scatterwalk_copychunks(block, &cryp->in_walk, min_t(size_t, AES_BLOCK_SIZE, + cryp->total_in), 0); + cryp->total_in -= min_t(size_t, AES_BLOCK_SIZE, cryp->total_in); + + for (i = 0; i < AES_BLOCK_32; i++) + writel(block[i], cryp->base + STARFIVE_AES_AESDIO0R); + + stat = readl(cryp->base + STARFIVE_IE_MASK_OFFSET); + stat &= ~STARFIVE_IE_MASK_AES_DONE; + writel(stat, cryp->base + STARFIVE_IE_MASK_OFFSET); + + return 0; +} + +static int starfive_aes_init_tfm(struct crypto_skcipher *tfm) +{ + struct starfive_cryp_ctx *ctx = crypto_skcipher_ctx(tfm); + + ctx->cryp = starfive_cryp_find_dev(ctx); + if (!ctx->cryp) + return -ENODEV; + + crypto_skcipher_set_reqsize(tfm, sizeof(struct starfive_cryp_request_ctx) + + sizeof(struct skcipher_request)); + + return 0; +} + +static int starfive_aes_aead_do_one_req(struct crypto_engine *engine, void *areq) +{ + struct aead_request *req = + container_of(areq, struct aead_request, base); + struct starfive_cryp_ctx *ctx = + crypto_aead_ctx(crypto_aead_reqtfm(req)); + struct starfive_cryp_dev *cryp = ctx->cryp; + struct starfive_cryp_request_ctx *rctx = ctx->rctx; + u32 block[AES_BLOCK_32]; + u32 stat; + int err; + int i; + + err = starfive_aes_prepare_req(NULL, req); + if (err) + return err; + + if (!cryp->assoclen) + goto write_text; + + if ((cryp->flags & FLG_MODE_MASK) == STARFIVE_AES_MODE_CCM) + cryp->err = starfive_aes_ccm_write_adata(ctx); + else + cryp->err = starfive_aes_gcm_write_adata(ctx); + + kfree(rctx->adata); + + if (cryp->err) + return cryp->err; + +write_text: + if (!cryp->total_in) + goto finish_req; + + /* + * Write first plain/ciphertext block to start the module + * then let irq tasklet handle the rest of the data blocks. + */ + scatterwalk_copychunks(block, &cryp->in_walk, min_t(size_t, AES_BLOCK_SIZE, + cryp->total_in), 0); + cryp->total_in -= min_t(size_t, AES_BLOCK_SIZE, cryp->total_in); + + for (i = 0; i < AES_BLOCK_32; i++) + writel(block[i], cryp->base + STARFIVE_AES_AESDIO0R); + + stat = readl(cryp->base + STARFIVE_IE_MASK_OFFSET); + stat &= ~STARFIVE_IE_MASK_AES_DONE; + writel(stat, cryp->base + STARFIVE_IE_MASK_OFFSET); + + return 0; + +finish_req: + starfive_aes_finish_req(cryp); + return 0; +} + +static int starfive_aes_aead_init_tfm(struct crypto_aead *tfm) +{ + struct starfive_cryp_ctx *ctx = crypto_aead_ctx(tfm); + struct starfive_cryp_dev *cryp = ctx->cryp; + struct crypto_tfm *aead = crypto_aead_tfm(tfm); + struct crypto_alg *alg = aead->__crt_alg; + + ctx->cryp = starfive_cryp_find_dev(ctx); + if (!ctx->cryp) + return -ENODEV; + + if (alg->cra_flags & CRYPTO_ALG_NEED_FALLBACK) { + ctx->aead_fbk = crypto_alloc_aead(alg->cra_name, 0, + CRYPTO_ALG_NEED_FALLBACK); + if (IS_ERR(ctx->aead_fbk)) + return dev_err_probe(cryp->dev, PTR_ERR(ctx->aead_fbk), + "%s() failed to allocate fallback for %s\n", + __func__, alg->cra_name); + } + + crypto_aead_set_reqsize(tfm, sizeof(struct starfive_cryp_ctx) + + sizeof(struct aead_request)); + + return 0; +} + +static void starfive_aes_aead_exit_tfm(struct crypto_aead *tfm) +{ + struct starfive_cryp_ctx *ctx = crypto_aead_ctx(tfm); + + crypto_free_aead(ctx->aead_fbk); +} + +static int starfive_aes_crypt(struct skcipher_request *req, unsigned long flags) +{ + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct starfive_cryp_ctx *ctx = crypto_skcipher_ctx(tfm); + struct starfive_cryp_dev *cryp = ctx->cryp; + unsigned int blocksize_align = crypto_skcipher_blocksize(tfm) - 1; + + cryp->flags = flags; + + if ((cryp->flags & FLG_MODE_MASK) == STARFIVE_AES_MODE_ECB || + (cryp->flags & FLG_MODE_MASK) == STARFIVE_AES_MODE_CBC) + if (req->cryptlen & blocksize_align) + return -EINVAL; + + return crypto_transfer_skcipher_request_to_engine(cryp->engine, req); +} + +static int starfive_aes_aead_crypt(struct aead_request *req, unsigned long flags) +{ + struct starfive_cryp_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); + struct starfive_cryp_dev *cryp = ctx->cryp; + + cryp->flags = flags; + + /* + * HW engine could not perform CCM tag verification on + * non-blocksize aligned text, use fallback algo instead + */ + if (ctx->aead_fbk && !is_encrypt(cryp)) { + struct aead_request *subreq = aead_request_ctx(req); + + aead_request_set_tfm(subreq, ctx->aead_fbk); + aead_request_set_callback(subreq, req->base.flags, + req->base.complete, req->base.data); + aead_request_set_crypt(subreq, req->src, + req->dst, req->cryptlen, req->iv); + aead_request_set_ad(subreq, req->assoclen); + + return crypto_aead_decrypt(subreq); + } + + return crypto_transfer_aead_request_to_engine(cryp->engine, req); +} + +static int starfive_aes_setkey(struct crypto_skcipher *tfm, const u8 *key, + unsigned int keylen) +{ + struct starfive_cryp_ctx *ctx = crypto_skcipher_ctx(tfm); + + if (!key || !keylen) + return -EINVAL; + + if (keylen != AES_KEYSIZE_128 && + keylen != AES_KEYSIZE_192 && + keylen != AES_KEYSIZE_256) + return -EINVAL; + + memcpy(ctx->key, key, keylen); + ctx->keylen = keylen; + + return 0; +} + +static int starfive_aes_aead_setkey(struct crypto_aead *tfm, const u8 *key, + unsigned int keylen) +{ + struct starfive_cryp_ctx *ctx = crypto_aead_ctx(tfm); + + if (!key || !keylen) + return -EINVAL; + + if (keylen != AES_KEYSIZE_128 && + keylen != AES_KEYSIZE_192 && + keylen != AES_KEYSIZE_256) + return -EINVAL; + + memcpy(ctx->key, key, keylen); + ctx->keylen = keylen; + + if (ctx->aead_fbk) + return crypto_aead_setkey(ctx->aead_fbk, key, keylen); + + return 0; +} + +static int starfive_aes_gcm_setauthsize(struct crypto_aead *tfm, + unsigned int authsize) +{ + return crypto_gcm_check_authsize(authsize); +} + +static int starfive_aes_ccm_setauthsize(struct crypto_aead *tfm, + unsigned int authsize) +{ + struct starfive_cryp_ctx *ctx = crypto_aead_ctx(tfm); + + switch (authsize) { + case 4: + case 6: + case 8: + case 10: + case 12: + case 14: + case 16: + break; + default: + return -EINVAL; + } + + return crypto_aead_setauthsize(ctx->aead_fbk, authsize); +} + +static int starfive_aes_ecb_encrypt(struct skcipher_request *req) +{ + return starfive_aes_crypt(req, STARFIVE_AES_MODE_ECB | FLG_ENCRYPT); +} + +static int starfive_aes_ecb_decrypt(struct skcipher_request *req) +{ + return starfive_aes_crypt(req, STARFIVE_AES_MODE_ECB); +} + +static int starfive_aes_cbc_encrypt(struct skcipher_request *req) +{ + return starfive_aes_crypt(req, STARFIVE_AES_MODE_CBC | FLG_ENCRYPT); +} + +static int starfive_aes_cbc_decrypt(struct skcipher_request *req) +{ + return starfive_aes_crypt(req, STARFIVE_AES_MODE_CBC); +} + +static int starfive_aes_cfb_encrypt(struct skcipher_request *req) +{ + return starfive_aes_crypt(req, STARFIVE_AES_MODE_CFB | FLG_ENCRYPT); +} + +static int starfive_aes_cfb_decrypt(struct skcipher_request *req) +{ + return starfive_aes_crypt(req, STARFIVE_AES_MODE_CFB); +} + +static int starfive_aes_ofb_encrypt(struct skcipher_request *req) +{ + return starfive_aes_crypt(req, STARFIVE_AES_MODE_OFB | FLG_ENCRYPT); +} + +static int starfive_aes_ofb_decrypt(struct skcipher_request *req) +{ + return starfive_aes_crypt(req, STARFIVE_AES_MODE_OFB); +} + +static int starfive_aes_ctr_encrypt(struct skcipher_request *req) +{ + return starfive_aes_crypt(req, STARFIVE_AES_MODE_CTR | FLG_ENCRYPT); +} + +static int starfive_aes_ctr_decrypt(struct skcipher_request *req) +{ + return starfive_aes_crypt(req, STARFIVE_AES_MODE_CTR); +} + +static int starfive_aes_gcm_encrypt(struct aead_request *req) +{ + return starfive_aes_aead_crypt(req, STARFIVE_AES_MODE_GCM | FLG_ENCRYPT); +} + +static int starfive_aes_gcm_decrypt(struct aead_request *req) +{ + return starfive_aes_aead_crypt(req, STARFIVE_AES_MODE_GCM); +} + +static int starfive_aes_ccm_encrypt(struct aead_request *req) +{ + int ret; + + ret = starfive_aes_ccm_check_iv(req->iv); + if (ret) + return ret; + + return starfive_aes_aead_crypt(req, STARFIVE_AES_MODE_CCM | FLG_ENCRYPT); +} + +static int starfive_aes_ccm_decrypt(struct aead_request *req) +{ + int ret; + + ret = starfive_aes_ccm_check_iv(req->iv); + if (ret) + return ret; + + return starfive_aes_aead_crypt(req, STARFIVE_AES_MODE_CCM); +} + +static struct skcipher_engine_alg skcipher_algs[] = { +{ + .base.init = starfive_aes_init_tfm, + .base.setkey = starfive_aes_setkey, + .base.encrypt = starfive_aes_ecb_encrypt, + .base.decrypt = starfive_aes_ecb_decrypt, + .base.min_keysize = AES_MIN_KEY_SIZE, + .base.max_keysize = AES_MAX_KEY_SIZE, + .base.base = { + .cra_name = "ecb(aes)", + .cra_driver_name = "starfive-ecb-aes", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 0xf, + .cra_module = THIS_MODULE, + }, + .op = { + .do_one_request = starfive_aes_do_one_req, + }, +}, { + .base.init = starfive_aes_init_tfm, + .base.setkey = starfive_aes_setkey, + .base.encrypt = starfive_aes_cbc_encrypt, + .base.decrypt = starfive_aes_cbc_decrypt, + .base.min_keysize = AES_MIN_KEY_SIZE, + .base.max_keysize = AES_MAX_KEY_SIZE, + .base.ivsize = AES_BLOCK_SIZE, + .base.base = { + .cra_name = "cbc(aes)", + .cra_driver_name = "starfive-cbc-aes", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 0xf, + .cra_module = THIS_MODULE, + }, + .op = { + .do_one_request = starfive_aes_do_one_req, + }, +}, { + .base.init = starfive_aes_init_tfm, + .base.setkey = starfive_aes_setkey, + .base.encrypt = starfive_aes_ctr_encrypt, + .base.decrypt = starfive_aes_ctr_decrypt, + .base.min_keysize = AES_MIN_KEY_SIZE, + .base.max_keysize = AES_MAX_KEY_SIZE, + .base.ivsize = AES_BLOCK_SIZE, + .base.base = { + .cra_name = "ctr(aes)", + .cra_driver_name = "starfive-ctr-aes", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 0xf, + .cra_module = THIS_MODULE, + }, + .op = { + .do_one_request = starfive_aes_do_one_req, + }, +}, { + .base.init = starfive_aes_init_tfm, + .base.setkey = starfive_aes_setkey, + .base.encrypt = starfive_aes_cfb_encrypt, + .base.decrypt = starfive_aes_cfb_decrypt, + .base.min_keysize = AES_MIN_KEY_SIZE, + .base.max_keysize = AES_MAX_KEY_SIZE, + .base.ivsize = AES_BLOCK_SIZE, + .base.base = { + .cra_name = "cfb(aes)", + .cra_driver_name = "starfive-cfb-aes", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 0xf, + .cra_module = THIS_MODULE, + }, + .op = { + .do_one_request = starfive_aes_do_one_req, + }, +}, { + .base.init = starfive_aes_init_tfm, + .base.setkey = starfive_aes_setkey, + .base.encrypt = starfive_aes_ofb_encrypt, + .base.decrypt = starfive_aes_ofb_decrypt, + .base.min_keysize = AES_MIN_KEY_SIZE, + .base.max_keysize = AES_MAX_KEY_SIZE, + .base.ivsize = AES_BLOCK_SIZE, + .base.base = { + .cra_name = "ofb(aes)", + .cra_driver_name = "starfive-ofb-aes", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 0xf, + .cra_module = THIS_MODULE, + }, + .op = { + .do_one_request = starfive_aes_do_one_req, + }, +}, +}; + +static struct aead_engine_alg aead_algs[] = { +{ + .base.setkey = starfive_aes_aead_setkey, + .base.setauthsize = starfive_aes_gcm_setauthsize, + .base.encrypt = starfive_aes_gcm_encrypt, + .base.decrypt = starfive_aes_gcm_decrypt, + .base.init = starfive_aes_aead_init_tfm, + .base.exit = starfive_aes_aead_exit_tfm, + .base.ivsize = GCM_AES_IV_SIZE, + .base.maxauthsize = AES_BLOCK_SIZE, + .base.base = { + .cra_name = "gcm(aes)", + .cra_driver_name = "starfive-gcm-aes", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 0xf, + .cra_module = THIS_MODULE, + }, + .op = { + .do_one_request = starfive_aes_aead_do_one_req, + }, +}, { + .base.setkey = starfive_aes_aead_setkey, + .base.setauthsize = starfive_aes_ccm_setauthsize, + .base.encrypt = starfive_aes_ccm_encrypt, + .base.decrypt = starfive_aes_ccm_decrypt, + .base.init = starfive_aes_aead_init_tfm, + .base.exit = starfive_aes_aead_exit_tfm, + .base.ivsize = AES_BLOCK_SIZE, + .base.maxauthsize = AES_BLOCK_SIZE, + .base.base = { + .cra_name = "ccm(aes)", + .cra_driver_name = "starfive-ccm-aes", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_NEED_FALLBACK, + .cra_blocksize = 1, + .cra_ctxsize = sizeof(struct starfive_cryp_ctx), + .cra_alignmask = 0xf, + .cra_module = THIS_MODULE, + }, + .op = { + .do_one_request = starfive_aes_aead_do_one_req, + }, +}, +}; + +int starfive_aes_register_algs(void) +{ + int ret; + + ret = crypto_engine_register_skciphers(skcipher_algs, ARRAY_SIZE(skcipher_algs)); + if (ret) + return ret; + + ret = crypto_engine_register_aeads(aead_algs, ARRAY_SIZE(aead_algs)); + if (ret) + crypto_engine_unregister_skciphers(skcipher_algs, ARRAY_SIZE(skcipher_algs)); + + return ret; +} + +void starfive_aes_unregister_algs(void) +{ + crypto_engine_unregister_aeads(aead_algs, ARRAY_SIZE(aead_algs)); + crypto_engine_unregister_skciphers(skcipher_algs, ARRAY_SIZE(skcipher_algs)); +} diff --git a/drivers/crypto/starfive/jh7110-cryp.c b/drivers/crypto/starfive/jh7110-cryp.c index cc43556b6c80..08e974e0dd12 100644 --- a/drivers/crypto/starfive/jh7110-cryp.c +++ b/drivers/crypto/starfive/jh7110-cryp.c @@ -7,17 +7,20 @@ * */ +#include <crypto/engine.h> +#include "jh7110-cryp.h" #include <linux/clk.h> -#include <linux/delay.h> +#include <linux/completion.h> +#include <linux/err.h> #include <linux/interrupt.h> #include <linux/iopoll.h> +#include <linux/kernel.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/reset.h> - -#include "jh7110-cryp.h" +#include <linux/spinlock.h> #define DRIVER_NAME "jh7110-crypto" @@ -51,6 +54,13 @@ struct starfive_cryp_dev *starfive_cryp_find_dev(struct starfive_cryp_ctx *ctx) return cryp; } +static u16 side_chan; +module_param(side_chan, ushort, 0); +MODULE_PARM_DESC(side_chan, "Enable side channel mitigation for AES module.\n" + "Enabling this feature will reduce speed performance.\n" + " 0 - Disabled\n" + " other - Enabled"); + static int starfive_dma_init(struct starfive_cryp_dev *cryp) { dma_cap_mask_t mask; @@ -82,20 +92,26 @@ static void starfive_dma_cleanup(struct starfive_cryp_dev *cryp) static irqreturn_t starfive_cryp_irq(int irq, void *priv) { u32 status; + u32 mask; struct starfive_cryp_dev *cryp = (struct starfive_cryp_dev *)priv; + mask = readl(cryp->base + STARFIVE_IE_MASK_OFFSET); status = readl(cryp->base + STARFIVE_IE_FLAG_OFFSET); + if (status & STARFIVE_IE_FLAG_AES_DONE) { + mask |= STARFIVE_IE_MASK_AES_DONE; + writel(mask, cryp->base + STARFIVE_IE_MASK_OFFSET); + tasklet_schedule(&cryp->aes_done); + } + if (status & STARFIVE_IE_FLAG_HASH_DONE) { - status = readl(cryp->base + STARFIVE_IE_MASK_OFFSET); - status |= STARFIVE_IE_MASK_HASH_DONE; - writel(status, cryp->base + STARFIVE_IE_MASK_OFFSET); + mask |= STARFIVE_IE_MASK_HASH_DONE; + writel(mask, cryp->base + STARFIVE_IE_MASK_OFFSET); tasklet_schedule(&cryp->hash_done); } if (status & STARFIVE_IE_FLAG_PKA_DONE) { - status = readl(cryp->base + STARFIVE_IE_MASK_OFFSET); - status |= STARFIVE_IE_MASK_PKA_DONE; - writel(status, cryp->base + STARFIVE_IE_MASK_OFFSET); + mask |= STARFIVE_IE_MASK_PKA_DONE; + writel(mask, cryp->base + STARFIVE_IE_MASK_OFFSET); complete(&cryp->pka_done); } @@ -121,10 +137,12 @@ static int starfive_cryp_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, PTR_ERR(cryp->base), "Error remapping memory for platform device\n"); + tasklet_init(&cryp->aes_done, starfive_aes_done_task, (unsigned long)cryp); tasklet_init(&cryp->hash_done, starfive_hash_done_task, (unsigned long)cryp); cryp->phys_base = res->start; cryp->dma_maxburst = 32; + cryp->side_chan = side_chan; cryp->hclk = devm_clk_get(&pdev->dev, "hclk"); if (IS_ERR(cryp->hclk)) @@ -180,6 +198,10 @@ static int starfive_cryp_probe(struct platform_device *pdev) if (ret) goto err_engine_start; + ret = starfive_aes_register_algs(); + if (ret) + goto err_algs_aes; + ret = starfive_hash_register_algs(); if (ret) goto err_algs_hash; @@ -193,6 +215,8 @@ static int starfive_cryp_probe(struct platform_device *pdev) err_algs_rsa: starfive_hash_unregister_algs(); err_algs_hash: + starfive_aes_unregister_algs(); +err_algs_aes: crypto_engine_stop(cryp->engine); err_engine_start: crypto_engine_exit(cryp->engine); @@ -207,18 +231,21 @@ err_dma_init: clk_disable_unprepare(cryp->ahb); reset_control_assert(cryp->rst); + tasklet_kill(&cryp->aes_done); tasklet_kill(&cryp->hash_done); err_probe_defer: return ret; } -static int starfive_cryp_remove(struct platform_device *pdev) +static void starfive_cryp_remove(struct platform_device *pdev) { struct starfive_cryp_dev *cryp = platform_get_drvdata(pdev); + starfive_aes_unregister_algs(); starfive_hash_unregister_algs(); starfive_rsa_unregister_algs(); + tasklet_kill(&cryp->aes_done); tasklet_kill(&cryp->hash_done); crypto_engine_stop(cryp->engine); @@ -233,8 +260,6 @@ static int starfive_cryp_remove(struct platform_device *pdev) clk_disable_unprepare(cryp->hclk); clk_disable_unprepare(cryp->ahb); reset_control_assert(cryp->rst); - - return 0; } static const struct of_device_id starfive_dt_ids[] __maybe_unused = { @@ -245,7 +270,7 @@ MODULE_DEVICE_TABLE(of, starfive_dt_ids); static struct platform_driver starfive_cryp_driver = { .probe = starfive_cryp_probe, - .remove = starfive_cryp_remove, + .remove_new = starfive_cryp_remove, .driver = { .name = DRIVER_NAME, .of_match_table = starfive_dt_ids, diff --git a/drivers/crypto/starfive/jh7110-cryp.h b/drivers/crypto/starfive/jh7110-cryp.h index 0cdcffc0d7d4..fe011d50473d 100644 --- a/drivers/crypto/starfive/jh7110-cryp.h +++ b/drivers/crypto/starfive/jh7110-cryp.h @@ -2,13 +2,15 @@ #ifndef __STARFIVE_STR_H__ #define __STARFIVE_STR_H__ +#include <crypto/aes.h> +#include <crypto/hash.h> +#include <crypto/scatterwalk.h> +#include <crypto/sha2.h> +#include <crypto/sm3.h> #include <linux/delay.h> #include <linux/dma-mapping.h> #include <linux/dmaengine.h> - -#include <crypto/engine.h> -#include <crypto/sha2.h> -#include <crypto/sm3.h> +#include <linux/interrupt.h> #define STARFIVE_ALG_CR_OFFSET 0x0 #define STARFIVE_ALG_FIFO_OFFSET 0x4 @@ -17,13 +19,56 @@ #define STARFIVE_DMA_IN_LEN_OFFSET 0x10 #define STARFIVE_DMA_OUT_LEN_OFFSET 0x14 +#define STARFIVE_IE_MASK_AES_DONE 0x1 #define STARFIVE_IE_MASK_HASH_DONE 0x4 #define STARFIVE_IE_MASK_PKA_DONE 0x8 +#define STARFIVE_IE_FLAG_AES_DONE 0x1 #define STARFIVE_IE_FLAG_HASH_DONE 0x4 #define STARFIVE_IE_FLAG_PKA_DONE 0x8 #define STARFIVE_MSG_BUFFER_SIZE SZ_16K #define MAX_KEY_SIZE SHA512_BLOCK_SIZE +#define STARFIVE_AES_IV_LEN AES_BLOCK_SIZE +#define STARFIVE_AES_CTR_LEN AES_BLOCK_SIZE + +union starfive_aes_csr { + u32 v; + struct { + u32 cmode :1; +#define STARFIVE_AES_KEYMODE_128 0x0 +#define STARFIVE_AES_KEYMODE_192 0x1 +#define STARFIVE_AES_KEYMODE_256 0x2 + u32 keymode :2; +#define STARFIVE_AES_BUSY BIT(3) + u32 busy :1; + u32 done :1; +#define STARFIVE_AES_KEY_DONE BIT(5) + u32 krdy :1; + u32 aesrst :1; + u32 ie :1; +#define STARFIVE_AES_CCM_START BIT(8) + u32 ccm_start :1; +#define STARFIVE_AES_MODE_ECB 0x0 +#define STARFIVE_AES_MODE_CBC 0x1 +#define STARFIVE_AES_MODE_CFB 0x2 +#define STARFIVE_AES_MODE_OFB 0x3 +#define STARFIVE_AES_MODE_CTR 0x4 +#define STARFIVE_AES_MODE_CCM 0x5 +#define STARFIVE_AES_MODE_GCM 0x6 + u32 mode :3; +#define STARFIVE_AES_GCM_START BIT(12) + u32 gcm_start :1; +#define STARFIVE_AES_GCM_DONE BIT(13) + u32 gcm_done :1; + u32 delay_aes :1; + u32 vaes_start :1; + u32 rsvd_0 :8; +#define STARFIVE_AES_MODE_XFB_1 0x0 +#define STARFIVE_AES_MODE_XFB_128 0x5 + u32 stmode :3; + u32 rsvd_1 :5; + }; +}; union starfive_hash_csr { u32 v; @@ -105,7 +150,6 @@ union starfive_alg_cr { }; struct starfive_cryp_ctx { - struct crypto_engine_ctx enginectx; struct starfive_cryp_dev *cryp; struct starfive_cryp_request_ctx *rctx; @@ -116,6 +160,7 @@ struct starfive_cryp_ctx { struct starfive_rsa_key rsa_key; struct crypto_akcipher *akcipher_fbk; struct crypto_ahash *ahash_fbk; + struct crypto_aead *aead_fbk; }; struct starfive_cryp_dev { @@ -133,13 +178,26 @@ struct starfive_cryp_dev { struct dma_chan *rx; struct dma_slave_config cfg_in; struct dma_slave_config cfg_out; + struct scatter_walk in_walk; + struct scatter_walk out_walk; struct crypto_engine *engine; + struct tasklet_struct aes_done; struct tasklet_struct hash_done; struct completion pka_done; + size_t assoclen; + size_t total_in; + size_t total_out; + u32 tag_in[4]; + u32 tag_out[4]; + unsigned int authsize; + unsigned long flags; int err; + bool side_chan; union starfive_alg_cr alg_cr; union { struct ahash_request *hreq; + struct aead_request *areq; + struct skcipher_request *sreq; } req; }; @@ -147,6 +205,7 @@ struct starfive_cryp_request_ctx { union { union starfive_hash_csr hash; union starfive_pka_cacr pka; + union starfive_aes_csr aes; } csr; struct scatterlist *in_sg; @@ -157,6 +216,7 @@ struct starfive_cryp_request_ctx { unsigned int blksize; unsigned int digsize; unsigned long in_sg_len; + unsigned char *adata; u8 rsa_data[] __aligned(sizeof(u32)); }; @@ -168,5 +228,9 @@ void starfive_hash_unregister_algs(void); int starfive_rsa_register_algs(void); void starfive_rsa_unregister_algs(void); +int starfive_aes_register_algs(void); +void starfive_aes_unregister_algs(void); + void starfive_hash_done_task(unsigned long param); +void starfive_aes_done_task(unsigned long param); #endif diff --git a/drivers/crypto/starfive/jh7110-hash.c b/drivers/crypto/starfive/jh7110-hash.c index 5064150b8a1c..cc7650198d70 100644 --- a/drivers/crypto/starfive/jh7110-hash.c +++ b/drivers/crypto/starfive/jh7110-hash.c @@ -6,25 +6,20 @@ * */ +#include <crypto/engine.h> +#include <crypto/internal/hash.h> +#include <crypto/scatterwalk.h> +#include "jh7110-cryp.h" +#include <linux/amba/pl080.h> #include <linux/clk.h> -#include <linux/crypto.h> #include <linux/dma-direct.h> #include <linux/interrupt.h> -#include <linux/io.h> #include <linux/iopoll.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/reset.h> -#include <linux/amba/pl080.h> - -#include <crypto/hash.h> -#include <crypto/scatterwalk.h> -#include <crypto/internal/hash.h> - -#include "jh7110-cryp.h" #define STARFIVE_HASH_REGS_OFFSET 0x300 #define STARFIVE_HASH_SHACSR (STARFIVE_HASH_REGS_OFFSET + 0x0) @@ -433,10 +428,6 @@ static int starfive_hash_init_tfm(struct crypto_ahash *hash, ctx->keylen = 0; ctx->hash_mode = mode; - ctx->enginectx.op.do_one_request = starfive_hash_one_request; - ctx->enginectx.op.prepare_request = NULL; - ctx->enginectx.op.unprepare_request = NULL; - return 0; } @@ -445,11 +436,6 @@ static void starfive_hash_exit_tfm(struct crypto_ahash *hash) struct starfive_cryp_ctx *ctx = crypto_ahash_ctx(hash); crypto_free_ahash(ctx->ahash_fbk); - - ctx->ahash_fbk = NULL; - ctx->enginectx.op.do_one_request = NULL; - ctx->enginectx.op.prepare_request = NULL; - ctx->enginectx.op.unprepare_request = NULL; } static int starfive_hash_long_setkey(struct starfive_cryp_ctx *ctx, @@ -619,18 +605,18 @@ static int starfive_hmac_sm3_init_tfm(struct crypto_ahash *hash) STARFIVE_HASH_SM3); } -static struct ahash_alg algs_sha2_sm3[] = { +static struct ahash_engine_alg algs_sha2_sm3[] = { { - .init = starfive_hash_init, - .update = starfive_hash_update, - .final = starfive_hash_final, - .finup = starfive_hash_finup, - .digest = starfive_hash_digest, - .export = starfive_hash_export, - .import = starfive_hash_import, - .init_tfm = starfive_sha224_init_tfm, - .exit_tfm = starfive_hash_exit_tfm, - .halg = { + .base.init = starfive_hash_init, + .base.update = starfive_hash_update, + .base.final = starfive_hash_final, + .base.finup = starfive_hash_finup, + .base.digest = starfive_hash_digest, + .base.export = starfive_hash_export, + .base.import = starfive_hash_import, + .base.init_tfm = starfive_sha224_init_tfm, + .base.exit_tfm = starfive_hash_exit_tfm, + .base.halg = { .digestsize = SHA224_DIGEST_SIZE, .statesize = sizeof(struct sha256_state), .base = { @@ -645,19 +631,22 @@ static struct ahash_alg algs_sha2_sm3[] = { .cra_alignmask = 3, .cra_module = THIS_MODULE, } - } + }, + .op = { + .do_one_request = starfive_hash_one_request, + }, }, { - .init = starfive_hash_init, - .update = starfive_hash_update, - .final = starfive_hash_final, - .finup = starfive_hash_finup, - .digest = starfive_hash_digest, - .export = starfive_hash_export, - .import = starfive_hash_import, - .init_tfm = starfive_hmac_sha224_init_tfm, - .exit_tfm = starfive_hash_exit_tfm, - .setkey = starfive_hash_setkey, - .halg = { + .base.init = starfive_hash_init, + .base.update = starfive_hash_update, + .base.final = starfive_hash_final, + .base.finup = starfive_hash_finup, + .base.digest = starfive_hash_digest, + .base.export = starfive_hash_export, + .base.import = starfive_hash_import, + .base.init_tfm = starfive_hmac_sha224_init_tfm, + .base.exit_tfm = starfive_hash_exit_tfm, + .base.setkey = starfive_hash_setkey, + .base.halg = { .digestsize = SHA224_DIGEST_SIZE, .statesize = sizeof(struct sha256_state), .base = { @@ -672,18 +661,21 @@ static struct ahash_alg algs_sha2_sm3[] = { .cra_alignmask = 3, .cra_module = THIS_MODULE, } - } + }, + .op = { + .do_one_request = starfive_hash_one_request, + }, }, { - .init = starfive_hash_init, - .update = starfive_hash_update, - .final = starfive_hash_final, - .finup = starfive_hash_finup, - .digest = starfive_hash_digest, - .export = starfive_hash_export, - .import = starfive_hash_import, - .init_tfm = starfive_sha256_init_tfm, - .exit_tfm = starfive_hash_exit_tfm, - .halg = { + .base.init = starfive_hash_init, + .base.update = starfive_hash_update, + .base.final = starfive_hash_final, + .base.finup = starfive_hash_finup, + .base.digest = starfive_hash_digest, + .base.export = starfive_hash_export, + .base.import = starfive_hash_import, + .base.init_tfm = starfive_sha256_init_tfm, + .base.exit_tfm = starfive_hash_exit_tfm, + .base.halg = { .digestsize = SHA256_DIGEST_SIZE, .statesize = sizeof(struct sha256_state), .base = { @@ -698,19 +690,22 @@ static struct ahash_alg algs_sha2_sm3[] = { .cra_alignmask = 3, .cra_module = THIS_MODULE, } - } + }, + .op = { + .do_one_request = starfive_hash_one_request, + }, }, { - .init = starfive_hash_init, - .update = starfive_hash_update, - .final = starfive_hash_final, - .finup = starfive_hash_finup, - .digest = starfive_hash_digest, - .export = starfive_hash_export, - .import = starfive_hash_import, - .init_tfm = starfive_hmac_sha256_init_tfm, - .exit_tfm = starfive_hash_exit_tfm, - .setkey = starfive_hash_setkey, - .halg = { + .base.init = starfive_hash_init, + .base.update = starfive_hash_update, + .base.final = starfive_hash_final, + .base.finup = starfive_hash_finup, + .base.digest = starfive_hash_digest, + .base.export = starfive_hash_export, + .base.import = starfive_hash_import, + .base.init_tfm = starfive_hmac_sha256_init_tfm, + .base.exit_tfm = starfive_hash_exit_tfm, + .base.setkey = starfive_hash_setkey, + .base.halg = { .digestsize = SHA256_DIGEST_SIZE, .statesize = sizeof(struct sha256_state), .base = { @@ -725,18 +720,21 @@ static struct ahash_alg algs_sha2_sm3[] = { .cra_alignmask = 3, .cra_module = THIS_MODULE, } - } + }, + .op = { + .do_one_request = starfive_hash_one_request, + }, }, { - .init = starfive_hash_init, - .update = starfive_hash_update, - .final = starfive_hash_final, - .finup = starfive_hash_finup, - .digest = starfive_hash_digest, - .export = starfive_hash_export, - .import = starfive_hash_import, - .init_tfm = starfive_sha384_init_tfm, - .exit_tfm = starfive_hash_exit_tfm, - .halg = { + .base.init = starfive_hash_init, + .base.update = starfive_hash_update, + .base.final = starfive_hash_final, + .base.finup = starfive_hash_finup, + .base.digest = starfive_hash_digest, + .base.export = starfive_hash_export, + .base.import = starfive_hash_import, + .base.init_tfm = starfive_sha384_init_tfm, + .base.exit_tfm = starfive_hash_exit_tfm, + .base.halg = { .digestsize = SHA384_DIGEST_SIZE, .statesize = sizeof(struct sha512_state), .base = { @@ -751,19 +749,22 @@ static struct ahash_alg algs_sha2_sm3[] = { .cra_alignmask = 3, .cra_module = THIS_MODULE, } - } + }, + .op = { + .do_one_request = starfive_hash_one_request, + }, }, { - .init = starfive_hash_init, - .update = starfive_hash_update, - .final = starfive_hash_final, - .finup = starfive_hash_finup, - .digest = starfive_hash_digest, - .export = starfive_hash_export, - .import = starfive_hash_import, - .init_tfm = starfive_hmac_sha384_init_tfm, - .exit_tfm = starfive_hash_exit_tfm, - .setkey = starfive_hash_setkey, - .halg = { + .base.init = starfive_hash_init, + .base.update = starfive_hash_update, + .base.final = starfive_hash_final, + .base.finup = starfive_hash_finup, + .base.digest = starfive_hash_digest, + .base.export = starfive_hash_export, + .base.import = starfive_hash_import, + .base.init_tfm = starfive_hmac_sha384_init_tfm, + .base.exit_tfm = starfive_hash_exit_tfm, + .base.setkey = starfive_hash_setkey, + .base.halg = { .digestsize = SHA384_DIGEST_SIZE, .statesize = sizeof(struct sha512_state), .base = { @@ -778,18 +779,21 @@ static struct ahash_alg algs_sha2_sm3[] = { .cra_alignmask = 3, .cra_module = THIS_MODULE, } - } + }, + .op = { + .do_one_request = starfive_hash_one_request, + }, }, { - .init = starfive_hash_init, - .update = starfive_hash_update, - .final = starfive_hash_final, - .finup = starfive_hash_finup, - .digest = starfive_hash_digest, - .export = starfive_hash_export, - .import = starfive_hash_import, - .init_tfm = starfive_sha512_init_tfm, - .exit_tfm = starfive_hash_exit_tfm, - .halg = { + .base.init = starfive_hash_init, + .base.update = starfive_hash_update, + .base.final = starfive_hash_final, + .base.finup = starfive_hash_finup, + .base.digest = starfive_hash_digest, + .base.export = starfive_hash_export, + .base.import = starfive_hash_import, + .base.init_tfm = starfive_sha512_init_tfm, + .base.exit_tfm = starfive_hash_exit_tfm, + .base.halg = { .digestsize = SHA512_DIGEST_SIZE, .statesize = sizeof(struct sha512_state), .base = { @@ -804,19 +808,22 @@ static struct ahash_alg algs_sha2_sm3[] = { .cra_alignmask = 3, .cra_module = THIS_MODULE, } - } + }, + .op = { + .do_one_request = starfive_hash_one_request, + }, }, { - .init = starfive_hash_init, - .update = starfive_hash_update, - .final = starfive_hash_final, - .finup = starfive_hash_finup, - .digest = starfive_hash_digest, - .export = starfive_hash_export, - .import = starfive_hash_import, - .init_tfm = starfive_hmac_sha512_init_tfm, - .exit_tfm = starfive_hash_exit_tfm, - .setkey = starfive_hash_setkey, - .halg = { + .base.init = starfive_hash_init, + .base.update = starfive_hash_update, + .base.final = starfive_hash_final, + .base.finup = starfive_hash_finup, + .base.digest = starfive_hash_digest, + .base.export = starfive_hash_export, + .base.import = starfive_hash_import, + .base.init_tfm = starfive_hmac_sha512_init_tfm, + .base.exit_tfm = starfive_hash_exit_tfm, + .base.setkey = starfive_hash_setkey, + .base.halg = { .digestsize = SHA512_DIGEST_SIZE, .statesize = sizeof(struct sha512_state), .base = { @@ -831,18 +838,21 @@ static struct ahash_alg algs_sha2_sm3[] = { .cra_alignmask = 3, .cra_module = THIS_MODULE, } - } + }, + .op = { + .do_one_request = starfive_hash_one_request, + }, }, { - .init = starfive_hash_init, - .update = starfive_hash_update, - .final = starfive_hash_final, - .finup = starfive_hash_finup, - .digest = starfive_hash_digest, - .export = starfive_hash_export, - .import = starfive_hash_import, - .init_tfm = starfive_sm3_init_tfm, - .exit_tfm = starfive_hash_exit_tfm, - .halg = { + .base.init = starfive_hash_init, + .base.update = starfive_hash_update, + .base.final = starfive_hash_final, + .base.finup = starfive_hash_finup, + .base.digest = starfive_hash_digest, + .base.export = starfive_hash_export, + .base.import = starfive_hash_import, + .base.init_tfm = starfive_sm3_init_tfm, + .base.exit_tfm = starfive_hash_exit_tfm, + .base.halg = { .digestsize = SM3_DIGEST_SIZE, .statesize = sizeof(struct sm3_state), .base = { @@ -857,19 +867,22 @@ static struct ahash_alg algs_sha2_sm3[] = { .cra_alignmask = 3, .cra_module = THIS_MODULE, } - } + }, + .op = { + .do_one_request = starfive_hash_one_request, + }, }, { - .init = starfive_hash_init, - .update = starfive_hash_update, - .final = starfive_hash_final, - .finup = starfive_hash_finup, - .digest = starfive_hash_digest, - .export = starfive_hash_export, - .import = starfive_hash_import, - .init_tfm = starfive_hmac_sm3_init_tfm, - .exit_tfm = starfive_hash_exit_tfm, - .setkey = starfive_hash_setkey, - .halg = { + .base.init = starfive_hash_init, + .base.update = starfive_hash_update, + .base.final = starfive_hash_final, + .base.finup = starfive_hash_finup, + .base.digest = starfive_hash_digest, + .base.export = starfive_hash_export, + .base.import = starfive_hash_import, + .base.init_tfm = starfive_hmac_sm3_init_tfm, + .base.exit_tfm = starfive_hash_exit_tfm, + .base.setkey = starfive_hash_setkey, + .base.halg = { .digestsize = SM3_DIGEST_SIZE, .statesize = sizeof(struct sm3_state), .base = { @@ -884,16 +897,19 @@ static struct ahash_alg algs_sha2_sm3[] = { .cra_alignmask = 3, .cra_module = THIS_MODULE, } - } + }, + .op = { + .do_one_request = starfive_hash_one_request, + }, }, }; int starfive_hash_register_algs(void) { - return crypto_register_ahashes(algs_sha2_sm3, ARRAY_SIZE(algs_sha2_sm3)); + return crypto_engine_register_ahashes(algs_sha2_sm3, ARRAY_SIZE(algs_sha2_sm3)); } void starfive_hash_unregister_algs(void) { - crypto_unregister_ahashes(algs_sha2_sm3, ARRAY_SIZE(algs_sha2_sm3)); + crypto_engine_unregister_ahashes(algs_sha2_sm3, ARRAY_SIZE(algs_sha2_sm3)); } diff --git a/drivers/crypto/stm32/Kconfig b/drivers/crypto/stm32/Kconfig index 4fc581e9e595..49dfd161e9b9 100644 --- a/drivers/crypto/stm32/Kconfig +++ b/drivers/crypto/stm32/Kconfig @@ -16,6 +16,8 @@ config CRYPTO_DEV_STM32_HASH select CRYPTO_MD5 select CRYPTO_SHA1 select CRYPTO_SHA256 + select CRYPTO_SHA512 + select CRYPTO_SHA3 select CRYPTO_ENGINE help This enables support for the HASH hw accelerator which can be found diff --git a/drivers/crypto/stm32/stm32-cryp.c b/drivers/crypto/stm32/stm32-cryp.c index 6b8d731092a4..f095f0065428 100644 --- a/drivers/crypto/stm32/stm32-cryp.c +++ b/drivers/crypto/stm32/stm32-cryp.c @@ -5,22 +5,24 @@ * Ux500 support taken from snippets in the old Ux500 cryp driver */ +#include <crypto/aes.h> +#include <crypto/engine.h> +#include <crypto/internal/aead.h> +#include <crypto/internal/des.h> +#include <crypto/internal/skcipher.h> +#include <crypto/scatterwalk.h> #include <linux/clk.h> #include <linux/delay.h> -#include <linux/interrupt.h> +#include <linux/err.h> #include <linux/iopoll.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/reset.h> - -#include <crypto/aes.h> -#include <crypto/internal/des.h> -#include <crypto/engine.h> -#include <crypto/scatterwalk.h> -#include <crypto/internal/aead.h> -#include <crypto/internal/skcipher.h> +#include <linux/string.h> #define DRIVER_NAME "stm32-cryp" @@ -156,7 +158,6 @@ struct stm32_cryp_caps { }; struct stm32_cryp_ctx { - struct crypto_engine_ctx enginectx; struct stm32_cryp *cryp; int keylen; __be32 key[AES_KEYSIZE_256 / sizeof(u32)]; @@ -825,35 +826,20 @@ static int stm32_cryp_cpu_start(struct stm32_cryp *cryp) } static int stm32_cryp_cipher_one_req(struct crypto_engine *engine, void *areq); -static int stm32_cryp_prepare_cipher_req(struct crypto_engine *engine, - void *areq); static int stm32_cryp_init_tfm(struct crypto_skcipher *tfm) { - struct stm32_cryp_ctx *ctx = crypto_skcipher_ctx(tfm); - crypto_skcipher_set_reqsize(tfm, sizeof(struct stm32_cryp_reqctx)); - ctx->enginectx.op.do_one_request = stm32_cryp_cipher_one_req; - ctx->enginectx.op.prepare_request = stm32_cryp_prepare_cipher_req; - ctx->enginectx.op.unprepare_request = NULL; return 0; } static int stm32_cryp_aead_one_req(struct crypto_engine *engine, void *areq); -static int stm32_cryp_prepare_aead_req(struct crypto_engine *engine, - void *areq); static int stm32_cryp_aes_aead_init(struct crypto_aead *tfm) { - struct stm32_cryp_ctx *ctx = crypto_aead_ctx(tfm); - tfm->reqsize = sizeof(struct stm32_cryp_reqctx); - ctx->enginectx.op.do_one_request = stm32_cryp_aead_one_req; - ctx->enginectx.op.prepare_request = stm32_cryp_prepare_aead_req; - ctx->enginectx.op.unprepare_request = NULL; - return 0; } @@ -1180,9 +1166,6 @@ static int stm32_cryp_prepare_req(struct skcipher_request *req, cryp = ctx->cryp; - if (!cryp) - return -ENODEV; - rctx = req ? skcipher_request_ctx(req) : aead_request_ctx(areq); rctx->mode &= FLG_MODE_MASK; @@ -1248,16 +1231,6 @@ static int stm32_cryp_prepare_req(struct skcipher_request *req, return ret; } -static int stm32_cryp_prepare_cipher_req(struct crypto_engine *engine, - void *areq) -{ - struct skcipher_request *req = container_of(areq, - struct skcipher_request, - base); - - return stm32_cryp_prepare_req(req, NULL); -} - static int stm32_cryp_cipher_one_req(struct crypto_engine *engine, void *areq) { struct skcipher_request *req = container_of(areq, @@ -1270,15 +1243,8 @@ static int stm32_cryp_cipher_one_req(struct crypto_engine *engine, void *areq) if (!cryp) return -ENODEV; - return stm32_cryp_cpu_start(cryp); -} - -static int stm32_cryp_prepare_aead_req(struct crypto_engine *engine, void *areq) -{ - struct aead_request *req = container_of(areq, struct aead_request, - base); - - return stm32_cryp_prepare_req(NULL, req); + return stm32_cryp_prepare_req(req, NULL) ?: + stm32_cryp_cpu_start(cryp); } static int stm32_cryp_aead_one_req(struct crypto_engine *engine, void *areq) @@ -1287,10 +1253,15 @@ static int stm32_cryp_aead_one_req(struct crypto_engine *engine, void *areq) base); struct stm32_cryp_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); struct stm32_cryp *cryp = ctx->cryp; + int err; if (!cryp) return -ENODEV; + err = stm32_cryp_prepare_req(NULL, req); + if (err) + return err; + if (unlikely(!cryp->payload_in && !cryp->header_in)) { /* No input data to process: get tag and finish */ stm32_cryp_finish_req(cryp, 0); @@ -1709,143 +1680,178 @@ static irqreturn_t stm32_cryp_irq(int irq, void *arg) return IRQ_WAKE_THREAD; } -static struct skcipher_alg crypto_algs[] = { +static struct skcipher_engine_alg crypto_algs[] = { { - .base.cra_name = "ecb(aes)", - .base.cra_driver_name = "stm32-ecb-aes", - .base.cra_priority = 200, - .base.cra_flags = CRYPTO_ALG_ASYNC, - .base.cra_blocksize = AES_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), - .base.cra_alignmask = 0, - .base.cra_module = THIS_MODULE, - - .init = stm32_cryp_init_tfm, - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .setkey = stm32_cryp_aes_setkey, - .encrypt = stm32_cryp_aes_ecb_encrypt, - .decrypt = stm32_cryp_aes_ecb_decrypt, + .base = { + .base.cra_name = "ecb(aes)", + .base.cra_driver_name = "stm32-ecb-aes", + .base.cra_priority = 200, + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = AES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), + .base.cra_alignmask = 0, + .base.cra_module = THIS_MODULE, + + .init = stm32_cryp_init_tfm, + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .setkey = stm32_cryp_aes_setkey, + .encrypt = stm32_cryp_aes_ecb_encrypt, + .decrypt = stm32_cryp_aes_ecb_decrypt, + }, + .op = { + .do_one_request = stm32_cryp_cipher_one_req, + }, }, { - .base.cra_name = "cbc(aes)", - .base.cra_driver_name = "stm32-cbc-aes", - .base.cra_priority = 200, - .base.cra_flags = CRYPTO_ALG_ASYNC, - .base.cra_blocksize = AES_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), - .base.cra_alignmask = 0, - .base.cra_module = THIS_MODULE, - - .init = stm32_cryp_init_tfm, - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = stm32_cryp_aes_setkey, - .encrypt = stm32_cryp_aes_cbc_encrypt, - .decrypt = stm32_cryp_aes_cbc_decrypt, + .base = { + .base.cra_name = "cbc(aes)", + .base.cra_driver_name = "stm32-cbc-aes", + .base.cra_priority = 200, + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = AES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), + .base.cra_alignmask = 0, + .base.cra_module = THIS_MODULE, + + .init = stm32_cryp_init_tfm, + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = stm32_cryp_aes_setkey, + .encrypt = stm32_cryp_aes_cbc_encrypt, + .decrypt = stm32_cryp_aes_cbc_decrypt, + }, + .op = { + .do_one_request = stm32_cryp_cipher_one_req, + }, }, { - .base.cra_name = "ctr(aes)", - .base.cra_driver_name = "stm32-ctr-aes", - .base.cra_priority = 200, - .base.cra_flags = CRYPTO_ALG_ASYNC, - .base.cra_blocksize = 1, - .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), - .base.cra_alignmask = 0, - .base.cra_module = THIS_MODULE, - - .init = stm32_cryp_init_tfm, - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = stm32_cryp_aes_setkey, - .encrypt = stm32_cryp_aes_ctr_encrypt, - .decrypt = stm32_cryp_aes_ctr_decrypt, + .base = { + .base.cra_name = "ctr(aes)", + .base.cra_driver_name = "stm32-ctr-aes", + .base.cra_priority = 200, + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = 1, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), + .base.cra_alignmask = 0, + .base.cra_module = THIS_MODULE, + + .init = stm32_cryp_init_tfm, + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_BLOCK_SIZE, + .setkey = stm32_cryp_aes_setkey, + .encrypt = stm32_cryp_aes_ctr_encrypt, + .decrypt = stm32_cryp_aes_ctr_decrypt, + }, + .op = { + .do_one_request = stm32_cryp_cipher_one_req, + }, }, { - .base.cra_name = "ecb(des)", - .base.cra_driver_name = "stm32-ecb-des", - .base.cra_priority = 200, - .base.cra_flags = CRYPTO_ALG_ASYNC, - .base.cra_blocksize = DES_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), - .base.cra_alignmask = 0, - .base.cra_module = THIS_MODULE, - - .init = stm32_cryp_init_tfm, - .min_keysize = DES_BLOCK_SIZE, - .max_keysize = DES_BLOCK_SIZE, - .setkey = stm32_cryp_des_setkey, - .encrypt = stm32_cryp_des_ecb_encrypt, - .decrypt = stm32_cryp_des_ecb_decrypt, + .base = { + .base.cra_name = "ecb(des)", + .base.cra_driver_name = "stm32-ecb-des", + .base.cra_priority = 200, + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), + .base.cra_alignmask = 0, + .base.cra_module = THIS_MODULE, + + .init = stm32_cryp_init_tfm, + .min_keysize = DES_BLOCK_SIZE, + .max_keysize = DES_BLOCK_SIZE, + .setkey = stm32_cryp_des_setkey, + .encrypt = stm32_cryp_des_ecb_encrypt, + .decrypt = stm32_cryp_des_ecb_decrypt, + }, + .op = { + .do_one_request = stm32_cryp_cipher_one_req, + }, }, { - .base.cra_name = "cbc(des)", - .base.cra_driver_name = "stm32-cbc-des", - .base.cra_priority = 200, - .base.cra_flags = CRYPTO_ALG_ASYNC, - .base.cra_blocksize = DES_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), - .base.cra_alignmask = 0, - .base.cra_module = THIS_MODULE, - - .init = stm32_cryp_init_tfm, - .min_keysize = DES_BLOCK_SIZE, - .max_keysize = DES_BLOCK_SIZE, - .ivsize = DES_BLOCK_SIZE, - .setkey = stm32_cryp_des_setkey, - .encrypt = stm32_cryp_des_cbc_encrypt, - .decrypt = stm32_cryp_des_cbc_decrypt, + .base = { + .base.cra_name = "cbc(des)", + .base.cra_driver_name = "stm32-cbc-des", + .base.cra_priority = 200, + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), + .base.cra_alignmask = 0, + .base.cra_module = THIS_MODULE, + + .init = stm32_cryp_init_tfm, + .min_keysize = DES_BLOCK_SIZE, + .max_keysize = DES_BLOCK_SIZE, + .ivsize = DES_BLOCK_SIZE, + .setkey = stm32_cryp_des_setkey, + .encrypt = stm32_cryp_des_cbc_encrypt, + .decrypt = stm32_cryp_des_cbc_decrypt, + }, + .op = { + .do_one_request = stm32_cryp_cipher_one_req, + }, }, { - .base.cra_name = "ecb(des3_ede)", - .base.cra_driver_name = "stm32-ecb-des3", - .base.cra_priority = 200, - .base.cra_flags = CRYPTO_ALG_ASYNC, - .base.cra_blocksize = DES_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), - .base.cra_alignmask = 0, - .base.cra_module = THIS_MODULE, - - .init = stm32_cryp_init_tfm, - .min_keysize = 3 * DES_BLOCK_SIZE, - .max_keysize = 3 * DES_BLOCK_SIZE, - .setkey = stm32_cryp_tdes_setkey, - .encrypt = stm32_cryp_tdes_ecb_encrypt, - .decrypt = stm32_cryp_tdes_ecb_decrypt, + .base = { + .base.cra_name = "ecb(des3_ede)", + .base.cra_driver_name = "stm32-ecb-des3", + .base.cra_priority = 200, + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), + .base.cra_alignmask = 0, + .base.cra_module = THIS_MODULE, + + .init = stm32_cryp_init_tfm, + .min_keysize = 3 * DES_BLOCK_SIZE, + .max_keysize = 3 * DES_BLOCK_SIZE, + .setkey = stm32_cryp_tdes_setkey, + .encrypt = stm32_cryp_tdes_ecb_encrypt, + .decrypt = stm32_cryp_tdes_ecb_decrypt, + }, + .op = { + .do_one_request = stm32_cryp_cipher_one_req, + }, }, { - .base.cra_name = "cbc(des3_ede)", - .base.cra_driver_name = "stm32-cbc-des3", - .base.cra_priority = 200, - .base.cra_flags = CRYPTO_ALG_ASYNC, - .base.cra_blocksize = DES_BLOCK_SIZE, - .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), - .base.cra_alignmask = 0, - .base.cra_module = THIS_MODULE, - - .init = stm32_cryp_init_tfm, - .min_keysize = 3 * DES_BLOCK_SIZE, - .max_keysize = 3 * DES_BLOCK_SIZE, - .ivsize = DES_BLOCK_SIZE, - .setkey = stm32_cryp_tdes_setkey, - .encrypt = stm32_cryp_tdes_cbc_encrypt, - .decrypt = stm32_cryp_tdes_cbc_decrypt, + .base = { + .base.cra_name = "cbc(des3_ede)", + .base.cra_driver_name = "stm32-cbc-des3", + .base.cra_priority = 200, + .base.cra_flags = CRYPTO_ALG_ASYNC, + .base.cra_blocksize = DES_BLOCK_SIZE, + .base.cra_ctxsize = sizeof(struct stm32_cryp_ctx), + .base.cra_alignmask = 0, + .base.cra_module = THIS_MODULE, + + .init = stm32_cryp_init_tfm, + .min_keysize = 3 * DES_BLOCK_SIZE, + .max_keysize = 3 * DES_BLOCK_SIZE, + .ivsize = DES_BLOCK_SIZE, + .setkey = stm32_cryp_tdes_setkey, + .encrypt = stm32_cryp_tdes_cbc_encrypt, + .decrypt = stm32_cryp_tdes_cbc_decrypt, + }, + .op = { + .do_one_request = stm32_cryp_cipher_one_req, + }, }, }; -static struct aead_alg aead_algs[] = { +static struct aead_engine_alg aead_algs[] = { { - .setkey = stm32_cryp_aes_aead_setkey, - .setauthsize = stm32_cryp_aes_gcm_setauthsize, - .encrypt = stm32_cryp_aes_gcm_encrypt, - .decrypt = stm32_cryp_aes_gcm_decrypt, - .init = stm32_cryp_aes_aead_init, - .ivsize = 12, - .maxauthsize = AES_BLOCK_SIZE, + .base.setkey = stm32_cryp_aes_aead_setkey, + .base.setauthsize = stm32_cryp_aes_gcm_setauthsize, + .base.encrypt = stm32_cryp_aes_gcm_encrypt, + .base.decrypt = stm32_cryp_aes_gcm_decrypt, + .base.init = stm32_cryp_aes_aead_init, + .base.ivsize = 12, + .base.maxauthsize = AES_BLOCK_SIZE, - .base = { + .base.base = { .cra_name = "gcm(aes)", .cra_driver_name = "stm32-gcm-aes", .cra_priority = 200, @@ -1855,17 +1861,20 @@ static struct aead_alg aead_algs[] = { .cra_alignmask = 0, .cra_module = THIS_MODULE, }, + .op = { + .do_one_request = stm32_cryp_aead_one_req, + }, }, { - .setkey = stm32_cryp_aes_aead_setkey, - .setauthsize = stm32_cryp_aes_ccm_setauthsize, - .encrypt = stm32_cryp_aes_ccm_encrypt, - .decrypt = stm32_cryp_aes_ccm_decrypt, - .init = stm32_cryp_aes_aead_init, - .ivsize = AES_BLOCK_SIZE, - .maxauthsize = AES_BLOCK_SIZE, + .base.setkey = stm32_cryp_aes_aead_setkey, + .base.setauthsize = stm32_cryp_aes_ccm_setauthsize, + .base.encrypt = stm32_cryp_aes_ccm_encrypt, + .base.decrypt = stm32_cryp_aes_ccm_decrypt, + .base.init = stm32_cryp_aes_aead_init, + .base.ivsize = AES_BLOCK_SIZE, + .base.maxauthsize = AES_BLOCK_SIZE, - .base = { + .base.base = { .cra_name = "ccm(aes)", .cra_driver_name = "stm32-ccm-aes", .cra_priority = 200, @@ -1875,6 +1884,9 @@ static struct aead_alg aead_algs[] = { .cra_alignmask = 0, .cra_module = THIS_MODULE, }, + .op = { + .do_one_request = stm32_cryp_aead_one_req, + }, }, }; @@ -2036,14 +2048,14 @@ static int stm32_cryp_probe(struct platform_device *pdev) goto err_engine2; } - ret = crypto_register_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs)); + ret = crypto_engine_register_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs)); if (ret) { dev_err(dev, "Could not register algs\n"); goto err_algs; } if (cryp->caps->aeads_support) { - ret = crypto_register_aeads(aead_algs, ARRAY_SIZE(aead_algs)); + ret = crypto_engine_register_aeads(aead_algs, ARRAY_SIZE(aead_algs)); if (ret) goto err_aead_algs; } @@ -2055,7 +2067,7 @@ static int stm32_cryp_probe(struct platform_device *pdev) return 0; err_aead_algs: - crypto_unregister_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs)); + crypto_engine_unregister_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs)); err_algs: err_engine2: crypto_engine_exit(cryp->engine); @@ -2085,8 +2097,8 @@ static int stm32_cryp_remove(struct platform_device *pdev) return ret; if (cryp->caps->aeads_support) - crypto_unregister_aeads(aead_algs, ARRAY_SIZE(aead_algs)); - crypto_unregister_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs)); + crypto_engine_unregister_aeads(aead_algs, ARRAY_SIZE(aead_algs)); + crypto_engine_unregister_skciphers(crypto_algs, ARRAY_SIZE(crypto_algs)); crypto_engine_exit(cryp->engine); diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c index f0df32382719..2b2382d4332c 100644 --- a/drivers/crypto/stm32/stm32-hash.c +++ b/drivers/crypto/stm32/stm32-hash.c @@ -6,27 +6,26 @@ * Author(s): Lionel DEBIEVE <lionel.debieve@st.com> for STMicroelectronics. */ +#include <crypto/engine.h> +#include <crypto/internal/hash.h> +#include <crypto/md5.h> +#include <crypto/scatterwalk.h> +#include <crypto/sha1.h> +#include <crypto/sha2.h> +#include <crypto/sha3.h> #include <linux/clk.h> #include <linux/delay.h> #include <linux/dma-mapping.h> #include <linux/dmaengine.h> #include <linux/interrupt.h> -#include <linux/io.h> #include <linux/iopoll.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/reset.h> - -#include <crypto/engine.h> -#include <crypto/hash.h> -#include <crypto/md5.h> -#include <crypto/scatterwalk.h> -#include <crypto/sha1.h> -#include <crypto/sha2.h> -#include <crypto/internal/hash.h> +#include <linux/string.h> #define HASH_CR 0x00 #define HASH_DIN 0x04 @@ -45,19 +44,11 @@ #define HASH_CR_DMAE BIT(3) #define HASH_CR_DATATYPE_POS 4 #define HASH_CR_MODE BIT(6) +#define HASH_CR_ALGO_POS 7 #define HASH_CR_MDMAT BIT(13) #define HASH_CR_DMAA BIT(14) #define HASH_CR_LKEY BIT(16) -#define HASH_CR_ALGO_SHA1 0x0 -#define HASH_CR_ALGO_MD5 0x80 -#define HASH_CR_ALGO_SHA224 0x40000 -#define HASH_CR_ALGO_SHA256 0x40080 - -#define HASH_CR_UX500_EMPTYMSG BIT(20) -#define HASH_CR_UX500_ALGO_SHA1 BIT(7) -#define HASH_CR_UX500_ALGO_SHA256 0x0 - /* Interrupt */ #define HASH_DINIE BIT(0) #define HASH_DCIE BIT(1) @@ -66,9 +57,6 @@ #define HASH_MASK_CALC_COMPLETION BIT(0) #define HASH_MASK_DATA_INPUT BIT(1) -/* Context swap register */ -#define HASH_CSR_REGISTER_NUMBER 54 - /* Status Flags */ #define HASH_SR_DATA_INPUT_READY BIT(0) #define HASH_SR_OUTPUT_READY BIT(1) @@ -79,28 +67,39 @@ #define HASH_STR_NBLW_MASK GENMASK(4, 0) #define HASH_STR_DCAL BIT(8) +/* HWCFGR Register */ +#define HASH_HWCFG_DMA_MASK GENMASK(3, 0) + +/* Context swap register */ +#define HASH_CSR_NB_SHA256_HMAC 54 +#define HASH_CSR_NB_SHA256 38 +#define HASH_CSR_NB_SHA512_HMAC 103 +#define HASH_CSR_NB_SHA512 91 +#define HASH_CSR_NB_SHA3_HMAC 88 +#define HASH_CSR_NB_SHA3 72 +#define HASH_CSR_NB_MAX HASH_CSR_NB_SHA512_HMAC + #define HASH_FLAGS_INIT BIT(0) #define HASH_FLAGS_OUTPUT_READY BIT(1) #define HASH_FLAGS_CPU BIT(2) -#define HASH_FLAGS_DMA_READY BIT(3) -#define HASH_FLAGS_DMA_ACTIVE BIT(4) -#define HASH_FLAGS_HMAC_INIT BIT(5) -#define HASH_FLAGS_HMAC_FINAL BIT(6) -#define HASH_FLAGS_HMAC_KEY BIT(7) - +#define HASH_FLAGS_DMA_ACTIVE BIT(3) +#define HASH_FLAGS_HMAC_INIT BIT(4) +#define HASH_FLAGS_HMAC_FINAL BIT(5) +#define HASH_FLAGS_HMAC_KEY BIT(6) +#define HASH_FLAGS_SHA3_MODE BIT(7) #define HASH_FLAGS_FINAL BIT(15) #define HASH_FLAGS_FINUP BIT(16) -#define HASH_FLAGS_ALGO_MASK GENMASK(21, 18) -#define HASH_FLAGS_MD5 BIT(18) -#define HASH_FLAGS_SHA1 BIT(19) -#define HASH_FLAGS_SHA224 BIT(20) -#define HASH_FLAGS_SHA256 BIT(21) +#define HASH_FLAGS_ALGO_MASK GENMASK(20, 17) +#define HASH_FLAGS_ALGO_SHIFT 17 +#define HASH_FLAGS_ERRORS BIT(21) #define HASH_FLAGS_EMPTY BIT(22) #define HASH_FLAGS_HMAC BIT(23) #define HASH_OP_UPDATE 1 #define HASH_OP_FINAL 2 +#define HASH_BURST_LEVEL 4 + enum stm32_hash_data_format { HASH_DATA_32_BITS = 0x0, HASH_DATA_16_BITS = 0x1, @@ -108,16 +107,30 @@ enum stm32_hash_data_format { HASH_DATA_1_BIT = 0x3 }; -#define HASH_BUFLEN 256 -#define HASH_LONG_KEY 64 -#define HASH_MAX_KEY_SIZE (SHA256_BLOCK_SIZE * 8) -#define HASH_QUEUE_LENGTH 16 -#define HASH_DMA_THRESHOLD 50 +#define HASH_BUFLEN (SHA3_224_BLOCK_SIZE + 4) +#define HASH_MAX_KEY_SIZE (SHA512_BLOCK_SIZE * 8) + +enum stm32_hash_algo { + HASH_SHA1 = 0, + HASH_MD5 = 1, + HASH_SHA224 = 2, + HASH_SHA256 = 3, + HASH_SHA3_224 = 4, + HASH_SHA3_256 = 5, + HASH_SHA3_384 = 6, + HASH_SHA3_512 = 7, + HASH_SHA384 = 12, + HASH_SHA512 = 15, +}; + +enum ux500_hash_algo { + HASH_SHA256_UX500 = 0, + HASH_SHA1_UX500 = 1, +}; #define HASH_AUTOSUSPEND_DELAY 50 struct stm32_hash_ctx { - struct crypto_engine_ctx enginectx; struct stm32_hash_dev *hdev; struct crypto_shash *xtfm; unsigned long flags; @@ -130,19 +143,19 @@ struct stm32_hash_state { u32 flags; u16 bufcnt; - u16 buflen; + u16 blocklen; u8 buffer[HASH_BUFLEN] __aligned(4); /* hash state */ - u32 hw_context[3 + HASH_CSR_REGISTER_NUMBER]; + u32 hw_context[3 + HASH_CSR_NB_MAX]; }; struct stm32_hash_request_ctx { struct stm32_hash_dev *hdev; unsigned long op; - u8 digest[SHA256_DIGEST_SIZE] __aligned(sizeof(u32)); + u8 digest[SHA512_DIGEST_SIZE] __aligned(sizeof(u32)); size_t digcnt; /* DMA */ @@ -161,17 +174,18 @@ struct stm32_hash_request_ctx { }; struct stm32_hash_algs_info { - struct ahash_alg *algs_list; + struct ahash_engine_alg *algs_list; size_t size; }; struct stm32_hash_pdata { - struct stm32_hash_algs_info *algs_info; - size_t algs_info_size; - bool has_sr; - bool has_mdmat; - bool broken_emptymsg; - bool ux500; + const int alg_shift; + const struct stm32_hash_algs_info *algs_info; + size_t algs_info_size; + bool has_sr; + bool has_mdmat; + bool broken_emptymsg; + bool ux500; }; struct stm32_hash_dev { @@ -182,7 +196,6 @@ struct stm32_hash_dev { void __iomem *io_base; phys_addr_t phys_base; u32 dma_mode; - u32 dma_maxburst; bool polled; struct ahash_request *req; @@ -269,37 +282,25 @@ static int stm32_hash_write_key(struct stm32_hash_dev *hdev) return 0; } -static void stm32_hash_write_ctrl(struct stm32_hash_dev *hdev, int bufcnt) +static void stm32_hash_write_ctrl(struct stm32_hash_dev *hdev) { struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req); struct crypto_ahash *tfm = crypto_ahash_reqtfm(hdev->req); struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm); struct stm32_hash_state *state = &rctx->state; + u32 alg = (state->flags & HASH_FLAGS_ALGO_MASK) >> HASH_FLAGS_ALGO_SHIFT; u32 reg = HASH_CR_INIT; if (!(hdev->flags & HASH_FLAGS_INIT)) { - switch (state->flags & HASH_FLAGS_ALGO_MASK) { - case HASH_FLAGS_MD5: - reg |= HASH_CR_ALGO_MD5; - break; - case HASH_FLAGS_SHA1: - if (hdev->pdata->ux500) - reg |= HASH_CR_UX500_ALGO_SHA1; + if (hdev->pdata->ux500) { + reg |= ((alg & BIT(0)) << HASH_CR_ALGO_POS); + } else { + if (hdev->pdata->alg_shift == HASH_CR_ALGO_POS) + reg |= ((alg & BIT(1)) << 17) | + ((alg & BIT(0)) << HASH_CR_ALGO_POS); else - reg |= HASH_CR_ALGO_SHA1; - break; - case HASH_FLAGS_SHA224: - reg |= HASH_CR_ALGO_SHA224; - break; - case HASH_FLAGS_SHA256: - if (hdev->pdata->ux500) - reg |= HASH_CR_UX500_ALGO_SHA256; - else - reg |= HASH_CR_ALGO_SHA256; - break; - default: - reg |= HASH_CR_ALGO_MD5; + reg |= alg << hdev->pdata->alg_shift; } reg |= (rctx->data_type << HASH_CR_DATATYPE_POS); @@ -307,7 +308,7 @@ static void stm32_hash_write_ctrl(struct stm32_hash_dev *hdev, int bufcnt) if (state->flags & HASH_FLAGS_HMAC) { hdev->flags |= HASH_FLAGS_HMAC; reg |= HASH_CR_MODE; - if (ctx->keylen > HASH_LONG_KEY) + if (ctx->keylen > crypto_ahash_blocksize(tfm)) reg |= HASH_CR_LKEY; } @@ -318,6 +319,12 @@ static void stm32_hash_write_ctrl(struct stm32_hash_dev *hdev, int bufcnt) hdev->flags |= HASH_FLAGS_INIT; + /* + * After first block + 1 words are fill up, + * we only need to fill 1 block to start partial computation + */ + rctx->state.blocklen -= sizeof(u32); + dev_dbg(hdev->dev, "Write Control %x\n", reg); } } @@ -327,9 +334,9 @@ static void stm32_hash_append_sg(struct stm32_hash_request_ctx *rctx) struct stm32_hash_state *state = &rctx->state; size_t count; - while ((state->bufcnt < state->buflen) && rctx->total) { + while ((state->bufcnt < state->blocklen) && rctx->total) { count = min(rctx->sg->length - rctx->offset, rctx->total); - count = min_t(size_t, count, state->buflen - state->bufcnt); + count = min_t(size_t, count, state->blocklen - state->bufcnt); if (count <= 0) { if ((rctx->sg->length == 0) && !sg_is_last(rctx->sg)) { @@ -384,7 +391,7 @@ static int stm32_hash_xmit_cpu(struct stm32_hash_dev *hdev, hdev->flags |= HASH_FLAGS_CPU; - stm32_hash_write_ctrl(hdev, length); + stm32_hash_write_ctrl(hdev); if (stm32_hash_wait_busy(hdev)) return -ETIMEDOUT; @@ -419,20 +426,59 @@ static int stm32_hash_xmit_cpu(struct stm32_hash_dev *hdev, return 0; } +static int hash_swap_reg(struct stm32_hash_request_ctx *rctx) +{ + struct stm32_hash_state *state = &rctx->state; + + switch ((state->flags & HASH_FLAGS_ALGO_MASK) >> + HASH_FLAGS_ALGO_SHIFT) { + case HASH_MD5: + case HASH_SHA1: + case HASH_SHA224: + case HASH_SHA256: + if (state->flags & HASH_FLAGS_HMAC) + return HASH_CSR_NB_SHA256_HMAC; + else + return HASH_CSR_NB_SHA256; + break; + + case HASH_SHA384: + case HASH_SHA512: + if (state->flags & HASH_FLAGS_HMAC) + return HASH_CSR_NB_SHA512_HMAC; + else + return HASH_CSR_NB_SHA512; + break; + + case HASH_SHA3_224: + case HASH_SHA3_256: + case HASH_SHA3_384: + case HASH_SHA3_512: + if (state->flags & HASH_FLAGS_HMAC) + return HASH_CSR_NB_SHA3_HMAC; + else + return HASH_CSR_NB_SHA3; + break; + + default: + return -EINVAL; + } +} + static int stm32_hash_update_cpu(struct stm32_hash_dev *hdev) { struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req); struct stm32_hash_state *state = &rctx->state; u32 *preg = state->hw_context; int bufcnt, err = 0, final; - int i; + int i, swap_reg; dev_dbg(hdev->dev, "%s flags %x\n", __func__, state->flags); final = state->flags & HASH_FLAGS_FINAL; - while ((rctx->total >= state->buflen) || - (state->bufcnt + rctx->total >= state->buflen)) { + while ((rctx->total >= state->blocklen) || + (state->bufcnt + rctx->total >= state->blocklen)) { stm32_hash_append_sg(rctx); bufcnt = state->bufcnt; state->bufcnt = 0; @@ -455,11 +501,13 @@ static int stm32_hash_update_cpu(struct stm32_hash_dev *hdev) if (stm32_hash_wait_busy(hdev)) return -ETIMEDOUT; + swap_reg = hash_swap_reg(rctx); + if (!hdev->pdata->ux500) *preg++ = stm32_hash_read(hdev, HASH_IMR); *preg++ = stm32_hash_read(hdev, HASH_STR); *preg++ = stm32_hash_read(hdev, HASH_CR); - for (i = 0; i < HASH_CSR_REGISTER_NUMBER; i++) + for (i = 0; i < swap_reg; i++) *preg++ = stm32_hash_read(hdev, HASH_CSR(i)); state->flags |= HASH_FLAGS_INIT; @@ -492,7 +540,7 @@ static int stm32_hash_xmit_dma(struct stm32_hash_dev *hdev, reg = stm32_hash_read(hdev, HASH_CR); - if (!hdev->pdata->has_mdmat) { + if (hdev->pdata->has_mdmat) { if (mdma) reg |= HASH_CR_MDMAT; else @@ -533,8 +581,6 @@ static void stm32_hash_dma_callback(void *param) struct stm32_hash_dev *hdev = param; complete(&hdev->dma_completion); - - hdev->flags |= HASH_FLAGS_DMA_READY; } static int stm32_hash_hmac_dma_send(struct stm32_hash_dev *hdev) @@ -544,7 +590,7 @@ static int stm32_hash_hmac_dma_send(struct stm32_hash_dev *hdev) struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm); int err; - if (ctx->keylen < HASH_DMA_THRESHOLD || (hdev->dma_mode == 1)) { + if (ctx->keylen < rctx->state.blocklen || hdev->dma_mode == 1) { err = stm32_hash_write_key(hdev); if (stm32_hash_wait_busy(hdev)) return -ETIMEDOUT; @@ -579,8 +625,8 @@ static int stm32_hash_dma_init(struct stm32_hash_dev *hdev) dma_conf.direction = DMA_MEM_TO_DEV; dma_conf.dst_addr = hdev->phys_base + HASH_DIN; dma_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - dma_conf.src_maxburst = hdev->dma_maxburst; - dma_conf.dst_maxburst = hdev->dma_maxburst; + dma_conf.src_maxburst = HASH_BURST_LEVEL; + dma_conf.dst_maxburst = HASH_BURST_LEVEL; dma_conf.device_fc = false; chan = dma_request_chan(hdev->dev, "in"); @@ -607,18 +653,18 @@ static int stm32_hash_dma_send(struct stm32_hash_dev *hdev) struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req); u32 *buffer = (void *)rctx->state.buffer; struct scatterlist sg[1], *tsg; - int err = 0, len = 0, reg, ncp = 0; - unsigned int i; + int err = 0, reg, ncp = 0; + unsigned int i, len = 0, bufcnt = 0; + bool is_last = false; rctx->sg = hdev->req->src; rctx->total = hdev->req->nbytes; rctx->nents = sg_nents(rctx->sg); - if (rctx->nents < 0) return -EINVAL; - stm32_hash_write_ctrl(hdev, rctx->total); + stm32_hash_write_ctrl(hdev); if (hdev->flags & HASH_FLAGS_HMAC) { err = stm32_hash_hmac_dma_send(hdev); @@ -627,10 +673,12 @@ static int stm32_hash_dma_send(struct stm32_hash_dev *hdev) } for_each_sg(rctx->sg, tsg, rctx->nents, i) { + sg[0] = *tsg; len = sg->length; - sg[0] = *tsg; - if (sg_is_last(sg)) { + if (sg_is_last(sg) || (bufcnt + sg[0].length) >= rctx->total) { + sg->length = rctx->total - bufcnt; + is_last = true; if (hdev->dma_mode == 1) { len = (ALIGN(sg->length, 16) - 16); @@ -656,13 +704,15 @@ static int stm32_hash_dma_send(struct stm32_hash_dev *hdev) return -ENOMEM; } - err = stm32_hash_xmit_dma(hdev, sg, len, - !sg_is_last(sg)); + err = stm32_hash_xmit_dma(hdev, sg, len, !is_last); + bufcnt += sg[0].length; dma_unmap_sg(hdev->dev, sg, 1, DMA_TO_DEVICE); if (err == -ENOMEM) return err; + if (is_last) + break; } if (hdev->dma_mode == 1) { @@ -718,11 +768,12 @@ static struct stm32_hash_dev *stm32_hash_find_dev(struct stm32_hash_ctx *ctx) static bool stm32_hash_dma_aligned_data(struct ahash_request *req) { struct scatterlist *sg; + struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); int i; - if (req->nbytes <= HASH_DMA_THRESHOLD) + if (!hdev->dma_lch || req->nbytes <= rctx->state.blocklen) return false; if (sg_nents(req->src) > 1) { @@ -748,31 +799,64 @@ static int stm32_hash_init(struct ahash_request *req) struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); struct stm32_hash_state *state = &rctx->state; + bool sha3_mode = ctx->flags & HASH_FLAGS_SHA3_MODE; rctx->hdev = hdev; state->flags = HASH_FLAGS_CPU; + if (sha3_mode) + state->flags |= HASH_FLAGS_SHA3_MODE; + rctx->digcnt = crypto_ahash_digestsize(tfm); switch (rctx->digcnt) { case MD5_DIGEST_SIZE: - state->flags |= HASH_FLAGS_MD5; + state->flags |= HASH_MD5 << HASH_FLAGS_ALGO_SHIFT; break; case SHA1_DIGEST_SIZE: - state->flags |= HASH_FLAGS_SHA1; + if (hdev->pdata->ux500) + state->flags |= HASH_SHA1_UX500 << HASH_FLAGS_ALGO_SHIFT; + else + state->flags |= HASH_SHA1 << HASH_FLAGS_ALGO_SHIFT; break; case SHA224_DIGEST_SIZE: - state->flags |= HASH_FLAGS_SHA224; + if (sha3_mode) + state->flags |= HASH_SHA3_224 << HASH_FLAGS_ALGO_SHIFT; + else + state->flags |= HASH_SHA224 << HASH_FLAGS_ALGO_SHIFT; break; case SHA256_DIGEST_SIZE: - state->flags |= HASH_FLAGS_SHA256; + if (sha3_mode) { + state->flags |= HASH_SHA3_256 << HASH_FLAGS_ALGO_SHIFT; + } else { + if (hdev->pdata->ux500) + state->flags |= HASH_SHA256_UX500 << HASH_FLAGS_ALGO_SHIFT; + else + state->flags |= HASH_SHA256 << HASH_FLAGS_ALGO_SHIFT; + } + break; + case SHA384_DIGEST_SIZE: + if (sha3_mode) + state->flags |= HASH_SHA3_384 << HASH_FLAGS_ALGO_SHIFT; + else + state->flags |= HASH_SHA384 << HASH_FLAGS_ALGO_SHIFT; + break; + case SHA512_DIGEST_SIZE: + if (sha3_mode) + state->flags |= HASH_SHA3_512 << HASH_FLAGS_ALGO_SHIFT; + else + state->flags |= HASH_SHA512 << HASH_FLAGS_ALGO_SHIFT; break; default: return -EINVAL; } rctx->state.bufcnt = 0; - rctx->state.buflen = HASH_BUFLEN; + rctx->state.blocklen = crypto_ahash_blocksize(tfm) + sizeof(u32); + if (rctx->state.blocklen > HASH_BUFLEN) { + dev_err(hdev->dev, "Error, block too large"); + return -EINVAL; + } rctx->total = 0; rctx->offset = 0; rctx->data_type = HASH_DATA_8_BITS; @@ -842,6 +926,7 @@ static void stm32_hash_emptymsg_fallback(struct ahash_request *req) static void stm32_hash_copy_hash(struct ahash_request *req) { + struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); struct stm32_hash_state *state = &rctx->state; struct stm32_hash_dev *hdev = rctx->hdev; @@ -851,22 +936,7 @@ static void stm32_hash_copy_hash(struct ahash_request *req) if (hdev->pdata->broken_emptymsg && (state->flags & HASH_FLAGS_EMPTY)) return stm32_hash_emptymsg_fallback(req); - switch (state->flags & HASH_FLAGS_ALGO_MASK) { - case HASH_FLAGS_MD5: - hashsize = MD5_DIGEST_SIZE; - break; - case HASH_FLAGS_SHA1: - hashsize = SHA1_DIGEST_SIZE; - break; - case HASH_FLAGS_SHA224: - hashsize = SHA224_DIGEST_SIZE; - break; - case HASH_FLAGS_SHA256: - hashsize = SHA256_DIGEST_SIZE; - break; - default: - return; - } + hashsize = crypto_ahash_digestsize(tfm); for (i = 0; i < hashsize / sizeof(u32); i++) { if (hdev->pdata->ux500) @@ -881,6 +951,11 @@ static void stm32_hash_copy_hash(struct ahash_request *req) static int stm32_hash_finish(struct ahash_request *req) { struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); + u32 reg; + + reg = stm32_hash_read(rctx->hdev, HASH_SR); + reg &= ~HASH_SR_OUTPUT_READY; + stm32_hash_write(rctx->hdev, HASH_SR, reg); if (!req->result) return -EINVAL; @@ -920,6 +995,7 @@ static int stm32_hash_one_request(struct crypto_engine *engine, void *areq) struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req); struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx); struct stm32_hash_state *state = &rctx->state; + int swap_reg; int err = 0; if (!hdev) @@ -932,6 +1008,7 @@ static int stm32_hash_one_request(struct crypto_engine *engine, void *areq) hdev->req = req; hdev->flags = 0; + swap_reg = hash_swap_reg(rctx); if (state->flags & HASH_FLAGS_INIT) { u32 *preg = rctx->state.hw_context; @@ -945,7 +1022,7 @@ static int stm32_hash_one_request(struct crypto_engine *engine, void *areq) reg = *preg++ | HASH_CR_INIT; stm32_hash_write(hdev, HASH_CR, reg); - for (i = 0; i < HASH_CSR_REGISTER_NUMBER; i++) + for (i = 0; i < swap_reg; i++) stm32_hash_write(hdev, HASH_CSR(i), *preg++); hdev->flags |= HASH_FLAGS_INIT; @@ -1000,7 +1077,7 @@ static int stm32_hash_update(struct ahash_request *req) rctx->sg = req->src; rctx->offset = 0; - if ((state->bufcnt + rctx->total < state->buflen)) { + if ((state->bufcnt + rctx->total < state->blocklen)) { stm32_hash_append_sg(rctx); return 0; } @@ -1102,8 +1179,7 @@ static int stm32_hash_init_fallback(struct crypto_tfm *tfm) return 0; } -static int stm32_hash_cra_init_algs(struct crypto_tfm *tfm, - const char *algs_hmac_name) +static int stm32_hash_cra_init_algs(struct crypto_tfm *tfm, u32 algs_flags) { struct stm32_hash_ctx *ctx = crypto_tfm_ctx(tfm); @@ -1112,38 +1188,33 @@ static int stm32_hash_cra_init_algs(struct crypto_tfm *tfm, ctx->keylen = 0; - if (algs_hmac_name) - ctx->flags |= HASH_FLAGS_HMAC; - - ctx->enginectx.op.do_one_request = stm32_hash_one_request; + if (algs_flags) + ctx->flags |= algs_flags; return stm32_hash_init_fallback(tfm); } static int stm32_hash_cra_init(struct crypto_tfm *tfm) { - return stm32_hash_cra_init_algs(tfm, NULL); + return stm32_hash_cra_init_algs(tfm, 0); } -static int stm32_hash_cra_md5_init(struct crypto_tfm *tfm) +static int stm32_hash_cra_hmac_init(struct crypto_tfm *tfm) { - return stm32_hash_cra_init_algs(tfm, "md5"); + return stm32_hash_cra_init_algs(tfm, HASH_FLAGS_HMAC); } -static int stm32_hash_cra_sha1_init(struct crypto_tfm *tfm) +static int stm32_hash_cra_sha3_init(struct crypto_tfm *tfm) { - return stm32_hash_cra_init_algs(tfm, "sha1"); + return stm32_hash_cra_init_algs(tfm, HASH_FLAGS_SHA3_MODE); } -static int stm32_hash_cra_sha224_init(struct crypto_tfm *tfm) +static int stm32_hash_cra_sha3_hmac_init(struct crypto_tfm *tfm) { - return stm32_hash_cra_init_algs(tfm, "sha224"); + return stm32_hash_cra_init_algs(tfm, HASH_FLAGS_SHA3_MODE | + HASH_FLAGS_HMAC); } -static int stm32_hash_cra_sha256_init(struct crypto_tfm *tfm) -{ - return stm32_hash_cra_init_algs(tfm, "sha256"); -} static void stm32_hash_cra_exit(struct crypto_tfm *tfm) { @@ -1162,11 +1233,9 @@ static irqreturn_t stm32_hash_irq_thread(int irq, void *dev_id) hdev->flags &= ~HASH_FLAGS_OUTPUT_READY; goto finish; } - } else if (HASH_FLAGS_DMA_READY & hdev->flags) { - if (HASH_FLAGS_DMA_ACTIVE & hdev->flags) { - hdev->flags &= ~HASH_FLAGS_DMA_ACTIVE; - goto finish; - } + } else if (HASH_FLAGS_DMA_ACTIVE & hdev->flags) { + hdev->flags &= ~HASH_FLAGS_DMA_ACTIVE; + goto finish; } return IRQ_HANDLED; @@ -1185,8 +1254,6 @@ static irqreturn_t stm32_hash_irq_handler(int irq, void *dev_id) reg = stm32_hash_read(hdev, HASH_SR); if (reg & HASH_SR_OUTPUT_READY) { - reg &= ~HASH_SR_OUTPUT_READY; - stm32_hash_write(hdev, HASH_SR, reg); hdev->flags |= HASH_FLAGS_OUTPUT_READY; /* Disable IT*/ stm32_hash_write(hdev, HASH_IMR, 0); @@ -1196,16 +1263,16 @@ static irqreturn_t stm32_hash_irq_handler(int irq, void *dev_id) return IRQ_NONE; } -static struct ahash_alg algs_md5[] = { +static struct ahash_engine_alg algs_md5[] = { { - .init = stm32_hash_init, - .update = stm32_hash_update, - .final = stm32_hash_final, - .finup = stm32_hash_finup, - .digest = stm32_hash_digest, - .export = stm32_hash_export, - .import = stm32_hash_import, - .halg = { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.halg = { .digestsize = MD5_DIGEST_SIZE, .statesize = sizeof(struct stm32_hash_state), .base = { @@ -1221,18 +1288,21 @@ static struct ahash_alg algs_md5[] = { .cra_exit = stm32_hash_cra_exit, .cra_module = THIS_MODULE, } - } + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, }, { - .init = stm32_hash_init, - .update = stm32_hash_update, - .final = stm32_hash_final, - .finup = stm32_hash_finup, - .digest = stm32_hash_digest, - .export = stm32_hash_export, - .import = stm32_hash_import, - .setkey = stm32_hash_setkey, - .halg = { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.setkey = stm32_hash_setkey, + .base.halg = { .digestsize = MD5_DIGEST_SIZE, .statesize = sizeof(struct stm32_hash_state), .base = { @@ -1244,24 +1314,27 @@ static struct ahash_alg algs_md5[] = { .cra_blocksize = MD5_HMAC_BLOCK_SIZE, .cra_ctxsize = sizeof(struct stm32_hash_ctx), .cra_alignmask = 3, - .cra_init = stm32_hash_cra_md5_init, + .cra_init = stm32_hash_cra_hmac_init, .cra_exit = stm32_hash_cra_exit, .cra_module = THIS_MODULE, } - } - }, + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, + } }; -static struct ahash_alg algs_sha1[] = { +static struct ahash_engine_alg algs_sha1[] = { { - .init = stm32_hash_init, - .update = stm32_hash_update, - .final = stm32_hash_final, - .finup = stm32_hash_finup, - .digest = stm32_hash_digest, - .export = stm32_hash_export, - .import = stm32_hash_import, - .halg = { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.halg = { .digestsize = SHA1_DIGEST_SIZE, .statesize = sizeof(struct stm32_hash_state), .base = { @@ -1277,18 +1350,21 @@ static struct ahash_alg algs_sha1[] = { .cra_exit = stm32_hash_cra_exit, .cra_module = THIS_MODULE, } - } + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, }, { - .init = stm32_hash_init, - .update = stm32_hash_update, - .final = stm32_hash_final, - .finup = stm32_hash_finup, - .digest = stm32_hash_digest, - .export = stm32_hash_export, - .import = stm32_hash_import, - .setkey = stm32_hash_setkey, - .halg = { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.setkey = stm32_hash_setkey, + .base.halg = { .digestsize = SHA1_DIGEST_SIZE, .statesize = sizeof(struct stm32_hash_state), .base = { @@ -1300,24 +1376,27 @@ static struct ahash_alg algs_sha1[] = { .cra_blocksize = SHA1_BLOCK_SIZE, .cra_ctxsize = sizeof(struct stm32_hash_ctx), .cra_alignmask = 3, - .cra_init = stm32_hash_cra_sha1_init, + .cra_init = stm32_hash_cra_hmac_init, .cra_exit = stm32_hash_cra_exit, .cra_module = THIS_MODULE, } - } + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, }, }; -static struct ahash_alg algs_sha224[] = { +static struct ahash_engine_alg algs_sha224[] = { { - .init = stm32_hash_init, - .update = stm32_hash_update, - .final = stm32_hash_final, - .finup = stm32_hash_finup, - .digest = stm32_hash_digest, - .export = stm32_hash_export, - .import = stm32_hash_import, - .halg = { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.halg = { .digestsize = SHA224_DIGEST_SIZE, .statesize = sizeof(struct stm32_hash_state), .base = { @@ -1333,18 +1412,21 @@ static struct ahash_alg algs_sha224[] = { .cra_exit = stm32_hash_cra_exit, .cra_module = THIS_MODULE, } - } + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, }, { - .init = stm32_hash_init, - .update = stm32_hash_update, - .final = stm32_hash_final, - .finup = stm32_hash_finup, - .digest = stm32_hash_digest, - .setkey = stm32_hash_setkey, - .export = stm32_hash_export, - .import = stm32_hash_import, - .halg = { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.setkey = stm32_hash_setkey, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.halg = { .digestsize = SHA224_DIGEST_SIZE, .statesize = sizeof(struct stm32_hash_state), .base = { @@ -1356,24 +1438,27 @@ static struct ahash_alg algs_sha224[] = { .cra_blocksize = SHA224_BLOCK_SIZE, .cra_ctxsize = sizeof(struct stm32_hash_ctx), .cra_alignmask = 3, - .cra_init = stm32_hash_cra_sha224_init, + .cra_init = stm32_hash_cra_hmac_init, .cra_exit = stm32_hash_cra_exit, .cra_module = THIS_MODULE, } - } + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, }, }; -static struct ahash_alg algs_sha256[] = { +static struct ahash_engine_alg algs_sha256[] = { { - .init = stm32_hash_init, - .update = stm32_hash_update, - .final = stm32_hash_final, - .finup = stm32_hash_finup, - .digest = stm32_hash_digest, - .export = stm32_hash_export, - .import = stm32_hash_import, - .halg = { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.halg = { .digestsize = SHA256_DIGEST_SIZE, .statesize = sizeof(struct stm32_hash_state), .base = { @@ -1389,18 +1474,21 @@ static struct ahash_alg algs_sha256[] = { .cra_exit = stm32_hash_cra_exit, .cra_module = THIS_MODULE, } - } + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, }, { - .init = stm32_hash_init, - .update = stm32_hash_update, - .final = stm32_hash_final, - .finup = stm32_hash_finup, - .digest = stm32_hash_digest, - .export = stm32_hash_export, - .import = stm32_hash_import, - .setkey = stm32_hash_setkey, - .halg = { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.setkey = stm32_hash_setkey, + .base.halg = { .digestsize = SHA256_DIGEST_SIZE, .statesize = sizeof(struct stm32_hash_state), .base = { @@ -1412,14 +1500,377 @@ static struct ahash_alg algs_sha256[] = { .cra_blocksize = SHA256_BLOCK_SIZE, .cra_ctxsize = sizeof(struct stm32_hash_ctx), .cra_alignmask = 3, - .cra_init = stm32_hash_cra_sha256_init, + .cra_init = stm32_hash_cra_hmac_init, .cra_exit = stm32_hash_cra_exit, .cra_module = THIS_MODULE, } - } + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, }, }; +static struct ahash_engine_alg algs_sha384_sha512[] = { + { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.halg = { + .digestsize = SHA384_DIGEST_SIZE, + .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "sha384", + .cra_driver_name = "stm32-sha384", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = SHA384_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct stm32_hash_ctx), + .cra_alignmask = 3, + .cra_init = stm32_hash_cra_init, + .cra_exit = stm32_hash_cra_exit, + .cra_module = THIS_MODULE, + } + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, + }, + { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.setkey = stm32_hash_setkey, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.halg = { + .digestsize = SHA384_DIGEST_SIZE, + .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "hmac(sha384)", + .cra_driver_name = "stm32-hmac-sha384", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = SHA384_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct stm32_hash_ctx), + .cra_alignmask = 3, + .cra_init = stm32_hash_cra_hmac_init, + .cra_exit = stm32_hash_cra_exit, + .cra_module = THIS_MODULE, + } + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, + }, + { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.halg = { + .digestsize = SHA512_DIGEST_SIZE, + .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "sha512", + .cra_driver_name = "stm32-sha512", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = SHA512_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct stm32_hash_ctx), + .cra_alignmask = 3, + .cra_init = stm32_hash_cra_init, + .cra_exit = stm32_hash_cra_exit, + .cra_module = THIS_MODULE, + } + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, + }, + { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.setkey = stm32_hash_setkey, + .base.halg = { + .digestsize = SHA512_DIGEST_SIZE, + .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "hmac(sha512)", + .cra_driver_name = "stm32-hmac-sha512", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = SHA512_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct stm32_hash_ctx), + .cra_alignmask = 3, + .cra_init = stm32_hash_cra_hmac_init, + .cra_exit = stm32_hash_cra_exit, + .cra_module = THIS_MODULE, + } + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, + }, +}; + +static struct ahash_engine_alg algs_sha3[] = { + { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.halg = { + .digestsize = SHA3_224_DIGEST_SIZE, + .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "sha3-224", + .cra_driver_name = "stm32-sha3-224", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = SHA3_224_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct stm32_hash_ctx), + .cra_alignmask = 3, + .cra_init = stm32_hash_cra_sha3_init, + .cra_exit = stm32_hash_cra_exit, + .cra_module = THIS_MODULE, + } + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, + }, + { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.setkey = stm32_hash_setkey, + .base.halg = { + .digestsize = SHA3_224_DIGEST_SIZE, + .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "hmac(sha3-224)", + .cra_driver_name = "stm32-hmac-sha3-224", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = SHA3_224_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct stm32_hash_ctx), + .cra_alignmask = 3, + .cra_init = stm32_hash_cra_sha3_hmac_init, + .cra_exit = stm32_hash_cra_exit, + .cra_module = THIS_MODULE, + } + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, + }, + { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.halg = { + .digestsize = SHA3_256_DIGEST_SIZE, + .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "sha3-256", + .cra_driver_name = "stm32-sha3-256", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = SHA3_256_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct stm32_hash_ctx), + .cra_alignmask = 3, + .cra_init = stm32_hash_cra_sha3_init, + .cra_exit = stm32_hash_cra_exit, + .cra_module = THIS_MODULE, + } + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, + }, + { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.setkey = stm32_hash_setkey, + .base.halg = { + .digestsize = SHA3_256_DIGEST_SIZE, + .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "hmac(sha3-256)", + .cra_driver_name = "stm32-hmac-sha3-256", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = SHA3_256_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct stm32_hash_ctx), + .cra_alignmask = 3, + .cra_init = stm32_hash_cra_sha3_hmac_init, + .cra_exit = stm32_hash_cra_exit, + .cra_module = THIS_MODULE, + } + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, + }, + { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.halg = { + .digestsize = SHA3_384_DIGEST_SIZE, + .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "sha3-384", + .cra_driver_name = "stm32-sha3-384", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = SHA3_384_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct stm32_hash_ctx), + .cra_alignmask = 3, + .cra_init = stm32_hash_cra_sha3_init, + .cra_exit = stm32_hash_cra_exit, + .cra_module = THIS_MODULE, + } + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, + }, + { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.setkey = stm32_hash_setkey, + .base.halg = { + .digestsize = SHA3_384_DIGEST_SIZE, + .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "hmac(sha3-384)", + .cra_driver_name = "stm32-hmac-sha3-384", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = SHA3_384_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct stm32_hash_ctx), + .cra_alignmask = 3, + .cra_init = stm32_hash_cra_sha3_hmac_init, + .cra_exit = stm32_hash_cra_exit, + .cra_module = THIS_MODULE, + } + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, + }, + { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.halg = { + .digestsize = SHA3_512_DIGEST_SIZE, + .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "sha3-512", + .cra_driver_name = "stm32-sha3-512", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = SHA3_512_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct stm32_hash_ctx), + .cra_alignmask = 3, + .cra_init = stm32_hash_cra_sha3_init, + .cra_exit = stm32_hash_cra_exit, + .cra_module = THIS_MODULE, + } + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, + }, + { + .base.init = stm32_hash_init, + .base.update = stm32_hash_update, + .base.final = stm32_hash_final, + .base.finup = stm32_hash_finup, + .base.digest = stm32_hash_digest, + .base.export = stm32_hash_export, + .base.import = stm32_hash_import, + .base.setkey = stm32_hash_setkey, + .base.halg = { + .digestsize = SHA3_512_DIGEST_SIZE, + .statesize = sizeof(struct stm32_hash_state), + .base = { + .cra_name = "hmac(sha3-512)", + .cra_driver_name = "stm32-hmac-sha3-512", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, + .cra_blocksize = SHA3_512_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct stm32_hash_ctx), + .cra_alignmask = 3, + .cra_init = stm32_hash_cra_sha3_hmac_init, + .cra_exit = stm32_hash_cra_exit, + .cra_module = THIS_MODULE, + } + }, + .op = { + .do_one_request = stm32_hash_one_request, + }, + } +}; + static int stm32_hash_register_algs(struct stm32_hash_dev *hdev) { unsigned int i, j; @@ -1427,7 +1878,7 @@ static int stm32_hash_register_algs(struct stm32_hash_dev *hdev) for (i = 0; i < hdev->pdata->algs_info_size; i++) { for (j = 0; j < hdev->pdata->algs_info[i].size; j++) { - err = crypto_register_ahash( + err = crypto_engine_register_ahash( &hdev->pdata->algs_info[i].algs_list[j]); if (err) goto err_algs; @@ -1439,7 +1890,7 @@ err_algs: dev_err(hdev->dev, "Algo %d : %d failed\n", i, j); for (; i--; ) { for (; j--;) - crypto_unregister_ahash( + crypto_engine_unregister_ahash( &hdev->pdata->algs_info[i].algs_list[j]); } @@ -1452,7 +1903,7 @@ static int stm32_hash_unregister_algs(struct stm32_hash_dev *hdev) for (i = 0; i < hdev->pdata->algs_info_size; i++) { for (j = 0; j < hdev->pdata->algs_info[i].size; j++) - crypto_unregister_ahash( + crypto_engine_unregister_ahash( &hdev->pdata->algs_info[i].algs_list[j]); } @@ -1471,6 +1922,7 @@ static struct stm32_hash_algs_info stm32_hash_algs_info_ux500[] = { }; static const struct stm32_hash_pdata stm32_hash_pdata_ux500 = { + .alg_shift = 7, .algs_info = stm32_hash_algs_info_ux500, .algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_ux500), .broken_emptymsg = true, @@ -1489,6 +1941,7 @@ static struct stm32_hash_algs_info stm32_hash_algs_info_stm32f4[] = { }; static const struct stm32_hash_pdata stm32_hash_pdata_stm32f4 = { + .alg_shift = 7, .algs_info = stm32_hash_algs_info_stm32f4, .algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_stm32f4), .has_sr = true, @@ -1515,25 +1968,49 @@ static struct stm32_hash_algs_info stm32_hash_algs_info_stm32f7[] = { }; static const struct stm32_hash_pdata stm32_hash_pdata_stm32f7 = { + .alg_shift = 7, .algs_info = stm32_hash_algs_info_stm32f7, .algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_stm32f7), .has_sr = true, .has_mdmat = true, }; -static const struct of_device_id stm32_hash_of_match[] = { +static struct stm32_hash_algs_info stm32_hash_algs_info_stm32mp13[] = { { - .compatible = "stericsson,ux500-hash", - .data = &stm32_hash_pdata_ux500, + .algs_list = algs_sha1, + .size = ARRAY_SIZE(algs_sha1), + }, + { + .algs_list = algs_sha224, + .size = ARRAY_SIZE(algs_sha224), + }, + { + .algs_list = algs_sha256, + .size = ARRAY_SIZE(algs_sha256), }, { - .compatible = "st,stm32f456-hash", - .data = &stm32_hash_pdata_stm32f4, + .algs_list = algs_sha384_sha512, + .size = ARRAY_SIZE(algs_sha384_sha512), }, { - .compatible = "st,stm32f756-hash", - .data = &stm32_hash_pdata_stm32f7, + .algs_list = algs_sha3, + .size = ARRAY_SIZE(algs_sha3), }, +}; + +static const struct stm32_hash_pdata stm32_hash_pdata_stm32mp13 = { + .alg_shift = 17, + .algs_info = stm32_hash_algs_info_stm32mp13, + .algs_info_size = ARRAY_SIZE(stm32_hash_algs_info_stm32mp13), + .has_sr = true, + .has_mdmat = true, +}; + +static const struct of_device_id stm32_hash_of_match[] = { + { .compatible = "stericsson,ux500-hash", .data = &stm32_hash_pdata_ux500 }, + { .compatible = "st,stm32f456-hash", .data = &stm32_hash_pdata_stm32f4 }, + { .compatible = "st,stm32f756-hash", .data = &stm32_hash_pdata_stm32f7 }, + { .compatible = "st,stm32mp13-hash", .data = &stm32_hash_pdata_stm32mp13 }, {}, }; @@ -1548,12 +2025,6 @@ static int stm32_hash_get_of_match(struct stm32_hash_dev *hdev, return -EINVAL; } - if (of_property_read_u32(dev->of_node, "dma-maxburst", - &hdev->dma_maxburst)) { - dev_info(dev, "dma-maxburst not specified, using 0\n"); - hdev->dma_maxburst = 0; - } - return 0; } @@ -1663,7 +2134,7 @@ static int stm32_hash_probe(struct platform_device *pdev) /* FIXME: implement DMA mode for Ux500 */ hdev->dma_mode = 0; else - hdev->dma_mode = stm32_hash_read(hdev, HASH_HWCFGR); + hdev->dma_mode = stm32_hash_read(hdev, HASH_HWCFGR) & HASH_HWCFG_DMA_MASK; /* Register algos */ ret = stm32_hash_register_algs(hdev); @@ -1696,18 +2167,12 @@ err_reset: return ret; } -static int stm32_hash_remove(struct platform_device *pdev) +static void stm32_hash_remove(struct platform_device *pdev) { - struct stm32_hash_dev *hdev; + struct stm32_hash_dev *hdev = platform_get_drvdata(pdev); int ret; - hdev = platform_get_drvdata(pdev); - if (!hdev) - return -ENODEV; - - ret = pm_runtime_resume_and_get(hdev->dev); - if (ret < 0) - return ret; + ret = pm_runtime_get_sync(hdev->dev); stm32_hash_unregister_algs(hdev); @@ -1723,9 +2188,8 @@ static int stm32_hash_remove(struct platform_device *pdev) pm_runtime_disable(hdev->dev); pm_runtime_put_noidle(hdev->dev); - clk_disable_unprepare(hdev->clk); - - return 0; + if (ret >= 0) + clk_disable_unprepare(hdev->clk); } #ifdef CONFIG_PM @@ -1762,7 +2226,7 @@ static const struct dev_pm_ops stm32_hash_pm_ops = { static struct platform_driver stm32_hash_driver = { .probe = stm32_hash_probe, - .remove = stm32_hash_remove, + .remove_new = stm32_hash_remove, .driver = { .name = "stm32-hash", .pm = &stm32_hash_pm_ops, @@ -1772,6 +2236,6 @@ static struct platform_driver stm32_hash_driver = { module_platform_driver(stm32_hash_driver); -MODULE_DESCRIPTION("STM32 SHA1/224/256 & MD5 (HMAC) hw accelerator driver"); +MODULE_DESCRIPTION("STM32 SHA1/SHA2/SHA3 & MD5 (HMAC) hw accelerator driver"); MODULE_AUTHOR("Lionel Debieve <lionel.debieve@st.com>"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index bb27f011cf31..4ca4fbd227bc 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -19,9 +19,9 @@ #include <linux/interrupt.h> #include <linux/crypto.h> #include <linux/hw_random.h> -#include <linux/of_address.h> +#include <linux/of.h> #include <linux/of_irq.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <linux/io.h> #include <linux/spinlock.h> diff --git a/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c b/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c index 6963344f6a3a..2621ff8a9376 100644 --- a/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c +++ b/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c @@ -7,15 +7,16 @@ * Copyright 2022 Bytedance CO., LTD. */ -#include <linux/mpi.h> -#include <linux/scatterlist.h> -#include <crypto/algapi.h> +#include <crypto/engine.h> #include <crypto/internal/akcipher.h> #include <crypto/internal/rsa.h> -#include <linux/err.h> #include <crypto/scatterwalk.h> -#include <linux/atomic.h> - +#include <linux/err.h> +#include <linux/kernel.h> +#include <linux/mpi.h> +#include <linux/scatterlist.h> +#include <linux/slab.h> +#include <linux/string.h> #include <uapi/linux/virtio_crypto.h> #include "virtio_crypto_common.h" @@ -24,7 +25,6 @@ struct virtio_crypto_rsa_ctx { }; struct virtio_crypto_akcipher_ctx { - struct crypto_engine_ctx enginectx; struct virtio_crypto *vcrypto; struct crypto_akcipher *tfm; bool session_valid; @@ -47,7 +47,7 @@ struct virtio_crypto_akcipher_algo { uint32_t algonum; uint32_t service; unsigned int active_devs; - struct akcipher_alg algo; + struct akcipher_engine_alg algo; }; static DEFINE_MUTEX(algs_lock); @@ -475,9 +475,6 @@ static int virtio_crypto_rsa_init_tfm(struct crypto_akcipher *tfm) struct virtio_crypto_akcipher_ctx *ctx = akcipher_tfm_ctx(tfm); ctx->tfm = tfm; - ctx->enginectx.op.do_one_request = virtio_crypto_rsa_do_req; - ctx->enginectx.op.prepare_request = NULL; - ctx->enginectx.op.unprepare_request = NULL; akcipher_set_reqsize(tfm, sizeof(struct virtio_crypto_akcipher_request)); @@ -500,7 +497,7 @@ static struct virtio_crypto_akcipher_algo virtio_crypto_akcipher_algs[] = { { .algonum = VIRTIO_CRYPTO_AKCIPHER_RSA, .service = VIRTIO_CRYPTO_SERVICE_AKCIPHER, - .algo = { + .algo.base = { .encrypt = virtio_crypto_rsa_encrypt, .decrypt = virtio_crypto_rsa_decrypt, .set_pub_key = virtio_crypto_rsa_raw_set_pub_key, @@ -516,11 +513,14 @@ static struct virtio_crypto_akcipher_algo virtio_crypto_akcipher_algs[] = { .cra_ctxsize = sizeof(struct virtio_crypto_akcipher_ctx), }, }, + .algo.op = { + .do_one_request = virtio_crypto_rsa_do_req, + }, }, { .algonum = VIRTIO_CRYPTO_AKCIPHER_RSA, .service = VIRTIO_CRYPTO_SERVICE_AKCIPHER, - .algo = { + .algo.base = { .encrypt = virtio_crypto_rsa_encrypt, .decrypt = virtio_crypto_rsa_decrypt, .sign = virtio_crypto_rsa_sign, @@ -538,6 +538,9 @@ static struct virtio_crypto_akcipher_algo virtio_crypto_akcipher_algs[] = { .cra_ctxsize = sizeof(struct virtio_crypto_akcipher_ctx), }, }, + .algo.op = { + .do_one_request = virtio_crypto_rsa_do_req, + }, }, }; @@ -556,14 +559,14 @@ int virtio_crypto_akcipher_algs_register(struct virtio_crypto *vcrypto) continue; if (virtio_crypto_akcipher_algs[i].active_devs == 0) { - ret = crypto_register_akcipher(&virtio_crypto_akcipher_algs[i].algo); + ret = crypto_engine_register_akcipher(&virtio_crypto_akcipher_algs[i].algo); if (ret) goto unlock; } virtio_crypto_akcipher_algs[i].active_devs++; dev_info(&vcrypto->vdev->dev, "Registered akcipher algo %s\n", - virtio_crypto_akcipher_algs[i].algo.base.cra_name); + virtio_crypto_akcipher_algs[i].algo.base.base.cra_name); } unlock: @@ -586,7 +589,7 @@ void virtio_crypto_akcipher_algs_unregister(struct virtio_crypto *vcrypto) continue; if (virtio_crypto_akcipher_algs[i].active_devs == 1) - crypto_unregister_akcipher(&virtio_crypto_akcipher_algs[i].algo); + crypto_engine_unregister_akcipher(&virtio_crypto_akcipher_algs[i].algo); virtio_crypto_akcipher_algs[i].active_devs--; } diff --git a/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c b/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c index e5876286828b..23c41d87d835 100644 --- a/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c +++ b/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c @@ -6,19 +6,16 @@ * Copyright 2016 HUAWEI TECHNOLOGIES CO., LTD. */ -#include <linux/scatterlist.h> -#include <crypto/algapi.h> +#include <crypto/engine.h> #include <crypto/internal/skcipher.h> -#include <linux/err.h> #include <crypto/scatterwalk.h> -#include <linux/atomic.h> - +#include <linux/err.h> +#include <linux/scatterlist.h> #include <uapi/linux/virtio_crypto.h> #include "virtio_crypto_common.h" struct virtio_crypto_skcipher_ctx { - struct crypto_engine_ctx enginectx; struct virtio_crypto *vcrypto; struct crypto_skcipher *tfm; @@ -42,7 +39,7 @@ struct virtio_crypto_algo { uint32_t algonum; uint32_t service; unsigned int active_devs; - struct skcipher_alg algo; + struct skcipher_engine_alg algo; }; /* @@ -523,9 +520,6 @@ static int virtio_crypto_skcipher_init(struct crypto_skcipher *tfm) crypto_skcipher_set_reqsize(tfm, sizeof(struct virtio_crypto_sym_request)); ctx->tfm = tfm; - ctx->enginectx.op.do_one_request = virtio_crypto_skcipher_crypt_req; - ctx->enginectx.op.prepare_request = NULL; - ctx->enginectx.op.unprepare_request = NULL; return 0; } @@ -580,7 +574,7 @@ static void virtio_crypto_skcipher_finalize_req( static struct virtio_crypto_algo virtio_crypto_algs[] = { { .algonum = VIRTIO_CRYPTO_CIPHER_AES_CBC, .service = VIRTIO_CRYPTO_SERVICE_CIPHER, - .algo = { + .algo.base = { .base.cra_name = "cbc(aes)", .base.cra_driver_name = "virtio_crypto_aes_cbc", .base.cra_priority = 150, @@ -598,6 +592,9 @@ static struct virtio_crypto_algo virtio_crypto_algs[] = { { .max_keysize = AES_MAX_KEY_SIZE, .ivsize = AES_BLOCK_SIZE, }, + .algo.op = { + .do_one_request = virtio_crypto_skcipher_crypt_req, + }, } }; int virtio_crypto_skcipher_algs_register(struct virtio_crypto *vcrypto) @@ -616,14 +613,14 @@ int virtio_crypto_skcipher_algs_register(struct virtio_crypto *vcrypto) continue; if (virtio_crypto_algs[i].active_devs == 0) { - ret = crypto_register_skcipher(&virtio_crypto_algs[i].algo); + ret = crypto_engine_register_skcipher(&virtio_crypto_algs[i].algo); if (ret) goto unlock; } virtio_crypto_algs[i].active_devs++; dev_info(&vcrypto->vdev->dev, "Registered algo %s\n", - virtio_crypto_algs[i].algo.base.cra_name); + virtio_crypto_algs[i].algo.base.base.cra_name); } unlock: @@ -647,7 +644,7 @@ void virtio_crypto_skcipher_algs_unregister(struct virtio_crypto *vcrypto) continue; if (virtio_crypto_algs[i].active_devs == 1) - crypto_unregister_skcipher(&virtio_crypto_algs[i].algo); + crypto_engine_unregister_skcipher(&virtio_crypto_algs[i].algo); virtio_crypto_algs[i].active_devs--; } diff --git a/drivers/crypto/xilinx/zynqmp-aes-gcm.c b/drivers/crypto/xilinx/zynqmp-aes-gcm.c index bf1f421e05f2..ce335578b759 100644 --- a/drivers/crypto/xilinx/zynqmp-aes-gcm.c +++ b/drivers/crypto/xilinx/zynqmp-aes-gcm.c @@ -9,13 +9,14 @@ #include <crypto/gcm.h> #include <crypto/internal/aead.h> #include <crypto/scatterwalk.h> - #include <linux/dma-mapping.h> +#include <linux/err.h> +#include <linux/firmware/xlnx-zynqmp.h> +#include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/mod_devicetable.h> #include <linux/platform_device.h> - -#include <linux/firmware/xlnx-zynqmp.h> +#include <linux/string.h> #define ZYNQMP_DMA_BIT_MASK 32U @@ -43,7 +44,7 @@ enum zynqmp_aead_keysrc { struct zynqmp_aead_drv_ctx { union { - struct aead_alg aead; + struct aead_engine_alg aead; } alg; struct device *dev; struct crypto_engine *engine; @@ -60,7 +61,6 @@ struct zynqmp_aead_hw_req { }; struct zynqmp_aead_tfm_ctx { - struct crypto_engine_ctx engine_ctx; struct device *dev; u8 key[ZYNQMP_AES_KEY_SIZE]; u8 *iv; @@ -286,7 +286,7 @@ static int zynqmp_aes_aead_encrypt(struct aead_request *req) struct zynqmp_aead_req_ctx *rq_ctx = aead_request_ctx(req); rq_ctx->op = ZYNQMP_AES_ENCRYPT; - drv_ctx = container_of(alg, struct zynqmp_aead_drv_ctx, alg.aead); + drv_ctx = container_of(alg, struct zynqmp_aead_drv_ctx, alg.aead.base); return crypto_transfer_aead_request_to_engine(drv_ctx->engine, req); } @@ -299,7 +299,7 @@ static int zynqmp_aes_aead_decrypt(struct aead_request *req) struct zynqmp_aead_req_ctx *rq_ctx = aead_request_ctx(req); rq_ctx->op = ZYNQMP_AES_DECRYPT; - drv_ctx = container_of(alg, struct zynqmp_aead_drv_ctx, alg.aead); + drv_ctx = container_of(alg, struct zynqmp_aead_drv_ctx, alg.aead.base); return crypto_transfer_aead_request_to_engine(drv_ctx->engine, req); } @@ -312,20 +312,16 @@ static int zynqmp_aes_aead_init(struct crypto_aead *aead) struct zynqmp_aead_drv_ctx *drv_ctx; struct aead_alg *alg = crypto_aead_alg(aead); - drv_ctx = container_of(alg, struct zynqmp_aead_drv_ctx, alg.aead); + drv_ctx = container_of(alg, struct zynqmp_aead_drv_ctx, alg.aead.base); tfm_ctx->dev = drv_ctx->dev; - tfm_ctx->engine_ctx.op.do_one_request = zynqmp_handle_aes_req; - tfm_ctx->engine_ctx.op.prepare_request = NULL; - tfm_ctx->engine_ctx.op.unprepare_request = NULL; - - tfm_ctx->fbk_cipher = crypto_alloc_aead(drv_ctx->alg.aead.base.cra_name, + tfm_ctx->fbk_cipher = crypto_alloc_aead(drv_ctx->alg.aead.base.base.cra_name, 0, CRYPTO_ALG_NEED_FALLBACK); if (IS_ERR(tfm_ctx->fbk_cipher)) { pr_err("%s() Error: failed to allocate fallback for %s\n", - __func__, drv_ctx->alg.aead.base.cra_name); + __func__, drv_ctx->alg.aead.base.base.cra_name); return PTR_ERR(tfm_ctx->fbk_cipher); } @@ -350,7 +346,7 @@ static void zynqmp_aes_aead_exit(struct crypto_aead *aead) } static struct zynqmp_aead_drv_ctx aes_drv_ctx = { - .alg.aead = { + .alg.aead.base = { .setkey = zynqmp_aes_aead_setkey, .setauthsize = zynqmp_aes_aead_setauthsize, .encrypt = zynqmp_aes_aead_encrypt, @@ -372,7 +368,10 @@ static struct zynqmp_aead_drv_ctx aes_drv_ctx = { .cra_ctxsize = sizeof(struct zynqmp_aead_tfm_ctx), .cra_module = THIS_MODULE, } - } + }, + .alg.aead.op = { + .do_one_request = zynqmp_handle_aes_req, + }, }; static int zynqmp_aes_aead_probe(struct platform_device *pdev) @@ -405,7 +404,7 @@ static int zynqmp_aes_aead_probe(struct platform_device *pdev) goto err_engine; } - err = crypto_register_aead(&aes_drv_ctx.alg.aead); + err = crypto_engine_register_aead(&aes_drv_ctx.alg.aead); if (err < 0) { dev_err(dev, "Failed to register AEAD alg.\n"); goto err_aead; @@ -413,7 +412,7 @@ static int zynqmp_aes_aead_probe(struct platform_device *pdev) return 0; err_aead: - crypto_unregister_aead(&aes_drv_ctx.alg.aead); + crypto_engine_unregister_aead(&aes_drv_ctx.alg.aead); err_engine: if (aes_drv_ctx.engine) @@ -425,7 +424,7 @@ err_engine: static int zynqmp_aes_aead_remove(struct platform_device *pdev) { crypto_engine_exit(aes_drv_ctx.engine); - crypto_unregister_aead(&aes_drv_ctx.alg.aead); + crypto_engine_unregister_aead(&aes_drv_ctx.alg.aead); return 0; } diff --git a/drivers/crypto/xilinx/zynqmp-sha.c b/drivers/crypto/xilinx/zynqmp-sha.c index 43ff170ff1c2..426bf1a72ba6 100644 --- a/drivers/crypto/xilinx/zynqmp-sha.c +++ b/drivers/crypto/xilinx/zynqmp-sha.c @@ -15,7 +15,6 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #define ZYNQMP_DMA_BIT_MASK 32U diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index e36cbb920ec8..474d81831ad3 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -472,10 +472,11 @@ static void devfreq_monitor(struct work_struct *work) * devfreq_monitor_start() - Start load monitoring of devfreq instance * @devfreq: the devfreq instance. * - * Helper function for starting devfreq device load monitoring. By - * default delayed work based monitoring is supported. Function - * to be called from governor in response to DEVFREQ_GOV_START - * event when device is added to devfreq framework. + * Helper function for starting devfreq device load monitoring. By default, + * deferrable timer is used for load monitoring. But the users can change this + * behavior using the "timer" type in devfreq_dev_profile. This function will be + * called by devfreq governor in response to the DEVFREQ_GOV_START event + * generated while adding a device to the devfreq framework. */ void devfreq_monitor_start(struct devfreq *devfreq) { @@ -763,6 +764,7 @@ static void devfreq_dev_release(struct device *dev) dev_pm_opp_put_opp_table(devfreq->opp_table); mutex_destroy(&devfreq->lock); + srcu_cleanup_notifier_head(&devfreq->transition_notifier_list); kfree(devfreq); } diff --git a/drivers/devfreq/imx-bus.c b/drivers/devfreq/imx-bus.c index a727067980fb..86850b7dea09 100644 --- a/drivers/devfreq/imx-bus.c +++ b/drivers/devfreq/imx-bus.c @@ -7,7 +7,7 @@ #include <linux/devfreq.h> #include <linux/device.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/pm_opp.h> #include <linux/platform_device.h> #include <linux/slab.h> diff --git a/drivers/devfreq/imx8m-ddrc.c b/drivers/devfreq/imx8m-ddrc.c index 16636973eb10..e1348490c8aa 100644 --- a/drivers/devfreq/imx8m-ddrc.c +++ b/drivers/devfreq/imx8m-ddrc.c @@ -3,9 +3,9 @@ * Copyright 2019 NXP */ +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/device.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/devfreq.h> #include <linux/pm_opp.h> diff --git a/drivers/devfreq/mtk-cci-devfreq.c b/drivers/devfreq/mtk-cci-devfreq.c index 6354622eda65..83a73f0ccd80 100644 --- a/drivers/devfreq/mtk-cci-devfreq.c +++ b/drivers/devfreq/mtk-cci-devfreq.c @@ -8,7 +8,6 @@ #include <linux/minmax.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_opp.h> #include <linux/regulator/consumer.h> diff --git a/drivers/devfreq/tegra30-devfreq.c b/drivers/devfreq/tegra30-devfreq.c index 503376b894b6..4a4f0106ab9d 100644 --- a/drivers/devfreq/tegra30-devfreq.c +++ b/drivers/devfreq/tegra30-devfreq.c @@ -13,7 +13,7 @@ #include <linux/io.h> #include <linux/irq.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_opp.h> #include <linux/reset.h> diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index 63f0aeb66db6..f0a35277fd84 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -191,6 +191,7 @@ static const struct dma_fence_ops timeline_fence_ops = { */ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) { + LIST_HEAD(signalled); struct sync_pt *pt, *next; trace_sync_timeline(obj); @@ -203,21 +204,20 @@ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) if (!timeline_fence_signaled(&pt->base)) break; - list_del_init(&pt->link); + dma_fence_get(&pt->base); + + list_move_tail(&pt->link, &signalled); rb_erase(&pt->node, &obj->pt_tree); - /* - * A signal callback may release the last reference to this - * fence, causing it to be freed. That operation has to be - * last to avoid a use after free inside this loop, and must - * be after we remove the fence from the timeline in order to - * prevent deadlocking on timeline->lock inside - * timeline_fence_release(). - */ dma_fence_signal_locked(&pt->base); } spin_unlock_irq(&obj->lock); + + list_for_each_entry_safe(pt, next, &signalled, link) { + list_del_init(&pt->link); + dma_fence_put(&pt->base); + } } /** diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 597dae7692b1..9b6642d00871 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -4150,6 +4150,20 @@ static int per_family_init(struct amd64_pvt *pvt) } break; + case 0x1A: + switch (pvt->model) { + case 0x00 ... 0x1f: + pvt->ctl_name = "F1Ah"; + pvt->max_mcs = 12; + pvt->flags.zn_regs_v2 = 1; + break; + case 0x40 ... 0x4f: + pvt->ctl_name = "F1Ah_M40h"; + pvt->flags.zn_regs_v2 = 1; + break; + } + break; + default: amd64_err("Unsupported family!\n"); return -ENODEV; @@ -4344,6 +4358,7 @@ static const struct x86_cpu_id amd64_cpuids[] = { X86_MATCH_VENDOR_FAM(AMD, 0x17, NULL), X86_MATCH_VENDOR_FAM(HYGON, 0x18, NULL), X86_MATCH_VENDOR_FAM(AMD, 0x19, NULL), + X86_MATCH_VENDOR_FAM(AMD, 0x1A, NULL), { } }; MODULE_DEVICE_TABLE(x86cpu, amd64_cpuids); diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c index a897b6aff368..5abf997ca7c1 100644 --- a/drivers/edac/i10nm_base.c +++ b/drivers/edac/i10nm_base.c @@ -906,7 +906,7 @@ static const struct x86_cpu_id i10nm_cpuids[] = { X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(SAPPHIRERAPIDS_X, X86_STEPPINGS(0x0, 0xf), &spr_cfg), X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(EMERALDRAPIDS_X, X86_STEPPINGS(0x0, 0xf), &spr_cfg), X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(GRANITERAPIDS_X, X86_STEPPINGS(0x0, 0xf), &gnr_cfg), - X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(SIERRAFOREST_X, X86_STEPPINGS(0x0, 0xf), &gnr_cfg), + X86_MATCH_INTEL_FAM6_MODEL_STEPPINGS(ATOM_CRESTMONT_X, X86_STEPPINGS(0x0, 0xf), &gnr_cfg), {} }; MODULE_DEVICE_TABLE(x86cpu, i10nm_cpuids); diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index 713582cc27d1..33f0ba11c6ad 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -60,7 +60,7 @@ static void __init eisa_name_device(struct eisa_device *edev) int i; for (i = 0; i < EISA_INFOS; i++) { if (!strcmp(edev->id.sig, eisa_table[i].id.sig)) { - strlcpy(edev->pretty_name, + strscpy(edev->pretty_name, eisa_table[i].name, sizeof(edev->pretty_name)); return; diff --git a/drivers/firmware/arm_sdei.c b/drivers/firmware/arm_sdei.c index f9040bd61081..285fe7ad490d 100644 --- a/drivers/firmware/arm_sdei.c +++ b/drivers/firmware/arm_sdei.c @@ -1095,3 +1095,22 @@ int sdei_event_handler(struct pt_regs *regs, return err; } NOKPROBE_SYMBOL(sdei_event_handler); + +void sdei_handler_abort(void) +{ + /* + * If the crash happened in an SDEI event handler then we need to + * finish the handler with the firmware so that we can have working + * interrupts in the crash kernel. + */ + if (__this_cpu_read(sdei_active_critical_event)) { + pr_warn("still in SDEI critical event context, attempting to finish handler.\n"); + __sdei_handler_abort(); + __this_cpu_write(sdei_active_critical_event, NULL); + } + if (__this_cpu_read(sdei_active_normal_event)) { + pr_warn("still in SDEI normal event context, attempting to finish handler.\n"); + __sdei_handler_abort(); + __this_cpu_write(sdei_active_normal_event, NULL); + } +} diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index 16d64a34d1e1..92389a5481ff 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile @@ -88,6 +88,7 @@ lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o \ lib-$(CONFIG_ARM) += arm32-stub.o lib-$(CONFIG_ARM64) += arm64.o arm64-stub.o smbios.o lib-$(CONFIG_X86) += x86-stub.o +lib-$(CONFIG_X86_64) += x86-5lvl.o lib-$(CONFIG_RISCV) += riscv.o riscv-stub.o lib-$(CONFIG_LOONGARCH) += loongarch.o loongarch-stub.o @@ -146,7 +147,7 @@ STUBCOPY_RELOC-$(CONFIG_ARM64) := R_AARCH64_ABS # For RISC-V, we don't need anything special other than arm64. Keep all the # symbols in .init section and make sure that no absolute symbols references -# doesn't exist. +# exist. STUBCOPY_FLAGS-$(CONFIG_RISCV) += --prefix-alloc-sections=.init \ --prefix-symbols=__efistub_ STUBCOPY_RELOC-$(CONFIG_RISCV) := R_RISCV_HI20 diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c index 770b8ecb7398..8c40fc89f5f9 100644 --- a/drivers/firmware/efi/libstub/arm64-stub.c +++ b/drivers/firmware/efi/libstub/arm64-stub.c @@ -106,7 +106,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, */ status = efi_random_alloc(*reserve_size, min_kimg_align, reserve_addr, phys_seed, - EFI_LOADER_CODE); + EFI_LOADER_CODE, EFI_ALLOC_LIMIT); if (status != EFI_SUCCESS) efi_warn("efi_random_alloc() failed: 0x%lx\n", status); } else { diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index 732984295295..bfa30625f5d0 100644 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -73,6 +73,8 @@ efi_status_t efi_parse_options(char const *cmdline) efi_loglevel = CONSOLE_LOGLEVEL_QUIET; } else if (!strcmp(param, "noinitrd")) { efi_noinitrd = true; + } else if (IS_ENABLED(CONFIG_X86_64) && !strcmp(param, "no5lvl")) { + efi_no5lvl = true; } else if (!strcmp(param, "efi") && val) { efi_nochunk = parse_option_str(val, "nochunk"); efi_novamap |= parse_option_str(val, "novamap"); diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index 6aa38a1bf126..9823f6fb3e01 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -33,6 +33,7 @@ #define EFI_ALLOC_LIMIT ULONG_MAX #endif +extern bool efi_no5lvl; extern bool efi_nochunk; extern bool efi_nokaslr; extern int efi_loglevel; @@ -955,7 +956,7 @@ efi_status_t efi_get_random_bytes(unsigned long size, u8 *out); efi_status_t efi_random_alloc(unsigned long size, unsigned long align, unsigned long *addr, unsigned long random_seed, - int memory_type); + int memory_type, unsigned long alloc_limit); efi_status_t efi_random_get_seed(void); diff --git a/drivers/firmware/efi/libstub/randomalloc.c b/drivers/firmware/efi/libstub/randomalloc.c index 32c7a54923b4..674a064b8f7a 100644 --- a/drivers/firmware/efi/libstub/randomalloc.c +++ b/drivers/firmware/efi/libstub/randomalloc.c @@ -16,7 +16,8 @@ */ static unsigned long get_entry_num_slots(efi_memory_desc_t *md, unsigned long size, - unsigned long align_shift) + unsigned long align_shift, + u64 alloc_limit) { unsigned long align = 1UL << align_shift; u64 first_slot, last_slot, region_end; @@ -29,7 +30,7 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md, return 0; region_end = min(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - 1, - (u64)EFI_ALLOC_LIMIT); + alloc_limit); if (region_end < size) return 0; @@ -54,7 +55,8 @@ efi_status_t efi_random_alloc(unsigned long size, unsigned long align, unsigned long *addr, unsigned long random_seed, - int memory_type) + int memory_type, + unsigned long alloc_limit) { unsigned long total_slots = 0, target_slot; unsigned long total_mirrored_slots = 0; @@ -76,7 +78,7 @@ efi_status_t efi_random_alloc(unsigned long size, efi_memory_desc_t *md = (void *)map->map + map_offset; unsigned long slots; - slots = get_entry_num_slots(md, size, ilog2(align)); + slots = get_entry_num_slots(md, size, ilog2(align), alloc_limit); MD_NUM_SLOTS(md) = slots; total_slots += slots; if (md->attribute & EFI_MEMORY_MORE_RELIABLE) diff --git a/drivers/firmware/efi/libstub/x86-5lvl.c b/drivers/firmware/efi/libstub/x86-5lvl.c new file mode 100644 index 000000000000..479dd445acdc --- /dev/null +++ b/drivers/firmware/efi/libstub/x86-5lvl.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include <linux/efi.h> + +#include <asm/boot.h> +#include <asm/desc.h> +#include <asm/efi.h> + +#include "efistub.h" +#include "x86-stub.h" + +bool efi_no5lvl; + +static void (*la57_toggle)(void *cr3); + +static const struct desc_struct gdt[] = { + [GDT_ENTRY_KERNEL32_CS] = GDT_ENTRY_INIT(0xc09b, 0, 0xfffff), + [GDT_ENTRY_KERNEL_CS] = GDT_ENTRY_INIT(0xa09b, 0, 0xfffff), +}; + +/* + * Enabling (or disabling) 5 level paging is tricky, because it can only be + * done from 32-bit mode with paging disabled. This means not only that the + * code itself must be running from 32-bit addressable physical memory, but + * also that the root page table must be 32-bit addressable, as programming + * a 64-bit value into CR3 when running in 32-bit mode is not supported. + */ +efi_status_t efi_setup_5level_paging(void) +{ + u8 tmpl_size = (u8 *)&trampoline_ljmp_imm_offset - (u8 *)&trampoline_32bit_src; + efi_status_t status; + u8 *la57_code; + + if (!efi_is_64bit()) + return EFI_SUCCESS; + + /* check for 5 level paging support */ + if (native_cpuid_eax(0) < 7 || + !(native_cpuid_ecx(7) & (1 << (X86_FEATURE_LA57 & 31)))) + return EFI_SUCCESS; + + /* allocate some 32-bit addressable memory for code and a page table */ + status = efi_allocate_pages(2 * PAGE_SIZE, (unsigned long *)&la57_code, + U32_MAX); + if (status != EFI_SUCCESS) + return status; + + la57_toggle = memcpy(la57_code, trampoline_32bit_src, tmpl_size); + memset(la57_code + tmpl_size, 0x90, PAGE_SIZE - tmpl_size); + + /* + * To avoid the need to allocate a 32-bit addressable stack, the + * trampoline uses a LJMP instruction to switch back to long mode. + * LJMP takes an absolute destination address, which needs to be + * fixed up at runtime. + */ + *(u32 *)&la57_code[trampoline_ljmp_imm_offset] += (unsigned long)la57_code; + + efi_adjust_memory_range_protection((unsigned long)la57_toggle, PAGE_SIZE); + + return EFI_SUCCESS; +} + +void efi_5level_switch(void) +{ + bool want_la57 = IS_ENABLED(CONFIG_X86_5LEVEL) && !efi_no5lvl; + bool have_la57 = native_read_cr4() & X86_CR4_LA57; + bool need_toggle = want_la57 ^ have_la57; + u64 *pgt = (void *)la57_toggle + PAGE_SIZE; + u64 *cr3 = (u64 *)__native_read_cr3(); + u64 *new_cr3; + + if (!la57_toggle || !need_toggle) + return; + + if (!have_la57) { + /* + * 5 level paging will be enabled, so a root level page needs + * to be allocated from the 32-bit addressable physical region, + * with its first entry referring to the existing hierarchy. + */ + new_cr3 = memset(pgt, 0, PAGE_SIZE); + new_cr3[0] = (u64)cr3 | _PAGE_TABLE_NOENC; + } else { + /* take the new root table pointer from the current entry #0 */ + new_cr3 = (u64 *)(cr3[0] & PAGE_MASK); + + /* copy the new root table if it is not 32-bit addressable */ + if ((u64)new_cr3 > U32_MAX) + new_cr3 = memcpy(pgt, new_cr3, PAGE_SIZE); + } + + native_load_gdt(&(struct desc_ptr){ sizeof(gdt) - 1, (u64)gdt }); + + la57_toggle(new_cr3); +} diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c index 220be75a5cdc..2fee52ed335d 100644 --- a/drivers/firmware/efi/libstub/x86-stub.c +++ b/drivers/firmware/efi/libstub/x86-stub.c @@ -15,16 +15,16 @@ #include <asm/setup.h> #include <asm/desc.h> #include <asm/boot.h> +#include <asm/kaslr.h> +#include <asm/sev.h> #include "efistub.h" - -/* Maximum physical address for 64-bit kernel with 4-level paging */ -#define MAXMEM_X86_64_4LEVEL (1ull << 46) +#include "x86-stub.h" const efi_system_table_t *efi_system_table; const efi_dxe_services_table_t *efi_dxe_table; -u32 image_offset __section(".data"); static efi_loaded_image_t *image = NULL; +static efi_memory_attribute_protocol_t *memattr; typedef union sev_memory_acceptance_protocol sev_memory_acceptance_protocol_t; union sev_memory_acceptance_protocol { @@ -72,7 +72,7 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom) rom->data.type = SETUP_PCI; rom->data.len = size - sizeof(struct setup_data); rom->data.next = 0; - rom->pcilen = pci->romsize; + rom->pcilen = romsize; *__rom = rom; status = efi_call_proto(pci, pci.read, EfiPciIoWidthUint16, @@ -223,8 +223,8 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params) } } -static void -adjust_memory_range_protection(unsigned long start, unsigned long size) +void efi_adjust_memory_range_protection(unsigned long start, + unsigned long size) { efi_status_t status; efi_gcd_memory_space_desc_t desc; @@ -232,12 +232,18 @@ adjust_memory_range_protection(unsigned long start, unsigned long size) unsigned long rounded_start, rounded_end; unsigned long unprotect_start, unprotect_size; - if (efi_dxe_table == NULL) - return; - rounded_start = rounddown(start, EFI_PAGE_SIZE); rounded_end = roundup(start + size, EFI_PAGE_SIZE); + if (memattr != NULL) { + efi_call_proto(memattr, clear_memory_attributes, rounded_start, + rounded_end - rounded_start, EFI_MEMORY_XP); + return; + } + + if (efi_dxe_table == NULL) + return; + /* * Don't modify memory region attributes, they are * already suitable, to lower the possibility to @@ -278,49 +284,6 @@ adjust_memory_range_protection(unsigned long start, unsigned long size) } } -/* - * Trampoline takes 2 pages and can be loaded in first megabyte of memory - * with its end placed between 128k and 640k where BIOS might start. - * (see arch/x86/boot/compressed/pgtable_64.c) - * - * We cannot find exact trampoline placement since memory map - * can be modified by UEFI, and it can alter the computed address. - */ - -#define TRAMPOLINE_PLACEMENT_BASE ((128 - 8)*1024) -#define TRAMPOLINE_PLACEMENT_SIZE (640*1024 - (128 - 8)*1024) - -void startup_32(struct boot_params *boot_params); - -static void -setup_memory_protection(unsigned long image_base, unsigned long image_size) -{ - /* - * Allow execution of possible trampoline used - * for switching between 4- and 5-level page tables - * and relocated kernel image. - */ - - adjust_memory_range_protection(TRAMPOLINE_PLACEMENT_BASE, - TRAMPOLINE_PLACEMENT_SIZE); - -#ifdef CONFIG_64BIT - if (image_base != (unsigned long)startup_32) - adjust_memory_range_protection(image_base, image_size); -#else - /* - * Clear protection flags on a whole range of possible - * addresses used for KASLR. We don't need to do that - * on x86_64, since KASLR/extraction is performed after - * dedicated identity page tables are built and we only - * need to remove possible protection on relocated image - * itself disregarding further relocations. - */ - adjust_memory_range_protection(LOAD_PHYSICAL_ADDR, - KERNEL_IMAGE_SIZE - LOAD_PHYSICAL_ADDR); -#endif -} - static void setup_unaccepted_memory(void) { efi_guid_t mem_acceptance_proto = OVMF_SEV_MEMORY_ACCEPTANCE_PROTOCOL_GUID; @@ -346,9 +309,7 @@ static void setup_unaccepted_memory(void) static const efi_char16_t apple[] = L"Apple"; -static void setup_quirks(struct boot_params *boot_params, - unsigned long image_base, - unsigned long image_size) +static void setup_quirks(struct boot_params *boot_params) { efi_char16_t *fw_vendor = (efi_char16_t *)(unsigned long) efi_table_attr(efi_system_table, fw_vendor); @@ -357,9 +318,6 @@ static void setup_quirks(struct boot_params *boot_params, if (IS_ENABLED(CONFIG_APPLE_PROPERTIES)) retrieve_apple_device_properties(boot_params); } - - if (IS_ENABLED(CONFIG_EFI_DXE_MEM_ATTRIBUTES)) - setup_memory_protection(image_base, image_size); } /* @@ -512,7 +470,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, } image_base = efi_table_attr(image, image_base); - image_offset = (void *)startup_32 - image_base; status = efi_allocate_pages(sizeof(struct boot_params), (unsigned long *)&boot_params, ULONG_MAX); @@ -803,19 +760,96 @@ static efi_status_t exit_boot(struct boot_params *boot_params, void *handle) return EFI_SUCCESS; } +static bool have_unsupported_snp_features(void) +{ + u64 unsupported; + + unsupported = snp_get_unsupported_features(sev_get_status()); + if (unsupported) { + efi_err("Unsupported SEV-SNP features detected: 0x%llx\n", + unsupported); + return true; + } + return false; +} + +static void efi_get_seed(void *seed, int size) +{ + efi_get_random_bytes(size, seed); + + /* + * This only updates seed[0] when running on 32-bit, but in that case, + * seed[1] is not used anyway, as there is no virtual KASLR on 32-bit. + */ + *(unsigned long *)seed ^= kaslr_get_random_long("EFI"); +} + +static void error(char *str) +{ + efi_warn("Decompression failed: %s\n", str); +} + +static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry) +{ + unsigned long virt_addr = LOAD_PHYSICAL_ADDR; + unsigned long addr, alloc_size, entry; + efi_status_t status; + u32 seed[2] = {}; + + /* determine the required size of the allocation */ + alloc_size = ALIGN(max_t(unsigned long, output_len, kernel_total_size), + MIN_KERNEL_ALIGN); + + if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && !efi_nokaslr) { + u64 range = KERNEL_IMAGE_SIZE - LOAD_PHYSICAL_ADDR - kernel_total_size; + + efi_get_seed(seed, sizeof(seed)); + + virt_addr += (range * seed[1]) >> 32; + virt_addr &= ~(CONFIG_PHYSICAL_ALIGN - 1); + } + + status = efi_random_alloc(alloc_size, CONFIG_PHYSICAL_ALIGN, &addr, + seed[0], EFI_LOADER_CODE, + EFI_X86_KERNEL_ALLOC_LIMIT); + if (status != EFI_SUCCESS) + return status; + + entry = decompress_kernel((void *)addr, virt_addr, error); + if (entry == ULONG_MAX) { + efi_free(alloc_size, addr); + return EFI_LOAD_ERROR; + } + + *kernel_entry = addr + entry; + + efi_adjust_memory_range_protection(addr, kernel_total_size); + + return EFI_SUCCESS; +} + +static void __noreturn enter_kernel(unsigned long kernel_addr, + struct boot_params *boot_params) +{ + /* enter decompressed kernel with boot_params pointer in RSI/ESI */ + asm("jmp *%0"::"r"(kernel_addr), "S"(boot_params)); + + unreachable(); +} + /* - * On success, we return the address of startup_32, which has potentially been - * relocated by efi_relocate_kernel. - * On failure, we exit to the firmware via efi_exit instead of returning. + * On success, this routine will jump to the relocated image directly and never + * return. On failure, it will exit to the firmware via efi_exit() instead of + * returning. */ -asmlinkage unsigned long efi_main(efi_handle_t handle, - efi_system_table_t *sys_table_arg, - struct boot_params *boot_params) +void __noreturn efi_stub_entry(efi_handle_t handle, + efi_system_table_t *sys_table_arg, + struct boot_params *boot_params) { - unsigned long bzimage_addr = (unsigned long)startup_32; - unsigned long buffer_start, buffer_end; + efi_guid_t guid = EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID; struct setup_header *hdr = &boot_params->hdr; const struct linux_efi_initrd *initrd = NULL; + unsigned long kernel_entry; efi_status_t status; efi_system_table = sys_table_arg; @@ -823,65 +857,25 @@ asmlinkage unsigned long efi_main(efi_handle_t handle, if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) efi_exit(handle, EFI_INVALID_PARAMETER); - efi_dxe_table = get_efi_config_table(EFI_DXE_SERVICES_TABLE_GUID); - if (efi_dxe_table && - efi_dxe_table->hdr.signature != EFI_DXE_SERVICES_TABLE_SIGNATURE) { - efi_warn("Ignoring DXE services table: invalid signature\n"); - efi_dxe_table = NULL; + if (have_unsupported_snp_features()) + efi_exit(handle, EFI_UNSUPPORTED); + + if (IS_ENABLED(CONFIG_EFI_DXE_MEM_ATTRIBUTES)) { + efi_dxe_table = get_efi_config_table(EFI_DXE_SERVICES_TABLE_GUID); + if (efi_dxe_table && + efi_dxe_table->hdr.signature != EFI_DXE_SERVICES_TABLE_SIGNATURE) { + efi_warn("Ignoring DXE services table: invalid signature\n"); + efi_dxe_table = NULL; + } } - /* - * If the kernel isn't already loaded at a suitable address, - * relocate it. - * - * It must be loaded above LOAD_PHYSICAL_ADDR. - * - * The maximum address for 64-bit is 1 << 46 for 4-level paging. This - * is defined as the macro MAXMEM, but unfortunately that is not a - * compile-time constant if 5-level paging is configured, so we instead - * define our own macro for use here. - * - * For 32-bit, the maximum address is complicated to figure out, for - * now use KERNEL_IMAGE_SIZE, which will be 512MiB, the same as what - * KASLR uses. - * - * Also relocate it if image_offset is zero, i.e. the kernel wasn't - * loaded by LoadImage, but rather by a bootloader that called the - * handover entry. The reason we must always relocate in this case is - * to handle the case of systemd-boot booting a unified kernel image, - * which is a PE executable that contains the bzImage and an initrd as - * COFF sections. The initrd section is placed after the bzImage - * without ensuring that there are at least init_size bytes available - * for the bzImage, and thus the compressed kernel's startup code may - * overwrite the initrd unless it is moved out of the way. - */ + /* grab the memory attributes protocol if it exists */ + efi_bs_call(locate_protocol, &guid, NULL, (void **)&memattr); - buffer_start = ALIGN(bzimage_addr - image_offset, - hdr->kernel_alignment); - buffer_end = buffer_start + hdr->init_size; - - if ((buffer_start < LOAD_PHYSICAL_ADDR) || - (IS_ENABLED(CONFIG_X86_32) && buffer_end > KERNEL_IMAGE_SIZE) || - (IS_ENABLED(CONFIG_X86_64) && buffer_end > MAXMEM_X86_64_4LEVEL) || - (image_offset == 0)) { - extern char _bss[]; - - status = efi_relocate_kernel(&bzimage_addr, - (unsigned long)_bss - bzimage_addr, - hdr->init_size, - hdr->pref_address, - hdr->kernel_alignment, - LOAD_PHYSICAL_ADDR); - if (status != EFI_SUCCESS) { - efi_err("efi_relocate_kernel() failed!\n"); - goto fail; - } - /* - * Now that we've copied the kernel elsewhere, we no longer - * have a set up block before startup_32(), so reset image_offset - * to zero in case it was set earlier. - */ - image_offset = 0; + status = efi_setup_5level_paging(); + if (status != EFI_SUCCESS) { + efi_err("efi_setup_5level_paging() failed!\n"); + goto fail; } #ifdef CONFIG_CMDLINE_BOOL @@ -901,6 +895,12 @@ asmlinkage unsigned long efi_main(efi_handle_t handle, } } + status = efi_decompress_kernel(&kernel_entry); + if (status != EFI_SUCCESS) { + efi_err("Failed to decompress kernel\n"); + goto fail; + } + /* * At this point, an initrd may already have been loaded by the * bootloader and passed via bootparams. We permit an initrd loaded @@ -940,7 +940,7 @@ asmlinkage unsigned long efi_main(efi_handle_t handle, setup_efi_pci(boot_params); - setup_quirks(boot_params, bzimage_addr, buffer_end - buffer_start); + setup_quirks(boot_params); setup_unaccepted_memory(); @@ -950,9 +950,38 @@ asmlinkage unsigned long efi_main(efi_handle_t handle, goto fail; } - return bzimage_addr; + /* + * Call the SEV init code while still running with the firmware's + * GDT/IDT, so #VC exceptions will be handled by EFI. + */ + sev_enable(boot_params); + + efi_5level_switch(); + + enter_kernel(kernel_entry, boot_params); fail: - efi_err("efi_main() failed!\n"); + efi_err("efi_stub_entry() failed!\n"); efi_exit(handle, status); } + +#ifdef CONFIG_EFI_HANDOVER_PROTOCOL +void efi_handover_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg, + struct boot_params *boot_params) +{ + extern char _bss[], _ebss[]; + + memset(_bss, 0, _ebss - _bss); + efi_stub_entry(handle, sys_table_arg, boot_params); +} + +#ifndef CONFIG_EFI_MIXED +extern __alias(efi_handover_entry) +void efi32_stub_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg, + struct boot_params *boot_params); + +extern __alias(efi_handover_entry) +void efi64_stub_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg, + struct boot_params *boot_params); +#endif +#endif diff --git a/drivers/firmware/efi/libstub/x86-stub.h b/drivers/firmware/efi/libstub/x86-stub.h new file mode 100644 index 000000000000..37c5a36b9d8c --- /dev/null +++ b/drivers/firmware/efi/libstub/x86-stub.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <linux/efi.h> + +extern void trampoline_32bit_src(void *, bool); +extern const u16 trampoline_ljmp_imm_offset; + +void efi_adjust_memory_range_protection(unsigned long start, + unsigned long size); + +#ifdef CONFIG_X86_64 +efi_status_t efi_setup_5level_paging(void); +void efi_5level_switch(void); +#else +static inline efi_status_t efi_setup_5level_paging(void) { return EFI_SUCCESS; } +static inline void efi_5level_switch(void) {} +#endif diff --git a/drivers/firmware/efi/libstub/zboot.c b/drivers/firmware/efi/libstub/zboot.c index e5d7fa1f1d8f..bdb17eac0cb4 100644 --- a/drivers/firmware/efi/libstub/zboot.c +++ b/drivers/firmware/efi/libstub/zboot.c @@ -119,7 +119,7 @@ efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab) } status = efi_random_alloc(alloc_size, min_kimg_align, &image_base, - seed, EFI_LOADER_CODE); + seed, EFI_LOADER_CODE, EFI_ALLOC_LIMIT); if (status != EFI_SUCCESS) { efi_err("Failed to allocate memory\n"); goto free_cmdline; diff --git a/drivers/firmware/efi/riscv-runtime.c b/drivers/firmware/efi/riscv-runtime.c index d0daacd2c903..09525fb5c240 100644 --- a/drivers/firmware/efi/riscv-runtime.c +++ b/drivers/firmware/efi/riscv-runtime.c @@ -130,14 +130,25 @@ static int __init riscv_enable_runtime_services(void) } early_initcall(riscv_enable_runtime_services); -void efi_virtmap_load(void) +static void efi_virtmap_load(void) { preempt_disable(); switch_mm(current->active_mm, &efi_mm, NULL); } -void efi_virtmap_unload(void) +static void efi_virtmap_unload(void) { switch_mm(&efi_mm, current->active_mm, NULL); preempt_enable(); } + +void arch_efi_call_virt_setup(void) +{ + sync_kernel_mappings(efi_mm.pgd); + efi_virtmap_load(); +} + +void arch_efi_call_virt_teardown(void) +{ + efi_virtmap_unload(); +} diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c index a400c4312c82..5d56bc40a79d 100644 --- a/drivers/firmware/efi/runtime-wrappers.c +++ b/drivers/firmware/efi/runtime-wrappers.c @@ -40,55 +40,97 @@ * code doesn't get too cluttered: */ #define efi_call_virt(f, args...) \ - efi_call_virt_pointer(efi.runtime, f, args) -#define __efi_call_virt(f, args...) \ - __efi_call_virt_pointer(efi.runtime, f, args) + arch_efi_call_virt(efi.runtime, f, args) + +union efi_rts_args { + struct { + efi_time_t *time; + efi_time_cap_t *capabilities; + } GET_TIME; + + struct { + efi_time_t *time; + } SET_TIME; + + struct { + efi_bool_t *enabled; + efi_bool_t *pending; + efi_time_t *time; + } GET_WAKEUP_TIME; + + struct { + efi_bool_t enable; + efi_time_t *time; + } SET_WAKEUP_TIME; + + struct { + efi_char16_t *name; + efi_guid_t *vendor; + u32 *attr; + unsigned long *data_size; + void *data; + } GET_VARIABLE; + + struct { + unsigned long *name_size; + efi_char16_t *name; + efi_guid_t *vendor; + } GET_NEXT_VARIABLE; + + struct { + efi_char16_t *name; + efi_guid_t *vendor; + u32 attr; + unsigned long data_size; + void *data; + } SET_VARIABLE; + + struct { + u32 attr; + u64 *storage_space; + u64 *remaining_space; + u64 *max_variable_size; + } QUERY_VARIABLE_INFO; + + struct { + u32 *high_count; + } GET_NEXT_HIGH_MONO_COUNT; + + struct { + efi_capsule_header_t **capsules; + unsigned long count; + unsigned long sg_list; + } UPDATE_CAPSULE; + + struct { + efi_capsule_header_t **capsules; + unsigned long count; + u64 *max_size; + int *reset_type; + } QUERY_CAPSULE_CAPS; + + struct { + efi_status_t (__efiapi *acpi_prm_handler)(u64, void *); + u64 param_buffer_addr; + void *context; + } ACPI_PRM_HANDLER; +}; struct efi_runtime_work efi_rts_work; /* - * efi_queue_work: Queue efi_runtime_service() and wait until it's done - * @rts: efi_runtime_service() function identifier - * @rts_arg<1-5>: efi_runtime_service() function arguments + * efi_queue_work: Queue EFI runtime service call and wait for completion + * @_rts: EFI runtime service function identifier + * @_args: Arguments to pass to the EFI runtime service * * Accesses to efi_runtime_services() are serialized by a binary * semaphore (efi_runtime_lock) and caller waits until the work is * finished, hence _only_ one work is queued at a time and the caller * thread waits for completion. */ -#define efi_queue_work(_rts, _arg1, _arg2, _arg3, _arg4, _arg5) \ -({ \ - efi_rts_work.status = EFI_ABORTED; \ - \ - if (!efi_enabled(EFI_RUNTIME_SERVICES)) { \ - pr_warn_once("EFI Runtime Services are disabled!\n"); \ - efi_rts_work.status = EFI_DEVICE_ERROR; \ - goto exit; \ - } \ - \ - init_completion(&efi_rts_work.efi_rts_comp); \ - INIT_WORK(&efi_rts_work.work, efi_call_rts); \ - efi_rts_work.arg1 = _arg1; \ - efi_rts_work.arg2 = _arg2; \ - efi_rts_work.arg3 = _arg3; \ - efi_rts_work.arg4 = _arg4; \ - efi_rts_work.arg5 = _arg5; \ - efi_rts_work.efi_rts_id = _rts; \ - \ - /* \ - * queue_work() returns 0 if work was already on queue, \ - * _ideally_ this should never happen. \ - */ \ - if (queue_work(efi_rts_wq, &efi_rts_work.work)) \ - wait_for_completion(&efi_rts_work.efi_rts_comp); \ - else \ - pr_err("Failed to queue work to efi_rts_wq.\n"); \ - \ - WARN_ON_ONCE(efi_rts_work.status == EFI_ABORTED); \ -exit: \ - efi_rts_work.efi_rts_id = EFI_NONE; \ - efi_rts_work.status; \ -}) +#define efi_queue_work(_rts, _args...) \ + __efi_queue_work(EFI_ ## _rts, \ + &(union efi_rts_args){ ._rts = { _args }}) #ifndef arch_efi_save_flags #define arch_efi_save_flags(state_flags) local_save_flags(state_flags) @@ -103,7 +145,7 @@ unsigned long efi_call_virt_save_flags(void) return flags; } -void efi_call_virt_check_flags(unsigned long flags, const char *call) +void efi_call_virt_check_flags(unsigned long flags, const void *caller) { unsigned long cur_flags, mismatch; @@ -114,8 +156,8 @@ void efi_call_virt_check_flags(unsigned long flags, const char *call) return; add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_NOW_UNRELIABLE); - pr_err_ratelimited(FW_BUG "IRQ flags corrupted (0x%08lx=>0x%08lx) by EFI %s\n", - flags, cur_flags, call); + pr_err_ratelimited(FW_BUG "IRQ flags corrupted (0x%08lx=>0x%08lx) by EFI call from %pS\n", + flags, cur_flags, caller ?: __builtin_return_address(0)); arch_efi_restore_flags(flags); } @@ -170,74 +212,90 @@ extern struct semaphore __efi_uv_runtime_lock __alias(efi_runtime_lock); /* * Calls the appropriate efi_runtime_service() with the appropriate * arguments. - * - * Semantics followed by efi_call_rts() to understand efi_runtime_work: - * 1. If argument was a pointer, recast it from void pointer to original - * pointer type. - * 2. If argument was a value, recast it from void pointer to original - * pointer type and dereference it. */ static void efi_call_rts(struct work_struct *work) { - void *arg1, *arg2, *arg3, *arg4, *arg5; + const union efi_rts_args *args = efi_rts_work.args; efi_status_t status = EFI_NOT_FOUND; + unsigned long flags; - arg1 = efi_rts_work.arg1; - arg2 = efi_rts_work.arg2; - arg3 = efi_rts_work.arg3; - arg4 = efi_rts_work.arg4; - arg5 = efi_rts_work.arg5; + arch_efi_call_virt_setup(); + flags = efi_call_virt_save_flags(); switch (efi_rts_work.efi_rts_id) { case EFI_GET_TIME: - status = efi_call_virt(get_time, (efi_time_t *)arg1, - (efi_time_cap_t *)arg2); + status = efi_call_virt(get_time, + args->GET_TIME.time, + args->GET_TIME.capabilities); break; case EFI_SET_TIME: - status = efi_call_virt(set_time, (efi_time_t *)arg1); + status = efi_call_virt(set_time, + args->SET_TIME.time); break; case EFI_GET_WAKEUP_TIME: - status = efi_call_virt(get_wakeup_time, (efi_bool_t *)arg1, - (efi_bool_t *)arg2, (efi_time_t *)arg3); + status = efi_call_virt(get_wakeup_time, + args->GET_WAKEUP_TIME.enabled, + args->GET_WAKEUP_TIME.pending, + args->GET_WAKEUP_TIME.time); break; case EFI_SET_WAKEUP_TIME: - status = efi_call_virt(set_wakeup_time, *(efi_bool_t *)arg1, - (efi_time_t *)arg2); + status = efi_call_virt(set_wakeup_time, + args->SET_WAKEUP_TIME.enable, + args->SET_WAKEUP_TIME.time); break; case EFI_GET_VARIABLE: - status = efi_call_virt(get_variable, (efi_char16_t *)arg1, - (efi_guid_t *)arg2, (u32 *)arg3, - (unsigned long *)arg4, (void *)arg5); + status = efi_call_virt(get_variable, + args->GET_VARIABLE.name, + args->GET_VARIABLE.vendor, + args->GET_VARIABLE.attr, + args->GET_VARIABLE.data_size, + args->GET_VARIABLE.data); break; case EFI_GET_NEXT_VARIABLE: - status = efi_call_virt(get_next_variable, (unsigned long *)arg1, - (efi_char16_t *)arg2, - (efi_guid_t *)arg3); + status = efi_call_virt(get_next_variable, + args->GET_NEXT_VARIABLE.name_size, + args->GET_NEXT_VARIABLE.name, + args->GET_NEXT_VARIABLE.vendor); break; case EFI_SET_VARIABLE: - status = efi_call_virt(set_variable, (efi_char16_t *)arg1, - (efi_guid_t *)arg2, *(u32 *)arg3, - *(unsigned long *)arg4, (void *)arg5); + status = efi_call_virt(set_variable, + args->SET_VARIABLE.name, + args->SET_VARIABLE.vendor, + args->SET_VARIABLE.attr, + args->SET_VARIABLE.data_size, + args->SET_VARIABLE.data); break; case EFI_QUERY_VARIABLE_INFO: - status = efi_call_virt(query_variable_info, *(u32 *)arg1, - (u64 *)arg2, (u64 *)arg3, (u64 *)arg4); + status = efi_call_virt(query_variable_info, + args->QUERY_VARIABLE_INFO.attr, + args->QUERY_VARIABLE_INFO.storage_space, + args->QUERY_VARIABLE_INFO.remaining_space, + args->QUERY_VARIABLE_INFO.max_variable_size); break; case EFI_GET_NEXT_HIGH_MONO_COUNT: - status = efi_call_virt(get_next_high_mono_count, (u32 *)arg1); + status = efi_call_virt(get_next_high_mono_count, + args->GET_NEXT_HIGH_MONO_COUNT.high_count); break; case EFI_UPDATE_CAPSULE: status = efi_call_virt(update_capsule, - (efi_capsule_header_t **)arg1, - *(unsigned long *)arg2, - *(unsigned long *)arg3); + args->UPDATE_CAPSULE.capsules, + args->UPDATE_CAPSULE.count, + args->UPDATE_CAPSULE.sg_list); break; case EFI_QUERY_CAPSULE_CAPS: status = efi_call_virt(query_capsule_caps, - (efi_capsule_header_t **)arg1, - *(unsigned long *)arg2, (u64 *)arg3, - (int *)arg4); + args->QUERY_CAPSULE_CAPS.capsules, + args->QUERY_CAPSULE_CAPS.count, + args->QUERY_CAPSULE_CAPS.max_size, + args->QUERY_CAPSULE_CAPS.reset_type); break; + case EFI_ACPI_PRM_HANDLER: +#ifdef CONFIG_ACPI_PRMT + status = arch_efi_call_virt(args, ACPI_PRM_HANDLER.acpi_prm_handler, + args->ACPI_PRM_HANDLER.param_buffer_addr, + args->ACPI_PRM_HANDLER.context); + break; +#endif default: /* * Ideally, we should never reach here because a caller of this @@ -246,17 +304,53 @@ static void efi_call_rts(struct work_struct *work) */ pr_err("Requested executing invalid EFI Runtime Service.\n"); } + + efi_call_virt_check_flags(flags, efi_rts_work.caller); + arch_efi_call_virt_teardown(); + efi_rts_work.status = status; complete(&efi_rts_work.efi_rts_comp); } +static efi_status_t __efi_queue_work(enum efi_rts_ids id, + union efi_rts_args *args) +{ + efi_rts_work.efi_rts_id = id; + efi_rts_work.args = args; + efi_rts_work.caller = __builtin_return_address(0); + efi_rts_work.status = EFI_ABORTED; + + if (!efi_enabled(EFI_RUNTIME_SERVICES)) { + pr_warn_once("EFI Runtime Services are disabled!\n"); + efi_rts_work.status = EFI_DEVICE_ERROR; + goto exit; + } + + init_completion(&efi_rts_work.efi_rts_comp); + INIT_WORK(&efi_rts_work.work, efi_call_rts); + + /* + * queue_work() returns 0 if work was already on queue, + * _ideally_ this should never happen. + */ + if (queue_work(efi_rts_wq, &efi_rts_work.work)) + wait_for_completion(&efi_rts_work.efi_rts_comp); + else + pr_err("Failed to queue work to efi_rts_wq.\n"); + + WARN_ON_ONCE(efi_rts_work.status == EFI_ABORTED); +exit: + efi_rts_work.efi_rts_id = EFI_NONE; + return efi_rts_work.status; +} + static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) { efi_status_t status; if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(EFI_GET_TIME, tm, tc, NULL, NULL, NULL); + status = efi_queue_work(GET_TIME, tm, tc); up(&efi_runtime_lock); return status; } @@ -267,7 +361,7 @@ static efi_status_t virt_efi_set_time(efi_time_t *tm) if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(EFI_SET_TIME, tm, NULL, NULL, NULL, NULL); + status = efi_queue_work(SET_TIME, tm); up(&efi_runtime_lock); return status; } @@ -280,8 +374,7 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled, if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(EFI_GET_WAKEUP_TIME, enabled, pending, tm, NULL, - NULL); + status = efi_queue_work(GET_WAKEUP_TIME, enabled, pending, tm); up(&efi_runtime_lock); return status; } @@ -292,8 +385,7 @@ static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(EFI_SET_WAKEUP_TIME, &enabled, tm, NULL, NULL, - NULL); + status = efi_queue_work(SET_WAKEUP_TIME, enabled, tm); up(&efi_runtime_lock); return status; } @@ -308,7 +400,7 @@ static efi_status_t virt_efi_get_variable(efi_char16_t *name, if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(EFI_GET_VARIABLE, name, vendor, attr, data_size, + status = efi_queue_work(GET_VARIABLE, name, vendor, attr, data_size, data); up(&efi_runtime_lock); return status; @@ -322,8 +414,7 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size, if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(EFI_GET_NEXT_VARIABLE, name_size, name, vendor, - NULL, NULL); + status = efi_queue_work(GET_NEXT_VARIABLE, name_size, name, vendor); up(&efi_runtime_lock); return status; } @@ -338,24 +429,23 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name, if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(EFI_SET_VARIABLE, name, vendor, &attr, &data_size, + status = efi_queue_work(SET_VARIABLE, name, vendor, attr, data_size, data); up(&efi_runtime_lock); return status; } static efi_status_t -virt_efi_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor, - u32 attr, unsigned long data_size, - void *data) +virt_efi_set_variable_nb(efi_char16_t *name, efi_guid_t *vendor, u32 attr, + unsigned long data_size, void *data) { efi_status_t status; if (down_trylock(&efi_runtime_lock)) return EFI_NOT_READY; - status = efi_call_virt(set_variable, name, vendor, attr, data_size, - data); + status = efi_call_virt_pointer(efi.runtime, set_variable, name, vendor, + attr, data_size, data); up(&efi_runtime_lock); return status; } @@ -373,17 +463,15 @@ static efi_status_t virt_efi_query_variable_info(u32 attr, if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(EFI_QUERY_VARIABLE_INFO, &attr, storage_space, - remaining_space, max_variable_size, NULL); + status = efi_queue_work(QUERY_VARIABLE_INFO, attr, storage_space, + remaining_space, max_variable_size); up(&efi_runtime_lock); return status; } static efi_status_t -virt_efi_query_variable_info_nonblocking(u32 attr, - u64 *storage_space, - u64 *remaining_space, - u64 *max_variable_size) +virt_efi_query_variable_info_nb(u32 attr, u64 *storage_space, + u64 *remaining_space, u64 *max_variable_size) { efi_status_t status; @@ -393,8 +481,9 @@ virt_efi_query_variable_info_nonblocking(u32 attr, if (down_trylock(&efi_runtime_lock)) return EFI_NOT_READY; - status = efi_call_virt(query_variable_info, attr, storage_space, - remaining_space, max_variable_size); + status = efi_call_virt_pointer(efi.runtime, query_variable_info, attr, + storage_space, remaining_space, + max_variable_size); up(&efi_runtime_lock); return status; } @@ -405,8 +494,7 @@ static efi_status_t virt_efi_get_next_high_mono_count(u32 *count) if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(EFI_GET_NEXT_HIGH_MONO_COUNT, count, NULL, NULL, - NULL, NULL); + status = efi_queue_work(GET_NEXT_HIGH_MONO_COUNT, count); up(&efi_runtime_lock); return status; } @@ -421,8 +509,13 @@ static void virt_efi_reset_system(int reset_type, "could not get exclusive access to the firmware\n"); return; } + + arch_efi_call_virt_setup(); efi_rts_work.efi_rts_id = EFI_RESET_SYSTEM; - __efi_call_virt(reset_system, reset_type, status, data_size, data); + arch_efi_call_virt(efi.runtime, reset_system, reset_type, status, + data_size, data); + arch_efi_call_virt_teardown(); + up(&efi_runtime_lock); } @@ -437,8 +530,7 @@ static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules, if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(EFI_UPDATE_CAPSULE, capsules, &count, &sg_list, - NULL, NULL); + status = efi_queue_work(UPDATE_CAPSULE, capsules, count, sg_list); up(&efi_runtime_lock); return status; } @@ -455,26 +547,44 @@ static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules, if (down_interruptible(&efi_runtime_lock)) return EFI_ABORTED; - status = efi_queue_work(EFI_QUERY_CAPSULE_CAPS, capsules, &count, - max_size, reset_type, NULL); + status = efi_queue_work(QUERY_CAPSULE_CAPS, capsules, count, + max_size, reset_type); up(&efi_runtime_lock); return status; } -void efi_native_runtime_setup(void) +void __init efi_native_runtime_setup(void) { - efi.get_time = virt_efi_get_time; - efi.set_time = virt_efi_set_time; - efi.get_wakeup_time = virt_efi_get_wakeup_time; - efi.set_wakeup_time = virt_efi_set_wakeup_time; - efi.get_variable = virt_efi_get_variable; - efi.get_next_variable = virt_efi_get_next_variable; - efi.set_variable = virt_efi_set_variable; - efi.set_variable_nonblocking = virt_efi_set_variable_nonblocking; - efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count; - efi.reset_system = virt_efi_reset_system; - efi.query_variable_info = virt_efi_query_variable_info; - efi.query_variable_info_nonblocking = virt_efi_query_variable_info_nonblocking; - efi.update_capsule = virt_efi_update_capsule; - efi.query_capsule_caps = virt_efi_query_capsule_caps; + efi.get_time = virt_efi_get_time; + efi.set_time = virt_efi_set_time; + efi.get_wakeup_time = virt_efi_get_wakeup_time; + efi.set_wakeup_time = virt_efi_set_wakeup_time; + efi.get_variable = virt_efi_get_variable; + efi.get_next_variable = virt_efi_get_next_variable; + efi.set_variable = virt_efi_set_variable; + efi.set_variable_nonblocking = virt_efi_set_variable_nb; + efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count; + efi.reset_system = virt_efi_reset_system; + efi.query_variable_info = virt_efi_query_variable_info; + efi.query_variable_info_nonblocking = virt_efi_query_variable_info_nb; + efi.update_capsule = virt_efi_update_capsule; + efi.query_capsule_caps = virt_efi_query_capsule_caps; } + +#ifdef CONFIG_ACPI_PRMT + +efi_status_t +efi_call_acpi_prm_handler(efi_status_t (__efiapi *handler_addr)(u64, void *), + u64 param_buffer_addr, void *context) +{ + efi_status_t status; + + if (down_interruptible(&efi_runtime_lock)) + return EFI_ABORTED; + status = efi_queue_work(ACPI_PRM_HANDLER, handler_addr, + param_buffer_addr, context); + up(&efi_runtime_lock); + return status; +} + +#endif diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index e382dfebad7c..673bafb8be58 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -111,6 +111,9 @@ config GPIO_MAX730X config GPIO_IDIO_16 tristate + select REGMAP_IRQ + select GPIOLIB_IRQCHIP + select GPIO_REGMAP help Enables support for the idio-16 library functions. The idio-16 library provides functions to facilitate communication with devices within the @@ -191,7 +194,7 @@ config GPIO_RASPBERRYPI_EXP config GPIO_BCM_KONA bool "Broadcom Kona GPIO" - depends on OF_GPIO && (ARCH_BCM_MOBILE || COMPILE_TEST) + depends on ARCH_BCM_MOBILE || COMPILE_TEST help Turn on GPIO support for Broadcom "Kona" chips. @@ -283,7 +286,7 @@ config GPIO_EXAR config GPIO_GE_FPGA bool "GE FPGA based GPIO" - depends on GE_FPGA + depends on GE_FPGA || COMPILE_TEST select GPIO_GENERIC help Support for common GPIO functionality provided on some GE Single Board @@ -564,7 +567,7 @@ config GPIO_SAMA5D2_PIOBU maintain their value during backup/self-refresh. config GPIO_SIFIVE - bool "SiFive GPIO support" + tristate "SiFive GPIO support" depends on OF_GPIO select IRQ_DOMAIN_HIERARCHY select GPIO_GENERIC @@ -858,6 +861,7 @@ config GPIO_104_DIO_48E select REGMAP_IRQ select GPIOLIB_IRQCHIP select GPIO_I8255 + select I8254 help Enables GPIO support for the ACCES 104-DIO-48E series (104-DIO-48E, 104-DIO-24E). The base port addresses for the devices may be @@ -868,7 +872,7 @@ config GPIO_104_IDIO_16 tristate "ACCES 104-IDIO-16 GPIO support" depends on PC104 select ISA_BUS_API - select GPIOLIB_IRQCHIP + select REGMAP_MMIO select GPIO_IDIO_16 help Enables GPIO support for the ACCES 104-IDIO-16 family (104-IDIO-16, @@ -994,7 +998,10 @@ config GPIO_WINBOND config GPIO_WS16C48 tristate "WinSystems WS16C48 GPIO support" select ISA_BUS_API + select REGMAP_IRQ + select REGMAP_MMIO select GPIOLIB_IRQCHIP + select GPIO_REGMAP help Enables GPIO support for the WinSystems WS16C48. The base port addresses for the devices may be configured via the base module @@ -1028,6 +1035,17 @@ config GPIO_FXL6408 To compile this driver as a module, choose M here: the module will be called gpio-fxl6408. +config GPIO_DS4520 + tristate "DS4520 I2C GPIO expander" + select REGMAP_I2C + select GPIO_REGMAP + help + GPIO driver for ADI DS4520 I2C-based GPIO expander. + Say yes here to enable the GPIO driver for the ADI DS4520 chip. + + To compile this driver as a module, choose M here: the module will + be called gpio-ds4520. + config GPIO_GW_PLD tristate "Gateworks PLD GPIO Expander" depends on OF_GPIO @@ -1640,7 +1658,7 @@ config GPIO_PCH config GPIO_PCI_IDIO_16 tristate "ACCES PCI-IDIO-16 GPIO support" - select GPIOLIB_IRQCHIP + select REGMAP_MMIO select GPIO_IDIO_16 help Enables GPIO support for the ACCES PCI-IDIO-16. An interrupt is @@ -1650,7 +1668,10 @@ config GPIO_PCI_IDIO_16 config GPIO_PCIE_IDIO_24 tristate "ACCES PCIe-IDIO-24 GPIO support" + select REGMAP_IRQ + select REGMAP_MMIO select GPIOLIB_IRQCHIP + select GPIO_REGMAP help Enables GPIO support for the ACCES PCIe-IDIO-24 family (PCIe-IDIO-24, PCIe-IDI-24, PCIe-IDO-24, PCIe-IDIO-12). An interrupt is generated diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index c3ac51d47aa9..eb73b5d633eb 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o obj-$(CONFIG_GPIO_DLN2) += gpio-dln2.o +obj-$(CONFIG_GPIO_DS4520) += gpio-ds4520.o obj-$(CONFIG_GPIO_DWAPB) += gpio-dwapb.o obj-$(CONFIG_GPIO_EIC_SPRD) += gpio-eic-sprd.o obj-$(CONFIG_GPIO_ELKHARTLAKE) += gpio-elkhartlake.o diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c index 8ff5f4ff5958..4df9becaf349 100644 --- a/drivers/gpio/gpio-104-dio-48e.c +++ b/drivers/gpio/gpio-104-dio-48e.c @@ -9,6 +9,7 @@ #include <linux/bits.h> #include <linux/device.h> #include <linux/err.h> +#include <linux/i8254.h> #include <linux/ioport.h> #include <linux/irq.h> #include <linux/isa.h> @@ -16,6 +17,7 @@ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/regmap.h> +#include <linux/spinlock.h> #include <linux/types.h> #include "gpio-i8255.h" @@ -37,6 +39,8 @@ MODULE_PARM_DESC(irq, "ACCES 104-DIO-48E interrupt line numbers"); #define DIO48E_ENABLE_INTERRUPT 0xB #define DIO48E_DISABLE_INTERRUPT DIO48E_ENABLE_INTERRUPT +#define DIO48E_ENABLE_COUNTER_TIMER_ADDRESSING 0xD +#define DIO48E_DISABLE_COUNTER_TIMER_ADDRESSING DIO48E_ENABLE_COUNTER_TIMER_ADDRESSING #define DIO48E_CLEAR_INTERRUPT 0xF #define DIO48E_NUM_PPI 2 @@ -75,18 +79,20 @@ static const struct regmap_access_table dio48e_precious_table = { .yes_ranges = dio48e_precious_ranges, .n_yes_ranges = ARRAY_SIZE(dio48e_precious_ranges), }; -static const struct regmap_config dio48e_regmap_config = { - .reg_bits = 8, - .reg_stride = 1, - .val_bits = 8, - .io_port = true, - .max_register = 0xF, - .wr_table = &dio48e_wr_table, - .rd_table = &dio48e_rd_table, - .volatile_table = &dio48e_volatile_table, - .precious_table = &dio48e_precious_table, - .cache_type = REGCACHE_FLAT, - .use_raw_spinlock = true, + +static const struct regmap_range pit_wr_ranges[] = { + regmap_reg_range(0x0, 0x3), +}; +static const struct regmap_range pit_rd_ranges[] = { + regmap_reg_range(0x0, 0x2), +}; +static const struct regmap_access_table pit_wr_table = { + .yes_ranges = pit_wr_ranges, + .n_yes_ranges = ARRAY_SIZE(pit_wr_ranges), +}; +static const struct regmap_access_table pit_rd_table = { + .yes_ranges = pit_rd_ranges, + .n_yes_ranges = ARRAY_SIZE(pit_rd_ranges), }; /* only bit 3 on each respective Port C supports interrupts */ @@ -102,14 +108,56 @@ static const struct regmap_irq dio48e_regmap_irqs[] = { /** * struct dio48e_gpio - GPIO device private data structure + * @lock: synchronization lock to prevent I/O race conditions * @map: Regmap for the device + * @regs: virtual mapping for device registers + * @flags: IRQ flags saved during locking * @irq_mask: Current IRQ mask state on the device */ struct dio48e_gpio { + raw_spinlock_t lock; struct regmap *map; + void __iomem *regs; + unsigned long flags; unsigned int irq_mask; }; +static void dio48e_regmap_lock(void *lock_arg) __acquires(&dio48egpio->lock) +{ + struct dio48e_gpio *const dio48egpio = lock_arg; + unsigned long flags; + + raw_spin_lock_irqsave(&dio48egpio->lock, flags); + dio48egpio->flags = flags; +} + +static void dio48e_regmap_unlock(void *lock_arg) __releases(&dio48egpio->lock) +{ + struct dio48e_gpio *const dio48egpio = lock_arg; + + raw_spin_unlock_irqrestore(&dio48egpio->lock, dio48egpio->flags); +} + +static void pit_regmap_lock(void *lock_arg) __acquires(&dio48egpio->lock) +{ + struct dio48e_gpio *const dio48egpio = lock_arg; + unsigned long flags; + + raw_spin_lock_irqsave(&dio48egpio->lock, flags); + dio48egpio->flags = flags; + + iowrite8(0x00, dio48egpio->regs + DIO48E_ENABLE_COUNTER_TIMER_ADDRESSING); +} + +static void pit_regmap_unlock(void *lock_arg) __releases(&dio48egpio->lock) +{ + struct dio48e_gpio *const dio48egpio = lock_arg; + + ioread8(dio48egpio->regs + DIO48E_DISABLE_COUNTER_TIMER_ADDRESSING); + + raw_spin_unlock_irqrestore(&dio48egpio->lock, dio48egpio->flags); +} + static int dio48e_handle_mask_sync(const int index, const unsigned int mask_buf_def, const unsigned int mask_buf, @@ -176,6 +224,9 @@ static int dio48e_probe(struct device *dev, unsigned int id) struct i8255_regmap_config config = {}; void __iomem *regs; struct regmap *map; + struct regmap_config dio48e_regmap_config; + struct regmap_config pit_regmap_config; + struct i8254_regmap_config pit_config; int err; struct regmap_irq_chip *chip; struct dio48e_gpio *dio48egpio; @@ -187,21 +238,58 @@ static int dio48e_probe(struct device *dev, unsigned int id) return -EBUSY; } + dio48egpio = devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL); + if (!dio48egpio) + return -ENOMEM; + regs = devm_ioport_map(dev, base[id], DIO48E_EXTENT); if (!regs) return -ENOMEM; + dio48egpio->regs = regs; + + raw_spin_lock_init(&dio48egpio->lock); + + dio48e_regmap_config = (struct regmap_config) { + .reg_bits = 8, + .reg_stride = 1, + .val_bits = 8, + .lock = dio48e_regmap_lock, + .unlock = dio48e_regmap_unlock, + .lock_arg = dio48egpio, + .io_port = true, + .wr_table = &dio48e_wr_table, + .rd_table = &dio48e_rd_table, + .volatile_table = &dio48e_volatile_table, + .precious_table = &dio48e_precious_table, + .cache_type = REGCACHE_FLAT, + }; + map = devm_regmap_init_mmio(dev, regs, &dio48e_regmap_config); if (IS_ERR(map)) return dev_err_probe(dev, PTR_ERR(map), "Unable to initialize register map\n"); - dio48egpio = devm_kzalloc(dev, sizeof(*dio48egpio), GFP_KERNEL); - if (!dio48egpio) - return -ENOMEM; - dio48egpio->map = map; + pit_regmap_config = (struct regmap_config) { + .name = "i8254", + .reg_bits = 8, + .reg_stride = 1, + .val_bits = 8, + .lock = pit_regmap_lock, + .unlock = pit_regmap_unlock, + .lock_arg = dio48egpio, + .io_port = true, + .wr_table = &pit_wr_table, + .rd_table = &pit_rd_table, + }; + + pit_config.map = devm_regmap_init_mmio(dev, regs, &pit_regmap_config); + if (IS_ERR(pit_config.map)) + return dev_err_probe(dev, PTR_ERR(pit_config.map), + "Unable to initialize i8254 register map\n"); + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); if (!chip) return -ENOMEM; @@ -225,6 +313,12 @@ static int dio48e_probe(struct device *dev, unsigned int id) if (err) return dev_err_probe(dev, err, "IRQ registration failed\n"); + pit_config.parent = dev; + + err = devm_i8254_regmap_register(dev, &pit_config); + if (err) + return err; + config.parent = dev; config.map = map; config.num_ppi = DIO48E_NUM_PPI; @@ -245,3 +339,4 @@ module_isa_driver_with_irq(dio48e_driver, num_dio48e, num_irq); MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>"); MODULE_DESCRIPTION("ACCES 104-DIO-48E GPIO driver"); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS(I8254); diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-16.c index 098fbefdbe22..f03ccd0f534c 100644 --- a/drivers/gpio/gpio-104-idio-16.c +++ b/drivers/gpio/gpio-104-idio-16.c @@ -6,19 +6,16 @@ * This driver supports the following ACCES devices: 104-IDIO-16, * 104-IDIO-16E, 104-IDO-16, 104-IDIO-8, 104-IDIO-8E, and 104-IDO-8. */ -#include <linux/bitmap.h> +#include <linux/bits.h> #include <linux/device.h> -#include <linux/errno.h> -#include <linux/gpio/driver.h> -#include <linux/io.h> +#include <linux/err.h> #include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/irqdesc.h> +#include <linux/irq.h> #include <linux/isa.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/spinlock.h> +#include <linux/regmap.h> #include <linux/types.h> #include "gpio-idio-16.h" @@ -36,187 +33,62 @@ static unsigned int num_irq; module_param_hw_array(irq, uint, irq, &num_irq, 0); MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers"); -/** - * struct idio_16_gpio - GPIO device private data structure - * @chip: instance of the gpio_chip - * @lock: synchronization lock to prevent I/O race conditions - * @irq_mask: I/O bits affected by interrupts - * @reg: I/O address offset for the device registers - * @state: ACCES IDIO-16 device state - */ -struct idio_16_gpio { - struct gpio_chip chip; - raw_spinlock_t lock; - unsigned long irq_mask; - struct idio_16 __iomem *reg; - struct idio_16_state state; +static const struct regmap_range idio_16_wr_ranges[] = { + regmap_reg_range(0x0, 0x2), regmap_reg_range(0x4, 0x4), }; - -static int idio_16_gpio_get_direction(struct gpio_chip *chip, - unsigned int offset) -{ - if (idio_16_get_direction(offset)) - return GPIO_LINE_DIRECTION_IN; - - return GPIO_LINE_DIRECTION_OUT; -} - -static int idio_16_gpio_direction_input(struct gpio_chip *chip, - unsigned int offset) -{ - return 0; -} - -static int idio_16_gpio_direction_output(struct gpio_chip *chip, - unsigned int offset, int value) -{ - chip->set(chip, offset, value); - return 0; -} - -static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset) -{ - struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - - return idio_16_get(idio16gpio->reg, &idio16gpio->state, offset); -} - -static int idio_16_gpio_get_multiple(struct gpio_chip *chip, - unsigned long *mask, unsigned long *bits) -{ - struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - - idio_16_get_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits); - - return 0; -} - -static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset, - int value) -{ - struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - - idio_16_set(idio16gpio->reg, &idio16gpio->state, offset, value); -} - -static void idio_16_gpio_set_multiple(struct gpio_chip *chip, - unsigned long *mask, unsigned long *bits) -{ - struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - - idio_16_set_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits); -} - -static void idio_16_irq_ack(struct irq_data *data) -{ -} - -static void idio_16_irq_mask(struct irq_data *data) -{ - struct gpio_chip *chip = irq_data_get_irq_chip_data(data); - struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - const unsigned long offset = irqd_to_hwirq(data); - unsigned long flags; - - idio16gpio->irq_mask &= ~BIT(offset); - gpiochip_disable_irq(chip, offset); - - if (!idio16gpio->irq_mask) { - raw_spin_lock_irqsave(&idio16gpio->lock, flags); - - iowrite8(0, &idio16gpio->reg->irq_ctl); - - raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); - } -} - -static void idio_16_irq_unmask(struct irq_data *data) -{ - struct gpio_chip *chip = irq_data_get_irq_chip_data(data); - struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - const unsigned long offset = irqd_to_hwirq(data); - const unsigned long prev_irq_mask = idio16gpio->irq_mask; - unsigned long flags; - - gpiochip_enable_irq(chip, offset); - idio16gpio->irq_mask |= BIT(offset); - - if (!prev_irq_mask) { - raw_spin_lock_irqsave(&idio16gpio->lock, flags); - - ioread8(&idio16gpio->reg->irq_ctl); - - raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); - } -} - -static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type) -{ - /* The only valid irq types are none and both-edges */ - if (flow_type != IRQ_TYPE_NONE && - (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH) - return -EINVAL; - - return 0; -} - -static const struct irq_chip idio_16_irqchip = { - .name = "104-idio-16", - .irq_ack = idio_16_irq_ack, - .irq_mask = idio_16_irq_mask, - .irq_unmask = idio_16_irq_unmask, - .irq_set_type = idio_16_irq_set_type, - .flags = IRQCHIP_IMMUTABLE, - GPIOCHIP_IRQ_RESOURCE_HELPERS, +static const struct regmap_range idio_16_rd_ranges[] = { + regmap_reg_range(0x1, 0x2), regmap_reg_range(0x5, 0x5), }; - -static irqreturn_t idio_16_irq_handler(int irq, void *dev_id) -{ - struct idio_16_gpio *const idio16gpio = dev_id; - struct gpio_chip *const chip = &idio16gpio->chip; - int gpio; - - for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio) - generic_handle_domain_irq(chip->irq.domain, gpio); - - raw_spin_lock(&idio16gpio->lock); - - iowrite8(0, &idio16gpio->reg->in0_7); - - raw_spin_unlock(&idio16gpio->lock); - - return IRQ_HANDLED; -} - -#define IDIO_16_NGPIO 32 -static const char *idio_16_names[IDIO_16_NGPIO] = { - "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7", - "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15", - "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7", - "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15" +static const struct regmap_range idio_16_precious_ranges[] = { + regmap_reg_range(0x2, 0x2), +}; +static const struct regmap_access_table idio_16_wr_table = { + .yes_ranges = idio_16_wr_ranges, + .n_yes_ranges = ARRAY_SIZE(idio_16_wr_ranges), +}; +static const struct regmap_access_table idio_16_rd_table = { + .yes_ranges = idio_16_rd_ranges, + .n_yes_ranges = ARRAY_SIZE(idio_16_rd_ranges), +}; +static const struct regmap_access_table idio_16_precious_table = { + .yes_ranges = idio_16_precious_ranges, + .n_yes_ranges = ARRAY_SIZE(idio_16_precious_ranges), +}; +static const struct regmap_config idio_16_regmap_config = { + .reg_bits = 8, + .reg_stride = 1, + .val_bits = 8, + .io_port = true, + .wr_table = &idio_16_wr_table, + .rd_table = &idio_16_rd_table, + .volatile_table = &idio_16_rd_table, + .precious_table = &idio_16_precious_table, + .cache_type = REGCACHE_FLAT, + .use_raw_spinlock = true, }; -static int idio_16_irq_init_hw(struct gpio_chip *gc) -{ - struct idio_16_gpio *const idio16gpio = gpiochip_get_data(gc); - - /* Disable IRQ by default */ - iowrite8(0, &idio16gpio->reg->irq_ctl); - iowrite8(0, &idio16gpio->reg->in0_7); +/* Only input lines (GPIO 16-31) support interrupts */ +#define IDIO_16_REGMAP_IRQ(_id) \ + [16 + _id] = { \ + .mask = BIT(_id), \ + .type = { .types_supported = IRQ_TYPE_EDGE_BOTH }, \ + } - return 0; -} +static const struct regmap_irq idio_16_regmap_irqs[] = { + IDIO_16_REGMAP_IRQ(0), IDIO_16_REGMAP_IRQ(1), IDIO_16_REGMAP_IRQ(2), /* 0-2 */ + IDIO_16_REGMAP_IRQ(3), IDIO_16_REGMAP_IRQ(4), IDIO_16_REGMAP_IRQ(5), /* 3-5 */ + IDIO_16_REGMAP_IRQ(6), IDIO_16_REGMAP_IRQ(7), IDIO_16_REGMAP_IRQ(8), /* 6-8 */ + IDIO_16_REGMAP_IRQ(9), IDIO_16_REGMAP_IRQ(10), IDIO_16_REGMAP_IRQ(11), /* 9-11 */ + IDIO_16_REGMAP_IRQ(12), IDIO_16_REGMAP_IRQ(13), IDIO_16_REGMAP_IRQ(14), /* 12-14 */ + IDIO_16_REGMAP_IRQ(15), /* 15 */ +}; static int idio_16_probe(struct device *dev, unsigned int id) { - struct idio_16_gpio *idio16gpio; const char *const name = dev_name(dev); - struct gpio_irq_chip *girq; - int err; - - idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL); - if (!idio16gpio) - return -ENOMEM; + struct idio_16_regmap_config config = {}; + void __iomem *regs; + struct regmap *map; if (!devm_request_region(dev, base[id], IDIO_16_EXTENT, name)) { dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", @@ -224,54 +96,22 @@ static int idio_16_probe(struct device *dev, unsigned int id) return -EBUSY; } - idio16gpio->reg = devm_ioport_map(dev, base[id], IDIO_16_EXTENT); - if (!idio16gpio->reg) + regs = devm_ioport_map(dev, base[id], IDIO_16_EXTENT); + if (!regs) return -ENOMEM; - idio16gpio->chip.label = name; - idio16gpio->chip.parent = dev; - idio16gpio->chip.owner = THIS_MODULE; - idio16gpio->chip.base = -1; - idio16gpio->chip.ngpio = IDIO_16_NGPIO; - idio16gpio->chip.names = idio_16_names; - idio16gpio->chip.get_direction = idio_16_gpio_get_direction; - idio16gpio->chip.direction_input = idio_16_gpio_direction_input; - idio16gpio->chip.direction_output = idio_16_gpio_direction_output; - idio16gpio->chip.get = idio_16_gpio_get; - idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple; - idio16gpio->chip.set = idio_16_gpio_set; - idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple; - - idio_16_state_init(&idio16gpio->state); - /* FET off states are represented by bit values of "1" */ - bitmap_fill(idio16gpio->state.out_state, IDIO_16_NOUT); - - girq = &idio16gpio->chip.irq; - gpio_irq_chip_set_chip(girq, &idio_16_irqchip); - /* This will let us handle the parent IRQ in the driver */ - girq->parent_handler = NULL; - girq->num_parents = 0; - girq->parents = NULL; - girq->default_type = IRQ_TYPE_NONE; - girq->handler = handle_edge_irq; - girq->init_hw = idio_16_irq_init_hw; + map = devm_regmap_init_mmio(dev, regs, &idio_16_regmap_config); + if (IS_ERR(map)) + return dev_err_probe(dev, PTR_ERR(map), "Unable to initialize register map\n"); - raw_spin_lock_init(&idio16gpio->lock); - - err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio); - if (err) { - dev_err(dev, "GPIO registering failed (%d)\n", err); - return err; - } - - err = devm_request_irq(dev, irq[id], idio_16_irq_handler, 0, name, - idio16gpio); - if (err) { - dev_err(dev, "IRQ handler registering failed (%d)\n", err); - return err; - } + config.parent = dev; + config.map = map; + config.regmap_irqs = idio_16_regmap_irqs; + config.num_regmap_irqs = ARRAY_SIZE(idio_16_regmap_irqs); + config.irq = irq[id]; + config.no_status = true; - return 0; + return devm_idio_16_regmap_register(dev, &config); } static struct isa_driver idio_16_driver = { diff --git a/drivers/gpio/gpio-74xx-mmio.c b/drivers/gpio/gpio-74xx-mmio.c index 0464f1ecd20d..c7ac5a9ffb1f 100644 --- a/drivers/gpio/gpio-74xx-mmio.c +++ b/drivers/gpio/gpio-74xx-mmio.c @@ -135,8 +135,6 @@ static int mmio_74xx_gpio_probe(struct platform_device *pdev) priv->gc.ngpio = MMIO_74XX_BIT_CNT(priv->flags); priv->gc.owner = THIS_MODULE; - platform_set_drvdata(pdev, priv); - return devm_gpiochip_add_data(&pdev->dev, &priv->gc, priv); } diff --git a/drivers/gpio/gpio-altera-a10sr.c b/drivers/gpio/gpio-altera-a10sr.c index be1ed7ee5225..11edf1fe6c90 100644 --- a/drivers/gpio/gpio-altera-a10sr.c +++ b/drivers/gpio/gpio-altera-a10sr.c @@ -9,6 +9,7 @@ #include <linux/gpio/driver.h> #include <linux/mfd/altera-a10sr.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/property.h> @@ -104,7 +105,7 @@ static struct platform_driver altr_a10sr_gpio_driver = { .probe = altr_a10sr_gpio_probe, .driver = { .name = "altr_a10sr_gpio", - .of_match_table = of_match_ptr(altr_a10sr_gpio_of_match), + .of_match_table = altr_a10sr_gpio_of_match, }, }; module_platform_driver(altr_a10sr_gpio_driver); diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c index aa0a954b8392..f0c0c0f77eb0 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c @@ -9,8 +9,9 @@ */ #include <linux/gpio/driver.h> +#include <linux/platform_device.h> #include <linux/platform_data/gpio-ath79.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/interrupt.h> #include <linux/module.h> #include <linux/irq.h> diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c index 70770429ba48..5321ef98f442 100644 --- a/drivers/gpio/gpio-bcm-kona.c +++ b/drivers/gpio/gpio-bcm-kona.c @@ -8,12 +8,14 @@ #include <linux/bitops.h> #include <linux/err.h> -#include <linux/io.h> #include <linux/gpio/driver.h> -#include <linux/of_device.h> #include <linux/init.h> +#include <linux/io.h> #include <linux/irqdomain.h> #include <linux/irqchip/chained_irq.h> +#include <linux/mod_devicetable.h> +#include <linux/platform_device.h> +#include <linux/property.h> #define BCM_GPIO_PASSWD 0x00a5a501 #define GPIO_PER_BANK 32 @@ -62,7 +64,6 @@ struct bcm_kona_gpio { struct gpio_chip gpio_chip; struct irq_domain *irq_domain; struct bcm_kona_gpio_bank *banks; - struct platform_device *pdev; }; struct bcm_kona_gpio_bank { @@ -556,19 +557,12 @@ static void bcm_kona_gpio_reset(struct bcm_kona_gpio *kona_gpio) static int bcm_kona_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - const struct of_device_id *match; struct bcm_kona_gpio_bank *bank; struct bcm_kona_gpio *kona_gpio; struct gpio_chip *chip; int ret; int i; - match = of_match_device(bcm_kona_gpio_of_match, dev); - if (!match) { - dev_err(dev, "Failed to find gpio controller\n"); - return -ENODEV; - } - kona_gpio = devm_kzalloc(dev, sizeof(*kona_gpio), GFP_KERNEL); if (!kona_gpio) return -ENOMEM; @@ -596,15 +590,13 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev) if (!kona_gpio->banks) return -ENOMEM; - kona_gpio->pdev = pdev; - platform_set_drvdata(pdev, kona_gpio); chip->parent = dev; chip->ngpio = kona_gpio->num_bank * GPIO_PER_BANK; - kona_gpio->irq_domain = irq_domain_add_linear(dev->of_node, - chip->ngpio, - &bcm_kona_irq_ops, - kona_gpio); + kona_gpio->irq_domain = irq_domain_create_linear(dev_fwnode(dev), + chip->ngpio, + &bcm_kona_irq_ops, + kona_gpio); if (!kona_gpio->irq_domain) { dev_err(dev, "Couldn't allocate IRQ domain\n"); return -ENXIO; diff --git a/drivers/gpio/gpio-brcmstb.c b/drivers/gpio/gpio-brcmstb.c index 6566517fe0d8..bccdbfd5ec80 100644 --- a/drivers/gpio/gpio-brcmstb.c +++ b/drivers/gpio/gpio-brcmstb.c @@ -3,12 +3,12 @@ #include <linux/bitops.h> #include <linux/gpio/driver.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> +#include <linux/of.h> #include <linux/module.h> #include <linux/irqdomain.h> #include <linux/irqchip/chained_irq.h> #include <linux/interrupt.h> +#include <linux/platform_device.h> enum gio_reg_index { GIO_REG_ODEN = 0, diff --git a/drivers/gpio/gpio-clps711x.c b/drivers/gpio/gpio-clps711x.c index 75f6f8d4323e..d69a24dd4828 100644 --- a/drivers/gpio/gpio-clps711x.c +++ b/drivers/gpio/gpio-clps711x.c @@ -67,7 +67,7 @@ static int clps711x_gpio_probe(struct platform_device *pdev) return devm_gpiochip_add_data(&pdev->dev, gc, NULL); } -static const struct of_device_id __maybe_unused clps711x_gpio_ids[] = { +static const struct of_device_id clps711x_gpio_ids[] = { { .compatible = "cirrus,ep7209-gpio" }, { } }; @@ -76,7 +76,7 @@ MODULE_DEVICE_TABLE(of, clps711x_gpio_ids); static struct platform_driver clps711x_gpio_driver = { .driver = { .name = "clps711x-gpio", - .of_match_table = of_match_ptr(clps711x_gpio_ids), + .of_match_table = clps711x_gpio_ids, }, .probe = clps711x_gpio_probe, }; diff --git a/drivers/gpio/gpio-creg-snps.c b/drivers/gpio/gpio-creg-snps.c index 789384c6e178..4968232f70f2 100644 --- a/drivers/gpio/gpio-creg-snps.c +++ b/drivers/gpio/gpio-creg-snps.c @@ -8,7 +8,7 @@ #include <linux/gpio/driver.h> #include <linux/io.h> #include <linux/of.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #define MAX_GPIO 32 diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index fff510d86e31..8db5717bdabe 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -236,7 +236,7 @@ static int davinci_gpio_probe(struct platform_device *pdev) for (i = 0; i < nirq; i++) { chips->irqs[i] = platform_get_irq(pdev, i); if (chips->irqs[i] < 0) - return dev_err_probe(dev, chips->irqs[i], "IRQ not populated\n"); + return chips->irqs[i]; } chips->chip.label = dev_name(dev); diff --git a/drivers/gpio/gpio-ds4520.c b/drivers/gpio/gpio-ds4520.c new file mode 100644 index 000000000000..1903deaef3e9 --- /dev/null +++ b/drivers/gpio/gpio-ds4520.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Analog Devices, Inc. + * Driver for the DS4520 I/O Expander + */ + +#include <linux/device.h> +#include <linux/gpio/driver.h> +#include <linux/gpio/regmap.h> +#include <linux/i2c.h> +#include <linux/property.h> +#include <linux/regmap.h> + +#define DS4520_PULLUP0 0xF0 +#define DS4520_IO_CONTROL0 0xF2 +#define DS4520_IO_STATUS0 0xF8 + +static const struct regmap_config ds4520_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +static int ds4520_gpio_probe(struct i2c_client *client) +{ + struct gpio_regmap_config config = { }; + struct device *dev = &client->dev; + struct regmap *regmap; + u32 ngpio; + u32 base; + int ret; + + ret = device_property_read_u32(dev, "reg", &base); + if (ret) + return dev_err_probe(dev, ret, "Missing 'reg' property.\n"); + + ret = device_property_read_u32(dev, "ngpios", &ngpio); + if (ret) + return dev_err_probe(dev, ret, "Missing 'ngpios' property.\n"); + + regmap = devm_regmap_init_i2c(client, &ds4520_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), + "Failed to allocate register map\n"); + + config.regmap = regmap; + config.parent = dev; + config.ngpio = ngpio; + + config.reg_dat_base = base + DS4520_IO_STATUS0; + config.reg_set_base = base + DS4520_PULLUP0; + config.reg_dir_out_base = base + DS4520_IO_CONTROL0; + + return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &config)); +} + +static const struct of_device_id ds4520_gpio_of_match_table[] = { + { .compatible = "adi,ds4520-gpio" }, + { } +}; +MODULE_DEVICE_TABLE(of, ds4520_gpio_of_match_table); + +static const struct i2c_device_id ds4520_gpio_id_table[] = { + { "ds4520-gpio" }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ds4520_gpio_id_table); + +static struct i2c_driver ds4520_gpio_driver = { + .driver = { + .name = "ds4520-gpio", + .of_match_table = ds4520_gpio_of_match_table, + }, + .probe = ds4520_gpio_probe, + .id_table = ds4520_gpio_id_table, +}; +module_i2c_driver(ds4520_gpio_driver); + +MODULE_DESCRIPTION("DS4520 I/O Expander"); +MODULE_AUTHOR("Okan Sahin <okan.sahin@analog.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c index 84352a6f4973..5320cf1de89c 100644 --- a/drivers/gpio/gpio-eic-sprd.c +++ b/drivers/gpio/gpio-eic-sprd.c @@ -9,7 +9,7 @@ #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/spinlock.h> @@ -653,7 +653,6 @@ static int sprd_eic_probe(struct platform_device *pdev) return ret; } - platform_set_drvdata(pdev, sprd_eic); return 0; } diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c index df1bdaae441c..5170fe7599cd 100644 --- a/drivers/gpio/gpio-exar.c +++ b/drivers/gpio/gpio-exar.c @@ -217,8 +217,6 @@ static int gpio_exar_probe(struct platform_device *pdev) if (ret) return ret; - platform_set_drvdata(pdev, exar_gpio); - return 0; } diff --git a/drivers/gpio/gpio-ftgpio010.c b/drivers/gpio/gpio-ftgpio010.c index 31e26072f6ae..5ce59dcf02e3 100644 --- a/drivers/gpio/gpio-ftgpio010.c +++ b/drivers/gpio/gpio-ftgpio010.c @@ -250,8 +250,8 @@ static int ftgpio_gpio_probe(struct platform_device *pdev) return PTR_ERR(g->base); irq = platform_get_irq(pdev, 0); - if (irq <= 0) - return irq ? irq : -EINVAL; + if (irq < 0) + return irq; g->clk = devm_clk_get(dev, NULL); if (!IS_ERR(g->clk)) { diff --git a/drivers/gpio/gpio-ge.c b/drivers/gpio/gpio-ge.c index 7bd4c2a4cc11..5dc49648d8e3 100644 --- a/drivers/gpio/gpio-ge.c +++ b/drivers/gpio/gpio-ge.c @@ -1,29 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Driver for GE FPGA based GPIO * * Author: Martyn Welch <martyn.welch@ge.com> * * 2008 (c) GE Intelligent Platforms Embedded Systems, Inc. - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. */ -/* TODO +/* + * TODO: * - * Configuration of output modes (totem-pole/open-drain) - * Interrupt configuration - interrupts are always generated the FPGA relies on - * the I/O interrupt controllers mask to stop them propergating + * Configuration of output modes (totem-pole/open-drain). + * Interrupt configuration - interrupts are always generated, the FPGA relies + * on the I/O interrupt controllers mask to stop them from being propagated. */ -#include <linux/kernel.h> +#include <linux/gpio/driver.h> #include <linux/io.h> -#include <linux/slab.h> -#include <linux/of_device.h> -#include <linux/of_address.h> +#include <linux/kernel.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/gpio/driver.h> +#include <linux/platform_device.h> +#include <linux/property.h> +#include <linux/slab.h> #define GEF_GPIO_DIRECT 0x00 #define GEF_GPIO_IN 0x04 @@ -52,46 +51,39 @@ MODULE_DEVICE_TABLE(of, gef_gpio_ids); static int __init gef_gpio_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct gpio_chip *gc; void __iomem *regs; int ret; - gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL); + gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); if (!gc) return -ENOMEM; - regs = of_iomap(pdev->dev.of_node, 0); - if (!regs) - return -ENOMEM; + regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) + return PTR_ERR(regs); - ret = bgpio_init(gc, &pdev->dev, 4, regs + GEF_GPIO_IN, - regs + GEF_GPIO_OUT, NULL, NULL, - regs + GEF_GPIO_DIRECT, BGPIOF_BIG_ENDIAN_BYTE_ORDER); - if (ret) { - dev_err(&pdev->dev, "bgpio_init failed\n"); - goto err0; - } + ret = bgpio_init(gc, dev, 4, regs + GEF_GPIO_IN, regs + GEF_GPIO_OUT, + NULL, NULL, regs + GEF_GPIO_DIRECT, + BGPIOF_BIG_ENDIAN_BYTE_ORDER); + if (ret) + return dev_err_probe(dev, ret, "bgpio_init failed\n"); /* Setup pointers to chip functions */ - gc->label = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%pOF", pdev->dev.of_node); - if (!gc->label) { - ret = -ENOMEM; - goto err0; - } + gc->label = devm_kasprintf(dev, GFP_KERNEL, "%pfw", dev_fwnode(dev)); + if (!gc->label) + return -ENOMEM; gc->base = -1; - gc->ngpio = (u16)(uintptr_t)of_device_get_match_data(&pdev->dev); + gc->ngpio = (uintptr_t)device_get_match_data(dev); /* This function adds a memory mapped GPIO chip */ - ret = devm_gpiochip_add_data(&pdev->dev, gc, NULL); + ret = devm_gpiochip_add_data(dev, gc, NULL); if (ret) - goto err0; + return dev_err_probe(dev, ret, "GPIO chip registration failed\n"); return 0; -err0: - iounmap(regs); - pr_err("%pOF: GPIO chip registration failed\n", pdev->dev.of_node); - return ret; }; static struct platform_driver gef_gpio_driver = { @@ -103,5 +95,5 @@ static struct platform_driver gef_gpio_driver = { module_platform_driver_probe(gef_gpio_driver, gef_gpio_probe); MODULE_DESCRIPTION("GE I/O FPGA GPIO driver"); -MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com"); +MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com>"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-grgpio.c b/drivers/gpio/gpio-grgpio.c index bea0e32c195d..0163c95f6dd7 100644 --- a/drivers/gpio/gpio-grgpio.c +++ b/drivers/gpio/gpio-grgpio.c @@ -19,10 +19,10 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> +#include <linux/platform_device.h> #include <linux/spinlock.h> #include <linux/io.h> #include <linux/of.h> -#include <linux/of_platform.h> #include <linux/gpio/driver.h> #include <linux/slab.h> #include <linux/err.h> diff --git a/drivers/gpio/gpio-hlwd.c b/drivers/gpio/gpio-hlwd.c index c208ac1c54a6..1bcfc1835dae 100644 --- a/drivers/gpio/gpio-hlwd.c +++ b/drivers/gpio/gpio-hlwd.c @@ -10,7 +10,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/seq_file.h> #include <linux/slab.h> diff --git a/drivers/gpio/gpio-idio-16.c b/drivers/gpio/gpio-idio-16.c index 13315242d220..53b1eb876a12 100644 --- a/drivers/gpio/gpio-idio-16.c +++ b/drivers/gpio/gpio-idio-16.c @@ -3,143 +3,169 @@ * GPIO library for the ACCES IDIO-16 family * Copyright (C) 2022 William Breathitt Gray */ -#include <linux/bitmap.h> +#include <linux/bits.h> +#include <linux/device.h> +#include <linux/err.h> #include <linux/export.h> -#include <linux/io.h> +#include <linux/gpio/regmap.h> #include <linux/module.h> -#include <linux/spinlock.h> +#include <linux/regmap.h> #include <linux/types.h> #include "gpio-idio-16.h" #define DEFAULT_SYMBOL_NAMESPACE GPIO_IDIO_16 -/** - * idio_16_get - get signal value at signal offset - * @reg: ACCES IDIO-16 device registers - * @state: ACCES IDIO-16 device state - * @offset: offset of signal to get - * - * Returns the signal value (0=low, 1=high) for the signal at @offset. - */ -int idio_16_get(struct idio_16 __iomem *const reg, - struct idio_16_state *const state, const unsigned long offset) -{ - const unsigned long mask = BIT(offset); - - if (offset < IDIO_16_NOUT) - return test_bit(offset, state->out_state); - - if (offset < 24) - return !!(ioread8(®->in0_7) & (mask >> IDIO_16_NOUT)); - - if (offset < 32) - return !!(ioread8(®->in8_15) & (mask >> 24)); - - return -EINVAL; -} -EXPORT_SYMBOL_GPL(idio_16_get); - -/** - * idio_16_get_multiple - get multiple signal values at multiple signal offsets - * @reg: ACCES IDIO-16 device registers - * @state: ACCES IDIO-16 device state - * @mask: mask of signals to get - * @bits: bitmap to store signal values - * - * Stores in @bits the values (0=low, 1=high) for the signals defined by @mask. - */ -void idio_16_get_multiple(struct idio_16 __iomem *const reg, - struct idio_16_state *const state, - const unsigned long *const mask, - unsigned long *const bits) +#define IDIO_16_DAT_BASE 0x0 +#define IDIO_16_OUT_BASE IDIO_16_DAT_BASE +#define IDIO_16_IN_BASE (IDIO_16_DAT_BASE + 1) +#define IDIO_16_CLEAR_INTERRUPT 0x1 +#define IDIO_16_ENABLE_IRQ 0x2 +#define IDIO_16_DEACTIVATE_INPUT_FILTERS 0x3 +#define IDIO_16_DISABLE_IRQ IDIO_16_ENABLE_IRQ +#define IDIO_16_INTERRUPT_STATUS 0x6 + +#define IDIO_16_NGPIO 32 +#define IDIO_16_NGPIO_PER_REG 8 +#define IDIO_16_REG_STRIDE 4 + +struct idio_16_data { + struct regmap *map; + unsigned int irq_mask; +}; + +static int idio_16_handle_mask_sync(const int index, const unsigned int mask_buf_def, + const unsigned int mask_buf, void *const irq_drv_data) { - unsigned long flags; - const unsigned long out_mask = GENMASK(IDIO_16_NOUT - 1, 0); - - spin_lock_irqsave(&state->lock, flags); - - bitmap_replace(bits, bits, state->out_state, &out_mask, IDIO_16_NOUT); - if (*mask & GENMASK(23, 16)) - bitmap_set_value8(bits, ioread8(®->in0_7), 16); - if (*mask & GENMASK(31, 24)) - bitmap_set_value8(bits, ioread8(®->in8_15), 24); - - spin_unlock_irqrestore(&state->lock, flags); + struct idio_16_data *const data = irq_drv_data; + const unsigned int prev_mask = data->irq_mask; + int err; + unsigned int val; + + /* exit early if no change since the previous mask */ + if (mask_buf == prev_mask) + return 0; + + /* remember the current mask for the next mask sync */ + data->irq_mask = mask_buf; + + /* if all previously masked, enable interrupts when unmasking */ + if (prev_mask == mask_buf_def) { + err = regmap_write(data->map, IDIO_16_CLEAR_INTERRUPT, 0x00); + if (err) + return err; + return regmap_read(data->map, IDIO_16_ENABLE_IRQ, &val); + } + + /* if all are currently masked, disable interrupts */ + if (mask_buf == mask_buf_def) + return regmap_write(data->map, IDIO_16_DISABLE_IRQ, 0x00); + + return 0; } -EXPORT_SYMBOL_GPL(idio_16_get_multiple); -/** - * idio_16_set - set signal value at signal offset - * @reg: ACCES IDIO-16 device registers - * @state: ACCES IDIO-16 device state - * @offset: offset of signal to set - * @value: value of signal to set - * - * Assigns output @value for the signal at @offset. - */ -void idio_16_set(struct idio_16 __iomem *const reg, - struct idio_16_state *const state, const unsigned long offset, - const unsigned long value) +static int idio_16_reg_mask_xlate(struct gpio_regmap *const gpio, const unsigned int base, + const unsigned int offset, unsigned int *const reg, + unsigned int *const mask) { - unsigned long flags; - - if (offset >= IDIO_16_NOUT) - return; + unsigned int stride; - spin_lock_irqsave(&state->lock, flags); + /* Input lines start at GPIO 16 */ + if (offset < 16) { + stride = offset / IDIO_16_NGPIO_PER_REG; + *reg = IDIO_16_OUT_BASE + stride * IDIO_16_REG_STRIDE; + } else { + stride = (offset - 16) / IDIO_16_NGPIO_PER_REG; + *reg = IDIO_16_IN_BASE + stride * IDIO_16_REG_STRIDE; + } - __assign_bit(offset, state->out_state, value); - if (offset < 8) - iowrite8(bitmap_get_value8(state->out_state, 0), ®->out0_7); - else - iowrite8(bitmap_get_value8(state->out_state, 8), ®->out8_15); + *mask = BIT(offset % IDIO_16_NGPIO_PER_REG); - spin_unlock_irqrestore(&state->lock, flags); + return 0; } -EXPORT_SYMBOL_GPL(idio_16_set); - -/** - * idio_16_set_multiple - set signal values at multiple signal offsets - * @reg: ACCES IDIO-16 device registers - * @state: ACCES IDIO-16 device state - * @mask: mask of signals to set - * @bits: bitmap of signal output values - * - * Assigns output values defined by @bits for the signals defined by @mask. - */ -void idio_16_set_multiple(struct idio_16 __iomem *const reg, - struct idio_16_state *const state, - const unsigned long *const mask, - const unsigned long *const bits) -{ - unsigned long flags; - spin_lock_irqsave(&state->lock, flags); - - bitmap_replace(state->out_state, state->out_state, bits, mask, - IDIO_16_NOUT); - if (*mask & GENMASK(7, 0)) - iowrite8(bitmap_get_value8(state->out_state, 0), ®->out0_7); - if (*mask & GENMASK(15, 8)) - iowrite8(bitmap_get_value8(state->out_state, 8), ®->out8_15); - - spin_unlock_irqrestore(&state->lock, flags); -} -EXPORT_SYMBOL_GPL(idio_16_set_multiple); +static const char *idio_16_names[IDIO_16_NGPIO] = { + "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7", + "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15", + "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7", + "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15", +}; /** - * idio_16_state_init - initialize idio_16_state structure - * @state: ACCES IDIO-16 device state + * devm_idio_16_regmap_register - Register an IDIO-16 GPIO device + * @dev: device that is registering this IDIO-16 GPIO device + * @config: configuration for idio_16_regmap_config * - * Initializes the ACCES IDIO-16 device @state for use in idio-16 library - * functions. + * Registers an IDIO-16 GPIO device. Returns 0 on success and negative error number on failure. */ -void idio_16_state_init(struct idio_16_state *const state) +int devm_idio_16_regmap_register(struct device *const dev, + const struct idio_16_regmap_config *const config) { - spin_lock_init(&state->lock); + struct gpio_regmap_config gpio_config = {}; + int err; + struct idio_16_data *data; + struct regmap_irq_chip *chip; + struct regmap_irq_chip_data *chip_data; + + if (!config->parent) + return -EINVAL; + + if (!config->map) + return -EINVAL; + + if (!config->regmap_irqs) + return -EINVAL; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + data->map = config->map; + + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->name = dev_name(dev); + chip->status_base = IDIO_16_INTERRUPT_STATUS; + chip->mask_base = IDIO_16_ENABLE_IRQ; + chip->ack_base = IDIO_16_CLEAR_INTERRUPT; + chip->no_status = config->no_status; + chip->num_regs = 1; + chip->irqs = config->regmap_irqs; + chip->num_irqs = config->num_regmap_irqs; + chip->handle_mask_sync = idio_16_handle_mask_sync; + chip->irq_drv_data = data; + + /* Disable IRQ to prevent spurious interrupts before we're ready */ + err = regmap_write(data->map, IDIO_16_DISABLE_IRQ, 0x00); + if (err) + return err; + + err = devm_regmap_add_irq_chip(dev, data->map, config->irq, 0, 0, chip, &chip_data); + if (err) + return dev_err_probe(dev, err, "IRQ registration failed\n"); + + if (config->filters) { + /* Deactivate input filters */ + err = regmap_write(data->map, IDIO_16_DEACTIVATE_INPUT_FILTERS, 0x00); + if (err) + return err; + } + + gpio_config.parent = config->parent; + gpio_config.regmap = data->map; + gpio_config.ngpio = IDIO_16_NGPIO; + gpio_config.names = idio_16_names; + gpio_config.reg_dat_base = GPIO_REGMAP_ADDR(IDIO_16_DAT_BASE); + gpio_config.reg_set_base = GPIO_REGMAP_ADDR(IDIO_16_DAT_BASE); + gpio_config.ngpio_per_reg = IDIO_16_NGPIO_PER_REG; + gpio_config.reg_stride = IDIO_16_REG_STRIDE; + gpio_config.irq_domain = regmap_irq_get_domain(chip_data); + gpio_config.reg_mask_xlate = idio_16_reg_mask_xlate; + + return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config)); } -EXPORT_SYMBOL_GPL(idio_16_state_init); +EXPORT_SYMBOL_GPL(devm_idio_16_regmap_register); MODULE_AUTHOR("William Breathitt Gray"); MODULE_DESCRIPTION("ACCES IDIO-16 GPIO Library"); diff --git a/drivers/gpio/gpio-idio-16.h b/drivers/gpio/gpio-idio-16.h index 928f8251a2bd..93b08ad73065 100644 --- a/drivers/gpio/gpio-idio-16.h +++ b/drivers/gpio/gpio-idio-16.h @@ -3,69 +3,30 @@ #ifndef _IDIO_16_H_ #define _IDIO_16_H_ -#include <linux/spinlock.h> -#include <linux/types.h> +struct device; +struct regmap; +struct regmap_irq; /** - * struct idio_16 - IDIO-16 registers structure - * @out0_7: Read: FET Drive Outputs 0-7 - * Write: FET Drive Outputs 0-7 - * @in0_7: Read: Isolated Inputs 0-7 - * Write: Clear Interrupt - * @irq_ctl: Read: Enable IRQ - * Write: Disable IRQ - * @filter_ctl: Read: Activate Input Filters 0-15 - * Write: Deactivate Input Filters 0-15 - * @out8_15: Read: FET Drive Outputs 8-15 - * Write: FET Drive Outputs 8-15 - * @in8_15: Read: Isolated Inputs 8-15 - * Write: Unused - * @irq_status: Read: Interrupt status - * Write: Unused + * struct idio_16_regmap_config - Configuration for the IDIO-16 register map + * @parent: parent device + * @map: regmap for the IDIO-16 device + * @regmap_irqs: descriptors for individual IRQs + * @num_regmap_irqs: number of IRQ descriptors + * @irq: IRQ number for the IDIO-16 device + * @no_status: device has no status register + * @filters: device has input filters */ -struct idio_16 { - u8 out0_7; - u8 in0_7; - u8 irq_ctl; - u8 filter_ctl; - u8 out8_15; - u8 in8_15; - u8 irq_status; +struct idio_16_regmap_config { + struct device *parent; + struct regmap *map; + const struct regmap_irq *regmap_irqs; + int num_regmap_irqs; + unsigned int irq; + bool no_status; + bool filters; }; -#define IDIO_16_NOUT 16 - -/** - * struct idio_16_state - IDIO-16 state structure - * @lock: synchronization lock for accessing device state - * @out_state: output signals state - */ -struct idio_16_state { - spinlock_t lock; - DECLARE_BITMAP(out_state, IDIO_16_NOUT); -}; - -/** - * idio_16_get_direction - get the I/O direction for a signal offset - * @offset: offset of signal to get direction - * - * Returns the signal direction (0=output, 1=input) for the signal at @offset. - */ -static inline int idio_16_get_direction(const unsigned long offset) -{ - return (offset >= IDIO_16_NOUT) ? 1 : 0; -} - -int idio_16_get(struct idio_16 __iomem *reg, struct idio_16_state *state, - unsigned long offset); -void idio_16_get_multiple(struct idio_16 __iomem *reg, - struct idio_16_state *state, - const unsigned long *mask, unsigned long *bits); -void idio_16_set(struct idio_16 __iomem *reg, struct idio_16_state *state, - unsigned long offset, unsigned long value); -void idio_16_set_multiple(struct idio_16 __iomem *reg, - struct idio_16_state *state, - const unsigned long *mask, const unsigned long *bits); -void idio_16_state_init(struct idio_16_state *state); +int devm_idio_16_regmap_register(struct device *dev, const struct idio_16_regmap_config *config); #endif /* _IDIO_16_H_ */ diff --git a/drivers/gpio/gpio-imx-scu.c b/drivers/gpio/gpio-imx-scu.c index e190bde5397d..13baf465aedf 100644 --- a/drivers/gpio/gpio-imx-scu.c +++ b/drivers/gpio/gpio-imx-scu.c @@ -6,6 +6,7 @@ * to control the PIN resources on SCU domain. */ +#include <linux/kernel.h> #include <linux/module.h> #include <linux/gpio/driver.h> #include <linux/platform_device.h> @@ -103,7 +104,7 @@ static int imx_scu_gpio_probe(struct platform_device *pdev) gc = &priv->chip; gc->base = -1; gc->parent = dev; - gc->ngpio = sizeof(scu_rsrc_arr)/sizeof(unsigned int); + gc->ngpio = ARRAY_SIZE(scu_rsrc_arr); gc->label = dev_name(dev); gc->get = imx_scu_gpio_get; gc->set = imx_scu_gpio_set; diff --git a/drivers/gpio/gpio-ixp4xx.c b/drivers/gpio/gpio-ixp4xx.c index 1e29de1671d4..dde6cf3a5779 100644 --- a/drivers/gpio/gpio-ixp4xx.c +++ b/drivers/gpio/gpio-ixp4xx.c @@ -302,7 +302,7 @@ static const struct of_device_id ixp4xx_gpio_of_match[] = { static struct platform_driver ixp4xx_gpio_driver = { .driver = { .name = "ixp4xx-gpio", - .of_match_table = of_match_ptr(ixp4xx_gpio_of_match), + .of_match_table = ixp4xx_gpio_of_match, }, .probe = ixp4xx_gpio_probe, }; diff --git a/drivers/gpio/gpio-logicvc.c b/drivers/gpio/gpio-logicvc.c index 992cc958a43f..05d62011f335 100644 --- a/drivers/gpio/gpio-logicvc.c +++ b/drivers/gpio/gpio-logicvc.c @@ -8,7 +8,6 @@ #include <linux/gpio/driver.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_address.h> #include <linux/platform_device.h> #include <linux/regmap.h> @@ -139,8 +138,6 @@ static int logicvc_gpio_probe(struct platform_device *pdev) logicvc->chip.set = logicvc_gpio_set; logicvc->chip.direction_output = logicvc_gpio_direction_output; - platform_set_drvdata(pdev, logicvc); - return devm_gpiochip_add_data(dev, &logicvc->chip, logicvc); } diff --git a/drivers/gpio/gpio-lp3943.c b/drivers/gpio/gpio-lp3943.c index 79edd5db49d2..8e58242f5123 100644 --- a/drivers/gpio/gpio-lp3943.c +++ b/drivers/gpio/gpio-lp3943.c @@ -199,8 +199,6 @@ static int lp3943_gpio_probe(struct platform_device *pdev) lp3943_gpio->chip = lp3943_gpio_chip; lp3943_gpio->chip.parent = &pdev->dev; - platform_set_drvdata(pdev, lp3943_gpio); - return devm_gpiochip_add_data(&pdev->dev, &lp3943_gpio->chip, lp3943_gpio); } diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index d2b65cfb336e..5ef8af824980 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -525,17 +525,15 @@ static int lpc32xx_gpio_probe(struct platform_device *pdev) return 0; } -#ifdef CONFIG_OF static const struct of_device_id lpc32xx_gpio_of_match[] = { { .compatible = "nxp,lpc3220-gpio", }, { }, }; -#endif static struct platform_driver lpc32xx_gpio_driver = { .driver = { .name = "lpc32xx-gpio", - .of_match_table = of_match_ptr(lpc32xx_gpio_of_match), + .of_match_table = lpc32xx_gpio_of_match, }, .probe = lpc32xx_gpio_probe, }; diff --git a/drivers/gpio/gpio-max3191x.c b/drivers/gpio/gpio-max3191x.c index 161c4751c5f7..bbacc714632b 100644 --- a/drivers/gpio/gpio-max3191x.c +++ b/drivers/gpio/gpio-max3191x.c @@ -457,7 +457,6 @@ static int __init max3191x_register_driver(struct spi_driver *sdrv) return spi_register_driver(sdrv); } -#ifdef CONFIG_OF static const struct of_device_id max3191x_of_id[] = { { .compatible = "maxim,max31910" }, { .compatible = "maxim,max31911" }, @@ -468,7 +467,6 @@ static const struct of_device_id max3191x_of_id[] = { { } }; MODULE_DEVICE_TABLE(of, max3191x_of_id); -#endif static const struct spi_device_id max3191x_spi_id[] = { { "max31910" }, @@ -484,7 +482,7 @@ MODULE_DEVICE_TABLE(spi, max3191x_spi_id); static struct spi_driver max3191x_driver = { .driver = { .name = "max3191x", - .of_match_table = of_match_ptr(max3191x_of_id), + .of_match_table = max3191x_of_id, }, .probe = max3191x_probe, .remove = max3191x_remove, diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c index fca9ca68e387..49d362907bc7 100644 --- a/drivers/gpio/gpio-max732x.c +++ b/drivers/gpio/gpio-max732x.c @@ -18,8 +18,6 @@ #include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/platform_data/max732x.h> -#include <linux/of.h> - /* * Each port of MAX732x (including MAX7319) falls into one of the @@ -114,7 +112,6 @@ static const struct i2c_device_id max732x_id[] = { }; MODULE_DEVICE_TABLE(i2c, max732x_id); -#ifdef CONFIG_OF static const struct of_device_id max732x_of_table[] = { { .compatible = "maxim,max7319" }, { .compatible = "maxim,max7320" }, @@ -128,7 +125,6 @@ static const struct of_device_id max732x_of_table[] = { { } }; MODULE_DEVICE_TABLE(of, max732x_of_table); -#endif struct max732x_chip { struct gpio_chip gpio_chip; @@ -709,7 +705,7 @@ static int max732x_probe(struct i2c_client *client) static struct i2c_driver max732x_driver = { .driver = { .name = "max732x", - .of_match_table = of_match_ptr(max732x_of_table), + .of_match_table = max732x_of_table, }, .probe = max732x_probe, .id_table = max732x_id, diff --git a/drivers/gpio/gpio-max77620.c b/drivers/gpio/gpio-max77620.c index c18b60e39a94..8c2a5609161f 100644 --- a/drivers/gpio/gpio-max77620.c +++ b/drivers/gpio/gpio-max77620.c @@ -331,8 +331,6 @@ static int max77620_gpio_probe(struct platform_device *pdev) girq->init_hw = max77620_gpio_irq_init_hw; girq->threaded = true; - platform_set_drvdata(pdev, mgpio); - ret = devm_gpiochip_add_data(&pdev->dev, &mgpio->gpio_chip, mgpio); if (ret < 0) { dev_err(&pdev->dev, "gpio_init: Failed to add max77620_gpio\n"); diff --git a/drivers/gpio/gpio-mb86s7x.c b/drivers/gpio/gpio-mb86s7x.c index 37c5363e391e..ca7eb5e8bfaa 100644 --- a/drivers/gpio/gpio-mb86s7x.c +++ b/drivers/gpio/gpio-mb86s7x.c @@ -10,11 +10,11 @@ #include <linux/io.h> #include <linux/init.h> #include <linux/clk.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/err.h> #include <linux/errno.h> #include <linux/ioport.h> -#include <linux/of_device.h> #include <linux/gpio/driver.h> #include <linux/platform_device.h> #include <linux/spinlock.h> diff --git a/drivers/gpio/gpio-mlxbf3.c b/drivers/gpio/gpio-mlxbf3.c index e30cee108986..7a3e1760fc5b 100644 --- a/drivers/gpio/gpio-mlxbf3.c +++ b/drivers/gpio/gpio-mlxbf3.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0-only or BSD-3-Clause +// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause /* Copyright (C) 2022 NVIDIA CORPORATION & AFFILIATES */ #include <linux/bitfield.h> @@ -19,6 +19,8 @@ * gpio[1]: HOST_GPIO32->HOST_GPIO55 */ #define MLXBF3_GPIO_MAX_PINS_PER_BLOCK 32 +#define MLXBF3_GPIO_MAX_PINS_BLOCK0 32 +#define MLXBF3_GPIO_MAX_PINS_BLOCK1 24 /* * fw_gpio[x] block registers and their offset @@ -158,6 +160,26 @@ static const struct irq_chip gpio_mlxbf3_irqchip = { GPIOCHIP_IRQ_RESOURCE_HELPERS, }; +static int mlxbf3_gpio_add_pin_ranges(struct gpio_chip *chip) +{ + unsigned int id; + + switch(chip->ngpio) { + case MLXBF3_GPIO_MAX_PINS_BLOCK0: + id = 0; + break; + case MLXBF3_GPIO_MAX_PINS_BLOCK1: + id = 1; + break; + default: + return -EINVAL; + } + + return gpiochip_add_pin_range(chip, "MLNXBF34:00", + chip->base, id * MLXBF3_GPIO_MAX_PINS_PER_BLOCK, + chip->ngpio); +} + static int mlxbf3_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -197,6 +219,7 @@ static int mlxbf3_gpio_probe(struct platform_device *pdev) gc->request = gpiochip_generic_request; gc->free = gpiochip_generic_free; gc->owner = THIS_MODULE; + gc->add_pin_ranges = mlxbf3_gpio_add_pin_ranges; irq = platform_get_irq(pdev, 0); if (irq >= 0) { @@ -243,6 +266,7 @@ static struct platform_driver mlxbf3_gpio_driver = { }; module_platform_driver(mlxbf3_gpio_driver); +MODULE_SOFTDEP("pre: pinctrl-mlxbf3"); MODULE_DESCRIPTION("NVIDIA BlueField-3 GPIO Driver"); MODULE_AUTHOR("Asmaa Mnebhi <asmaa@nvidia.com>"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c index d9dff3dc92ae..74fdf0d87b2c 100644 --- a/drivers/gpio/gpio-mmio.c +++ b/drivers/gpio/gpio-mmio.c @@ -60,6 +60,8 @@ o ` ~~~~\___/~~~~ ` controller in FPGA is ,.` #include <linux/of.h> #include <linux/of_device.h> +#include "gpiolib.h" + static void bgpio_write8(void __iomem *reg, unsigned long data) { writeb(data, reg); @@ -614,10 +616,15 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev, gc->parent = dev; gc->label = dev_name(dev); gc->base = -1; - gc->ngpio = gc->bgpio_bits; gc->request = bgpio_request; gc->be_bits = !!(flags & BGPIOF_BIG_ENDIAN); + ret = gpiochip_get_ngpios(gc, dev); + if (ret) + gc->ngpio = gc->bgpio_bits; + else + gc->bgpio_bits = roundup_pow_of_two(round_up(gc->ngpio, 8)); + ret = bgpio_setup_io(gc, dat, set, clr, flags); if (ret) return ret; diff --git a/drivers/gpio/gpio-mpc5200.c b/drivers/gpio/gpio-mpc5200.c index 3b0bfff8c778..b49e3ca64015 100644 --- a/drivers/gpio/gpio-mpc5200.c +++ b/drivers/gpio/gpio-mpc5200.c @@ -10,7 +10,7 @@ #include <linux/slab.h> #include <linux/gpio/legacy-of-mm-gpiochip.h> #include <linux/io.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/module.h> #include <asm/mpc52xx.h> diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index 5979a36bf754..ebf2f511df59 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -9,12 +9,10 @@ #include <linux/acpi.h> #include <linux/kernel.h> #include <linux/init.h> +#include <linux/platform_device.h> #include <linux/spinlock.h> #include <linux/io.h> #include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_irq.h> -#include <linux/of_platform.h> #include <linux/property.h> #include <linux/mod_devicetable.h> #include <linux/slab.h> diff --git a/drivers/gpio/gpio-msc313.c b/drivers/gpio/gpio-msc313.c index 036ad2324892..2f448eb23abb 100644 --- a/drivers/gpio/gpio-msc313.c +++ b/drivers/gpio/gpio-msc313.c @@ -6,7 +6,6 @@ #include <linux/types.h> #include <linux/io.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/gpio/driver.h> #include <linux/module.h> diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 9d0cec4b82a3..4cb455b2bdee 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -17,12 +17,12 @@ #include <linux/irqchip/chained_irq.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/syscore_ops.h> #include <linux/gpio/driver.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/bug.h> #define IMX_SCU_WAKEUP_OFF 0 @@ -62,6 +62,7 @@ struct mxc_gpio_port { struct clk *clk; int irq; int irq_high; + void (*mx_irq_handler)(struct irq_desc *desc); struct irq_domain *domain; struct gpio_chip gc; struct device *dev; @@ -382,6 +383,41 @@ static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned offset) return irq_find_mapping(port->domain, offset); } +static int mxc_gpio_request(struct gpio_chip *chip, unsigned int offset) +{ + int ret; + + ret = gpiochip_generic_request(chip, offset); + if (ret) + return ret; + + return pm_runtime_resume_and_get(chip->parent); +} + +static void mxc_gpio_free(struct gpio_chip *chip, unsigned int offset) +{ + gpiochip_generic_free(chip, offset); + pm_runtime_put(chip->parent); +} + +static void mxc_update_irq_chained_handler(struct mxc_gpio_port *port, bool enable) +{ + if (enable) + irq_set_chained_handler_and_data(port->irq, port->mx_irq_handler, port); + else + irq_set_chained_handler_and_data(port->irq, NULL, NULL); + + /* setup handler for GPIO 16 to 31 */ + if (port->irq_high > 0) { + if (enable) + irq_set_chained_handler_and_data(port->irq_high, + port->mx_irq_handler, + port); + else + irq_set_chained_handler_and_data(port->irq_high, NULL, NULL); + } +} + static int mxc_gpio_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -416,19 +452,17 @@ static int mxc_gpio_probe(struct platform_device *pdev) return port->irq; /* the controller clock is optional */ - port->clk = devm_clk_get_optional(&pdev->dev, NULL); + port->clk = devm_clk_get_optional_enabled(&pdev->dev, NULL); if (IS_ERR(port->clk)) return PTR_ERR(port->clk); - err = clk_prepare_enable(port->clk); - if (err) { - dev_err(&pdev->dev, "Unable to enable clock.\n"); - return err; - } - if (of_device_is_compatible(np, "fsl,imx7d-gpio")) port->power_off = true; + pm_runtime_get_noresume(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + /* disable the interrupt and clear the status */ writel(0, port->base + GPIO_IMR); writel(~0, port->base + GPIO_ISR); @@ -439,18 +473,12 @@ static int mxc_gpio_probe(struct platform_device *pdev) * the handler is needed only once, but doing it for every port * is more robust and easier. */ - irq_set_chained_handler(port->irq, mx2_gpio_irq_handler); - } else { - /* setup one handler for each entry */ - irq_set_chained_handler_and_data(port->irq, - mx3_gpio_irq_handler, port); - if (port->irq_high > 0) - /* setup handler for GPIO 16 to 31 */ - irq_set_chained_handler_and_data(port->irq_high, - mx3_gpio_irq_handler, - port); - } + port->irq_high = -1; + port->mx_irq_handler = mx2_gpio_irq_handler; + } else + port->mx_irq_handler = mx3_gpio_irq_handler; + mxc_update_irq_chained_handler(port, true); err = bgpio_init(&port->gc, &pdev->dev, 4, port->base + GPIO_PSR, port->base + GPIO_DR, NULL, @@ -459,8 +487,8 @@ static int mxc_gpio_probe(struct platform_device *pdev) if (err) goto out_bgio; - port->gc.request = gpiochip_generic_request; - port->gc.free = gpiochip_generic_free; + port->gc.request = mxc_gpio_request; + port->gc.free = mxc_gpio_free; port->gc.to_irq = mxc_gpio_to_irq; port->gc.base = (pdev->id < 0) ? of_alias_get_id(np, "gpio") * 32 : pdev->id * 32; @@ -482,6 +510,8 @@ static int mxc_gpio_probe(struct platform_device *pdev) goto out_bgio; } + irq_domain_set_pm_device(port->domain, &pdev->dev); + /* gpio-mxc can be a generic irq chip */ err = mxc_gpio_init_gc(port, irq_base); if (err < 0) @@ -490,13 +520,15 @@ static int mxc_gpio_probe(struct platform_device *pdev) list_add_tail(&port->node, &mxc_gpio_ports); platform_set_drvdata(pdev, port); + pm_runtime_put_autosuspend(&pdev->dev); return 0; out_irqdomain_remove: irq_domain_remove(port->domain); out_bgio: - clk_disable_unprepare(port->clk); + pm_runtime_disable(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err); return err; } @@ -572,7 +604,35 @@ static bool mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable) return ret; } -static int __maybe_unused mxc_gpio_noirq_suspend(struct device *dev) +static int mxc_gpio_runtime_suspend(struct device *dev) +{ + struct mxc_gpio_port *port = dev_get_drvdata(dev); + + mxc_gpio_save_regs(port); + clk_disable_unprepare(port->clk); + mxc_update_irq_chained_handler(port, false); + + return 0; +} + +static int mxc_gpio_runtime_resume(struct device *dev) +{ + struct mxc_gpio_port *port = dev_get_drvdata(dev); + int ret; + + mxc_update_irq_chained_handler(port, true); + ret = clk_prepare_enable(port->clk); + if (ret) { + mxc_update_irq_chained_handler(port, false); + return ret; + } + + mxc_gpio_restore_regs(port); + + return 0; +} + +static int mxc_gpio_noirq_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct mxc_gpio_port *port = platform_get_drvdata(pdev); @@ -583,7 +643,7 @@ static int __maybe_unused mxc_gpio_noirq_suspend(struct device *dev) return 0; } -static int __maybe_unused mxc_gpio_noirq_resume(struct device *dev) +static int mxc_gpio_noirq_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct mxc_gpio_port *port = platform_get_drvdata(pdev); @@ -596,15 +656,20 @@ static int __maybe_unused mxc_gpio_noirq_resume(struct device *dev) } static const struct dev_pm_ops mxc_gpio_dev_pm_ops = { - SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mxc_gpio_noirq_suspend, mxc_gpio_noirq_resume) + NOIRQ_SYSTEM_SLEEP_PM_OPS(mxc_gpio_noirq_suspend, mxc_gpio_noirq_resume) + RUNTIME_PM_OPS(mxc_gpio_runtime_suspend, mxc_gpio_runtime_resume, NULL) }; static int mxc_gpio_syscore_suspend(void) { struct mxc_gpio_port *port; + int ret; /* walk through all ports */ list_for_each_entry(port, &mxc_gpio_ports, node) { + ret = clk_prepare_enable(port->clk); + if (ret) + return ret; mxc_gpio_save_regs(port); clk_disable_unprepare(port->clk); } @@ -625,6 +690,7 @@ static void mxc_gpio_syscore_resume(void) return; } mxc_gpio_restore_regs(port); + clk_disable_unprepare(port->clk); } } @@ -638,7 +704,7 @@ static struct platform_driver mxc_gpio_driver = { .name = "gpio-mxc", .of_match_table = mxc_gpio_dt_ids, .suppress_bind_attrs = true, - .pm = &mxc_gpio_dev_pm_ops, + .pm = pm_ptr(&mxc_gpio_dev_pm_ops), }, .probe = mxc_gpio_probe, }; diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 390e619a2831..024ad077e98d 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -14,7 +14,6 @@ #include <linux/irqdomain.h> #include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/gpio/driver.h> @@ -272,7 +271,7 @@ static int mxs_gpio_probe(struct platform_device *pdev) port->id = of_alias_get_id(np, "gpio"); if (port->id < 0) return port->id; - port->devid = (enum mxs_gpio_id)of_device_get_match_data(&pdev->dev); + port->devid = (uintptr_t)of_device_get_match_data(&pdev->dev); port->dev = &pdev->dev; port->irq = platform_get_irq(pdev, 0); if (port->irq < 0) diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index a08be5bf6808..a927680c66f8 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -22,7 +22,6 @@ #include <linux/pm_runtime.h> #include <linux/pm.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/gpio/driver.h> #include <linux/bitops.h> #include <linux/platform_data/gpio-omap.h> @@ -1413,11 +1412,8 @@ static int omap_gpio_probe(struct platform_device *pdev) bank->dev = dev; bank->irq = platform_get_irq(pdev, 0); - if (bank->irq <= 0) { - if (!bank->irq) - bank->irq = -ENXIO; - return dev_err_probe(dev, bank->irq, "can't get irq resource\n"); - } + if (bank->irq < 0) + return bank->irq; bank->chip.parent = dev; bank->chip.owner = THIS_MODULE; diff --git a/drivers/gpio/gpio-palmas.c b/drivers/gpio/gpio-palmas.c index bac10c2faf56..28dba7048509 100644 --- a/drivers/gpio/gpio-palmas.c +++ b/drivers/gpio/gpio-palmas.c @@ -12,7 +12,6 @@ #include <linux/init.h> #include <linux/mfd/palmas.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> struct palmas_gpio { @@ -184,7 +183,6 @@ static int palmas_gpio_probe(struct platform_device *pdev) return ret; } - platform_set_drvdata(pdev, palmas_gpio); return ret; } diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index a806a3c1b801..bdd50a78e414 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -108,6 +108,7 @@ static const struct i2c_device_id pca953x_id[] = { { "tca6408", 8 | PCA953X_TYPE | PCA_INT, }, { "tca6416", 16 | PCA953X_TYPE | PCA_INT, }, { "tca6424", 24 | PCA953X_TYPE | PCA_INT, }, + { "tca9538", 8 | PCA953X_TYPE | PCA_INT, }, { "tca9539", 16 | PCA953X_TYPE | PCA_INT, }, { "tca9554", 8 | PCA953X_TYPE | PCA_INT, }, { "xra1202", 8 | PCA953X_TYPE }, @@ -1051,7 +1052,6 @@ out: static int pca953x_probe(struct i2c_client *client) { - const struct i2c_device_id *i2c_id = i2c_client_get_device_id(client); struct pca953x_platform_data *pdata; struct pca953x_chip *chip; int irq_base = 0; @@ -1090,6 +1090,9 @@ static int pca953x_probe(struct i2c_client *client) } chip->client = client; + chip->driver_data = (uintptr_t)i2c_get_match_data(client); + if (!chip->driver_data) + return -ENODEV; reg = devm_regulator_get(&client->dev, "vcc"); if (IS_ERR(reg)) @@ -1102,20 +1105,6 @@ static int pca953x_probe(struct i2c_client *client) } chip->regulator = reg; - if (i2c_id) { - chip->driver_data = i2c_id->driver_data; - } else { - const void *match; - - match = device_get_match_data(&client->dev); - if (!match) { - ret = -ENODEV; - goto err_exit; - } - - chip->driver_data = (uintptr_t)match; - } - i2c_set_clientdata(client, chip); pca953x_setup_gpio(chip, chip->driver_data & PCA_GPIO_MASK); @@ -1354,6 +1343,7 @@ static const struct of_device_id pca953x_dt_ids[] = { { .compatible = "ti,tca6408", .data = OF_953X( 8, PCA_INT), }, { .compatible = "ti,tca6416", .data = OF_953X(16, PCA_INT), }, { .compatible = "ti,tca6424", .data = OF_953X(24, PCA_INT), }, + { .compatible = "ti,tca9538", .data = OF_953X( 8, PCA_INT), }, { .compatible = "ti,tca9539", .data = OF_953X(16, PCA_INT), }, { .compatible = "onnn,cat9554", .data = OF_953X( 8, PCA_INT), }, diff --git a/drivers/gpio/gpio-pca9570.c b/drivers/gpio/gpio-pca9570.c index d8db80ef1293..d37ba4049368 100644 --- a/drivers/gpio/gpio-pca9570.c +++ b/drivers/gpio/gpio-pca9570.c @@ -30,7 +30,7 @@ struct pca9570_chip_data { /** * struct pca9570 - GPIO driver data * @chip: GPIO controller chip - * @p_data: GPIO controller platform data + * @chip_data: GPIO controller platform data * @lock: Protects write sequences * @out: Buffer for device register */ diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index c4c785548408..53b69abe6787 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c @@ -36,19 +36,19 @@ static const struct i2c_device_id pcf857x_id[] = { MODULE_DEVICE_TABLE(i2c, pcf857x_id); static const struct of_device_id pcf857x_of_table[] = { - { .compatible = "nxp,pcf8574" }, - { .compatible = "nxp,pcf8574a" }, - { .compatible = "nxp,pca8574" }, - { .compatible = "nxp,pca9670" }, - { .compatible = "nxp,pca9672" }, - { .compatible = "nxp,pca9674" }, - { .compatible = "nxp,pcf8575" }, - { .compatible = "nxp,pca8575" }, - { .compatible = "nxp,pca9671" }, - { .compatible = "nxp,pca9673" }, - { .compatible = "nxp,pca9675" }, - { .compatible = "maxim,max7328" }, - { .compatible = "maxim,max7329" }, + { .compatible = "nxp,pcf8574", (void *)8 }, + { .compatible = "nxp,pcf8574a", (void *)8 }, + { .compatible = "nxp,pca8574", (void *)8 }, + { .compatible = "nxp,pca9670", (void *)8 }, + { .compatible = "nxp,pca9672", (void *)8 }, + { .compatible = "nxp,pca9674", (void *)8 }, + { .compatible = "nxp,pcf8575", (void *)16 }, + { .compatible = "nxp,pca8575", (void *)16 }, + { .compatible = "nxp,pca9671", (void *)16 }, + { .compatible = "nxp,pca9673", (void *)16 }, + { .compatible = "nxp,pca9675", (void *)16 }, + { .compatible = "maxim,max7328", (void *)8 }, + { .compatible = "maxim,max7329", (void *)8 }, { } }; MODULE_DEVICE_TABLE(of, pcf857x_of_table); @@ -272,7 +272,6 @@ static const struct irq_chip pcf857x_irq_chip = { static int pcf857x_probe(struct i2c_client *client) { - const struct i2c_device_id *id = i2c_client_get_device_id(client); struct pcf857x *gpio; unsigned int n_latch = 0; int status; @@ -296,7 +295,7 @@ static int pcf857x_probe(struct i2c_client *client) gpio->chip.set_multiple = pcf857x_set_multiple; gpio->chip.direction_input = pcf857x_input; gpio->chip.direction_output = pcf857x_output; - gpio->chip.ngpio = id->driver_data; + gpio->chip.ngpio = (uintptr_t)i2c_get_match_data(client); /* NOTE: the OnSemi jlc1562b is also largely compatible with * these parts, notably for output. It has a low-resolution diff --git a/drivers/gpio/gpio-pci-idio-16.c b/drivers/gpio/gpio-pci-idio-16.c index 6726c32e31e6..44c0a21b1d1d 100644 --- a/drivers/gpio/gpio-pci-idio-16.c +++ b/drivers/gpio/gpio-pci-idio-16.c @@ -5,214 +5,75 @@ */ #include <linux/bits.h> #include <linux/device.h> -#include <linux/errno.h> -#include <linux/gpio/driver.h> -#include <linux/interrupt.h> -#include <linux/irqdesc.h> +#include <linux/err.h> +#include <linux/irq.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> -#include <linux/spinlock.h> +#include <linux/regmap.h> #include <linux/types.h> #include "gpio-idio-16.h" -/** - * struct idio_16_gpio - GPIO device private data structure - * @chip: instance of the gpio_chip - * @lock: synchronization lock to prevent I/O race conditions - * @reg: I/O address offset for the GPIO device registers - * @state: ACCES IDIO-16 device state - * @irq_mask: I/O bits affected by interrupts - */ -struct idio_16_gpio { - struct gpio_chip chip; - raw_spinlock_t lock; - struct idio_16 __iomem *reg; - struct idio_16_state state; - unsigned long irq_mask; +static const struct regmap_range idio_16_wr_ranges[] = { + regmap_reg_range(0x0, 0x2), regmap_reg_range(0x3, 0x4), }; - -static int idio_16_gpio_get_direction(struct gpio_chip *chip, - unsigned int offset) -{ - if (idio_16_get_direction(offset)) - return GPIO_LINE_DIRECTION_IN; - - return GPIO_LINE_DIRECTION_OUT; -} - -static int idio_16_gpio_direction_input(struct gpio_chip *chip, - unsigned int offset) -{ - return 0; -} - -static int idio_16_gpio_direction_output(struct gpio_chip *chip, - unsigned int offset, int value) -{ - chip->set(chip, offset, value); - return 0; -} - -static int idio_16_gpio_get(struct gpio_chip *chip, unsigned int offset) -{ - struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - - return idio_16_get(idio16gpio->reg, &idio16gpio->state, offset); -} - -static int idio_16_gpio_get_multiple(struct gpio_chip *chip, - unsigned long *mask, unsigned long *bits) -{ - struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - - idio_16_get_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits); - return 0; -} - -static void idio_16_gpio_set(struct gpio_chip *chip, unsigned int offset, - int value) -{ - struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - - idio_16_set(idio16gpio->reg, &idio16gpio->state, offset, value); -} - -static void idio_16_gpio_set_multiple(struct gpio_chip *chip, - unsigned long *mask, unsigned long *bits) -{ - struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - - idio_16_set_multiple(idio16gpio->reg, &idio16gpio->state, mask, bits); -} - -static void idio_16_irq_ack(struct irq_data *data) -{ -} - -static void idio_16_irq_mask(struct irq_data *data) -{ - struct gpio_chip *chip = irq_data_get_irq_chip_data(data); - struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - const unsigned long mask = BIT(irqd_to_hwirq(data)); - unsigned long flags; - - idio16gpio->irq_mask &= ~mask; - - if (!idio16gpio->irq_mask) { - raw_spin_lock_irqsave(&idio16gpio->lock, flags); - - iowrite8(0, &idio16gpio->reg->irq_ctl); - - raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); - } - - gpiochip_disable_irq(chip, irqd_to_hwirq(data)); -} - -static void idio_16_irq_unmask(struct irq_data *data) -{ - struct gpio_chip *chip = irq_data_get_irq_chip_data(data); - struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip); - const unsigned long mask = BIT(irqd_to_hwirq(data)); - const unsigned long prev_irq_mask = idio16gpio->irq_mask; - unsigned long flags; - - gpiochip_enable_irq(chip, irqd_to_hwirq(data)); - - idio16gpio->irq_mask |= mask; - - if (!prev_irq_mask) { - raw_spin_lock_irqsave(&idio16gpio->lock, flags); - - ioread8(&idio16gpio->reg->irq_ctl); - - raw_spin_unlock_irqrestore(&idio16gpio->lock, flags); - } -} - -static int idio_16_irq_set_type(struct irq_data *data, unsigned int flow_type) -{ - /* The only valid irq types are none and both-edges */ - if (flow_type != IRQ_TYPE_NONE && - (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH) - return -EINVAL; - - return 0; -} - -static const struct irq_chip idio_16_irqchip = { - .name = "pci-idio-16", - .irq_ack = idio_16_irq_ack, - .irq_mask = idio_16_irq_mask, - .irq_unmask = idio_16_irq_unmask, - .irq_set_type = idio_16_irq_set_type, - .flags = IRQCHIP_IMMUTABLE, - GPIOCHIP_IRQ_RESOURCE_HELPERS, +static const struct regmap_range idio_16_rd_ranges[] = { + regmap_reg_range(0x1, 0x2), regmap_reg_range(0x5, 0x6), }; - -static irqreturn_t idio_16_irq_handler(int irq, void *dev_id) -{ - struct idio_16_gpio *const idio16gpio = dev_id; - unsigned int irq_status; - struct gpio_chip *const chip = &idio16gpio->chip; - int gpio; - - raw_spin_lock(&idio16gpio->lock); - - irq_status = ioread8(&idio16gpio->reg->irq_status); - - raw_spin_unlock(&idio16gpio->lock); - - /* Make sure our device generated IRQ */ - if (!(irq_status & 0x3) || !(irq_status & 0x4)) - return IRQ_NONE; - - for_each_set_bit(gpio, &idio16gpio->irq_mask, chip->ngpio) - generic_handle_domain_irq(chip->irq.domain, gpio); - - raw_spin_lock(&idio16gpio->lock); - - /* Clear interrupt */ - iowrite8(0, &idio16gpio->reg->in0_7); - - raw_spin_unlock(&idio16gpio->lock); - - return IRQ_HANDLED; -} - -#define IDIO_16_NGPIO 32 -static const char *idio_16_names[IDIO_16_NGPIO] = { - "OUT0", "OUT1", "OUT2", "OUT3", "OUT4", "OUT5", "OUT6", "OUT7", - "OUT8", "OUT9", "OUT10", "OUT11", "OUT12", "OUT13", "OUT14", "OUT15", - "IIN0", "IIN1", "IIN2", "IIN3", "IIN4", "IIN5", "IIN6", "IIN7", - "IIN8", "IIN9", "IIN10", "IIN11", "IIN12", "IIN13", "IIN14", "IIN15" +static const struct regmap_range idio_16_precious_ranges[] = { + regmap_reg_range(0x2, 0x2), +}; +static const struct regmap_access_table idio_16_wr_table = { + .yes_ranges = idio_16_wr_ranges, + .n_yes_ranges = ARRAY_SIZE(idio_16_wr_ranges), +}; +static const struct regmap_access_table idio_16_rd_table = { + .yes_ranges = idio_16_rd_ranges, + .n_yes_ranges = ARRAY_SIZE(idio_16_rd_ranges), +}; +static const struct regmap_access_table idio_16_precious_table = { + .yes_ranges = idio_16_precious_ranges, + .n_yes_ranges = ARRAY_SIZE(idio_16_precious_ranges), +}; +static const struct regmap_config idio_16_regmap_config = { + .reg_bits = 8, + .reg_stride = 1, + .val_bits = 8, + .io_port = true, + .wr_table = &idio_16_wr_table, + .rd_table = &idio_16_rd_table, + .volatile_table = &idio_16_rd_table, + .precious_table = &idio_16_precious_table, + .cache_type = REGCACHE_FLAT, + .use_raw_spinlock = true, }; -static int idio_16_irq_init_hw(struct gpio_chip *gc) -{ - struct idio_16_gpio *const idio16gpio = gpiochip_get_data(gc); - - /* Disable IRQ by default and clear any pending interrupt */ - iowrite8(0, &idio16gpio->reg->irq_ctl); - iowrite8(0, &idio16gpio->reg->in0_7); +/* Only input lines (GPIO 16-31) support interrupts */ +#define IDIO_16_REGMAP_IRQ(_id) \ + [16 + _id] = { \ + .mask = BIT(2), \ + .type = { .types_supported = IRQ_TYPE_EDGE_BOTH }, \ + } - return 0; -} +static const struct regmap_irq idio_16_regmap_irqs[] = { + IDIO_16_REGMAP_IRQ(0), IDIO_16_REGMAP_IRQ(1), IDIO_16_REGMAP_IRQ(2), /* 0-2 */ + IDIO_16_REGMAP_IRQ(3), IDIO_16_REGMAP_IRQ(4), IDIO_16_REGMAP_IRQ(5), /* 3-5 */ + IDIO_16_REGMAP_IRQ(6), IDIO_16_REGMAP_IRQ(7), IDIO_16_REGMAP_IRQ(8), /* 6-8 */ + IDIO_16_REGMAP_IRQ(9), IDIO_16_REGMAP_IRQ(10), IDIO_16_REGMAP_IRQ(11), /* 9-11 */ + IDIO_16_REGMAP_IRQ(12), IDIO_16_REGMAP_IRQ(13), IDIO_16_REGMAP_IRQ(14), /* 12-14 */ + IDIO_16_REGMAP_IRQ(15), /* 15 */ +}; static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct device *const dev = &pdev->dev; - struct idio_16_gpio *idio16gpio; int err; const size_t pci_bar_index = 2; const char *const name = pci_name(pdev); - struct gpio_irq_chip *girq; - - idio16gpio = devm_kzalloc(dev, sizeof(*idio16gpio), GFP_KERNEL); - if (!idio16gpio) - return -ENOMEM; + struct idio_16_regmap_config config = {}; + void __iomem *regs; + struct regmap *map; err = pcim_enable_device(pdev); if (err) { @@ -226,53 +87,20 @@ static int idio_16_probe(struct pci_dev *pdev, const struct pci_device_id *id) return err; } - idio16gpio->reg = pcim_iomap_table(pdev)[pci_bar_index]; + regs = pcim_iomap_table(pdev)[pci_bar_index]; - /* Deactivate input filters */ - iowrite8(0, &idio16gpio->reg->filter_ctl); + map = devm_regmap_init_mmio(dev, regs, &idio_16_regmap_config); + if (IS_ERR(map)) + return dev_err_probe(dev, PTR_ERR(map), "Unable to initialize register map\n"); - idio16gpio->chip.label = name; - idio16gpio->chip.parent = dev; - idio16gpio->chip.owner = THIS_MODULE; - idio16gpio->chip.base = -1; - idio16gpio->chip.ngpio = IDIO_16_NGPIO; - idio16gpio->chip.names = idio_16_names; - idio16gpio->chip.get_direction = idio_16_gpio_get_direction; - idio16gpio->chip.direction_input = idio_16_gpio_direction_input; - idio16gpio->chip.direction_output = idio_16_gpio_direction_output; - idio16gpio->chip.get = idio_16_gpio_get; - idio16gpio->chip.get_multiple = idio_16_gpio_get_multiple; - idio16gpio->chip.set = idio_16_gpio_set; - idio16gpio->chip.set_multiple = idio_16_gpio_set_multiple; - - idio_16_state_init(&idio16gpio->state); - - girq = &idio16gpio->chip.irq; - gpio_irq_chip_set_chip(girq, &idio_16_irqchip); - /* This will let us handle the parent IRQ in the driver */ - girq->parent_handler = NULL; - girq->num_parents = 0; - girq->parents = NULL; - girq->default_type = IRQ_TYPE_NONE; - girq->handler = handle_edge_irq; - girq->init_hw = idio_16_irq_init_hw; - - raw_spin_lock_init(&idio16gpio->lock); - - err = devm_gpiochip_add_data(dev, &idio16gpio->chip, idio16gpio); - if (err) { - dev_err(dev, "GPIO registering failed (%d)\n", err); - return err; - } - - err = devm_request_irq(dev, pdev->irq, idio_16_irq_handler, IRQF_SHARED, - name, idio16gpio); - if (err) { - dev_err(dev, "IRQ handler registering failed (%d)\n", err); - return err; - } + config.parent = dev; + config.map = map; + config.regmap_irqs = idio_16_regmap_irqs; + config.num_regmap_irqs = ARRAY_SIZE(idio_16_regmap_irqs); + config.irq = pdev->irq; + config.filters = true; - return 0; + return devm_idio_16_regmap_register(dev, &config); } static const struct pci_device_id idio_16_pci_dev_id[] = { diff --git a/drivers/gpio/gpio-pcie-idio-24.c b/drivers/gpio/gpio-pcie-idio-24.c index 463c0613abb9..2efd1b1a0805 100644 --- a/drivers/gpio/gpio-pcie-idio-24.c +++ b/drivers/gpio/gpio-pcie-idio-24.c @@ -6,16 +6,15 @@ * This driver supports the following ACCES devices: PCIe-IDIO-24, * PCIe-IDI-24, PCIe-IDO-24, and PCIe-IDIO-12. */ -#include <linux/bitmap.h> -#include <linux/bitops.h> +#include <linux/bits.h> #include <linux/device.h> -#include <linux/errno.h> -#include <linux/gpio/driver.h> -#include <linux/interrupt.h> -#include <linux/irqdesc.h> +#include <linux/err.h> +#include <linux/gpio/regmap.h> +#include <linux/irq.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/pci.h> +#include <linux/regmap.h> #include <linux/spinlock.h> #include <linux/types.h> @@ -59,422 +58,224 @@ #define PLX_PEX8311_PCI_LCS_INTCSR 0x68 #define INTCSR_INTERNAL_PCI_WIRE BIT(8) #define INTCSR_LOCAL_INPUT BIT(11) +#define IDIO_24_ENABLE_IRQ (INTCSR_INTERNAL_PCI_WIRE | INTCSR_LOCAL_INPUT) + +#define IDIO_24_OUT_BASE 0x0 +#define IDIO_24_TTLCMOS_OUT_REG 0x3 +#define IDIO_24_IN_BASE 0x4 +#define IDIO_24_TTLCMOS_IN_REG 0x7 +#define IDIO_24_COS_STATUS_BASE 0x8 +#define IDIO_24_CONTROL_REG 0xC +#define IDIO_24_COS_ENABLE 0xE +#define IDIO_24_SOFT_RESET 0xF + +#define CONTROL_REG_OUT_MODE BIT(1) + +#define COS_ENABLE_RISING BIT(1) +#define COS_ENABLE_FALLING BIT(4) +#define COS_ENABLE_BOTH (COS_ENABLE_RISING | COS_ENABLE_FALLING) + +static const struct regmap_config pex8311_intcsr_regmap_config = { + .name = "pex8311_intcsr", + .reg_bits = 32, + .reg_stride = 1, + .reg_base = PLX_PEX8311_PCI_LCS_INTCSR, + .val_bits = 32, + .io_port = true, +}; -/** - * struct idio_24_gpio_reg - GPIO device registers structure - * @out0_7: Read: FET Outputs 0-7 - * Write: FET Outputs 0-7 - * @out8_15: Read: FET Outputs 8-15 - * Write: FET Outputs 8-15 - * @out16_23: Read: FET Outputs 16-23 - * Write: FET Outputs 16-23 - * @ttl_out0_7: Read: TTL/CMOS Outputs 0-7 - * Write: TTL/CMOS Outputs 0-7 - * @in0_7: Read: Isolated Inputs 0-7 - * Write: Reserved - * @in8_15: Read: Isolated Inputs 8-15 - * Write: Reserved - * @in16_23: Read: Isolated Inputs 16-23 - * Write: Reserved - * @ttl_in0_7: Read: TTL/CMOS Inputs 0-7 - * Write: Reserved - * @cos0_7: Read: COS Status Inputs 0-7 - * Write: COS Clear Inputs 0-7 - * @cos8_15: Read: COS Status Inputs 8-15 - * Write: COS Clear Inputs 8-15 - * @cos16_23: Read: COS Status Inputs 16-23 - * Write: COS Clear Inputs 16-23 - * @cos_ttl0_7: Read: COS Status TTL/CMOS 0-7 - * Write: COS Clear TTL/CMOS 0-7 - * @ctl: Read: Control Register - * Write: Control Register - * @reserved: Read: Reserved - * Write: Reserved - * @cos_enable: Read: COS Enable - * Write: COS Enable - * @soft_reset: Read: IRQ Output Pin Status - * Write: Software Board Reset - */ -struct idio_24_gpio_reg { - u8 out0_7; - u8 out8_15; - u8 out16_23; - u8 ttl_out0_7; - u8 in0_7; - u8 in8_15; - u8 in16_23; - u8 ttl_in0_7; - u8 cos0_7; - u8 cos8_15; - u8 cos16_23; - u8 cos_ttl0_7; - u8 ctl; - u8 reserved; - u8 cos_enable; - u8 soft_reset; +static const struct regmap_range idio_24_wr_ranges[] = { + regmap_reg_range(0x0, 0x3), regmap_reg_range(0x8, 0xC), + regmap_reg_range(0xE, 0xF), +}; +static const struct regmap_range idio_24_rd_ranges[] = { + regmap_reg_range(0x0, 0xC), regmap_reg_range(0xE, 0xF), +}; +static const struct regmap_range idio_24_volatile_ranges[] = { + regmap_reg_range(0x4, 0xB), regmap_reg_range(0xF, 0xF), +}; +static const struct regmap_access_table idio_24_wr_table = { + .yes_ranges = idio_24_wr_ranges, + .n_yes_ranges = ARRAY_SIZE(idio_24_wr_ranges), +}; +static const struct regmap_access_table idio_24_rd_table = { + .yes_ranges = idio_24_rd_ranges, + .n_yes_ranges = ARRAY_SIZE(idio_24_rd_ranges), +}; +static const struct regmap_access_table idio_24_volatile_table = { + .yes_ranges = idio_24_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(idio_24_volatile_ranges), +}; + +static const struct regmap_config idio_24_regmap_config = { + .reg_bits = 8, + .reg_stride = 1, + .val_bits = 8, + .io_port = true, + .wr_table = &idio_24_wr_table, + .rd_table = &idio_24_rd_table, + .volatile_table = &idio_24_volatile_table, + .cache_type = REGCACHE_FLAT, + .use_raw_spinlock = true, +}; + +#define IDIO_24_NGPIO_PER_REG 8 +#define IDIO_24_REGMAP_IRQ(_id) \ + [24 + _id] = { \ + .reg_offset = (_id) / IDIO_24_NGPIO_PER_REG, \ + .mask = BIT((_id) % IDIO_24_NGPIO_PER_REG), \ + .type = { .types_supported = IRQ_TYPE_EDGE_BOTH }, \ + } +#define IDIO_24_IIN_IRQ(_id) IDIO_24_REGMAP_IRQ(_id) +#define IDIO_24_TTL_IRQ(_id) IDIO_24_REGMAP_IRQ(24 + _id) + +static const struct regmap_irq idio_24_regmap_irqs[] = { + IDIO_24_IIN_IRQ(0), IDIO_24_IIN_IRQ(1), IDIO_24_IIN_IRQ(2), /* IIN 0-2 */ + IDIO_24_IIN_IRQ(3), IDIO_24_IIN_IRQ(4), IDIO_24_IIN_IRQ(5), /* IIN 3-5 */ + IDIO_24_IIN_IRQ(6), IDIO_24_IIN_IRQ(7), IDIO_24_IIN_IRQ(8), /* IIN 6-8 */ + IDIO_24_IIN_IRQ(9), IDIO_24_IIN_IRQ(10), IDIO_24_IIN_IRQ(11), /* IIN 9-11 */ + IDIO_24_IIN_IRQ(12), IDIO_24_IIN_IRQ(13), IDIO_24_IIN_IRQ(14), /* IIN 12-14 */ + IDIO_24_IIN_IRQ(15), IDIO_24_IIN_IRQ(16), IDIO_24_IIN_IRQ(17), /* IIN 15-17 */ + IDIO_24_IIN_IRQ(18), IDIO_24_IIN_IRQ(19), IDIO_24_IIN_IRQ(20), /* IIN 18-20 */ + IDIO_24_IIN_IRQ(21), IDIO_24_IIN_IRQ(22), IDIO_24_IIN_IRQ(23), /* IIN 21-23 */ + IDIO_24_TTL_IRQ(0), IDIO_24_TTL_IRQ(1), IDIO_24_TTL_IRQ(2), /* TTL 0-2 */ + IDIO_24_TTL_IRQ(3), IDIO_24_TTL_IRQ(4), IDIO_24_TTL_IRQ(5), /* TTL 3-5 */ + IDIO_24_TTL_IRQ(6), IDIO_24_TTL_IRQ(7), /* TTL 6-7 */ }; /** * struct idio_24_gpio - GPIO device private data structure - * @chip: instance of the gpio_chip + * @map: regmap for the device * @lock: synchronization lock to prevent I/O race conditions - * @reg: I/O address offset for the GPIO device registers - * @irq_mask: I/O bits affected by interrupts + * @irq_type: type configuration for IRQs */ struct idio_24_gpio { - struct gpio_chip chip; + struct regmap *map; raw_spinlock_t lock; - __u8 __iomem *plx; - struct idio_24_gpio_reg __iomem *reg; - unsigned long irq_mask; + u8 irq_type; }; -static int idio_24_gpio_get_direction(struct gpio_chip *chip, - unsigned int offset) -{ - struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); - const unsigned long out_mode_mask = BIT(1); - - /* FET Outputs */ - if (offset < 24) - return GPIO_LINE_DIRECTION_OUT; - - /* Isolated Inputs */ - if (offset < 48) - return GPIO_LINE_DIRECTION_IN; - - /* TTL/CMOS I/O */ - /* OUT MODE = 1 when TTL/CMOS Output Mode is set */ - if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask) - return GPIO_LINE_DIRECTION_OUT; - - return GPIO_LINE_DIRECTION_IN; -} - -static int idio_24_gpio_direction_input(struct gpio_chip *chip, - unsigned int offset) -{ - struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); - unsigned long flags; - unsigned int ctl_state; - const unsigned long out_mode_mask = BIT(1); - - /* TTL/CMOS I/O */ - if (offset > 47) { - raw_spin_lock_irqsave(&idio24gpio->lock, flags); - - /* Clear TTL/CMOS Output Mode */ - ctl_state = ioread8(&idio24gpio->reg->ctl) & ~out_mode_mask; - iowrite8(ctl_state, &idio24gpio->reg->ctl); - - raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); - } - - return 0; -} - -static int idio_24_gpio_direction_output(struct gpio_chip *chip, - unsigned int offset, int value) -{ - struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); - unsigned long flags; - unsigned int ctl_state; - const unsigned long out_mode_mask = BIT(1); - - /* TTL/CMOS I/O */ - if (offset > 47) { - raw_spin_lock_irqsave(&idio24gpio->lock, flags); - - /* Set TTL/CMOS Output Mode */ - ctl_state = ioread8(&idio24gpio->reg->ctl) | out_mode_mask; - iowrite8(ctl_state, &idio24gpio->reg->ctl); - - raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); - } - - chip->set(chip, offset, value); - return 0; -} - -static int idio_24_gpio_get(struct gpio_chip *chip, unsigned int offset) +static int idio_24_handle_mask_sync(const int index, const unsigned int mask_buf_def, + const unsigned int mask_buf, void *const irq_drv_data) { - struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); - const unsigned long offset_mask = BIT(offset % 8); - const unsigned long out_mode_mask = BIT(1); - - /* FET Outputs */ - if (offset < 8) - return !!(ioread8(&idio24gpio->reg->out0_7) & offset_mask); + const unsigned int type_mask = COS_ENABLE_BOTH << index; + struct idio_24_gpio *const idio24gpio = irq_drv_data; + u8 type; + int ret; - if (offset < 16) - return !!(ioread8(&idio24gpio->reg->out8_15) & offset_mask); - - if (offset < 24) - return !!(ioread8(&idio24gpio->reg->out16_23) & offset_mask); - - /* Isolated Inputs */ - if (offset < 32) - return !!(ioread8(&idio24gpio->reg->in0_7) & offset_mask); - - if (offset < 40) - return !!(ioread8(&idio24gpio->reg->in8_15) & offset_mask); - - if (offset < 48) - return !!(ioread8(&idio24gpio->reg->in16_23) & offset_mask); + raw_spin_lock(&idio24gpio->lock); - /* TTL/CMOS Outputs */ - if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask) - return !!(ioread8(&idio24gpio->reg->ttl_out0_7) & offset_mask); + /* if all are masked, then disable interrupts, else set to type */ + type = (mask_buf == mask_buf_def) ? ~type_mask : idio24gpio->irq_type; - /* TTL/CMOS Inputs */ - return !!(ioread8(&idio24gpio->reg->ttl_in0_7) & offset_mask); -} + ret = regmap_update_bits(idio24gpio->map, IDIO_24_COS_ENABLE, type_mask, type); -static int idio_24_gpio_get_multiple(struct gpio_chip *chip, - unsigned long *mask, unsigned long *bits) -{ - struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); - unsigned long offset; - unsigned long gpio_mask; - void __iomem *ports[] = { - &idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15, - &idio24gpio->reg->out16_23, &idio24gpio->reg->in0_7, - &idio24gpio->reg->in8_15, &idio24gpio->reg->in16_23, - }; - size_t index; - unsigned long port_state; - const unsigned long out_mode_mask = BIT(1); - - /* clear bits array to a clean slate */ - bitmap_zero(bits, chip->ngpio); - - for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) { - index = offset / 8; - - /* read bits from current gpio port (port 6 is TTL GPIO) */ - if (index < 6) - port_state = ioread8(ports[index]); - else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask) - port_state = ioread8(&idio24gpio->reg->ttl_out0_7); - else - port_state = ioread8(&idio24gpio->reg->ttl_in0_7); - - port_state &= gpio_mask; - - bitmap_set_value8(bits, port_state, offset); - } + raw_spin_unlock(&idio24gpio->lock); - return 0; + return ret; } -static void idio_24_gpio_set(struct gpio_chip *chip, unsigned int offset, - int value) +static int idio_24_set_type_config(unsigned int **const buf, const unsigned int type, + const struct regmap_irq *const irq_data, const int idx, + void *const irq_drv_data) { - struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); - const unsigned long out_mode_mask = BIT(1); - void __iomem *base; - const unsigned int mask = BIT(offset % 8); - unsigned long flags; - unsigned int out_state; - - /* Isolated Inputs */ - if (offset > 23 && offset < 48) - return; - - /* TTL/CMOS Inputs */ - if (offset > 47 && !(ioread8(&idio24gpio->reg->ctl) & out_mode_mask)) - return; - - /* TTL/CMOS Outputs */ - if (offset > 47) - base = &idio24gpio->reg->ttl_out0_7; - /* FET Outputs */ - else if (offset > 15) - base = &idio24gpio->reg->out16_23; - else if (offset > 7) - base = &idio24gpio->reg->out8_15; - else - base = &idio24gpio->reg->out0_7; - - raw_spin_lock_irqsave(&idio24gpio->lock, flags); - - if (value) - out_state = ioread8(base) | mask; - else - out_state = ioread8(base) & ~mask; - - iowrite8(out_state, base); - - raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); -} - -static void idio_24_gpio_set_multiple(struct gpio_chip *chip, - unsigned long *mask, unsigned long *bits) -{ - struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); - unsigned long offset; - unsigned long gpio_mask; - void __iomem *ports[] = { - &idio24gpio->reg->out0_7, &idio24gpio->reg->out8_15, - &idio24gpio->reg->out16_23 - }; - size_t index; - unsigned long bitmask; - unsigned long flags; - unsigned long out_state; - const unsigned long out_mode_mask = BIT(1); - - for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) { - index = offset / 8; - - bitmask = bitmap_get_value8(bits, offset) & gpio_mask; - - raw_spin_lock_irqsave(&idio24gpio->lock, flags); - - /* read bits from current gpio port (port 6 is TTL GPIO) */ - if (index < 6) { - out_state = ioread8(ports[index]); - } else if (ioread8(&idio24gpio->reg->ctl) & out_mode_mask) { - out_state = ioread8(&idio24gpio->reg->ttl_out0_7); - } else { - /* skip TTL GPIO if set for input */ - raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); - continue; - } - - /* set requested bit states */ - out_state &= ~gpio_mask; - out_state |= bitmask; - - /* write bits for current gpio port (port 6 is TTL GPIO) */ - if (index < 6) - iowrite8(out_state, ports[index]); - else - iowrite8(out_state, &idio24gpio->reg->ttl_out0_7); - - raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); + const unsigned int offset = irq_data->reg_offset; + const unsigned int rising = COS_ENABLE_RISING << offset; + const unsigned int falling = COS_ENABLE_FALLING << offset; + const unsigned int mask = COS_ENABLE_BOTH << offset; + struct idio_24_gpio *const idio24gpio = irq_drv_data; + unsigned int new; + unsigned int cos_enable; + int ret; + + switch (type) { + case IRQ_TYPE_EDGE_RISING: + new = rising; + break; + case IRQ_TYPE_EDGE_FALLING: + new = falling; + break; + case IRQ_TYPE_EDGE_BOTH: + new = mask; + break; + default: + return -EINVAL; } -} - -static void idio_24_irq_ack(struct irq_data *data) -{ -} -static void idio_24_irq_mask(struct irq_data *data) -{ - struct gpio_chip *const chip = irq_data_get_irq_chip_data(data); - struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); - unsigned long flags; - const unsigned long bit_offset = irqd_to_hwirq(data) - 24; - unsigned char new_irq_mask; - const unsigned long bank_offset = bit_offset / 8; - unsigned char cos_enable_state; - - raw_spin_lock_irqsave(&idio24gpio->lock, flags); - - idio24gpio->irq_mask &= ~BIT(bit_offset); - new_irq_mask = idio24gpio->irq_mask >> bank_offset * 8; + raw_spin_lock(&idio24gpio->lock); - if (!new_irq_mask) { - cos_enable_state = ioread8(&idio24gpio->reg->cos_enable); + /* replace old bitmap with new bitmap */ + idio24gpio->irq_type = (idio24gpio->irq_type & ~mask) | (new & mask); - /* Disable Rising Edge detection */ - cos_enable_state &= ~BIT(bank_offset); - /* Disable Falling Edge detection */ - cos_enable_state &= ~BIT(bank_offset + 4); + ret = regmap_read(idio24gpio->map, IDIO_24_COS_ENABLE, &cos_enable); + if (ret) + goto exit_unlock; - iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable); + /* if COS is currently enabled then update the edge type */ + if (cos_enable & mask) { + ret = regmap_update_bits(idio24gpio->map, IDIO_24_COS_ENABLE, mask, + idio24gpio->irq_type); + if (ret) + goto exit_unlock; } - raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); +exit_unlock: + raw_spin_unlock(&idio24gpio->lock); - gpiochip_disable_irq(chip, irqd_to_hwirq(data)); + return ret; } -static void idio_24_irq_unmask(struct irq_data *data) +static int idio_24_reg_mask_xlate(struct gpio_regmap *const gpio, const unsigned int base, + const unsigned int offset, unsigned int *const reg, + unsigned int *const mask) { - struct gpio_chip *const chip = irq_data_get_irq_chip_data(data); - struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip); - unsigned long flags; - unsigned char prev_irq_mask; - const unsigned long bit_offset = irqd_to_hwirq(data) - 24; - const unsigned long bank_offset = bit_offset / 8; - unsigned char cos_enable_state; - - gpiochip_enable_irq(chip, irqd_to_hwirq(data)); - - raw_spin_lock_irqsave(&idio24gpio->lock, flags); + const unsigned int out_stride = offset / IDIO_24_NGPIO_PER_REG; + const unsigned int in_stride = (offset - 24) / IDIO_24_NGPIO_PER_REG; + struct regmap *const map = gpio_regmap_get_drvdata(gpio); + int err; + unsigned int ctrl_reg; - prev_irq_mask = idio24gpio->irq_mask >> bank_offset * 8; - idio24gpio->irq_mask |= BIT(bit_offset); + switch (base) { + case IDIO_24_OUT_BASE: + *mask = BIT(offset % IDIO_24_NGPIO_PER_REG); - if (!prev_irq_mask) { - cos_enable_state = ioread8(&idio24gpio->reg->cos_enable); + /* FET Outputs */ + if (offset < 24) { + *reg = IDIO_24_OUT_BASE + out_stride; + return 0; + } - /* Enable Rising Edge detection */ - cos_enable_state |= BIT(bank_offset); - /* Enable Falling Edge detection */ - cos_enable_state |= BIT(bank_offset + 4); + /* Isolated Inputs */ + if (offset < 48) { + *reg = IDIO_24_IN_BASE + in_stride; + return 0; + } - iowrite8(cos_enable_state, &idio24gpio->reg->cos_enable); - } + err = regmap_read(map, IDIO_24_CONTROL_REG, &ctrl_reg); + if (err) + return err; - raw_spin_unlock_irqrestore(&idio24gpio->lock, flags); -} + /* TTL/CMOS Outputs */ + if (ctrl_reg & CONTROL_REG_OUT_MODE) { + *reg = IDIO_24_TTLCMOS_OUT_REG; + return 0; + } -static int idio_24_irq_set_type(struct irq_data *data, unsigned int flow_type) -{ - /* The only valid irq types are none and both-edges */ - if (flow_type != IRQ_TYPE_NONE && - (flow_type & IRQ_TYPE_EDGE_BOTH) != IRQ_TYPE_EDGE_BOTH) + /* TTL/CMOS Inputs */ + *reg = IDIO_24_TTLCMOS_IN_REG; + return 0; + case IDIO_24_CONTROL_REG: + /* We can only set direction for TTL/CMOS lines */ + if (offset < 48) + return -EOPNOTSUPP; + + *reg = IDIO_24_CONTROL_REG; + *mask = CONTROL_REG_OUT_MODE; + return 0; + default: + /* Should never reach this path */ return -EINVAL; - - return 0; -} - -static const struct irq_chip idio_24_irqchip = { - .name = "pcie-idio-24", - .irq_ack = idio_24_irq_ack, - .irq_mask = idio_24_irq_mask, - .irq_unmask = idio_24_irq_unmask, - .irq_set_type = idio_24_irq_set_type, - .flags = IRQCHIP_IMMUTABLE, - GPIOCHIP_IRQ_RESOURCE_HELPERS, -}; - -static irqreturn_t idio_24_irq_handler(int irq, void *dev_id) -{ - struct idio_24_gpio *const idio24gpio = dev_id; - unsigned long irq_status; - struct gpio_chip *const chip = &idio24gpio->chip; - unsigned long irq_mask; - int gpio; - - raw_spin_lock(&idio24gpio->lock); - - /* Read Change-Of-State status */ - irq_status = ioread32(&idio24gpio->reg->cos0_7); - - raw_spin_unlock(&idio24gpio->lock); - - /* Make sure our device generated IRQ */ - if (!irq_status) - return IRQ_NONE; - - /* Handle only unmasked IRQ */ - irq_mask = idio24gpio->irq_mask & irq_status; - - for_each_set_bit(gpio, &irq_mask, chip->ngpio - 24) - generic_handle_domain_irq(chip->irq.domain, gpio + 24); - - raw_spin_lock(&idio24gpio->lock); - - /* Clear Change-Of-State status */ - iowrite32(irq_status, &idio24gpio->reg->cos0_7); - - raw_spin_unlock(&idio24gpio->lock); - - return IRQ_HANDLED; + } } #define IDIO_24_NGPIO 56 @@ -496,11 +297,12 @@ static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id) const size_t pci_plx_bar_index = 1; const size_t pci_bar_index = 2; const char *const name = pci_name(pdev); - struct gpio_irq_chip *girq; - - idio24gpio = devm_kzalloc(dev, sizeof(*idio24gpio), GFP_KERNEL); - if (!idio24gpio) - return -ENOMEM; + struct gpio_regmap_config gpio_config = {}; + void __iomem *pex8311_regs; + void __iomem *idio_24_regs; + struct regmap *intcsr_map; + struct regmap_irq_chip *chip; + struct regmap_irq_chip_data *chip_data; err = pcim_enable_device(pdev); if (err) { @@ -514,57 +316,72 @@ static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id) return err; } - idio24gpio->plx = pcim_iomap_table(pdev)[pci_plx_bar_index]; - idio24gpio->reg = pcim_iomap_table(pdev)[pci_bar_index]; - - idio24gpio->chip.label = name; - idio24gpio->chip.parent = dev; - idio24gpio->chip.owner = THIS_MODULE; - idio24gpio->chip.base = -1; - idio24gpio->chip.ngpio = IDIO_24_NGPIO; - idio24gpio->chip.names = idio_24_names; - idio24gpio->chip.get_direction = idio_24_gpio_get_direction; - idio24gpio->chip.direction_input = idio_24_gpio_direction_input; - idio24gpio->chip.direction_output = idio_24_gpio_direction_output; - idio24gpio->chip.get = idio_24_gpio_get; - idio24gpio->chip.get_multiple = idio_24_gpio_get_multiple; - idio24gpio->chip.set = idio_24_gpio_set; - idio24gpio->chip.set_multiple = idio_24_gpio_set_multiple; - - girq = &idio24gpio->chip.irq; - gpio_irq_chip_set_chip(girq, &idio_24_irqchip); - /* This will let us handle the parent IRQ in the driver */ - girq->parent_handler = NULL; - girq->num_parents = 0; - girq->parents = NULL; - girq->default_type = IRQ_TYPE_NONE; - girq->handler = handle_edge_irq; + pex8311_regs = pcim_iomap_table(pdev)[pci_plx_bar_index]; + idio_24_regs = pcim_iomap_table(pdev)[pci_bar_index]; + + intcsr_map = devm_regmap_init_mmio(dev, pex8311_regs, &pex8311_intcsr_regmap_config); + if (IS_ERR(intcsr_map)) + return dev_err_probe(dev, PTR_ERR(intcsr_map), + "Unable to initialize PEX8311 register map\n"); + + idio24gpio = devm_kzalloc(dev, sizeof(*idio24gpio), GFP_KERNEL); + if (!idio24gpio) + return -ENOMEM; + + idio24gpio->map = devm_regmap_init_mmio(dev, idio_24_regs, &idio_24_regmap_config); + if (IS_ERR(idio24gpio->map)) + return dev_err_probe(dev, PTR_ERR(idio24gpio->map), + "Unable to initialize register map\n"); raw_spin_lock_init(&idio24gpio->lock); + /* Initialize all IRQ type configuration to IRQ_TYPE_EDGE_BOTH */ + idio24gpio->irq_type = GENMASK(7, 0); + + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->name = name; + chip->status_base = IDIO_24_COS_STATUS_BASE; + chip->mask_base = IDIO_24_COS_ENABLE; + chip->ack_base = IDIO_24_COS_STATUS_BASE; + chip->num_regs = 4; + chip->irqs = idio_24_regmap_irqs; + chip->num_irqs = ARRAY_SIZE(idio_24_regmap_irqs); + chip->handle_mask_sync = idio_24_handle_mask_sync; + chip->set_type_config = idio_24_set_type_config; + chip->irq_drv_data = idio24gpio; + /* Software board reset */ - iowrite8(0, &idio24gpio->reg->soft_reset); + err = regmap_write(idio24gpio->map, IDIO_24_SOFT_RESET, 0); + if (err) + return err; /* * enable PLX PEX8311 internal PCI wire interrupt and local interrupt * input */ - iowrite8((INTCSR_INTERNAL_PCI_WIRE | INTCSR_LOCAL_INPUT) >> 8, - idio24gpio->plx + PLX_PEX8311_PCI_LCS_INTCSR + 1); - - err = devm_gpiochip_add_data(dev, &idio24gpio->chip, idio24gpio); - if (err) { - dev_err(dev, "GPIO registering failed (%d)\n", err); + err = regmap_update_bits(intcsr_map, 0x0, IDIO_24_ENABLE_IRQ, IDIO_24_ENABLE_IRQ); + if (err) return err; - } - - err = devm_request_irq(dev, pdev->irq, idio_24_irq_handler, IRQF_SHARED, - name, idio24gpio); - if (err) { - dev_err(dev, "IRQ handler registering failed (%d)\n", err); - return err; - } - return 0; + err = devm_regmap_add_irq_chip(dev, idio24gpio->map, pdev->irq, 0, 0, chip, &chip_data); + if (err) + return dev_err_probe(dev, err, "IRQ registration failed\n"); + + gpio_config.parent = dev; + gpio_config.regmap = idio24gpio->map; + gpio_config.ngpio = IDIO_24_NGPIO; + gpio_config.names = idio_24_names; + gpio_config.reg_dat_base = GPIO_REGMAP_ADDR(IDIO_24_OUT_BASE); + gpio_config.reg_set_base = GPIO_REGMAP_ADDR(IDIO_24_OUT_BASE); + gpio_config.reg_dir_out_base = GPIO_REGMAP_ADDR(IDIO_24_CONTROL_REG); + gpio_config.ngpio_per_reg = IDIO_24_NGPIO_PER_REG; + gpio_config.irq_domain = regmap_irq_get_domain(chip_data); + gpio_config.reg_mask_xlate = idio_24_reg_mask_xlate; + gpio_config.drvdata = idio24gpio->map; + + return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config)); } static const struct pci_device_id idio_24_pci_dev_id[] = { diff --git a/drivers/gpio/gpio-pisosr.c b/drivers/gpio/gpio-pisosr.c index 67071bea08c2..e3013e778e15 100644 --- a/drivers/gpio/gpio-pisosr.c +++ b/drivers/gpio/gpio-pisosr.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ - * Andrew F. Davis <afd@ti.com> + * Copyright (C) 2015-2023 Texas Instruments Incorporated - https://www.ti.com/ + * Andrew Davis <afd@ti.com> */ #include <linux/bitmap.h> @@ -116,6 +116,11 @@ static const struct gpio_chip template_chip = { .can_sleep = true, }; +static void pisosr_mutex_destroy(void *lock) +{ + mutex_destroy(lock); +} + static int pisosr_gpio_probe(struct spi_device *spi) { struct device *dev = &spi->dev; @@ -126,8 +131,6 @@ static int pisosr_gpio_probe(struct spi_device *spi) if (!gpio) return -ENOMEM; - spi_set_drvdata(spi, gpio); - gpio->chip = template_chip; gpio->chip.parent = dev; of_property_read_u16(dev->of_node, "ngpios", &gpio->chip.ngpio); @@ -145,8 +148,11 @@ static int pisosr_gpio_probe(struct spi_device *spi) "Unable to allocate load GPIO\n"); mutex_init(&gpio->lock); + ret = devm_add_action_or_reset(dev, pisosr_mutex_destroy, &gpio->lock); + if (ret) + return ret; - ret = gpiochip_add_data(&gpio->chip, gpio); + ret = devm_gpiochip_add_data(dev, &gpio->chip, gpio); if (ret < 0) { dev_err(dev, "Unable to register gpiochip\n"); return ret; @@ -155,15 +161,6 @@ static int pisosr_gpio_probe(struct spi_device *spi) return 0; } -static void pisosr_gpio_remove(struct spi_device *spi) -{ - struct pisosr_gpio *gpio = spi_get_drvdata(spi); - - gpiochip_remove(&gpio->chip); - - mutex_destroy(&gpio->lock); -} - static const struct spi_device_id pisosr_gpio_id_table[] = { { "pisosr-gpio", }, { /* sentinel */ } @@ -182,11 +179,10 @@ static struct spi_driver pisosr_gpio_driver = { .of_match_table = pisosr_gpio_of_match_table, }, .probe = pisosr_gpio_probe, - .remove = pisosr_gpio_remove, .id_table = pisosr_gpio_id_table, }; module_spi_driver(pisosr_gpio_driver); -MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); +MODULE_AUTHOR("Andrew Davis <afd@ti.com>"); MODULE_DESCRIPTION("SPI Compatible PISO Shift Register GPIO Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpio/gpio-pmic-eic-sprd.c b/drivers/gpio/gpio-pmic-eic-sprd.c index c3e4d90f6b18..2b9b7be9b8fd 100644 --- a/drivers/gpio/gpio-pmic-eic-sprd.c +++ b/drivers/gpio/gpio-pmic-eic-sprd.c @@ -8,7 +8,7 @@ #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/regmap.h> @@ -363,7 +363,6 @@ static int sprd_pmic_eic_probe(struct platform_device *pdev) return ret; } - platform_set_drvdata(pdev, pmic_eic); return 0; } diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index a1630ed4b741..7e9f7a32d3ee 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -20,7 +20,6 @@ #include <linux/irqchip/chained_irq.h> #include <linux/io.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> #include <linux/syscore_ops.h> diff --git a/drivers/gpio/gpio-raspberrypi-exp.c b/drivers/gpio/gpio-raspberrypi-exp.c index ecb0d3800dfe..9d1b95e429f1 100644 --- a/drivers/gpio/gpio-raspberrypi-exp.c +++ b/drivers/gpio/gpio-raspberrypi-exp.c @@ -234,7 +234,7 @@ static int rpi_exp_gpio_probe(struct platform_device *pdev) return devm_gpiochip_add_data(dev, &rpi_gpio->gc, rpi_gpio); } -static const struct of_device_id rpi_exp_gpio_ids[] __maybe_unused = { +static const struct of_device_id rpi_exp_gpio_ids[] = { { .compatible = "raspberrypi,firmware-gpio" }, { } }; @@ -243,7 +243,7 @@ MODULE_DEVICE_TABLE(of, rpi_exp_gpio_ids); static struct platform_driver rpi_exp_gpio_driver = { .driver = { .name = MODULE_NAME, - .of_match_table = of_match_ptr(rpi_exp_gpio_ids), + .of_match_table = rpi_exp_gpio_ids, }, .probe = rpi_exp_gpio_probe, }; diff --git a/drivers/gpio/gpio-rc5t583.c b/drivers/gpio/gpio-rc5t583.c index 4fae3ebea790..c34dcadaee36 100644 --- a/drivers/gpio/gpio-rc5t583.c +++ b/drivers/gpio/gpio-rc5t583.c @@ -121,8 +121,6 @@ static int rc5t583_gpio_probe(struct platform_device *pdev) if (pdata && pdata->gpio_base) rc5t583_gpio->gpio_chip.base = pdata->gpio_base; - platform_set_drvdata(pdev, rc5t583_gpio); - return devm_gpiochip_add_data(&pdev->dev, &rc5t583_gpio->gpio_chip, rc5t583_gpio); } diff --git a/drivers/gpio/gpio-rcar.c b/drivers/gpio/gpio-rcar.c index 2525adb52f4f..86e69cde04da 100644 --- a/drivers/gpio/gpio-rcar.c +++ b/drivers/gpio/gpio-rcar.c @@ -15,7 +15,6 @@ #include <linux/irq.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c index e5de15a2ab9a..b35b9604413f 100644 --- a/drivers/gpio/gpio-rockchip.c +++ b/drivers/gpio/gpio-rockchip.c @@ -17,10 +17,10 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/pinctrl/consumer.h> #include <linux/pinctrl/pinconf-generic.h> +#include <linux/platform_device.h> #include <linux/regmap.h> #include "../pinctrl/core.h" diff --git a/drivers/gpio/gpio-sama5d2-piobu.c b/drivers/gpio/gpio-sama5d2-piobu.c index 767c33ae3213..d89da7300ddd 100644 --- a/drivers/gpio/gpio-sama5d2-piobu.c +++ b/drivers/gpio/gpio-sama5d2-piobu.c @@ -189,7 +189,6 @@ static int sama5d2_piobu_probe(struct platform_device *pdev) if (!piobu) return -ENOMEM; - platform_set_drvdata(pdev, piobu); piobu->chip.label = pdev->name; piobu->chip.parent = &pdev->dev; piobu->chip.owner = THIS_MODULE, diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c index 8a83f7bf4382..e48392074e4b 100644 --- a/drivers/gpio/gpio-sch.c +++ b/drivers/gpio/gpio-sch.c @@ -380,8 +380,6 @@ static int sch_gpio_probe(struct platform_device *pdev) return -ENODEV; } - platform_set_drvdata(pdev, sch); - girq = &sch->chip.irq; gpio_irq_chip_set_chip(girq, &sch_irqchip); girq->num_parents = 0; diff --git a/drivers/gpio/gpio-sifive.c b/drivers/gpio/gpio-sifive.c index 745e5f67254e..8decd9b5d229 100644 --- a/drivers/gpio/gpio-sifive.c +++ b/drivers/gpio/gpio-sifive.c @@ -6,10 +6,10 @@ #include <linux/bitops.h> #include <linux/device.h> #include <linux/errno.h> -#include <linux/of_irq.h> #include <linux/gpio/driver.h> #include <linux/init.h> #include <linux/platform_device.h> +#include <linux/property.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/regmap.h> @@ -150,6 +150,7 @@ static const struct irq_chip sifive_gpio_irqchip = { .irq_disable = sifive_gpio_irq_disable, .irq_eoi = sifive_gpio_irq_eoi, .irq_set_affinity = sifive_gpio_irq_set_affinity, + .irq_set_wake = irq_chip_set_wake_parent, .flags = IRQCHIP_IMMUTABLE, GPIOCHIP_IRQ_RESOURCE_HELPERS, }; @@ -180,12 +181,10 @@ static const struct regmap_config sifive_gpio_regmap_config = { static int sifive_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct device_node *node = pdev->dev.of_node; - struct device_node *irq_parent; struct irq_domain *parent; struct gpio_irq_chip *girq; struct sifive_gpio *chip; - int ret, ngpio, i; + int ret, ngpio; chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); if (!chip) @@ -202,31 +201,22 @@ static int sifive_gpio_probe(struct platform_device *pdev) if (IS_ERR(chip->regs)) return PTR_ERR(chip->regs); - ngpio = of_irq_count(node); - if (ngpio > SIFIVE_GPIO_MAX) { - dev_err(dev, "Too many GPIO interrupts (max=%d)\n", - SIFIVE_GPIO_MAX); - return -ENXIO; - } - - irq_parent = of_irq_find_parent(node); - if (!irq_parent) { - dev_err(dev, "no IRQ parent node\n"); - return -ENODEV; + for (ngpio = 0; ngpio < SIFIVE_GPIO_MAX; ngpio++) { + ret = platform_get_irq_optional(pdev, ngpio); + if (ret < 0) + break; + chip->irq_number[ngpio] = ret; } - parent = irq_find_host(irq_parent); - of_node_put(irq_parent); - if (!parent) { - dev_err(dev, "no IRQ parent domain\n"); + if (!ngpio) { + dev_err(dev, "no IRQ found\n"); return -ENODEV; } - for (i = 0; i < ngpio; i++) { - ret = platform_get_irq(pdev, i); - if (ret < 0) - return ret; - chip->irq_number[i] = ret; - } + /* + * The check above ensures at least one parent IRQ is valid. + * Assume all parent IRQs belong to the same domain. + */ + parent = irq_get_irq_data(chip->irq_number[0])->domain; ret = bgpio_init(&chip->gc, dev, 4, chip->base + SIFIVE_GPIO_INPUT_VAL, @@ -254,7 +244,7 @@ static int sifive_gpio_probe(struct platform_device *pdev) chip->gc.owner = THIS_MODULE; girq = &chip->gc.irq; gpio_irq_chip_set_chip(girq, &sifive_gpio_irqchip); - girq->fwnode = of_node_to_fwnode(node); + girq->fwnode = dev_fwnode(dev); girq->parent_domain = parent; girq->child_to_parent_hwirq = sifive_gpio_child_to_parent_hwirq; girq->handler = handle_bad_irq; @@ -277,4 +267,8 @@ static struct platform_driver sifive_gpio_driver = { .of_match_table = sifive_gpio_match, }, }; -builtin_platform_driver(sifive_gpio_driver) +module_platform_driver(sifive_gpio_driver) + +MODULE_AUTHOR("Yash Shah <yash.shah@sifive.com>"); +MODULE_DESCRIPTION("SiFive GPIO driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpio/gpio-sim.c b/drivers/gpio/gpio-sim.c index f1f6f1c32987..271db3639a78 100644 --- a/drivers/gpio/gpio-sim.c +++ b/drivers/gpio/gpio-sim.c @@ -8,6 +8,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/bitmap.h> +#include <linux/cleanup.h> #include <linux/completion.h> #include <linux/configfs.h> #include <linux/device.h> @@ -68,7 +69,7 @@ static int gpio_sim_apply_pull(struct gpio_sim_chip *chip, gc = &chip->gc; desc = &gc->gpiodev->descs[offset]; - mutex_lock(&chip->lock); + guard(mutex)(&chip->lock); if (test_bit(FLAG_REQUESTED, &desc->flags) && !test_bit(FLAG_IS_OUT, &desc->flags)) { @@ -104,29 +105,24 @@ set_value: set_pull: __assign_bit(offset, chip->pull_map, value); - mutex_unlock(&chip->lock); return 0; } static int gpio_sim_get(struct gpio_chip *gc, unsigned int offset) { struct gpio_sim_chip *chip = gpiochip_get_data(gc); - int ret; - mutex_lock(&chip->lock); - ret = !!test_bit(offset, chip->value_map); - mutex_unlock(&chip->lock); + guard(mutex)(&chip->lock); - return ret; + return !!test_bit(offset, chip->value_map); } static void gpio_sim_set(struct gpio_chip *gc, unsigned int offset, int value) { struct gpio_sim_chip *chip = gpiochip_get_data(gc); - mutex_lock(&chip->lock); - __assign_bit(offset, chip->value_map, value); - mutex_unlock(&chip->lock); + scoped_guard(mutex, &chip->lock) + __assign_bit(offset, chip->value_map, value); } static int gpio_sim_get_multiple(struct gpio_chip *gc, @@ -134,9 +130,8 @@ static int gpio_sim_get_multiple(struct gpio_chip *gc, { struct gpio_sim_chip *chip = gpiochip_get_data(gc); - mutex_lock(&chip->lock); - bitmap_replace(bits, bits, chip->value_map, mask, gc->ngpio); - mutex_unlock(&chip->lock); + scoped_guard(mutex, &chip->lock) + bitmap_replace(bits, bits, chip->value_map, mask, gc->ngpio); return 0; } @@ -146,9 +141,9 @@ static void gpio_sim_set_multiple(struct gpio_chip *gc, { struct gpio_sim_chip *chip = gpiochip_get_data(gc); - mutex_lock(&chip->lock); - bitmap_replace(chip->value_map, chip->value_map, bits, mask, gc->ngpio); - mutex_unlock(&chip->lock); + scoped_guard(mutex, &chip->lock) + bitmap_replace(chip->value_map, chip->value_map, bits, mask, + gc->ngpio); } static int gpio_sim_direction_output(struct gpio_chip *gc, @@ -156,10 +151,10 @@ static int gpio_sim_direction_output(struct gpio_chip *gc, { struct gpio_sim_chip *chip = gpiochip_get_data(gc); - mutex_lock(&chip->lock); - __clear_bit(offset, chip->direction_map); - __assign_bit(offset, chip->value_map, value); - mutex_unlock(&chip->lock); + scoped_guard(mutex, &chip->lock) { + __clear_bit(offset, chip->direction_map); + __assign_bit(offset, chip->value_map, value); + } return 0; } @@ -168,9 +163,8 @@ static int gpio_sim_direction_input(struct gpio_chip *gc, unsigned int offset) { struct gpio_sim_chip *chip = gpiochip_get_data(gc); - mutex_lock(&chip->lock); - __set_bit(offset, chip->direction_map); - mutex_unlock(&chip->lock); + scoped_guard(mutex, &chip->lock) + __set_bit(offset, chip->direction_map); return 0; } @@ -180,9 +174,8 @@ static int gpio_sim_get_direction(struct gpio_chip *gc, unsigned int offset) struct gpio_sim_chip *chip = gpiochip_get_data(gc); int direction; - mutex_lock(&chip->lock); - direction = !!test_bit(offset, chip->direction_map); - mutex_unlock(&chip->lock); + scoped_guard(mutex, &chip->lock) + direction = !!test_bit(offset, chip->direction_map); return direction ? GPIO_LINE_DIRECTION_IN : GPIO_LINE_DIRECTION_OUT; } @@ -215,9 +208,9 @@ static void gpio_sim_free(struct gpio_chip *gc, unsigned int offset) { struct gpio_sim_chip *chip = gpiochip_get_data(gc); - mutex_lock(&chip->lock); - __assign_bit(offset, chip->value_map, !!test_bit(offset, chip->pull_map)); - mutex_unlock(&chip->lock); + scoped_guard(mutex, &chip->lock) + __assign_bit(offset, chip->value_map, + !!test_bit(offset, chip->pull_map)); } static ssize_t gpio_sim_sysfs_val_show(struct device *dev, @@ -227,9 +220,8 @@ static ssize_t gpio_sim_sysfs_val_show(struct device *dev, struct gpio_sim_chip *chip = dev_get_drvdata(dev); int val; - mutex_lock(&chip->lock); - val = !!test_bit(line_attr->offset, chip->value_map); - mutex_unlock(&chip->lock); + scoped_guard(mutex, &chip->lock) + val = !!test_bit(line_attr->offset, chip->value_map); return sysfs_emit(buf, "%d\n", val); } @@ -258,9 +250,8 @@ static ssize_t gpio_sim_sysfs_pull_show(struct device *dev, struct gpio_sim_chip *chip = dev_get_drvdata(dev); int pull; - mutex_lock(&chip->lock); - pull = !!test_bit(line_attr->offset, chip->pull_map); - mutex_unlock(&chip->lock); + scoped_guard(mutex, &chip->lock) + pull = !!test_bit(line_attr->offset, chip->pull_map); return sysfs_emit(buf, "%s\n", gpio_sim_sysfs_pull_strings[pull]); } @@ -291,6 +282,15 @@ static void gpio_sim_mutex_destroy(void *data) mutex_destroy(lock); } +static void gpio_sim_dispose_mappings(void *data) +{ + struct gpio_sim_chip *chip = data; + unsigned int i; + + for (i = 0; i < chip->gc.ngpio; i++) + irq_dispose_mapping(irq_find_mapping(chip->irq_sim, i)); +} + static void gpio_sim_sysfs_remove(void *data) { struct gpio_sim_chip *chip = data; @@ -402,10 +402,14 @@ static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev) if (!chip->pull_map) return -ENOMEM; - chip->irq_sim = devm_irq_domain_create_sim(dev, NULL, num_lines); + chip->irq_sim = devm_irq_domain_create_sim(dev, swnode, num_lines); if (IS_ERR(chip->irq_sim)) return PTR_ERR(chip->irq_sim); + ret = devm_add_action_or_reset(dev, gpio_sim_dispose_mappings, chip); + if (ret) + return ret; + mutex_init(&chip->lock); ret = devm_add_action_or_reset(dev, gpio_sim_mutex_destroy, &chip->lock); @@ -489,7 +493,7 @@ struct gpio_sim_device { * This structure however can be modified by callbacks of different * attributes so we need another lock. * - * We use this lock fo protecting all data structures owned by this + * We use this lock for protecting all data structures owned by this * object too. */ struct mutex lock; @@ -643,16 +647,13 @@ static bool gpio_sim_device_is_live_unlocked(struct gpio_sim_device *dev) static char *gpio_sim_strdup_trimmed(const char *str, size_t count) { - char *dup, *trimmed; + char *trimmed; - dup = kstrndup(str, count, GFP_KERNEL); - if (!dup) + trimmed = kstrndup(skip_spaces(str), count, GFP_KERNEL); + if (!trimmed) return NULL; - trimmed = strstrip(dup); - memmove(dup, trimmed, strlen(trimmed) + 1); - - return dup; + return strim(trimmed); } static ssize_t gpio_sim_device_config_dev_name_show(struct config_item *item, @@ -660,17 +661,14 @@ static ssize_t gpio_sim_device_config_dev_name_show(struct config_item *item, { struct gpio_sim_device *dev = to_gpio_sim_device(item); struct platform_device *pdev; - int ret; - mutex_lock(&dev->lock); + guard(mutex)(&dev->lock); + pdev = dev->pdev; if (pdev) - ret = sprintf(page, "%s\n", dev_name(&pdev->dev)); - else - ret = sprintf(page, "gpio-sim.%d\n", dev->id); - mutex_unlock(&dev->lock); + return sprintf(page, "%s\n", dev_name(&pdev->dev)); - return ret; + return sprintf(page, "gpio-sim.%d\n", dev->id); } CONFIGFS_ATTR_RO(gpio_sim_device_config_, dev_name); @@ -681,9 +679,8 @@ gpio_sim_device_config_live_show(struct config_item *item, char *page) struct gpio_sim_device *dev = to_gpio_sim_device(item); bool live; - mutex_lock(&dev->lock); - live = gpio_sim_device_is_live_unlocked(dev); - mutex_unlock(&dev->lock); + scoped_guard(mutex, &dev->lock) + live = gpio_sim_device_is_live_unlocked(dev); return sprintf(page, "%c\n", live ? '1' : '0'); } @@ -838,8 +835,7 @@ gpio_sim_make_bank_swnode(struct gpio_sim_bank *bank, { struct property_entry properties[GPIO_SIM_PROP_MAX]; unsigned int prop_idx = 0, line_names_size = 0; - struct fwnode_handle *swnode; - char **line_names; + char **line_names __free(kfree) = NULL; memset(properties, 0, sizeof(properties)); @@ -858,9 +854,7 @@ gpio_sim_make_bank_swnode(struct gpio_sim_bank *bank, "gpio-line-names", line_names, line_names_size); - swnode = fwnode_create_software_node(properties, parent); - kfree(line_names); - return swnode; + return fwnode_create_software_node(properties, parent); } static void gpio_sim_remove_swnode_recursive(struct fwnode_handle *swnode) @@ -985,18 +979,15 @@ gpio_sim_device_config_live_store(struct config_item *item, if (ret) return ret; - mutex_lock(&dev->lock); + guard(mutex)(&dev->lock); - if ((!live && !gpio_sim_device_is_live_unlocked(dev)) || - (live && gpio_sim_device_is_live_unlocked(dev))) + if (live == gpio_sim_device_is_live_unlocked(dev)) ret = -EPERM; else if (live) ret = gpio_sim_device_activate_unlocked(dev); else gpio_sim_device_deactivate_unlocked(dev); - mutex_unlock(&dev->lock); - return ret ?: count; } @@ -1033,17 +1024,14 @@ static ssize_t gpio_sim_bank_config_chip_name_show(struct config_item *item, struct gpio_sim_bank *bank = to_gpio_sim_bank(item); struct gpio_sim_device *dev = gpio_sim_bank_get_device(bank); struct gpio_sim_chip_name_ctx ctx = { bank->swnode, page }; - int ret; - mutex_lock(&dev->lock); + guard(mutex)(&dev->lock); + if (gpio_sim_device_is_live_unlocked(dev)) - ret = device_for_each_child(&dev->pdev->dev, &ctx, - gpio_sim_emit_chip_name); - else - ret = sprintf(page, "none\n"); - mutex_unlock(&dev->lock); + return device_for_each_child(&dev->pdev->dev, &ctx, + gpio_sim_emit_chip_name); - return ret; + return sprintf(page, "none\n"); } CONFIGFS_ATTR_RO(gpio_sim_bank_config_, chip_name); @@ -1053,13 +1041,10 @@ gpio_sim_bank_config_label_show(struct config_item *item, char *page) { struct gpio_sim_bank *bank = to_gpio_sim_bank(item); struct gpio_sim_device *dev = gpio_sim_bank_get_device(bank); - int ret; - mutex_lock(&dev->lock); - ret = sprintf(page, "%s\n", bank->label ?: ""); - mutex_unlock(&dev->lock); + guard(mutex)(&dev->lock); - return ret; + return sprintf(page, "%s\n", bank->label ?: ""); } static ssize_t gpio_sim_bank_config_label_store(struct config_item *item, @@ -1069,23 +1054,18 @@ static ssize_t gpio_sim_bank_config_label_store(struct config_item *item, struct gpio_sim_device *dev = gpio_sim_bank_get_device(bank); char *trimmed; - mutex_lock(&dev->lock); + guard(mutex)(&dev->lock); - if (gpio_sim_device_is_live_unlocked(dev)) { - mutex_unlock(&dev->lock); + if (gpio_sim_device_is_live_unlocked(dev)) return -EBUSY; - } trimmed = gpio_sim_strdup_trimmed(page, count); - if (!trimmed) { - mutex_unlock(&dev->lock); + if (!trimmed) return -ENOMEM; - } kfree(bank->label); bank->label = trimmed; - mutex_unlock(&dev->lock); return count; } @@ -1096,13 +1076,10 @@ gpio_sim_bank_config_num_lines_show(struct config_item *item, char *page) { struct gpio_sim_bank *bank = to_gpio_sim_bank(item); struct gpio_sim_device *dev = gpio_sim_bank_get_device(bank); - int ret; - mutex_lock(&dev->lock); - ret = sprintf(page, "%u\n", bank->num_lines); - mutex_unlock(&dev->lock); + guard(mutex)(&dev->lock); - return ret; + return sprintf(page, "%u\n", bank->num_lines); } static ssize_t @@ -1121,16 +1098,13 @@ gpio_sim_bank_config_num_lines_store(struct config_item *item, if (num_lines == 0) return -EINVAL; - mutex_lock(&dev->lock); + guard(mutex)(&dev->lock); - if (gpio_sim_device_is_live_unlocked(dev)) { - mutex_unlock(&dev->lock); + if (gpio_sim_device_is_live_unlocked(dev)) return -EBUSY; - } bank->num_lines = num_lines; - mutex_unlock(&dev->lock); return count; } @@ -1148,13 +1122,10 @@ gpio_sim_line_config_name_show(struct config_item *item, char *page) { struct gpio_sim_line *line = to_gpio_sim_line(item); struct gpio_sim_device *dev = gpio_sim_line_get_device(line); - int ret; - mutex_lock(&dev->lock); - ret = sprintf(page, "%s\n", line->name ?: ""); - mutex_unlock(&dev->lock); + guard(mutex)(&dev->lock); - return ret; + return sprintf(page, "%s\n", line->name ?: ""); } static ssize_t gpio_sim_line_config_name_store(struct config_item *item, @@ -1164,24 +1135,18 @@ static ssize_t gpio_sim_line_config_name_store(struct config_item *item, struct gpio_sim_device *dev = gpio_sim_line_get_device(line); char *trimmed; - mutex_lock(&dev->lock); + guard(mutex)(&dev->lock); - if (gpio_sim_device_is_live_unlocked(dev)) { - mutex_unlock(&dev->lock); + if (gpio_sim_device_is_live_unlocked(dev)) return -EBUSY; - } trimmed = gpio_sim_strdup_trimmed(page, count); - if (!trimmed) { - mutex_unlock(&dev->lock); + if (!trimmed) return -ENOMEM; - } kfree(line->name); line->name = trimmed; - mutex_unlock(&dev->lock); - return count; } @@ -1197,13 +1162,10 @@ static ssize_t gpio_sim_hog_config_name_show(struct config_item *item, { struct gpio_sim_hog *hog = to_gpio_sim_hog(item); struct gpio_sim_device *dev = gpio_sim_hog_get_device(hog); - int ret; - mutex_lock(&dev->lock); - ret = sprintf(page, "%s\n", hog->name ?: ""); - mutex_unlock(&dev->lock); + guard(mutex)(&dev->lock); - return ret; + return sprintf(page, "%s\n", hog->name ?: ""); } static ssize_t gpio_sim_hog_config_name_store(struct config_item *item, @@ -1213,24 +1175,18 @@ static ssize_t gpio_sim_hog_config_name_store(struct config_item *item, struct gpio_sim_device *dev = gpio_sim_hog_get_device(hog); char *trimmed; - mutex_lock(&dev->lock); + guard(mutex)(&dev->lock); - if (gpio_sim_device_is_live_unlocked(dev)) { - mutex_unlock(&dev->lock); + if (gpio_sim_device_is_live_unlocked(dev)) return -EBUSY; - } trimmed = gpio_sim_strdup_trimmed(page, count); - if (!trimmed) { - mutex_unlock(&dev->lock); + if (!trimmed) return -ENOMEM; - } kfree(hog->name); hog->name = trimmed; - mutex_unlock(&dev->lock); - return count; } @@ -1244,9 +1200,8 @@ static ssize_t gpio_sim_hog_config_direction_show(struct config_item *item, char *repr; int dir; - mutex_lock(&dev->lock); - dir = hog->dir; - mutex_unlock(&dev->lock); + scoped_guard(mutex, &dev->lock) + dir = hog->dir; switch (dir) { case GPIOD_IN: @@ -1273,42 +1228,24 @@ gpio_sim_hog_config_direction_store(struct config_item *item, { struct gpio_sim_hog *hog = to_gpio_sim_hog(item); struct gpio_sim_device *dev = gpio_sim_hog_get_device(hog); - char *trimmed; int dir; - mutex_lock(&dev->lock); + guard(mutex)(&dev->lock); - if (gpio_sim_device_is_live_unlocked(dev)) { - mutex_unlock(&dev->lock); + if (gpio_sim_device_is_live_unlocked(dev)) return -EBUSY; - } - - trimmed = gpio_sim_strdup_trimmed(page, count); - if (!trimmed) { - mutex_unlock(&dev->lock); - return -ENOMEM; - } - if (strcmp(trimmed, "input") == 0) + if (sysfs_streq(page, "input")) dir = GPIOD_IN; - else if (strcmp(trimmed, "output-high") == 0) + else if (sysfs_streq(page, "output-high")) dir = GPIOD_OUT_HIGH; - else if (strcmp(trimmed, "output-low") == 0) + else if (sysfs_streq(page, "output-low")) dir = GPIOD_OUT_LOW; else - dir = -EINVAL; - - kfree(trimmed); - - if (dir < 0) { - mutex_unlock(&dev->lock); - return dir; - } + return -EINVAL; hog->dir = dir; - mutex_unlock(&dev->lock); - return count; } @@ -1326,9 +1263,8 @@ static void gpio_sim_hog_config_item_release(struct config_item *item) struct gpio_sim_line *line = hog->parent; struct gpio_sim_device *dev = gpio_sim_hog_get_device(hog); - mutex_lock(&dev->lock); - line->hog = NULL; - mutex_unlock(&dev->lock); + scoped_guard(mutex, &dev->lock) + line->hog = NULL; kfree(hog->name); kfree(hog); @@ -1354,13 +1290,11 @@ gpio_sim_line_config_make_hog_item(struct config_group *group, const char *name) if (strcmp(name, "hog") != 0) return ERR_PTR(-EINVAL); - mutex_lock(&dev->lock); + guard(mutex)(&dev->lock); hog = kzalloc(sizeof(*hog), GFP_KERNEL); - if (!hog) { - mutex_unlock(&dev->lock); + if (!hog) return ERR_PTR(-ENOMEM); - } config_item_init_type_name(&hog->item, name, &gpio_sim_hog_config_type); @@ -1370,8 +1304,6 @@ gpio_sim_line_config_make_hog_item(struct config_group *group, const char *name) hog->parent = line; line->hog = hog; - mutex_unlock(&dev->lock); - return &hog->item; } @@ -1380,9 +1312,8 @@ static void gpio_sim_line_config_group_release(struct config_item *item) struct gpio_sim_line *line = to_gpio_sim_line(item); struct gpio_sim_device *dev = gpio_sim_line_get_device(line); - mutex_lock(&dev->lock); - list_del(&line->siblings); - mutex_unlock(&dev->lock); + scoped_guard(mutex, &dev->lock) + list_del(&line->siblings); kfree(line->name); kfree(line); @@ -1417,18 +1348,14 @@ gpio_sim_bank_config_make_line_group(struct config_group *group, if (ret != 1 || nchar != strlen(name)) return ERR_PTR(-EINVAL); - mutex_lock(&dev->lock); + guard(mutex)(&dev->lock); - if (gpio_sim_device_is_live_unlocked(dev)) { - mutex_unlock(&dev->lock); + if (gpio_sim_device_is_live_unlocked(dev)) return ERR_PTR(-EBUSY); - } line = kzalloc(sizeof(*line), GFP_KERNEL); - if (!line) { - mutex_unlock(&dev->lock); + if (!line) return ERR_PTR(-ENOMEM); - } config_group_init_type_name(&line->group, name, &gpio_sim_line_config_type); @@ -1437,8 +1364,6 @@ gpio_sim_bank_config_make_line_group(struct config_group *group, line->offset = offset; list_add_tail(&line->siblings, &bank->line_list); - mutex_unlock(&dev->lock); - return &line->group; } @@ -1447,9 +1372,8 @@ static void gpio_sim_bank_config_group_release(struct config_item *item) struct gpio_sim_bank *bank = to_gpio_sim_bank(item); struct gpio_sim_device *dev = gpio_sim_bank_get_device(bank); - mutex_lock(&dev->lock); - list_del(&bank->siblings); - mutex_unlock(&dev->lock); + scoped_guard(mutex, &dev->lock) + list_del(&bank->siblings); kfree(bank->label); kfree(bank); @@ -1477,18 +1401,14 @@ gpio_sim_device_config_make_bank_group(struct config_group *group, struct gpio_sim_device *dev = to_gpio_sim_device(&group->cg_item); struct gpio_sim_bank *bank; - mutex_lock(&dev->lock); + guard(mutex)(&dev->lock); - if (gpio_sim_device_is_live_unlocked(dev)) { - mutex_unlock(&dev->lock); + if (gpio_sim_device_is_live_unlocked(dev)) return ERR_PTR(-EBUSY); - } bank = kzalloc(sizeof(*bank), GFP_KERNEL); - if (!bank) { - mutex_unlock(&dev->lock); + if (!bank) return ERR_PTR(-ENOMEM); - } config_group_init_type_name(&bank->group, name, &gpio_sim_bank_config_group_type); @@ -1497,8 +1417,6 @@ gpio_sim_device_config_make_bank_group(struct config_group *group, INIT_LIST_HEAD(&bank->line_list); list_add_tail(&bank->siblings, &dev->bank_list); - mutex_unlock(&dev->lock); - return &bank->group; } @@ -1506,10 +1424,10 @@ static void gpio_sim_device_config_group_release(struct config_item *item) { struct gpio_sim_device *dev = to_gpio_sim_device(item); - mutex_lock(&dev->lock); - if (gpio_sim_device_is_live_unlocked(dev)) - gpio_sim_device_deactivate_unlocked(dev); - mutex_unlock(&dev->lock); + scoped_guard(mutex, &dev->lock) { + if (gpio_sim_device_is_live_unlocked(dev)) + gpio_sim_device_deactivate_unlocked(dev); + } mutex_destroy(&dev->lock); ida_free(&gpio_sim_ida, dev->id); @@ -1534,7 +1452,7 @@ static const struct config_item_type gpio_sim_device_config_group_type = { static struct config_group * gpio_sim_config_make_device_group(struct config_group *group, const char *name) { - struct gpio_sim_device *dev; + struct gpio_sim_device *dev __free(kfree) = NULL; int id; dev = kzalloc(sizeof(*dev), GFP_KERNEL); @@ -1542,10 +1460,8 @@ gpio_sim_config_make_device_group(struct config_group *group, const char *name) return ERR_PTR(-ENOMEM); id = ida_alloc(&gpio_sim_ida, GFP_KERNEL); - if (id < 0) { - kfree(dev); + if (id < 0) return ERR_PTR(id); - } config_group_init_type_name(&dev->group, name, &gpio_sim_device_config_group_type); @@ -1556,7 +1472,7 @@ gpio_sim_config_make_device_group(struct config_group *group, const char *name) dev->bus_notifier.notifier_call = gpio_sim_bus_notifier_call; init_completion(&dev->probe_completion); - return &dev->group; + return &no_free_ptr(dev)->group; } static struct configfs_group_operations gpio_sim_config_group_ops = { diff --git a/drivers/gpio/gpio-sprd.c b/drivers/gpio/gpio-sprd.c index 072b4e653216..c117c11bfb29 100644 --- a/drivers/gpio/gpio-sprd.c +++ b/drivers/gpio/gpio-sprd.c @@ -7,8 +7,8 @@ #include <linux/bitops.h> #include <linux/gpio/driver.h> #include <linux/kernel.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/spinlock.h> diff --git a/drivers/gpio/gpio-stp-xway.c b/drivers/gpio/gpio-stp-xway.c index 4750ea34204c..053d616f2e02 100644 --- a/drivers/gpio/gpio-stp-xway.c +++ b/drivers/gpio/gpio-stp-xway.c @@ -4,11 +4,12 @@ * Copyright (C) 2012 John Crispin <john@phrozen.org> */ +#include <linux/platform_device.h> #include <linux/slab.h> #include <linux/init.h> #include <linux/module.h> #include <linux/types.h> -#include <linux/of_platform.h> +#include <linux/of.h> #include <linux/mutex.h> #include <linux/gpio/driver.h> #include <linux/io.h> diff --git a/drivers/gpio/gpio-syscon.c b/drivers/gpio/gpio-syscon.c index 6076937b18e7..6e1a2581e6ae 100644 --- a/drivers/gpio/gpio-syscon.c +++ b/drivers/gpio/gpio-syscon.c @@ -9,7 +9,6 @@ #include <linux/gpio/driver.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/mfd/syscon.h> @@ -249,8 +248,6 @@ static int syscon_gpio_probe(struct platform_device *pdev) priv->chip.direction_output = syscon_gpio_dir_out; } - platform_set_drvdata(pdev, priv); - return devm_gpiochip_add_data(&pdev->dev, &priv->chip, priv); } diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 5b265a6fd3c1..ea715582bcf3 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -15,7 +15,7 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/gpio/driver.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/module.h> #include <linux/seq_file.h> diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c index 80d08ddde40e..d87dd06db40d 100644 --- a/drivers/gpio/gpio-tegra186.c +++ b/drivers/gpio/gpio-tegra186.c @@ -11,7 +11,7 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/seq_file.h> diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index de14949a3fe5..bbd9e9191199 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -256,8 +256,6 @@ static int timbgpio_probe(struct platform_device *pdev) if (err) return err; - platform_set_drvdata(pdev, tgpio); - /* make sure to disable interrupts */ iowrite32(0x0, tgpio->membase + TGPIO_IER); diff --git a/drivers/gpio/gpio-tps65218.c b/drivers/gpio/gpio-tps65218.c index e1d425a18854..d7d9d50dcddf 100644 --- a/drivers/gpio/gpio-tps65218.c +++ b/drivers/gpio/gpio-tps65218.c @@ -216,7 +216,7 @@ MODULE_DEVICE_TABLE(platform, tps65218_gpio_id_table); static struct platform_driver tps65218_gpio_driver = { .driver = { .name = "tps65218-gpio", - .of_match_table = of_match_ptr(tps65218_dt_match) + .of_match_table = tps65218_dt_match, }, .probe = tps65218_gpio_probe, .id_table = tps65218_gpio_id_table, diff --git a/drivers/gpio/gpio-tps6586x.c b/drivers/gpio/gpio-tps6586x.c index c5713524b581..d277aa951143 100644 --- a/drivers/gpio/gpio-tps6586x.c +++ b/drivers/gpio/gpio-tps6586x.c @@ -15,7 +15,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/mfd/tps6586x.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> /* GPIO control registers */ diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c index 321e6945f0be..187d21580573 100644 --- a/drivers/gpio/gpio-tps65910.c +++ b/drivers/gpio/gpio-tps65910.c @@ -15,7 +15,7 @@ #include <linux/i2c.h> #include <linux/platform_device.h> #include <linux/mfd/tps65910.h> -#include <linux/of_device.h> +#include <linux/of.h> struct tps65910_gpio { struct gpio_chip gpio_chip; diff --git a/drivers/gpio/gpio-tqmx86.c b/drivers/gpio/gpio-tqmx86.c index 6f8bd1155db7..3a28c1f273c3 100644 --- a/drivers/gpio/gpio-tqmx86.c +++ b/drivers/gpio/gpio-tqmx86.c @@ -277,8 +277,6 @@ static int tqmx86_gpio_probe(struct platform_device *pdev) tqmx86_gpio_write(gpio, (u8)~TQMX86_DIR_INPUT_MASK, TQMX86_GPIODD); - platform_set_drvdata(pdev, gpio); - chip = &gpio->chip; chip->label = "gpio-tqmx86"; chip->owner = THIS_MODULE; diff --git a/drivers/gpio/gpio-ts4800.c b/drivers/gpio/gpio-ts4800.c index 95d80ba14bee..4748e3d47106 100644 --- a/drivers/gpio/gpio-ts4800.c +++ b/drivers/gpio/gpio-ts4800.c @@ -7,8 +7,7 @@ #include <linux/gpio/driver.h> #include <linux/module.h> -#include <linux/of_address.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #define DEFAULT_PIN_NUMBER 16 diff --git a/drivers/gpio/gpio-ts4900.c b/drivers/gpio/gpio-ts4900.c index eba96319dac2..0f6397b77c9d 100644 --- a/drivers/gpio/gpio-ts4900.c +++ b/drivers/gpio/gpio-ts4900.c @@ -8,7 +8,7 @@ #include <linux/gpio/driver.h> #include <linux/i2c.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/module.h> #include <linux/regmap.h> diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c index 19ce6675cbc0..9725b7aa18a7 100644 --- a/drivers/gpio/gpio-uniphier.c +++ b/drivers/gpio/gpio-uniphier.c @@ -9,7 +9,6 @@ #include <linux/irqdomain.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/platform_device.h> #include <linux/spinlock.h> diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c index d3f3a69d4907..dbc7ba0ee72c 100644 --- a/drivers/gpio/gpio-vf610.c +++ b/drivers/gpio/gpio-vf610.c @@ -17,7 +17,6 @@ #include <linux/irq.h> #include <linux/platform_device.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/pinctrl/consumer.h> @@ -259,7 +258,6 @@ static void vf610_gpio_disable_clk(void *data) static int vf610_gpio_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; struct vf610_gpio_port *port; struct gpio_chip *gc; struct gpio_irq_chip *girq; @@ -319,7 +317,7 @@ static int vf610_gpio_probe(struct platform_device *pdev) gc->parent = dev; gc->label = dev_name(dev); gc->ngpio = VF610_GPIO_PER_PORT; - gc->base = of_alias_get_id(np, "gpio") * VF610_GPIO_PER_PORT; + gc->base = -1; gc->request = gpiochip_generic_request; gc->free = gpiochip_generic_free; diff --git a/drivers/gpio/gpio-vx855.c b/drivers/gpio/gpio-vx855.c index 69713fd5485b..8fd6c3913d69 100644 --- a/drivers/gpio/gpio-vx855.c +++ b/drivers/gpio/gpio-vx855.c @@ -240,8 +240,6 @@ static int vx855gpio_probe(struct platform_device *pdev) if (!vg) return -ENOMEM; - platform_set_drvdata(pdev, vg); - dev_info(&pdev->dev, "found VX855 GPIO controller\n"); vg->io_gpi = res_gpi->start; vg->io_gpo = res_gpo->start; diff --git a/drivers/gpio/gpio-wcd934x.c b/drivers/gpio/gpio-wcd934x.c index 817750e4e033..2bba27b13947 100644 --- a/drivers/gpio/gpio-wcd934x.c +++ b/drivers/gpio/gpio-wcd934x.c @@ -1,11 +1,12 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2019, Linaro Limited +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/gpio/driver.h> +#include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/slab.h> -#include <linux/of_device.h> #define WCD_PIN_MASK(p) BIT(p) #define WCD_REG_DIR_CTL_OFFSET 0x42 diff --git a/drivers/gpio/gpio-ws16c48.c b/drivers/gpio/gpio-ws16c48.c index afb42a8e916f..6289b0510cf2 100644 --- a/drivers/gpio/gpio-ws16c48.c +++ b/drivers/gpio/gpio-ws16c48.c @@ -3,19 +3,18 @@ * GPIO driver for the WinSystems WS16C48 * Copyright (C) 2016 William Breathitt Gray */ -#include <linux/bitmap.h> +#include <linux/bitfield.h> +#include <linux/bits.h> #include <linux/device.h> -#include <linux/errno.h> -#include <linux/gpio/driver.h> -#include <linux/io.h> -#include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/irqdesc.h> +#include <linux/err.h> +#include <linux/gpio/regmap.h> +#include <linux/irq.h> #include <linux/isa.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/spinlock.h> +#include <linux/regmap.h> #include <linux/types.h> #define WS16C48_EXTENT 11 @@ -31,371 +30,178 @@ static unsigned int num_irq; module_param_hw_array(irq, uint, irq, &num_irq, 0); MODULE_PARM_DESC(irq, "WinSystems WS16C48 interrupt line numbers"); -/** - * struct ws16c48_reg - device register structure - * @port: Port 0 through 5 I/O - * @int_pending: Interrupt Pending - * @page_lock: Register page (Bits 7-6) and I/O port lock (Bits 5-0) - * @pol_enab_int_id: Interrupt polarity, enable, and ID - */ -struct ws16c48_reg { - u8 port[6]; - u8 int_pending; - u8 page_lock; - u8 pol_enab_int_id[3]; +#define WS16C48_DAT_BASE 0x0 +#define WS16C48_PAGE_LOCK 0x7 +#define WS16C48_PAGE_BASE 0x8 +#define WS16C48_POL WS16C48_PAGE_BASE +#define WS16C48_ENAB WS16C48_PAGE_BASE +#define WS16C48_INT_ID WS16C48_PAGE_BASE + +#define PAGE_LOCK_PAGE_FIELD GENMASK(7, 6) +#define POL_PAGE u8_encode_bits(1, PAGE_LOCK_PAGE_FIELD) +#define ENAB_PAGE u8_encode_bits(2, PAGE_LOCK_PAGE_FIELD) +#define INT_ID_PAGE u8_encode_bits(3, PAGE_LOCK_PAGE_FIELD) + +static const struct regmap_range ws16c48_wr_ranges[] = { + regmap_reg_range(0x0, 0x5), regmap_reg_range(0x7, 0xA), +}; +static const struct regmap_range ws16c48_rd_ranges[] = { + regmap_reg_range(0x0, 0xA), +}; +static const struct regmap_range ws16c48_volatile_ranges[] = { + regmap_reg_range(0x0, 0x6), regmap_reg_range(0x8, 0xA), +}; +static const struct regmap_access_table ws16c48_wr_table = { + .yes_ranges = ws16c48_wr_ranges, + .n_yes_ranges = ARRAY_SIZE(ws16c48_wr_ranges), +}; +static const struct regmap_access_table ws16c48_rd_table = { + .yes_ranges = ws16c48_rd_ranges, + .n_yes_ranges = ARRAY_SIZE(ws16c48_rd_ranges), +}; +static const struct regmap_access_table ws16c48_volatile_table = { + .yes_ranges = ws16c48_volatile_ranges, + .n_yes_ranges = ARRAY_SIZE(ws16c48_volatile_ranges), +}; +static const struct regmap_config ws16c48_regmap_config = { + .reg_bits = 8, + .reg_stride = 1, + .val_bits = 8, + .io_port = true, + .wr_table = &ws16c48_wr_table, + .rd_table = &ws16c48_rd_table, + .volatile_table = &ws16c48_volatile_table, + .cache_type = REGCACHE_FLAT, + .use_raw_spinlock = true, +}; + +#define WS16C48_NGPIO_PER_REG 8 +#define WS16C48_REGMAP_IRQ(_id) \ + [_id] = { \ + .reg_offset = (_id) / WS16C48_NGPIO_PER_REG, \ + .mask = BIT((_id) % WS16C48_NGPIO_PER_REG), \ + .type = { \ + .type_reg_offset = (_id) / WS16C48_NGPIO_PER_REG, \ + .types_supported = IRQ_TYPE_EDGE_BOTH, \ + }, \ + } + +/* Only the first 24 lines (Port 0-2) support interrupts */ +#define WS16C48_NUM_IRQS 24 +static const struct regmap_irq ws16c48_regmap_irqs[WS16C48_NUM_IRQS] = { + WS16C48_REGMAP_IRQ(0), WS16C48_REGMAP_IRQ(1), WS16C48_REGMAP_IRQ(2), /* 0-2 */ + WS16C48_REGMAP_IRQ(3), WS16C48_REGMAP_IRQ(4), WS16C48_REGMAP_IRQ(5), /* 3-5 */ + WS16C48_REGMAP_IRQ(6), WS16C48_REGMAP_IRQ(7), WS16C48_REGMAP_IRQ(8), /* 6-8 */ + WS16C48_REGMAP_IRQ(9), WS16C48_REGMAP_IRQ(10), WS16C48_REGMAP_IRQ(11), /* 9-11 */ + WS16C48_REGMAP_IRQ(12), WS16C48_REGMAP_IRQ(13), WS16C48_REGMAP_IRQ(14), /* 12-14 */ + WS16C48_REGMAP_IRQ(15), WS16C48_REGMAP_IRQ(16), WS16C48_REGMAP_IRQ(17), /* 15-17 */ + WS16C48_REGMAP_IRQ(18), WS16C48_REGMAP_IRQ(19), WS16C48_REGMAP_IRQ(20), /* 18-20 */ + WS16C48_REGMAP_IRQ(21), WS16C48_REGMAP_IRQ(22), WS16C48_REGMAP_IRQ(23), /* 21-23 */ }; /** * struct ws16c48_gpio - GPIO device private data structure - * @chip: instance of the gpio_chip - * @io_state: bit I/O state (whether bit is set to input or output) - * @out_state: output bits state + * @map: regmap for the device * @lock: synchronization lock to prevent I/O race conditions * @irq_mask: I/O bits affected by interrupts - * @flow_mask: IRQ flow type mask for the respective I/O bits - * @reg: I/O address offset for the device registers */ struct ws16c48_gpio { - struct gpio_chip chip; - unsigned char io_state[6]; - unsigned char out_state[6]; + struct regmap *map; raw_spinlock_t lock; - unsigned long irq_mask; - unsigned long flow_mask; - struct ws16c48_reg __iomem *reg; + u8 irq_mask[WS16C48_NUM_IRQS / WS16C48_NGPIO_PER_REG]; }; -static int ws16c48_gpio_get_direction(struct gpio_chip *chip, unsigned offset) +static int ws16c48_handle_pre_irq(void *const irq_drv_data) __acquires(&ws16c48gpio->lock) { - struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); - const unsigned port = offset / 8; - const unsigned mask = BIT(offset % 8); + struct ws16c48_gpio *const ws16c48gpio = irq_drv_data; - if (ws16c48gpio->io_state[port] & mask) - return GPIO_LINE_DIRECTION_IN; - - return GPIO_LINE_DIRECTION_OUT; -} - -static int ws16c48_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); - const unsigned port = offset / 8; - const unsigned mask = BIT(offset % 8); - unsigned long flags; - - raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); - - ws16c48gpio->io_state[port] |= mask; - ws16c48gpio->out_state[port] &= ~mask; - iowrite8(ws16c48gpio->out_state[port], ws16c48gpio->reg->port + port); - - raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + /* Lock to prevent Page/Lock register change while we handle IRQ */ + raw_spin_lock(&ws16c48gpio->lock); return 0; } -static int ws16c48_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int value) +static int ws16c48_handle_post_irq(void *const irq_drv_data) __releases(&ws16c48gpio->lock) { - struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); - const unsigned port = offset / 8; - const unsigned mask = BIT(offset % 8); - unsigned long flags; - - raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); + struct ws16c48_gpio *const ws16c48gpio = irq_drv_data; - ws16c48gpio->io_state[port] &= ~mask; - if (value) - ws16c48gpio->out_state[port] |= mask; - else - ws16c48gpio->out_state[port] &= ~mask; - iowrite8(ws16c48gpio->out_state[port], ws16c48gpio->reg->port + port); - - raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + raw_spin_unlock(&ws16c48gpio->lock); return 0; } -static int ws16c48_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); - const unsigned port = offset / 8; - const unsigned mask = BIT(offset % 8); - unsigned long flags; - unsigned port_state; - - raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); - - /* ensure that GPIO is set for input */ - if (!(ws16c48gpio->io_state[port] & mask)) { - raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); - return -EINVAL; - } - - port_state = ioread8(ws16c48gpio->reg->port + port); - - raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); - - return !!(port_state & mask); -} - -static int ws16c48_gpio_get_multiple(struct gpio_chip *chip, - unsigned long *mask, unsigned long *bits) -{ - struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); - unsigned long offset; - unsigned long gpio_mask; - size_t index; - u8 __iomem *port_addr; - unsigned long port_state; - - /* clear bits array to a clean slate */ - bitmap_zero(bits, chip->ngpio); - - for_each_set_clump8(offset, gpio_mask, mask, chip->ngpio) { - index = offset / 8; - port_addr = ws16c48gpio->reg->port + index; - port_state = ioread8(port_addr) & gpio_mask; - - bitmap_set_value8(bits, port_state, offset); - } - - return 0; -} - -static void ws16c48_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); - const unsigned port = offset / 8; - const unsigned mask = BIT(offset % 8); - unsigned long flags; - - raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); - - /* ensure that GPIO is set for output */ - if (ws16c48gpio->io_state[port] & mask) { - raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); - return; - } - - if (value) - ws16c48gpio->out_state[port] |= mask; - else - ws16c48gpio->out_state[port] &= ~mask; - iowrite8(ws16c48gpio->out_state[port], ws16c48gpio->reg->port + port); - - raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); -} - -static void ws16c48_gpio_set_multiple(struct gpio_chip *chip, - unsigned long *mask, unsigned long *bits) -{ - struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); - unsigned long offset; - unsigned long gpio_mask; - size_t index; - u8 __iomem *port_addr; - unsigned long bitmask; - unsigned long flags; - - for_each_set_clump8(offset, gpio_mask, mask, chip->ngpio) { - index = offset / 8; - port_addr = ws16c48gpio->reg->port + index; - - /* mask out GPIO configured for input */ - gpio_mask &= ~ws16c48gpio->io_state[index]; - bitmask = bitmap_get_value8(bits, offset) & gpio_mask; - - raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); - - /* update output state data and set device gpio register */ - ws16c48gpio->out_state[index] &= ~gpio_mask; - ws16c48gpio->out_state[index] |= bitmask; - iowrite8(ws16c48gpio->out_state[index], port_addr); - - raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); - } -} - -static void ws16c48_irq_ack(struct irq_data *data) +static int ws16c48_handle_mask_sync(const int index, const unsigned int mask_buf_def, + const unsigned int mask_buf, void *const irq_drv_data) { - struct gpio_chip *chip = irq_data_get_irq_chip_data(data); - struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); - const unsigned long offset = irqd_to_hwirq(data); - const unsigned port = offset / 8; - const unsigned mask = BIT(offset % 8); + struct ws16c48_gpio *const ws16c48gpio = irq_drv_data; unsigned long flags; - unsigned port_state; - - /* only the first 3 ports support interrupts */ - if (port > 2) - return; + int ret = 0; raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); - port_state = ws16c48gpio->irq_mask >> (8*port); + /* exit early if no change since the last mask sync */ + if (mask_buf == ws16c48gpio->irq_mask[index]) + goto exit_unlock; + ws16c48gpio->irq_mask[index] = mask_buf; - /* Select Register Page 2; Unlock all I/O ports */ - iowrite8(0x80, &ws16c48gpio->reg->page_lock); + ret = regmap_write(ws16c48gpio->map, WS16C48_PAGE_LOCK, ENAB_PAGE); + if (ret) + goto exit_unlock; - /* Clear pending interrupt */ - iowrite8(port_state & ~mask, ws16c48gpio->reg->pol_enab_int_id + port); - iowrite8(port_state | mask, ws16c48gpio->reg->pol_enab_int_id + port); + /* Update ENAB register (inverted mask) */ + ret = regmap_write(ws16c48gpio->map, WS16C48_ENAB + index, ~mask_buf); + if (ret) + goto exit_unlock; - /* Select Register Page 3; Unlock all I/O ports */ - iowrite8(0xC0, &ws16c48gpio->reg->page_lock); + ret = regmap_write(ws16c48gpio->map, WS16C48_PAGE_LOCK, INT_ID_PAGE); + if (ret) + goto exit_unlock; +exit_unlock: raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); -} - -static void ws16c48_irq_mask(struct irq_data *data) -{ - struct gpio_chip *chip = irq_data_get_irq_chip_data(data); - struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); - const unsigned long offset = irqd_to_hwirq(data); - const unsigned long mask = BIT(offset); - const unsigned port = offset / 8; - unsigned long flags; - unsigned long port_state; - - /* only the first 3 ports support interrupts */ - if (port > 2) - return; - - raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); - ws16c48gpio->irq_mask &= ~mask; - gpiochip_disable_irq(chip, offset); - port_state = ws16c48gpio->irq_mask >> (8 * port); - - /* Select Register Page 2; Unlock all I/O ports */ - iowrite8(0x80, &ws16c48gpio->reg->page_lock); - - /* Disable interrupt */ - iowrite8(port_state, ws16c48gpio->reg->pol_enab_int_id + port); - - /* Select Register Page 3; Unlock all I/O ports */ - iowrite8(0xC0, &ws16c48gpio->reg->page_lock); - - raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); + return ret; } -static void ws16c48_irq_unmask(struct irq_data *data) +static int ws16c48_set_type_config(unsigned int **const buf, const unsigned int type, + const struct regmap_irq *const irq_data, const int idx, + void *const irq_drv_data) { - struct gpio_chip *chip = irq_data_get_irq_chip_data(data); - struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); - const unsigned long offset = irqd_to_hwirq(data); - const unsigned long mask = BIT(offset); - const unsigned port = offset / 8; + struct ws16c48_gpio *const ws16c48gpio = irq_drv_data; + unsigned int polarity; unsigned long flags; - unsigned long port_state; - - /* only the first 3 ports support interrupts */ - if (port > 2) - return; - - raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); - - gpiochip_enable_irq(chip, offset); - ws16c48gpio->irq_mask |= mask; - port_state = ws16c48gpio->irq_mask >> (8 * port); - - /* Select Register Page 2; Unlock all I/O ports */ - iowrite8(0x80, &ws16c48gpio->reg->page_lock); - - /* Enable interrupt */ - iowrite8(port_state, ws16c48gpio->reg->pol_enab_int_id + port); - - /* Select Register Page 3; Unlock all I/O ports */ - iowrite8(0xC0, &ws16c48gpio->reg->page_lock); - - raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); -} + int ret; -static int ws16c48_irq_set_type(struct irq_data *data, unsigned flow_type) -{ - struct gpio_chip *chip = irq_data_get_irq_chip_data(data); - struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip); - const unsigned long offset = irqd_to_hwirq(data); - const unsigned long mask = BIT(offset); - const unsigned port = offset / 8; - unsigned long flags; - unsigned long port_state; - - /* only the first 3 ports support interrupts */ - if (port > 2) - return -EINVAL; - - raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); - - switch (flow_type) { - case IRQ_TYPE_NONE: - break; + switch (type) { case IRQ_TYPE_EDGE_RISING: - ws16c48gpio->flow_mask |= mask; + polarity = irq_data->mask; break; case IRQ_TYPE_EDGE_FALLING: - ws16c48gpio->flow_mask &= ~mask; + polarity = 0; break; default: - raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); return -EINVAL; } - port_state = ws16c48gpio->flow_mask >> (8 * port); + raw_spin_lock_irqsave(&ws16c48gpio->lock, flags); - /* Select Register Page 1; Unlock all I/O ports */ - iowrite8(0x40, &ws16c48gpio->reg->page_lock); + ret = regmap_write(ws16c48gpio->map, WS16C48_PAGE_LOCK, POL_PAGE); + if (ret) + goto exit_unlock; /* Set interrupt polarity */ - iowrite8(port_state, ws16c48gpio->reg->pol_enab_int_id + port); + ret = regmap_update_bits(ws16c48gpio->map, WS16C48_POL + idx, irq_data->mask, polarity); + if (ret) + goto exit_unlock; - /* Select Register Page 3; Unlock all I/O ports */ - iowrite8(0xC0, &ws16c48gpio->reg->page_lock); + ret = regmap_write(ws16c48gpio->map, WS16C48_PAGE_LOCK, INT_ID_PAGE); + if (ret) + goto exit_unlock; +exit_unlock: raw_spin_unlock_irqrestore(&ws16c48gpio->lock, flags); - return 0; -} - -static const struct irq_chip ws16c48_irqchip = { - .name = "ws16c48", - .irq_ack = ws16c48_irq_ack, - .irq_mask = ws16c48_irq_mask, - .irq_unmask = ws16c48_irq_unmask, - .irq_set_type = ws16c48_irq_set_type, - .flags = IRQCHIP_IMMUTABLE, - GPIOCHIP_IRQ_RESOURCE_HELPERS, -}; - -static irqreturn_t ws16c48_irq_handler(int irq, void *dev_id) -{ - struct ws16c48_gpio *const ws16c48gpio = dev_id; - struct gpio_chip *const chip = &ws16c48gpio->chip; - struct ws16c48_reg __iomem *const reg = ws16c48gpio->reg; - unsigned long int_pending; - unsigned long port; - unsigned long int_id; - unsigned long gpio; - - int_pending = ioread8(®->int_pending) & 0x7; - if (!int_pending) - return IRQ_NONE; - - /* loop until all pending interrupts are handled */ - do { - for_each_set_bit(port, &int_pending, 3) { - int_id = ioread8(reg->pol_enab_int_id + port); - for_each_set_bit(gpio, &int_id, 8) - generic_handle_domain_irq(chip->irq.domain, - gpio + 8*port); - } - - int_pending = ioread8(®->int_pending) & 0x7; - } while (int_pending); - - return IRQ_HANDLED; + return ret; } #define WS16C48_NGPIO 48 @@ -414,30 +220,37 @@ static const char *ws16c48_names[WS16C48_NGPIO] = { "Port 5 Bit 4", "Port 5 Bit 5", "Port 5 Bit 6", "Port 5 Bit 7" }; -static int ws16c48_irq_init_hw(struct gpio_chip *gc) +static int ws16c48_irq_init_hw(struct regmap *const map) { - struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(gc); + int err; - /* Select Register Page 2; Unlock all I/O ports */ - iowrite8(0x80, &ws16c48gpio->reg->page_lock); + err = regmap_write(map, WS16C48_PAGE_LOCK, ENAB_PAGE); + if (err) + return err; /* Disable interrupts for all lines */ - iowrite8(0, &ws16c48gpio->reg->pol_enab_int_id[0]); - iowrite8(0, &ws16c48gpio->reg->pol_enab_int_id[1]); - iowrite8(0, &ws16c48gpio->reg->pol_enab_int_id[2]); - - /* Select Register Page 3; Unlock all I/O ports */ - iowrite8(0xC0, &ws16c48gpio->reg->page_lock); + err = regmap_write(map, WS16C48_ENAB + 0, 0x00); + if (err) + return err; + err = regmap_write(map, WS16C48_ENAB + 1, 0x00); + if (err) + return err; + err = regmap_write(map, WS16C48_ENAB + 2, 0x00); + if (err) + return err; - return 0; + return regmap_write(map, WS16C48_PAGE_LOCK, INT_ID_PAGE); } static int ws16c48_probe(struct device *dev, unsigned int id) { struct ws16c48_gpio *ws16c48gpio; const char *const name = dev_name(dev); - struct gpio_irq_chip *girq; int err; + struct gpio_regmap_config gpio_config = {}; + void __iomem *regs; + struct regmap_irq_chip *chip; + struct regmap_irq_chip_data *chip_data; ws16c48gpio = devm_kzalloc(dev, sizeof(*ws16c48gpio), GFP_KERNEL); if (!ws16c48gpio) @@ -449,50 +262,55 @@ static int ws16c48_probe(struct device *dev, unsigned int id) return -EBUSY; } - ws16c48gpio->reg = devm_ioport_map(dev, base[id], WS16C48_EXTENT); - if (!ws16c48gpio->reg) + regs = devm_ioport_map(dev, base[id], WS16C48_EXTENT); + if (!regs) return -ENOMEM; - ws16c48gpio->chip.label = name; - ws16c48gpio->chip.parent = dev; - ws16c48gpio->chip.owner = THIS_MODULE; - ws16c48gpio->chip.base = -1; - ws16c48gpio->chip.ngpio = WS16C48_NGPIO; - ws16c48gpio->chip.names = ws16c48_names; - ws16c48gpio->chip.get_direction = ws16c48_gpio_get_direction; - ws16c48gpio->chip.direction_input = ws16c48_gpio_direction_input; - ws16c48gpio->chip.direction_output = ws16c48_gpio_direction_output; - ws16c48gpio->chip.get = ws16c48_gpio_get; - ws16c48gpio->chip.get_multiple = ws16c48_gpio_get_multiple; - ws16c48gpio->chip.set = ws16c48_gpio_set; - ws16c48gpio->chip.set_multiple = ws16c48_gpio_set_multiple; - - girq = &ws16c48gpio->chip.irq; - gpio_irq_chip_set_chip(girq, &ws16c48_irqchip); - /* This will let us handle the parent IRQ in the driver */ - girq->parent_handler = NULL; - girq->num_parents = 0; - girq->parents = NULL; - girq->default_type = IRQ_TYPE_NONE; - girq->handler = handle_edge_irq; - girq->init_hw = ws16c48_irq_init_hw; + ws16c48gpio->map = devm_regmap_init_mmio(dev, regs, &ws16c48_regmap_config); + if (IS_ERR(ws16c48gpio->map)) + return dev_err_probe(dev, PTR_ERR(ws16c48gpio->map), + "Unable to initialize register map\n"); - raw_spin_lock_init(&ws16c48gpio->lock); + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; - err = devm_gpiochip_add_data(dev, &ws16c48gpio->chip, ws16c48gpio); - if (err) { - dev_err(dev, "GPIO registering failed (%d)\n", err); - return err; - } + chip->name = name; + chip->status_base = WS16C48_INT_ID; + chip->mask_base = WS16C48_ENAB; + chip->ack_base = WS16C48_INT_ID; + chip->num_regs = 3; + chip->irqs = ws16c48_regmap_irqs; + chip->num_irqs = ARRAY_SIZE(ws16c48_regmap_irqs); + chip->handle_pre_irq = ws16c48_handle_pre_irq; + chip->handle_post_irq = ws16c48_handle_post_irq; + chip->handle_mask_sync = ws16c48_handle_mask_sync; + chip->set_type_config = ws16c48_set_type_config; + chip->irq_drv_data = ws16c48gpio; - err = devm_request_irq(dev, irq[id], ws16c48_irq_handler, IRQF_SHARED, - name, ws16c48gpio); - if (err) { - dev_err(dev, "IRQ handler registering failed (%d)\n", err); + raw_spin_lock_init(&ws16c48gpio->lock); + + /* Initialize to prevent spurious interrupts before we're ready */ + err = ws16c48_irq_init_hw(ws16c48gpio->map); + if (err) return err; - } - return 0; + err = devm_regmap_add_irq_chip(dev, ws16c48gpio->map, irq[id], 0, 0, chip, &chip_data); + if (err) + return dev_err_probe(dev, err, "IRQ registration failed\n"); + + gpio_config.parent = dev; + gpio_config.regmap = ws16c48gpio->map; + gpio_config.ngpio = WS16C48_NGPIO; + gpio_config.names = ws16c48_names; + gpio_config.reg_dat_base = GPIO_REGMAP_ADDR(WS16C48_DAT_BASE); + gpio_config.reg_set_base = GPIO_REGMAP_ADDR(WS16C48_DAT_BASE); + /* Setting a GPIO to 0 allows it to be used as an input */ + gpio_config.reg_dir_out_base = GPIO_REGMAP_ADDR(WS16C48_DAT_BASE); + gpio_config.ngpio_per_reg = WS16C48_NGPIO_PER_REG; + gpio_config.irq_domain = regmap_irq_get_domain(chip_data); + + return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config)); } static struct isa_driver ws16c48_driver = { diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index 1fa66f2a667f..a16945e8319e 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -15,8 +15,8 @@ #include <linux/io.h> #include <linux/irq.h> #include <linux/module.h> -#include <linux/of_device.h> -#include <linux/of_platform.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/slab.h> diff --git a/drivers/gpio/gpio-xra1403.c b/drivers/gpio/gpio-xra1403.c index bbc06cdd9634..dc2710c21c50 100644 --- a/drivers/gpio/gpio-xra1403.c +++ b/drivers/gpio/gpio-xra1403.c @@ -8,9 +8,9 @@ #include <linux/bitops.h> #include <linux/gpio/driver.h> #include <linux/kernel.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/mutex.h> -#include <linux/of_device.h> #include <linux/seq_file.h> #include <linux/spi/spi.h> #include <linux/regmap.h> @@ -194,7 +194,7 @@ static const struct spi_device_id xra1403_ids[] = { }; MODULE_DEVICE_TABLE(spi, xra1403_ids); -static const struct of_device_id xra1403_spi_of_match[] __maybe_unused = { +static const struct of_device_id xra1403_spi_of_match[] = { { .compatible = "exar,xra1403" }, {}, }; @@ -205,7 +205,7 @@ static struct spi_driver xra1403_driver = { .id_table = xra1403_ids, .driver = { .name = "xra1403", - .of_match_table = of_match_ptr(xra1403_spi_of_match), + .of_match_table = xra1403_spi_of_match, }, }; diff --git a/drivers/gpio/gpio-zevio.c b/drivers/gpio/gpio-zevio.c index f0f571b323f2..2de61337ad3b 100644 --- a/drivers/gpio/gpio-zevio.c +++ b/drivers/gpio/gpio-zevio.c @@ -176,8 +176,6 @@ static int zevio_gpio_probe(struct platform_device *pdev) if (!controller) return -ENOMEM; - platform_set_drvdata(pdev, controller); - /* Copy our reference */ controller->chip = zevio_gpio_chip; controller->chip.parent = &pdev->dev; diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 97496c0f9133..fbda452fb4d6 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -128,7 +128,7 @@ static bool acpi_gpio_deferred_req_irqs_done; static int acpi_gpiochip_find(struct gpio_chip *gc, void *data) { - return ACPI_HANDLE_FWNODE(gc->fwnode) == data; + return device_match_acpi_handle(&gc->gpiodev->dev, data); } /** diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 0a33971c964c..e39d344feb28 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -230,9 +230,7 @@ static long linehandle_set_config(struct linehandle_state *lh, return ret; } - blocking_notifier_call_chain(&desc->gdev->notifier, - GPIO_V2_LINE_CHANGED_CONFIG, - desc); + gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_CONFIG); } return 0; } @@ -414,8 +412,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) goto out_free_lh; } - blocking_notifier_call_chain(&desc->gdev->notifier, - GPIO_V2_LINE_CHANGED_REQUESTED, desc); + gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_REQUESTED); dev_dbg(&gdev->dev, "registered chardev handle for line %d\n", offset); @@ -555,6 +552,7 @@ struct line { * @label: consumer label used to tag GPIO descriptors * @num_lines: the number of lines in the lines array * @wait: wait queue that handles blocking reads of events + * @device_unregistered_nb: notifier block for receiving gdev unregister events * @event_buffer_size: the number of elements allocated in @events * @events: KFIFO for the GPIO events * @seqno: the sequence number for edge events generated on all lines in @@ -569,6 +567,7 @@ struct linereq { const char *label; u32 num_lines; wait_queue_head_t wait; + struct notifier_block device_unregistered_nb; u32 event_buffer_size; DECLARE_KFIFO_PTR(events, struct gpio_v2_line_event); atomic_t seqno; @@ -610,6 +609,17 @@ struct linereq { GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE | \ GPIO_V2_LINE_EDGE_FLAGS) +static int linereq_unregistered_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct linereq *lr = container_of(nb, struct linereq, + device_unregistered_nb); + + wake_up_poll(&lr->wait, EPOLLIN | EPOLLERR); + + return NOTIFY_OK; +} + static void linereq_put_event(struct linereq *lr, struct gpio_v2_line_event *le) { @@ -1407,9 +1417,7 @@ static long linereq_set_config_unlocked(struct linereq *lr, WRITE_ONCE(line->edflags, edflags); - blocking_notifier_call_chain(&desc->gdev->notifier, - GPIO_V2_LINE_CHANGED_CONFIG, - desc); + gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_CONFIG); } return 0; } @@ -1567,6 +1575,10 @@ static void linereq_free(struct linereq *lr) { unsigned int i; + if (lr->device_unregistered_nb.notifier_call) + blocking_notifier_chain_unregister(&lr->gdev->device_notifier, + &lr->device_unregistered_nb); + for (i = 0; i < lr->num_lines; i++) { if (lr->lines[i].desc) { edge_detector_stop(&lr->lines[i]); @@ -1720,13 +1732,18 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip) lr->lines[i].edflags = edflags; - blocking_notifier_call_chain(&desc->gdev->notifier, - GPIO_V2_LINE_CHANGED_REQUESTED, desc); + gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_REQUESTED); dev_dbg(&gdev->dev, "registered chardev handle for line %d\n", offset); } + lr->device_unregistered_nb.notifier_call = linereq_unregistered_notify; + ret = blocking_notifier_chain_register(&gdev->device_notifier, + &lr->device_unregistered_nb); + if (ret) + goto out_free_linereq; + fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC); if (fd < 0) { ret = fd; @@ -1779,6 +1796,7 @@ out_free_linereq: * @eflags: the event flags this line was requested with * @irq: the interrupt that trigger in response to events on this GPIO * @wait: wait queue that handles blocking reads of events + * @device_unregistered_nb: notifier block for receiving gdev unregister events * @events: KFIFO for the GPIO events * @timestamp: cache for the timestamp storing it between hardirq * and IRQ thread, used to bring the timestamp close to the actual @@ -1791,6 +1809,7 @@ struct lineevent_state { u32 eflags; int irq; wait_queue_head_t wait; + struct notifier_block device_unregistered_nb; DECLARE_KFIFO(events, struct gpioevent_data, 16); u64 timestamp; }; @@ -1824,6 +1843,17 @@ static __poll_t lineevent_poll(struct file *file, return call_poll_locked(file, wait, le->gdev, lineevent_poll_unlocked); } +static int lineevent_unregistered_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct lineevent_state *le = container_of(nb, struct lineevent_state, + device_unregistered_nb); + + wake_up_poll(&le->wait, EPOLLIN | EPOLLERR); + + return NOTIFY_OK; +} + struct compat_gpioeevent_data { compat_u64 timestamp; u32 id; @@ -1909,6 +1939,9 @@ static ssize_t lineevent_read(struct file *file, char __user *buf, static void lineevent_free(struct lineevent_state *le) { + if (le->device_unregistered_nb.notifier_call) + blocking_notifier_chain_unregister(&le->gdev->device_notifier, + &le->device_unregistered_nb); if (le->irq) free_irq(le->irq, le); if (le->desc) @@ -2117,8 +2150,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) if (ret) goto out_free_le; - blocking_notifier_call_chain(&desc->gdev->notifier, - GPIO_V2_LINE_CHANGED_REQUESTED, desc); + gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_REQUESTED); irq = gpiod_to_irq(desc); if (irq <= 0) { @@ -2137,6 +2169,12 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) INIT_KFIFO(le->events); init_waitqueue_head(&le->wait); + le->device_unregistered_nb.notifier_call = lineevent_unregistered_notify; + ret = blocking_notifier_chain_register(&gdev->device_notifier, + &le->device_unregistered_nb); + if (ret) + goto out_free_le; + /* Request a thread to read the events */ ret = request_threaded_irq(irq, lineevent_irq_handler, @@ -2320,6 +2358,7 @@ struct gpio_chardev_data { wait_queue_head_t wait; DECLARE_KFIFO(events, struct gpio_v2_line_info_changed, 32); struct notifier_block lineinfo_changed_nb; + struct notifier_block device_unregistered_nb; unsigned long *watched_lines; #ifdef CONFIG_GPIO_CDEV_V1 atomic_t watch_abi_version; @@ -2491,16 +2530,11 @@ static long gpio_ioctl_compat(struct file *file, unsigned int cmd, } #endif -static struct gpio_chardev_data * -to_gpio_chardev_data(struct notifier_block *nb) -{ - return container_of(nb, struct gpio_chardev_data, lineinfo_changed_nb); -} - static int lineinfo_changed_notify(struct notifier_block *nb, unsigned long action, void *data) { - struct gpio_chardev_data *cdev = to_gpio_chardev_data(nb); + struct gpio_chardev_data *cdev = + container_of(nb, struct gpio_chardev_data, lineinfo_changed_nb); struct gpio_v2_line_info_changed chg; struct gpio_desc *desc = data; int ret; @@ -2522,6 +2556,18 @@ static int lineinfo_changed_notify(struct notifier_block *nb, return NOTIFY_OK; } +static int gpio_device_unregistered_notify(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct gpio_chardev_data *cdev = container_of(nb, + struct gpio_chardev_data, + device_unregistered_nb); + + wake_up_poll(&cdev->wait, EPOLLIN | EPOLLERR); + + return NOTIFY_OK; +} + static __poll_t lineinfo_watch_poll_unlocked(struct file *file, struct poll_table_struct *pollt) { @@ -2671,23 +2717,33 @@ static int gpio_chrdev_open(struct inode *inode, struct file *file) cdev->gdev = gpio_device_get(gdev); cdev->lineinfo_changed_nb.notifier_call = lineinfo_changed_notify; - ret = blocking_notifier_chain_register(&gdev->notifier, + ret = blocking_notifier_chain_register(&gdev->line_state_notifier, &cdev->lineinfo_changed_nb); if (ret) goto out_free_bitmap; + cdev->device_unregistered_nb.notifier_call = + gpio_device_unregistered_notify; + ret = blocking_notifier_chain_register(&gdev->device_notifier, + &cdev->device_unregistered_nb); + if (ret) + goto out_unregister_line_notifier; + file->private_data = cdev; ret = nonseekable_open(inode, file); if (ret) - goto out_unregister_notifier; + goto out_unregister_device_notifier; up_read(&gdev->sem); return ret; -out_unregister_notifier: - blocking_notifier_chain_unregister(&gdev->notifier, +out_unregister_device_notifier: + blocking_notifier_chain_unregister(&gdev->device_notifier, + &cdev->device_unregistered_nb); +out_unregister_line_notifier: + blocking_notifier_chain_unregister(&gdev->line_state_notifier, &cdev->lineinfo_changed_nb); out_free_bitmap: gpio_device_put(gdev); @@ -2711,7 +2767,9 @@ static int gpio_chrdev_release(struct inode *inode, struct file *file) struct gpio_device *gdev = cdev->gdev; bitmap_free(cdev->watched_lines); - blocking_notifier_chain_unregister(&gdev->notifier, + blocking_notifier_chain_unregister(&gdev->device_notifier, + &cdev->device_unregistered_nb); + blocking_notifier_chain_unregister(&gdev->line_state_notifier, &cdev->lineinfo_changed_nb); gpio_device_put(gdev); kfree(cdev); @@ -2753,4 +2811,5 @@ int gpiolib_cdev_register(struct gpio_device *gdev, dev_t devt) void gpiolib_cdev_unregister(struct gpio_device *gdev) { cdev_device_del(&gdev->chrdev, &gdev->dev); + blocking_notifier_call_chain(&gdev->device_notifier, 0, NULL); } diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index 1436cdb5fa26..531faabead0f 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -209,6 +209,8 @@ static void of_gpio_set_polarity_by_property(const struct device_node *np, const char *propname, enum of_gpio_flags *flags) { + const struct device_node *np_compat = np; + const struct device_node *np_propname = np; static const struct { const char *compatible; const char *gpio_propname; @@ -253,14 +255,28 @@ static void of_gpio_set_polarity_by_property(const struct device_node *np, { "regulator-gpio", "enable-gpio", "enable-active-high" }, { "regulator-gpio", "enable-gpios", "enable-active-high" }, #endif +#if IS_ENABLED(CONFIG_MMC_ATMELMCI) + { "atmel,hsmci", "cd-gpios", "cd-inverted" }, +#endif }; unsigned int i; bool active_high; +#if IS_ENABLED(CONFIG_MMC_ATMELMCI) + /* + * The Atmel HSMCI has compatible property in the parent node and + * gpio property in a child node + */ + if (of_device_is_compatible(np->parent, "atmel,hsmci")) { + np_compat = np->parent; + np_propname = np; + } +#endif + for (i = 0; i < ARRAY_SIZE(gpios); i++) { - if (of_device_is_compatible(np, gpios[i].compatible) && + if (of_device_is_compatible(np_compat, gpios[i].compatible) && !strcmp(propname, gpios[i].gpio_propname)) { - active_high = of_property_read_bool(np, + active_high = of_property_read_bool(np_propname, gpios[i].polarity_propname); of_gpio_quirk_polarity(np, active_high, flags); break; @@ -1078,16 +1094,16 @@ int of_gpiochip_add(struct gpio_chip *chip) if (ret) return ret; - fwnode_handle_get(chip->fwnode); + of_node_get(np); ret = of_gpiochip_scan_gpios(chip); if (ret) - fwnode_handle_put(chip->fwnode); + of_node_put(np); return ret; } void of_gpiochip_remove(struct gpio_chip *chip) { - fwnode_handle_put(chip->fwnode); + of_node_put(dev_of_node(&chip->gpiodev->dev)); } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 76e0c38026c3..40a0022ea719 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -700,6 +700,40 @@ void *gpiochip_get_data(struct gpio_chip *gc) } EXPORT_SYMBOL_GPL(gpiochip_get_data); +int gpiochip_get_ngpios(struct gpio_chip *gc, struct device *dev) +{ + u32 ngpios = gc->ngpio; + int ret; + + if (ngpios == 0) { + ret = device_property_read_u32(dev, "ngpios", &ngpios); + if (ret == -ENODATA) + /* + * -ENODATA means that there is no property found and + * we want to issue the error message to the user. + * Besides that, we want to return different error code + * to state that supplied value is not valid. + */ + ngpios = 0; + else if (ret) + return ret; + + gc->ngpio = ngpios; + } + + if (gc->ngpio == 0) { + chip_err(gc, "tried to insert a GPIO chip with zero lines\n"); + return -EINVAL; + } + + if (gc->ngpio > FASTPATH_NGPIO) + chip_warn(gc, "line cnt %u is greater than fast path cnt %u\n", + gc->ngpio, FASTPATH_NGPIO); + + return 0; +} +EXPORT_SYMBOL_GPL(gpiochip_get_ngpios); + int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, struct lock_class_key *lock_key, struct lock_class_key *request_key) @@ -707,18 +741,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, struct gpio_device *gdev; unsigned long flags; unsigned int i; - u32 ngpios = 0; int base = 0; int ret = 0; /* - * If the calling driver did not initialize firmware node, do it here - * using the parent device, if any. - */ - if (!gc->fwnode && gc->parent) - gc->fwnode = dev_fwnode(gc->parent); - - /* * First: allocate and populate the internal stat container, and * set up the struct device. */ @@ -732,7 +758,14 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, gc->gpiodev = gdev; gpiochip_set_data(gc, data); - device_set_node(&gdev->dev, gc->fwnode); + /* + * If the calling driver did not initialize firmware node, + * do it here using the parent device, if any. + */ + if (gc->fwnode) + device_set_node(&gdev->dev, gc->fwnode); + else if (gc->parent) + device_set_node(&gdev->dev, dev_fwnode(gc->parent)); gdev->id = ida_alloc(&gpio_ida, GFP_KERNEL); if (gdev->id < 0) { @@ -753,36 +786,9 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, else gdev->owner = THIS_MODULE; - /* - * Try the device properties if the driver didn't supply the number - * of GPIO lines. - */ - ngpios = gc->ngpio; - if (ngpios == 0) { - ret = device_property_read_u32(&gdev->dev, "ngpios", &ngpios); - if (ret == -ENODATA) - /* - * -ENODATA means that there is no property found and - * we want to issue the error message to the user. - * Besides that, we want to return different error code - * to state that supplied value is not valid. - */ - ngpios = 0; - else if (ret) - goto err_free_dev_name; - - gc->ngpio = ngpios; - } - - if (gc->ngpio == 0) { - chip_err(gc, "tried to insert a GPIO chip with zero lines\n"); - ret = -EINVAL; + ret = gpiochip_get_ngpios(gc, &gdev->dev); + if (ret) goto err_free_dev_name; - } - - if (gc->ngpio > FASTPATH_NGPIO) - chip_warn(gc, "line cnt %u is greater than fast path cnt %u\n", - gc->ngpio, FASTPATH_NGPIO); gdev->descs = kcalloc(gc->ngpio, sizeof(*gdev->descs), GFP_KERNEL); if (!gdev->descs) { @@ -841,7 +847,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, spin_unlock_irqrestore(&gpio_lock, flags); - BLOCKING_INIT_NOTIFIER_HEAD(&gdev->notifier); + BLOCKING_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier); + BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier); init_rwsem(&gdev->sem); #ifdef CONFIG_PINCTRL @@ -947,7 +954,7 @@ err_print_message: /* failures here can mean systems won't boot... */ if (ret != -EPROBE_DEFER) { pr_err("%s: GPIOs %d..%d (%s) failed to register, %d\n", __func__, - base, base + (int)ngpios - 1, + base, base + (int)gc->ngpio - 1, gc->label ? : "generic", ret); } return ret; @@ -1292,12 +1299,14 @@ static void gpiochip_hierarchy_setup_domain_ops(struct irq_domain_ops *ops) ops->free = irq_domain_free_irqs_common; } -static int gpiochip_hierarchy_add_domain(struct gpio_chip *gc) +static struct irq_domain *gpiochip_hierarchy_create_domain(struct gpio_chip *gc) { + struct irq_domain *domain; + if (!gc->irq.child_to_parent_hwirq || !gc->irq.fwnode) { chip_err(gc, "missing irqdomain vital data\n"); - return -EINVAL; + return ERR_PTR(-EINVAL); } if (!gc->irq.child_offset_to_irq) @@ -1309,7 +1318,7 @@ static int gpiochip_hierarchy_add_domain(struct gpio_chip *gc) gpiochip_hierarchy_setup_domain_ops(&gc->irq.child_irq_domain_ops); - gc->irq.domain = irq_domain_create_hierarchy( + domain = irq_domain_create_hierarchy( gc->irq.parent_domain, 0, gc->ngpio, @@ -1317,12 +1326,12 @@ static int gpiochip_hierarchy_add_domain(struct gpio_chip *gc) &gc->irq.child_irq_domain_ops, gc); - if (!gc->irq.domain) - return -ENOMEM; + if (!domain) + return ERR_PTR(-ENOMEM); gpiochip_set_hierarchical_irqchip(gc, gc->irq.chip); - return 0; + return domain; } static bool gpiochip_hierarchy_is_hierarchical(struct gpio_chip *gc) @@ -1366,9 +1375,9 @@ EXPORT_SYMBOL_GPL(gpiochip_populate_parent_fwspec_fourcell); #else -static int gpiochip_hierarchy_add_domain(struct gpio_chip *gc) +static struct irq_domain *gpiochip_hierarchy_create_domain(struct gpio_chip *gc) { - return -EINVAL; + return ERR_PTR(-EINVAL); } static bool gpiochip_hierarchy_is_hierarchical(struct gpio_chip *gc) @@ -1445,6 +1454,19 @@ static const struct irq_domain_ops gpiochip_domain_ops = { .xlate = irq_domain_xlate_twocell, }; +static struct irq_domain *gpiochip_simple_create_domain(struct gpio_chip *gc) +{ + struct fwnode_handle *fwnode = dev_fwnode(&gc->gpiodev->dev); + struct irq_domain *domain; + + domain = irq_domain_create_simple(fwnode, gc->ngpio, gc->irq.first, + &gpiochip_domain_ops, gc); + if (!domain) + return ERR_PTR(-EINVAL); + + return domain; +} + /* * TODO: move these activate/deactivate in under the hierarchicial * irqchip implementation as static once SPMI and SSBI (all external @@ -1623,6 +1645,31 @@ static void gpiochip_set_irq_hooks(struct gpio_chip *gc) } } +static int gpiochip_irqchip_add_allocated_domain(struct gpio_chip *gc, + struct irq_domain *domain, + bool allocated_externally) +{ + if (!domain) + return -EINVAL; + + if (gc->to_irq) + chip_warn(gc, "to_irq is redefined in %s and you shouldn't rely on it\n", __func__); + + gc->to_irq = gpiochip_to_irq; + gc->irq.domain = domain; + gc->irq.domain_is_allocated_externally = allocated_externally; + + /* + * Using barrier() here to prevent compiler from reordering + * gc->irq.initialized before adding irqdomain. + */ + barrier(); + + gc->irq.initialized = true; + + return 0; +} + /** * gpiochip_add_irqchip() - adds an IRQ chip to a GPIO chip * @gc: the GPIO chip to add the IRQ chip to @@ -1635,8 +1682,10 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc, { struct fwnode_handle *fwnode = dev_fwnode(&gc->gpiodev->dev); struct irq_chip *irqchip = gc->irq.chip; + struct irq_domain *domain; unsigned int type; unsigned int i; + int ret; if (!irqchip) return 0; @@ -1657,28 +1706,18 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc, "%pfw: Ignoring %u default trigger\n", fwnode, type)) type = IRQ_TYPE_NONE; - if (gc->to_irq) - chip_warn(gc, "to_irq is redefined in %s and you shouldn't rely on it\n", __func__); - - gc->to_irq = gpiochip_to_irq; gc->irq.default_type = type; gc->irq.lock_key = lock_key; gc->irq.request_key = request_key; /* If a parent irqdomain is provided, let's build a hierarchy */ if (gpiochip_hierarchy_is_hierarchical(gc)) { - int ret = gpiochip_hierarchy_add_domain(gc); - if (ret) - return ret; + domain = gpiochip_hierarchy_create_domain(gc); } else { - gc->irq.domain = irq_domain_create_simple(fwnode, - gc->ngpio, - gc->irq.first, - &gpiochip_domain_ops, - gc); - if (!gc->irq.domain) - return -EINVAL; + domain = gpiochip_simple_create_domain(gc); } + if (IS_ERR(domain)) + return PTR_ERR(domain); if (gc->irq.parent_handler) { for (i = 0; i < gc->irq.num_parents; i++) { @@ -1702,14 +1741,9 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc, gpiochip_set_irq_hooks(gc); - /* - * Using barrier() here to prevent compiler from reordering - * gc->irq.initialized before initialization of above - * GPIO chip irq members. - */ - barrier(); - - gc->irq.initialized = true; + ret = gpiochip_irqchip_add_allocated_domain(gc, domain, false); + if (ret) + return ret; acpi_gpiochip_request_interrupts(gc); @@ -1780,22 +1814,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gc) int gpiochip_irqchip_add_domain(struct gpio_chip *gc, struct irq_domain *domain) { - if (!domain) - return -EINVAL; - - gc->to_irq = gpiochip_to_irq; - gc->irq.domain = domain; - gc->irq.domain_is_allocated_externally = true; - - /* - * Using barrier() here to prevent compiler from reordering - * gc->irq.initialized before adding irqdomain. - */ - barrier(); - - gc->irq.initialized = true; - - return 0; + return gpiochip_irqchip_add_allocated_domain(gc, domain, true); } EXPORT_SYMBOL_GPL(gpiochip_irqchip_add_domain); @@ -2159,8 +2178,7 @@ static bool gpiod_free_commit(struct gpio_desc *desc) } spin_unlock_irqrestore(&gpio_lock, flags); - blocking_notifier_call_chain(&desc->gdev->notifier, - GPIOLINE_CHANGED_RELEASED, desc); + gpiod_line_state_notify(desc, GPIOLINE_CHANGED_RELEASED); return ret; } @@ -3728,6 +3746,12 @@ int gpiod_set_array_value_cansleep(unsigned int array_size, } EXPORT_SYMBOL_GPL(gpiod_set_array_value_cansleep); +void gpiod_line_state_notify(struct gpio_desc *desc, unsigned long action) +{ + blocking_notifier_call_chain(&desc->gdev->line_state_notifier, + action, desc); +} + /** * gpiod_add_lookup_table() - register GPIO device consumers * @table: table of consumers to register @@ -3995,8 +4019,7 @@ static struct gpio_desc *gpiod_find_and_request(struct device *consumer, return ERR_PTR(ret); } - blocking_notifier_call_chain(&desc->gdev->notifier, - GPIOLINE_CHANGED_REQUESTED, desc); + gpiod_line_state_notify(desc, GPIOLINE_CHANGED_REQUESTED); return desc; } diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index cca81375f127..a0a67569300b 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -9,12 +9,13 @@ #ifndef GPIOLIB_H #define GPIOLIB_H -#include <linux/gpio/driver.h> -#include <linux/gpio/consumer.h> /* for enum gpiod_flags */ -#include <linux/err.h> +#include <linux/cdev.h> #include <linux/device.h> +#include <linux/err.h> +#include <linux/gpio/consumer.h> /* for enum gpiod_flags */ +#include <linux/gpio/driver.h> #include <linux/module.h> -#include <linux/cdev.h> +#include <linux/notifier.h> #include <linux/rwsem.h> #define GPIOCHIP_NAME "gpiochip" @@ -38,8 +39,10 @@ * or name of the IP component in a System on Chip. * @data: per-instance data assigned by the driver * @list: links gpio_device:s together for traversal - * @notifier: used to notify subscribers about lines being requested, released - * or reconfigured + * @line_state_notifier: used to notify subscribers about lines being + * requested, released or reconfigured + * @device_notifier: used to notify character device wait queues about the GPIO + * device being unregistered * @sem: protects the structure from a NULL-pointer dereference of @chip by * user-space operations when the device gets unregistered during * a hot-unplug event @@ -63,7 +66,8 @@ struct gpio_device { const char *label; void *data; struct list_head list; - struct blocking_notifier_head notifier; + struct blocking_notifier_head line_state_notifier; + struct blocking_notifier_head device_notifier; struct rw_semaphore sem; #ifdef CONFIG_PINCTRL @@ -143,6 +147,7 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, extern spinlock_t gpio_lock; extern struct list_head gpio_devices; +void gpiod_line_state_notify(struct gpio_desc *desc, unsigned long action); /** * struct gpio_desc - Opaque descriptor for a GPIO @@ -217,6 +222,7 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id, int gpio_set_debounce_timeout(struct gpio_desc *desc, unsigned int debounce); int gpiod_hog(struct gpio_desc *desc, const char *name, unsigned long lflags, enum gpiod_flags dflags); +int gpiochip_get_ngpios(struct gpio_chip *gc, struct device *dev); /* * Return the GPIO number of the passed descriptor relative to its chip diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index 043b8109e64a..73ec60757dbc 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -1386,6 +1386,18 @@ static void samsung_dsim_disable_irq(struct samsung_dsim *dsi) disable_irq(dsi->irq); } +static void samsung_dsim_set_stop_state(struct samsung_dsim *dsi, bool enable) +{ + u32 reg = samsung_dsim_read(dsi, DSIM_ESCMODE_REG); + + if (enable) + reg |= DSIM_FORCE_STOP_STATE; + else + reg &= ~DSIM_FORCE_STOP_STATE; + + samsung_dsim_write(dsi, DSIM_ESCMODE_REG, reg); +} + static int samsung_dsim_init(struct samsung_dsim *dsi) { const struct samsung_dsim_driver_data *driver_data = dsi->driver_data; @@ -1445,15 +1457,12 @@ static void samsung_dsim_atomic_enable(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state) { struct samsung_dsim *dsi = bridge_to_dsi(bridge); - u32 reg; if (samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type)) { samsung_dsim_set_display_mode(dsi); samsung_dsim_set_display_enable(dsi, true); } else { - reg = samsung_dsim_read(dsi, DSIM_ESCMODE_REG); - reg &= ~DSIM_FORCE_STOP_STATE; - samsung_dsim_write(dsi, DSIM_ESCMODE_REG, reg); + samsung_dsim_set_stop_state(dsi, false); } dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE; @@ -1463,16 +1472,12 @@ static void samsung_dsim_atomic_disable(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state) { struct samsung_dsim *dsi = bridge_to_dsi(bridge); - u32 reg; if (!(dsi->state & DSIM_STATE_ENABLED)) return; - if (!samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type)) { - reg = samsung_dsim_read(dsi, DSIM_ESCMODE_REG); - reg |= DSIM_FORCE_STOP_STATE; - samsung_dsim_write(dsi, DSIM_ESCMODE_REG, reg); - } + if (!samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type)) + samsung_dsim_set_stop_state(dsi, true); dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE; } @@ -1775,6 +1780,8 @@ static ssize_t samsung_dsim_host_transfer(struct mipi_dsi_host *host, if (ret) return ret; + samsung_dsim_set_stop_state(dsi, false); + ret = mipi_dsi_create_packet(&xfer.packet, msg); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 2fb9bf901a2c..3f479483d7d8 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -262,6 +262,26 @@ static bool drm_kms_helper_enable_hpd(struct drm_device *dev) } #define DRM_OUTPUT_POLL_PERIOD (10*HZ) +static void reschedule_output_poll_work(struct drm_device *dev) +{ + unsigned long delay = DRM_OUTPUT_POLL_PERIOD; + + if (dev->mode_config.delayed_event) + /* + * FIXME: + * + * Use short (1s) delay to handle the initial delayed event. + * This delay should not be needed, but Optimus/nouveau will + * fail in a mysterious way if the delayed event is handled as + * soon as possible like it is done in + * drm_helper_probe_single_connector_modes() in case the poll + * was enabled before. + */ + delay = HZ; + + schedule_delayed_work(&dev->mode_config.output_poll_work, delay); +} + /** * drm_kms_helper_poll_enable - re-enable output polling. * @dev: drm_device @@ -279,37 +299,41 @@ static bool drm_kms_helper_enable_hpd(struct drm_device *dev) */ void drm_kms_helper_poll_enable(struct drm_device *dev) { - bool poll = false; - unsigned long delay = DRM_OUTPUT_POLL_PERIOD; - if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll || dev->mode_config.poll_running) return; - poll = drm_kms_helper_enable_hpd(dev); - - if (dev->mode_config.delayed_event) { - /* - * FIXME: - * - * Use short (1s) delay to handle the initial delayed event. - * This delay should not be needed, but Optimus/nouveau will - * fail in a mysterious way if the delayed event is handled as - * soon as possible like it is done in - * drm_helper_probe_single_connector_modes() in case the poll - * was enabled before. - */ - poll = true; - delay = HZ; - } - - if (poll) - schedule_delayed_work(&dev->mode_config.output_poll_work, delay); + if (drm_kms_helper_enable_hpd(dev) || + dev->mode_config.delayed_event) + reschedule_output_poll_work(dev); dev->mode_config.poll_running = true; } EXPORT_SYMBOL(drm_kms_helper_poll_enable); +/** + * drm_kms_helper_poll_reschedule - reschedule the output polling work + * @dev: drm_device + * + * This function reschedules the output polling work, after polling for a + * connector has been enabled. + * + * Drivers must call this helper after enabling polling for a connector by + * setting %DRM_CONNECTOR_POLL_CONNECT / %DRM_CONNECTOR_POLL_DISCONNECT flags + * in drm_connector::polled. Note that after disabling polling by clearing these + * flags for a connector will stop the output polling work automatically if + * the polling is disabled for all other connectors as well. + * + * The function can be called only after polling has been enabled by calling + * drm_kms_helper_poll_init() / drm_kms_helper_poll_enable(). + */ +void drm_kms_helper_poll_reschedule(struct drm_device *dev) +{ + if (dev->mode_config.poll_running) + reschedule_output_poll_work(dev); +} +EXPORT_SYMBOL(drm_kms_helper_poll_reschedule); + static enum drm_connector_status drm_helper_probe_detect_ctx(struct drm_connector *connector, bool force) { diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c index 1160fa20433b..5eac7032bb5a 100644 --- a/drivers/gpu/drm/i915/display/intel_hotplug.c +++ b/drivers/gpu/drm/i915/display/intel_hotplug.c @@ -211,7 +211,7 @@ intel_hpd_irq_storm_switch_to_polling(struct drm_i915_private *dev_priv) /* Enable polling and queue hotplug re-enabling. */ if (hpd_disabled) { - drm_kms_helper_poll_enable(&dev_priv->drm); + drm_kms_helper_poll_reschedule(&dev_priv->drm); mod_delayed_work(dev_priv->unordered_wq, &dev_priv->display.hotplug.reenable_work, msecs_to_jiffies(HPD_STORM_REENABLE_DELAY)); @@ -649,7 +649,7 @@ static void i915_hpd_poll_init_work(struct work_struct *work) drm_connector_list_iter_end(&conn_iter); if (enabled) - drm_kms_helper_poll_enable(&dev_priv->drm); + drm_kms_helper_poll_reschedule(&dev_priv->drm); mutex_unlock(&dev_priv->drm.mode_config.mutex); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.c b/drivers/gpu/drm/i915/gt/uc/intel_huc.c index ddd146265beb..fa70defcb5b2 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_huc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.c @@ -26,6 +26,7 @@ * The kernel driver is only responsible for loading the HuC firmware and * triggering its security authentication. This is done differently depending * on the platform: + * * - older platforms (from Gen9 to most Gen12s): the load is performed via DMA * and the authentication via GuC * - DG2: load and authentication are both performed via GSC. @@ -33,6 +34,7 @@ * not-DG2 older platforms), while the authentication is done in 2-steps, * a first auth for clear-media workloads via GuC and a second one for all * workloads via GSC. + * * On platforms where the GuC does the authentication, to correctly do so the * HuC binary must be loaded before the GuC one. * Loading the HuC is optional; however, not using the HuC might negatively diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 0ad0c5885ec2..7d8671fdf447 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -443,7 +443,6 @@ static int i915_pcode_init(struct drm_i915_private *i915) static int i915_driver_hw_probe(struct drm_i915_private *dev_priv) { struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); - struct pci_dev *root_pdev; int ret; if (i915_inject_probe_failure(dev_priv)) @@ -557,15 +556,6 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv) intel_bw_init_hw(dev_priv); - /* - * FIXME: Temporary hammer to avoid freezing the machine on our DGFX - * This should be totally removed when we handle the pci states properly - * on runtime PM and on s2idle cases. - */ - root_pdev = pcie_find_root_port(pdev); - if (root_pdev) - pci_d3cold_disable(root_pdev); - return 0; err_opregion: @@ -591,7 +581,6 @@ err_perf: static void i915_driver_hw_remove(struct drm_i915_private *dev_priv) { struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); - struct pci_dev *root_pdev; i915_perf_fini(dev_priv); @@ -599,10 +588,6 @@ static void i915_driver_hw_remove(struct drm_i915_private *dev_priv) if (pdev->msi_enabled) pci_disable_msi(pdev); - - root_pdev = pcie_find_root_port(pdev); - if (root_pdev) - pci_d3cold_enable(root_pdev); } /** @@ -1517,6 +1502,8 @@ static int intel_runtime_suspend(struct device *kdev) { struct drm_i915_private *dev_priv = kdev_to_i915(kdev); struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; + struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); + struct pci_dev *root_pdev; struct intel_gt *gt; int ret, i; @@ -1568,6 +1555,15 @@ static int intel_runtime_suspend(struct device *kdev) drm_err(&dev_priv->drm, "Unclaimed access detected prior to suspending\n"); + /* + * FIXME: Temporary hammer to avoid freezing the machine on our DGFX + * This should be totally removed when we handle the pci states properly + * on runtime PM. + */ + root_pdev = pcie_find_root_port(pdev); + if (root_pdev) + pci_d3cold_disable(root_pdev); + rpm->suspended = true; /* @@ -1606,6 +1602,8 @@ static int intel_runtime_resume(struct device *kdev) { struct drm_i915_private *dev_priv = kdev_to_i915(kdev); struct intel_runtime_pm *rpm = &dev_priv->runtime_pm; + struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); + struct pci_dev *root_pdev; struct intel_gt *gt; int ret, i; @@ -1619,6 +1617,11 @@ static int intel_runtime_resume(struct device *kdev) intel_opregion_notify_adapter(dev_priv, PCI_D0); rpm->suspended = false; + + root_pdev = pcie_find_root_port(pdev); + if (root_pdev) + pci_d3cold_enable(root_pdev); + if (intel_uncore_unclaimed_mmio(&dev_priv->uncore)) drm_dbg(&dev_priv->drm, "Unclaimed access during suspend, bios?\n"); diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c index 58dfb15a8757..e78de99e9933 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c @@ -96,7 +96,7 @@ static int panfrost_read_speedbin(struct device *dev) * keep going without it; any other error means that we are * supposed to read the bin value, but we failed doing so. */ - if (ret != -ENOENT) { + if (ret != -ENOENT && ret != -EOPNOTSUPP) { DRM_DEV_ERROR(dev, "Cannot read speed-bin (%d).", ret); return ret; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c index 82094c137855..c43853597776 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c @@ -497,10 +497,9 @@ static int vmw_user_bo_synccpu_release(struct drm_file *filp, if (!(flags & drm_vmw_synccpu_allow_cs)) { atomic_dec(&vmw_bo->cpu_writers); } - ttm_bo_put(&vmw_bo->tbo); + vmw_user_bo_unref(vmw_bo); } - drm_gem_object_put(&vmw_bo->tbo.base); return ret; } @@ -540,8 +539,7 @@ int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data, return ret; ret = vmw_user_bo_synccpu_grab(vbo, arg->flags); - vmw_bo_unreference(&vbo); - drm_gem_object_put(&vbo->tbo.base); + vmw_user_bo_unref(vbo); if (unlikely(ret != 0)) { if (ret == -ERESTARTSYS || ret == -EBUSY) return -EBUSY; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h index 50a836e70994..1d433fceed3d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h @@ -195,6 +195,14 @@ static inline struct vmw_bo *vmw_bo_reference(struct vmw_bo *buf) return buf; } +static inline void vmw_user_bo_unref(struct vmw_bo *vbo) +{ + if (vbo) { + ttm_bo_put(&vbo->tbo); + drm_gem_object_put(&vbo->tbo.base); + } +} + static inline struct vmw_bo *to_vmw_bo(struct drm_gem_object *gobj) { return container_of((gobj), struct vmw_bo, tbo.base); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 3810a9984a7f..58bfdf203eca 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -1513,4 +1513,16 @@ static inline bool vmw_has_fences(struct vmw_private *vmw) return (vmw_fifo_caps(vmw) & SVGA_FIFO_CAP_FENCE) != 0; } +static inline bool vmw_shadertype_is_valid(enum vmw_sm_type shader_model, + u32 shader_type) +{ + SVGA3dShaderType max_allowed = SVGA3D_SHADERTYPE_PREDX_MAX; + + if (shader_model >= VMW_SM_5) + max_allowed = SVGA3D_SHADERTYPE_MAX; + else if (shader_model >= VMW_SM_4) + max_allowed = SVGA3D_SHADERTYPE_DX10_MAX; + return shader_type >= SVGA3D_SHADERTYPE_MIN && shader_type < max_allowed; +} + #endif diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 6b9aa2b4ef54..98e0723ca6f5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -1164,8 +1164,7 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, } vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB); ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo); - ttm_bo_put(&vmw_bo->tbo); - drm_gem_object_put(&vmw_bo->tbo.base); + vmw_user_bo_unref(vmw_bo); if (unlikely(ret != 0)) return ret; @@ -1221,8 +1220,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM); ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo); - ttm_bo_put(&vmw_bo->tbo); - drm_gem_object_put(&vmw_bo->tbo.base); + vmw_user_bo_unref(vmw_bo); if (unlikely(ret != 0)) return ret; @@ -1992,7 +1990,7 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv, cmd = container_of(header, typeof(*cmd), header); - if (cmd->body.type >= SVGA3D_SHADERTYPE_PREDX_MAX) { + if (!vmw_shadertype_is_valid(VMW_SM_LEGACY, cmd->body.type)) { VMW_DEBUG_USER("Illegal shader type %u.\n", (unsigned int) cmd->body.type); return -EINVAL; @@ -2115,8 +2113,6 @@ vmw_cmd_dx_set_single_constant_buffer(struct vmw_private *dev_priv, SVGA3dCmdHeader *header) { VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetSingleConstantBuffer); - SVGA3dShaderType max_shader_num = has_sm5_context(dev_priv) ? - SVGA3D_NUM_SHADERTYPE : SVGA3D_NUM_SHADERTYPE_DX10; struct vmw_resource *res = NULL; struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); @@ -2133,6 +2129,14 @@ vmw_cmd_dx_set_single_constant_buffer(struct vmw_private *dev_priv, if (unlikely(ret != 0)) return ret; + if (!vmw_shadertype_is_valid(dev_priv->sm_type, cmd->body.type) || + cmd->body.slot >= SVGA3D_DX_MAX_CONSTBUFFERS) { + VMW_DEBUG_USER("Illegal const buffer shader %u slot %u.\n", + (unsigned int) cmd->body.type, + (unsigned int) cmd->body.slot); + return -EINVAL; + } + binding.bi.ctx = ctx_node->ctx; binding.bi.res = res; binding.bi.bt = vmw_ctx_binding_cb; @@ -2141,14 +2145,6 @@ vmw_cmd_dx_set_single_constant_buffer(struct vmw_private *dev_priv, binding.size = cmd->body.sizeInBytes; binding.slot = cmd->body.slot; - if (binding.shader_slot >= max_shader_num || - binding.slot >= SVGA3D_DX_MAX_CONSTBUFFERS) { - VMW_DEBUG_USER("Illegal const buffer shader %u slot %u.\n", - (unsigned int) cmd->body.type, - (unsigned int) binding.slot); - return -EINVAL; - } - vmw_binding_add(ctx_node->staged, &binding.bi, binding.shader_slot, binding.slot); @@ -2207,15 +2203,13 @@ static int vmw_cmd_dx_set_shader_res(struct vmw_private *dev_priv, { VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetShaderResources) = container_of(header, typeof(*cmd), header); - SVGA3dShaderType max_allowed = has_sm5_context(dev_priv) ? - SVGA3D_SHADERTYPE_MAX : SVGA3D_SHADERTYPE_DX10_MAX; u32 num_sr_view = (cmd->header.size - sizeof(cmd->body)) / sizeof(SVGA3dShaderResourceViewId); if ((u64) cmd->body.startView + (u64) num_sr_view > (u64) SVGA3D_DX_MAX_SRVIEWS || - cmd->body.type >= max_allowed) { + !vmw_shadertype_is_valid(dev_priv->sm_type, cmd->body.type)) { VMW_DEBUG_USER("Invalid shader binding.\n"); return -EINVAL; } @@ -2239,8 +2233,6 @@ static int vmw_cmd_dx_set_shader(struct vmw_private *dev_priv, SVGA3dCmdHeader *header) { VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXSetShader); - SVGA3dShaderType max_allowed = has_sm5_context(dev_priv) ? - SVGA3D_SHADERTYPE_MAX : SVGA3D_SHADERTYPE_DX10_MAX; struct vmw_resource *res = NULL; struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context); struct vmw_ctx_bindinfo_shader binding; @@ -2251,8 +2243,7 @@ static int vmw_cmd_dx_set_shader(struct vmw_private *dev_priv, cmd = container_of(header, typeof(*cmd), header); - if (cmd->body.type >= max_allowed || - cmd->body.type < SVGA3D_SHADERTYPE_MIN) { + if (!vmw_shadertype_is_valid(dev_priv->sm_type, cmd->body.type)) { VMW_DEBUG_USER("Illegal shader type %u.\n", (unsigned int) cmd->body.type); return -EINVAL; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index b62207be3363..1489ad73c103 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1665,10 +1665,8 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, err_out: /* vmw_user_lookup_handle takes one ref so does new_fb */ - if (bo) { - vmw_bo_unreference(&bo); - drm_gem_object_put(&bo->tbo.base); - } + if (bo) + vmw_user_bo_unref(bo); if (surface) vmw_surface_unreference(&surface); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c index 7e112319a23c..fb85f244c3d0 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c @@ -451,8 +451,7 @@ int vmw_overlay_ioctl(struct drm_device *dev, void *data, ret = vmw_overlay_update_stream(dev_priv, buf, arg, true); - vmw_bo_unreference(&buf); - drm_gem_object_put(&buf->tbo.base); + vmw_user_bo_unref(buf); out_unlock: mutex_unlock(&overlay->mutex); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c index e7226db8b242..1e81ff2422cf 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c @@ -809,8 +809,7 @@ static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv, shader_type, num_input_sig, num_output_sig, tfile, shader_handle); out_bad_arg: - vmw_bo_unreference(&buffer); - drm_gem_object_put(&buffer->tbo.base); + vmw_user_bo_unref(buffer); return ret; } diff --git a/drivers/hsi/controllers/omap_ssi_core.c b/drivers/hsi/controllers/omap_ssi_core.c index 84ba8b875199..4c1a00f9929e 100644 --- a/drivers/hsi/controllers/omap_ssi_core.c +++ b/drivers/hsi/controllers/omap_ssi_core.c @@ -25,6 +25,7 @@ #include <linux/debugfs.h> #include <linux/pinctrl/consumer.h> #include <linux/pm_runtime.h> +#include <linux/of.h> #include <linux/of_platform.h> #include <linux/hsi/hsi.h> #include <linux/idr.h> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 307477b8a371..ec38c8892158 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -734,6 +734,16 @@ config SENSORS_HIH6130 This driver can also be built as a module. If so, the module will be called hih6130. +config SENSORS_HS3001 + tristate "Renesas HS3001 humidity and temperature sensors" + depends on I2C + help + If you say yes here you get support for the Renesas HS3001, + to HS3004 humidity and temperature sensors. + + This driver can also be built as a module. If so, the module + will be called hs3001. + config SENSORS_IBMAEM tristate "IBM Active Energy Manager temperature/power sensors and control" select IPMI_SI @@ -1951,20 +1961,6 @@ config SENSORS_SFCTEMP This driver can also be built as a module. If so, the module will be called sfctemp. -config SENSORS_SMM665 - tristate "Summit Microelectronics SMM665" - depends on I2C - help - If you say yes here you get support for the hardware monitoring - features of the Summit Microelectronics SMM665/SMM665B Six-Channel - Active DC Output Controller / Monitor. - - Other supported chips are SMM465, SMM665C, SMM764, and SMM766. - Support for those chips is untested. - - This driver can also be built as a module. If so, the module will - be called smm665. - config SENSORS_ADC128D818 tristate "Texas Instruments ADC128D818" depends on I2C diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 3f4b0fda0998..4ac9452b5430 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -86,6 +86,7 @@ obj-$(CONFIG_SENSORS_GSC) += gsc-hwmon.o obj-$(CONFIG_SENSORS_GPIO_FAN) += gpio-fan.o obj-$(CONFIG_SENSORS_GXP_FAN_CTRL) += gxp-fan-ctrl.o obj-$(CONFIG_SENSORS_HIH6130) += hih6130.o +obj-$(CONFIG_SENSORS_HS3001) += hs3001.o obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o obj-$(CONFIG_SENSORS_I5500) += i5500_temp.o obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o @@ -191,7 +192,6 @@ obj-$(CONFIG_SENSORS_SHT3x) += sht3x.o obj-$(CONFIG_SENSORS_SHT4x) += sht4x.o obj-$(CONFIG_SENSORS_SHTC1) += shtc1.o obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o -obj-$(CONFIG_SENSORS_SMM665) += smm665.o obj-$(CONFIG_SENSORS_SMPRO) += smpro-hwmon.o obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c index ffe81e445010..4829f83ff52e 100644 --- a/drivers/hwmon/ad7418.c +++ b/drivers/hwmon/ad7418.c @@ -16,7 +16,7 @@ #include <linux/hwmon-sysfs.h> #include <linux/err.h> #include <linux/mutex.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/delay.h> #include <linux/slab.h> @@ -253,7 +253,7 @@ static int ad7418_probe(struct i2c_client *client) mutex_init(&data->lock); data->client = client; if (dev->of_node) - data->type = (enum chips)of_device_get_match_data(dev); + data->type = (uintptr_t)of_device_get_match_data(dev); else data->type = i2c_match_id(ad7418_id, client)->driver_data; diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c index 1932613ec095..809e830f52a6 100644 --- a/drivers/hwmon/ads7828.c +++ b/drivers/hwmon/ads7828.c @@ -18,7 +18,7 @@ #include <linux/i2c.h> #include <linux/init.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_data/ads7828.h> #include <linux/regmap.h> #include <linux/slab.h> @@ -139,8 +139,7 @@ static int ads7828_probe(struct i2c_client *client) } if (client->dev.of_node) - chip = (enum ads7828_chips) - of_device_get_match_data(&client->dev); + chip = (uintptr_t)of_device_get_match_data(&client->dev); else chip = i2c_match_id(ads7828_device_ids, client)->driver_data; diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c index c0ce88324ea6..03acadc3a6cb 100644 --- a/drivers/hwmon/adt7475.c +++ b/drivers/hwmon/adt7475.c @@ -10,7 +10,6 @@ */ #include <linux/module.h> -#include <linux/of_device.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/i2c.h> @@ -1653,7 +1652,7 @@ static int adt7475_probe(struct i2c_client *client) i2c_set_clientdata(client, data); if (client->dev.of_node) - chip = (enum chips)of_device_get_match_data(&client->dev); + chip = (uintptr_t)of_device_get_match_data(&client->dev); else chip = id->driver_data; diff --git a/drivers/hwmon/as370-hwmon.c b/drivers/hwmon/as370-hwmon.c index fffbf385a57f..316454bd983d 100644 --- a/drivers/hwmon/as370-hwmon.c +++ b/drivers/hwmon/as370-hwmon.c @@ -11,7 +11,8 @@ #include <linux/init.h> #include <linux/io.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/mod_devicetable.h> +#include <linux/platform_device.h> #define CTRL 0x0 #define PD BIT(0) diff --git a/drivers/hwmon/aspeed-pwm-tacho.c b/drivers/hwmon/aspeed-pwm-tacho.c index d11f674e3dc3..997df4b40509 100644 --- a/drivers/hwmon/aspeed-pwm-tacho.c +++ b/drivers/hwmon/aspeed-pwm-tacho.c @@ -12,8 +12,7 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> -#include <linux/of_platform.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/reset.h> diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c index f52a539eb33e..51f9c2db403e 100644 --- a/drivers/hwmon/asus-ec-sensors.c +++ b/drivers/hwmon/asus-ec-sensors.c @@ -340,7 +340,7 @@ static const struct ec_board_info board_info_crosshair_x670e_hero = { .sensors = SENSOR_TEMP_CPU | SENSOR_TEMP_CPU_PACKAGE | SENSOR_TEMP_MB | SENSOR_TEMP_VRM | SENSOR_SET_TEMP_WATER, - .mutex_path = ASUS_HW_ACCESS_MUTEX_RMTW_ASMX, + .mutex_path = ACPI_GLOBAL_LOCK_PSEUDO_PATH, .family = family_amd_600_series, }; diff --git a/drivers/hwmon/bt1-pvt.c b/drivers/hwmon/bt1-pvt.c index 8d402a627306..b77ebac2e0ce 100644 --- a/drivers/hwmon/bt1-pvt.c +++ b/drivers/hwmon/bt1-pvt.c @@ -891,15 +891,8 @@ static struct pvt_hwmon *pvt_create_data(struct platform_device *pdev) static int pvt_request_regs(struct pvt_hwmon *pvt) { struct platform_device *pdev = to_platform_device(pvt->dev); - struct resource *res; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(pvt->dev, "Couldn't find PVT memresource\n"); - return -EINVAL; - } - - pvt->regs = devm_ioremap_resource(pvt->dev, res); + pvt->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(pvt->regs)) return PTR_ERR(pvt->regs); diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c index 1b6ff4712138..fad69ef56c75 100644 --- a/drivers/hwmon/g762.c +++ b/drivers/hwmon/g762.c @@ -39,7 +39,6 @@ #include <linux/kernel.h> #include <linux/clk.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_data/g762.h> #define DRVNAME "g762" diff --git a/drivers/hwmon/gxp-fan-ctrl.c b/drivers/hwmon/gxp-fan-ctrl.c index 2e05bc2f627a..00e057050437 100644 --- a/drivers/hwmon/gxp-fan-ctrl.c +++ b/drivers/hwmon/gxp-fan-ctrl.c @@ -6,7 +6,7 @@ #include <linux/hwmon.h> #include <linux/io.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/mod_devicetable.h> #include <linux/platform_device.h> #define OFS_FAN_INST 0 /* Is 0 because plreg base will be set at INST */ diff --git a/drivers/hwmon/hp-wmi-sensors.c b/drivers/hwmon/hp-wmi-sensors.c index ebe2fb513480..17ae62f88bbf 100644 --- a/drivers/hwmon/hp-wmi-sensors.c +++ b/drivers/hwmon/hp-wmi-sensors.c @@ -435,25 +435,11 @@ static union acpi_object *hp_wmi_get_wobj(const char *guid, u8 instance) /* hp_wmi_wobj_instance_count - find count of WMI object instances */ static u8 hp_wmi_wobj_instance_count(const char *guid) { - u8 hi = HP_WMI_MAX_INSTANCES; - union acpi_object *wobj; - u8 lo = 0; - u8 mid; - - while (lo < hi) { - mid = (lo + hi) / 2; + int count; - wobj = hp_wmi_get_wobj(guid, mid); - if (!wobj) { - hi = mid; - continue; - } + count = wmi_instance_count(guid); - lo = mid + 1; - kfree(wobj); - } - - return lo; + return clamp(count, 0, (int)HP_WMI_MAX_INSTANCES); } static int check_wobj(const union acpi_object *wobj, @@ -1927,7 +1913,7 @@ static bool add_event_handler(struct hp_wmi_sensors *state) static int hp_wmi_sensors_init(struct hp_wmi_sensors *state) { struct hp_wmi_info *connected[HP_WMI_MAX_INSTANCES]; - struct hp_wmi_platform_events *pevents; + struct hp_wmi_platform_events *pevents = NULL; struct device *dev = &state->wdev->dev; struct hp_wmi_info *info; struct device *hwdev; diff --git a/drivers/hwmon/hs3001.c b/drivers/hwmon/hs3001.c new file mode 100644 index 000000000000..ac574e46d069 --- /dev/null +++ b/drivers/hwmon/hs3001.c @@ -0,0 +1,242 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * This is a non-complete driver implementation for the + * HS3001 humidity and temperature sensor and compatibles. It does not include + * the configuration possibilities, where it needs to be set to 'programming mode' + * during power-up. + * + * + * Copyright (C) 2023 SYS TEC electronic AG + * Author: Andre Werner <andre.werner@systec-electronic.com> + */ + +#include <linux/bitfield.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/hwmon.h> +#include <linux/i2c.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/slab.h> +#include <linux/types.h> + +/* Measurement times */ +#define HS3001_WAKEUP_TIME 100 /* us */ +#define HS3001_8BIT_RESOLUTION 550 /* us */ +#define HS3001_10BIT_RESOLUTION 1310 /* us */ +#define HS3001_12BIT_RESOLUTION 4500 /* us */ +#define HS3001_14BIT_RESOLUTION 16900 /* us */ + +#define HS3001_RESPONSE_LENGTH 4 + +#define HS3001_FIXPOINT_ARITH 1000U + +#define HS3001_MASK_HUMIDITY_0X3FFF GENMASK(13, 0) +#define HS3001_MASK_STATUS_0XC0 GENMASK(7, 6) + +/* Definitions for Status Bits of A/D Data */ +#define HS3001_DATA_VALID 0x00 /* Valid Data */ +#define HS3001_DATA_STALE 0x01 /* Stale Data */ + +struct hs3001_data { + struct i2c_client *client; + struct mutex i2c_lock; /* lock for sending i2c commands */ + u32 wait_time; /* in us */ + int temperature; /* in milli degree */ + u32 humidity; /* in milli % */ +}; + +static int hs3001_extract_temperature(u16 raw) +{ + /* fixpoint arithmetic 1 digit */ + u32 temp = (raw >> 2) * HS3001_FIXPOINT_ARITH * 165; + + temp /= (1 << 14) - 1; + + return (int)temp - 40 * HS3001_FIXPOINT_ARITH; +} + +static u32 hs3001_extract_humidity(u16 raw) +{ + u32 hum = (raw & HS3001_MASK_HUMIDITY_0X3FFF) * HS3001_FIXPOINT_ARITH * 100; + + return hum /= (1 << 14) - 1; +} + +static int hs3001_data_fetch_command(struct i2c_client *client, + struct hs3001_data *data) +{ + int ret; + u8 buf[HS3001_RESPONSE_LENGTH]; + u8 hs3001_status; + + ret = i2c_master_recv(client, buf, HS3001_RESPONSE_LENGTH); + if (ret != HS3001_RESPONSE_LENGTH) { + ret = ret < 0 ? ret : -EIO; + dev_dbg(&client->dev, + "Error in i2c communication. Error code: %d.\n", ret); + return ret; + } + + hs3001_status = FIELD_GET(HS3001_MASK_STATUS_0XC0, buf[0]); + if (hs3001_status == HS3001_DATA_STALE) { + dev_dbg(&client->dev, "Sensor busy.\n"); + return -EBUSY; + } + if (hs3001_status != HS3001_DATA_VALID) { + dev_dbg(&client->dev, "Data invalid.\n"); + return -EIO; + } + + data->humidity = + hs3001_extract_humidity(be16_to_cpup((__be16 *)&buf[0])); + data->temperature = + hs3001_extract_temperature(be16_to_cpup((__be16 *)&buf[2])); + + return 0; +} + +static umode_t hs3001_is_visible(const void *data, enum hwmon_sensor_types type, + u32 attr, int channel) +{ + /* Both, humidity and temperature can only be read. */ + return 0444; +} + +static int hs3001_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) +{ + struct hs3001_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int ret; + + mutex_lock(&data->i2c_lock); + ret = i2c_master_send(client, NULL, 0); + if (ret < 0) { + mutex_unlock(&data->i2c_lock); + return ret; + } + + /* + * Sensor needs some time to process measurement depending on + * resolution (ref. datasheet) + */ + fsleep(data->wait_time); + + ret = hs3001_data_fetch_command(client, data); + mutex_unlock(&data->i2c_lock); + + if (ret < 0) + return ret; + + switch (type) { + case hwmon_temp: + switch (attr) { + case hwmon_temp_input: + *val = data->temperature; + break; + default: + return -EINVAL; + } + break; + case hwmon_humidity: + switch (attr) { + case hwmon_humidity_input: + *val = data->humidity; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct hwmon_channel_info *hs3001_info[] = { + HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT), + HWMON_CHANNEL_INFO(humidity, HWMON_H_INPUT), + NULL +}; + +static const struct hwmon_ops hs3001_hwmon_ops = { + .is_visible = hs3001_is_visible, + .read = hs3001_read, +}; + +static const struct hwmon_chip_info hs3001_chip_info = { + .ops = &hs3001_hwmon_ops, + .info = hs3001_info, +}; + +/* device ID table */ +static const struct i2c_device_id hs3001_ids[] = { + { "hs3001", 0 }, + { }, +}; + +MODULE_DEVICE_TABLE(i2c, hs3001_ids); + +static const struct of_device_id hs3001_of_match[] = { + {.compatible = "renesas,hs3001"}, + { }, +}; + +MODULE_DEVICE_TABLE(of, hs3001_of_match); + +static int hs3001_probe(struct i2c_client *client) +{ + struct hs3001_data *data; + struct device *hwmon_dev; + struct device *dev = &client->dev; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -EOPNOTSUPP; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->client = client; + + /* + * Measurement time = wake-up time + measurement time temperature + * + measurement time humidity. This is currently static, because + * enabling programming mode is not supported, yet. + */ + data->wait_time = (HS3001_WAKEUP_TIME + HS3001_14BIT_RESOLUTION + + HS3001_14BIT_RESOLUTION); + + mutex_init(&data->i2c_lock); + + hwmon_dev = devm_hwmon_device_register_with_info(dev, + client->name, + data, + &hs3001_chip_info, + NULL); + + if (IS_ERR(hwmon_dev)) + return dev_err_probe(dev, PTR_ERR(hwmon_dev), + "Unable to register hwmon device.\n"); + + return 0; +} + +static struct i2c_driver hs3001_i2c_driver = { + .driver = { + .name = "hs3001", + .of_match_table = hs3001_of_match, + }, + .probe = hs3001_probe, + .id_table = hs3001_ids, +}; + +module_i2c_driver(hs3001_i2c_driver); + +MODULE_AUTHOR("Andre Werner <andre.werner@systec-electronic.com>"); +MODULE_DESCRIPTION("HS3001 humidity and temperature sensor base driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c index cfd7efef5cdf..d8415d1f21fc 100644 --- a/drivers/hwmon/ina2xx.c +++ b/drivers/hwmon/ina2xx.c @@ -31,7 +31,6 @@ #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/jiffies.h> -#include <linux/of_device.h> #include <linux/of.h> #include <linux/delay.h> #include <linux/util_macros.h> @@ -625,7 +624,7 @@ static int ina2xx_probe(struct i2c_client *client) enum ina2xx_ids chip; if (client->dev.of_node) - chip = (enum ina2xx_ids)of_device_get_match_data(&client->dev); + chip = (uintptr_t)of_device_get_match_data(&client->dev); else chip = i2c_match_id(ina2xx_id, client)->driver_data; diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 5deff5e5f693..fbe86cec6055 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -221,6 +221,10 @@ static bool fix_pwm_polarity; * Super-I/O configuration space. */ #define IT87_REG_VID 0x0a + +/* Interface Selection register on other chips */ +#define IT87_REG_IFSEL 0x0a + /* * The IT8705F and IT8712F earlier than revision 0x08 use register 0x0b * for fan divisors. Later IT8712F revisions must use 16-bit tachometer @@ -1159,28 +1163,66 @@ static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 3, 0); static SENSOR_DEVICE_ATTR_2(temp5_input, S_IRUGO, show_temp, NULL, 4, 0); static SENSOR_DEVICE_ATTR_2(temp6_input, S_IRUGO, show_temp, NULL, 5, 0); +static int get_temp_type(struct it87_data *data, int index) +{ + /* + * 2 is deprecated; + * 3 = thermal diode; + * 4 = thermistor; + * 5 = AMDTSI; + * 6 = Intel PECI; + * 0 = disabled + */ + u8 reg, extra; + int ttype, type = 0; + + /* Detect PECI vs. AMDTSI */ + ttype = 6; + if ((has_temp_peci(data, index)) || data->type == it8721 || + data->type == it8720) { + extra = it87_read_value(data, IT87_REG_IFSEL); + if ((extra & 0x70) == 0x40) + ttype = 5; + } + + reg = it87_read_value(data, IT87_REG_TEMP_ENABLE); + + /* Per chip special detection */ + switch (data->type) { + case it8622: + if (!(reg & 0xc0) && index == 3) + type = ttype; + break; + default: + break; + } + + if (type || index >= 3) + return type; + + extra = it87_read_value(data, IT87_REG_TEMP_EXTRA); + + if ((has_temp_peci(data, index) && (reg >> 6 == index + 1)) || + (has_temp_old_peci(data, index) && (extra & 0x80))) + type = ttype; /* Intel PECI or AMDTSI */ + else if (reg & BIT(index)) + type = 3; /* thermal diode */ + else if (reg & BIT(index + 3)) + type = 4; /* thermistor */ + + return type; +} + static ssize_t show_temp_type(struct device *dev, struct device_attribute *attr, char *buf) { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; struct it87_data *data = it87_update_device(dev); - u8 reg, extra; if (IS_ERR(data)) return PTR_ERR(data); - reg = data->sensor; /* In case value is updated while used */ - extra = data->extra; - - if ((has_temp_peci(data, nr) && (reg >> 6 == nr + 1)) || - (has_temp_old_peci(data, nr) && (extra & 0x80))) - return sprintf(buf, "6\n"); /* Intel PECI */ - if (reg & (1 << nr)) - return sprintf(buf, "3\n"); /* thermal diode */ - if (reg & (8 << nr)) - return sprintf(buf, "4\n"); /* thermistor */ - return sprintf(buf, "0\n"); /* disabled */ + return sprintf(buf, "%d\n", get_temp_type(data, sensor_attr->index)); } static ssize_t set_temp_type(struct device *dev, struct device_attribute *attr, @@ -2313,6 +2355,12 @@ static umode_t it87_temp_is_visible(struct kobject *kobj, if (!(data->has_temp & BIT(i))) return 0; + if (a == 3) { + if (get_temp_type(data, i) == 0) + return 0; + return attr->mode; + } + if (a == 5 && !has_temp_offset(data)) return 0; diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c index a267b11731a8..bae0becfa24b 100644 --- a/drivers/hwmon/k10temp.c +++ b/drivers/hwmon/k10temp.c @@ -65,7 +65,7 @@ static DEFINE_MUTEX(nb_smu_ind_mutex); #define F15H_M60H_HARDWARE_TEMP_CTRL_OFFSET 0xd8200c64 #define F15H_M60H_REPORTED_TEMP_CTRL_OFFSET 0xd8200ca4 -/* Common for Zen CPU families (Family 17h and 18h and 19h) */ +/* Common for Zen CPU families (Family 17h and 18h and 19h and 1Ah) */ #define ZEN_REPORTED_TEMP_CTRL_BASE 0x00059800 #define ZEN_CCD_TEMP(offset, x) (ZEN_REPORTED_TEMP_CTRL_BASE + \ @@ -475,6 +475,10 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id) k10temp_get_ccd_support(pdev, data, 12); break; } + } else if (boot_cpu_data.x86 == 0x1a) { + data->temp_adjust_mask = ZEN_CUR_TEMP_RANGE_SEL_MASK; + data->read_tempreg = read_tempreg_nb_zen; + data->is_zen = true; } else { data->read_htcreg = read_htcreg_pci; data->read_tempreg = read_tempreg_pci; @@ -521,6 +525,8 @@ static const struct pci_device_id k10temp_id_table[] = { { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M60H_DF_F3) }, { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M70H_DF_F3) }, { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_19H_M78H_DF_F3) }, + { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_1AH_M00H_DF_F3) }, + { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_1AH_M20H_DF_F3) }, { PCI_VDEVICE(HYGON, PCI_DEVICE_ID_AMD_17H_DF_F3) }, {} }; diff --git a/drivers/hwmon/lan966x-hwmon.c b/drivers/hwmon/lan966x-hwmon.c index f8658359a098..7247c03e4f44 100644 --- a/drivers/hwmon/lan966x-hwmon.c +++ b/drivers/hwmon/lan966x-hwmon.c @@ -334,24 +334,6 @@ static struct regmap *lan966x_init_regmap(struct platform_device *pdev, return devm_regmap_init_mmio(&pdev->dev, base, ®map_config); } -static void lan966x_clk_disable(void *data) -{ - struct lan966x_hwmon *hwmon = data; - - clk_disable_unprepare(hwmon->clk); -} - -static int lan966x_clk_enable(struct device *dev, struct lan966x_hwmon *hwmon) -{ - int ret; - - ret = clk_prepare_enable(hwmon->clk); - if (ret) - return ret; - - return devm_add_action_or_reset(dev, lan966x_clk_disable, hwmon); -} - static int lan966x_hwmon_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -363,15 +345,11 @@ static int lan966x_hwmon_probe(struct platform_device *pdev) if (!hwmon) return -ENOMEM; - hwmon->clk = devm_clk_get(dev, NULL); + hwmon->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(hwmon->clk)) return dev_err_probe(dev, PTR_ERR(hwmon->clk), "failed to get clock\n"); - ret = lan966x_clk_enable(dev, hwmon); - if (ret) - return dev_err_probe(dev, ret, "failed to enable clock\n"); - hwmon->clk_rate = clk_get_rate(hwmon->clk); hwmon->regmap_pvt = lan966x_init_regmap(pdev, "pvt"); diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index 6972454eb4e0..0878a044dd8e 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c @@ -33,7 +33,7 @@ #include <linux/hwmon.h> #include <linux/err.h> #include <linux/mutex.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/sysfs.h> #include <linux/types.h> @@ -1105,7 +1105,7 @@ static int lm63_probe(struct i2c_client *client) /* Set the device type */ if (client->dev.of_node) - data->kind = (enum chips)of_device_get_match_data(&client->dev); + data->kind = (uintptr_t)of_device_get_match_data(&client->dev); else data->kind = i2c_match_id(lm63_id, client)->driver_data; if (data->kind == lm64) diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 72e634d1b857..5b2ea05c951e 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -13,7 +13,6 @@ #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/err.h> -#include <linux/of_device.h> #include <linux/of.h> #include <linux/regmap.h> #include <linux/util_macros.h> @@ -579,7 +578,7 @@ static int lm75_probe(struct i2c_client *client) enum lm75_type kind; if (client->dev.of_node) - kind = (enum lm75_type)of_device_get_match_data(&client->dev); + kind = (uintptr_t)of_device_get_match_data(&client->dev); else kind = i2c_match_id(lm75_ids, client)->driver_data; diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 8540178f5b74..68c210002357 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -12,7 +12,7 @@ */ #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/jiffies.h> @@ -1559,7 +1559,7 @@ static int lm85_probe(struct i2c_client *client) data->client = client; if (client->dev.of_node) - data->type = (enum chips)of_device_get_match_data(&client->dev); + data->type = (uintptr_t)of_device_get_match_data(&client->dev); else data->type = i2c_match_id(lm85_id, client)->driver_data; mutex_init(&data->update_lock); diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 90101c236f35..e0d7454a301c 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -106,7 +106,7 @@ #include <linux/kstrtox.h> #include <linux/module.h> #include <linux/mutex.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> #include <linux/workqueue.h> @@ -2765,7 +2765,7 @@ static int lm90_probe(struct i2c_client *client) /* Set the device type */ if (client->dev.of_node) - data->kind = (enum chips)of_device_get_match_data(&client->dev); + data->kind = (uintptr_t)of_device_get_match_data(&client->dev); else data->kind = i2c_match_id(lm90_id, client)->driver_data; diff --git a/drivers/hwmon/lochnagar-hwmon.c b/drivers/hwmon/lochnagar-hwmon.c index 6350904a8a8b..5202dddfd61e 100644 --- a/drivers/hwmon/lochnagar-hwmon.c +++ b/drivers/hwmon/lochnagar-hwmon.c @@ -16,7 +16,6 @@ #include <linux/mfd/lochnagar2_regs.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regmap.h> diff --git a/drivers/hwmon/ltq-cputemp.c b/drivers/hwmon/ltq-cputemp.c index 08e09a82acab..f7e4a4ca5239 100644 --- a/drivers/hwmon/ltq-cputemp.c +++ b/drivers/hwmon/ltq-cputemp.c @@ -9,8 +9,9 @@ #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/init.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> #include <lantiq_soc.h> diff --git a/drivers/hwmon/max31730.c b/drivers/hwmon/max31730.c index b1300ca9db1f..7d237db6e57c 100644 --- a/drivers/hwmon/max31730.c +++ b/drivers/hwmon/max31730.c @@ -11,7 +11,6 @@ #include <linux/init.h> #include <linux/hwmon.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/of.h> #include <linux/slab.h> diff --git a/drivers/hwmon/max6621.c b/drivers/hwmon/max6621.c index 7f709fd1af89..af7e62685898 100644 --- a/drivers/hwmon/max6621.c +++ b/drivers/hwmon/max6621.c @@ -12,7 +12,7 @@ #include <linux/i2c.h> #include <linux/init.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regmap.h> #define MAX6621_DRV_NAME "max6621" diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c index caf527154fca..aa7f21ab2395 100644 --- a/drivers/hwmon/max6639.c +++ b/drivers/hwmon/max6639.c @@ -618,11 +618,17 @@ MODULE_DEVICE_TABLE(i2c, max6639_id); static DEFINE_SIMPLE_DEV_PM_OPS(max6639_pm_ops, max6639_suspend, max6639_resume); +static const struct of_device_id max6639_of_match[] = { + { .compatible = "maxim,max6639", }, + { }, +}; + static struct i2c_driver max6639_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "max6639", .pm = pm_sleep_ptr(&max6639_pm_ops), + .of_match_table = max6639_of_match, }, .probe = max6639_probe, .id_table = max6639_id, diff --git a/drivers/hwmon/max6697.c b/drivers/hwmon/max6697.c index 3a67778f111c..7d10dd434f2e 100644 --- a/drivers/hwmon/max6697.c +++ b/drivers/hwmon/max6697.c @@ -15,7 +15,6 @@ #include <linux/hwmon-sysfs.h> #include <linux/err.h> #include <linux/mutex.h> -#include <linux/of_device.h> #include <linux/of.h> #include <linux/platform_data/max6697.h> @@ -703,7 +702,7 @@ static int max6697_probe(struct i2c_client *client) return -ENOMEM; if (client->dev.of_node) - data->type = (enum chips)of_device_get_match_data(&client->dev); + data->type = (uintptr_t)of_device_get_match_data(&client->dev); else data->type = i2c_match_id(max6697_id, client)->driver_data; data->chip = &max6697_chip_data[data->type]; diff --git a/drivers/hwmon/mcp3021.c b/drivers/hwmon/mcp3021.c index 127e15ff3e76..9814eaf24564 100644 --- a/drivers/hwmon/mcp3021.c +++ b/drivers/hwmon/mcp3021.c @@ -20,7 +20,6 @@ #include <linux/err.h> #include <linux/device.h> #include <linux/of.h> -#include <linux/of_device.h> /* Vdd / reference voltage in millivolt */ #define MCP3021_VDD_REF_MAX 5500 diff --git a/drivers/hwmon/mlxreg-fan.c b/drivers/hwmon/mlxreg-fan.c index c2a96468c9b4..a5f89aab3fb4 100644 --- a/drivers/hwmon/mlxreg-fan.c +++ b/drivers/hwmon/mlxreg-fan.c @@ -12,7 +12,7 @@ #include <linux/regmap.h> #include <linux/thermal.h> -#define MLXREG_FAN_MAX_TACHO 14 +#define MLXREG_FAN_MAX_TACHO 24 #define MLXREG_FAN_MAX_PWM 4 #define MLXREG_FAN_PWM_NOT_CONNECTED 0xff #define MLXREG_FAN_MAX_STATE 10 @@ -300,6 +300,16 @@ static const struct hwmon_channel_info * const mlxreg_fan_hwmon_info[] = { HWMON_F_INPUT | HWMON_F_FAULT, HWMON_F_INPUT | HWMON_F_FAULT, HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_INPUT | HWMON_F_FAULT, HWMON_F_INPUT | HWMON_F_FAULT), HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT, diff --git a/drivers/hwmon/nct6775-core.c b/drivers/hwmon/nct6775-core.c index 08ce4984151d..02a71244fc3b 100644 --- a/drivers/hwmon/nct6775-core.c +++ b/drivers/hwmon/nct6775-core.c @@ -33,7 +33,8 @@ * (0xd451) * nct6798d 14 7 7 2+6 0xd428 0xc1 0x5ca3 * (0xd429) - * nct6799d 14 7 7 2+6 0xd802 0xc1 0x5ca3 + * nct6796d-s 18 7 7 6+2 0xd801 0xc1 0x5ca3 + * nct6799d-r 18 7 7 6+2 0xd802 0xc1 0x5ca3 * * #temp lists the number of monitored temperature sources (first value) plus * the number of directly connectable temperature sensors (second value). @@ -79,14 +80,17 @@ static const char * const nct6775_device_names[] = { /* Common and NCT6775 specific data */ -/* Voltage min/max registers for nr=7..14 are in bank 5 */ +/* + * Voltage min/max registers for nr=7..14 are in bank 5 + * min/max: 15-17 for NCT6799 only + */ static const u16 NCT6775_REG_IN_MAX[] = { 0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x554, 0x556, 0x558, 0x55a, - 0x55c, 0x55e, 0x560, 0x562 }; + 0x55c, 0x55e, 0x560, 0x562, 0x564, 0x570, 0x572 }; static const u16 NCT6775_REG_IN_MIN[] = { 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x555, 0x557, 0x559, 0x55b, - 0x55d, 0x55f, 0x561, 0x563 }; + 0x55d, 0x55f, 0x561, 0x563, 0x565, 0x571, 0x573 }; static const u16 NCT6775_REG_IN[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551, 0x552 }; @@ -97,31 +101,23 @@ static const u16 NCT6775_REG_IN[] = { static const u16 NCT6775_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B }; -/* 0..15 voltages, 16..23 fans, 24..29 temperatures, 30..31 intrusion */ - -static const s8 NCT6775_ALARM_BITS[] = { - 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */ - 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */ - -1, /* unused */ - 6, 7, 11, -1, -1, /* fan1..fan5 */ - -1, -1, -1, /* unused */ - 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ - 12, -1 }; /* intrusion0, intrusion1 */ +static const s8 NCT6775_ALARM_BITS[NUM_ALARM_BITS] = { + 0, 1, 2, 3, 8, 21, 20, 16, 17, -1, -1, -1, /* in0-in11 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */ + 6, 7, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */ + 4, 5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */ + 12, -1, /* intr0-intr1 */ +}; static const u16 NCT6775_REG_BEEP[NUM_REG_BEEP] = { 0x56, 0x57, 0x453, 0x4e }; -/* - * 0..14 voltages, 15 global beep enable, 16..23 fans, 24..29 temperatures, - * 30..31 intrusion - */ -static const s8 NCT6775_BEEP_BITS[] = { - 0, 1, 2, 3, 8, 9, 10, 16, /* in0.. in7 */ - 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */ - 21, /* global beep enable */ - 6, 7, 11, 28, -1, /* fan1..fan5 */ - -1, -1, -1, /* unused */ - 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ - 12, -1 }; /* intrusion0, intrusion1 */ +static const s8 NCT6775_BEEP_BITS[NUM_BEEP_BITS] = { + 0, 1, 2, 3, 8, 9, 10, 16, 17, -1, -1, -1, /* in0-in11 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */ + 6, 7, 11, 28, -1, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */ + 4, 5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */ + 12, -1, 21 /* intr0-intr1, beep_en */ +}; /* DC or PWM output fan configuration */ static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 }; @@ -255,25 +251,24 @@ static const u16 NCT6775_REG_TSI_TEMP[] = { 0x669 }; #define NCT6776_REG_FAN_STEP_UP_TIME NCT6775_REG_FAN_STEP_DOWN_TIME #define NCT6776_REG_FAN_STEP_DOWN_TIME NCT6775_REG_FAN_STEP_UP_TIME -static const s8 NCT6776_ALARM_BITS[] = { - 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */ - 17, -1, -1, -1, -1, -1, -1, /* in8..in14 */ - -1, /* unused */ - 6, 7, 11, 10, 23, /* fan1..fan5 */ - -1, -1, -1, /* unused */ - 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ - 12, 9 }; /* intrusion0, intrusion1 */ - -static const u16 NCT6776_REG_BEEP[NUM_REG_BEEP] = { 0xb2, 0xb3, 0xb4, 0xb5 }; - -static const s8 NCT6776_BEEP_BITS[] = { - 0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */ - 8, -1, -1, -1, -1, -1, -1, /* in8..in14 */ - 24, /* global beep enable */ - 25, 26, 27, 28, 29, /* fan1..fan5 */ - -1, -1, -1, /* unused */ - 16, 17, 18, 19, 20, 21, /* temp1..temp6 */ - 30, 31 }; /* intrusion0, intrusion1 */ +static const s8 NCT6776_ALARM_BITS[NUM_ALARM_BITS] = { + 0, 1, 2, 3, 8, 21, 20, 16, 17, -1, -1, -1, /* in0-in11 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */ + 6, 7, 11, 10, 23, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */ + 4, 5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */ + 12, 9, /* intr0-intr1 */ +}; + +/* 0xbf: nct6799 only */ +static const u16 NCT6776_REG_BEEP[NUM_REG_BEEP] = { 0xb2, 0xb3, 0xb4, 0xb5, 0xbf }; + +static const s8 NCT6776_BEEP_BITS[NUM_BEEP_BITS] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, -1, -1, -1, /* in0-in11 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */ + 25, 26, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */ + 16, 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */ + 30, 31, 24 /* intr0-intr1, beep_en */ +}; static const u16 NCT6776_REG_TOLERANCE_H[] = { 0x10c, 0x20c, 0x30c, 0x80c, 0x90c, 0xa0c, 0xb0c }; @@ -337,30 +332,35 @@ static const u16 NCT6776_REG_TSI_TEMP[] = { /* NCT6779 specific data */ +/* + * 15-17 for NCT6799 only, register labels are: + * CPUVC, VIN1, AVSB, 3VCC, VIN0, VIN8, VIN4, 3VSB + * VBAT, VTT, VIN5, VIN6, VIN2, VIN3, VIN7, VIN9 + * VHIF, VIN10 + */ static const u16 NCT6779_REG_IN[] = { 0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487, - 0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e }; + 0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e, 0x48f, + 0x470, 0x471}; static const u16 NCT6779_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B, 0x568 }; -static const s8 NCT6779_ALARM_BITS[] = { - 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */ - 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */ - -1, /* unused */ - 6, 7, 11, 10, 23, /* fan1..fan5 */ - -1, -1, -1, /* unused */ - 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ - 12, 9 }; /* intrusion0, intrusion1 */ - -static const s8 NCT6779_BEEP_BITS[] = { - 0, 1, 2, 3, 4, 5, 6, 7, /* in0.. in7 */ - 8, 9, 10, 11, 12, 13, 14, /* in8..in14 */ - 24, /* global beep enable */ - 25, 26, 27, 28, 29, /* fan1..fan5 */ - -1, -1, -1, /* unused */ - 16, 17, -1, -1, -1, -1, /* temp1..temp6 */ - 30, 31 }; /* intrusion0, intrusion1 */ +static const s8 NCT6779_ALARM_BITS[NUM_ALARM_BITS] = { + 0, 1, 2, 3, 8, 21, 20, 16, 17, 24, 25, 26, /* in0-in11 */ + 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */ + 6, 7, 11, 10, 23, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */ + 4, 5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */ + 12, 9, /* intr0-intr1 */ +}; + +static const s8 NCT6779_BEEP_BITS[NUM_BEEP_BITS] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, /* in0-in11 */ + 12, 13, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */ + 25, 26, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */ + 16, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */ + 30, 31, 24 /* intr0-intr1, beep_en */ +}; static const u16 NCT6779_REG_FAN[] = { 0x4c0, 0x4c2, 0x4c4, 0x4c6, 0x4c8, 0x4ca, 0x4ce }; @@ -448,14 +448,13 @@ static const u16 NCT6791_REG_WEIGHT_DUTY_BASE[NUM_FAN] = { 0, 0x23e }; static const u16 NCT6791_REG_ALARM[NUM_REG_ALARM] = { 0x459, 0x45A, 0x45B, 0x568, 0x45D }; -static const s8 NCT6791_ALARM_BITS[] = { - 0, 1, 2, 3, 8, 21, 20, 16, /* in0.. in7 */ - 17, 24, 25, 26, 27, 28, 29, /* in8..in14 */ - -1, /* unused */ - 6, 7, 11, 10, 23, 33, /* fan1..fan6 */ - -1, -1, /* unused */ - 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ - 12, 9 }; /* intrusion0, intrusion1 */ +static const s8 NCT6791_ALARM_BITS[NUM_ALARM_BITS] = { + 0, 1, 2, 3, 8, 21, 20, 16, 17, 24, 25, 26, /* in0-in11 */ + 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */ + 6, 7, 11, 10, 23, 33, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */ + 4, 5, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */ + 12, 9, /* intr0-intr1 */ +}; /* NCT6792/NCT6793 specific data */ @@ -618,6 +617,28 @@ static const char *const nct6796_temp_label[] = { static const u16 NCT6796_REG_TSI_TEMP[] = { 0x409, 0x40b }; +static const u16 NCT6798_REG_TEMP[] = { + 0x27, 0x150, 0x670, 0x672, 0x674, 0x676, 0x678, 0x67a}; + +static const u16 NCT6798_REG_TEMP_SOURCE[] = { + 0x621, 0x622, 0xc26, 0xc27, 0xc28, 0xc29, 0xc2a, 0xc2b }; + +static const u16 NCT6798_REG_TEMP_MON[] = { + 0x73, 0x75, 0x77, 0x79, 0x7b, 0x7d, 0x4a0 }; +static const u16 NCT6798_REG_TEMP_OVER[] = { + 0x39, 0x155, 0xc1a, 0xc1b, 0xc1c, 0xc1d, 0xc1e, 0xc1f }; +static const u16 NCT6798_REG_TEMP_HYST[] = { + 0x3a, 0x153, 0xc20, 0xc21, 0xc22, 0xc23, 0xc24, 0xc25 }; + +static const u16 NCT6798_REG_TEMP_CRIT[32] = { + 0x135, 0x235, 0x335, 0x835, 0x935, 0xa35, 0xb35, 0 }; + +static const u16 NCT6798_REG_TEMP_ALTERNATE[32] = { + 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0x496, 0, + 0, 0, 0, 0, 0x4a2, 0, 0, 0, + 0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407, + 0x408, 0x419, 0x41a, 0x4f4, 0x4f5 }; + static const char *const nct6798_temp_label[] = { "", "SYSTIN", @@ -656,6 +677,26 @@ static const char *const nct6798_temp_label[] = { #define NCT6798_TEMP_MASK 0xbfff0ffe #define NCT6798_VIRT_TEMP_MASK 0x80000c00 +static const u16 NCT6799_REG_ALARM[NUM_REG_ALARM] = { + 0x459, 0x45A, 0x45B, 0x568, 0x45D, 0xc01 }; + +static const s8 NCT6799_ALARM_BITS[NUM_ALARM_BITS] = { + 0, 1, 2, 3, 8, -1, 20, 16, 17, 24, 25, 26, /* in0-in11 */ + 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */ + 6, 7, 11, 10, 23, 33, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */ + 4, 5, 40, 41, 42, 43, 44, -1, -1, -1, -1, -1, /* temp1-temp12 */ + 12, 9, /* intr0-intr1 */ +}; + +static const s8 NCT6799_BEEP_BITS[NUM_BEEP_BITS] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, /* in0-in11 */ + 12, 13, 14, 15, 34, 35, -1, -1, -1, -1, -1, -1, /* in12-in23 */ + 25, 26, 27, 28, 29, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */ + 16, 17, 18, 19, 20, 21, 22, 23, -1, -1, -1, -1, /* temp1-temp12 */ + 30, 31, 24 /* intr0-intr1, beep_en */ +}; + +/* PECI Calibration only for NCT6799D, not NCT6796D-S */ static const char *const nct6799_temp_label[] = { "", "SYSTIN", @@ -685,8 +726,8 @@ static const char *const nct6799_temp_label[] = { "Agent1 Dimm1", "BYTE_TEMP0", "BYTE_TEMP1", - "PECI Agent 0 Calibration", /* undocumented */ - "PECI Agent 1 Calibration", /* undocumented */ + "PECI/TSI Agent 0 Calibration", + "PECI/TSI Agent 1 Calibration", "", "Virtual_TEMP" }; @@ -763,27 +804,23 @@ static const u16 NCT6106_REG_AUTO_PWM[] = { 0x164, 0x174, 0x184 }; static const u16 NCT6106_REG_ALARM[NUM_REG_ALARM] = { 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d }; -static const s8 NCT6106_ALARM_BITS[] = { - 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */ - 9, -1, -1, -1, -1, -1, -1, /* in8..in14 */ - -1, /* unused */ - 32, 33, 34, -1, -1, /* fan1..fan5 */ - -1, -1, -1, /* unused */ - 16, 17, 18, 19, 20, 21, /* temp1..temp6 */ - 48, -1 /* intrusion0, intrusion1 */ +static const s8 NCT6106_ALARM_BITS[NUM_ALARM_BITS] = { + 0, 1, 2, 3, 4, 5, 7, 8, 9, -1, -1, -1, /* in0-in11 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */ + 32, 33, 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */ + 16, 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */ + 48, -1, /* intr0-intr1 */ }; static const u16 NCT6106_REG_BEEP[NUM_REG_BEEP] = { 0x3c0, 0x3c1, 0x3c2, 0x3c3, 0x3c4 }; -static const s8 NCT6106_BEEP_BITS[] = { - 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */ - 9, 10, 11, 12, -1, -1, -1, /* in8..in14 */ - 32, /* global beep enable */ - 24, 25, 26, 27, 28, /* fan1..fan5 */ - -1, -1, -1, /* unused */ - 16, 17, 18, 19, 20, 21, /* temp1..temp6 */ - 34, -1 /* intrusion0, intrusion1 */ +static const s8 NCT6106_BEEP_BITS[NUM_BEEP_BITS] = { + 0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, /* in0-in11 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */ + 24, 25, 26, 27, 28, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */ + 16, 17, 18, 19, 20, 21, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */ + 34, -1, 32 /* intr0-intr1, beep_en */ }; static const u16 NCT6106_REG_TEMP_ALTERNATE[32] = { @@ -843,24 +880,20 @@ static const u16 NCT6116_REG_AUTO_TEMP[] = { static const u16 NCT6116_REG_AUTO_PWM[] = { 0x164, 0x174, 0x184, 0x1d4, 0x1e4 }; -static const s8 NCT6116_ALARM_BITS[] = { - 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */ - 9, -1, -1, -1, -1, -1, -1, /* in8..in9 */ - -1, /* unused */ - 32, 33, 34, 35, 36, /* fan1..fan5 */ - -1, -1, -1, /* unused */ - 16, 17, 18, -1, -1, -1, /* temp1..temp6 */ - 48, -1 /* intrusion0, intrusion1 */ +static const s8 NCT6116_ALARM_BITS[NUM_ALARM_BITS] = { + 0, 1, 2, 3, 4, 5, 7, 8, 9, -1, -1, -1, /* in0-in11 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */ + 32, 33, 34, 35, 36, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */ + 16, 17, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */ + 48, -1, /* intr0-intr1 */ }; -static const s8 NCT6116_BEEP_BITS[] = { - 0, 1, 2, 3, 4, 5, 7, 8, /* in0.. in7 */ - 9, 10, 11, 12, -1, -1, -1, /* in8..in14 */ - 32, /* global beep enable */ - 24, 25, 26, 27, 28, /* fan1..fan5 */ - -1, -1, -1, /* unused */ - 16, 17, 18, -1, -1, -1, /* temp1..temp6 */ - 34, -1 /* intrusion0, intrusion1 */ +static const s8 NCT6116_BEEP_BITS[NUM_BEEP_BITS] = { + 0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, /* in0-in11 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* in12-in23 */ + 24, 25, 26, 27, 28, -1, -1, -1, -1, -1, -1, -1, /* fan1-fan12 */ + 16, 17, 18, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* temp1-temp12 */ + 34, -1, 32 /* intr0-intr1, beep_en */ }; static const u16 NCT6116_REG_TSI_TEMP[] = { 0x59, 0x5b }; @@ -958,12 +991,12 @@ static const u16 scale_in[15] = { /* * NCT6798 scaling: * CPUVC, IN1, AVSB, 3VCC, IN0, IN8, IN4, 3VSB, VBAT, VTT, IN5, IN6, IN2, - * IN3, IN7 - * Additional scales to be added later: IN9 (800), VHIF (1600) + * IN3, IN7, IN9, VHIF, IN10 + * 15-17 for NCT6799 only */ -static const u16 scale_in_6798[15] = { +static const u16 scale_in_6798[NUM_IN] = { 800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 1600, 1600, 1600, 800, - 800, 800 + 800, 800, 800, 1600, 800 }; static inline long in_from_reg(u8 reg, u8 nr, const u16 *scales) @@ -3862,13 +3895,9 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, case nct6795: case nct6796: case nct6797: - case nct6798: - case nct6799: data->in_num = 15; data->pwm_num = (data->kind == nct6796 || - data->kind == nct6797 || - data->kind == nct6798 || - data->kind == nct6799) ? 7 : 6; + data->kind == nct6797) ? 7 : 6; data->auto_pwm_num = 4; data->has_fan_div = false; data->temp_fixed_num = 6; @@ -3912,16 +3941,6 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, data->temp_mask = NCT6796_TEMP_MASK; data->virt_temp_mask = NCT6796_VIRT_TEMP_MASK; break; - case nct6798: - data->temp_label = nct6798_temp_label; - data->temp_mask = NCT6798_TEMP_MASK; - data->virt_temp_mask = NCT6798_VIRT_TEMP_MASK; - break; - case nct6799: - data->temp_label = nct6799_temp_label; - data->temp_mask = NCT6799_TEMP_MASK; - data->virt_temp_mask = NCT6799_VIRT_TEMP_MASK; - break; } data->REG_CONFIG = NCT6775_REG_CONFIG; @@ -3980,8 +3999,6 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, case nct6795: case nct6796: case nct6797: - case nct6798: - case nct6799: data->REG_TSI_TEMP = NCT6796_REG_TSI_TEMP; num_reg_tsi_temp = ARRAY_SIZE(NCT6796_REG_TSI_TEMP); break; @@ -3990,9 +4007,6 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, break; } - if (data->kind == nct6798 || data->kind == nct6799) - data->scale_in = scale_in_6798; - reg_temp = NCT6779_REG_TEMP; num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP); if (data->kind == nct6791) { @@ -4009,6 +4023,95 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, reg_temp_crit = NCT6779_REG_TEMP_CRIT; break; + case nct6798: + case nct6799: + data->in_num = data->kind == nct6799 ? 18 : 15; + data->scale_in = scale_in_6798; + data->pwm_num = 7; + data->auto_pwm_num = 4; + data->has_fan_div = false; + data->temp_fixed_num = 6; + data->num_temp_alarms = 7; + data->num_temp_beeps = 8; + + data->ALARM_BITS = NCT6799_ALARM_BITS; + data->BEEP_BITS = NCT6799_BEEP_BITS; + + data->fan_from_reg = fan_from_reg_rpm; + data->fan_from_reg_min = fan_from_reg13; + data->target_temp_mask = 0xff; + data->tolerance_mask = 0x07; + data->speed_tolerance_limit = 63; + + switch (data->kind) { + default: + case nct6798: + data->temp_label = nct6798_temp_label; + data->temp_mask = NCT6798_TEMP_MASK; + data->virt_temp_mask = NCT6798_VIRT_TEMP_MASK; + break; + case nct6799: + data->temp_label = nct6799_temp_label; + data->temp_mask = NCT6799_TEMP_MASK; + data->virt_temp_mask = NCT6799_VIRT_TEMP_MASK; + break; + } + + data->REG_CONFIG = NCT6775_REG_CONFIG; + data->REG_VBAT = NCT6775_REG_VBAT; + data->REG_DIODE = NCT6775_REG_DIODE; + data->DIODE_MASK = NCT6775_DIODE_MASK; + data->REG_VIN = NCT6779_REG_IN; + data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN; + data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX; + data->REG_TARGET = NCT6775_REG_TARGET; + data->REG_FAN = NCT6779_REG_FAN; + data->REG_FAN_MODE = NCT6775_REG_FAN_MODE; + data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; + data->REG_FAN_PULSES = NCT6779_REG_FAN_PULSES; + data->FAN_PULSE_SHIFT = NCT6775_FAN_PULSE_SHIFT; + data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME; + data->REG_FAN_TIME[1] = NCT6776_REG_FAN_STEP_UP_TIME; + data->REG_FAN_TIME[2] = NCT6776_REG_FAN_STEP_DOWN_TIME; + data->REG_TOLERANCE_H = NCT6776_REG_TOLERANCE_H; + data->REG_PWM[0] = NCT6775_REG_PWM; + data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT; + data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT; + data->REG_PWM[5] = NCT6791_REG_WEIGHT_DUTY_STEP; + data->REG_PWM[6] = NCT6791_REG_WEIGHT_DUTY_BASE; + data->REG_PWM_READ = NCT6775_REG_PWM_READ; + data->REG_PWM_MODE = NCT6776_REG_PWM_MODE; + data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK; + data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP; + data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM; + data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP; + data->REG_CRITICAL_TEMP_TOLERANCE = NCT6775_REG_CRITICAL_TEMP_TOLERANCE; + data->REG_CRITICAL_PWM_ENABLE = NCT6779_REG_CRITICAL_PWM_ENABLE; + data->CRITICAL_PWM_ENABLE_MASK = NCT6779_CRITICAL_PWM_ENABLE_MASK; + data->REG_CRITICAL_PWM = NCT6779_REG_CRITICAL_PWM; + data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET; + data->REG_TEMP_SOURCE = NCT6798_REG_TEMP_SOURCE; + data->REG_TEMP_SEL = NCT6775_REG_TEMP_SEL; + data->REG_WEIGHT_TEMP_SEL = NCT6791_REG_WEIGHT_TEMP_SEL; + data->REG_WEIGHT_TEMP[0] = NCT6791_REG_WEIGHT_TEMP_STEP; + data->REG_WEIGHT_TEMP[1] = NCT6791_REG_WEIGHT_TEMP_STEP_TOL; + data->REG_WEIGHT_TEMP[2] = NCT6791_REG_WEIGHT_TEMP_BASE; + data->REG_ALARM = NCT6799_REG_ALARM; + data->REG_BEEP = NCT6792_REG_BEEP; + data->REG_TSI_TEMP = NCT6796_REG_TSI_TEMP; + num_reg_tsi_temp = ARRAY_SIZE(NCT6796_REG_TSI_TEMP); + + reg_temp = NCT6798_REG_TEMP; + num_reg_temp = ARRAY_SIZE(NCT6798_REG_TEMP); + reg_temp_mon = NCT6798_REG_TEMP_MON; + num_reg_temp_mon = ARRAY_SIZE(NCT6798_REG_TEMP_MON); + reg_temp_over = NCT6798_REG_TEMP_OVER; + reg_temp_hyst = NCT6798_REG_TEMP_HYST; + reg_temp_config = NCT6779_REG_TEMP_CONFIG; + reg_temp_alternate = NCT6798_REG_TEMP_ALTERNATE; + reg_temp_crit = NCT6798_REG_TEMP_CRIT; + + break; default: return -ENODEV; } diff --git a/drivers/hwmon/nct6775-platform.c b/drivers/hwmon/nct6775-platform.c index a409d7a0b813..81bf03dad6bb 100644 --- a/drivers/hwmon/nct6775-platform.c +++ b/drivers/hwmon/nct6775-platform.c @@ -35,7 +35,7 @@ static const char * const nct6775_sio_names[] __initconst = { "NCT6796D", "NCT6797D", "NCT6798D", - "NCT6799D", + "NCT6796D-S/NCT6799D-R", }; static unsigned short force_id; diff --git a/drivers/hwmon/nct6775.h b/drivers/hwmon/nct6775.h index a84c6ce7275d..296eff99d003 100644 --- a/drivers/hwmon/nct6775.h +++ b/drivers/hwmon/nct6775.h @@ -8,7 +8,7 @@ enum kinds { nct6106, nct6116, nct6775, nct6776, nct6779, nct6791, nct6792, nct6793, nct6795, nct6796, nct6797, nct6798, nct6799 }; enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 }; -#define NUM_TEMP 10 /* Max number of temp attribute sets w/ limits*/ +#define NUM_TEMP 12 /* Max number of temp attribute sets w/ limits*/ #define NUM_TEMP_FIXED 6 /* Max number of fixed temp attribute sets */ #define NUM_TSI_TEMP 8 /* Max number of TSI temp register pairs */ @@ -16,6 +16,7 @@ enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 }; #define NUM_REG_BEEP 5 /* Max number of beep registers */ #define NUM_FAN 7 +#define NUM_IN 18 struct nct6775_data { int addr; /* IO base of hw monitor block */ @@ -97,7 +98,7 @@ struct nct6775_data { /* Register values */ u8 bank; /* current register bank */ u8 in_num; /* number of in inputs we have */ - u8 in[15][3]; /* [0]=in, [1]=in_max, [2]=in_min */ + u8 in[NUM_IN][3]; /* [0]=in, [1]=in_max, [2]=in_min */ const u16 *scale_in; /* internal scaling factors */ unsigned int rpm[NUM_FAN]; u16 fan_min[NUM_FAN]; @@ -166,7 +167,7 @@ struct nct6775_data { u16 have_temp; u16 have_temp_fixed; u16 have_tsi_temp; - u16 have_in; + u32 have_in; /* Remember extra register values over suspend/resume */ u8 vbat; @@ -239,10 +240,25 @@ nct6775_add_attr_group(struct nct6775_data *data, const struct attribute_group * #define NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE 0x28 -#define FAN_ALARM_BASE 16 -#define TEMP_ALARM_BASE 24 -#define INTRUSION_ALARM_BASE 30 -#define BEEP_ENABLE_BASE 15 +/* + * ALARM_BITS and BEEP_BITS store bit-index for the mask of the registers + * loaded into data->alarm and data->beep. + * + * Every input register (IN/TEMP/FAN) must have a corresponding + * ALARM/BEEP bit at the same index BITS[BASE + index] + * Set value to -1 to disable the visibility of that '*_alarm' attribute and + * to pad the bits until the next BASE + * + * Beep has an additional GLOBAL_BEEP_ENABLE bit + */ +#define VIN_ALARM_BASE 0 +#define FAN_ALARM_BASE 24 +#define TEMP_ALARM_BASE 36 +#define INTRUSION_ALARM_BASE 48 +#define BEEP_ENABLE_BASE 50 + +#define NUM_ALARM_BITS (INTRUSION_ALARM_BASE + 4) +#define NUM_BEEP_BITS (BEEP_ENABLE_BASE + 1) /* * Not currently used: diff --git a/drivers/hwmon/nsa320-hwmon.c b/drivers/hwmon/nsa320-hwmon.c index ebe6b031e56f..18076ba7fc14 100644 --- a/drivers/hwmon/nsa320-hwmon.c +++ b/drivers/hwmon/nsa320-hwmon.c @@ -20,8 +20,6 @@ #include <linux/module.h> #include <linux/mutex.h> #include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_platform.h> #include <linux/platform_device.h> /* Tests for error return values rely upon this value being < 0x80 */ @@ -193,7 +191,7 @@ static struct platform_driver nsa320_hwmon_driver = { .probe = nsa320_hwmon_probe, .driver = { .name = "nsa320-hwmon", - .of_match_table = of_match_ptr(of_nsa320_hwmon_match), + .of_match_table = of_nsa320_hwmon_match, }, }; diff --git a/drivers/hwmon/oxp-sensors.c b/drivers/hwmon/oxp-sensors.c index 1e1cc67bcdea..ea9602063eab 100644 --- a/drivers/hwmon/oxp-sensors.c +++ b/drivers/hwmon/oxp-sensors.c @@ -434,23 +434,9 @@ static const struct hwmon_chip_info oxp_ec_chip_info = { /* Initialization logic */ static int oxp_platform_probe(struct platform_device *pdev) { - const struct dmi_system_id *dmi_entry; struct device *dev = &pdev->dev; struct device *hwdev; - /* - * Have to check for AMD processor here because DMI strings are the - * same between Intel and AMD boards, the only way to tell them apart - * is the CPU. - * Intel boards seem to have different EC registers and values to - * read/write. - */ - dmi_entry = dmi_first_match(dmi_table); - if (!dmi_entry || boot_cpu_data.x86_vendor != X86_VENDOR_AMD) - return -ENODEV; - - board = (enum oxp_board)(unsigned long)dmi_entry->driver_data; - hwdev = devm_hwmon_device_register_with_info(dev, "oxpec", NULL, &oxp_ec_chip_info, NULL); @@ -469,6 +455,21 @@ static struct platform_device *oxp_platform_device; static int __init oxp_platform_init(void) { + const struct dmi_system_id *dmi_entry; + + /* + * Have to check for AMD processor here because DMI strings are the + * same between Intel and AMD boards, the only way to tell them apart + * is the CPU. + * Intel boards seem to have different EC registers and values to + * read/write. + */ + dmi_entry = dmi_first_match(dmi_table); + if (!dmi_entry || boot_cpu_data.x86_vendor != X86_VENDOR_AMD) + return -ENODEV; + + board = (enum oxp_board)(unsigned long)dmi_entry->driver_data; + oxp_platform_device = platform_create_bundle(&oxp_platform_driver, oxp_platform_probe, NULL, 0, NULL, 0); diff --git a/drivers/hwmon/peci/dimmtemp.c b/drivers/hwmon/peci/dimmtemp.c index ed968401f93c..ce89da3937a0 100644 --- a/drivers/hwmon/peci/dimmtemp.c +++ b/drivers/hwmon/peci/dimmtemp.c @@ -219,19 +219,21 @@ static int check_populated_dimms(struct peci_dimmtemp *priv) { int chan_rank_max = priv->gen_info->chan_rank_max; int dimm_idx_max = priv->gen_info->dimm_idx_max; - u32 chan_rank_empty = 0; - u32 dimm_mask = 0; - int chan_rank, dimm_idx, ret; + DECLARE_BITMAP(dimm_mask, DIMM_NUMS_MAX); + DECLARE_BITMAP(chan_rank_empty, CHAN_RANK_MAX); + + int chan_rank, dimm_idx, ret, i; u32 pcs; - BUILD_BUG_ON(BITS_PER_TYPE(chan_rank_empty) < CHAN_RANK_MAX); - BUILD_BUG_ON(BITS_PER_TYPE(dimm_mask) < DIMM_NUMS_MAX); if (chan_rank_max * dimm_idx_max > DIMM_NUMS_MAX) { WARN_ONCE(1, "Unsupported number of DIMMs - chan_rank_max: %d, dimm_idx_max: %d", chan_rank_max, dimm_idx_max); return -EINVAL; } + bitmap_zero(dimm_mask, DIMM_NUMS_MAX); + bitmap_zero(chan_rank_empty, CHAN_RANK_MAX); + for (chan_rank = 0; chan_rank < chan_rank_max; chan_rank++) { ret = peci_pcs_read(priv->peci_dev, PECI_PCS_DDR_DIMM_TEMP, chan_rank, &pcs); if (ret) { @@ -242,7 +244,7 @@ static int check_populated_dimms(struct peci_dimmtemp *priv) * detection to be performed at a later point in time. */ if (ret == -EINVAL) { - chan_rank_empty |= BIT(chan_rank); + bitmap_set(chan_rank_empty, chan_rank, 1); continue; } @@ -251,7 +253,7 @@ static int check_populated_dimms(struct peci_dimmtemp *priv) for (dimm_idx = 0; dimm_idx < dimm_idx_max; dimm_idx++) if (__dimm_temp(pcs, dimm_idx)) - dimm_mask |= BIT(chan_rank * dimm_idx_max + dimm_idx); + bitmap_set(dimm_mask, chan_rank * dimm_idx_max + dimm_idx, 1); } /* @@ -260,7 +262,7 @@ static int check_populated_dimms(struct peci_dimmtemp *priv) * host platform boot. Retrying a couple of times lets us make sure * that the state is persistent. */ - if (chan_rank_empty == GENMASK(chan_rank_max - 1, 0)) { + if (bitmap_full(chan_rank_empty, chan_rank_max)) { if (priv->no_dimm_retry_count < NO_DIMM_RETRY_COUNT_MAX) { priv->no_dimm_retry_count++; @@ -274,14 +276,16 @@ static int check_populated_dimms(struct peci_dimmtemp *priv) * It's possible that memory training is not done yet. In this case we * defer the detection to be performed at a later point in time. */ - if (!dimm_mask) { + if (bitmap_empty(dimm_mask, DIMM_NUMS_MAX)) { priv->no_dimm_retry_count = 0; return -EAGAIN; } - dev_dbg(priv->dev, "Scanned populated DIMMs: %#x\n", dimm_mask); + for_each_set_bit(i, dimm_mask, DIMM_NUMS_MAX) { + dev_dbg(priv->dev, "Found DIMM%#x\n", i); + } - bitmap_from_arr32(priv->dimm_mask, &dimm_mask, DIMM_NUMS_MAX); + bitmap_copy(priv->dimm_mask, dimm_mask, DIMM_NUMS_MAX); return 0; } diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig index 270b6336b76d..b4e93bd5835e 100644 --- a/drivers/hwmon/pmbus/Kconfig +++ b/drivers/hwmon/pmbus/Kconfig @@ -317,6 +317,13 @@ config SENSORS_MP2975 This driver can also be built as a module. If so, the module will be called mp2975. +config SENSORS_MP2975_REGULATOR + depends on SENSORS_MP2975 && REGULATOR + bool "Regulator support for MPS MP2975" + help + If you say yes here you get regulator support for MPS MP2975 + Dual Loop Digital Multi-Phase Controller. + config SENSORS_MP5023 tristate "MPS MP5023" help diff --git a/drivers/hwmon/pmbus/acbel-fsg032.c b/drivers/hwmon/pmbus/acbel-fsg032.c index 0a0ef4ce3493..e0c55fd8f3a6 100644 --- a/drivers/hwmon/pmbus/acbel-fsg032.c +++ b/drivers/hwmon/pmbus/acbel-fsg032.c @@ -3,14 +3,51 @@ * Copyright 2023 IBM Corp. */ +#include <linux/debugfs.h> #include <linux/device.h> #include <linux/fs.h> #include <linux/i2c.h> +#include <linux/minmax.h> #include <linux/module.h> #include <linux/pmbus.h> #include <linux/hwmon-sysfs.h> #include "pmbus.h" +#define ACBEL_MFR_FW_REVISION 0xd9 + +static ssize_t acbel_fsg032_debugfs_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) +{ + struct i2c_client *client = file->private_data; + u8 data[I2C_SMBUS_BLOCK_MAX + 2] = { 0 }; + char out[8]; + int rc; + + rc = i2c_smbus_read_block_data(client, ACBEL_MFR_FW_REVISION, data); + if (rc < 0) + return rc; + + rc = snprintf(out, sizeof(out), "%*phN\n", min(rc, 3), data); + return simple_read_from_buffer(buf, count, ppos, out, rc); +} + +static const struct file_operations acbel_debugfs_ops = { + .llseek = noop_llseek, + .read = acbel_fsg032_debugfs_read, + .write = NULL, + .open = simple_open, +}; + +static void acbel_fsg032_init_debugfs(struct i2c_client *client) +{ + struct dentry *debugfs = pmbus_get_debugfs_dir(client); + + if (!debugfs) + return; + + debugfs_create_file("fw_version", 0444, debugfs, client, &acbel_debugfs_ops); +} + static const struct i2c_device_id acbel_fsg032_id[] = { { "acbel_fsg032" }, {} @@ -59,6 +96,7 @@ static int acbel_fsg032_probe(struct i2c_client *client) if (rc) return rc; + acbel_fsg032_init_debugfs(client); return 0; } diff --git a/drivers/hwmon/pmbus/dps920ab.c b/drivers/hwmon/pmbus/dps920ab.c index f7ff3e4650b7..04e0d598a6e5 100644 --- a/drivers/hwmon/pmbus/dps920ab.c +++ b/drivers/hwmon/pmbus/dps920ab.c @@ -9,7 +9,7 @@ #include <linux/debugfs.h> #include <linux/i2c.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include "pmbus.h" struct dps920ab_data { diff --git a/drivers/hwmon/pmbus/ibm-cffps.c b/drivers/hwmon/pmbus/ibm-cffps.c index c791925b8907..1ba4c5e95820 100644 --- a/drivers/hwmon/pmbus/ibm-cffps.c +++ b/drivers/hwmon/pmbus/ibm-cffps.c @@ -13,7 +13,7 @@ #include <linux/leds.h> #include <linux/module.h> #include <linux/mutex.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/pmbus.h> #include "pmbus.h" @@ -489,7 +489,7 @@ static int ibm_cffps_probe(struct i2c_client *client) const struct i2c_device_id *id; if (md) { - vs = (enum versions)md; + vs = (uintptr_t)md; } else { id = i2c_match_id(ibm_cffps_id, client); if (id) diff --git a/drivers/hwmon/pmbus/ir38064.c b/drivers/hwmon/pmbus/ir38064.c index 871c322d3d51..04185be3fdb6 100644 --- a/drivers/hwmon/pmbus/ir38064.c +++ b/drivers/hwmon/pmbus/ir38064.c @@ -6,7 +6,7 @@ * * VOUT_MODE is not supported by the device. The driver fakes VOUT linear16 * mode with exponent value -8 as direct mode with m=256/b=0/R=0. - * + * * The device supports VOUT_PEAK, IOUT_PEAK, and TEMPERATURE_PEAK, however * this driver does not currently support them. */ @@ -16,7 +16,7 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regulator/driver.h> #include "pmbus.h" diff --git a/drivers/hwmon/pmbus/max20730.c b/drivers/hwmon/pmbus/max20730.c index 7bcf27995033..d56ec24764fd 100644 --- a/drivers/hwmon/pmbus/max20730.c +++ b/drivers/hwmon/pmbus/max20730.c @@ -15,7 +15,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/mutex.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/pmbus.h> #include <linux/util_macros.h> #include "pmbus.h" @@ -114,6 +114,7 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf, const struct pmbus_driver_info *info; const struct max20730_data *data; char tbuf[DEBUG_FS_DATA_MAX] = { 0 }; + char *result = tbuf; u16 val; info = pmbus_get_driver_info(psu->client); @@ -148,13 +149,13 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf, >> MAX20730_MFR_DEVSET1_TSTAT_BIT_POS; if (val == 0) - len = strlcpy(tbuf, "2000\n", DEBUG_FS_DATA_MAX); + result = "2000\n"; else if (val == 1) - len = strlcpy(tbuf, "125\n", DEBUG_FS_DATA_MAX); + result = "125\n"; else if (val == 2) - len = strlcpy(tbuf, "62.5\n", DEBUG_FS_DATA_MAX); + result = "62.5\n"; else - len = strlcpy(tbuf, "32\n", DEBUG_FS_DATA_MAX); + result = "32\n"; break; case MAX20730_DEBUGFS_INTERNAL_GAIN: val = (data->mfr_devset1 & MAX20730_MFR_DEVSET1_RGAIN_MASK) @@ -163,35 +164,35 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf, if (data->id == max20734) { /* AN6209 */ if (val == 0) - len = strlcpy(tbuf, "0.8\n", DEBUG_FS_DATA_MAX); + result = "0.8\n"; else if (val == 1) - len = strlcpy(tbuf, "3.2\n", DEBUG_FS_DATA_MAX); + result = "3.2\n"; else if (val == 2) - len = strlcpy(tbuf, "1.6\n", DEBUG_FS_DATA_MAX); + result = "1.6\n"; else - len = strlcpy(tbuf, "6.4\n", DEBUG_FS_DATA_MAX); + result = "6.4\n"; } else if (data->id == max20730 || data->id == max20710) { /* AN6042 or AN6140 */ if (val == 0) - len = strlcpy(tbuf, "0.9\n", DEBUG_FS_DATA_MAX); + result = "0.9\n"; else if (val == 1) - len = strlcpy(tbuf, "3.6\n", DEBUG_FS_DATA_MAX); + result = "3.6\n"; else if (val == 2) - len = strlcpy(tbuf, "1.8\n", DEBUG_FS_DATA_MAX); + result = "1.8\n"; else - len = strlcpy(tbuf, "7.2\n", DEBUG_FS_DATA_MAX); + result = "7.2\n"; } else if (data->id == max20743) { /* AN6042 */ if (val == 0) - len = strlcpy(tbuf, "0.45\n", DEBUG_FS_DATA_MAX); + result = "0.45\n"; else if (val == 1) - len = strlcpy(tbuf, "1.8\n", DEBUG_FS_DATA_MAX); + result = "1.8\n"; else if (val == 2) - len = strlcpy(tbuf, "0.9\n", DEBUG_FS_DATA_MAX); + result = "0.9\n"; else - len = strlcpy(tbuf, "3.6\n", DEBUG_FS_DATA_MAX); + result = "3.6\n"; } else { - len = strlcpy(tbuf, "Not supported\n", DEBUG_FS_DATA_MAX); + result = "Not supported\n"; } break; case MAX20730_DEBUGFS_BOOT_VOLTAGE: @@ -199,26 +200,26 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf, >> MAX20730_MFR_DEVSET1_VBOOT_BIT_POS; if (val == 0) - len = strlcpy(tbuf, "0.6484\n", DEBUG_FS_DATA_MAX); + result = "0.6484\n"; else if (val == 1) - len = strlcpy(tbuf, "0.8984\n", DEBUG_FS_DATA_MAX); + result = "0.8984\n"; else if (val == 2) - len = strlcpy(tbuf, "1.0\n", DEBUG_FS_DATA_MAX); + result = "1.0\n"; else - len = strlcpy(tbuf, "Invalid\n", DEBUG_FS_DATA_MAX); + result = "Invalid\n"; break; case MAX20730_DEBUGFS_OUT_V_RAMP_RATE: val = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_VRATE) >> MAX20730_MFR_DEVSET2_VRATE_BIT_POS; if (val == 0) - len = strlcpy(tbuf, "4\n", DEBUG_FS_DATA_MAX); + result = "4\n"; else if (val == 1) - len = strlcpy(tbuf, "2\n", DEBUG_FS_DATA_MAX); + result = "2\n"; else if (val == 2) - len = strlcpy(tbuf, "1\n", DEBUG_FS_DATA_MAX); + result = "1\n"; else - len = strlcpy(tbuf, "Invalid\n", DEBUG_FS_DATA_MAX); + result = "Invalid\n"; break; case MAX20730_DEBUGFS_OC_PROTECT_MODE: ret = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_OCPM_MASK) @@ -230,13 +231,13 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf, >> MAX20730_MFR_DEVSET2_SS_BIT_POS; if (val == 0) - len = strlcpy(tbuf, "0.75\n", DEBUG_FS_DATA_MAX); + result = "0.75\n"; else if (val == 1) - len = strlcpy(tbuf, "1.5\n", DEBUG_FS_DATA_MAX); + result = "1.5\n"; else if (val == 2) - len = strlcpy(tbuf, "3\n", DEBUG_FS_DATA_MAX); + result = "3\n"; else - len = strlcpy(tbuf, "6\n", DEBUG_FS_DATA_MAX); + result = "6\n"; break; case MAX20730_DEBUGFS_IMAX: ret = (data->mfr_devset2 & MAX20730_MFR_DEVSET2_IMAX_MASK) @@ -287,10 +288,11 @@ static ssize_t max20730_debugfs_read(struct file *file, char __user *buf, "%d.%d\n", ret / 10000, ret % 10000); break; default: - len = strlcpy(tbuf, "Invalid\n", DEBUG_FS_DATA_MAX); + result = "Invalid\n"; } - return simple_read_from_buffer(buf, count, ppos, tbuf, len); + len = strlen(result); + return simple_read_from_buffer(buf, count, ppos, result, len); } static const struct file_operations max20730_fops = { @@ -714,7 +716,7 @@ static int max20730_probe(struct i2c_client *client) } if (client->dev.of_node) - chip_id = (enum chips)of_device_get_match_data(dev); + chip_id = (uintptr_t)of_device_get_match_data(dev); else chip_id = i2c_match_id(max20730_id, client)->driver_data; diff --git a/drivers/hwmon/pmbus/mp2975.c b/drivers/hwmon/pmbus/mp2975.c index 2109b0458a8b..26ba50633100 100644 --- a/drivers/hwmon/pmbus/mp2975.c +++ b/drivers/hwmon/pmbus/mp2975.c @@ -10,6 +10,7 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/of_device.h> #include "pmbus.h" /* Vendor specific registers. */ @@ -34,6 +35,8 @@ #define MP2975_MFR_OVP_TH_SET 0xe5 #define MP2975_MFR_UVP_SET 0xe6 +#define MP2973_MFR_RESO_SET 0xc7 + #define MP2975_VOUT_FORMAT BIT(15) #define MP2975_VID_STEP_SEL_R1 BIT(4) #define MP2975_IMVP9_EN_R1 BIT(13) @@ -48,43 +51,80 @@ #define MP2975_SENSE_AMPL_HALF 2 #define MP2975_VIN_UV_LIMIT_UNIT 8 +#define MP2973_VOUT_FORMAT_R1 GENMASK(7, 6) +#define MP2973_VOUT_FORMAT_R2 GENMASK(4, 3) +#define MP2973_VOUT_FORMAT_DIRECT_R1 BIT(7) +#define MP2973_VOUT_FORMAT_LINEAR_R1 BIT(6) +#define MP2973_VOUT_FORMAT_DIRECT_R2 BIT(4) +#define MP2973_VOUT_FORMAT_LINEAR_R2 BIT(3) + +#define MP2973_MFR_VR_MULTI_CONFIG_R1 0x0d +#define MP2973_MFR_VR_MULTI_CONFIG_R2 0x1d +#define MP2973_VID_STEP_SEL_R1 BIT(4) +#define MP2973_IMVP9_EN_R1 BIT(14) +#define MP2973_VID_STEP_SEL_R2 BIT(3) +#define MP2973_IMVP9_EN_R2 BIT(13) + +#define MP2973_MFR_OCP_TOTAL_SET 0x5f +#define MP2973_OCP_TOTAL_CUR_MASK GENMASK(6, 0) +#define MP2973_MFR_OCP_LEVEL_RES BIT(15) + +#define MP2973_MFR_READ_IOUT_PK 0x90 +#define MP2973_MFR_READ_POUT_PK 0x91 + #define MP2975_MAX_PHASE_RAIL1 8 #define MP2975_MAX_PHASE_RAIL2 4 + +#define MP2973_MAX_PHASE_RAIL1 14 +#define MP2973_MAX_PHASE_RAIL2 6 + +#define MP2971_MAX_PHASE_RAIL1 8 +#define MP2971_MAX_PHASE_RAIL2 3 + #define MP2975_PAGE_NUM 2 #define MP2975_RAIL2_FUNC (PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | \ PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | \ PMBUS_HAVE_POUT | PMBUS_PHASE_VIRTUAL) +enum chips { + mp2971, mp2973, mp2975 +}; + +static const int mp2975_max_phases[][MP2975_PAGE_NUM] = { + [mp2975] = { MP2975_MAX_PHASE_RAIL1, MP2975_MAX_PHASE_RAIL2 }, + [mp2973] = { MP2973_MAX_PHASE_RAIL1, MP2973_MAX_PHASE_RAIL2 }, + [mp2971] = { MP2971_MAX_PHASE_RAIL1, MP2971_MAX_PHASE_RAIL2 }, +}; + struct mp2975_data { struct pmbus_driver_info info; + enum chips chip_id; int vout_scale; + int max_phases[MP2975_PAGE_NUM]; int vid_step[MP2975_PAGE_NUM]; int vref[MP2975_PAGE_NUM]; int vref_off[MP2975_PAGE_NUM]; int vout_max[MP2975_PAGE_NUM]; int vout_ov_fixed[MP2975_PAGE_NUM]; - int vout_format[MP2975_PAGE_NUM]; int curr_sense_gain[MP2975_PAGE_NUM]; }; -#define to_mp2975_data(x) container_of(x, struct mp2975_data, info) +static const struct i2c_device_id mp2975_id[] = { + {"mp2971", mp2971}, + {"mp2973", mp2973}, + {"mp2975", mp2975}, + {} +}; -static int mp2975_read_byte_data(struct i2c_client *client, int page, int reg) -{ - switch (reg) { - case PMBUS_VOUT_MODE: - /* - * Enforce VOUT direct format, since device allows to set the - * different formats for the different rails. Conversion from - * VID to direct provided by driver internally, in case it is - * necessary. - */ - return PB_VOUT_MODE_DIRECT; - default: - return -ENODATA; - } -} +MODULE_DEVICE_TABLE(i2c, mp2975_id); + +static const struct regulator_desc __maybe_unused mp2975_reg_desc[] = { + PMBUS_REGULATOR("vout", 0), + PMBUS_REGULATOR("vout", 1), +}; + +#define to_mp2975_data(x) container_of(x, struct mp2975_data, info) static int mp2975_read_word_helper(struct i2c_client *client, int page, int phase, u8 reg, @@ -117,6 +157,41 @@ mp2975_vid2direct(int vrf, int val) return 0; } +#define MAX_LIN_MANTISSA (1023 * 1000) +#define MIN_LIN_MANTISSA (511 * 1000) + +/* Converts a milli-unit DIRECT value to LINEAR11 format */ +static u16 mp2975_data2reg_linear11(s64 val) +{ + s16 exponent = 0, mantissa; + bool negative = false; + + /* simple case */ + if (val == 0) + return 0; + + /* Reduce large mantissa until it fits into 10 bit */ + while (val >= MAX_LIN_MANTISSA && exponent < 15) { + exponent++; + val >>= 1; + } + /* Increase small mantissa to improve precision */ + while (val < MIN_LIN_MANTISSA && exponent > -15) { + exponent--; + val <<= 1; + } + + /* Convert mantissa from milli-units to units */ + mantissa = clamp_val(DIV_ROUND_CLOSEST_ULL(val, 1000), 0, 0x3ff); + + /* restore sign */ + if (negative) + mantissa = -mantissa; + + /* Convert to 5 bit exponent, 11 bit mantissa */ + return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800); +} + static int mp2975_read_phase(struct i2c_client *client, struct mp2975_data *data, int page, int phase, u8 reg) @@ -214,6 +289,89 @@ mp2975_read_phases(struct i2c_client *client, struct mp2975_data *data, return ret; } +static int mp2973_read_word_data(struct i2c_client *client, int page, + int phase, int reg) +{ + const struct pmbus_driver_info *info = pmbus_get_driver_info(client); + struct mp2975_data *data = to_mp2975_data(info); + int ret; + + switch (reg) { + case PMBUS_OT_FAULT_LIMIT: + ret = mp2975_read_word_helper(client, page, phase, reg, + GENMASK(7, 0)); + break; + case PMBUS_VIN_OV_FAULT_LIMIT: + ret = mp2975_read_word_helper(client, page, phase, reg, + GENMASK(7, 0)); + if (ret < 0) + return ret; + + ret = DIV_ROUND_CLOSEST(ret, MP2975_VIN_UV_LIMIT_UNIT); + break; + case PMBUS_VOUT_OV_FAULT_LIMIT: + /* + * MP2971 and mp2973 only supports tracking (ovp1) mode. + */ + ret = mp2975_read_word_helper(client, page, phase, + MP2975_MFR_OVP_TH_SET, + GENMASK(2, 0)); + if (ret < 0) + return ret; + + ret = data->vout_max[page] + 50 * (ret + 1); + break; + case PMBUS_VOUT_UV_FAULT_LIMIT: + ret = mp2975_read_word_helper(client, page, phase, reg, + GENMASK(8, 0)); + if (ret < 0) + return ret; + ret = mp2975_vid2direct(info->vrm_version[page], ret); + break; + case PMBUS_VIRT_READ_POUT_MAX: + ret = pmbus_read_word_data(client, page, phase, + MP2973_MFR_READ_POUT_PK); + break; + case PMBUS_VIRT_READ_IOUT_MAX: + ret = pmbus_read_word_data(client, page, phase, + MP2973_MFR_READ_IOUT_PK); + break; + case PMBUS_IOUT_OC_FAULT_LIMIT: + ret = mp2975_read_word_helper(client, page, phase, + MP2973_MFR_OCP_TOTAL_SET, + GENMASK(15, 0)); + if (ret < 0) + return ret; + + if (ret & MP2973_MFR_OCP_LEVEL_RES) + ret = 2 * (ret & MP2973_OCP_TOTAL_CUR_MASK); + else + ret = ret & MP2973_OCP_TOTAL_CUR_MASK; + + ret = mp2975_data2reg_linear11(ret * info->phases[page] * 1000); + break; + case PMBUS_UT_WARN_LIMIT: + case PMBUS_UT_FAULT_LIMIT: + case PMBUS_VIN_UV_WARN_LIMIT: + case PMBUS_VIN_UV_FAULT_LIMIT: + case PMBUS_VOUT_UV_WARN_LIMIT: + case PMBUS_VOUT_OV_WARN_LIMIT: + case PMBUS_VIN_OV_WARN_LIMIT: + case PMBUS_IIN_OC_FAULT_LIMIT: + case PMBUS_IOUT_OC_LV_FAULT_LIMIT: + case PMBUS_IOUT_OC_WARN_LIMIT: + case PMBUS_IOUT_UC_FAULT_LIMIT: + case PMBUS_POUT_OP_FAULT_LIMIT: + case PMBUS_POUT_OP_WARN_LIMIT: + case PMBUS_PIN_OP_WARN_LIMIT: + return -ENXIO; + default: + return -ENODATA; + } + + return ret; +} + static int mp2975_read_word_data(struct i2c_client *client, int page, int phase, int reg) { @@ -222,6 +380,11 @@ static int mp2975_read_word_data(struct i2c_client *client, int page, int ret; switch (reg) { + case PMBUS_STATUS_WORD: + /* MP2973 & MP2971 return PGOOD instead of PB_STATUS_POWER_GOOD_N. */ + ret = pmbus_read_word_data(client, page, phase, reg); + ret ^= PB_STATUS_POWER_GOOD_N; + break; case PMBUS_OT_FAULT_LIMIT: ret = mp2975_read_word_helper(client, page, phase, reg, GENMASK(7, 0)); @@ -260,24 +423,6 @@ static int mp2975_read_word_data(struct i2c_client *client, int page, ret = DIV_ROUND_CLOSEST(data->vref[page] * 10 - 50 * (ret + 1) * data->vout_scale, 10); break; - case PMBUS_READ_VOUT: - ret = mp2975_read_word_helper(client, page, phase, reg, - GENMASK(11, 0)); - if (ret < 0) - return ret; - - /* - * READ_VOUT can be provided in VID or direct format. The - * format type is specified by bit 15 of the register - * MP2975_MFR_DC_LOOP_CTRL. The driver enforces VOUT direct - * format, since device allows to set the different formats for - * the different rails and also all VOUT limits registers are - * provided in a direct format. In case format is VID - convert - * to direct. - */ - if (data->vout_format[page] == vid) - ret = mp2975_vid2direct(info->vrm_version[page], ret); - break; case PMBUS_VIRT_READ_POUT_MAX: ret = mp2975_read_word_helper(client, page, phase, MP2975_MFR_READ_POUT_PK, @@ -326,25 +471,25 @@ static int mp2975_read_word_data(struct i2c_client *client, int page, return ret; } -static int mp2975_identify_multiphase_rail2(struct i2c_client *client) +static int mp2975_identify_multiphase_rail2(struct i2c_client *client, + struct mp2975_data *data) { int ret; /* - * Identify multiphase for rail 2 - could be from 0 to 4. + * Identify multiphase for rail 2 - could be from 0 to data->max_phases[1]. * In case phase number is zero – only page zero is supported */ ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2); if (ret < 0) return ret; - /* Identify multiphase for rail 2 - could be from 0 to 4. */ ret = i2c_smbus_read_word_data(client, MP2975_MFR_VR_MULTI_CONFIG_R2); if (ret < 0) return ret; ret &= GENMASK(2, 0); - return (ret >= 4) ? 4 : ret; + return (ret >= data->max_phases[1]) ? data->max_phases[1] : ret; } static void mp2975_set_phase_rail1(struct pmbus_driver_info *info) @@ -375,7 +520,7 @@ mp2975_identify_multiphase(struct i2c_client *client, struct mp2975_data *data, if (ret < 0) return ret; - /* Identify multiphase for rail 1 - could be from 1 to 8. */ + /* Identify multiphase for rail 1 - could be from 1 to data->max_phases[0]. */ ret = i2c_smbus_read_word_data(client, MP2975_MFR_VR_MULTI_CONFIG_R1); if (ret <= 0) return ret; @@ -383,21 +528,23 @@ mp2975_identify_multiphase(struct i2c_client *client, struct mp2975_data *data, info->phases[0] = ret & GENMASK(3, 0); /* - * The device provides a total of 8 PWM pins, and can be configured + * The device provides a total of $n PWM pins, and can be configured * to different phase count applications for rail 1 and rail 2. - * Rail 1 can be set to 8 phases, while rail 2 can only be set to 4 - * phases at most. When rail 1’s phase count is configured as 0, rail + * Rail 1 can be set to $n phases, while rail 2 can be set to less than + * that. When rail 1’s phase count is configured as 0, rail * 1 operates with 1-phase DCM. When rail 2 phase count is configured * as 0, rail 2 is disabled. */ - if (info->phases[0] > MP2975_MAX_PHASE_RAIL1) + if (info->phases[0] > data->max_phases[0]) return -EINVAL; - mp2975_set_phase_rail1(info); - num_phases2 = min(MP2975_MAX_PHASE_RAIL1 - info->phases[0], - MP2975_MAX_PHASE_RAIL2); - if (info->phases[1] && info->phases[1] <= num_phases2) - mp2975_set_phase_rail2(info, num_phases2); + if (data->chip_id == mp2975) { + mp2975_set_phase_rail1(info); + num_phases2 = min(data->max_phases[0] - info->phases[0], + data->max_phases[1]); + if (info->phases[1] && info->phases[1] <= num_phases2) + mp2975_set_phase_rail2(info, num_phases2); + } return 0; } @@ -451,6 +598,35 @@ mp2975_identify_rails_vid(struct i2c_client *client, struct mp2975_data *data, MP2975_MFR_VR_MULTI_CONFIG_R2, 1, MP2975_IMVP9_EN_R2, MP2975_VID_STEP_SEL_R2); + + return ret; +} + +static int +mp2973_identify_rails_vid(struct i2c_client *client, struct mp2975_data *data, + struct pmbus_driver_info *info) +{ + int ret; + + ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2); + if (ret < 0) + return ret; + + /* Identify VID mode for rail 1. */ + ret = mp2975_identify_vid(client, data, info, + MP2973_MFR_VR_MULTI_CONFIG_R1, 0, + MP2973_IMVP9_EN_R1, MP2973_VID_STEP_SEL_R1); + + if (ret < 0) + return ret; + + /* Identify VID mode for rail 2, if connected. */ + if (info->phases[1]) + ret = mp2975_identify_vid(client, data, info, + MP2973_MFR_VR_MULTI_CONFIG_R2, 1, + MP2973_IMVP9_EN_R2, + MP2973_VID_STEP_SEL_R2); + return ret; } @@ -565,20 +741,37 @@ mp2975_vout_max_get(struct i2c_client *client, struct mp2975_data *data, } static int -mp2975_identify_vout_format(struct i2c_client *client, - struct mp2975_data *data, int page) +mp2975_set_vout_format(struct i2c_client *client, + struct mp2975_data *data, int page) { - int ret; + int ret, i; - ret = i2c_smbus_read_word_data(client, MP2975_MFR_DC_LOOP_CTRL); - if (ret < 0) - return ret; - - if (ret & MP2975_VOUT_FORMAT) - data->vout_format[page] = vid; - else - data->vout_format[page] = direct; - return 0; + /* Enable DIRECT VOUT format 1mV/LSB */ + if (data->chip_id == mp2975) { + ret = i2c_smbus_read_word_data(client, MP2975_MFR_DC_LOOP_CTRL); + if (ret < 0) + return ret; + if (ret & MP2975_VOUT_FORMAT) { + ret &= ~MP2975_VOUT_FORMAT; + ret = i2c_smbus_write_word_data(client, MP2975_MFR_DC_LOOP_CTRL, ret); + } + } else { + ret = i2c_smbus_read_word_data(client, MP2973_MFR_RESO_SET); + if (ret < 0) + return ret; + i = ret; + + if (page == 0) { + i &= ~MP2973_VOUT_FORMAT_R1; + i |= MP2973_VOUT_FORMAT_DIRECT_R1; + } else { + i &= ~MP2973_VOUT_FORMAT_R2; + i |= MP2973_VOUT_FORMAT_DIRECT_R2; + } + if (i != ret) + ret = i2c_smbus_write_word_data(client, MP2973_MFR_RESO_SET, i); + } + return ret; } static int @@ -600,7 +793,7 @@ mp2975_vout_ov_scale_get(struct i2c_client *client, struct mp2975_data *data, if (ret < 0) return ret; thres_dev = ret & MP2975_PRT_THRES_DIV_OV_EN ? MP2975_PROT_DEV_OV_ON : - MP2975_PROT_DEV_OV_OFF; + MP2975_PROT_DEV_OV_OFF; /* Select the gain of remote sense amplifier. */ ret = i2c_smbus_read_word_data(client, PMBUS_VOUT_SCALE_LOOP); @@ -624,10 +817,10 @@ mp2975_vout_per_rail_config_get(struct i2c_client *client, for (i = 0; i < data->info.pages; i++) { ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i); if (ret < 0) - return ret; + continue; - /* Obtain voltage reference offsets. */ - ret = mp2975_vref_offset_get(client, data, i); + /* Set VOUT format for READ_VOUT command : direct. */ + ret = mp2975_set_vout_format(client, data, i); if (ret < 0) return ret; @@ -636,12 +829,12 @@ mp2975_vout_per_rail_config_get(struct i2c_client *client, if (ret < 0) return ret; - /* - * Get VOUT format for READ_VOUT command : VID or direct. - * Pages on same device can be configured with different - * formats. - */ - ret = mp2975_identify_vout_format(client, data, i); + /* Skip if reading Vref is unsupported */ + if (data->chip_id != mp2975) + continue; + + /* Obtain voltage reference offsets. */ + ret = mp2975_vref_offset_get(client, data, i); if (ret < 0) return ret; @@ -676,8 +869,32 @@ static struct pmbus_driver_info mp2975_info = { PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT | PMBUS_PHASE_VIRTUAL, - .read_byte_data = mp2975_read_byte_data, .read_word_data = mp2975_read_word_data, +#if IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR) + .num_regulators = 1, + .reg_desc = mp2975_reg_desc, +#endif +}; + +static struct pmbus_driver_info mp2973_info = { + .pages = 1, + .format[PSC_VOLTAGE_IN] = linear, + .format[PSC_VOLTAGE_OUT] = direct, + .format[PSC_TEMPERATURE] = linear, + .format[PSC_CURRENT_IN] = linear, + .format[PSC_CURRENT_OUT] = linear, + .format[PSC_POWER] = linear, + .m[PSC_VOLTAGE_OUT] = 1, + .R[PSC_VOLTAGE_OUT] = 3, + .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | + PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | + PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT | + PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT, + .read_word_data = mp2973_read_word_data, +#if IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR) + .num_regulators = 1, + .reg_desc = mp2975_reg_desc, +#endif }; static int mp2975_probe(struct i2c_client *client) @@ -691,11 +908,23 @@ static int mp2975_probe(struct i2c_client *client) if (!data) return -ENOMEM; - memcpy(&data->info, &mp2975_info, sizeof(*info)); + if (client->dev.of_node) + data->chip_id = (enum chips)(unsigned long)of_device_get_match_data(&client->dev); + else + data->chip_id = i2c_match_id(mp2975_id, client)->driver_data; + + memcpy(data->max_phases, mp2975_max_phases[data->chip_id], + sizeof(data->max_phases)); + + if (data->chip_id == mp2975) + memcpy(&data->info, &mp2975_info, sizeof(*info)); + else + memcpy(&data->info, &mp2973_info, sizeof(*info)); + info = &data->info; /* Identify multiphase configuration for rail 2. */ - ret = mp2975_identify_multiphase_rail2(client); + ret = mp2975_identify_multiphase_rail2(client, data); if (ret < 0) return ret; @@ -704,6 +933,8 @@ static int mp2975_probe(struct i2c_client *client) data->info.pages = MP2975_PAGE_NUM; data->info.phases[1] = ret; data->info.func[1] = MP2975_RAIL2_FUNC; + if (IS_ENABLED(CONFIG_SENSORS_MP2975_REGULATOR)) + data->info.num_regulators = MP2975_PAGE_NUM; } /* Identify multiphase configuration. */ @@ -711,25 +942,32 @@ static int mp2975_probe(struct i2c_client *client) if (ret) return ret; - /* Identify VID setting per rail. */ - ret = mp2975_identify_rails_vid(client, data, info); - if (ret < 0) - return ret; + if (data->chip_id == mp2975) { + /* Identify VID setting per rail. */ + ret = mp2975_identify_rails_vid(client, data, info); + if (ret < 0) + return ret; - /* Obtain current sense gain of power stage. */ - ret = mp2975_current_sense_gain_get(client, data); - if (ret) - return ret; + /* Obtain current sense gain of power stage. */ + ret = mp2975_current_sense_gain_get(client, data); + if (ret) + return ret; - /* Obtain voltage reference values. */ - ret = mp2975_vref_get(client, data, info); - if (ret) - return ret; + /* Obtain voltage reference values. */ + ret = mp2975_vref_get(client, data, info); + if (ret) + return ret; - /* Obtain vout over-voltage scales. */ - ret = mp2975_vout_ov_scale_get(client, data, info); - if (ret < 0) - return ret; + /* Obtain vout over-voltage scales. */ + ret = mp2975_vout_ov_scale_get(client, data, info); + if (ret < 0) + return ret; + } else { + /* Identify VID setting per rail. */ + ret = mp2973_identify_rails_vid(client, data, info); + if (ret < 0) + return ret; + } /* Obtain offsets, maximum and format for vout. */ ret = mp2975_vout_per_rail_config_get(client, data, info); @@ -739,15 +977,10 @@ static int mp2975_probe(struct i2c_client *client) return pmbus_do_probe(client, info); } -static const struct i2c_device_id mp2975_id[] = { - {"mp2975", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, mp2975_id); - static const struct of_device_id __maybe_unused mp2975_of_match[] = { - {.compatible = "mps,mp2975"}, + {.compatible = "mps,mp2971", .data = (void *)mp2971}, + {.compatible = "mps,mp2973", .data = (void *)mp2973}, + {.compatible = "mps,mp2975", .data = (void *)mp2975}, {} }; MODULE_DEVICE_TABLE(of, mp2975_of_match); diff --git a/drivers/hwmon/pmbus/mp5023.c b/drivers/hwmon/pmbus/mp5023.c index c4c4324d2b74..21acb7fd9a1a 100644 --- a/drivers/hwmon/pmbus/mp5023.c +++ b/drivers/hwmon/pmbus/mp5023.c @@ -5,7 +5,7 @@ #include <linux/i2c.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include "pmbus.h" static struct pmbus_driver_info mp5023_info = { diff --git a/drivers/hwmon/pmbus/mpq7932.c b/drivers/hwmon/pmbus/mpq7932.c index 865d42edda1a..6c62f01da7c6 100644 --- a/drivers/hwmon/pmbus/mpq7932.c +++ b/drivers/hwmon/pmbus/mpq7932.c @@ -12,7 +12,7 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/pmbus.h> #include "pmbus.h" diff --git a/drivers/hwmon/pmbus/pli1209bc.c b/drivers/hwmon/pmbus/pli1209bc.c index 7d8bd3167b21..c95433790b11 100644 --- a/drivers/hwmon/pmbus/pli1209bc.c +++ b/drivers/hwmon/pmbus/pli1209bc.c @@ -5,6 +5,7 @@ * Copyright (c) 2022 9elements GmbH */ +#include <linux/delay.h> #include <linux/i2c.h> #include <linux/module.h> #include <linux/pmbus.h> @@ -53,6 +54,30 @@ static int pli1209bc_read_word_data(struct i2c_client *client, int page, } } +static int pli1209bc_write_byte(struct i2c_client *client, int page, u8 reg) +{ + int ret; + + switch (reg) { + case PMBUS_CLEAR_FAULTS: + ret = pmbus_write_byte(client, page, reg); + /* + * PLI1209 takes 230 usec to execute the CLEAR_FAULTS command. + * During that time it's busy and NACKs all requests on the + * SMBUS interface. It also NACKs reads on PMBUS_STATUS_BYTE + * making it impossible to poll the BUSY flag. + * + * Just wait for not BUSY unconditionally. + */ + usleep_range(250, 300); + break; + default: + ret = -ENODATA; + break; + } + return ret; +} + #if IS_ENABLED(CONFIG_SENSORS_PLI1209BC_REGULATOR) static const struct regulator_desc pli1209bc_reg_desc = { .name = "vout2", @@ -102,6 +127,7 @@ static struct pmbus_driver_info pli1209bc_info = { | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_INPUT, .read_word_data = pli1209bc_read_word_data, + .write_byte = pli1209bc_write_byte, #if IS_ENABLED(CONFIG_SENSORS_PLI1209BC_REGULATOR) .num_regulators = 1, .reg_desc = &pli1209bc_reg_desc, diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index 69a4e62b6c8d..1363d9f89181 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -561,7 +561,8 @@ static bool pmbus_check_register(struct i2c_client *client, rv = pmbus_check_status_cml(client); if (rv < 0 && (data->flags & PMBUS_READ_STATUS_AFTER_FAILED_CHECK)) data->read_status(client, -1); - pmbus_clear_fault_page(client, -1); + if (reg < PMBUS_VIRT_BASE) + pmbus_clear_fault_page(client, -1); return rv >= 0; } @@ -2540,7 +2541,6 @@ static int pmbus_identify_common(struct i2c_client *client, } } - pmbus_clear_fault_page(client, page); return 0; } diff --git a/drivers/hwmon/pmbus/q54sj108a2.c b/drivers/hwmon/pmbus/q54sj108a2.c index b830f3b02bcc..a235c1cdf4fe 100644 --- a/drivers/hwmon/pmbus/q54sj108a2.c +++ b/drivers/hwmon/pmbus/q54sj108a2.c @@ -10,7 +10,7 @@ #include <linux/i2c.h> #include <linux/kstrtox.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include "pmbus.h" #define STORE_DEFAULT_ALL 0x11 diff --git a/drivers/hwmon/pmbus/tps53679.c b/drivers/hwmon/pmbus/tps53679.c index ef99005a3af5..5c9466244d70 100644 --- a/drivers/hwmon/pmbus/tps53679.c +++ b/drivers/hwmon/pmbus/tps53679.c @@ -12,7 +12,7 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include "pmbus.h" enum chips { @@ -235,7 +235,7 @@ static int tps53679_probe(struct i2c_client *client) enum chips chip_id; if (dev->of_node) - chip_id = (enum chips)of_device_get_match_data(dev); + chip_id = (uintptr_t)of_device_get_match_data(dev); else chip_id = i2c_match_id(tps53679_id, client)->driver_data; diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c index c404d306e8f7..8d9d422450e5 100644 --- a/drivers/hwmon/pmbus/ucd9000.c +++ b/drivers/hwmon/pmbus/ucd9000.c @@ -10,7 +10,7 @@ #include <linux/delay.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/init.h> #include <linux/err.h> #include <linux/slab.h> @@ -588,7 +588,7 @@ static int ucd9000_probe(struct i2c_client *client) } if (client->dev.of_node) - chip = (enum chips)of_device_get_match_data(&client->dev); + chip = (uintptr_t)of_device_get_match_data(&client->dev); else chip = mid->driver_data; diff --git a/drivers/hwmon/pmbus/ucd9200.c b/drivers/hwmon/pmbus/ucd9200.c index a82847945508..7920d1c06df0 100644 --- a/drivers/hwmon/pmbus/ucd9200.c +++ b/drivers/hwmon/pmbus/ucd9200.c @@ -7,7 +7,7 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/init.h> #include <linux/err.h> #include <linux/slab.h> @@ -103,7 +103,7 @@ static int ucd9200_probe(struct i2c_client *client) } if (client->dev.of_node) - chip = (enum chips)of_device_get_match_data(&client->dev); + chip = (uintptr_t)of_device_get_match_data(&client->dev); else chip = mid->driver_data; diff --git a/drivers/hwmon/sbtsi_temp.c b/drivers/hwmon/sbtsi_temp.c index b79cece4ac9a..dd85cf89f008 100644 --- a/drivers/hwmon/sbtsi_temp.c +++ b/drivers/hwmon/sbtsi_temp.c @@ -13,7 +13,6 @@ #include <linux/hwmon.h> #include <linux/module.h> #include <linux/mutex.h> -#include <linux/of_device.h> #include <linux/of.h> /* diff --git a/drivers/hwmon/scpi-hwmon.c b/drivers/hwmon/scpi-hwmon.c index 121e5e9f487f..a0d220609565 100644 --- a/drivers/hwmon/scpi-hwmon.c +++ b/drivers/hwmon/scpi-hwmon.c @@ -8,7 +8,7 @@ #include <linux/hwmon.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/scpi_protocol.h> #include <linux/slab.h> diff --git a/drivers/hwmon/sht3x.c b/drivers/hwmon/sht3x.c index bf18630619e0..79657910b79e 100644 --- a/drivers/hwmon/sht3x.c +++ b/drivers/hwmon/sht3x.c @@ -147,8 +147,20 @@ static const u16 mode_to_update_interval[] = { 100, }; +static const struct hwmon_channel_info * const sht3x_channel_info[] = { + HWMON_CHANNEL_INFO(chip, HWMON_C_UPDATE_INTERVAL), + HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MIN | + HWMON_T_MIN_HYST | HWMON_T_MAX | + HWMON_T_MAX_HYST | HWMON_T_ALARM), + HWMON_CHANNEL_INFO(humidity, HWMON_H_INPUT | HWMON_H_MIN | + HWMON_H_MIN_HYST | HWMON_H_MAX | + HWMON_H_MAX_HYST | HWMON_H_ALARM), + NULL, +}; + struct sht3x_data { struct i2c_client *client; + enum sht3x_chips chip_id; struct mutex i2c_lock; /* lock for sending i2c commands */ struct mutex data_lock; /* lock for updating driver data */ @@ -276,27 +288,24 @@ out: return data; } -/* sysfs attributes */ -static ssize_t temp1_input_show(struct device *dev, - struct device_attribute *attr, char *buf) +static int temp1_input_read(struct device *dev) { struct sht3x_data *data = sht3x_update_client(dev); if (IS_ERR(data)) return PTR_ERR(data); - return sprintf(buf, "%d\n", data->temperature); + return data->temperature; } -static ssize_t humidity1_input_show(struct device *dev, - struct device_attribute *attr, char *buf) +static int humidity1_input_read(struct device *dev) { struct sht3x_data *data = sht3x_update_client(dev); if (IS_ERR(data)) return PTR_ERR(data); - return sprintf(buf, "%u\n", data->humidity); + return data->humidity; } /* @@ -332,33 +341,24 @@ static int limits_update(struct sht3x_data *data) return ret; } -static ssize_t temp1_limit_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static int temp1_limit_read(struct device *dev, int index) { struct sht3x_data *data = dev_get_drvdata(dev); - u8 index = to_sensor_dev_attr(attr)->index; - int temperature_limit = data->temperature_limits[index]; - return sysfs_emit(buf, "%d\n", temperature_limit); + return data->temperature_limits[index]; } -static ssize_t humidity1_limit_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static int humidity1_limit_read(struct device *dev, int index) { struct sht3x_data *data = dev_get_drvdata(dev); - u8 index = to_sensor_dev_attr(attr)->index; - u32 humidity_limit = data->humidity_limits[index]; - return sysfs_emit(buf, "%u\n", humidity_limit); + return data->humidity_limits[index]; } /* - * limit_store must only be called with data_lock held + * limit_write must only be called with data_lock held */ -static size_t limit_store(struct device *dev, - size_t count, +static size_t limit_write(struct device *dev, u8 index, int temperature, u32 humidity) @@ -379,7 +379,7 @@ static size_t limit_store(struct device *dev, * ST = (T + 45) / 175 * 2^16 * SRH = RH / 100 * 2^16 * adapted for fixed point arithmetic and packed the same as - * in limit_show() + * in limit_read() */ raw = ((u32)(temperature + 45000) * 24543) >> (16 + 7); raw |= ((humidity * 42950) >> 16) & 0xfe00; @@ -400,50 +400,35 @@ static size_t limit_store(struct device *dev, data->temperature_limits[index] = temperature; data->humidity_limits[index] = humidity; - return count; + + return 0; } -static ssize_t temp1_limit_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) +static int temp1_limit_write(struct device *dev, int index, int val) { int temperature; int ret; struct sht3x_data *data = dev_get_drvdata(dev); - u8 index = to_sensor_dev_attr(attr)->index; - ret = kstrtoint(buf, 0, &temperature); - if (ret) - return ret; - - temperature = clamp_val(temperature, SHT3X_MIN_TEMPERATURE, + temperature = clamp_val(val, SHT3X_MIN_TEMPERATURE, SHT3X_MAX_TEMPERATURE); mutex_lock(&data->data_lock); - ret = limit_store(dev, count, index, temperature, + ret = limit_write(dev, index, temperature, data->humidity_limits[index]); mutex_unlock(&data->data_lock); return ret; } -static ssize_t humidity1_limit_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) +static int humidity1_limit_write(struct device *dev, int index, int val) { u32 humidity; int ret; struct sht3x_data *data = dev_get_drvdata(dev); - u8 index = to_sensor_dev_attr(attr)->index; - - ret = kstrtou32(buf, 0, &humidity); - if (ret) - return ret; - humidity = clamp_val(humidity, SHT3X_MIN_HUMIDITY, SHT3X_MAX_HUMIDITY); + humidity = clamp_val(val, SHT3X_MIN_HUMIDITY, SHT3X_MAX_HUMIDITY); mutex_lock(&data->data_lock); - ret = limit_store(dev, count, index, data->temperature_limits[index], + ret = limit_write(dev, index, data->temperature_limits[index], humidity); mutex_unlock(&data->data_lock); @@ -474,7 +459,6 @@ static void sht3x_select_command(struct sht3x_data *data) } static int status_register_read(struct device *dev, - struct device_attribute *attr, char *buffer, int length) { int ret; @@ -487,34 +471,30 @@ static int status_register_read(struct device *dev, return ret; } -static ssize_t temp1_alarm_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static int temp1_alarm_read(struct device *dev) { char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN]; int ret; - ret = status_register_read(dev, attr, buffer, + ret = status_register_read(dev, buffer, SHT3X_WORD_LEN + SHT3X_CRC8_LEN); if (ret) return ret; - return sysfs_emit(buf, "%d\n", !!(buffer[0] & 0x04)); + return !!(buffer[0] & 0x04); } -static ssize_t humidity1_alarm_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static int humidity1_alarm_read(struct device *dev) { char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN]; int ret; - ret = status_register_read(dev, attr, buffer, + ret = status_register_read(dev, buffer, SHT3X_WORD_LEN + SHT3X_CRC8_LEN); if (ret) return ret; - return sysfs_emit(buf, "%d\n", !!(buffer[0] & 0x08)); + return !!(buffer[0] & 0x08); } static ssize_t heater_enable_show(struct device *dev, @@ -524,7 +504,7 @@ static ssize_t heater_enable_show(struct device *dev, char buffer[SHT3X_WORD_LEN + SHT3X_CRC8_LEN]; int ret; - ret = status_register_read(dev, attr, buffer, + ret = status_register_read(dev, buffer, SHT3X_WORD_LEN + SHT3X_CRC8_LEN); if (ret) return ret; @@ -560,39 +540,28 @@ static ssize_t heater_enable_store(struct device *dev, return ret; } -static ssize_t update_interval_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static int update_interval_read(struct device *dev) { struct sht3x_data *data = dev_get_drvdata(dev); - return sysfs_emit(buf, "%u\n", - mode_to_update_interval[data->mode]); + return mode_to_update_interval[data->mode]; } -static ssize_t update_interval_store(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) +static int update_interval_write(struct device *dev, int val) { - u16 update_interval; u8 mode; int ret; const char *command; struct sht3x_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; - ret = kstrtou16(buf, 0, &update_interval); - if (ret) - return ret; - - mode = get_mode_from_update_interval(update_interval); + mode = get_mode_from_update_interval(val); mutex_lock(&data->data_lock); /* mode did not change */ if (mode == data->mode) { mutex_unlock(&data->data_lock); - return count; + return 0; } mutex_lock(&data->i2c_lock); @@ -634,7 +603,7 @@ out: if (ret != SHT3X_CMD_LENGTH) return ret < 0 ? ret : -EIO; - return count; + return 0; } static ssize_t repeatability_show(struct device *dev, @@ -668,60 +637,219 @@ static ssize_t repeatability_store(struct device *dev, return count; } -static SENSOR_DEVICE_ATTR_RO(temp1_input, temp1_input, 0); -static SENSOR_DEVICE_ATTR_RO(humidity1_input, humidity1_input, 0); -static SENSOR_DEVICE_ATTR_RW(temp1_max, temp1_limit, limit_max); -static SENSOR_DEVICE_ATTR_RW(humidity1_max, humidity1_limit, limit_max); -static SENSOR_DEVICE_ATTR_RW(temp1_max_hyst, temp1_limit, limit_max_hyst); -static SENSOR_DEVICE_ATTR_RW(humidity1_max_hyst, humidity1_limit, - limit_max_hyst); -static SENSOR_DEVICE_ATTR_RW(temp1_min, temp1_limit, limit_min); -static SENSOR_DEVICE_ATTR_RW(humidity1_min, humidity1_limit, limit_min); -static SENSOR_DEVICE_ATTR_RW(temp1_min_hyst, temp1_limit, limit_min_hyst); -static SENSOR_DEVICE_ATTR_RW(humidity1_min_hyst, humidity1_limit, - limit_min_hyst); -static SENSOR_DEVICE_ATTR_RO(temp1_alarm, temp1_alarm, 0); -static SENSOR_DEVICE_ATTR_RO(humidity1_alarm, humidity1_alarm, 0); static SENSOR_DEVICE_ATTR_RW(heater_enable, heater_enable, 0); -static SENSOR_DEVICE_ATTR_RW(update_interval, update_interval, 0); static SENSOR_DEVICE_ATTR_RW(repeatability, repeatability, 0); static struct attribute *sht3x_attrs[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_humidity1_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - &sensor_dev_attr_humidity1_max.dev_attr.attr, - &sensor_dev_attr_humidity1_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_min_hyst.dev_attr.attr, - &sensor_dev_attr_humidity1_min.dev_attr.attr, - &sensor_dev_attr_humidity1_min_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_humidity1_alarm.dev_attr.attr, &sensor_dev_attr_heater_enable.dev_attr.attr, - &sensor_dev_attr_update_interval.dev_attr.attr, &sensor_dev_attr_repeatability.dev_attr.attr, NULL }; -static struct attribute *sts3x_attrs[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_min_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_heater_enable.dev_attr.attr, - &sensor_dev_attr_update_interval.dev_attr.attr, - &sensor_dev_attr_repeatability.dev_attr.attr, - NULL +ATTRIBUTE_GROUPS(sht3x); + +static umode_t sht3x_is_visible(const void *data, enum hwmon_sensor_types type, + u32 attr, int channel) +{ + const struct sht3x_data *chip_data = data; + + switch (type) { + case hwmon_chip: + switch (attr) { + case hwmon_chip_update_interval: + return 0644; + default: + break; + } + break; + case hwmon_temp: + switch (attr) { + case hwmon_temp_input: + case hwmon_temp_alarm: + return 0444; + case hwmon_temp_max: + case hwmon_temp_max_hyst: + case hwmon_temp_min: + case hwmon_temp_min_hyst: + return 0644; + default: + break; + } + break; + case hwmon_humidity: + if (chip_data->chip_id == sts3x) + break; + switch (attr) { + case hwmon_humidity_input: + case hwmon_humidity_alarm: + return 0444; + case hwmon_humidity_max: + case hwmon_humidity_max_hyst: + case hwmon_humidity_min: + case hwmon_humidity_min_hyst: + return 0644; + default: + break; + } + break; + default: + break; + } + + return 0; +} + +static int sht3x_read(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long *val) +{ + enum sht3x_limits index; + + switch (type) { + case hwmon_chip: + switch (attr) { + case hwmon_chip_update_interval: + *val = update_interval_read(dev); + break; + default: + return -EOPNOTSUPP; + } + break; + case hwmon_temp: + switch (attr) { + case hwmon_temp_input: + *val = temp1_input_read(dev); + break; + case hwmon_temp_alarm: + *val = temp1_alarm_read(dev); + break; + case hwmon_temp_max: + index = limit_max; + *val = temp1_limit_read(dev, index); + break; + case hwmon_temp_max_hyst: + index = limit_max_hyst; + *val = temp1_limit_read(dev, index); + break; + case hwmon_temp_min: + index = limit_min; + *val = temp1_limit_read(dev, index); + break; + case hwmon_temp_min_hyst: + index = limit_min_hyst; + *val = temp1_limit_read(dev, index); + break; + default: + return -EOPNOTSUPP; + } + break; + case hwmon_humidity: + switch (attr) { + case hwmon_humidity_input: + *val = humidity1_input_read(dev); + break; + case hwmon_humidity_alarm: + *val = humidity1_alarm_read(dev); + break; + case hwmon_humidity_max: + index = limit_max; + *val = humidity1_limit_read(dev, index); + break; + case hwmon_humidity_max_hyst: + index = limit_max_hyst; + *val = humidity1_limit_read(dev, index); + break; + case hwmon_humidity_min: + index = limit_min; + *val = humidity1_limit_read(dev, index); + break; + case hwmon_humidity_min_hyst: + index = limit_min_hyst; + *val = humidity1_limit_read(dev, index); + break; + default: + return -EOPNOTSUPP; + } + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int sht3x_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long val) +{ + enum sht3x_limits index; + + switch (type) { + case hwmon_chip: + switch (attr) { + case hwmon_chip_update_interval: + return update_interval_write(dev, val); + default: + return -EOPNOTSUPP; + } + case hwmon_temp: + switch (attr) { + case hwmon_temp_max: + index = limit_max; + break; + case hwmon_temp_max_hyst: + index = limit_max_hyst; + break; + case hwmon_temp_min: + index = limit_min; + break; + case hwmon_temp_min_hyst: + index = limit_min_hyst; + break; + default: + return -EOPNOTSUPP; + } + return temp1_limit_write(dev, index, val); + case hwmon_humidity: + switch (attr) { + case hwmon_humidity_max: + index = limit_max; + break; + case hwmon_humidity_max_hyst: + index = limit_max_hyst; + break; + case hwmon_humidity_min: + index = limit_min; + break; + case hwmon_humidity_min_hyst: + index = limit_min_hyst; + break; + default: + return -EOPNOTSUPP; + } + return humidity1_limit_write(dev, index, val); + default: + return -EOPNOTSUPP; + } +} + +static const struct hwmon_ops sht3x_ops = { + .is_visible = sht3x_is_visible, + .read = sht3x_read, + .write = sht3x_write, }; -ATTRIBUTE_GROUPS(sht3x); -ATTRIBUTE_GROUPS(sts3x); +static const struct hwmon_chip_info sht3x_chip_info = { + .ops = &sht3x_ops, + .info = sht3x_channel_info, +}; + +/* device ID table */ +static const struct i2c_device_id sht3x_ids[] = { + {"sht3x", sht3x}, + {"sts3x", sts3x}, + {} +}; -static const struct i2c_device_id sht3x_ids[]; +MODULE_DEVICE_TABLE(i2c, sht3x_ids); static int sht3x_probe(struct i2c_client *client) { @@ -730,7 +858,6 @@ static int sht3x_probe(struct i2c_client *client) struct device *hwmon_dev; struct i2c_adapter *adap = client->adapter; struct device *dev = &client->dev; - const struct attribute_group **attribute_groups; /* * we require full i2c support since the sht3x uses multi-byte read and @@ -753,6 +880,7 @@ static int sht3x_probe(struct i2c_client *client) data->mode = 0; data->last_update = jiffies - msecs_to_jiffies(3000); data->client = client; + data->chip_id = i2c_match_id(sht3x_ids, client)->driver_data; crc8_populate_msb(sht3x_crc8_table, SHT3X_CRC8_POLYNOMIAL); sht3x_select_command(data); @@ -771,15 +899,11 @@ static int sht3x_probe(struct i2c_client *client) if (ret) return ret; - if (i2c_match_id(sht3x_ids, client)->driver_data == sts3x) - attribute_groups = sts3x_groups; - else - attribute_groups = sht3x_groups; - - hwmon_dev = devm_hwmon_device_register_with_groups(dev, - client->name, - data, - attribute_groups); + hwmon_dev = devm_hwmon_device_register_with_info(dev, + client->name, + data, + &sht3x_chip_info, + sht3x_groups); if (IS_ERR(hwmon_dev)) dev_dbg(dev, "unable to register hwmon device\n"); @@ -787,15 +911,6 @@ static int sht3x_probe(struct i2c_client *client) return PTR_ERR_OR_ZERO(hwmon_dev); } -/* device ID table */ -static const struct i2c_device_id sht3x_ids[] = { - {"sht3x", sht3x}, - {"sts3x", sts3x}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, sht3x_ids); - static struct i2c_driver sht3x_i2c_driver = { .driver.name = "sht3x", .probe = sht3x_probe, diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index b0b05fd12221..0a0479501e11 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c @@ -798,7 +798,7 @@ static int sis5595_pci_probe(struct pci_dev *dev, { u16 address; u8 enable; - int *i; + int *i, err; for (i = blacklist; *i != 0; i++) { struct pci_dev *d; @@ -818,8 +818,8 @@ static int sis5595_pci_probe(struct pci_dev *dev, pci_write_config_word(dev, SIS5595_BASE_REG, force_addr); } - if (PCIBIOS_SUCCESSFUL != - pci_read_config_word(dev, SIS5595_BASE_REG, &address)) { + err = pci_read_config_word(dev, SIS5595_BASE_REG, &address); + if (err != PCIBIOS_SUCCESSFUL) { dev_err(&dev->dev, "Failed to read ISA address\n"); return -ENODEV; } @@ -836,22 +836,23 @@ static int sis5595_pci_probe(struct pci_dev *dev, return -ENODEV; } - if (PCIBIOS_SUCCESSFUL != - pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable)) { + err = pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable); + if (err != PCIBIOS_SUCCESSFUL) { dev_err(&dev->dev, "Failed to read enable register\n"); return -ENODEV; } if (!(enable & 0x80)) { - if ((PCIBIOS_SUCCESSFUL != - pci_write_config_byte(dev, SIS5595_ENABLE_REG, - enable | 0x80)) - || (PCIBIOS_SUCCESSFUL != - pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable)) - || (!(enable & 0x80))) { - /* doesn't work for some chips! */ - dev_err(&dev->dev, "Failed to enable HWM device\n"); - return -ENODEV; - } + err = pci_write_config_byte(dev, SIS5595_ENABLE_REG, enable | 0x80); + if (err != PCIBIOS_SUCCESSFUL) + goto enable_fail; + + err = pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable); + if (err != PCIBIOS_SUCCESSFUL) + goto enable_fail; + + /* doesn't work for some chips! */ + if (!(enable & 0x80)) + goto enable_fail; } if (platform_driver_register(&sis5595_driver)) { @@ -871,6 +872,10 @@ static int sis5595_pci_probe(struct pci_dev *dev, */ return -ENODEV; +enable_fail: + dev_err(&dev->dev, "Failed to enable HWM device\n"); + goto exit; + exit_unregister: pci_dev_put(dev); platform_driver_unregister(&sis5595_driver); diff --git a/drivers/hwmon/smm665.c b/drivers/hwmon/smm665.c deleted file mode 100644 index 026c76f8c22e..000000000000 --- a/drivers/hwmon/smm665.c +++ /dev/null @@ -1,706 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Driver for SMM665 Power Controller / Monitor - * - * Copyright (C) 2010 Ericsson AB. - * - * This driver should also work for SMM465, SMM764, and SMM766, but is untested - * for those chips. Only monitoring functionality is implemented. - * - * Datasheets: - * http://www.summitmicro.com/prod_select/summary/SMM665/SMM665B_2089_20.pdf - * http://www.summitmicro.com/prod_select/summary/SMM766B/SMM766B_2122.pdf - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/err.h> -#include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/hwmon.h> -#include <linux/hwmon-sysfs.h> -#include <linux/delay.h> -#include <linux/jiffies.h> - -/* Internal reference voltage (VREF, x 1000 */ -#define SMM665_VREF_ADC_X1000 1250 - -/* module parameters */ -static int vref = SMM665_VREF_ADC_X1000; -module_param(vref, int, 0); -MODULE_PARM_DESC(vref, "Reference voltage in mV"); - -enum chips { smm465, smm665, smm665c, smm764, smm766 }; - -/* - * ADC channel addresses - */ -#define SMM665_MISC16_ADC_DATA_A 0x00 -#define SMM665_MISC16_ADC_DATA_B 0x01 -#define SMM665_MISC16_ADC_DATA_C 0x02 -#define SMM665_MISC16_ADC_DATA_D 0x03 -#define SMM665_MISC16_ADC_DATA_E 0x04 -#define SMM665_MISC16_ADC_DATA_F 0x05 -#define SMM665_MISC16_ADC_DATA_VDD 0x06 -#define SMM665_MISC16_ADC_DATA_12V 0x07 -#define SMM665_MISC16_ADC_DATA_INT_TEMP 0x08 -#define SMM665_MISC16_ADC_DATA_AIN1 0x09 -#define SMM665_MISC16_ADC_DATA_AIN2 0x0a - -/* - * Command registers - */ -#define SMM665_MISC8_CMD_STS 0x80 -#define SMM665_MISC8_STATUS1 0x81 -#define SMM665_MISC8_STATUSS2 0x82 -#define SMM665_MISC8_IO_POLARITY 0x83 -#define SMM665_MISC8_PUP_POLARITY 0x84 -#define SMM665_MISC8_ADOC_STATUS1 0x85 -#define SMM665_MISC8_ADOC_STATUS2 0x86 -#define SMM665_MISC8_WRITE_PROT 0x87 -#define SMM665_MISC8_STS_TRACK 0x88 - -/* - * Configuration registers and register groups - */ -#define SMM665_ADOC_ENABLE 0x0d -#define SMM665_LIMIT_BASE 0x80 /* First limit register */ - -/* - * Limit register bit masks - */ -#define SMM665_TRIGGER_RST 0x8000 -#define SMM665_TRIGGER_HEALTHY 0x4000 -#define SMM665_TRIGGER_POWEROFF 0x2000 -#define SMM665_TRIGGER_SHUTDOWN 0x1000 -#define SMM665_ADC_MASK 0x03ff - -#define smm665_is_critical(lim) ((lim) & (SMM665_TRIGGER_RST \ - | SMM665_TRIGGER_POWEROFF \ - | SMM665_TRIGGER_SHUTDOWN)) -/* - * Fault register bit definitions - * Values are merged from status registers 1/2, - * with status register 1 providing the upper 8 bits. - */ -#define SMM665_FAULT_A 0x0001 -#define SMM665_FAULT_B 0x0002 -#define SMM665_FAULT_C 0x0004 -#define SMM665_FAULT_D 0x0008 -#define SMM665_FAULT_E 0x0010 -#define SMM665_FAULT_F 0x0020 -#define SMM665_FAULT_VDD 0x0040 -#define SMM665_FAULT_12V 0x0080 -#define SMM665_FAULT_TEMP 0x0100 -#define SMM665_FAULT_AIN1 0x0200 -#define SMM665_FAULT_AIN2 0x0400 - -/* - * I2C Register addresses - * - * The configuration register needs to be the configured base register. - * The command/status register address is derived from it. - */ -#define SMM665_REGMASK 0x78 -#define SMM665_CMDREG_BASE 0x48 -#define SMM665_CONFREG_BASE 0x50 - -/* - * Equations given by chip manufacturer to calculate voltage/temperature values - * vref = Reference voltage on VREF_ADC pin (module parameter) - * adc = 10bit ADC value read back from registers - */ - -/* Voltage A-F and VDD */ -#define SMM665_VMON_ADC_TO_VOLTS(adc) ((adc) * vref / 256) - -/* Voltage 12VIN */ -#define SMM665_12VIN_ADC_TO_VOLTS(adc) ((adc) * vref * 3 / 256) - -/* Voltage AIN1, AIN2 */ -#define SMM665_AIN_ADC_TO_VOLTS(adc) ((adc) * vref / 512) - -/* Temp Sensor */ -#define SMM665_TEMP_ADC_TO_CELSIUS(adc) (((adc) <= 511) ? \ - ((int)(adc) * 1000 / 4) : \ - (((int)(adc) - 0x400) * 1000 / 4)) - -#define SMM665_NUM_ADC 11 - -/* - * Chip dependent ADC conversion time, in uS - */ -#define SMM665_ADC_WAIT_SMM665 70 -#define SMM665_ADC_WAIT_SMM766 185 - -struct smm665_data { - enum chips type; - int conversion_time; /* ADC conversion time */ - struct i2c_client *client; - struct mutex update_lock; - bool valid; - unsigned long last_updated; /* in jiffies */ - u16 adc[SMM665_NUM_ADC]; /* adc values (raw) */ - u16 faults; /* fault status */ - /* The following values are in mV */ - int critical_min_limit[SMM665_NUM_ADC]; - int alarm_min_limit[SMM665_NUM_ADC]; - int critical_max_limit[SMM665_NUM_ADC]; - int alarm_max_limit[SMM665_NUM_ADC]; - struct i2c_client *cmdreg; -}; - -/* - * smm665_read16() - * - * Read 16 bit value from <reg>, <reg+1>. Upper 8 bits are in <reg>. - */ -static int smm665_read16(struct i2c_client *client, int reg) -{ - int rv, val; - - rv = i2c_smbus_read_byte_data(client, reg); - if (rv < 0) - return rv; - val = rv << 8; - rv = i2c_smbus_read_byte_data(client, reg + 1); - if (rv < 0) - return rv; - val |= rv; - return val; -} - -/* - * Read adc value. - */ -static int smm665_read_adc(struct smm665_data *data, int adc) -{ - struct i2c_client *client = data->cmdreg; - int rv; - int radc; - - /* - * Algorithm for reading ADC, per SMM665 datasheet - * - * {[S][addr][W][Ack]} {[offset][Ack]} {[S][addr][R][Nack]} - * [wait conversion time] - * {[S][addr][R][Ack]} {[datahi][Ack]} {[datalo][Ack][P]} - * - * To implement the first part of this exchange, - * do a full read transaction and expect a failure/Nack. - * This sets up the address pointer on the SMM665 - * and starts the ADC conversion. - * Then do a two-byte read transaction. - */ - rv = i2c_smbus_read_byte_data(client, adc << 3); - if (rv != -ENXIO) { - /* - * We expect ENXIO to reflect NACK - * (per Documentation/i2c/fault-codes.rst). - * Everything else is an error. - */ - dev_dbg(&client->dev, - "Unexpected return code %d when setting ADC index", rv); - return (rv < 0) ? rv : -EIO; - } - - udelay(data->conversion_time); - - /* - * Now read two bytes. - * - * Neither i2c_smbus_read_byte() nor - * i2c_smbus_read_block_data() worked here, - * so use i2c_smbus_read_word_swapped() instead. - * We could also try to use i2c_master_recv(), - * but that is not always supported. - */ - rv = i2c_smbus_read_word_swapped(client, 0); - if (rv < 0) { - dev_dbg(&client->dev, "Failed to read ADC value: error %d", rv); - return rv; - } - /* - * Validate/verify readback adc channel (in bit 11..14). - */ - radc = (rv >> 11) & 0x0f; - if (radc != adc) { - dev_dbg(&client->dev, "Unexpected RADC: Expected %d got %d", - adc, radc); - return -EIO; - } - - return rv & SMM665_ADC_MASK; -} - -static struct smm665_data *smm665_update_device(struct device *dev) -{ - struct smm665_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; - struct smm665_data *ret = data; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - int i, val; - - /* - * read status registers - */ - val = smm665_read16(client, SMM665_MISC8_STATUS1); - if (unlikely(val < 0)) { - ret = ERR_PTR(val); - goto abort; - } - data->faults = val; - - /* Read adc registers */ - for (i = 0; i < SMM665_NUM_ADC; i++) { - val = smm665_read_adc(data, i); - if (unlikely(val < 0)) { - ret = ERR_PTR(val); - goto abort; - } - data->adc[i] = val; - } - data->last_updated = jiffies; - data->valid = true; - } -abort: - mutex_unlock(&data->update_lock); - return ret; -} - -/* Return converted value from given adc */ -static int smm665_convert(u16 adcval, int index) -{ - int val = 0; - - switch (index) { - case SMM665_MISC16_ADC_DATA_12V: - val = SMM665_12VIN_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK); - break; - - case SMM665_MISC16_ADC_DATA_VDD: - case SMM665_MISC16_ADC_DATA_A: - case SMM665_MISC16_ADC_DATA_B: - case SMM665_MISC16_ADC_DATA_C: - case SMM665_MISC16_ADC_DATA_D: - case SMM665_MISC16_ADC_DATA_E: - case SMM665_MISC16_ADC_DATA_F: - val = SMM665_VMON_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK); - break; - - case SMM665_MISC16_ADC_DATA_AIN1: - case SMM665_MISC16_ADC_DATA_AIN2: - val = SMM665_AIN_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK); - break; - - case SMM665_MISC16_ADC_DATA_INT_TEMP: - val = SMM665_TEMP_ADC_TO_CELSIUS(adcval & SMM665_ADC_MASK); - break; - - default: - /* If we get here, the developer messed up */ - WARN_ON_ONCE(1); - break; - } - - return val; -} - -static int smm665_get_min(struct device *dev, int index) -{ - struct smm665_data *data = dev_get_drvdata(dev); - - return data->alarm_min_limit[index]; -} - -static int smm665_get_max(struct device *dev, int index) -{ - struct smm665_data *data = dev_get_drvdata(dev); - - return data->alarm_max_limit[index]; -} - -static int smm665_get_lcrit(struct device *dev, int index) -{ - struct smm665_data *data = dev_get_drvdata(dev); - - return data->critical_min_limit[index]; -} - -static int smm665_get_crit(struct device *dev, int index) -{ - struct smm665_data *data = dev_get_drvdata(dev); - - return data->critical_max_limit[index]; -} - -static ssize_t smm665_show_crit_alarm(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct smm665_data *data = smm665_update_device(dev); - int val = 0; - - if (IS_ERR(data)) - return PTR_ERR(data); - - if (data->faults & (1 << attr->index)) - val = 1; - - return sysfs_emit(buf, "%d\n", val); -} - -static ssize_t smm665_show_input(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct smm665_data *data = smm665_update_device(dev); - int adc = attr->index; - int val; - - if (IS_ERR(data)) - return PTR_ERR(data); - - val = smm665_convert(data->adc[adc], adc); - return sysfs_emit(buf, "%d\n", val); -} - -#define SMM665_SHOW(what) \ -static ssize_t smm665_show_##what(struct device *dev, \ - struct device_attribute *da, char *buf) \ -{ \ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ - const int val = smm665_get_##what(dev, attr->index); \ - return snprintf(buf, PAGE_SIZE, "%d\n", val); \ -} - -SMM665_SHOW(min); -SMM665_SHOW(max); -SMM665_SHOW(lcrit); -SMM665_SHOW(crit); - -/* - * These macros are used below in constructing device attribute objects - * for use with sysfs_create_group() to make a sysfs device file - * for each register. - */ - -#define SMM665_ATTR(name, type, cmd_idx) \ - static SENSOR_DEVICE_ATTR(name##_##type, S_IRUGO, \ - smm665_show_##type, NULL, cmd_idx) - -/* Construct a sensor_device_attribute structure for each register */ - -/* Input voltages */ -SMM665_ATTR(in1, input, SMM665_MISC16_ADC_DATA_12V); -SMM665_ATTR(in2, input, SMM665_MISC16_ADC_DATA_VDD); -SMM665_ATTR(in3, input, SMM665_MISC16_ADC_DATA_A); -SMM665_ATTR(in4, input, SMM665_MISC16_ADC_DATA_B); -SMM665_ATTR(in5, input, SMM665_MISC16_ADC_DATA_C); -SMM665_ATTR(in6, input, SMM665_MISC16_ADC_DATA_D); -SMM665_ATTR(in7, input, SMM665_MISC16_ADC_DATA_E); -SMM665_ATTR(in8, input, SMM665_MISC16_ADC_DATA_F); -SMM665_ATTR(in9, input, SMM665_MISC16_ADC_DATA_AIN1); -SMM665_ATTR(in10, input, SMM665_MISC16_ADC_DATA_AIN2); - -/* Input voltages min */ -SMM665_ATTR(in1, min, SMM665_MISC16_ADC_DATA_12V); -SMM665_ATTR(in2, min, SMM665_MISC16_ADC_DATA_VDD); -SMM665_ATTR(in3, min, SMM665_MISC16_ADC_DATA_A); -SMM665_ATTR(in4, min, SMM665_MISC16_ADC_DATA_B); -SMM665_ATTR(in5, min, SMM665_MISC16_ADC_DATA_C); -SMM665_ATTR(in6, min, SMM665_MISC16_ADC_DATA_D); -SMM665_ATTR(in7, min, SMM665_MISC16_ADC_DATA_E); -SMM665_ATTR(in8, min, SMM665_MISC16_ADC_DATA_F); -SMM665_ATTR(in9, min, SMM665_MISC16_ADC_DATA_AIN1); -SMM665_ATTR(in10, min, SMM665_MISC16_ADC_DATA_AIN2); - -/* Input voltages max */ -SMM665_ATTR(in1, max, SMM665_MISC16_ADC_DATA_12V); -SMM665_ATTR(in2, max, SMM665_MISC16_ADC_DATA_VDD); -SMM665_ATTR(in3, max, SMM665_MISC16_ADC_DATA_A); -SMM665_ATTR(in4, max, SMM665_MISC16_ADC_DATA_B); -SMM665_ATTR(in5, max, SMM665_MISC16_ADC_DATA_C); -SMM665_ATTR(in6, max, SMM665_MISC16_ADC_DATA_D); -SMM665_ATTR(in7, max, SMM665_MISC16_ADC_DATA_E); -SMM665_ATTR(in8, max, SMM665_MISC16_ADC_DATA_F); -SMM665_ATTR(in9, max, SMM665_MISC16_ADC_DATA_AIN1); -SMM665_ATTR(in10, max, SMM665_MISC16_ADC_DATA_AIN2); - -/* Input voltages lcrit */ -SMM665_ATTR(in1, lcrit, SMM665_MISC16_ADC_DATA_12V); -SMM665_ATTR(in2, lcrit, SMM665_MISC16_ADC_DATA_VDD); -SMM665_ATTR(in3, lcrit, SMM665_MISC16_ADC_DATA_A); -SMM665_ATTR(in4, lcrit, SMM665_MISC16_ADC_DATA_B); -SMM665_ATTR(in5, lcrit, SMM665_MISC16_ADC_DATA_C); -SMM665_ATTR(in6, lcrit, SMM665_MISC16_ADC_DATA_D); -SMM665_ATTR(in7, lcrit, SMM665_MISC16_ADC_DATA_E); -SMM665_ATTR(in8, lcrit, SMM665_MISC16_ADC_DATA_F); -SMM665_ATTR(in9, lcrit, SMM665_MISC16_ADC_DATA_AIN1); -SMM665_ATTR(in10, lcrit, SMM665_MISC16_ADC_DATA_AIN2); - -/* Input voltages crit */ -SMM665_ATTR(in1, crit, SMM665_MISC16_ADC_DATA_12V); -SMM665_ATTR(in2, crit, SMM665_MISC16_ADC_DATA_VDD); -SMM665_ATTR(in3, crit, SMM665_MISC16_ADC_DATA_A); -SMM665_ATTR(in4, crit, SMM665_MISC16_ADC_DATA_B); -SMM665_ATTR(in5, crit, SMM665_MISC16_ADC_DATA_C); -SMM665_ATTR(in6, crit, SMM665_MISC16_ADC_DATA_D); -SMM665_ATTR(in7, crit, SMM665_MISC16_ADC_DATA_E); -SMM665_ATTR(in8, crit, SMM665_MISC16_ADC_DATA_F); -SMM665_ATTR(in9, crit, SMM665_MISC16_ADC_DATA_AIN1); -SMM665_ATTR(in10, crit, SMM665_MISC16_ADC_DATA_AIN2); - -/* critical alarms */ -SMM665_ATTR(in1, crit_alarm, SMM665_FAULT_12V); -SMM665_ATTR(in2, crit_alarm, SMM665_FAULT_VDD); -SMM665_ATTR(in3, crit_alarm, SMM665_FAULT_A); -SMM665_ATTR(in4, crit_alarm, SMM665_FAULT_B); -SMM665_ATTR(in5, crit_alarm, SMM665_FAULT_C); -SMM665_ATTR(in6, crit_alarm, SMM665_FAULT_D); -SMM665_ATTR(in7, crit_alarm, SMM665_FAULT_E); -SMM665_ATTR(in8, crit_alarm, SMM665_FAULT_F); -SMM665_ATTR(in9, crit_alarm, SMM665_FAULT_AIN1); -SMM665_ATTR(in10, crit_alarm, SMM665_FAULT_AIN2); - -/* Temperature */ -SMM665_ATTR(temp1, input, SMM665_MISC16_ADC_DATA_INT_TEMP); -SMM665_ATTR(temp1, min, SMM665_MISC16_ADC_DATA_INT_TEMP); -SMM665_ATTR(temp1, max, SMM665_MISC16_ADC_DATA_INT_TEMP); -SMM665_ATTR(temp1, lcrit, SMM665_MISC16_ADC_DATA_INT_TEMP); -SMM665_ATTR(temp1, crit, SMM665_MISC16_ADC_DATA_INT_TEMP); -SMM665_ATTR(temp1, crit_alarm, SMM665_FAULT_TEMP); - -/* - * Finally, construct an array of pointers to members of the above objects, - * as required for sysfs_create_group() - */ -static struct attribute *smm665_attrs[] = { - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in1_min.dev_attr.attr, - &sensor_dev_attr_in1_max.dev_attr.attr, - &sensor_dev_attr_in1_lcrit.dev_attr.attr, - &sensor_dev_attr_in1_crit.dev_attr.attr, - &sensor_dev_attr_in1_crit_alarm.dev_attr.attr, - - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in2_min.dev_attr.attr, - &sensor_dev_attr_in2_max.dev_attr.attr, - &sensor_dev_attr_in2_lcrit.dev_attr.attr, - &sensor_dev_attr_in2_crit.dev_attr.attr, - &sensor_dev_attr_in2_crit_alarm.dev_attr.attr, - - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in3_min.dev_attr.attr, - &sensor_dev_attr_in3_max.dev_attr.attr, - &sensor_dev_attr_in3_lcrit.dev_attr.attr, - &sensor_dev_attr_in3_crit.dev_attr.attr, - &sensor_dev_attr_in3_crit_alarm.dev_attr.attr, - - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in4_min.dev_attr.attr, - &sensor_dev_attr_in4_max.dev_attr.attr, - &sensor_dev_attr_in4_lcrit.dev_attr.attr, - &sensor_dev_attr_in4_crit.dev_attr.attr, - &sensor_dev_attr_in4_crit_alarm.dev_attr.attr, - - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in5_min.dev_attr.attr, - &sensor_dev_attr_in5_max.dev_attr.attr, - &sensor_dev_attr_in5_lcrit.dev_attr.attr, - &sensor_dev_attr_in5_crit.dev_attr.attr, - &sensor_dev_attr_in5_crit_alarm.dev_attr.attr, - - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_in6_min.dev_attr.attr, - &sensor_dev_attr_in6_max.dev_attr.attr, - &sensor_dev_attr_in6_lcrit.dev_attr.attr, - &sensor_dev_attr_in6_crit.dev_attr.attr, - &sensor_dev_attr_in6_crit_alarm.dev_attr.attr, - - &sensor_dev_attr_in7_input.dev_attr.attr, - &sensor_dev_attr_in7_min.dev_attr.attr, - &sensor_dev_attr_in7_max.dev_attr.attr, - &sensor_dev_attr_in7_lcrit.dev_attr.attr, - &sensor_dev_attr_in7_crit.dev_attr.attr, - &sensor_dev_attr_in7_crit_alarm.dev_attr.attr, - - &sensor_dev_attr_in8_input.dev_attr.attr, - &sensor_dev_attr_in8_min.dev_attr.attr, - &sensor_dev_attr_in8_max.dev_attr.attr, - &sensor_dev_attr_in8_lcrit.dev_attr.attr, - &sensor_dev_attr_in8_crit.dev_attr.attr, - &sensor_dev_attr_in8_crit_alarm.dev_attr.attr, - - &sensor_dev_attr_in9_input.dev_attr.attr, - &sensor_dev_attr_in9_min.dev_attr.attr, - &sensor_dev_attr_in9_max.dev_attr.attr, - &sensor_dev_attr_in9_lcrit.dev_attr.attr, - &sensor_dev_attr_in9_crit.dev_attr.attr, - &sensor_dev_attr_in9_crit_alarm.dev_attr.attr, - - &sensor_dev_attr_in10_input.dev_attr.attr, - &sensor_dev_attr_in10_min.dev_attr.attr, - &sensor_dev_attr_in10_max.dev_attr.attr, - &sensor_dev_attr_in10_lcrit.dev_attr.attr, - &sensor_dev_attr_in10_crit.dev_attr.attr, - &sensor_dev_attr_in10_crit_alarm.dev_attr.attr, - - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_lcrit.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - - NULL, -}; - -ATTRIBUTE_GROUPS(smm665); - -static const struct i2c_device_id smm665_id[]; - -static int smm665_probe(struct i2c_client *client) -{ - struct i2c_adapter *adapter = client->adapter; - struct smm665_data *data; - struct device *hwmon_dev; - int i, ret; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA - | I2C_FUNC_SMBUS_WORD_DATA)) - return -ENODEV; - - if (i2c_smbus_read_byte_data(client, SMM665_ADOC_ENABLE) < 0) - return -ENODEV; - - data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - data->client = client; - data->type = i2c_match_id(smm665_id, client)->driver_data; - data->cmdreg = i2c_new_dummy_device(adapter, (client->addr & ~SMM665_REGMASK) - | SMM665_CMDREG_BASE); - if (IS_ERR(data->cmdreg)) - return PTR_ERR(data->cmdreg); - - switch (data->type) { - case smm465: - case smm665: - data->conversion_time = SMM665_ADC_WAIT_SMM665; - break; - case smm665c: - case smm764: - case smm766: - data->conversion_time = SMM665_ADC_WAIT_SMM766; - break; - } - - ret = -ENODEV; - if (i2c_smbus_read_byte_data(data->cmdreg, SMM665_MISC8_CMD_STS) < 0) - goto out_unregister; - - /* - * Read limits. - * - * Limit registers start with register SMM665_LIMIT_BASE. - * Each channel uses 8 registers, providing four limit values - * per channel. Each limit value requires two registers, with the - * high byte in the first register and the low byte in the second - * register. The first two limits are under limit values, followed - * by two over limit values. - * - * Limit register order matches the ADC register order, so we use - * ADC register defines throughout the code to index limit registers. - * - * We save the first retrieved value both as "critical" and "alarm" - * value. The second value overwrites either the critical or the - * alarm value, depending on its configuration. This ensures that both - * critical and alarm values are initialized, even if both registers are - * configured as critical or non-critical. - */ - for (i = 0; i < SMM665_NUM_ADC; i++) { - int val; - - val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8); - if (unlikely(val < 0)) - goto out_unregister; - data->critical_min_limit[i] = data->alarm_min_limit[i] - = smm665_convert(val, i); - val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 2); - if (unlikely(val < 0)) - goto out_unregister; - if (smm665_is_critical(val)) - data->critical_min_limit[i] = smm665_convert(val, i); - else - data->alarm_min_limit[i] = smm665_convert(val, i); - val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 4); - if (unlikely(val < 0)) - goto out_unregister; - data->critical_max_limit[i] = data->alarm_max_limit[i] - = smm665_convert(val, i); - val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 6); - if (unlikely(val < 0)) - goto out_unregister; - if (smm665_is_critical(val)) - data->critical_max_limit[i] = smm665_convert(val, i); - else - data->alarm_max_limit[i] = smm665_convert(val, i); - } - - hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev, - client->name, data, - smm665_groups); - if (IS_ERR(hwmon_dev)) { - ret = PTR_ERR(hwmon_dev); - goto out_unregister; - } - - return 0; - -out_unregister: - i2c_unregister_device(data->cmdreg); - return ret; -} - -static void smm665_remove(struct i2c_client *client) -{ - struct smm665_data *data = i2c_get_clientdata(client); - - i2c_unregister_device(data->cmdreg); -} - -static const struct i2c_device_id smm665_id[] = { - {"smm465", smm465}, - {"smm665", smm665}, - {"smm665c", smm665c}, - {"smm764", smm764}, - {"smm766", smm766}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, smm665_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver smm665_driver = { - .driver = { - .name = "smm665", - }, - .probe = smm665_probe, - .remove = smm665_remove, - .id_table = smm665_id, -}; - -module_i2c_driver(smm665_driver); - -MODULE_AUTHOR("Guenter Roeck"); -MODULE_DESCRIPTION("SMM665 driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c index 3cde3916ab6d..10b66c9ce045 100644 --- a/drivers/hwmon/tmp421.c +++ b/drivers/hwmon/tmp421.c @@ -20,7 +20,7 @@ #include <linux/hwmon-sysfs.h> #include <linux/err.h> #include <linux/mutex.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/sysfs.h> /* Addresses to scan */ diff --git a/drivers/hwmon/tmp464.c b/drivers/hwmon/tmp464.c index 4b79c3f4d9fe..f58ca4c6acb6 100644 --- a/drivers/hwmon/tmp464.c +++ b/drivers/hwmon/tmp464.c @@ -14,7 +14,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/mutex.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regmap.h> #include <linux/slab.h> diff --git a/drivers/hwmon/tmp513.c b/drivers/hwmon/tmp513.c index bff10f4b56e1..9a180b1030c9 100644 --- a/drivers/hwmon/tmp513.c +++ b/drivers/hwmon/tmp513.c @@ -434,7 +434,7 @@ static umode_t tmp51x_is_visible(const void *_data, switch (type) { case hwmon_temp: - if (data->id == tmp512 && channel == 4) + if (data->id == tmp512 && channel == 3) return 0; switch (attr) { case hwmon_temp_input: @@ -720,10 +720,7 @@ static int tmp51x_probe(struct i2c_client *client) if (!data) return -ENOMEM; - if (client->dev.of_node) - data->id = (enum tmp51x_ids)device_get_match_data(&client->dev); - else - data->id = i2c_match_id(tmp51x_id, client)->driver_data; + data->id = (uintptr_t)i2c_get_match_data(client); ret = tmp51x_configure(dev, data); if (ret < 0) { diff --git a/drivers/hwmon/tps23861.c b/drivers/hwmon/tps23861.c index 8fbbb29ae11d..d33ecbac00d6 100644 --- a/drivers/hwmon/tps23861.c +++ b/drivers/hwmon/tps23861.c @@ -14,7 +14,7 @@ #include <linux/hwmon.h> #include <linux/i2c.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regmap.h> #define TEMPERATURE 0x2c diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c index b23cff2e3d5d..3b580f229887 100644 --- a/drivers/hwmon/ultra45_env.c +++ b/drivers/hwmon/ultra45_env.c @@ -9,7 +9,8 @@ #include <linux/types.h> #include <linux/slab.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/io.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> diff --git a/drivers/hwmon/vexpress-hwmon.c b/drivers/hwmon/vexpress-hwmon.c index 2ac5fb96bba4..d82a3b454d0e 100644 --- a/drivers/hwmon/vexpress-hwmon.c +++ b/drivers/hwmon/vexpress-hwmon.c @@ -13,7 +13,6 @@ #include <linux/hwmon-sysfs.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/vexpress.h> diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c index 37d7374896f6..407933d6e425 100644 --- a/drivers/hwmon/via686a.c +++ b/drivers/hwmon/via686a.c @@ -855,16 +855,17 @@ static int via686a_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { u16 address, val; + int ret; if (force_addr) { address = force_addr & ~(VIA686A_EXTENT - 1); dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", address); - if (PCIBIOS_SUCCESSFUL != - pci_write_config_word(dev, VIA686A_BASE_REG, address | 1)) + ret = pci_write_config_word(dev, VIA686A_BASE_REG, address | 1); + if (ret != PCIBIOS_SUCCESSFUL) return -ENODEV; } - if (PCIBIOS_SUCCESSFUL != - pci_read_config_word(dev, VIA686A_BASE_REG, &val)) + ret = pci_read_config_word(dev, VIA686A_BASE_REG, &val); + if (ret != PCIBIOS_SUCCESSFUL) return -ENODEV; address = val & ~(VIA686A_EXTENT - 1); @@ -874,8 +875,8 @@ static int via686a_pci_probe(struct pci_dev *dev, return -ENODEV; } - if (PCIBIOS_SUCCESSFUL != - pci_read_config_word(dev, VIA686A_ENABLE_REG, &val)) + ret = pci_read_config_word(dev, VIA686A_ENABLE_REG, &val); + if (ret != PCIBIOS_SUCCESSFUL) return -ENODEV; if (!(val & 0x0001)) { if (!force_addr) { @@ -886,9 +887,8 @@ static int via686a_pci_probe(struct pci_dev *dev, } dev_warn(&dev->dev, "Enabling sensors\n"); - if (PCIBIOS_SUCCESSFUL != - pci_write_config_word(dev, VIA686A_ENABLE_REG, - val | 0x0001)) + ret = pci_write_config_word(dev, VIA686A_ENABLE_REG, val | 0x1); + if (ret != PCIBIOS_SUCCESSFUL) return -ENODEV; } diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index b7c6392ba673..16bc16d33cd1 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c @@ -971,13 +971,15 @@ static int vt8231_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { u16 address, val; + int ret; + if (force_addr) { address = force_addr & 0xff00; dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", address); - if (PCIBIOS_SUCCESSFUL != - pci_write_config_word(dev, VT8231_BASE_REG, address | 1)) + ret = pci_write_config_word(dev, VT8231_BASE_REG, address | 1); + if (ret != PCIBIOS_SUCCESSFUL) return -ENODEV; } @@ -997,9 +999,8 @@ static int vt8231_pci_probe(struct pci_dev *dev, if (!(val & 0x0001)) { dev_warn(&dev->dev, "enabling sensors\n"); - if (PCIBIOS_SUCCESSFUL != - pci_write_config_word(dev, VT8231_ENABLE_REG, - val | 0x0001)) + ret = pci_write_config_word(dev, VT8231_ENABLE_REG, val | 0x1); + if (ret != PCIBIOS_SUCCESSFUL) return -ENODEV; } diff --git a/drivers/hwmon/w83773g.c b/drivers/hwmon/w83773g.c index 7f3615f5587c..045eea8378c2 100644 --- a/drivers/hwmon/w83773g.c +++ b/drivers/hwmon/w83773g.c @@ -12,7 +12,7 @@ #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/err.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regmap.h> /* W83773 has 3 channels */ diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 256c2d42e350..ea5a6a14c553 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -923,7 +923,7 @@ static struct cpuidle_state adl_l_cstates[] __initdata = { .enter = NULL } }; -static struct cpuidle_state adl_n_cstates[] __initdata = { +static struct cpuidle_state gmt_cstates[] __initdata = { { .name = "C1", .desc = "MWAIT 0x00", @@ -1349,8 +1349,8 @@ static const struct idle_cpu idle_cpu_adl_l __initconst = { .state_table = adl_l_cstates, }; -static const struct idle_cpu idle_cpu_adl_n __initconst = { - .state_table = adl_n_cstates, +static const struct idle_cpu idle_cpu_gmt __initconst = { + .state_table = gmt_cstates, }; static const struct idle_cpu idle_cpu_spr __initconst = { @@ -1423,7 +1423,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = { X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D, &idle_cpu_icx), X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, &idle_cpu_adl), X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, &idle_cpu_adl_l), - X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, &idle_cpu_adl_n), + X86_MATCH_INTEL_FAM6_MODEL(ATOM_GRACEMONT, &idle_cpu_gmt), X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X, &idle_cpu_spr), X86_MATCH_INTEL_FAM6_MODEL(EMERALDRAPIDS_X, &idle_cpu_spr), X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL, &idle_cpu_knl), @@ -1898,7 +1898,7 @@ static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv) break; case INTEL_FAM6_ALDERLAKE: case INTEL_FAM6_ALDERLAKE_L: - case INTEL_FAM6_ALDERLAKE_N: + case INTEL_FAM6_ATOM_GRACEMONT: adl_idle_state_table_update(); break; } diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c index a973905afd13..ed7d4b02f45a 100644 --- a/drivers/infiniband/hw/qib/qib_fs.c +++ b/drivers/infiniband/hw/qib/qib_fs.c @@ -64,9 +64,8 @@ static int qibfs_mknod(struct inode *dir, struct dentry *dentry, inode->i_uid = GLOBAL_ROOT_UID; inode->i_gid = GLOBAL_ROOT_GID; inode->i_blocks = 0; - inode->i_atime = current_time(inode); + inode->i_atime = inode_set_ctime_current(inode); inode->i_mtime = inode->i_atime; - inode->i_ctime = inode->i_atime; inode->i_private = data; if (S_ISDIR(mode)) { inode->i_op = &simple_dir_inode_operations; diff --git a/drivers/irqchip/irq-bcm6345-l1.c b/drivers/irqchip/irq-bcm6345-l1.c index 6341c0167c4a..9745a119d0e6 100644 --- a/drivers/irqchip/irq-bcm6345-l1.c +++ b/drivers/irqchip/irq-bcm6345-l1.c @@ -60,7 +60,6 @@ #include <linux/of.h> #include <linux/of_irq.h> #include <linux/of_address.h> -#include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/smp.h> diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c index a62b96237b82..24ca1d656adc 100644 --- a/drivers/irqchip/irq-bcm7038-l1.c +++ b/drivers/irqchip/irq-bcm7038-l1.c @@ -20,7 +20,6 @@ #include <linux/of.h> #include <linux/of_irq.h> #include <linux/of_address.h> -#include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/smp.h> diff --git a/drivers/irqchip/irq-brcmstb-l2.c b/drivers/irqchip/irq-brcmstb-l2.c index 091b0fe7e324..5559c943f03f 100644 --- a/drivers/irqchip/irq-brcmstb-l2.c +++ b/drivers/irqchip/irq-brcmstb-l2.c @@ -15,7 +15,6 @@ #include <linux/of.h> #include <linux/of_irq.h> #include <linux/of_address.h> -#include <linux/of_platform.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/io.h> diff --git a/drivers/irqchip/irq-gic-pm.c b/drivers/irqchip/irq-gic-pm.c index 3989d16f997b..a275a8071a25 100644 --- a/drivers/irqchip/irq-gic-pm.c +++ b/drivers/irqchip/irq-gic-pm.c @@ -4,7 +4,7 @@ */ #include <linux/module.h> #include <linux/clk.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/of_irq.h> #include <linux/irqchip/arm-gic.h> #include <linux/platform_device.h> diff --git a/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c index 634263dfd7b5..8e87fc35f8aa 100644 --- a/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c +++ b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c @@ -9,8 +9,6 @@ #include <linux/acpi.h> #include <linux/acpi_iort.h> -#include <linux/of_device.h> -#include <linux/of_address.h> #include <linux/irq.h> #include <linux/msi.h> #include <linux/of.h> diff --git a/drivers/irqchip/irq-i8259.c b/drivers/irqchip/irq-i8259.c index b70ce0d3c092..115bdcffab24 100644 --- a/drivers/irqchip/irq-i8259.c +++ b/drivers/irqchip/irq-i8259.c @@ -340,7 +340,7 @@ static void i8259_irq_dispatch(struct irq_desc *desc) generic_handle_domain_irq(domain, hwirq); } -int __init i8259_of_init(struct device_node *node, struct device_node *parent) +static int __init i8259_of_init(struct device_node *node, struct device_node *parent) { struct irq_domain *domain; unsigned int parent_irq; diff --git a/drivers/irqchip/irq-imx-intmux.c b/drivers/irqchip/irq-imx-intmux.c index 80aaea82468a..6d9a08238c9d 100644 --- a/drivers/irqchip/irq-imx-intmux.c +++ b/drivers/irqchip/irq-imx-intmux.c @@ -50,8 +50,9 @@ #include <linux/irqchip/chained_irq.h> #include <linux/irqdomain.h> #include <linux/kernel.h> +#include <linux/mod_devicetable.h> #include <linux/of_irq.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/spinlock.h> #include <linux/pm_runtime.h> diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c index 96230a04ec23..bd9543314539 100644 --- a/drivers/irqchip/irq-imx-irqsteer.c +++ b/drivers/irqchip/irq-imx-irqsteer.c @@ -10,8 +10,9 @@ #include <linux/irqchip/chained_irq.h> #include <linux/irqdomain.h> #include <linux/kernel.h> +#include <linux/of.h> #include <linux/of_irq.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/spinlock.h> diff --git a/drivers/irqchip/irq-imx-mu-msi.c b/drivers/irqchip/irq-imx-mu-msi.c index 229039eda1b1..90d41c1407ac 100644 --- a/drivers/irqchip/irq-imx-mu-msi.c +++ b/drivers/irqchip/irq-imx-mu-msi.c @@ -339,8 +339,8 @@ static int __init imx_mu_of_init(struct device_node *dn, msi_data->msiir_addr = res->start + msi_data->cfg->xTR; irq = platform_get_irq(pdev, 0); - if (irq <= 0) - return -ENODEV; + if (irq < 0) + return irq; platform_set_drvdata(pdev, msi_data); diff --git a/drivers/irqchip/irq-keystone.c b/drivers/irqchip/irq-keystone.c index ba9792e60329..a36396db4b08 100644 --- a/drivers/irqchip/irq-keystone.c +++ b/drivers/irqchip/irq-keystone.c @@ -15,7 +15,7 @@ #include <linux/irqdomain.h> #include <linux/irqchip.h> #include <linux/of.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/mfd/syscon.h> #include <linux/regmap.h> diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index 92d8aa28bdf5..1623cd779175 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -144,7 +144,7 @@ static int eiointc_router_init(unsigned int cpu) int i, bit; uint32_t data; uint32_t node = cpu_to_eio_node(cpu); - uint32_t index = eiointc_index(node); + int index = eiointc_index(node); if (index < 0) { pr_err("Error: invalid nodemap!\n"); diff --git a/drivers/irqchip/irq-loongson-htvec.c b/drivers/irqchip/irq-loongson-htvec.c index fc8bf1f5d41b..0bff728b25e3 100644 --- a/drivers/irqchip/irq-loongson-htvec.c +++ b/drivers/irqchip/irq-loongson-htvec.c @@ -15,7 +15,6 @@ #include <linux/platform_device.h> #include <linux/of_address.h> #include <linux/of_irq.h> -#include <linux/of_platform.h> #include <linux/syscore_ops.h> /* Registers */ diff --git a/drivers/irqchip/irq-loongson-pch-pic.c b/drivers/irqchip/irq-loongson-pch-pic.c index 93a71f66efeb..63db8e2172e0 100644 --- a/drivers/irqchip/irq-loongson-pch-pic.c +++ b/drivers/irqchip/irq-loongson-pch-pic.c @@ -12,9 +12,9 @@ #include <linux/irqdomain.h> #include <linux/kernel.h> #include <linux/platform_device.h> +#include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> -#include <linux/of_platform.h> #include <linux/syscore_ops.h> /* Registers */ diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c index f5ba3f9f8415..f31a262fe438 100644 --- a/drivers/irqchip/irq-ls-scfg-msi.c +++ b/drivers/irqchip/irq-ls-scfg-msi.c @@ -349,8 +349,7 @@ static int ls_scfg_msi_probe(struct platform_device *pdev) msi_data->cfg = (struct ls_scfg_msi_cfg *) match->data; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - msi_data->regs = devm_ioremap_resource(&pdev->dev, res); + msi_data->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(msi_data->regs)) { dev_err(&pdev->dev, "failed to initialize 'regs'\n"); return PTR_ERR(msi_data->regs); diff --git a/drivers/irqchip/irq-madera.c b/drivers/irqchip/irq-madera.c index 8b81271c823c..3eb1f8cdf674 100644 --- a/drivers/irqchip/irq-madera.c +++ b/drivers/irqchip/irq-madera.c @@ -10,12 +10,10 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/irqdomain.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/slab.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> #include <linux/irqchip/irq-madera.h> #include <linux/mfd/madera/core.h> #include <linux/mfd/madera/pdata.h> diff --git a/drivers/irqchip/irq-meson-gpio.c b/drivers/irqchip/irq-meson-gpio.c index 7da18ef95211..f88df39f4129 100644 --- a/drivers/irqchip/irq-meson-gpio.c +++ b/drivers/irqchip/irq-meson-gpio.c @@ -150,6 +150,10 @@ static const struct meson_gpio_irq_params s4_params = { INIT_MESON_S4_COMMON_DATA(82) }; +static const struct meson_gpio_irq_params c3_params = { + INIT_MESON_S4_COMMON_DATA(55) +}; + static const struct of_device_id meson_irq_gpio_matches[] __maybe_unused = { { .compatible = "amlogic,meson8-gpio-intc", .data = &meson8_params }, { .compatible = "amlogic,meson8b-gpio-intc", .data = &meson8b_params }, @@ -160,6 +164,7 @@ static const struct of_device_id meson_irq_gpio_matches[] __maybe_unused = { { .compatible = "amlogic,meson-sm1-gpio-intc", .data = &sm1_params }, { .compatible = "amlogic,meson-a1-gpio-intc", .data = &a1_params }, { .compatible = "amlogic,meson-s4-gpio-intc", .data = &s4_params }, + { .compatible = "amlogic,c3-gpio-intc", .data = &c3_params }, { } }; diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 6d5ecc10a870..76253e864f23 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -557,7 +557,7 @@ static int gic_irq_domain_alloc(struct irq_domain *d, unsigned int virq, return gic_irq_domain_map(d, virq, hwirq); } -void gic_irq_domain_free(struct irq_domain *d, unsigned int virq, +static void gic_irq_domain_free(struct irq_domain *d, unsigned int virq, unsigned int nr_irqs) { } diff --git a/drivers/irqchip/irq-mvebu-sei.c b/drivers/irqchip/irq-mvebu-sei.c index 4ecef6d83777..a48dbe91b036 100644 --- a/drivers/irqchip/irq-mvebu-sei.c +++ b/drivers/irqchip/irq-mvebu-sei.c @@ -377,8 +377,7 @@ static int mvebu_sei_probe(struct platform_device *pdev) mutex_init(&sei->cp_msi_lock); raw_spin_lock_init(&sei->mask_lock); - sei->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - sei->base = devm_ioremap_resource(sei->dev, sei->res); + sei->base = devm_platform_get_and_ioremap_resource(pdev, 0, &sei->res); if (IS_ERR(sei->base)) return PTR_ERR(sei->base); diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c index 17c2c7a07f10..4e4e874e09a8 100644 --- a/drivers/irqchip/irq-orion.c +++ b/drivers/irqchip/irq-orion.c @@ -57,8 +57,7 @@ static int __init orion_irq_init(struct device_node *np, struct resource r; /* count number of irq chips by valid reg addresses */ - while (of_address_to_resource(np, num_chips, &r) == 0) - num_chips++; + num_chips = of_address_count(np); orion_irq_domain = irq_domain_add_linear(np, num_chips * ORION_IRQS_PER_CHIP, diff --git a/drivers/irqchip/irq-pruss-intc.c b/drivers/irqchip/irq-pruss-intc.c index fa8d89b02ec0..0f64ecb9b1f4 100644 --- a/drivers/irqchip/irq-pruss-intc.c +++ b/drivers/irqchip/irq-pruss-intc.c @@ -17,7 +17,7 @@ #include <linux/irqchip/chained_irq.h> #include <linux/irqdomain.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> /* @@ -565,8 +565,8 @@ static int pruss_intc_probe(struct platform_device *pdev) continue; irq = platform_get_irq_byname(pdev, irq_names[i]); - if (irq <= 0) { - ret = (irq == 0) ? -EINVAL : irq; + if (irq < 0) { + ret = irq; goto fail_irq; } diff --git a/drivers/irqchip/irq-qcom-mpm.c b/drivers/irqchip/irq-qcom-mpm.c index d30614661eea..7124565234a5 100644 --- a/drivers/irqchip/irq-qcom-mpm.c +++ b/drivers/irqchip/irq-qcom-mpm.c @@ -14,7 +14,7 @@ #include <linux/mailbox_client.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> +#include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/slab.h> diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c index 26e4c17a7bf2..fa19585f3dee 100644 --- a/drivers/irqchip/irq-renesas-intc-irqpin.c +++ b/drivers/irqchip/irq-renesas-intc-irqpin.c @@ -17,7 +17,6 @@ #include <linux/err.h> #include <linux/slab.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/pm_runtime.h> #define INTC_IRQPIN_MAX 8 /* maximum 8 interrupts per driver instance */ diff --git a/drivers/irqchip/irq-st.c b/drivers/irqchip/irq-st.c index 819a12297b58..de71bb350d57 100644 --- a/drivers/irqchip/irq-st.c +++ b/drivers/irqchip/irq-st.c @@ -10,7 +10,7 @@ #include <dt-bindings/interrupt-controller/irq-st.h> #include <linux/err.h> #include <linux/mfd/syscon.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/slab.h> diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c index b5fa76ce5046..d8ba5fba7450 100644 --- a/drivers/irqchip/irq-stm32-exti.c +++ b/drivers/irqchip/irq-stm32-exti.c @@ -14,10 +14,11 @@ #include <linux/irqchip.h> #include <linux/irqchip/chained_irq.h> #include <linux/irqdomain.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/of_address.h> #include <linux/of_irq.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/syscore_ops.h> #include <dt-bindings/interrupt-controller/arm-gic.h> diff --git a/drivers/irqchip/irq-sunxi-nmi.c b/drivers/irqchip/irq-sunxi-nmi.c index 21d49791f855..e760b1278143 100644 --- a/drivers/irqchip/irq-sunxi-nmi.c +++ b/drivers/irqchip/irq-sunxi-nmi.c @@ -19,7 +19,6 @@ #include <linux/irqdomain.h> #include <linux/of_irq.h> #include <linux/of_address.h> -#include <linux/of_platform.h> #include <linux/irqchip.h> #include <linux/irqchip/chained_irq.h> diff --git a/drivers/irqchip/irq-tb10x.c b/drivers/irqchip/irq-tb10x.c index 8a0e69298e83..680586354d12 100644 --- a/drivers/irqchip/irq-tb10x.c +++ b/drivers/irqchip/irq-tb10x.c @@ -13,7 +13,6 @@ #include <linux/irqchip.h> #include <linux/of_irq.h> #include <linux/of_address.h> -#include <linux/of_platform.h> #include <linux/io.h> #include <linux/slab.h> #include <linux/bitops.h> diff --git a/drivers/irqchip/irq-ti-sci-inta.c b/drivers/irqchip/irq-ti-sci-inta.c index 7133f9fa6fd9..b83f5cbab123 100644 --- a/drivers/irqchip/irq-ti-sci-inta.c +++ b/drivers/irqchip/irq-ti-sci-inta.c @@ -15,9 +15,9 @@ #include <linux/msi.h> #include <linux/module.h> #include <linux/moduleparam.h> -#include <linux/of_address.h> +#include <linux/of.h> #include <linux/of_irq.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/irqchip/chained_irq.h> #include <linux/soc/ti/ti_sci_inta_msi.h> #include <linux/soc/ti/ti_sci_protocol.h> diff --git a/drivers/irqchip/irq-ti-sci-intr.c b/drivers/irqchip/irq-ti-sci-intr.c index 1186f1e431a3..c027cd9e4a69 100644 --- a/drivers/irqchip/irq-ti-sci-intr.c +++ b/drivers/irqchip/irq-ti-sci-intr.c @@ -12,9 +12,9 @@ #include <linux/io.h> #include <linux/irqchip.h> #include <linux/irqdomain.h> -#include <linux/of_platform.h> -#include <linux/of_address.h> +#include <linux/of.h> #include <linux/of_irq.h> +#include <linux/platform_device.h> #include <linux/soc/ti/ti_sci_protocol.h> /** diff --git a/drivers/irqchip/irq-uniphier-aidet.c b/drivers/irqchip/irq-uniphier-aidet.c index 716b1bb88bf2..601f9343d5b3 100644 --- a/drivers/irqchip/irq-uniphier-aidet.c +++ b/drivers/irqchip/irq-uniphier-aidet.c @@ -12,7 +12,6 @@ #include <linux/irqdomain.h> #include <linux/kernel.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/platform_device.h> #include <linux/spinlock.h> diff --git a/drivers/irqchip/irq-xtensa-pic.c b/drivers/irqchip/irq-xtensa-pic.c index ab12328be5ee..0c18d1f1e264 100644 --- a/drivers/irqchip/irq-xtensa-pic.c +++ b/drivers/irqchip/irq-xtensa-pic.c @@ -16,6 +16,7 @@ #include <linux/irqdomain.h> #include <linux/irq.h> #include <linux/irqchip.h> +#include <linux/irqchip/xtensa-pic.h> #include <linux/of.h> unsigned int cached_irq_mask; diff --git a/drivers/irqchip/irqchip.c b/drivers/irqchip/irqchip.c index 7899607fbee8..1eeb0d0156ce 100644 --- a/drivers/irqchip/irqchip.c +++ b/drivers/irqchip/irqchip.c @@ -10,7 +10,7 @@ #include <linux/acpi.h> #include <linux/init.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/of_irq.h> #include <linux/irqchip.h> #include <linux/platform_device.h> diff --git a/drivers/irqchip/qcom-pdc.c b/drivers/irqchip/qcom-pdc.c index d96916cf6a41..a32c0d28d038 100644 --- a/drivers/irqchip/qcom-pdc.c +++ b/drivers/irqchip/qcom-pdc.c @@ -14,7 +14,6 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/soc/qcom/irq.h> #include <linux/spinlock.h> diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c index 9ff439a50f53..315e97a2450e 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c @@ -821,6 +821,8 @@ static int vb2ops_venc_queue_setup(struct vb2_queue *vq, return -EINVAL; if (*nplanes) { + if (*nplanes != q_data->fmt->num_planes) + return -EINVAL; for (i = 0; i < *nplanes; i++) if (sizes[i] < q_data->sizeimage[i]) return -EINVAL; diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 6f5b259a6d6a..85be64579fc9 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -237,6 +237,29 @@ config MFD_CROS_EC_DEV To compile this driver as a module, choose M here: the module will be called cros-ec-dev. +config MFD_CS42L43 + tristate + select MFD_CORE + select REGMAP + +config MFD_CS42L43_I2C + tristate "Cirrus Logic CS42L43 (I2C)" + depends on I2C + select REGMAP_I2C + select MFD_CS42L43 + help + Select this to support the Cirrus Logic CS42L43 PC CODEC with + headphone and class D speaker drivers over I2C. + +config MFD_CS42L43_SDW + tristate "Cirrus Logic CS42L43 (SoundWire)" + depends on SOUNDWIRE + select REGMAP_SOUNDWIRE + select MFD_CS42L43 + help + Select this to support the Cirrus Logic CS42L43 PC CODEC with + headphone and class D speaker drivers over SoundWire. + config MFD_MADERA tristate "Cirrus Logic Madera codecs" select MFD_CORE diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index f3d1f1dc73b5..c66f07edcd0e 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -13,6 +13,9 @@ obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o obj-$(CONFIG_MFD_CROS_EC_DEV) += cros_ec_dev.o +obj-$(CONFIG_MFD_CS42L43) += cs42l43.o +obj-$(CONFIG_MFD_CS42L43_I2C) += cs42l43-i2c.o +obj-$(CONFIG_MFD_CS42L43_SDW) += cs42l43-sdw.o obj-$(CONFIG_MFD_ENE_KB3930) += ene-kb3930.o obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o obj-$(CONFIG_MFD_GATEWORKS_GSC) += gateworks-gsc.o diff --git a/drivers/mfd/cs42l43-i2c.c b/drivers/mfd/cs42l43-i2c.c new file mode 100644 index 000000000000..4922211680c9 --- /dev/null +++ b/drivers/mfd/cs42l43-i2c.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * CS42L43 I2C driver + * + * Copyright (C) 2022-2023 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/i2c.h> +#include <linux/mfd/cs42l43-regs.h> +#include <linux/module.h> + +#include "cs42l43.h" + +static const struct regmap_config cs42l43_i2c_regmap = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .reg_format_endian = REGMAP_ENDIAN_BIG, + .val_format_endian = REGMAP_ENDIAN_BIG, + + .max_register = CS42L43_MCU_RAM_MAX, + .readable_reg = cs42l43_readable_register, + .volatile_reg = cs42l43_volatile_register, + .precious_reg = cs42l43_precious_register, + + .cache_type = REGCACHE_MAPLE, + .reg_defaults = cs42l43_reg_default, + .num_reg_defaults = ARRAY_SIZE(cs42l43_reg_default), +}; + +static int cs42l43_i2c_probe(struct i2c_client *i2c) +{ + struct cs42l43 *cs42l43; + int ret; + + cs42l43 = devm_kzalloc(&i2c->dev, sizeof(*cs42l43), GFP_KERNEL); + if (!cs42l43) + return -ENOMEM; + + cs42l43->dev = &i2c->dev; + cs42l43->irq = i2c->irq; + /* A device on an I2C is always attached by definition. */ + cs42l43->attached = true; + + cs42l43->regmap = devm_regmap_init_i2c(i2c, &cs42l43_i2c_regmap); + if (IS_ERR(cs42l43->regmap)) { + ret = PTR_ERR(cs42l43->regmap); + dev_err(cs42l43->dev, "Failed to allocate regmap: %d\n", ret); + return ret; + } + + return cs42l43_dev_probe(cs42l43); +} + +static void cs42l43_i2c_remove(struct i2c_client *i2c) +{ + struct cs42l43 *cs42l43 = dev_get_drvdata(&i2c->dev); + + cs42l43_dev_remove(cs42l43); +} + +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id cs42l43_of_match[] = { + { .compatible = "cirrus,cs42l43", }, + {} +}; +MODULE_DEVICE_TABLE(of, cs42l43_of_match); +#endif + +#if IS_ENABLED(CONFIG_ACPI) +static const struct acpi_device_id cs42l43_acpi_match[] = { + { "CSC4243", 0 }, + {} +}; +MODULE_DEVICE_TABLE(acpi, cs42l43_acpi_match); +#endif + +static struct i2c_driver cs42l43_i2c_driver = { + .driver = { + .name = "cs42l43", + .pm = pm_ptr(&cs42l43_pm_ops), + .of_match_table = of_match_ptr(cs42l43_of_match), + .acpi_match_table = ACPI_PTR(cs42l43_acpi_match), + }, + + .probe = cs42l43_i2c_probe, + .remove = cs42l43_i2c_remove, +}; +module_i2c_driver(cs42l43_i2c_driver); + +MODULE_IMPORT_NS(MFD_CS42L43); + +MODULE_DESCRIPTION("CS42L43 I2C Driver"); +MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/cs42l43-sdw.c b/drivers/mfd/cs42l43-sdw.c new file mode 100644 index 000000000000..7392b3d2e6b9 --- /dev/null +++ b/drivers/mfd/cs42l43-sdw.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * CS42L43 SoundWire driver + * + * Copyright (C) 2022-2023 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/mfd/cs42l43-regs.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/soundwire/sdw.h> +#include <linux/soundwire/sdw_registers.h> +#include <linux/soundwire/sdw_type.h> + +#include "cs42l43.h" + +enum cs42l43_sdw_ports { + CS42L43_DMIC_DEC_ASP_PORT = 1, + CS42L43_SPK_TX_PORT, + CS42L43_SPDIF_HP_PORT, + CS42L43_SPK_RX_PORT, + CS42L43_ASP_PORT, +}; + +static const struct regmap_config cs42l43_sdw_regmap = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .reg_format_endian = REGMAP_ENDIAN_LITTLE, + .val_format_endian = REGMAP_ENDIAN_LITTLE, + + .max_register = CS42L43_MCU_RAM_MAX, + .readable_reg = cs42l43_readable_register, + .volatile_reg = cs42l43_volatile_register, + .precious_reg = cs42l43_precious_register, + + .cache_type = REGCACHE_MAPLE, + .reg_defaults = cs42l43_reg_default, + .num_reg_defaults = ARRAY_SIZE(cs42l43_reg_default), +}; + +static int cs42l43_read_prop(struct sdw_slave *sdw) +{ + struct sdw_slave_prop *prop = &sdw->prop; + struct device *dev = &sdw->dev; + struct sdw_dpn_prop *dpn; + unsigned long addr; + int nval; + int i; + u32 bit; + + prop->use_domain_irq = true; + prop->paging_support = true; + prop->wake_capable = true; + prop->source_ports = BIT(CS42L43_DMIC_DEC_ASP_PORT) | BIT(CS42L43_SPK_TX_PORT); + prop->sink_ports = BIT(CS42L43_SPDIF_HP_PORT) | + BIT(CS42L43_SPK_RX_PORT) | BIT(CS42L43_ASP_PORT); + prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; + prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY | + SDW_SCP_INT1_IMPL_DEF; + + nval = hweight32(prop->source_ports); + prop->src_dpn_prop = devm_kcalloc(dev, nval, sizeof(*prop->src_dpn_prop), + GFP_KERNEL); + if (!prop->src_dpn_prop) + return -ENOMEM; + + i = 0; + dpn = prop->src_dpn_prop; + addr = prop->source_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[i].num = bit; + dpn[i].max_ch = 2; + dpn[i].type = SDW_DPN_FULL; + dpn[i].max_word = 24; + i++; + } + /* + * All ports are 2 channels max, except the first one, + * CS42L43_DMIC_DEC_ASP_PORT. + */ + dpn[CS42L43_DMIC_DEC_ASP_PORT].max_ch = 4; + + nval = hweight32(prop->sink_ports); + prop->sink_dpn_prop = devm_kcalloc(dev, nval, sizeof(*prop->sink_dpn_prop), + GFP_KERNEL); + if (!prop->sink_dpn_prop) + return -ENOMEM; + + i = 0; + dpn = prop->sink_dpn_prop; + addr = prop->sink_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[i].num = bit; + dpn[i].max_ch = 2; + dpn[i].type = SDW_DPN_FULL; + dpn[i].max_word = 24; + i++; + } + + return 0; +} + +static int cs42l43_sdw_update_status(struct sdw_slave *sdw, enum sdw_slave_status status) +{ + struct cs42l43 *cs42l43 = dev_get_drvdata(&sdw->dev); + + switch (status) { + case SDW_SLAVE_ATTACHED: + dev_dbg(cs42l43->dev, "Device attach\n"); + + sdw_write_no_pm(sdw, CS42L43_GEN_INT_MASK_1, + CS42L43_INT_STAT_GEN1_MASK); + + cs42l43->attached = true; + + complete(&cs42l43->device_attach); + break; + case SDW_SLAVE_UNATTACHED: + dev_dbg(cs42l43->dev, "Device detach\n"); + + cs42l43->attached = false; + + reinit_completion(&cs42l43->device_attach); + complete(&cs42l43->device_detach); + break; + default: + break; + } + + return 0; +} + +static int cs42l43_sdw_interrupt(struct sdw_slave *sdw, + struct sdw_slave_intr_status *status) +{ + /* + * The IRQ itself was handled through the regmap_irq handler, this is + * just clearing up the additional Cirrus SoundWire registers that are + * not covered by the SoundWire framework or the IRQ handler itself. + * There is only a single bit in GEN_INT_STAT_1 and it doesn't clear if + * IRQs are still pending so doing a read/write here after handling the + * IRQ is fine. + */ + sdw_read_no_pm(sdw, CS42L43_GEN_INT_STAT_1); + sdw_write_no_pm(sdw, CS42L43_GEN_INT_STAT_1, CS42L43_INT_STAT_GEN1_MASK); + + return 0; +} + +static int cs42l43_sdw_bus_config(struct sdw_slave *sdw, + struct sdw_bus_params *params) +{ + struct cs42l43 *cs42l43 = dev_get_drvdata(&sdw->dev); + int ret = 0; + + mutex_lock(&cs42l43->pll_lock); + + if (cs42l43->sdw_freq != params->curr_dr_freq / 2) { + if (cs42l43->sdw_pll_active) { + dev_err(cs42l43->dev, + "PLL active can't change SoundWire bus clock\n"); + ret = -EBUSY; + } else { + cs42l43->sdw_freq = params->curr_dr_freq / 2; + } + } + + mutex_unlock(&cs42l43->pll_lock); + + return ret; +} + +static const struct sdw_slave_ops cs42l43_sdw_ops = { + .read_prop = cs42l43_read_prop, + .update_status = cs42l43_sdw_update_status, + .interrupt_callback = cs42l43_sdw_interrupt, + .bus_config = cs42l43_sdw_bus_config, +}; + +static int cs42l43_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id) +{ + struct cs42l43 *cs42l43; + struct device *dev = &sdw->dev; + int ret; + + cs42l43 = devm_kzalloc(dev, sizeof(*cs42l43), GFP_KERNEL); + if (!cs42l43) + return -ENOMEM; + + cs42l43->dev = dev; + cs42l43->sdw = sdw; + + cs42l43->regmap = devm_regmap_init_sdw(sdw, &cs42l43_sdw_regmap); + if (IS_ERR(cs42l43->regmap)) { + ret = PTR_ERR(cs42l43->regmap); + dev_err(cs42l43->dev, "Failed to allocate regmap: %d\n", ret); + return ret; + } + + return cs42l43_dev_probe(cs42l43); +} + +static int cs42l43_sdw_remove(struct sdw_slave *sdw) +{ + struct cs42l43 *cs42l43 = dev_get_drvdata(&sdw->dev); + + cs42l43_dev_remove(cs42l43); + + return 0; +} + +static const struct sdw_device_id cs42l43_sdw_id[] = { + SDW_SLAVE_ENTRY(0x01FA, 0x4243, 0), + {} +}; +MODULE_DEVICE_TABLE(sdw, cs42l43_sdw_id); + +static struct sdw_driver cs42l43_sdw_driver = { + .driver = { + .name = "cs42l43", + .pm = pm_ptr(&cs42l43_pm_ops), + }, + + .probe = cs42l43_sdw_probe, + .remove = cs42l43_sdw_remove, + .id_table = cs42l43_sdw_id, + .ops = &cs42l43_sdw_ops, +}; +module_sdw_driver(cs42l43_sdw_driver); + +MODULE_IMPORT_NS(MFD_CS42L43); + +MODULE_DESCRIPTION("CS42L43 SoundWire Driver"); +MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/cs42l43.c b/drivers/mfd/cs42l43.c new file mode 100644 index 000000000000..37b23e9bae82 --- /dev/null +++ b/drivers/mfd/cs42l43.c @@ -0,0 +1,1188 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * CS42L43 core driver + * + * Copyright (C) 2022-2023 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#include <linux/bitops.h> +#include <linux/build_bug.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/firmware.h> +#include <linux/jiffies.h> +#include <linux/mfd/core.h> +#include <linux/mfd/cs42l43-regs.h> +#include <linux/module.h> +#include <linux/pm_runtime.h> +#include <linux/soundwire/sdw.h> + +#include "cs42l43.h" + +#define CS42L43_RESET_DELAY 20 + +#define CS42L43_SDW_ATTACH_TIMEOUT 500 +#define CS42L43_SDW_DETACH_TIMEOUT 100 + +#define CS42L43_MCU_BOOT_STAGE1 1 +#define CS42L43_MCU_BOOT_STAGE2 2 +#define CS42L43_MCU_BOOT_STAGE3 3 +#define CS42L43_MCU_BOOT_STAGE4 4 +#define CS42L43_MCU_POLL 5000 +#define CS42L43_MCU_CMD_TIMEOUT 20000 +#define CS42L43_MCU_UPDATE_FORMAT 3 +#define CS42L43_MCU_UPDATE_OFFSET 0x100000 +#define CS42L43_MCU_UPDATE_TIMEOUT 500000 +#define CS42L43_MCU_UPDATE_RETRIES 5 + +#define CS42L43_MCU_SUPPORTED_REV 0x2105 +#define CS42L43_MCU_SHADOW_REGS_REQUIRED_REV 0x2200 +#define CS42L43_MCU_SUPPORTED_BIOS_REV 0x0001 + +#define CS42L43_VDDP_DELAY 50 +#define CS42L43_VDDD_DELAY 1000 + +#define CS42L43_AUTOSUSPEND_TIME 250 + +struct cs42l43_patch_header { + __le16 version; + __le16 size; + u8 reserved; + u8 secure; + __le16 bss_size; + __le32 apply_addr; + __le32 checksum; + __le32 sha; + __le16 swrev; + __le16 patchid; + __le16 ipxid; + __le16 romver; + __le32 load_addr; +} __packed; + +static const struct reg_sequence cs42l43_reva_patch[] = { + { 0x4000, 0x00000055 }, + { 0x4000, 0x000000AA }, + { 0x10084, 0x00000000 }, + { 0x1741C, 0x00CD2000 }, + { 0x1718C, 0x00000003 }, + { 0x4000, 0x00000000 }, + { CS42L43_CCM_BLK_CLK_CONTROL, 0x00000002 }, + { CS42L43_HPPATHVOL, 0x011B011B }, + { CS42L43_OSC_DIV_SEL, 0x00000001 }, + { CS42L43_DACCNFG2, 0x00000005 }, + { CS42L43_MIC_DETECT_CONTROL_ANDROID, 0x80790079 }, + { CS42L43_RELID, 0x0000000F }, +}; + +const struct reg_default cs42l43_reg_default[CS42L43_N_DEFAULTS] = { + { CS42L43_DRV_CTRL1, 0x000186C0 }, + { CS42L43_DRV_CTRL3, 0x286DB018 }, + { CS42L43_DRV_CTRL4, 0x000006D8 }, + { CS42L43_DRV_CTRL_5, 0x136C00C0 }, + { CS42L43_GPIO_CTRL1, 0x00000707 }, + { CS42L43_GPIO_CTRL2, 0x00000000 }, + { CS42L43_GPIO_FN_SEL, 0x00000000 }, + { CS42L43_MCLK_SRC_SEL, 0x00000000 }, + { CS42L43_SAMPLE_RATE1, 0x00000003 }, + { CS42L43_SAMPLE_RATE2, 0x00000003 }, + { CS42L43_SAMPLE_RATE3, 0x00000003 }, + { CS42L43_SAMPLE_RATE4, 0x00000003 }, + { CS42L43_PLL_CONTROL, 0x00000000 }, + { CS42L43_FS_SELECT1, 0x00000000 }, + { CS42L43_FS_SELECT2, 0x00000000 }, + { CS42L43_FS_SELECT3, 0x00000000 }, + { CS42L43_FS_SELECT4, 0x00000000 }, + { CS42L43_PDM_CONTROL, 0x00000000 }, + { CS42L43_ASP_CLK_CONFIG1, 0x00010001 }, + { CS42L43_ASP_CLK_CONFIG2, 0x00000000 }, + { CS42L43_OSC_DIV_SEL, 0x00000001 }, + { CS42L43_ADC_B_CTRL1, 0x00000000 }, + { CS42L43_ADC_B_CTRL2, 0x00000000 }, + { CS42L43_DECIM_HPF_WNF_CTRL1, 0x00000001 }, + { CS42L43_DECIM_HPF_WNF_CTRL2, 0x00000001 }, + { CS42L43_DECIM_HPF_WNF_CTRL3, 0x00000001 }, + { CS42L43_DECIM_HPF_WNF_CTRL4, 0x00000001 }, + { CS42L43_DMIC_PDM_CTRL, 0x00000000 }, + { CS42L43_DECIM_VOL_CTRL_CH1_CH2, 0x20122012 }, + { CS42L43_DECIM_VOL_CTRL_CH3_CH4, 0x20122012 }, + { CS42L43_INTP_VOLUME_CTRL1, 0x00000180 }, + { CS42L43_INTP_VOLUME_CTRL2, 0x00000180 }, + { CS42L43_AMP1_2_VOL_RAMP, 0x00000022 }, + { CS42L43_ASP_CTRL, 0x00000004 }, + { CS42L43_ASP_FSYNC_CTRL1, 0x000000FA }, + { CS42L43_ASP_FSYNC_CTRL2, 0x00000001 }, + { CS42L43_ASP_FSYNC_CTRL3, 0x00000000 }, + { CS42L43_ASP_FSYNC_CTRL4, 0x000001F4 }, + { CS42L43_ASP_DATA_CTRL, 0x0000003A }, + { CS42L43_ASP_RX_EN, 0x00000000 }, + { CS42L43_ASP_TX_EN, 0x00000000 }, + { CS42L43_ASP_RX_CH1_CTRL, 0x00170001 }, + { CS42L43_ASP_RX_CH2_CTRL, 0x00170031 }, + { CS42L43_ASP_RX_CH3_CTRL, 0x00170061 }, + { CS42L43_ASP_RX_CH4_CTRL, 0x00170091 }, + { CS42L43_ASP_RX_CH5_CTRL, 0x001700C1 }, + { CS42L43_ASP_RX_CH6_CTRL, 0x001700F1 }, + { CS42L43_ASP_TX_CH1_CTRL, 0x00170001 }, + { CS42L43_ASP_TX_CH2_CTRL, 0x00170031 }, + { CS42L43_ASP_TX_CH3_CTRL, 0x00170061 }, + { CS42L43_ASP_TX_CH4_CTRL, 0x00170091 }, + { CS42L43_ASP_TX_CH5_CTRL, 0x001700C1 }, + { CS42L43_ASP_TX_CH6_CTRL, 0x001700F1 }, + { CS42L43_ASPTX1_INPUT, 0x00800000 }, + { CS42L43_ASPTX2_INPUT, 0x00800000 }, + { CS42L43_ASPTX3_INPUT, 0x00800000 }, + { CS42L43_ASPTX4_INPUT, 0x00800000 }, + { CS42L43_ASPTX5_INPUT, 0x00800000 }, + { CS42L43_ASPTX6_INPUT, 0x00800000 }, + { CS42L43_SWIRE_DP1_CH1_INPUT, 0x00800000 }, + { CS42L43_SWIRE_DP1_CH2_INPUT, 0x00800000 }, + { CS42L43_SWIRE_DP1_CH3_INPUT, 0x00800000 }, + { CS42L43_SWIRE_DP1_CH4_INPUT, 0x00800000 }, + { CS42L43_SWIRE_DP2_CH1_INPUT, 0x00800000 }, + { CS42L43_SWIRE_DP2_CH2_INPUT, 0x00800000 }, + { CS42L43_SWIRE_DP3_CH1_INPUT, 0x00800000 }, + { CS42L43_SWIRE_DP3_CH2_INPUT, 0x00800000 }, + { CS42L43_SWIRE_DP4_CH1_INPUT, 0x00800000 }, + { CS42L43_SWIRE_DP4_CH2_INPUT, 0x00800000 }, + { CS42L43_ASRC_INT1_INPUT1, 0x00800000 }, + { CS42L43_ASRC_INT2_INPUT1, 0x00800000 }, + { CS42L43_ASRC_INT3_INPUT1, 0x00800000 }, + { CS42L43_ASRC_INT4_INPUT1, 0x00800000 }, + { CS42L43_ASRC_DEC1_INPUT1, 0x00800000 }, + { CS42L43_ASRC_DEC2_INPUT1, 0x00800000 }, + { CS42L43_ASRC_DEC3_INPUT1, 0x00800000 }, + { CS42L43_ASRC_DEC4_INPUT1, 0x00800000 }, + { CS42L43_ISRC1INT1_INPUT1, 0x00800000 }, + { CS42L43_ISRC1INT2_INPUT1, 0x00800000 }, + { CS42L43_ISRC1DEC1_INPUT1, 0x00800000 }, + { CS42L43_ISRC1DEC2_INPUT1, 0x00800000 }, + { CS42L43_ISRC2INT1_INPUT1, 0x00800000 }, + { CS42L43_ISRC2INT2_INPUT1, 0x00800000 }, + { CS42L43_ISRC2DEC1_INPUT1, 0x00800000 }, + { CS42L43_ISRC2DEC2_INPUT1, 0x00800000 }, + { CS42L43_EQ1MIX_INPUT1, 0x00800000 }, + { CS42L43_EQ1MIX_INPUT2, 0x00800000 }, + { CS42L43_EQ1MIX_INPUT3, 0x00800000 }, + { CS42L43_EQ1MIX_INPUT4, 0x00800000 }, + { CS42L43_EQ2MIX_INPUT1, 0x00800000 }, + { CS42L43_EQ2MIX_INPUT2, 0x00800000 }, + { CS42L43_EQ2MIX_INPUT3, 0x00800000 }, + { CS42L43_EQ2MIX_INPUT4, 0x00800000 }, + { CS42L43_SPDIF1_INPUT1, 0x00800000 }, + { CS42L43_SPDIF2_INPUT1, 0x00800000 }, + { CS42L43_AMP1MIX_INPUT1, 0x00800000 }, + { CS42L43_AMP1MIX_INPUT2, 0x00800000 }, + { CS42L43_AMP1MIX_INPUT3, 0x00800000 }, + { CS42L43_AMP1MIX_INPUT4, 0x00800000 }, + { CS42L43_AMP2MIX_INPUT1, 0x00800000 }, + { CS42L43_AMP2MIX_INPUT2, 0x00800000 }, + { CS42L43_AMP2MIX_INPUT3, 0x00800000 }, + { CS42L43_AMP2MIX_INPUT4, 0x00800000 }, + { CS42L43_AMP3MIX_INPUT1, 0x00800000 }, + { CS42L43_AMP3MIX_INPUT2, 0x00800000 }, + { CS42L43_AMP3MIX_INPUT3, 0x00800000 }, + { CS42L43_AMP3MIX_INPUT4, 0x00800000 }, + { CS42L43_AMP4MIX_INPUT1, 0x00800000 }, + { CS42L43_AMP4MIX_INPUT2, 0x00800000 }, + { CS42L43_AMP4MIX_INPUT3, 0x00800000 }, + { CS42L43_AMP4MIX_INPUT4, 0x00800000 }, + { CS42L43_ASRC_INT_ENABLES, 0x00000100 }, + { CS42L43_ASRC_DEC_ENABLES, 0x00000100 }, + { CS42L43_PDNCNTL, 0x00000000 }, + { CS42L43_RINGSENSE_DEB_CTRL, 0x0000001B }, + { CS42L43_TIPSENSE_DEB_CTRL, 0x0000001B }, + { CS42L43_HS2, 0x050106F3 }, + { CS42L43_STEREO_MIC_CTRL, 0x00000000 }, + { CS42L43_STEREO_MIC_CLAMP_CTRL, 0x00000001 }, + { CS42L43_BLOCK_EN2, 0x00000000 }, + { CS42L43_BLOCK_EN3, 0x00000000 }, + { CS42L43_BLOCK_EN4, 0x00000000 }, + { CS42L43_BLOCK_EN5, 0x00000000 }, + { CS42L43_BLOCK_EN6, 0x00000000 }, + { CS42L43_BLOCK_EN7, 0x00000000 }, + { CS42L43_BLOCK_EN8, 0x00000000 }, + { CS42L43_BLOCK_EN9, 0x00000000 }, + { CS42L43_BLOCK_EN10, 0x00000000 }, + { CS42L43_BLOCK_EN11, 0x00000000 }, + { CS42L43_TONE_CH1_CTRL, 0x00000000 }, + { CS42L43_TONE_CH2_CTRL, 0x00000000 }, + { CS42L43_MIC_DETECT_CONTROL_1, 0x00000003 }, + { CS42L43_HS_BIAS_SENSE_AND_CLAMP_AUTOCONTROL, 0x02000003 }, + { CS42L43_MIC_DETECT_CONTROL_ANDROID, 0x80790079 }, + { CS42L43_ISRC1_CTRL, 0x00000000 }, + { CS42L43_ISRC2_CTRL, 0x00000000 }, + { CS42L43_CTRL_REG, 0x00000006 }, + { CS42L43_FDIV_FRAC, 0x40000000 }, + { CS42L43_CAL_RATIO, 0x00000080 }, + { CS42L43_SPI_CLK_CONFIG1, 0x00000000 }, + { CS42L43_SPI_CONFIG1, 0x00000000 }, + { CS42L43_SPI_CONFIG2, 0x00000000 }, + { CS42L43_SPI_CONFIG3, 0x00000001 }, + { CS42L43_SPI_CONFIG4, 0x00000000 }, + { CS42L43_TRAN_CONFIG3, 0x00000000 }, + { CS42L43_TRAN_CONFIG4, 0x00000000 }, + { CS42L43_TRAN_CONFIG5, 0x00000000 }, + { CS42L43_TRAN_CONFIG6, 0x00000000 }, + { CS42L43_TRAN_CONFIG7, 0x00000000 }, + { CS42L43_TRAN_CONFIG8, 0x00000000 }, + { CS42L43_DACCNFG1, 0x00000008 }, + { CS42L43_DACCNFG2, 0x00000005 }, + { CS42L43_HPPATHVOL, 0x011B011B }, + { CS42L43_PGAVOL, 0x00003470 }, + { CS42L43_LOADDETENA, 0x00000000 }, + { CS42L43_CTRL, 0x00000037 }, + { CS42L43_COEFF_DATA_IN0, 0x00000000 }, + { CS42L43_COEFF_RD_WR0, 0x00000000 }, + { CS42L43_START_EQZ0, 0x00000000 }, + { CS42L43_MUTE_EQ_IN0, 0x00000000 }, + { CS42L43_DECIM_MASK, 0x0000000F }, + { CS42L43_EQ_MIX_MASK, 0x0000000F }, + { CS42L43_ASP_MASK, 0x000000FF }, + { CS42L43_PLL_MASK, 0x00000003 }, + { CS42L43_SOFT_MASK, 0x0000FFFF }, + { CS42L43_SWIRE_MASK, 0x00007FFF }, + { CS42L43_MSM_MASK, 0x00000FFF }, + { CS42L43_ACC_DET_MASK, 0x00000FFF }, + { CS42L43_I2C_TGT_MASK, 0x00000003 }, + { CS42L43_SPI_MSTR_MASK, 0x00000007 }, + { CS42L43_SW_TO_SPI_BRIDGE_MASK, 0x00000001 }, + { CS42L43_OTP_MASK, 0x00000007 }, + { CS42L43_CLASS_D_AMP_MASK, 0x00003FFF }, + { CS42L43_GPIO_INT_MASK, 0x0000003F }, + { CS42L43_ASRC_MASK, 0x0000000F }, + { CS42L43_HPOUT_MASK, 0x00000003 }, +}; +EXPORT_SYMBOL_NS_GPL(cs42l43_reg_default, MFD_CS42L43); + +bool cs42l43_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CS42L43_DEVID: + case CS42L43_REVID: + case CS42L43_RELID: + case CS42L43_SFT_RESET: + case CS42L43_DRV_CTRL1: + case CS42L43_DRV_CTRL3: + case CS42L43_DRV_CTRL4: + case CS42L43_DRV_CTRL_5: + case CS42L43_GPIO_CTRL1: + case CS42L43_GPIO_CTRL2: + case CS42L43_GPIO_STS: + case CS42L43_GPIO_FN_SEL: + case CS42L43_MCLK_SRC_SEL: + case CS42L43_SAMPLE_RATE1 ... CS42L43_SAMPLE_RATE4: + case CS42L43_PLL_CONTROL: + case CS42L43_FS_SELECT1 ... CS42L43_FS_SELECT4: + case CS42L43_PDM_CONTROL: + case CS42L43_ASP_CLK_CONFIG1 ... CS42L43_ASP_CLK_CONFIG2: + case CS42L43_OSC_DIV_SEL: + case CS42L43_ADC_B_CTRL1 ... CS42L43_ADC_B_CTRL2: + case CS42L43_DECIM_HPF_WNF_CTRL1 ... CS42L43_DECIM_HPF_WNF_CTRL4: + case CS42L43_DMIC_PDM_CTRL: + case CS42L43_DECIM_VOL_CTRL_CH1_CH2 ... CS42L43_DECIM_VOL_CTRL_CH3_CH4: + case CS42L43_INTP_VOLUME_CTRL1 ... CS42L43_INTP_VOLUME_CTRL2: + case CS42L43_AMP1_2_VOL_RAMP: + case CS42L43_ASP_CTRL: + case CS42L43_ASP_FSYNC_CTRL1 ... CS42L43_ASP_FSYNC_CTRL4: + case CS42L43_ASP_DATA_CTRL: + case CS42L43_ASP_RX_EN ... CS42L43_ASP_TX_EN: + case CS42L43_ASP_RX_CH1_CTRL ... CS42L43_ASP_RX_CH6_CTRL: + case CS42L43_ASP_TX_CH1_CTRL ... CS42L43_ASP_TX_CH6_CTRL: + case CS42L43_OTP_REVISION_ID: + case CS42L43_ASPTX1_INPUT: + case CS42L43_ASPTX2_INPUT: + case CS42L43_ASPTX3_INPUT: + case CS42L43_ASPTX4_INPUT: + case CS42L43_ASPTX5_INPUT: + case CS42L43_ASPTX6_INPUT: + case CS42L43_SWIRE_DP1_CH1_INPUT: + case CS42L43_SWIRE_DP1_CH2_INPUT: + case CS42L43_SWIRE_DP1_CH3_INPUT: + case CS42L43_SWIRE_DP1_CH4_INPUT: + case CS42L43_SWIRE_DP2_CH1_INPUT: + case CS42L43_SWIRE_DP2_CH2_INPUT: + case CS42L43_SWIRE_DP3_CH1_INPUT: + case CS42L43_SWIRE_DP3_CH2_INPUT: + case CS42L43_SWIRE_DP4_CH1_INPUT: + case CS42L43_SWIRE_DP4_CH2_INPUT: + case CS42L43_ASRC_INT1_INPUT1: + case CS42L43_ASRC_INT2_INPUT1: + case CS42L43_ASRC_INT3_INPUT1: + case CS42L43_ASRC_INT4_INPUT1: + case CS42L43_ASRC_DEC1_INPUT1: + case CS42L43_ASRC_DEC2_INPUT1: + case CS42L43_ASRC_DEC3_INPUT1: + case CS42L43_ASRC_DEC4_INPUT1: + case CS42L43_ISRC1INT1_INPUT1: + case CS42L43_ISRC1INT2_INPUT1: + case CS42L43_ISRC1DEC1_INPUT1: + case CS42L43_ISRC1DEC2_INPUT1: + case CS42L43_ISRC2INT1_INPUT1: + case CS42L43_ISRC2INT2_INPUT1: + case CS42L43_ISRC2DEC1_INPUT1: + case CS42L43_ISRC2DEC2_INPUT1: + case CS42L43_EQ1MIX_INPUT1 ... CS42L43_EQ1MIX_INPUT4: + case CS42L43_EQ2MIX_INPUT1 ... CS42L43_EQ2MIX_INPUT4: + case CS42L43_SPDIF1_INPUT1: + case CS42L43_SPDIF2_INPUT1: + case CS42L43_AMP1MIX_INPUT1 ... CS42L43_AMP1MIX_INPUT4: + case CS42L43_AMP2MIX_INPUT1 ... CS42L43_AMP2MIX_INPUT4: + case CS42L43_AMP3MIX_INPUT1 ... CS42L43_AMP3MIX_INPUT4: + case CS42L43_AMP4MIX_INPUT1 ... CS42L43_AMP4MIX_INPUT4: + case CS42L43_ASRC_INT_ENABLES ... CS42L43_ASRC_DEC_ENABLES: + case CS42L43_PDNCNTL: + case CS42L43_RINGSENSE_DEB_CTRL: + case CS42L43_TIPSENSE_DEB_CTRL: + case CS42L43_TIP_RING_SENSE_INTERRUPT_STATUS: + case CS42L43_HS2: + case CS42L43_HS_STAT: + case CS42L43_MCU_SW_INTERRUPT: + case CS42L43_STEREO_MIC_CTRL: + case CS42L43_STEREO_MIC_CLAMP_CTRL: + case CS42L43_BLOCK_EN2 ... CS42L43_BLOCK_EN11: + case CS42L43_TONE_CH1_CTRL ... CS42L43_TONE_CH2_CTRL: + case CS42L43_MIC_DETECT_CONTROL_1: + case CS42L43_DETECT_STATUS_1: + case CS42L43_HS_BIAS_SENSE_AND_CLAMP_AUTOCONTROL: + case CS42L43_MIC_DETECT_CONTROL_ANDROID: + case CS42L43_ISRC1_CTRL: + case CS42L43_ISRC2_CTRL: + case CS42L43_CTRL_REG: + case CS42L43_FDIV_FRAC: + case CS42L43_CAL_RATIO: + case CS42L43_SPI_CLK_CONFIG1: + case CS42L43_SPI_CONFIG1 ... CS42L43_SPI_CONFIG4: + case CS42L43_SPI_STATUS1 ... CS42L43_SPI_STATUS2: + case CS42L43_TRAN_CONFIG1 ... CS42L43_TRAN_CONFIG8: + case CS42L43_TRAN_STATUS1 ... CS42L43_TRAN_STATUS3: + case CS42L43_TX_DATA: + case CS42L43_RX_DATA: + case CS42L43_DACCNFG1 ... CS42L43_DACCNFG2: + case CS42L43_HPPATHVOL: + case CS42L43_PGAVOL: + case CS42L43_LOADDETRESULTS: + case CS42L43_LOADDETENA: + case CS42L43_CTRL: + case CS42L43_COEFF_DATA_IN0: + case CS42L43_COEFF_RD_WR0: + case CS42L43_INIT_DONE0: + case CS42L43_START_EQZ0: + case CS42L43_MUTE_EQ_IN0: + case CS42L43_DECIM_INT ... CS42L43_HPOUT_INT: + case CS42L43_DECIM_MASK ... CS42L43_HPOUT_MASK: + case CS42L43_DECIM_INT_SHADOW ... CS42L43_HP_OUT_SHADOW: + case CS42L43_BOOT_CONTROL: + case CS42L43_BLOCK_EN: + case CS42L43_SHUTTER_CONTROL: + case CS42L43_MCU_SW_REV ... CS42L43_MCU_RAM_MAX: + return true; + default: + return false; + } +} +EXPORT_SYMBOL_NS_GPL(cs42l43_readable_register, MFD_CS42L43); + +bool cs42l43_precious_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CS42L43_SFT_RESET: + case CS42L43_TX_DATA: + case CS42L43_RX_DATA: + case CS42L43_DECIM_INT ... CS42L43_HPOUT_INT: + case CS42L43_MCU_SW_REV ... CS42L43_MCU_RAM_MAX: + return true; + default: + return false; + } +} +EXPORT_SYMBOL_NS_GPL(cs42l43_precious_register, MFD_CS42L43); + +bool cs42l43_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CS42L43_DEVID: + case CS42L43_REVID: + case CS42L43_RELID: + case CS42L43_GPIO_STS: + case CS42L43_OTP_REVISION_ID: + case CS42L43_TIP_RING_SENSE_INTERRUPT_STATUS: + case CS42L43_HS_STAT: + case CS42L43_MCU_SW_INTERRUPT: + case CS42L43_DETECT_STATUS_1: + case CS42L43_SPI_STATUS1 ... CS42L43_SPI_STATUS2: + case CS42L43_TRAN_CONFIG1 ... CS42L43_TRAN_CONFIG2: + case CS42L43_TRAN_CONFIG8: + case CS42L43_TRAN_STATUS1 ... CS42L43_TRAN_STATUS3: + case CS42L43_LOADDETRESULTS: + case CS42L43_INIT_DONE0: + case CS42L43_DECIM_INT_SHADOW ... CS42L43_HP_OUT_SHADOW: + case CS42L43_BOOT_CONTROL: + case CS42L43_BLOCK_EN: + return true; + default: + return cs42l43_precious_register(dev, reg); + } +} +EXPORT_SYMBOL_NS_GPL(cs42l43_volatile_register, MFD_CS42L43); + +#define CS42L43_IRQ_OFFSET(reg) ((CS42L43_##reg##_INT) - CS42L43_DECIM_INT) + +#define CS42L43_IRQ_REG(name, reg) REGMAP_IRQ_REG(CS42L43_##name, \ + CS42L43_IRQ_OFFSET(reg), \ + CS42L43_##name##_INT_MASK) + +static const struct regmap_irq cs42l43_regmap_irqs[] = { + CS42L43_IRQ_REG(PLL_LOST_LOCK, PLL), + CS42L43_IRQ_REG(PLL_READY, PLL), + + CS42L43_IRQ_REG(HP_STARTUP_DONE, MSM), + CS42L43_IRQ_REG(HP_SHUTDOWN_DONE, MSM), + CS42L43_IRQ_REG(HSDET_DONE, MSM), + CS42L43_IRQ_REG(TIPSENSE_UNPLUG_DB, MSM), + CS42L43_IRQ_REG(TIPSENSE_PLUG_DB, MSM), + CS42L43_IRQ_REG(RINGSENSE_UNPLUG_DB, MSM), + CS42L43_IRQ_REG(RINGSENSE_PLUG_DB, MSM), + CS42L43_IRQ_REG(TIPSENSE_UNPLUG_PDET, MSM), + CS42L43_IRQ_REG(TIPSENSE_PLUG_PDET, MSM), + CS42L43_IRQ_REG(RINGSENSE_UNPLUG_PDET, MSM), + CS42L43_IRQ_REG(RINGSENSE_PLUG_PDET, MSM), + + CS42L43_IRQ_REG(HS2_BIAS_SENSE, ACC_DET), + CS42L43_IRQ_REG(HS1_BIAS_SENSE, ACC_DET), + CS42L43_IRQ_REG(DC_DETECT1_FALSE, ACC_DET), + CS42L43_IRQ_REG(DC_DETECT1_TRUE, ACC_DET), + CS42L43_IRQ_REG(HSBIAS_CLAMPED, ACC_DET), + CS42L43_IRQ_REG(HS3_4_BIAS_SENSE, ACC_DET), + + CS42L43_IRQ_REG(AMP2_CLK_STOP_FAULT, CLASS_D_AMP), + CS42L43_IRQ_REG(AMP1_CLK_STOP_FAULT, CLASS_D_AMP), + CS42L43_IRQ_REG(AMP2_VDDSPK_FAULT, CLASS_D_AMP), + CS42L43_IRQ_REG(AMP1_VDDSPK_FAULT, CLASS_D_AMP), + CS42L43_IRQ_REG(AMP2_SHUTDOWN_DONE, CLASS_D_AMP), + CS42L43_IRQ_REG(AMP1_SHUTDOWN_DONE, CLASS_D_AMP), + CS42L43_IRQ_REG(AMP2_STARTUP_DONE, CLASS_D_AMP), + CS42L43_IRQ_REG(AMP1_STARTUP_DONE, CLASS_D_AMP), + CS42L43_IRQ_REG(AMP2_THERM_SHDN, CLASS_D_AMP), + CS42L43_IRQ_REG(AMP1_THERM_SHDN, CLASS_D_AMP), + CS42L43_IRQ_REG(AMP2_THERM_WARN, CLASS_D_AMP), + CS42L43_IRQ_REG(AMP1_THERM_WARN, CLASS_D_AMP), + CS42L43_IRQ_REG(AMP2_SCDET, CLASS_D_AMP), + CS42L43_IRQ_REG(AMP1_SCDET, CLASS_D_AMP), + + CS42L43_IRQ_REG(GPIO3_FALL, GPIO), + CS42L43_IRQ_REG(GPIO3_RISE, GPIO), + CS42L43_IRQ_REG(GPIO2_FALL, GPIO), + CS42L43_IRQ_REG(GPIO2_RISE, GPIO), + CS42L43_IRQ_REG(GPIO1_FALL, GPIO), + CS42L43_IRQ_REG(GPIO1_RISE, GPIO), + + CS42L43_IRQ_REG(HP_ILIMIT, HPOUT), + CS42L43_IRQ_REG(HP_LOADDET_DONE, HPOUT), +}; + +static const struct regmap_irq_chip cs42l43_irq_chip = { + .name = "cs42l43", + + .status_base = CS42L43_DECIM_INT, + .mask_base = CS42L43_DECIM_MASK, + .num_regs = 16, + + .irqs = cs42l43_regmap_irqs, + .num_irqs = ARRAY_SIZE(cs42l43_regmap_irqs), + + .runtime_pm = true, +}; + +static const char * const cs42l43_core_supplies[] = { + "vdd-a", "vdd-io", "vdd-cp", +}; + +static const char * const cs42l43_parent_supplies[] = { "vdd-amp" }; + +static const struct mfd_cell cs42l43_devs[] = { + { .name = "cs42l43-pinctrl", }, + { .name = "cs42l43-spi", }, + { + .name = "cs42l43-codec", + .parent_supplies = cs42l43_parent_supplies, + .num_parent_supplies = ARRAY_SIZE(cs42l43_parent_supplies), + }, +}; + +/* + * If the device is connected over Soundwire, as well as soft resetting the + * device, this function will also way for the device to detach from the bus + * before returning. + */ +static int cs42l43_soft_reset(struct cs42l43 *cs42l43) +{ + static const struct reg_sequence reset[] = { + { CS42L43_SFT_RESET, CS42L43_SFT_RESET_VAL }, + }; + + reinit_completion(&cs42l43->device_detach); + + /* + * Apply cache only because the soft reset will cause the device to + * detach from the soundwire bus. + */ + regcache_cache_only(cs42l43->regmap, true); + regmap_multi_reg_write_bypassed(cs42l43->regmap, reset, ARRAY_SIZE(reset)); + + msleep(CS42L43_RESET_DELAY); + + if (cs42l43->sdw) { + unsigned long timeout = msecs_to_jiffies(CS42L43_SDW_DETACH_TIMEOUT); + unsigned long time; + + time = wait_for_completion_timeout(&cs42l43->device_detach, timeout); + if (!time) { + dev_err(cs42l43->dev, "Timed out waiting for device detach\n"); + return -ETIMEDOUT; + } + } + + return -EAGAIN; +} + +/* + * This function is essentially a no-op on I2C, but will wait for the device to + * attach when the device is used on a SoundWire bus. + */ +static int cs42l43_wait_for_attach(struct cs42l43 *cs42l43) +{ + if (!cs42l43->attached) { + unsigned long timeout = msecs_to_jiffies(CS42L43_SDW_ATTACH_TIMEOUT); + unsigned long time; + + time = wait_for_completion_timeout(&cs42l43->device_attach, timeout); + if (!time) { + dev_err(cs42l43->dev, "Timed out waiting for device re-attach\n"); + return -ETIMEDOUT; + } + } + + regcache_cache_only(cs42l43->regmap, false); + + /* The hardware requires enabling OSC_DIV before doing any SoundWire reads. */ + if (cs42l43->sdw) + regmap_write(cs42l43->regmap, CS42L43_OSC_DIV_SEL, + CS42L43_OSC_DIV2_EN_MASK); + + return 0; +} + +/* + * This function will advance the firmware into boot stage 3 from boot stage 2. + * Boot stage 3 is required to send commands to the firmware. This is achieved + * by setting the firmware NEED configuration register to zero, this indicates + * no configuration is required forcing the firmware to advance to boot stage 3. + * + * Later revisions of the firmware require the use of an alternative register + * for this purpose, which is indicated through the shadow flag. + */ +static int cs42l43_mcu_stage_2_3(struct cs42l43 *cs42l43, bool shadow) +{ + unsigned int need_reg = CS42L43_NEED_CONFIGS; + unsigned int val; + int ret; + + if (shadow) + need_reg = CS42L43_FW_SH_BOOT_CFG_NEED_CONFIGS; + + regmap_write(cs42l43->regmap, need_reg, 0); + + ret = regmap_read_poll_timeout(cs42l43->regmap, CS42L43_BOOT_STATUS, + val, (val == CS42L43_MCU_BOOT_STAGE3), + CS42L43_MCU_POLL, CS42L43_MCU_CMD_TIMEOUT); + if (ret) { + dev_err(cs42l43->dev, "Failed to move to stage 3: %d, 0x%x\n", ret, val); + return ret; + } + + return -EAGAIN; +} + +/* + * This function will return the firmware to boot stage 2 from boot stage 3. + * Boot stage 2 is required to apply updates to the firmware. This is achieved + * by setting the firmware NEED configuration register to FW_PATCH_NEED_CFG, + * setting the HAVE configuration register to 0, and soft resetting. The + * firmware will see it is missing a patch configuration and will pause in boot + * stage 2. + * + * Note: Unlike cs42l43_mcu_stage_2_3 there is no need to consider the shadow + * register here as the driver will only return to boot stage 2 if the firmware + * requires update which means the revision does not include shadow register + * support. + */ +static int cs42l43_mcu_stage_3_2(struct cs42l43 *cs42l43) +{ + regmap_write(cs42l43->regmap, CS42L43_FW_MISSION_CTRL_NEED_CONFIGS, + CS42L43_FW_PATCH_NEED_CFG_MASK); + regmap_write(cs42l43->regmap, CS42L43_FW_MISSION_CTRL_HAVE_CONFIGS, 0); + + return cs42l43_soft_reset(cs42l43); +} + +/* + * Disable the firmware running on the device such that the driver can access + * the registers without fear of the MCU changing them under it. + */ +static int cs42l43_mcu_disable(struct cs42l43 *cs42l43) +{ + unsigned int val; + int ret; + + regmap_write(cs42l43->regmap, CS42L43_FW_MISSION_CTRL_MM_MCU_CFG_REG, + CS42L43_FW_MISSION_CTRL_MM_MCU_CFG_DISABLE_VAL); + regmap_write(cs42l43->regmap, CS42L43_FW_MISSION_CTRL_MM_CTRL_SELECTION, + CS42L43_FW_MM_CTRL_MCU_SEL_MASK); + regmap_write(cs42l43->regmap, CS42L43_MCU_SW_INTERRUPT, CS42L43_CONTROL_IND_MASK); + regmap_write(cs42l43->regmap, CS42L43_MCU_SW_INTERRUPT, 0); + + ret = regmap_read_poll_timeout(cs42l43->regmap, CS42L43_SOFT_INT_SHADOW, val, + (val & CS42L43_CONTROL_APPLIED_INT_MASK), + CS42L43_MCU_POLL, CS42L43_MCU_CMD_TIMEOUT); + if (ret) { + dev_err(cs42l43->dev, "Failed to disable firmware: %d, 0x%x\n", ret, val); + return ret; + } + + /* Soft reset to clear any register state the firmware left behind. */ + return cs42l43_soft_reset(cs42l43); +} + +/* + * Callback to load firmware updates. + */ +static void cs42l43_mcu_load_firmware(const struct firmware *firmware, void *context) +{ + struct cs42l43 *cs42l43 = context; + const struct cs42l43_patch_header *hdr; + unsigned int loadaddr, val; + int ret; + + if (!firmware) { + dev_err(cs42l43->dev, "Failed to load firmware\n"); + cs42l43->firmware_error = -ENODEV; + goto err; + } + + hdr = (const struct cs42l43_patch_header *)&firmware->data[0]; + loadaddr = le32_to_cpu(hdr->load_addr); + + if (le16_to_cpu(hdr->version) != CS42L43_MCU_UPDATE_FORMAT) { + dev_err(cs42l43->dev, "Bad firmware file format: %d\n", hdr->version); + cs42l43->firmware_error = -EINVAL; + goto err_release; + } + + regmap_write(cs42l43->regmap, CS42L43_PATCH_START_ADDR, loadaddr); + regmap_bulk_write(cs42l43->regmap, loadaddr + CS42L43_MCU_UPDATE_OFFSET, + &firmware->data[0], firmware->size / sizeof(u32)); + + regmap_write(cs42l43->regmap, CS42L43_MCU_SW_INTERRUPT, CS42L43_PATCH_IND_MASK); + regmap_write(cs42l43->regmap, CS42L43_MCU_SW_INTERRUPT, 0); + + ret = regmap_read_poll_timeout(cs42l43->regmap, CS42L43_SOFT_INT_SHADOW, val, + (val & CS42L43_PATCH_APPLIED_INT_MASK), + CS42L43_MCU_POLL, CS42L43_MCU_UPDATE_TIMEOUT); + if (ret) { + dev_err(cs42l43->dev, "Failed to update firmware: %d, 0x%x\n", ret, val); + cs42l43->firmware_error = ret; + goto err_release; + } + +err_release: + release_firmware(firmware); +err: + complete(&cs42l43->firmware_download); +} + +/* + * The process of updating the firmware is split into a series of steps, at the + * end of each step a soft reset of the device might be required which will + * require the driver to wait for the device to re-attach on the SoundWire bus, + * if that control bus is being used. + */ +static int cs42l43_mcu_update_step(struct cs42l43 *cs42l43) +{ + unsigned int mcu_rev, bios_rev, boot_status, secure_cfg; + bool patched, shadow; + int ret; + + /* Clear any stale software interrupt bits. */ + regmap_read(cs42l43->regmap, CS42L43_SOFT_INT, &mcu_rev); + + ret = regmap_read(cs42l43->regmap, CS42L43_BOOT_STATUS, &boot_status); + if (ret) { + dev_err(cs42l43->dev, "Failed to read boot status: %d\n", ret); + return ret; + } + + ret = regmap_read(cs42l43->regmap, CS42L43_MCU_SW_REV, &mcu_rev); + if (ret) { + dev_err(cs42l43->dev, "Failed to read firmware revision: %d\n", ret); + return ret; + } + + bios_rev = (((mcu_rev & CS42L43_BIOS_MAJOR_REV_MASK) << 12) | + ((mcu_rev & CS42L43_BIOS_MINOR_REV_MASK) << 4) | + ((mcu_rev & CS42L43_BIOS_SUBMINOR_REV_MASK) >> 8)) >> + CS42L43_BIOS_MAJOR_REV_SHIFT; + mcu_rev = ((mcu_rev & CS42L43_FW_MAJOR_REV_MASK) << 12) | + ((mcu_rev & CS42L43_FW_MINOR_REV_MASK) << 4) | + ((mcu_rev & CS42L43_FW_SUBMINOR_REV_MASK) >> 8); + + /* + * The firmware has two revision numbers bringing either of them up to a + * supported version will provide the features the driver requires. + */ + patched = mcu_rev >= CS42L43_MCU_SUPPORTED_REV || + bios_rev >= CS42L43_MCU_SUPPORTED_BIOS_REV; + /* + * Later versions of the firmwware require the driver to access some + * features through a set of shadow registers. + */ + shadow = mcu_rev >= CS42L43_MCU_SHADOW_REGS_REQUIRED_REV; + + ret = regmap_read(cs42l43->regmap, CS42L43_BOOT_CONTROL, &secure_cfg); + if (ret) { + dev_err(cs42l43->dev, "Failed to read security settings: %d\n", ret); + return ret; + } + + cs42l43->hw_lock = secure_cfg & CS42L43_LOCK_HW_STS_MASK; + + if (!patched && cs42l43->hw_lock) { + dev_err(cs42l43->dev, "Unpatched secure device\n"); + return -EPERM; + } + + dev_dbg(cs42l43->dev, "Firmware(0x%x, 0x%x) in boot stage %d\n", + mcu_rev, bios_rev, boot_status); + + switch (boot_status) { + case CS42L43_MCU_BOOT_STAGE2: + if (!patched) { + ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT, + "cs42l43.bin", cs42l43->dev, + GFP_KERNEL, cs42l43, + cs42l43_mcu_load_firmware); + if (ret) { + dev_err(cs42l43->dev, "Failed to request firmware: %d\n", ret); + return ret; + } + + wait_for_completion(&cs42l43->firmware_download); + + if (cs42l43->firmware_error) + return cs42l43->firmware_error; + + return -EAGAIN; + } else { + return cs42l43_mcu_stage_2_3(cs42l43, shadow); + } + case CS42L43_MCU_BOOT_STAGE3: + if (patched) + return cs42l43_mcu_disable(cs42l43); + else + return cs42l43_mcu_stage_3_2(cs42l43); + case CS42L43_MCU_BOOT_STAGE4: + return 0; + default: + dev_err(cs42l43->dev, "Invalid boot status: %d\n", boot_status); + return -EINVAL; + } +} + +/* + * Update the firmware running on the device. + */ +static int cs42l43_mcu_update(struct cs42l43 *cs42l43) +{ + int i, ret; + + for (i = 0; i < CS42L43_MCU_UPDATE_RETRIES; i++) { + ret = cs42l43_mcu_update_step(cs42l43); + if (ret != -EAGAIN) + return ret; + + ret = cs42l43_wait_for_attach(cs42l43); + if (ret) + return ret; + } + + dev_err(cs42l43->dev, "Failed retrying update\n"); + return -ETIMEDOUT; +} + +static int cs42l43_irq_config(struct cs42l43 *cs42l43) +{ + struct irq_data *irq_data; + unsigned long irq_flags; + int ret; + + if (cs42l43->sdw) + cs42l43->irq = cs42l43->sdw->irq; + + cs42l43->irq_chip = cs42l43_irq_chip; + cs42l43->irq_chip.irq_drv_data = cs42l43; + + irq_data = irq_get_irq_data(cs42l43->irq); + if (!irq_data) { + dev_err(cs42l43->dev, "Invalid IRQ: %d\n", cs42l43->irq); + return -EINVAL; + } + + irq_flags = irqd_get_trigger_type(irq_data); + switch (irq_flags) { + case IRQF_TRIGGER_LOW: + case IRQF_TRIGGER_HIGH: + case IRQF_TRIGGER_RISING: + case IRQF_TRIGGER_FALLING: + break; + case IRQ_TYPE_NONE: + default: + irq_flags = IRQF_TRIGGER_LOW; + break; + } + + irq_flags |= IRQF_ONESHOT; + + ret = devm_regmap_add_irq_chip(cs42l43->dev, cs42l43->regmap, + cs42l43->irq, irq_flags, 0, + &cs42l43->irq_chip, &cs42l43->irq_data); + if (ret) { + dev_err(cs42l43->dev, "Failed to add IRQ chip: %d\n", ret); + return ret; + } + + dev_dbg(cs42l43->dev, "Configured IRQ %d with flags 0x%lx\n", + cs42l43->irq, irq_flags); + + return 0; +} + +static void cs42l43_boot_work(struct work_struct *work) +{ + struct cs42l43 *cs42l43 = container_of(work, struct cs42l43, boot_work); + unsigned int devid, revid, otp; + int ret; + + ret = cs42l43_wait_for_attach(cs42l43); + if (ret) + goto err; + + ret = regmap_read(cs42l43->regmap, CS42L43_DEVID, &devid); + if (ret) { + dev_err(cs42l43->dev, "Failed to read devid: %d\n", ret); + goto err; + } + + switch (devid) { + case CS42L43_DEVID_VAL: + break; + default: + dev_err(cs42l43->dev, "Unrecognised devid: 0x%06x\n", devid); + goto err; + } + + ret = regmap_read(cs42l43->regmap, CS42L43_REVID, &revid); + if (ret) { + dev_err(cs42l43->dev, "Failed to read rev: %d\n", ret); + goto err; + } + + ret = regmap_read(cs42l43->regmap, CS42L43_OTP_REVISION_ID, &otp); + if (ret) { + dev_err(cs42l43->dev, "Failed to read otp rev: %d\n", ret); + goto err; + } + + dev_info(cs42l43->dev, + "devid: 0x%06x, rev: 0x%02x, otp: 0x%02x\n", devid, revid, otp); + + ret = cs42l43_mcu_update(cs42l43); + if (ret) + goto err; + + ret = regmap_register_patch(cs42l43->regmap, cs42l43_reva_patch, + ARRAY_SIZE(cs42l43_reva_patch)); + if (ret) { + dev_err(cs42l43->dev, "Failed to apply register patch: %d\n", ret); + goto err; + } + + ret = cs42l43_irq_config(cs42l43); + if (ret) + goto err; + + ret = devm_mfd_add_devices(cs42l43->dev, PLATFORM_DEVID_NONE, + cs42l43_devs, ARRAY_SIZE(cs42l43_devs), + NULL, 0, NULL); + if (ret) { + dev_err(cs42l43->dev, "Failed to add subdevices: %d\n", ret); + goto err; + } + + pm_runtime_mark_last_busy(cs42l43->dev); + pm_runtime_put_autosuspend(cs42l43->dev); + + return; + +err: + pm_runtime_put_sync(cs42l43->dev); + cs42l43_dev_remove(cs42l43); +} + +static int cs42l43_power_up(struct cs42l43 *cs42l43) +{ + int ret; + + ret = regulator_enable(cs42l43->vdd_p); + if (ret) { + dev_err(cs42l43->dev, "Failed to enable vdd-p: %d\n", ret); + return ret; + } + + /* vdd-p must be on for 50uS before any other supply */ + usleep_range(CS42L43_VDDP_DELAY, 2 * CS42L43_VDDP_DELAY); + + gpiod_set_value_cansleep(cs42l43->reset, 1); + + ret = regulator_bulk_enable(CS42L43_N_SUPPLIES, cs42l43->core_supplies); + if (ret) { + dev_err(cs42l43->dev, "Failed to enable core supplies: %d\n", ret); + goto err_reset; + } + + ret = regulator_enable(cs42l43->vdd_d); + if (ret) { + dev_err(cs42l43->dev, "Failed to enable vdd-d: %d\n", ret); + goto err_core_supplies; + } + + usleep_range(CS42L43_VDDD_DELAY, 2 * CS42L43_VDDD_DELAY); + + return 0; + +err_core_supplies: + regulator_bulk_disable(CS42L43_N_SUPPLIES, cs42l43->core_supplies); +err_reset: + gpiod_set_value_cansleep(cs42l43->reset, 0); + regulator_disable(cs42l43->vdd_p); + + return ret; +} + +static int cs42l43_power_down(struct cs42l43 *cs42l43) +{ + int ret; + + ret = regulator_disable(cs42l43->vdd_d); + if (ret) { + dev_err(cs42l43->dev, "Failed to disable vdd-d: %d\n", ret); + return ret; + } + + ret = regulator_bulk_disable(CS42L43_N_SUPPLIES, cs42l43->core_supplies); + if (ret) { + dev_err(cs42l43->dev, "Failed to disable core supplies: %d\n", ret); + return ret; + } + + gpiod_set_value_cansleep(cs42l43->reset, 0); + + ret = regulator_disable(cs42l43->vdd_p); + if (ret) { + dev_err(cs42l43->dev, "Failed to disable vdd-p: %d\n", ret); + return ret; + } + + return 0; +} + +int cs42l43_dev_probe(struct cs42l43 *cs42l43) +{ + int i, ret; + + dev_set_drvdata(cs42l43->dev, cs42l43); + + mutex_init(&cs42l43->pll_lock); + init_completion(&cs42l43->device_attach); + init_completion(&cs42l43->device_detach); + init_completion(&cs42l43->firmware_download); + INIT_WORK(&cs42l43->boot_work, cs42l43_boot_work); + + regcache_cache_only(cs42l43->regmap, true); + + cs42l43->reset = devm_gpiod_get_optional(cs42l43->dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(cs42l43->reset)) + return dev_err_probe(cs42l43->dev, PTR_ERR(cs42l43->reset), + "Failed to get reset\n"); + + cs42l43->vdd_p = devm_regulator_get(cs42l43->dev, "vdd-p"); + if (IS_ERR(cs42l43->vdd_p)) + return dev_err_probe(cs42l43->dev, PTR_ERR(cs42l43->vdd_p), + "Failed to get vdd-p\n"); + + cs42l43->vdd_d = devm_regulator_get(cs42l43->dev, "vdd-d"); + if (IS_ERR(cs42l43->vdd_d)) + return dev_err_probe(cs42l43->dev, PTR_ERR(cs42l43->vdd_d), + "Failed to get vdd-d\n"); + + BUILD_BUG_ON(ARRAY_SIZE(cs42l43_core_supplies) != CS42L43_N_SUPPLIES); + + for (i = 0; i < CS42L43_N_SUPPLIES; i++) + cs42l43->core_supplies[i].supply = cs42l43_core_supplies[i]; + + ret = devm_regulator_bulk_get(cs42l43->dev, CS42L43_N_SUPPLIES, + cs42l43->core_supplies); + if (ret) + return dev_err_probe(cs42l43->dev, ret, + "Failed to get core supplies\n"); + + ret = cs42l43_power_up(cs42l43); + if (ret) + return ret; + + pm_runtime_set_autosuspend_delay(cs42l43->dev, CS42L43_AUTOSUSPEND_TIME); + pm_runtime_use_autosuspend(cs42l43->dev); + pm_runtime_set_active(cs42l43->dev); + /* + * The device is already powered up, but keep it from suspending until + * the boot work runs. + */ + pm_runtime_get_noresume(cs42l43->dev); + devm_pm_runtime_enable(cs42l43->dev); + + queue_work(system_long_wq, &cs42l43->boot_work); + + return 0; +} +EXPORT_SYMBOL_NS_GPL(cs42l43_dev_probe, MFD_CS42L43); + +void cs42l43_dev_remove(struct cs42l43 *cs42l43) +{ + cs42l43_power_down(cs42l43); +} +EXPORT_SYMBOL_NS_GPL(cs42l43_dev_remove, MFD_CS42L43); + +static int cs42l43_suspend(struct device *dev) +{ + struct cs42l43 *cs42l43 = dev_get_drvdata(dev); + int ret; + + /* + * Don't care about being resumed here, but the driver does want + * force_resume to always trigger an actual resume, so that register + * state for the MCU/GPIOs is returned as soon as possible after system + * resume. force_resume will resume if the reference count is resumed on + * suspend hence the get_noresume. + */ + pm_runtime_get_noresume(dev); + + ret = pm_runtime_force_suspend(dev); + if (ret) { + dev_err(cs42l43->dev, "Failed to force suspend: %d\n", ret); + pm_runtime_put_noidle(dev); + return ret; + } + + pm_runtime_put_noidle(dev); + + ret = cs42l43_power_down(cs42l43); + if (ret) + return ret; + + return 0; +} + +static int cs42l43_resume(struct device *dev) +{ + struct cs42l43 *cs42l43 = dev_get_drvdata(dev); + int ret; + + ret = cs42l43_power_up(cs42l43); + if (ret) + return ret; + + ret = pm_runtime_force_resume(dev); + if (ret) { + dev_err(cs42l43->dev, "Failed to force resume: %d\n", ret); + return ret; + } + + return 0; +} + +static int cs42l43_runtime_suspend(struct device *dev) +{ + struct cs42l43 *cs42l43 = dev_get_drvdata(dev); + + /* + * Whilst the driver doesn't power the chip down here, going into runtime + * suspend lets the SoundWire bus power down, which means the driver + * can't communicate with the device any more. + */ + regcache_cache_only(cs42l43->regmap, true); + + return 0; +} + +static int cs42l43_runtime_resume(struct device *dev) +{ + struct cs42l43 *cs42l43 = dev_get_drvdata(dev); + unsigned int reset_canary; + int ret; + + ret = cs42l43_wait_for_attach(cs42l43); + if (ret) + return ret; + + ret = regmap_read(cs42l43->regmap, CS42L43_RELID, &reset_canary); + if (ret) { + dev_err(cs42l43->dev, "Failed to check reset canary: %d\n", ret); + goto err; + } + + if (!reset_canary) { + /* + * If the canary has cleared the chip has reset, re-handle the + * MCU and mark the cache as dirty to indicate the chip reset. + */ + ret = cs42l43_mcu_update(cs42l43); + if (ret) + goto err; + + regcache_mark_dirty(cs42l43->regmap); + } + + ret = regcache_sync(cs42l43->regmap); + if (ret) { + dev_err(cs42l43->dev, "Failed to restore register cache: %d\n", ret); + goto err; + } + + return 0; + +err: + regcache_cache_only(cs42l43->regmap, true); + + return ret; +} + +EXPORT_NS_GPL_DEV_PM_OPS(cs42l43_pm_ops, MFD_CS42L43) = { + SET_SYSTEM_SLEEP_PM_OPS(cs42l43_suspend, cs42l43_resume) + SET_RUNTIME_PM_OPS(cs42l43_runtime_suspend, cs42l43_runtime_resume, NULL) +}; + +MODULE_DESCRIPTION("CS42L43 Core Driver"); +MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>"); +MODULE_LICENSE("GPL"); +MODULE_FIRMWARE("cs42l43.bin"); diff --git a/drivers/mfd/cs42l43.h b/drivers/mfd/cs42l43.h new file mode 100644 index 000000000000..eb4caf393833 --- /dev/null +++ b/drivers/mfd/cs42l43.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * CS42L43 core driver internal data + * + * Copyright (C) 2022-2023 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#include <linux/mfd/cs42l43.h> +#include <linux/pm.h> +#include <linux/regmap.h> + +#ifndef CS42L43_CORE_INT_H +#define CS42L43_CORE_INT_H + +#define CS42L43_N_DEFAULTS 176 + +extern const struct dev_pm_ops cs42l43_pm_ops; +extern const struct reg_default cs42l43_reg_default[CS42L43_N_DEFAULTS]; + +bool cs42l43_readable_register(struct device *dev, unsigned int reg); +bool cs42l43_precious_register(struct device *dev, unsigned int reg); +bool cs42l43_volatile_register(struct device *dev, unsigned int reg); + +int cs42l43_dev_probe(struct cs42l43 *cs42l43); +void cs42l43_dev_remove(struct cs42l43 *cs42l43); + +#endif /* CS42L43_CORE_INT_H */ diff --git a/drivers/mfd/tps65086.c b/drivers/mfd/tps65086.c index 6a21000aad4a..9bb7d7d8dcfc 100644 --- a/drivers/mfd/tps65086.c +++ b/drivers/mfd/tps65086.c @@ -81,16 +81,23 @@ static int tps65086_probe(struct i2c_client *client) return PTR_ERR(tps->regmap); } - ret = regmap_read(tps->regmap, TPS65086_DEVICEID, &version); + /* Store device ID to load regulator configuration that fit to IC variant */ + ret = regmap_read(tps->regmap, TPS65086_DEVICEID1, &tps->chip_id); if (ret) { - dev_err(tps->dev, "Failed to read revision register\n"); + dev_err(tps->dev, "Failed to read revision register 1\n"); + return ret; + } + + ret = regmap_read(tps->regmap, TPS65086_DEVICEID2, &version); + if (ret) { + dev_err(tps->dev, "Failed to read revision register 2\n"); return ret; } dev_info(tps->dev, "Device: TPS65086%01lX, OTP: %c, Rev: %ld\n", - (version & TPS65086_DEVICEID_PART_MASK), - (char)((version & TPS65086_DEVICEID_OTP_MASK) >> 4) + 'A', - (version & TPS65086_DEVICEID_REV_MASK) >> 6); + (version & TPS65086_DEVICEID2_PART_MASK), + (char)((version & TPS65086_DEVICEID2_OTP_MASK) >> 4) + 'A', + (version & TPS65086_DEVICEID2_REV_MASK) >> 6); if (tps->irq > 0) { ret = regmap_add_irq_chip(tps->regmap, tps->irq, IRQF_ONESHOT, 0, diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c index 35fec1bf1b3d..5867af9f592c 100644 --- a/drivers/misc/ibmasm/ibmasmfs.c +++ b/drivers/misc/ibmasm/ibmasmfs.c @@ -139,7 +139,7 @@ static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode) if (ret) { ret->i_ino = get_next_ino(); ret->i_mode = mode; - ret->i_atime = ret->i_mtime = ret->i_ctime = current_time(ret); + ret->i_atime = ret->i_mtime = inode_set_ctime_current(ret); } return ret; } diff --git a/drivers/misc/ibmvmc.c b/drivers/misc/ibmvmc.c index cbaf6d35e854..2101eb12bcba 100644 --- a/drivers/misc/ibmvmc.c +++ b/drivers/misc/ibmvmc.c @@ -1124,7 +1124,7 @@ static ssize_t ibmvmc_write(struct file *file, const char *buffer, goto out; inode = file_inode(file); - inode->i_mtime = current_time(inode); + inode->i_mtime = inode_set_ctime_current(inode); mark_inode_dirty(inode); dev_dbg(adapter->dev, "write: file = 0x%lx, count = 0x%lx\n", diff --git a/drivers/misc/lkdtm/bugs.c b/drivers/misc/lkdtm/bugs.c index 3c95600ab2f7..c66cc05a68c4 100644 --- a/drivers/misc/lkdtm/bugs.c +++ b/drivers/misc/lkdtm/bugs.c @@ -273,8 +273,8 @@ static void lkdtm_HUNG_TASK(void) schedule(); } -volatile unsigned int huge = INT_MAX - 2; -volatile unsigned int ignored; +static volatile unsigned int huge = INT_MAX - 2; +static volatile unsigned int ignored; static void lkdtm_OVERFLOW_SIGNED(void) { @@ -305,7 +305,7 @@ static void lkdtm_OVERFLOW_UNSIGNED(void) ignored = value; } -/* Intentionally using old-style flex array definition of 1 byte. */ +/* Intentionally using unannotated flex array definition. */ struct array_bounds_flex_array { int one; int two; @@ -357,6 +357,46 @@ static void lkdtm_ARRAY_BOUNDS(void) pr_expected_config(CONFIG_UBSAN_BOUNDS); } +struct lkdtm_annotated { + unsigned long flags; + int count; + int array[] __counted_by(count); +}; + +static volatile int fam_count = 4; + +static void lkdtm_FAM_BOUNDS(void) +{ + struct lkdtm_annotated *inst; + + inst = kzalloc(struct_size(inst, array, fam_count + 1), GFP_KERNEL); + if (!inst) { + pr_err("FAIL: could not allocate test struct!\n"); + return; + } + + inst->count = fam_count; + pr_info("Array access within bounds ...\n"); + inst->array[1] = fam_count; + ignored = inst->array[1]; + + pr_info("Array access beyond bounds ...\n"); + inst->array[fam_count] = fam_count; + ignored = inst->array[fam_count]; + + kfree(inst); + + pr_err("FAIL: survived access of invalid flexible array member index!\n"); + + if (!__has_attribute(__counted_by__)) + pr_warn("This is expected since this %s was built a compiler supporting __counted_by\n", + lkdtm_kernel_info); + else if (IS_ENABLED(CONFIG_UBSAN_BOUNDS)) + pr_expected_config(CONFIG_UBSAN_TRAP); + else + pr_expected_config(CONFIG_UBSAN_BOUNDS); +} + static void lkdtm_CORRUPT_LIST_ADD(void) { /* @@ -393,7 +433,7 @@ static void lkdtm_CORRUPT_LIST_ADD(void) pr_err("Overwrite did not happen, but no BUG?!\n"); else { pr_err("list_add() corruption not detected!\n"); - pr_expected_config(CONFIG_DEBUG_LIST); + pr_expected_config(CONFIG_LIST_HARDENED); } } @@ -420,7 +460,7 @@ static void lkdtm_CORRUPT_LIST_DEL(void) pr_err("Overwrite did not happen, but no BUG?!\n"); else { pr_err("list_del() corruption not detected!\n"); - pr_expected_config(CONFIG_DEBUG_LIST); + pr_expected_config(CONFIG_LIST_HARDENED); } } @@ -616,6 +656,7 @@ static struct crashtype crashtypes[] = { CRASHTYPE(OVERFLOW_SIGNED), CRASHTYPE(OVERFLOW_UNSIGNED), CRASHTYPE(ARRAY_BOUNDS), + CRASHTYPE(FAM_BOUNDS), CRASHTYPE(CORRUPT_LIST_ADD), CRASHTYPE(CORRUPT_LIST_DEL), CRASHTYPE(STACK_GUARD_PAGE_LEADING), diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index b6f4be25b31b..b5b414a71e0b 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -918,17 +918,9 @@ static int mmc_sd_num_wr_blocks(struct mmc_card *card, u32 *written_blocks) struct scatterlist sg; - cmd.opcode = MMC_APP_CMD; - cmd.arg = card->rca << 16; - cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; - - err = mmc_wait_for_cmd(card->host, &cmd, 0); + err = mmc_app_cmd(card->host, card); if (err) return err; - if (!mmc_host_is_spi(card->host) && !(cmd.resp[0] & R1_APP_CMD)) - return -EIO; - - memset(&cmd, 0, sizeof(struct mmc_command)); cmd.opcode = SD_APP_SEND_NUM_WR_BLKS; cmd.arg = 0; @@ -3026,7 +3018,6 @@ static void mmc_blk_remove(struct mmc_card *card) pm_runtime_disable(&card->dev); pm_runtime_put_noidle(&card->dev); mmc_blk_remove_req(md); - dev_set_drvdata(&card->dev, NULL); destroy_workqueue(card->complete_wq); } diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 2c3074a605fc..0af96548e7da 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -310,6 +310,9 @@ int mmc_add_card(struct mmc_card *card) dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca); + dev_set_removable(&card->dev, + mmc_card_is_removable(card->host) ? + DEVICE_REMOVABLE : DEVICE_FIXED); switch (card->type) { case MMC_TYPE_MMC: diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index 09ffbc00908b..92d4194c7893 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -32,7 +32,6 @@ int mmc_send_adtc_data(struct mmc_card *card, struct mmc_host *host, u32 opcode, u32 args, void *buf, unsigned len); int mmc_send_csd(struct mmc_card *card, u32 *csd); int __mmc_send_status(struct mmc_card *card, u32 *status, unsigned int retries); -int mmc_send_status(struct mmc_card *card, u32 *status); int mmc_send_cid(struct mmc_host *host, u32 *cid); int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp); int mmc_spi_set_crc(struct mmc_host *host, int use_crc); diff --git a/drivers/mmc/core/pwrseq_emmc.c b/drivers/mmc/core/pwrseq_emmc.c index f6dde9edd7a3..3b6d69cefb4e 100644 --- a/drivers/mmc/core/pwrseq_emmc.c +++ b/drivers/mmc/core/pwrseq_emmc.c @@ -90,14 +90,12 @@ static int mmc_pwrseq_emmc_probe(struct platform_device *pdev) return mmc_pwrseq_register(&pwrseq->pwrseq); } -static int mmc_pwrseq_emmc_remove(struct platform_device *pdev) +static void mmc_pwrseq_emmc_remove(struct platform_device *pdev) { struct mmc_pwrseq_emmc *pwrseq = platform_get_drvdata(pdev); unregister_restart_handler(&pwrseq->reset_nb); mmc_pwrseq_unregister(&pwrseq->pwrseq); - - return 0; } static const struct of_device_id mmc_pwrseq_emmc_of_match[] = { @@ -109,7 +107,7 @@ MODULE_DEVICE_TABLE(of, mmc_pwrseq_emmc_of_match); static struct platform_driver mmc_pwrseq_emmc_driver = { .probe = mmc_pwrseq_emmc_probe, - .remove = mmc_pwrseq_emmc_remove, + .remove_new = mmc_pwrseq_emmc_remove, .driver = { .name = "pwrseq_emmc", .of_match_table = mmc_pwrseq_emmc_of_match, diff --git a/drivers/mmc/core/pwrseq_sd8787.c b/drivers/mmc/core/pwrseq_sd8787.c index 0c5f5e371e1f..0c5808fc3206 100644 --- a/drivers/mmc/core/pwrseq_sd8787.c +++ b/drivers/mmc/core/pwrseq_sd8787.c @@ -113,18 +113,16 @@ static int mmc_pwrseq_sd8787_probe(struct platform_device *pdev) return mmc_pwrseq_register(&pwrseq->pwrseq); } -static int mmc_pwrseq_sd8787_remove(struct platform_device *pdev) +static void mmc_pwrseq_sd8787_remove(struct platform_device *pdev) { struct mmc_pwrseq_sd8787 *pwrseq = platform_get_drvdata(pdev); mmc_pwrseq_unregister(&pwrseq->pwrseq); - - return 0; } static struct platform_driver mmc_pwrseq_sd8787_driver = { .probe = mmc_pwrseq_sd8787_probe, - .remove = mmc_pwrseq_sd8787_remove, + .remove_new = mmc_pwrseq_sd8787_remove, .driver = { .name = "pwrseq_sd8787", .of_match_table = mmc_pwrseq_sd8787_of_match, diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c index 3bac1e71411b..df9588503ad0 100644 --- a/drivers/mmc/core/pwrseq_simple.c +++ b/drivers/mmc/core/pwrseq_simple.c @@ -142,18 +142,16 @@ static int mmc_pwrseq_simple_probe(struct platform_device *pdev) return mmc_pwrseq_register(&pwrseq->pwrseq); } -static int mmc_pwrseq_simple_remove(struct platform_device *pdev) +static void mmc_pwrseq_simple_remove(struct platform_device *pdev) { struct mmc_pwrseq_simple *pwrseq = platform_get_drvdata(pdev); mmc_pwrseq_unregister(&pwrseq->pwrseq); - - return 0; } static struct platform_driver mmc_pwrseq_simple_driver = { .probe = mmc_pwrseq_simple_probe, - .remove = mmc_pwrseq_simple_remove, + .remove_new = mmc_pwrseq_simple_remove, .driver = { .name = "pwrseq_simple", .of_match_table = mmc_pwrseq_simple_of_match, diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 246ce027ae0a..c3e554344c99 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1518,6 +1518,13 @@ retry: */ mmc_set_clock(host, mmc_sd_get_max_clock(card)); + if (host->ios.timing == MMC_TIMING_SD_HS && + host->ops->prepare_sd_hs_tuning) { + err = host->ops->prepare_sd_hs_tuning(host, card); + if (err) + goto free_card; + } + /* * Switch to wider bus (if supported). */ @@ -1529,6 +1536,13 @@ retry: mmc_set_bus_width(host, MMC_BUS_WIDTH_4); } + + if (host->ios.timing == MMC_TIMING_SD_HS && + host->ops->execute_sd_hs_tuning) { + err = host->ops->execute_sd_hs_tuning(host, card); + if (err) + goto free_card; + } } cont: if (!oldcard) { diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index ef8d1dce5af1..a59cd592f06e 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c @@ -323,6 +323,7 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group, return mmc_send_adtc_data(card, card->host, SD_SWITCH, cmd_args, resp, 64); } +EXPORT_SYMBOL_GPL(mmc_sd_switch); int mmc_app_sd_status(struct mmc_card *card, void *ssr) { diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h index 3ba7b3cf4652..7667fc223b74 100644 --- a/drivers/mmc/core/sd_ops.h +++ b/drivers/mmc/core/sd_ops.h @@ -19,8 +19,6 @@ int mmc_send_if_cond(struct mmc_host *host, u32 ocr); int mmc_send_if_cond_pcie(struct mmc_host *host, u32 ocr); int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca); int mmc_app_send_scr(struct mmc_card *card); -int mmc_sd_switch(struct mmc_card *card, int mode, int group, - u8 value, u8 *resp); int mmc_app_sd_status(struct mmc_card *card, void *ssr); int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card); diff --git a/drivers/mmc/host/alcor.c b/drivers/mmc/host/alcor.c index d01df01d4b4d..42aa43740ba8 100644 --- a/drivers/mmc/host/alcor.c +++ b/drivers/mmc/host/alcor.c @@ -1125,7 +1125,7 @@ free_host: return ret; } -static int alcor_pci_sdmmc_drv_remove(struct platform_device *pdev) +static void alcor_pci_sdmmc_drv_remove(struct platform_device *pdev) { struct alcor_sdmmc_host *host = dev_get_drvdata(&pdev->dev); struct mmc_host *mmc = mmc_from_priv(host); @@ -1136,8 +1136,6 @@ static int alcor_pci_sdmmc_drv_remove(struct platform_device *pdev) alcor_hw_uninit(host); mmc_remove_host(mmc); mmc_free_host(mmc); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1177,7 +1175,7 @@ MODULE_DEVICE_TABLE(platform, alcor_pci_sdmmc_ids); static struct platform_driver alcor_pci_sdmmc_driver = { .probe = alcor_pci_sdmmc_drv_probe, - .remove = alcor_pci_sdmmc_drv_remove, + .remove_new = alcor_pci_sdmmc_drv_remove, .id_table = alcor_pci_sdmmc_ids, .driver = { .name = DRV_NAME_ALCOR_PCI_SDMMC, diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index dd18440a90c5..535783c43105 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -11,15 +11,14 @@ #include <linux/dmaengine.h> #include <linux/dma-mapping.h> #include <linux/err.h> -#include <linux/gpio.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/ioport.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_gpio.h> +#include <linux/irq.h> +#include <linux/gpio/consumer.h> #include <linux/platform_device.h> #include <linux/scatterlist.h> #include <linux/seq_file.h> @@ -30,7 +29,6 @@ #include <linux/mmc/host.h> #include <linux/mmc/sdio.h> -#include <linux/atmel-mci.h> #include <linux/atmel_pdc.h> #include <linux/pm.h> #include <linux/pm_runtime.h> @@ -40,6 +38,8 @@ #include <asm/io.h> #include <asm/unaligned.h> +#define ATMCI_MAX_NR_SLOTS 2 + /* * Superset of MCI IP registers integrated in Atmel AT91 Processor * Registers and bitfields marked with [2] are only available in MCI2 @@ -201,6 +201,40 @@ enum atmci_pdc_buf { PDC_SECOND_BUF, }; +/** + * struct mci_slot_pdata - board-specific per-slot configuration + * @bus_width: Number of data lines wired up the slot + * @detect_pin: GPIO pin wired to the card detect switch + * @wp_pin: GPIO pin wired to the write protect sensor + * @non_removable: The slot is not removable, only detect once + * + * If a given slot is not present on the board, @bus_width should be + * set to 0. The other fields are ignored in this case. + * + * Any pins that aren't available should be set to a negative value. + * + * Note that support for multiple slots is experimental -- some cards + * might get upset if we don't get the clock management exactly right. + * But in most cases, it should work just fine. + */ +struct mci_slot_pdata { + unsigned int bus_width; + struct gpio_desc *detect_pin; + struct gpio_desc *wp_pin; + bool non_removable; +}; + +/** + * struct mci_platform_data - board-specific MMC/SDcard configuration + * @dma_slave: DMA slave interface to use in data transfers. + * @slot: Per-slot configuration data. + */ +struct mci_platform_data { + void *dma_slave; + dma_filter_fn dma_filter; + struct mci_slot_pdata slot[ATMCI_MAX_NR_SLOTS]; +}; + struct atmel_mci_caps { bool has_dma_conf_reg; bool has_pdc; @@ -369,7 +403,6 @@ struct atmel_mci { * available. * @wp_pin: GPIO pin used for card write protect sending, or negative * if not available. - * @detect_is_active_high: The state of the detect pin when it is active. * @detect_timer: Timer used for debouncing @detect_pin interrupts. */ struct atmel_mci_slot { @@ -388,9 +421,8 @@ struct atmel_mci_slot { #define ATMCI_CARD_NEED_INIT 1 #define ATMCI_SHUTDOWN 2 - int detect_pin; - int wp_pin; - bool detect_is_active_high; + struct gpio_desc *detect_pin; + struct gpio_desc *wp_pin; struct timer_list detect_timer; }; @@ -608,6 +640,7 @@ atmci_of_init(struct platform_device *pdev) struct device_node *cnp; struct mci_platform_data *pdata; u32 slot_id; + int err; if (!np) { dev_err(&pdev->dev, "device node not found\n"); @@ -637,16 +670,27 @@ atmci_of_init(struct platform_device *pdev) pdata->slot[slot_id].bus_width = 1; pdata->slot[slot_id].detect_pin = - of_get_named_gpio(cnp, "cd-gpios", 0); - - pdata->slot[slot_id].detect_is_active_high = - of_property_read_bool(cnp, "cd-inverted"); + devm_fwnode_gpiod_get(&pdev->dev, of_fwnode_handle(cnp), + "cd", GPIOD_IN, "cd-gpios"); + err = PTR_ERR_OR_ZERO(pdata->slot[slot_id].detect_pin); + if (err) { + if (err != -ENOENT) + return ERR_PTR(err); + pdata->slot[slot_id].detect_pin = NULL; + } pdata->slot[slot_id].non_removable = of_property_read_bool(cnp, "non-removable"); pdata->slot[slot_id].wp_pin = - of_get_named_gpio(cnp, "wp-gpios", 0); + devm_fwnode_gpiod_get(&pdev->dev, of_fwnode_handle(cnp), + "wp", GPIOD_IN, "wp-gpios"); + err = PTR_ERR_OR_ZERO(pdata->slot[slot_id].wp_pin); + if (err) { + if (err != -ENOENT) + return ERR_PTR(err); + pdata->slot[slot_id].wp_pin = NULL; + } } return pdata; @@ -1509,8 +1553,8 @@ static int atmci_get_ro(struct mmc_host *mmc) int read_only = -ENOSYS; struct atmel_mci_slot *slot = mmc_priv(mmc); - if (gpio_is_valid(slot->wp_pin)) { - read_only = gpio_get_value(slot->wp_pin); + if (slot->wp_pin) { + read_only = gpiod_get_value(slot->wp_pin); dev_dbg(&mmc->class_dev, "card is %s\n", read_only ? "read-only" : "read-write"); } @@ -1523,9 +1567,8 @@ static int atmci_get_cd(struct mmc_host *mmc) int present = -ENOSYS; struct atmel_mci_slot *slot = mmc_priv(mmc); - if (gpio_is_valid(slot->detect_pin)) { - present = !(gpio_get_value(slot->detect_pin) ^ - slot->detect_is_active_high); + if (slot->detect_pin) { + present = gpiod_get_value_cansleep(slot->detect_pin); dev_dbg(&mmc->class_dev, "card is %spresent\n", present ? "" : "not "); } @@ -1637,9 +1680,8 @@ static void atmci_detect_change(struct timer_list *t) if (test_bit(ATMCI_SHUTDOWN, &slot->flags)) return; - enable_irq(gpio_to_irq(slot->detect_pin)); - present = !(gpio_get_value(slot->detect_pin) ^ - slot->detect_is_active_high); + enable_irq(gpiod_to_irq(slot->detect_pin)); + present = gpiod_get_value_cansleep(slot->detect_pin); present_old = test_bit(ATMCI_CARD_PRESENT, &slot->flags); dev_vdbg(&slot->mmc->class_dev, "detect change: %d (was %d)\n", @@ -2230,16 +2272,15 @@ static int atmci_init_slot(struct atmel_mci *host, slot->host = host; slot->detect_pin = slot_data->detect_pin; slot->wp_pin = slot_data->wp_pin; - slot->detect_is_active_high = slot_data->detect_is_active_high; slot->sdc_reg = sdc_reg; slot->sdio_irq = sdio_irq; dev_dbg(&mmc->class_dev, "slot[%u]: bus_width=%u, detect_pin=%d, " "detect_is_active_high=%s, wp_pin=%d\n", - id, slot_data->bus_width, slot_data->detect_pin, - slot_data->detect_is_active_high ? "true" : "false", - slot_data->wp_pin); + id, slot_data->bus_width, desc_to_gpio(slot_data->detect_pin), + !gpiod_is_active_low(slot_data->detect_pin) ? "true" : "false", + desc_to_gpio(slot_data->wp_pin)); mmc->ops = &atmci_ops; mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512); @@ -2275,31 +2316,22 @@ static int atmci_init_slot(struct atmel_mci *host, /* Assume card is present initially */ set_bit(ATMCI_CARD_PRESENT, &slot->flags); - if (gpio_is_valid(slot->detect_pin)) { - if (devm_gpio_request(&host->pdev->dev, slot->detect_pin, - "mmc_detect")) { - dev_dbg(&mmc->class_dev, "no detect pin available\n"); - slot->detect_pin = -EBUSY; - } else if (gpio_get_value(slot->detect_pin) ^ - slot->detect_is_active_high) { + if (slot->detect_pin) { + if (!gpiod_get_value_cansleep(slot->detect_pin)) clear_bit(ATMCI_CARD_PRESENT, &slot->flags); - } + } else { + dev_dbg(&mmc->class_dev, "no detect pin available\n"); } - if (!gpio_is_valid(slot->detect_pin)) { + if (!slot->detect_pin) { if (slot_data->non_removable) mmc->caps |= MMC_CAP_NONREMOVABLE; else mmc->caps |= MMC_CAP_NEEDS_POLL; } - if (gpio_is_valid(slot->wp_pin)) { - if (devm_gpio_request(&host->pdev->dev, slot->wp_pin, - "mmc_wp")) { - dev_dbg(&mmc->class_dev, "no WP pin available\n"); - slot->wp_pin = -EBUSY; - } - } + if (!slot->wp_pin) + dev_dbg(&mmc->class_dev, "no WP pin available\n"); host->slot[id] = slot; mmc_regulator_get_supply(mmc); @@ -2309,18 +2341,18 @@ static int atmci_init_slot(struct atmel_mci *host, return ret; } - if (gpio_is_valid(slot->detect_pin)) { + if (slot->detect_pin) { timer_setup(&slot->detect_timer, atmci_detect_change, 0); - ret = request_irq(gpio_to_irq(slot->detect_pin), - atmci_detect_interrupt, - IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, - "mmc-detect", slot); + ret = request_irq(gpiod_to_irq(slot->detect_pin), + atmci_detect_interrupt, + IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, + "mmc-detect", slot); if (ret) { dev_dbg(&mmc->class_dev, "could not request IRQ %d for detect pin\n", - gpio_to_irq(slot->detect_pin)); - slot->detect_pin = -EBUSY; + gpiod_to_irq(slot->detect_pin)); + slot->detect_pin = NULL; } } @@ -2339,10 +2371,8 @@ static void atmci_cleanup_slot(struct atmel_mci_slot *slot, mmc_remove_host(slot->mmc); - if (gpio_is_valid(slot->detect_pin)) { - int pin = slot->detect_pin; - - free_irq(gpio_to_irq(pin), slot); + if (slot->detect_pin) { + free_irq(gpiod_to_irq(slot->detect_pin), slot); del_timer_sync(&slot->detect_timer); } @@ -2600,7 +2630,7 @@ err_dma_probe_defer: return ret; } -static int atmci_remove(struct platform_device *pdev) +static void atmci_remove(struct platform_device *pdev) { struct atmel_mci *host = platform_get_drvdata(pdev); unsigned int i; @@ -2630,8 +2660,6 @@ static int atmci_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); - - return 0; } #ifdef CONFIG_PM @@ -2664,7 +2692,7 @@ static const struct dev_pm_ops atmci_dev_pm_ops = { static struct platform_driver atmci_driver = { .probe = atmci_probe, - .remove = atmci_remove, + .remove_new = atmci_remove, .driver = { .name = "atmel_mci", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index 82dd0ae40305..b5a5c6a2fe8b 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c @@ -1114,7 +1114,7 @@ out0: return ret; } -static int au1xmmc_remove(struct platform_device *pdev) +static void au1xmmc_remove(struct platform_device *pdev) { struct au1xmmc_host *host = platform_get_drvdata(pdev); @@ -1153,7 +1153,6 @@ static int au1xmmc_remove(struct platform_device *pdev) mmc_free_host(host->mmc); } - return 0; } #ifdef CONFIG_PM @@ -1185,7 +1184,7 @@ static int au1xmmc_resume(struct platform_device *pdev) static struct platform_driver au1xmmc_driver = { .probe = au1xmmc_probe, - .remove = au1xmmc_remove, + .remove_new = au1xmmc_remove, .suspend = au1xmmc_suspend, .resume = au1xmmc_resume, .driver = { diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c index eea208856ce0..35d8fdea668b 100644 --- a/drivers/mmc/host/bcm2835.c +++ b/drivers/mmc/host/bcm2835.c @@ -1431,7 +1431,7 @@ err: return ret; } -static int bcm2835_remove(struct platform_device *pdev) +static void bcm2835_remove(struct platform_device *pdev) { struct bcm2835_host *host = platform_get_drvdata(pdev); struct mmc_host *mmc = mmc_from_priv(host); @@ -1449,8 +1449,6 @@ static int bcm2835_remove(struct platform_device *pdev) dma_release_channel(host->dma_chan_rxtx); mmc_free_host(mmc); - - return 0; } static const struct of_device_id bcm2835_match[] = { @@ -1461,7 +1459,7 @@ MODULE_DEVICE_TABLE(of, bcm2835_match); static struct platform_driver bcm2835_driver = { .probe = bcm2835_probe, - .remove = bcm2835_remove, + .remove_new = bcm2835_remove, .driver = { .name = "sdhost-bcm2835", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/cavium-octeon.c b/drivers/mmc/host/cavium-octeon.c index 12dca91a8ef6..060ec4f4800f 100644 --- a/drivers/mmc/host/cavium-octeon.c +++ b/drivers/mmc/host/cavium-octeon.c @@ -13,7 +13,9 @@ #include <linux/mmc/mmc.h> #include <linux/mmc/slot-gpio.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/of_platform.h> +#include <linux/platform_device.h> #include <asm/octeon/octeon.h> #include "cavium.h" @@ -294,7 +296,7 @@ error: return ret; } -static int octeon_mmc_remove(struct platform_device *pdev) +static void octeon_mmc_remove(struct platform_device *pdev) { struct cvm_mmc_host *host = platform_get_drvdata(pdev); u64 dma_cfg; @@ -309,7 +311,6 @@ static int octeon_mmc_remove(struct platform_device *pdev) writeq(dma_cfg, host->dma_base + MIO_EMM_DMA_CFG(host)); octeon_mmc_set_shared_power(host, 0); - return 0; } static const struct of_device_id octeon_mmc_match[] = { @@ -325,7 +326,7 @@ MODULE_DEVICE_TABLE(of, octeon_mmc_match); static struct platform_driver octeon_mmc_driver = { .probe = octeon_mmc_probe, - .remove = octeon_mmc_remove, + .remove_new = octeon_mmc_remove, .driver = { .name = KBUILD_MODNAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/cavium-thunderx.c b/drivers/mmc/host/cavium-thunderx.c index 202b1d6da678..2e2ff984f0b3 100644 --- a/drivers/mmc/host/cavium-thunderx.c +++ b/drivers/mmc/host/cavium-thunderx.c @@ -14,6 +14,7 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/pci.h> #include "cavium.h" diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c index 6d623b2681c3..0aec33b88bef 100644 --- a/drivers/mmc/host/cb710-mmc.c +++ b/drivers/mmc/host/cb710-mmc.c @@ -745,7 +745,7 @@ err_free_mmc: return err; } -static int cb710_mmc_exit(struct platform_device *pdev) +static void cb710_mmc_exit(struct platform_device *pdev) { struct cb710_slot *slot = cb710_pdev_to_slot(pdev); struct mmc_host *mmc = cb710_slot_to_mmc(slot); @@ -766,13 +766,12 @@ static int cb710_mmc_exit(struct platform_device *pdev) tasklet_kill(&reader->finish_req_tasklet); mmc_free_host(mmc); - return 0; } static struct platform_driver cb710_mmc_driver = { .driver.name = "cb710-mmc", .probe = cb710_mmc_init, - .remove = cb710_mmc_exit, + .remove_new = cb710_mmc_exit, #ifdef CONFIG_PM .suspend = cb710_mmc_suspend, .resume = cb710_mmc_resume, diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index 7138dfa065bf..ee3b1a4e0848 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c @@ -21,7 +21,6 @@ #include <linux/dma-mapping.h> #include <linux/mmc/mmc.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/mmc/slot-gpio.h> #include <linux/interrupt.h> @@ -1257,7 +1256,7 @@ static int davinci_mmcsd_probe(struct platform_device *pdev) host->use_dma = use_dma; host->mmc_irq = irq; - host->sdio_irq = platform_get_irq(pdev, 1); + host->sdio_irq = platform_get_irq_optional(pdev, 1); if (host->use_dma) { ret = davinci_acquire_dma_channels(host); @@ -1345,7 +1344,7 @@ ioremap_fail: return ret; } -static int __exit davinci_mmcsd_remove(struct platform_device *pdev) +static void __exit davinci_mmcsd_remove(struct platform_device *pdev) { struct mmc_davinci_host *host = platform_get_drvdata(pdev); @@ -1354,8 +1353,6 @@ static int __exit davinci_mmcsd_remove(struct platform_device *pdev) davinci_release_dma_channels(host); clk_disable_unprepare(host->clk); mmc_free_host(host->mmc); - - return 0; } #ifdef CONFIG_PM @@ -1402,7 +1399,7 @@ static struct platform_driver davinci_mmcsd_driver = { .of_match_table = davinci_mmc_dt_ids, }, .probe = davinci_mmcsd_probe, - .remove = __exit_p(davinci_mmcsd_remove), + .remove_new = __exit_p(davinci_mmcsd_remove), .id_table = davinci_mmc_devtype, }; diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 9f20ac524c8b..698408e8bad0 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -664,15 +664,13 @@ static int dw_mci_exynos_probe(struct platform_device *pdev) return 0; } -static int dw_mci_exynos_remove(struct platform_device *pdev) +static void dw_mci_exynos_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); dw_mci_pltfm_remove(pdev); - - return 0; } static const struct dev_pm_ops dw_mci_exynos_pmops = { @@ -685,7 +683,7 @@ static const struct dev_pm_ops dw_mci_exynos_pmops = { static struct platform_driver dw_mci_exynos_pltfm_driver = { .probe = dw_mci_exynos_probe, - .remove = dw_mci_exynos_remove, + .remove_new = dw_mci_exynos_remove, .driver = { .name = "dwmmc_exynos", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/dw_mmc-hi3798cv200.c b/drivers/mmc/host/dw_mmc-hi3798cv200.c index 6f22fe054087..e9470c50a348 100644 --- a/drivers/mmc/host/dw_mmc-hi3798cv200.c +++ b/drivers/mmc/host/dw_mmc-hi3798cv200.c @@ -171,7 +171,7 @@ static int dw_mci_hi3798cv200_probe(struct platform_device *pdev) return dw_mci_pltfm_register(pdev, &hi3798cv200_data); } -static int dw_mci_hi3798cv200_remove(struct platform_device *pdev) +static void dw_mci_hi3798cv200_remove(struct platform_device *pdev) { struct dw_mci *host = platform_get_drvdata(pdev); struct hi3798cv200_priv *priv = host->priv; @@ -180,8 +180,6 @@ static int dw_mci_hi3798cv200_remove(struct platform_device *pdev) clk_disable_unprepare(priv->sample_clk); dw_mci_pltfm_remove(pdev); - - return 0; } static const struct of_device_id dw_mci_hi3798cv200_match[] = { @@ -192,7 +190,7 @@ static const struct of_device_id dw_mci_hi3798cv200_match[] = { MODULE_DEVICE_TABLE(of, dw_mci_hi3798cv200_match); static struct platform_driver dw_mci_hi3798cv200_driver = { .probe = dw_mci_hi3798cv200_probe, - .remove = dw_mci_hi3798cv200_remove, + .remove_new = dw_mci_hi3798cv200_remove, .driver = { .name = "dwmmc_hi3798cv200", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c index 2a99f15f527f..b07190ba4b7a 100644 --- a/drivers/mmc/host/dw_mmc-rockchip.c +++ b/drivers/mmc/host/dw_mmc-rockchip.c @@ -371,15 +371,13 @@ static int dw_mci_rockchip_probe(struct platform_device *pdev) return 0; } -static int dw_mci_rockchip_remove(struct platform_device *pdev) +static void dw_mci_rockchip_remove(struct platform_device *pdev) { pm_runtime_get_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); dw_mci_pltfm_remove(pdev); - - return 0; } static const struct dev_pm_ops dw_mci_rockchip_dev_pm_ops = { @@ -392,7 +390,7 @@ static const struct dev_pm_ops dw_mci_rockchip_dev_pm_ops = { static struct platform_driver dw_mci_rockchip_pltfm_driver = { .probe = dw_mci_rockchip_probe, - .remove = dw_mci_rockchip_remove, + .remove_new = dw_mci_rockchip_remove, .driver = { .name = "dwmmc_rockchip", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index 1846a05210e3..f379ce5b582d 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -1163,7 +1163,7 @@ err_free_host: return ret; } -static int jz4740_mmc_remove(struct platform_device *pdev) +static void jz4740_mmc_remove(struct platform_device *pdev) { struct jz4740_mmc_host *host = platform_get_drvdata(pdev); @@ -1179,8 +1179,6 @@ static int jz4740_mmc_remove(struct platform_device *pdev) jz4740_mmc_release_dma_channels(host); mmc_free_host(host->mmc); - - return 0; } static int jz4740_mmc_suspend(struct device *dev) @@ -1198,7 +1196,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(jz4740_mmc_pm_ops, jz4740_mmc_suspend, static struct platform_driver jz4740_mmc_driver = { .probe = jz4740_mmc_probe, - .remove = jz4740_mmc_remove, + .remove_new = jz4740_mmc_remove, .driver = { .name = "jz4740-mmc", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/litex_mmc.c b/drivers/mmc/host/litex_mmc.c index 9af6b0902efe..4ec8072dc60b 100644 --- a/drivers/mmc/host/litex_mmc.c +++ b/drivers/mmc/host/litex_mmc.c @@ -629,12 +629,11 @@ static int litex_mmc_probe(struct platform_device *pdev) return 0; } -static int litex_mmc_remove(struct platform_device *pdev) +static void litex_mmc_remove(struct platform_device *pdev) { struct litex_mmc_host *host = platform_get_drvdata(pdev); mmc_remove_host(host->mmc); - return 0; } static const struct of_device_id litex_match[] = { @@ -645,7 +644,7 @@ MODULE_DEVICE_TABLE(of, litex_match); static struct platform_driver litex_mmc_driver = { .probe = litex_mmc_probe, - .remove = litex_mmc_remove, + .remove_new = litex_mmc_remove, .driver = { .name = "litex-mmc", .of_match_table = litex_match, diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index ee9a25b900ae..9837dab096e6 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -11,7 +11,7 @@ #include <linux/delay.h> #include <linux/device.h> #include <linux/iopoll.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/ioport.h> #include <linux/dma-mapping.h> @@ -948,9 +948,6 @@ static irqreturn_t meson_mmc_irq(int irq, void *dev_id) return IRQ_NONE; } - if (WARN_ON(!host)) - return IRQ_NONE; - /* ack all raised interrupts */ writel(status, host->regs + SD_EMMC_STATUS); @@ -1297,7 +1294,7 @@ err_init_clk: return ret; } -static int meson_mmc_remove(struct platform_device *pdev) +static void meson_mmc_remove(struct platform_device *pdev) { struct meson_host *host = dev_get_drvdata(&pdev->dev); @@ -1308,8 +1305,6 @@ static int meson_mmc_remove(struct platform_device *pdev) free_irq(host->irq, host); clk_disable_unprepare(host->mmc_clk); - - return 0; } static const struct meson_mmc_data meson_gx_data = { @@ -1340,7 +1335,7 @@ MODULE_DEVICE_TABLE(of, meson_mmc_of_match); static struct platform_driver meson_mmc_driver = { .probe = meson_mmc_probe, - .remove = meson_mmc_remove, + .remove_new = meson_mmc_remove, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/meson-mx-sdhc-mmc.c b/drivers/mmc/host/meson-mx-sdhc-mmc.c index 97168cdfa8e9..528ec8166e7c 100644 --- a/drivers/mmc/host/meson-mx-sdhc-mmc.c +++ b/drivers/mmc/host/meson-mx-sdhc-mmc.c @@ -880,7 +880,7 @@ err_disable_pclk: return ret; } -static int meson_mx_sdhc_remove(struct platform_device *pdev) +static void meson_mx_sdhc_remove(struct platform_device *pdev) { struct meson_mx_sdhc_host *host = platform_get_drvdata(pdev); @@ -889,8 +889,6 @@ static int meson_mx_sdhc_remove(struct platform_device *pdev) meson_mx_sdhc_disable_clks(host->mmc); clk_disable_unprepare(host->pclk); - - return 0; } static const struct meson_mx_sdhc_data meson_mx_sdhc_data_meson8 = { @@ -925,7 +923,7 @@ MODULE_DEVICE_TABLE(of, meson_mx_sdhc_of_match); static struct platform_driver meson_mx_sdhc_driver = { .probe = meson_mx_sdhc_probe, - .remove = meson_mx_sdhc_remove, + .remove_new = meson_mx_sdhc_remove, .driver = { .name = "meson-mx-sdhc", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/meson-mx-sdio.c b/drivers/mmc/host/meson-mx-sdio.c index 3a19a05ef55a..a11577f2ee69 100644 --- a/drivers/mmc/host/meson-mx-sdio.c +++ b/drivers/mmc/host/meson-mx-sdio.c @@ -728,7 +728,7 @@ error_unregister_slot_pdev: return ret; } -static int meson_mx_mmc_remove(struct platform_device *pdev) +static void meson_mx_mmc_remove(struct platform_device *pdev) { struct meson_mx_mmc_host *host = platform_get_drvdata(pdev); struct device *slot_dev = mmc_dev(host->mmc); @@ -743,8 +743,6 @@ static int meson_mx_mmc_remove(struct platform_device *pdev) clk_disable_unprepare(host->core_clk); mmc_free_host(host->mmc); - - return 0; } static const struct of_device_id meson_mx_mmc_of_match[] = { @@ -756,7 +754,7 @@ MODULE_DEVICE_TABLE(of, meson_mx_mmc_of_match); static struct platform_driver meson_mx_mmc_driver = { .probe = meson_mx_mmc_probe, - .remove = meson_mx_mmc_remove, + .remove_new = meson_mx_mmc_remove, .driver = { .name = "meson-mx-sdio", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 769b34afa835..dda756a56379 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -764,7 +764,8 @@ static bool ux500_busy_complete(struct mmci_host *host, struct mmc_command *cmd, } retries--; } - dev_dbg(mmc_dev(host->mmc), "no busy signalling in time\n"); + dev_dbg(mmc_dev(host->mmc), + "no busy signalling in time CMD%02x\n", cmd->opcode); ux500_busy_clear_mask_done(host); break; @@ -786,7 +787,8 @@ static bool ux500_busy_complete(struct mmci_host *host, struct mmc_command *cmd, host->busy_state = MMCI_BUSY_WAITING_FOR_END_IRQ; } else { dev_dbg(mmc_dev(host->mmc), - "lost busy status when waiting for busy start IRQ\n"); + "lost busy status when waiting for busy start IRQ CMD%02x\n", + cmd->opcode); cancel_delayed_work(&host->ux500_busy_timeout_work); ux500_busy_clear_mask_done(host); } @@ -800,13 +802,14 @@ static bool ux500_busy_complete(struct mmci_host *host, struct mmc_command *cmd, ux500_busy_clear_mask_done(host); } else { dev_dbg(mmc_dev(host->mmc), - "busy status still asserted when handling busy end IRQ - will keep waiting\n"); + "busy status still asserted when handling busy end IRQ - will keep waiting CMD%02x\n", + cmd->opcode); } break; default: - dev_dbg(mmc_dev(host->mmc), "fell through on state %d\n", - host->busy_state); + dev_dbg(mmc_dev(host->mmc), "fell through on state %d, CMD%02x\n", + host->busy_state, cmd->opcode); break; } @@ -1533,6 +1536,20 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, } } +static char *ux500_state_str(struct mmci_host *host) +{ + switch (host->busy_state) { + case MMCI_BUSY_WAITING_FOR_START_IRQ: + return "waiting for start IRQ"; + case MMCI_BUSY_WAITING_FOR_END_IRQ: + return "waiting for end IRQ"; + case MMCI_BUSY_DONE: + return "not waiting for IRQs"; + default: + return "unknown"; + } +} + /* * This busy timeout worker is used to "kick" the command IRQ if a * busy detect IRQ fails to appear in reasonable time. Only used on @@ -1548,12 +1565,18 @@ static void ux500_busy_timeout_work(struct work_struct *work) spin_lock_irqsave(&host->lock, flags); if (host->cmd) { - dev_dbg(mmc_dev(host->mmc), "timeout waiting for busy IRQ\n"); - /* If we are still busy let's tag on a cmd-timeout error. */ status = readl(host->base + MMCISTATUS); - if (status & host->variant->busy_detect_flag) + if (status & host->variant->busy_detect_flag) { status |= MCI_CMDTIMEOUT; + dev_err(mmc_dev(host->mmc), + "timeout in state %s still busy with CMD%02x\n", + ux500_state_str(host), host->cmd->opcode); + } else { + dev_err(mmc_dev(host->mmc), + "timeout in state %s waiting for busy CMD%02x\n", + ux500_state_str(host), host->cmd->opcode); + } mmci_cmd_irq(host, host->cmd, status); } diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c index d0d6ffcf78d4..5cfdd3a86e54 100644 --- a/drivers/mmc/host/moxart-mmc.c +++ b/drivers/mmc/host/moxart-mmc.c @@ -687,13 +687,11 @@ out_mmc: return ret; } -static int moxart_remove(struct platform_device *pdev) +static void moxart_remove(struct platform_device *pdev) { struct mmc_host *mmc = dev_get_drvdata(&pdev->dev); struct moxart_host *host = mmc_priv(mmc); - dev_set_drvdata(&pdev->dev, NULL); - if (!IS_ERR_OR_NULL(host->dma_chan_tx)) dma_release_channel(host->dma_chan_tx); if (!IS_ERR_OR_NULL(host->dma_chan_rx)) @@ -705,8 +703,6 @@ static int moxart_remove(struct platform_device *pdev) writel(readl(host->base + REG_CLOCK_CONTROL) | CLK_OFF, host->base + REG_CLOCK_CONTROL); mmc_free_host(mmc); - - return 0; } static const struct of_device_id moxart_mmc_match[] = { @@ -718,7 +714,7 @@ MODULE_DEVICE_TABLE(of, moxart_mmc_match); static struct platform_driver moxart_mmc_driver = { .probe = moxart_probe, - .remove = moxart_remove, + .remove_new = moxart_remove, .driver = { .name = "mmc-moxart", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 02403ff99e0d..5392200cfdf7 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -12,9 +12,7 @@ #include <linux/iopoll.h> #include <linux/ioport.h> #include <linux/irq.h> -#include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> +#include <linux/of.h> #include <linux/of_gpio.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> @@ -2887,7 +2885,7 @@ host_free: return ret; } -static int msdc_drv_remove(struct platform_device *pdev) +static void msdc_drv_remove(struct platform_device *pdev) { struct mmc_host *mmc; struct msdc_host *host; @@ -2911,8 +2909,6 @@ static int msdc_drv_remove(struct platform_device *pdev) host->dma.bd, host->dma.bd_addr); mmc_free_host(mmc); - - return 0; } static void msdc_save_reg(struct msdc_host *host) @@ -3054,7 +3050,7 @@ static const struct dev_pm_ops msdc_dev_pm_ops = { static struct platform_driver mt_msdc_driver = { .probe = msdc_drv_probe, - .remove = msdc_drv_remove, + .remove_new = msdc_drv_remove, .driver = { .name = "mtk-msdc", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index b4f6a0a2fcb5..ca01b7d204ba 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c @@ -796,7 +796,7 @@ out: return ret; } -static int mvsd_remove(struct platform_device *pdev) +static void mvsd_remove(struct platform_device *pdev) { struct mmc_host *mmc = platform_get_drvdata(pdev); @@ -809,8 +809,6 @@ static int mvsd_remove(struct platform_device *pdev) if (!IS_ERR(host->clk)) clk_disable_unprepare(host->clk); mmc_free_host(mmc); - - return 0; } static const struct of_device_id mvsdio_dt_ids[] = { @@ -821,7 +819,7 @@ MODULE_DEVICE_TABLE(of, mvsdio_dt_ids); static struct platform_driver mvsd_driver = { .probe = mvsd_probe, - .remove = mvsd_remove, + .remove_new = mvsd_remove, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 668f865f3efb..5b3ab0e20505 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -31,7 +31,6 @@ #include <linux/dmaengine.h> #include <linux/types.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_dma.h> #include <linux/mmc/slot-gpio.h> @@ -989,7 +988,6 @@ static int mxcmci_probe(struct platform_device *pdev) pr_info("i.MX/MPC512x SDHC driver\n"); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; @@ -1000,7 +998,7 @@ static int mxcmci_probe(struct platform_device *pdev) host = mmc_priv(mmc); - host->base = devm_ioremap_resource(&pdev->dev, res); + host->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(host->base)) { ret = PTR_ERR(host->base); goto out_free; @@ -1164,7 +1162,7 @@ out_free: return ret; } -static int mxcmci_remove(struct platform_device *pdev) +static void mxcmci_remove(struct platform_device *pdev) { struct mmc_host *mmc = platform_get_drvdata(pdev); struct mxcmci_host *host = mmc_priv(mmc); @@ -1181,8 +1179,6 @@ static int mxcmci_remove(struct platform_device *pdev) clk_disable_unprepare(host->clk_ipg); mmc_free_host(mmc); - - return 0; } static int mxcmci_suspend(struct device *dev) @@ -1216,7 +1212,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(mxcmci_pm_ops, mxcmci_suspend, mxcmci_resume); static struct platform_driver mxcmci_driver = { .probe = mxcmci_probe, - .remove = mxcmci_remove, + .remove_new = mxcmci_remove, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 8c3655d3be96..6751da9b60f9 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -11,7 +11,6 @@ #include <linux/init.h> #include <linux/ioport.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/delay.h> #include <linux/interrupt.h> @@ -674,7 +673,7 @@ out_mmc_free: return ret; } -static int mxs_mmc_remove(struct platform_device *pdev) +static void mxs_mmc_remove(struct platform_device *pdev) { struct mmc_host *mmc = platform_get_drvdata(pdev); struct mxs_mmc_host *host = mmc_priv(mmc); @@ -688,8 +687,6 @@ static int mxs_mmc_remove(struct platform_device *pdev) clk_disable_unprepare(ssp->clk); mmc_free_host(mmc); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -717,7 +714,7 @@ static SIMPLE_DEV_PM_OPS(mxs_mmc_pm_ops, mxs_mmc_suspend, mxs_mmc_resume); static struct platform_driver mxs_mmc_driver = { .probe = mxs_mmc_probe, - .remove = mxs_mmc_remove, + .remove_new = mxs_mmc_remove, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 6a259563690d..9fb8995b43a1 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -1506,7 +1506,7 @@ err_free_iclk: return ret; } -static int mmc_omap_remove(struct platform_device *pdev) +static void mmc_omap_remove(struct platform_device *pdev) { struct mmc_omap_host *host = platform_get_drvdata(pdev); int i; @@ -1532,8 +1532,6 @@ static int mmc_omap_remove(struct platform_device *pdev) dma_release_channel(host->dma_rx); destroy_workqueue(host->mmc_omap_wq); - - return 0; } #if IS_BUILTIN(CONFIG_OF) @@ -1546,7 +1544,7 @@ MODULE_DEVICE_TABLE(of, mmc_omap_match); static struct platform_driver mmc_omap_driver = { .probe = mmc_omap_probe, - .remove = mmc_omap_remove, + .remove_new = mmc_omap_remove, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 1e0f2d7774bd..e120aeb869b8 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1790,14 +1790,11 @@ static int omap_hsmmc_probe(struct platform_device *pdev) return -ENXIO; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENXIO; irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(base)) return PTR_ERR(base); @@ -1982,7 +1979,7 @@ err: return ret; } -static int omap_hsmmc_remove(struct platform_device *pdev) +static void omap_hsmmc_remove(struct platform_device *pdev) { struct omap_hsmmc_host *host = platform_get_drvdata(pdev); @@ -2000,8 +1997,6 @@ static int omap_hsmmc_remove(struct platform_device *pdev) clk_disable_unprepare(host->dbclk); mmc_free_host(host->mmc); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -2126,7 +2121,7 @@ static const struct dev_pm_ops omap_hsmmc_dev_pm_ops = { static struct platform_driver omap_hsmmc_driver = { .probe = omap_hsmmc_probe, - .remove = omap_hsmmc_remove, + .remove_new = omap_hsmmc_remove, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/owl-mmc.c b/drivers/mmc/host/owl-mmc.c index 1bf22b08b373..fc08f25c34eb 100644 --- a/drivers/mmc/host/owl-mmc.c +++ b/drivers/mmc/host/owl-mmc.c @@ -16,8 +16,9 @@ #include <linux/interrupt.h> #include <linux/mmc/host.h> #include <linux/mmc/slot-gpio.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/reset.h> #include <linux/spinlock.h> @@ -667,7 +668,7 @@ err_free_host: return ret; } -static int owl_mmc_remove(struct platform_device *pdev) +static void owl_mmc_remove(struct platform_device *pdev) { struct mmc_host *mmc = platform_get_drvdata(pdev); struct owl_mmc_host *owl_host = mmc_priv(mmc); @@ -676,8 +677,6 @@ static int owl_mmc_remove(struct platform_device *pdev) disable_irq(owl_host->irq); dma_release_channel(owl_host->dma); mmc_free_host(mmc); - - return 0; } static const struct of_device_id owl_mmc_of_match[] = { @@ -693,7 +692,7 @@ static struct platform_driver owl_mmc_driver = { .of_match_table = owl_mmc_of_match, }, .probe = owl_mmc_probe, - .remove = owl_mmc_remove, + .remove_new = owl_mmc_remove, }; module_platform_driver(owl_mmc_driver); diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 2a988f942b6c..fae3192c3a14 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -30,7 +30,6 @@ #include <linux/gpio/consumer.h> #include <linux/gfp.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/soc/pxa/cpu.h> #include <linux/sizes.h> @@ -612,7 +611,6 @@ static int pxamci_probe(struct platform_device *pdev) struct resource *r; int ret, irq; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; @@ -685,14 +683,14 @@ static int pxamci_probe(struct platform_device *pdev) } spin_lock_init(&host->lock); - host->res = r; host->imask = MMC_I_MASK_ALL; - host->base = devm_ioremap_resource(dev, r); + host->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r); if (IS_ERR(host->base)) { ret = PTR_ERR(host->base); goto out; } + host->res = r; /* * Ensure that the host controller is shut down, and setup @@ -784,7 +782,7 @@ out: return ret; } -static int pxamci_remove(struct platform_device *pdev) +static void pxamci_remove(struct platform_device *pdev) { struct mmc_host *mmc = platform_get_drvdata(pdev); @@ -808,13 +806,11 @@ static int pxamci_remove(struct platform_device *pdev) mmc_free_host(mmc); } - - return 0; } static struct platform_driver pxamci_driver = { .probe = pxamci_probe, - .remove = pxamci_remove, + .remove_new = pxamci_remove, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h index 68da3da9e2e5..c1fb9740eab0 100644 --- a/drivers/mmc/host/renesas_sdhi.h +++ b/drivers/mmc/host/renesas_sdhi.h @@ -101,5 +101,5 @@ int renesas_sdhi_probe(struct platform_device *pdev, const struct tmio_mmc_dma_ops *dma_ops, const struct renesas_sdhi_of_data *of_data, const struct renesas_sdhi_quirks *quirks); -int renesas_sdhi_remove(struct platform_device *pdev); +void renesas_sdhi_remove(struct platform_device *pdev); #endif diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 345934e4f59e..c675dec587ef 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -983,12 +983,12 @@ int renesas_sdhi_probe(struct platform_device *pdev, } - host->write16_hook = renesas_sdhi_write16_hook; - host->clk_enable = renesas_sdhi_clk_enable; - host->clk_disable = renesas_sdhi_clk_disable; - host->set_clock = renesas_sdhi_set_clock; - host->multi_io_quirk = renesas_sdhi_multi_io_quirk; - host->dma_ops = dma_ops; + host->write16_hook = renesas_sdhi_write16_hook; + host->clk_enable = renesas_sdhi_clk_enable; + host->clk_disable = renesas_sdhi_clk_disable; + host->set_clock = renesas_sdhi_set_clock; + host->multi_io_quirk = renesas_sdhi_multi_io_quirk; + host->dma_ops = dma_ops; if (sdhi_has_quirk(priv, hs400_disabled)) host->mmc->caps2 &= ~(MMC_CAP2_HS400 | MMC_CAP2_HS400_ES); @@ -1006,6 +1006,8 @@ int renesas_sdhi_probe(struct platform_device *pdev, host->sdcard_irq_setbit_mask = TMIO_STAT_ALWAYS_SET_27; host->sdcard_irq_mask_all = TMIO_MASK_ALL_RCAR2; host->reset = renesas_sdhi_reset; + } else { + host->sdcard_irq_mask_all = TMIO_MASK_ALL; } /* Orginally registers were 16 bit apart, could be 32 or 64 nowadays */ @@ -1100,9 +1102,7 @@ int renesas_sdhi_probe(struct platform_device *pdev, host->ops.hs400_complete = renesas_sdhi_hs400_complete; } - ret = tmio_mmc_host_probe(host); - if (ret < 0) - goto edisclk; + sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, host->sdcard_irq_mask_all); num_irqs = platform_irq_count(pdev); if (num_irqs < 0) { @@ -1129,6 +1129,10 @@ int renesas_sdhi_probe(struct platform_device *pdev, goto eirq; } + ret = tmio_mmc_host_probe(host); + if (ret < 0) + goto edisclk; + dev_info(&pdev->dev, "%s base at %pa, max clock rate %u MHz\n", mmc_hostname(host->mmc), &res->start, host->mmc->f_max / 1000000); @@ -1145,15 +1149,13 @@ efree: } EXPORT_SYMBOL_GPL(renesas_sdhi_probe); -int renesas_sdhi_remove(struct platform_device *pdev) +void renesas_sdhi_remove(struct platform_device *pdev) { struct tmio_mmc_host *host = platform_get_drvdata(pdev); tmio_mmc_host_remove(host); renesas_sdhi_clk_disable(host); tmio_mmc_host_free(host); - - return 0; } EXPORT_SYMBOL_GPL(renesas_sdhi_remove); diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index 9ab813903b2c..53d34c3eddce 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -15,7 +15,8 @@ #include <linux/mmc/host.h> #include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/pagemap.h> #include <linux/scatterlist.h> #include <linux/sys_soc.h> @@ -609,7 +610,7 @@ static struct platform_driver renesas_internal_dmac_sdhi_driver = { .of_match_table = renesas_sdhi_internal_dmac_of_match, }, .probe = renesas_sdhi_internal_dmac_probe, - .remove = renesas_sdhi_remove, + .remove_new = renesas_sdhi_remove, }; module_platform_driver(renesas_internal_dmac_sdhi_driver); diff --git a/drivers/mmc/host/renesas_sdhi_sys_dmac.c b/drivers/mmc/host/renesas_sdhi_sys_dmac.c index b559ad38b667..9cf7f9feab72 100644 --- a/drivers/mmc/host/renesas_sdhi_sys_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_sys_dmac.c @@ -15,7 +15,8 @@ #include <linux/mmc/host.h> #include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/pagemap.h> #include <linux/scatterlist.h> #include <linux/sys_soc.h> @@ -470,7 +471,7 @@ static struct platform_driver renesas_sys_dmac_sdhi_driver = { .of_match_table = renesas_sdhi_sys_dmac_of_match, }, .probe = renesas_sdhi_sys_dmac_probe, - .remove = renesas_sdhi_remove, + .remove_new = renesas_sdhi_remove, }; module_platform_driver(renesas_sys_dmac_sdhi_driver); diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index 8098726dcc0b..87d78432a1e0 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c @@ -1523,15 +1523,12 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev) return 0; } -static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev) +static void rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev) { struct realtek_pci_sdmmc *host = platform_get_drvdata(pdev); struct rtsx_pcr *pcr; struct mmc_host *mmc; - if (!host) - return 0; - pcr = host->pcr; pcr->slots[RTSX_SD_CARD].p_dev = NULL; pcr->slots[RTSX_SD_CARD].card_event = NULL; @@ -1566,8 +1563,6 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev) dev_dbg(&(pdev->dev), ": Realtek PCI-E SDMMC controller has been removed\n"); - - return 0; } static const struct platform_device_id rtsx_pci_sdmmc_ids[] = { @@ -1581,7 +1576,7 @@ MODULE_DEVICE_TABLE(platform, rtsx_pci_sdmmc_ids); static struct platform_driver rtsx_pci_sdmmc_driver = { .probe = rtsx_pci_sdmmc_drv_probe, - .remove = rtsx_pci_sdmmc_drv_remove, + .remove_new = rtsx_pci_sdmmc_drv_remove, .id_table = rtsx_pci_sdmmc_ids, .driver = { .name = DRV_NAME_RTSX_PCI_SDMMC, diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c index 2c650cd58693..ded9b6849e35 100644 --- a/drivers/mmc/host/rtsx_usb_sdmmc.c +++ b/drivers/mmc/host/rtsx_usb_sdmmc.c @@ -1379,13 +1379,13 @@ static int rtsx_usb_sdmmc_drv_probe(struct platform_device *pdev) return 0; } -static int rtsx_usb_sdmmc_drv_remove(struct platform_device *pdev) +static void rtsx_usb_sdmmc_drv_remove(struct platform_device *pdev) { struct rtsx_usb_sdmmc *host = platform_get_drvdata(pdev); struct mmc_host *mmc; if (!host) - return 0; + return; mmc = host->mmc; host->host_removal = true; @@ -1415,8 +1415,6 @@ static int rtsx_usb_sdmmc_drv_remove(struct platform_device *pdev) dev_dbg(&(pdev->dev), ": Realtek USB SD/MMC module has been removed\n"); - - return 0; } #ifdef CONFIG_PM @@ -1455,7 +1453,7 @@ MODULE_DEVICE_TABLE(platform, rtsx_usb_sdmmc_ids); static struct platform_driver rtsx_usb_sdmmc_driver = { .probe = rtsx_usb_sdmmc_drv_probe, - .remove = rtsx_usb_sdmmc_drv_remove, + .remove_new = rtsx_usb_sdmmc_drv_remove, .id_table = rtsx_usb_sdmmc_ids, .driver = { .name = "rtsx_usb_sdmmc", diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index edf2e6c14dc6..acf5fc3ad7e4 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -917,7 +917,7 @@ err_free: return err; } -static int sdhci_acpi_remove(struct platform_device *pdev) +static void sdhci_acpi_remove(struct platform_device *pdev) { struct sdhci_acpi_host *c = platform_get_drvdata(pdev); struct device *dev = &pdev->dev; @@ -939,8 +939,6 @@ static int sdhci_acpi_remove(struct platform_device *pdev) c->slot->free_slot(pdev); sdhci_free_host(c->host); - - return 0; } static void __maybe_unused sdhci_acpi_reset_signal_voltage_if_needed( @@ -1033,7 +1031,7 @@ static struct platform_driver sdhci_acpi_driver = { .pm = &sdhci_acpi_pm_ops, }, .probe = sdhci_acpi_probe, - .remove = sdhci_acpi_remove, + .remove_new = sdhci_acpi_remove, }; module_platform_driver(sdhci_acpi_driver); diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c index 6a93a54fe067..cb9152c6a65d 100644 --- a/drivers/mmc/host/sdhci-bcm-kona.c +++ b/drivers/mmc/host/sdhci-bcm-kona.c @@ -11,7 +11,6 @@ #include <linux/clk.h> #include <linux/regulator/consumer.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/mmc/slot-gpio.h> #include "sdhci-pltfm.h" @@ -311,6 +310,16 @@ err_pltfm_free: return ret; } +static void sdhci_bcm_kona_remove(struct platform_device *pdev) +{ + struct sdhci_host *host = platform_get_drvdata(pdev); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct clk *clk = pltfm_host->clk; + + sdhci_pltfm_remove(pdev); + clk_disable_unprepare(clk); +} + static struct platform_driver sdhci_bcm_kona_driver = { .driver = { .name = "sdhci-kona", @@ -319,7 +328,7 @@ static struct platform_driver sdhci_bcm_kona_driver = { .of_match_table = sdhci_bcm_kona_of_match, }, .probe = sdhci_bcm_kona_probe, - .remove = sdhci_pltfm_unregister, + .remove_new = sdhci_bcm_kona_remove, }; module_platform_driver(sdhci_bcm_kona_driver); diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c index 4c22337199cf..c23251bb95f3 100644 --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -264,23 +264,17 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "Probe found match for %s\n", match->compatible); - clk = devm_clk_get_optional(&pdev->dev, NULL); + clk = devm_clk_get_optional_enabled(&pdev->dev, NULL); if (IS_ERR(clk)) return dev_err_probe(&pdev->dev, PTR_ERR(clk), - "Failed to get clock from Device Tree\n"); - - res = clk_prepare_enable(clk); - if (res) - return res; + "Failed to get and enable clock from Device Tree\n"); memset(&brcmstb_pdata, 0, sizeof(brcmstb_pdata)); brcmstb_pdata.ops = match_priv->ops; host = sdhci_pltfm_init(pdev, &brcmstb_pdata, sizeof(struct sdhci_brcmstb_priv)); - if (IS_ERR(host)) { - res = PTR_ERR(host); - goto err_clk; - } + if (IS_ERR(host)) + return PTR_ERR(host); pltfm_host = sdhci_priv(host); priv = sdhci_pltfm_priv(pltfm_host); @@ -369,9 +363,7 @@ add_host: err: sdhci_pltfm_free(pdev); -err_clk: clk_disable_unprepare(base_clk); - clk_disable_unprepare(clk); return res; } @@ -430,7 +422,7 @@ static struct platform_driver sdhci_brcmstb_driver = { .of_match_table = of_match_ptr(sdhci_brcm_of_match), }, .probe = sdhci_brcmstb_probe, - .remove = sdhci_pltfm_unregister, + .remove_new = sdhci_pltfm_remove, .shutdown = sdhci_brcmstb_shutdown, }; diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c index d2f625054689..be1505e8c536 100644 --- a/drivers/mmc/host/sdhci-cadence.c +++ b/drivers/mmc/host/sdhci-cadence.c @@ -11,7 +11,7 @@ #include <linux/mmc/host.h> #include <linux/mmc/mmc.h> #include <linux/of.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> #include <linux/reset.h> #include "sdhci-pltfm.h" @@ -487,14 +487,10 @@ static int sdhci_cdns_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; static const u16 version = SDHCI_SPEC_400 << SDHCI_SPEC_VER_SHIFT; - clk = devm_clk_get(dev, NULL); + clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(clk)) return PTR_ERR(clk); - ret = clk_prepare_enable(clk); - if (ret) - return ret; - data = of_device_get_match_data(dev); if (!data) data = &sdhci_cdns_drv_data; @@ -502,10 +498,8 @@ static int sdhci_cdns_probe(struct platform_device *pdev) nr_phy_params = sdhci_cdns_phy_param_count(dev->of_node); host = sdhci_pltfm_init(pdev, &data->pltfm_data, struct_size(priv, phy_params, nr_phy_params)); - if (IS_ERR(host)) { - ret = PTR_ERR(host); - goto disable_clk; - } + if (IS_ERR(host)) + return PTR_ERR(host); pltfm_host = sdhci_priv(host); pltfm_host->clk = clk; @@ -556,9 +550,6 @@ static int sdhci_cdns_probe(struct platform_device *pdev) return 0; free: sdhci_pltfm_free(pdev); -disable_clk: - clk_disable_unprepare(clk); - return ret; } @@ -617,7 +608,7 @@ static struct platform_driver sdhci_cdns_driver = { .of_match_table = sdhci_cdns_match, }, .probe = sdhci_cdns_probe, - .remove = sdhci_pltfm_unregister, + .remove_new = sdhci_pltfm_remove, }; module_platform_driver(sdhci_cdns_driver); diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index 5e5bf82e5976..88ec23417808 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c @@ -75,10 +75,7 @@ static int sdhci_dove_probe(struct platform_device *pdev) return PTR_ERR(host); pltfm_host = sdhci_priv(host); - pltfm_host->clk = devm_clk_get(&pdev->dev, NULL); - - if (!IS_ERR(pltfm_host->clk)) - clk_prepare_enable(pltfm_host->clk); + pltfm_host->clk = devm_clk_get_enabled(&pdev->dev, NULL); ret = mmc_of_parse(host->mmc); if (ret) @@ -91,7 +88,6 @@ static int sdhci_dove_probe(struct platform_device *pdev) return 0; err_sdhci_add: - clk_disable_unprepare(pltfm_host->clk); sdhci_pltfm_free(pdev); return ret; } @@ -110,7 +106,7 @@ static struct platform_driver sdhci_dove_driver = { .of_match_table = sdhci_dove_of_match_table, }, .probe = sdhci_dove_probe, - .remove = sdhci_pltfm_unregister, + .remove_new = sdhci_pltfm_remove, }; module_platform_driver(sdhci_dove_driver); diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index eebf94604a7f..3b8030f3552a 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -22,7 +22,7 @@ #include <linux/mmc/sdio.h> #include <linux/mmc/slot-gpio.h> #include <linux/of.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> #include <linux/pinctrl/consumer.h> #include <linux/pm_runtime.h> #include "sdhci-cqhci.h" @@ -171,8 +171,8 @@ #define ESDHC_FLAG_HS400 BIT(9) /* * The IP has errata ERR010450 - * uSDHC: Due to the I/O timing limit, for SDR mode, SD card clock can't - * exceed 150MHz, for DDR mode, SD card clock can't exceed 45MHz. + * uSDHC: At 1.8V due to the I/O timing limit, for SDR mode, SD card + * clock can't exceed 150MHz, for DDR mode, SD card clock can't exceed 45MHz. */ #define ESDHC_FLAG_ERR010450 BIT(10) /* The IP supports HS400ES mode */ @@ -961,7 +961,8 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host, | ESDHC_CLOCK_MASK); sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); - if (imx_data->socdata->flags & ESDHC_FLAG_ERR010450) { + if ((imx_data->socdata->flags & ESDHC_FLAG_ERR010450) && + (!(host->quirks2 & SDHCI_QUIRK2_NO_1_8_V))) { unsigned int max_clock; max_clock = imx_data->is_ddr ? 45000000 : 150000000; @@ -1802,7 +1803,7 @@ free_sdhci: return err; } -static int sdhci_esdhc_imx_remove(struct platform_device *pdev) +static void sdhci_esdhc_imx_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -1824,8 +1825,6 @@ static int sdhci_esdhc_imx_remove(struct platform_device *pdev) cpu_latency_qos_remove_request(&imx_data->pm_qos_req); sdhci_pltfm_free(pdev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1986,7 +1985,7 @@ static struct platform_driver sdhci_esdhc_imx_driver = { .pm = &sdhci_esdhc_pmops, }, .probe = sdhci_esdhc_imx_probe, - .remove = sdhci_esdhc_imx_remove, + .remove_new = sdhci_esdhc_imx_remove, }; module_platform_driver(sdhci_esdhc_imx_driver); diff --git a/drivers/mmc/host/sdhci-esdhc-mcf.c b/drivers/mmc/host/sdhci-esdhc-mcf.c index 05926bf5ecf9..a07f8333cd6b 100644 --- a/drivers/mmc/host/sdhci-esdhc-mcf.c +++ b/drivers/mmc/host/sdhci-esdhc-mcf.c @@ -489,7 +489,7 @@ err_exit: return err; } -static int sdhci_esdhc_mcf_remove(struct platform_device *pdev) +static void sdhci_esdhc_mcf_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -502,8 +502,6 @@ static int sdhci_esdhc_mcf_remove(struct platform_device *pdev) clk_disable_unprepare(mcf_data->clk_per); sdhci_pltfm_free(pdev); - - return 0; } static struct platform_driver sdhci_esdhc_mcf_driver = { @@ -512,7 +510,7 @@ static struct platform_driver sdhci_esdhc_mcf_driver = { .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .probe = sdhci_esdhc_mcf_probe, - .remove = sdhci_esdhc_mcf_remove, + .remove_new = sdhci_esdhc_mcf_remove, }; module_platform_driver(sdhci_esdhc_mcf_driver); diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c index 86eb0045515e..10235fdff246 100644 --- a/drivers/mmc/host/sdhci-iproc.c +++ b/drivers/mmc/host/sdhci-iproc.c @@ -10,7 +10,7 @@ #include <linux/module.h> #include <linux/mmc/host.h> #include <linux/of.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> #include "sdhci-pltfm.h" struct sdhci_iproc_data { @@ -386,16 +386,11 @@ static int sdhci_iproc_probe(struct platform_device *pdev) host->mmc->caps |= iproc_host->data->mmc_caps; if (dev->of_node) { - pltfm_host->clk = devm_clk_get(dev, NULL); + pltfm_host->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(pltfm_host->clk)) { ret = PTR_ERR(pltfm_host->clk); goto err; } - ret = clk_prepare_enable(pltfm_host->clk); - if (ret) { - dev_err(dev, "failed to enable host clk\n"); - goto err; - } } if (iproc_host->data->missing_caps) { @@ -406,13 +401,10 @@ static int sdhci_iproc_probe(struct platform_device *pdev) ret = sdhci_add_host(host); if (ret) - goto err_clk; + goto err; return 0; -err_clk: - if (dev->of_node) - clk_disable_unprepare(pltfm_host->clk); err: sdhci_pltfm_free(pdev); return ret; @@ -432,7 +424,7 @@ static struct platform_driver sdhci_iproc_driver = { .pm = &sdhci_pltfm_pmops, }, .probe = sdhci_iproc_probe, - .remove = sdhci_pltfm_unregister, + .remove_new = sdhci_pltfm_remove, .shutdown = sdhci_iproc_shutdown, }; module_platform_driver(sdhci_iproc_driver); diff --git a/drivers/mmc/host/sdhci-milbeaut.c b/drivers/mmc/host/sdhci-milbeaut.c index 148b37ac6564..83706edc9796 100644 --- a/drivers/mmc/host/sdhci-milbeaut.c +++ b/drivers/mmc/host/sdhci-milbeaut.c @@ -313,7 +313,7 @@ err: return ret; } -static int sdhci_milbeaut_remove(struct platform_device *pdev) +static void sdhci_milbeaut_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct f_sdhost_priv *priv = sdhci_priv(host); @@ -326,18 +326,16 @@ static int sdhci_milbeaut_remove(struct platform_device *pdev) sdhci_free_host(host); platform_set_drvdata(pdev, NULL); - - return 0; } static struct platform_driver sdhci_milbeaut_driver = { .driver = { .name = "sdhci-milbeaut", .probe_type = PROBE_PREFER_ASYNCHRONOUS, - .of_match_table = of_match_ptr(mlb_dt_ids), + .of_match_table = mlb_dt_ids, }, .probe = sdhci_milbeaut_probe, - .remove = sdhci_milbeaut_remove, + .remove_new = sdhci_milbeaut_remove, }; module_platform_driver(sdhci_milbeaut_driver); diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 1c935b5bafe1..668e0aceeeba 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -6,7 +6,6 @@ */ #include <linux/module.h> -#include <linux/of_device.h> #include <linux/delay.h> #include <linux/mmc/mmc.h> #include <linux/pm_runtime.h> @@ -15,6 +14,7 @@ #include <linux/iopoll.h> #include <linux/regulator/consumer.h> #include <linux/interconnect.h> +#include <linux/of.h> #include <linux/pinctrl/consumer.h> #include <linux/reset.h> @@ -2668,7 +2668,7 @@ pltfm_free: return ret; } -static int sdhci_msm_remove(struct platform_device *pdev) +static void sdhci_msm_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -2687,7 +2687,6 @@ static int sdhci_msm_remove(struct platform_device *pdev) if (!IS_ERR(msm_host->bus_clk)) clk_disable_unprepare(msm_host->bus_clk); sdhci_pltfm_free(pdev); - return 0; } static __maybe_unused int sdhci_msm_runtime_suspend(struct device *dev) @@ -2740,7 +2739,7 @@ static const struct dev_pm_ops sdhci_msm_pm_ops = { static struct platform_driver sdhci_msm_driver = { .probe = sdhci_msm_probe, - .remove = sdhci_msm_remove, + .remove_new = sdhci_msm_remove, .driver = { .name = "sdhci_msm", .of_match_table = sdhci_msm_dt_match, diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index 294dd605fd2b..5edd024347bd 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -18,11 +18,11 @@ #include <linux/clk-provider.h> #include <linux/mfd/syscon.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/phy/phy.h> #include <linux/regmap.h> #include <linux/reset.h> -#include <linux/of.h> #include <linux/firmware/xlnx-zynqmp.h> #include "cqhci.h" @@ -2016,12 +2016,13 @@ err_pltfm_free: return ret; } -static int sdhci_arasan_remove(struct platform_device *pdev) +static void sdhci_arasan_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host); struct clk *clk_ahb = sdhci_arasan->clk_ahb; + struct clk *clk_xin = pltfm_host->clk; if (!IS_ERR(sdhci_arasan->phy)) { if (sdhci_arasan->is_phy_on) @@ -2031,11 +2032,10 @@ static int sdhci_arasan_remove(struct platform_device *pdev) sdhci_arasan_unregister_sdclk(&pdev->dev); - sdhci_pltfm_unregister(pdev); + sdhci_pltfm_remove(pdev); + clk_disable_unprepare(clk_xin); clk_disable_unprepare(clk_ahb); - - return 0; } static struct platform_driver sdhci_arasan_driver = { @@ -2046,7 +2046,7 @@ static struct platform_driver sdhci_arasan_driver = { .pm = &sdhci_arasan_dev_pm_ops, }, .probe = sdhci_arasan_probe, - .remove = sdhci_arasan_remove, + .remove_new = sdhci_arasan_remove, }; module_platform_driver(sdhci_arasan_driver); diff --git a/drivers/mmc/host/sdhci-of-aspeed.c b/drivers/mmc/host/sdhci-of-aspeed.c index 25b4073f698b..42d54532cabe 100644 --- a/drivers/mmc/host/sdhci-of-aspeed.c +++ b/drivers/mmc/host/sdhci-of-aspeed.c @@ -450,22 +450,19 @@ err_pltfm_free: return ret; } -static int aspeed_sdhci_remove(struct platform_device *pdev) +static void aspeed_sdhci_remove(struct platform_device *pdev) { struct sdhci_pltfm_host *pltfm_host; struct sdhci_host *host; - int dead = 0; host = platform_get_drvdata(pdev); pltfm_host = sdhci_priv(host); - sdhci_remove_host(host, dead); + sdhci_remove_host(host, 0); clk_disable_unprepare(pltfm_host->clk); sdhci_pltfm_free(pdev); - - return 0; } static const struct aspeed_sdhci_pdata ast2400_sdhci_pdata = { @@ -521,7 +518,7 @@ static struct platform_driver aspeed_sdhci_driver = { .of_match_table = aspeed_sdhci_of_match, }, .probe = aspeed_sdhci_probe, - .remove = aspeed_sdhci_remove, + .remove_new = aspeed_sdhci_remove, }; static int aspeed_sdc_probe(struct platform_device *pdev) @@ -574,13 +571,11 @@ err_clk: return ret; } -static int aspeed_sdc_remove(struct platform_device *pdev) +static void aspeed_sdc_remove(struct platform_device *pdev) { struct aspeed_sdc *sdc = dev_get_drvdata(&pdev->dev); clk_disable_unprepare(sdc->clk); - - return 0; } static const struct of_device_id aspeed_sdc_of_match[] = { @@ -600,7 +595,7 @@ static struct platform_driver aspeed_sdc_driver = { .of_match_table = aspeed_sdc_of_match, }, .probe = aspeed_sdc_probe, - .remove = aspeed_sdc_remove, + .remove_new = aspeed_sdc_remove, }; #if defined(CONFIG_MMC_SDHCI_OF_ASPEED_TEST) diff --git a/drivers/mmc/host/sdhci-of-at91.c b/drivers/mmc/host/sdhci-of-at91.c index cd0134580a90..23a9faad2ff8 100644 --- a/drivers/mmc/host/sdhci-of-at91.c +++ b/drivers/mmc/host/sdhci-of-at91.c @@ -17,7 +17,7 @@ #include <linux/mmc/slot-gpio.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> #include <linux/pm.h> #include <linux/pm_runtime.h> @@ -443,7 +443,7 @@ sdhci_pltfm_free: return ret; } -static int sdhci_at91_remove(struct platform_device *pdev) +static void sdhci_at91_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -456,13 +456,11 @@ static int sdhci_at91_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); - sdhci_pltfm_unregister(pdev); + sdhci_pltfm_remove(pdev); clk_disable_unprepare(gck); clk_disable_unprepare(hclock); clk_disable_unprepare(mainck); - - return 0; } static struct platform_driver sdhci_at91_driver = { @@ -473,7 +471,7 @@ static struct platform_driver sdhci_at91_driver = { .pm = &sdhci_at91_dev_pm_ops, }, .probe = sdhci_at91_probe, - .remove = sdhci_at91_remove, + .remove_new = sdhci_at91_remove, }; module_platform_driver(sdhci_at91_driver); diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index e68cd87998c8..3a3bae6948a8 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -14,7 +14,8 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/reset.h> #include <linux/sizes.h> @@ -548,9 +549,13 @@ static int dwcmshc_probe(struct platform_device *pdev) host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + err = sdhci_setup_host(host); if (err) - goto err_clk; + goto err_rpm; if (rk_priv) dwcmshc_rk35xx_postinit(host, priv); @@ -559,10 +564,15 @@ static int dwcmshc_probe(struct platform_device *pdev) if (err) goto err_setup_host; + pm_runtime_put(dev); + return 0; err_setup_host: sdhci_cleanup_host(host); +err_rpm: + pm_runtime_disable(dev); + pm_runtime_put_noidle(dev); err_clk: clk_disable_unprepare(pltfm_host->clk); clk_disable_unprepare(priv->bus_clk); @@ -574,7 +584,7 @@ free_pltfm: return err; } -static int dwcmshc_remove(struct platform_device *pdev) +static void dwcmshc_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -589,8 +599,6 @@ static int dwcmshc_remove(struct platform_device *pdev) clk_bulk_disable_unprepare(RK35xx_MAX_CLKS, rk_priv->rockchip_clks); sdhci_pltfm_free(pdev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -602,6 +610,8 @@ static int dwcmshc_suspend(struct device *dev) struct rk35xx_priv *rk_priv = priv->priv; int ret; + pm_runtime_resume(dev); + ret = sdhci_suspend_host(host); if (ret) return ret; @@ -632,21 +642,84 @@ static int dwcmshc_resume(struct device *dev) if (!IS_ERR(priv->bus_clk)) { ret = clk_prepare_enable(priv->bus_clk); if (ret) - return ret; + goto disable_clk; } if (rk_priv) { ret = clk_bulk_prepare_enable(RK35xx_MAX_CLKS, rk_priv->rockchip_clks); if (ret) - return ret; + goto disable_bus_clk; } - return sdhci_resume_host(host); + ret = sdhci_resume_host(host); + if (ret) + goto disable_rockchip_clks; + + return 0; + +disable_rockchip_clks: + if (rk_priv) + clk_bulk_disable_unprepare(RK35xx_MAX_CLKS, + rk_priv->rockchip_clks); +disable_bus_clk: + if (!IS_ERR(priv->bus_clk)) + clk_disable_unprepare(priv->bus_clk); +disable_clk: + clk_disable_unprepare(pltfm_host->clk); + return ret; } #endif -static SIMPLE_DEV_PM_OPS(dwcmshc_pmops, dwcmshc_suspend, dwcmshc_resume); +#ifdef CONFIG_PM + +static void dwcmshc_enable_card_clk(struct sdhci_host *host) +{ + u16 ctrl; + + ctrl = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + if ((ctrl & SDHCI_CLOCK_INT_EN) && !(ctrl & SDHCI_CLOCK_CARD_EN)) { + ctrl |= SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, ctrl, SDHCI_CLOCK_CONTROL); + } +} + +static void dwcmshc_disable_card_clk(struct sdhci_host *host) +{ + u16 ctrl; + + ctrl = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + if (ctrl & SDHCI_CLOCK_CARD_EN) { + ctrl &= ~SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, ctrl, SDHCI_CLOCK_CONTROL); + } +} + +static int dwcmshc_runtime_suspend(struct device *dev) +{ + struct sdhci_host *host = dev_get_drvdata(dev); + + dwcmshc_disable_card_clk(host); + + return 0; +} + +static int dwcmshc_runtime_resume(struct device *dev) +{ + struct sdhci_host *host = dev_get_drvdata(dev); + + dwcmshc_enable_card_clk(host); + + return 0; +} + +#endif + +static const struct dev_pm_ops dwcmshc_pmops = { + SET_SYSTEM_SLEEP_PM_OPS(dwcmshc_suspend, dwcmshc_resume) + SET_RUNTIME_PM_OPS(dwcmshc_runtime_suspend, + dwcmshc_runtime_resume, NULL) +}; static struct platform_driver sdhci_dwcmshc_driver = { .driver = { @@ -657,7 +730,7 @@ static struct platform_driver sdhci_dwcmshc_driver = { .pm = &dwcmshc_pmops, }, .probe = dwcmshc_probe, - .remove = dwcmshc_remove, + .remove_new = dwcmshc_remove, }; module_platform_driver(sdhci_dwcmshc_driver); diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index 48ca1cf15b19..3ae9aa25745a 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -1521,7 +1521,7 @@ static struct platform_driver sdhci_esdhc_driver = { .pm = &esdhc_of_dev_pm_ops, }, .probe = sdhci_esdhc_probe, - .remove = sdhci_pltfm_unregister, + .remove_new = sdhci_pltfm_remove, }; module_platform_driver(sdhci_esdhc_driver); diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c index 12675797b296..9c1c0ce610ef 100644 --- a/drivers/mmc/host/sdhci-of-hlwd.c +++ b/drivers/mmc/host/sdhci-of-hlwd.c @@ -68,7 +68,7 @@ static const struct sdhci_pltfm_data sdhci_hlwd_pdata = { static int sdhci_hlwd_probe(struct platform_device *pdev) { - return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata, 0); + return sdhci_pltfm_init_and_add_host(pdev, &sdhci_hlwd_pdata, 0); } static const struct of_device_id sdhci_hlwd_of_match[] = { @@ -85,7 +85,7 @@ static struct platform_driver sdhci_hlwd_driver = { .pm = &sdhci_pltfm_pmops, }, .probe = sdhci_hlwd_probe, - .remove = sdhci_pltfm_unregister, + .remove_new = sdhci_pltfm_remove, }; module_platform_driver(sdhci_hlwd_driver); diff --git a/drivers/mmc/host/sdhci-of-sparx5.c b/drivers/mmc/host/sdhci-of-sparx5.c index 28e4ee69e100..64b77e7d14cd 100644 --- a/drivers/mmc/host/sdhci-of-sparx5.c +++ b/drivers/mmc/host/sdhci-of-sparx5.c @@ -13,9 +13,9 @@ #include <linux/delay.h> #include <linux/module.h> #include <linux/regmap.h> -#include <linux/of_device.h> #include <linux/mfd/syscon.h> #include <linux/dma-mapping.h> +#include <linux/of.h> #include "sdhci-pltfm.h" @@ -184,15 +184,12 @@ static int sdhci_sparx5_probe(struct platform_device *pdev) sdhci_sparx5 = sdhci_pltfm_priv(pltfm_host); sdhci_sparx5->host = host; - pltfm_host->clk = devm_clk_get(&pdev->dev, "core"); + pltfm_host->clk = devm_clk_get_enabled(&pdev->dev, "core"); if (IS_ERR(pltfm_host->clk)) { ret = PTR_ERR(pltfm_host->clk); - dev_err(&pdev->dev, "failed to get core clk: %d\n", ret); + dev_err(&pdev->dev, "failed to get and enable core clk: %d\n", ret); goto free_pltfm; } - ret = clk_prepare_enable(pltfm_host->clk); - if (ret) - goto free_pltfm; if (!of_property_read_u32(np, "microchip,clock-delay", &value) && (value > 0 && value <= MSHC_DLY_CC_MAX)) @@ -202,13 +199,13 @@ static int sdhci_sparx5_probe(struct platform_device *pdev) ret = mmc_of_parse(host->mmc); if (ret) - goto err_clk; + goto free_pltfm; sdhci_sparx5->cpu_ctrl = syscon_regmap_lookup_by_compatible(syscon); if (IS_ERR(sdhci_sparx5->cpu_ctrl)) { dev_err(&pdev->dev, "No CPU syscon regmap !\n"); ret = PTR_ERR(sdhci_sparx5->cpu_ctrl); - goto err_clk; + goto free_pltfm; } if (sdhci_sparx5->delay_clock >= 0) @@ -225,7 +222,7 @@ static int sdhci_sparx5_probe(struct platform_device *pdev) ret = sdhci_add_host(host); if (ret) - goto err_clk; + goto free_pltfm; /* Set AXI bus master to use un-cached access (for DMA) */ if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA) && @@ -239,8 +236,6 @@ static int sdhci_sparx5_probe(struct platform_device *pdev) return ret; -err_clk: - clk_disable_unprepare(pltfm_host->clk); free_pltfm: sdhci_pltfm_free(pdev); return ret; @@ -260,7 +255,7 @@ static struct platform_driver sdhci_sparx5_driver = { .pm = &sdhci_pltfm_pmops, }, .probe = sdhci_sparx5_probe, - .remove = sdhci_pltfm_unregister, + .remove_new = sdhci_pltfm_remove, }; module_platform_driver(sdhci_sparx5_driver); diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c index 8ed9256b83da..1e0bc7bace1b 100644 --- a/drivers/mmc/host/sdhci-omap.c +++ b/drivers/mmc/host/sdhci-omap.c @@ -11,7 +11,6 @@ #include <linux/mmc/slot-gpio.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> @@ -1394,7 +1393,7 @@ err_pltfm_free: return ret; } -static int sdhci_omap_remove(struct platform_device *pdev) +static void sdhci_omap_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct sdhci_host *host = platform_get_drvdata(pdev); @@ -1408,8 +1407,6 @@ static int sdhci_omap_remove(struct platform_device *pdev) /* Ensure device gets disabled despite userspace sysfs config */ pm_runtime_force_suspend(dev); sdhci_pltfm_free(pdev); - - return 0; } #ifdef CONFIG_PM @@ -1478,7 +1475,7 @@ static const struct dev_pm_ops sdhci_omap_dev_pm_ops = { static struct platform_driver sdhci_omap_driver = { .probe = sdhci_omap_probe, - .remove = sdhci_omap_remove, + .remove_new = sdhci_omap_remove, .driver = { .name = "sdhci-omap", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 1c2572c0f012..7c14feb5db77 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -1898,6 +1898,10 @@ static const struct pci_device_id pci_ids[] = { SDHCI_PCI_DEVICE(O2, SDS1, o2), SDHCI_PCI_DEVICE(O2, SEABIRD0, o2), SDHCI_PCI_DEVICE(O2, SEABIRD1, o2), + SDHCI_PCI_DEVICE(O2, GG8_9860, o2), + SDHCI_PCI_DEVICE(O2, GG8_9861, o2), + SDHCI_PCI_DEVICE(O2, GG8_9862, o2), + SDHCI_PCI_DEVICE(O2, GG8_9863, o2), SDHCI_PCI_DEVICE(ARASAN, PHY_EMMC, arasan), SDHCI_PCI_DEVICE(SYNOPSYS, DWC_MSHC, snps), SDHCI_PCI_DEVICE(GLI, 9750, gl9750), diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c index 620f52ad9667..7bfee28116af 100644 --- a/drivers/mmc/host/sdhci-pci-o2micro.c +++ b/drivers/mmc/host/sdhci-pci-o2micro.c @@ -21,6 +21,7 @@ * O2Micro device registers */ +#define O2_SD_PCIE_SWITCH 0x54 #define O2_SD_MISC_REG5 0x64 #define O2_SD_LD0_CTRL 0x68 #define O2_SD_DEV_CTRL 0x88 @@ -36,6 +37,7 @@ #define O2_SD_INF_MOD 0xF1 #define O2_SD_MISC_CTRL4 0xFC #define O2_SD_MISC_CTRL 0x1C0 +#define O2_SD_EXP_INT_REG 0x1E0 #define O2_SD_PWR_FORCE_L0 0x0002 #define O2_SD_TUNING_CTRL 0x300 #define O2_SD_PLL_SETTING 0x304 @@ -49,6 +51,9 @@ #define O2_SD_UHS2_L1_CTRL 0x35C #define O2_SD_FUNC_REG3 0x3E0 #define O2_SD_FUNC_REG4 0x3E4 +#define O2_SD_PARA_SET_REG1 0x444 +#define O2_SD_VDDX_CTRL_REG 0x508 +#define O2_SD_GPIO_CTRL_REG1 0x510 #define O2_SD_LED_ENABLE BIT(6) #define O2_SD_FREG0_LEDOFF BIT(13) #define O2_SD_SEL_DLL BIT(16) @@ -334,33 +339,45 @@ static int sdhci_o2_execute_tuning(struct mmc_host *mmc, u32 opcode) scratch |= O2_SD_PWR_FORCE_L0; sdhci_writew(host, scratch, O2_SD_MISC_CTRL); - /* Stop clk */ - reg_val = sdhci_readw(host, SDHCI_CLOCK_CONTROL); - reg_val &= ~SDHCI_CLOCK_CARD_EN; - sdhci_writew(host, reg_val, SDHCI_CLOCK_CONTROL); - - if ((host->timing == MMC_TIMING_MMC_HS200) || - (host->timing == MMC_TIMING_UHS_SDR104)) { - /* UnLock WP */ - pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8); - scratch_8 &= 0x7f; - pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); - - /* Set pcr 0x354[16] to choose dll clock, and set the default phase */ - pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, ®_val); - reg_val &= ~(O2_SD_SEL_DLL | O2_SD_PHASE_MASK); - reg_val |= (O2_SD_SEL_DLL | O2_SD_FIX_PHASE); - pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, reg_val); + /* Update output phase */ + switch (chip->pdev->device) { + case PCI_DEVICE_ID_O2_SDS0: + case PCI_DEVICE_ID_O2_SEABIRD0: + case PCI_DEVICE_ID_O2_SEABIRD1: + case PCI_DEVICE_ID_O2_SDS1: + case PCI_DEVICE_ID_O2_FUJIN2: + /* Stop clk */ + reg_val = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + reg_val &= ~SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, reg_val, SDHCI_CLOCK_CONTROL); + + if (host->timing == MMC_TIMING_MMC_HS200 || + host->timing == MMC_TIMING_UHS_SDR104) { + /* UnLock WP */ + pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8); + scratch_8 &= 0x7f; + pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); + + /* Set pcr 0x354[16] to choose dll clock, and set the default phase */ + pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, ®_val); + reg_val &= ~(O2_SD_SEL_DLL | O2_SD_PHASE_MASK); + reg_val |= (O2_SD_SEL_DLL | O2_SD_FIX_PHASE); + pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, reg_val); + + /* Lock WP */ + pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8); + scratch_8 |= 0x80; + pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); + } - /* Lock WP */ - pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch_8); - scratch_8 |= 0x80; - pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch_8); + /* Start clk */ + reg_val = sdhci_readw(host, SDHCI_CLOCK_CONTROL); + reg_val |= SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, reg_val, SDHCI_CLOCK_CONTROL); + break; + default: + break; } - /* Start clk */ - reg_val = sdhci_readw(host, SDHCI_CLOCK_CONTROL); - reg_val |= SDHCI_CLOCK_CARD_EN; - sdhci_writew(host, reg_val, SDHCI_CLOCK_CONTROL); /* wait DLL lock, timeout value 5ms */ if (readx_poll_timeout(sdhci_o2_pll_dll_wdt_control, host, @@ -563,6 +580,7 @@ static void sdhci_pci_o2_set_clock(struct sdhci_host *host, unsigned int clock) u16 clk; u8 scratch; u32 scratch_32; + u32 dmdn_208m, dmdn_200m; struct sdhci_pci_slot *slot = sdhci_priv(host); struct sdhci_pci_chip *chip = slot->chip; @@ -578,16 +596,27 @@ static void sdhci_pci_o2_set_clock(struct sdhci_host *host, unsigned int clock) scratch &= 0x7f; pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); + if (chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9860 || + chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9861 || + chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9862 || + chip->pdev->device == PCI_DEVICE_ID_O2_GG8_9863) { + dmdn_208m = 0x2c500000; + dmdn_200m = 0x25200000; + } else { + dmdn_208m = 0x2c280000; + dmdn_200m = 0x25100000; + } + if ((host->timing == MMC_TIMING_UHS_SDR104) && (clock == 200000000)) { pci_read_config_dword(chip->pdev, O2_SD_PLL_SETTING, &scratch_32); - if ((scratch_32 & 0xFFFF0000) != 0x2c280000) - o2_pci_set_baseclk(chip, 0x2c280000); + if ((scratch_32 & 0xFFFF0000) != dmdn_208m) + o2_pci_set_baseclk(chip, dmdn_208m); } else { pci_read_config_dword(chip->pdev, O2_SD_PLL_SETTING, &scratch_32); - if ((scratch_32 & 0xFFFF0000) != 0x25100000) - o2_pci_set_baseclk(chip, 0x25100000); + if ((scratch_32 & 0xFFFF0000) != dmdn_200m) + o2_pci_set_baseclk(chip, dmdn_200m); } pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, &scratch_32); @@ -603,6 +632,67 @@ static void sdhci_pci_o2_set_clock(struct sdhci_host *host, unsigned int clock) sdhci_o2_enable_clk(host, clk); } +static int sdhci_pci_o2_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct sdhci_host *host = mmc_priv(mmc); + struct sdhci_pci_slot *slot = sdhci_priv(host); + struct sdhci_pci_chip *chip = slot->chip; + u8 scratch8; + u16 scratch16; + int ret; + + /* Disable clock */ + sdhci_writeb(host, 0, SDHCI_CLOCK_CONTROL); + + /* Set VDD2 voltage*/ + scratch8 = sdhci_readb(host, SDHCI_POWER_CONTROL); + scratch8 &= 0x0F; + if (host->mmc->ios.timing == MMC_TIMING_SD_EXP_1_2V && + host->mmc->caps2 & MMC_CAP2_SD_EXP_1_2V) { + scratch8 |= SDHCI_VDD2_POWER_ON | SDHCI_VDD2_POWER_120; + } else { + scratch8 |= SDHCI_VDD2_POWER_ON | SDHCI_VDD2_POWER_180; + } + + sdhci_writeb(host, scratch8, SDHCI_POWER_CONTROL); + + /* UnLock WP */ + pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch8); + scratch8 &= 0x7f; + pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch8); + + /* Wait for express card clkreqn assert */ + ret = read_poll_timeout(sdhci_readb, scratch8, !(scratch8 & BIT(0)), + 1, 30000, false, host, O2_SD_EXP_INT_REG); + + if (!ret) { + /* Switch to PCIe mode */ + scratch16 = sdhci_readw(host, O2_SD_PCIE_SWITCH); + scratch16 |= BIT(8); + sdhci_writew(host, scratch16, O2_SD_PCIE_SWITCH); + } else { + /* Power off VDD2 voltage*/ + scratch8 = sdhci_readb(host, SDHCI_POWER_CONTROL); + scratch8 &= 0x0F; + sdhci_writeb(host, scratch8, SDHCI_POWER_CONTROL); + + /* Keep mode as UHSI */ + pci_read_config_word(chip->pdev, O2_SD_PARA_SET_REG1, &scratch16); + scratch16 &= ~BIT(11); + pci_write_config_word(chip->pdev, O2_SD_PARA_SET_REG1, scratch16); + + host->mmc->ios.timing = MMC_TIMING_LEGACY; + pr_info("%s: Express card initialization failed, falling back to Legacy\n", + mmc_hostname(host->mmc)); + } + /* Lock WP */ + pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch8); + scratch8 |= 0x80; + pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch8); + + return 0; +} + static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) { struct sdhci_pci_chip *chip; @@ -624,6 +714,11 @@ static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) if (caps & SDHCI_CAN_DO_8BIT) host->mmc->caps |= MMC_CAP_8_BIT_DATA; + host->quirks2 |= SDHCI_QUIRK2_BROKEN_DDR50; + + sdhci_pci_o2_enable_msi(chip, host); + + host->mmc_host_ops.execute_tuning = sdhci_o2_execute_tuning; switch (chip->pdev->device) { case PCI_DEVICE_ID_O2_SDS0: case PCI_DEVICE_ID_O2_SEABIRD0: @@ -634,10 +729,6 @@ static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) if (reg & 0x1) host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; - host->quirks2 |= SDHCI_QUIRK2_BROKEN_DDR50; - - sdhci_pci_o2_enable_msi(chip, host); - if (chip->pdev->device == PCI_DEVICE_ID_O2_SEABIRD0) { ret = pci_read_config_dword(chip->pdev, O2_SD_MISC_SETTING, ®); @@ -663,15 +754,22 @@ static int sdhci_pci_o2_probe_slot(struct sdhci_pci_slot *slot) host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; } - host->mmc_host_ops.execute_tuning = sdhci_o2_execute_tuning; - if (chip->pdev->device != PCI_DEVICE_ID_O2_FUJIN2) break; /* set dll watch dog timer */ reg = sdhci_readl(host, O2_SD_VENDOR_SETTING2); reg |= (1 << 12); sdhci_writel(host, reg, O2_SD_VENDOR_SETTING2); - + break; + case PCI_DEVICE_ID_O2_GG8_9860: + case PCI_DEVICE_ID_O2_GG8_9861: + case PCI_DEVICE_ID_O2_GG8_9862: + case PCI_DEVICE_ID_O2_GG8_9863: + host->mmc->caps2 |= MMC_CAP2_NO_SDIO | MMC_CAP2_SD_EXP | MMC_CAP2_SD_EXP_1_2V; + host->mmc->caps |= MMC_CAP_HW_RESET; + host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN; + slot->host->mmc_host_ops.get_cd = sdhci_o2_get_cd; + host->mmc_host_ops.init_sd_express = sdhci_pci_o2_init_sd_express; break; default: break; @@ -684,6 +782,7 @@ static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip) { int ret; u8 scratch; + u16 scratch16; u32 scratch_32; switch (chip->pdev->device) { @@ -893,6 +992,46 @@ static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip) scratch |= 0x80; pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); break; + case PCI_DEVICE_ID_O2_GG8_9860: + case PCI_DEVICE_ID_O2_GG8_9861: + case PCI_DEVICE_ID_O2_GG8_9862: + case PCI_DEVICE_ID_O2_GG8_9863: + /* UnLock WP */ + ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch); + if (ret) + return ret; + scratch &= 0x7f; + pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); + + /* Select mode switch source as software control */ + pci_read_config_word(chip->pdev, O2_SD_PARA_SET_REG1, &scratch16); + scratch16 &= 0xF8FF; + scratch16 |= BIT(9); + pci_write_config_word(chip->pdev, O2_SD_PARA_SET_REG1, scratch16); + + /* set VDD1 supply source */ + pci_read_config_word(chip->pdev, O2_SD_VDDX_CTRL_REG, &scratch16); + scratch16 &= 0xFFE3; + scratch16 |= BIT(3); + pci_write_config_word(chip->pdev, O2_SD_VDDX_CTRL_REG, scratch16); + + /* Set host drive strength*/ + scratch16 = 0x0025; + pci_write_config_word(chip->pdev, O2_SD_PLL_SETTING, scratch16); + + /* Set output delay*/ + pci_read_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, &scratch_32); + scratch_32 &= 0xFF0FFF00; + scratch_32 |= 0x00B0003B; + pci_write_config_dword(chip->pdev, O2_SD_OUTPUT_CLK_SOURCE_SWITCH, scratch_32); + + /* Lock WP */ + ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch); + if (ret) + return ret; + scratch |= 0x80; + pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); + break; } return 0; diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h index 9c8863956381..153704f812ed 100644 --- a/drivers/mmc/host/sdhci-pci.h +++ b/drivers/mmc/host/sdhci-pci.h @@ -11,6 +11,10 @@ #define PCI_DEVICE_ID_O2_FUJIN2 0x8520 #define PCI_DEVICE_ID_O2_SEABIRD0 0x8620 #define PCI_DEVICE_ID_O2_SEABIRD1 0x8621 +#define PCI_DEVICE_ID_O2_GG8_9860 0x9860 +#define PCI_DEVICE_ID_O2_GG8_9861 0x9861 +#define PCI_DEVICE_ID_O2_GG8_9862 0x9862 +#define PCI_DEVICE_ID_O2_GG8_9863 0x9863 #define PCI_DEVICE_ID_INTEL_PCH_SDIO0 0x8809 #define PCI_DEVICE_ID_INTEL_PCH_SDIO1 0x880a diff --git a/drivers/mmc/host/sdhci-pic32.c b/drivers/mmc/host/sdhci-pic32.c index 6696b6bdd88e..7a0351a9c74e 100644 --- a/drivers/mmc/host/sdhci-pic32.c +++ b/drivers/mmc/host/sdhci-pic32.c @@ -210,7 +210,7 @@ err: return ret; } -static int pic32_sdhci_remove(struct platform_device *pdev) +static void pic32_sdhci_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct pic32_sdhci_priv *sdhci_pdata = sdhci_priv(host); @@ -221,8 +221,6 @@ static int pic32_sdhci_remove(struct platform_device *pdev) clk_disable_unprepare(sdhci_pdata->base_clk); clk_disable_unprepare(sdhci_pdata->sys_clk); sdhci_pltfm_free(pdev); - - return 0; } static const struct of_device_id pic32_sdhci_id_table[] = { @@ -238,7 +236,7 @@ static struct platform_driver pic32_sdhci_driver = { .of_match_table = of_match_ptr(pic32_sdhci_id_table), }, .probe = pic32_sdhci_probe, - .remove = pic32_sdhci_remove, + .remove_new = pic32_sdhci_remove, }; module_platform_driver(pic32_sdhci_driver); diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index 673e750a8490..a72e123a585d 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c @@ -166,9 +166,9 @@ void sdhci_pltfm_free(struct platform_device *pdev) } EXPORT_SYMBOL_GPL(sdhci_pltfm_free); -int sdhci_pltfm_register(struct platform_device *pdev, - const struct sdhci_pltfm_data *pdata, - size_t priv_size) +int sdhci_pltfm_init_and_add_host(struct platform_device *pdev, + const struct sdhci_pltfm_data *pdata, + size_t priv_size) { struct sdhci_host *host; int ret = 0; @@ -185,21 +185,17 @@ int sdhci_pltfm_register(struct platform_device *pdev, return ret; } -EXPORT_SYMBOL_GPL(sdhci_pltfm_register); +EXPORT_SYMBOL_GPL(sdhci_pltfm_init_and_add_host); -int sdhci_pltfm_unregister(struct platform_device *pdev) +void sdhci_pltfm_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); - struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); sdhci_remove_host(host, dead); - clk_disable_unprepare(pltfm_host->clk); sdhci_pltfm_free(pdev); - - return 0; } -EXPORT_SYMBOL_GPL(sdhci_pltfm_unregister); +EXPORT_SYMBOL_GPL(sdhci_pltfm_remove); #ifdef CONFIG_PM_SLEEP int sdhci_pltfm_suspend(struct device *dev) diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h index 9bd717ff784b..b81d5b0fd616 100644 --- a/drivers/mmc/host/sdhci-pltfm.h +++ b/drivers/mmc/host/sdhci-pltfm.h @@ -99,10 +99,10 @@ extern struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, size_t priv_size); extern void sdhci_pltfm_free(struct platform_device *pdev); -extern int sdhci_pltfm_register(struct platform_device *pdev, - const struct sdhci_pltfm_data *pdata, - size_t priv_size); -extern int sdhci_pltfm_unregister(struct platform_device *pdev); +extern int sdhci_pltfm_init_and_add_host(struct platform_device *pdev, + const struct sdhci_pltfm_data *pdata, + size_t priv_size); +extern void sdhci_pltfm_remove(struct platform_device *pdev); extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host); diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c index 91aca8f8d6ef..b75cbea88b40 100644 --- a/drivers/mmc/host/sdhci-pxav2.c +++ b/drivers/mmc/host/sdhci-pxav2.c @@ -19,7 +19,6 @@ #include <linux/platform_data/pxa_sdhci.h> #include <linux/slab.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/mmc/sdio.h> #include <linux/mmc/mmc.h> #include <linux/pinctrl/consumer.h> @@ -269,26 +268,21 @@ static int sdhci_pxav2_probe(struct platform_device *pdev) pltfm_host = sdhci_priv(host); pxav2_host = sdhci_pltfm_priv(pltfm_host); - clk = devm_clk_get(dev, "io"); - if (IS_ERR(clk) && PTR_ERR(clk) != -EPROBE_DEFER) - clk = devm_clk_get(dev, NULL); + clk = devm_clk_get_optional_enabled(dev, "io"); + if (!clk) + clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err_probe(dev, ret, "failed to get io clock\n"); goto free; } pltfm_host->clk = clk; - ret = clk_prepare_enable(clk); - if (ret) { - dev_err(dev, "failed to enable io clock\n"); - goto free; - } clk_core = devm_clk_get_optional_enabled(dev, "core"); if (IS_ERR(clk_core)) { ret = PTR_ERR(clk_core); dev_err_probe(dev, ret, "failed to enable core clock\n"); - goto disable_clk; + goto free; } host->quirks = SDHCI_QUIRK_BROKEN_ADMA @@ -340,12 +334,10 @@ static int sdhci_pxav2_probe(struct platform_device *pdev) ret = sdhci_add_host(host); if (ret) - goto disable_clk; + goto free; return 0; -disable_clk: - clk_disable_unprepare(clk); free: sdhci_pltfm_free(pdev); return ret; @@ -359,7 +351,7 @@ static struct platform_driver sdhci_pxav2_driver = { .pm = &sdhci_pltfm_pmops, }, .probe = sdhci_pxav2_probe, - .remove = sdhci_pltfm_unregister, + .remove_new = sdhci_pltfm_remove, }; module_platform_driver(sdhci_pxav2_driver); diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index e39dcc998772..3af43ac05825 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c @@ -470,7 +470,7 @@ err_clk_get: return ret; } -static int sdhci_pxav3_remove(struct platform_device *pdev) +static void sdhci_pxav3_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -486,8 +486,6 @@ static int sdhci_pxav3_remove(struct platform_device *pdev) clk_disable_unprepare(pxa->clk_core); sdhci_pltfm_free(pdev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -570,7 +568,7 @@ static struct platform_driver sdhci_pxav3_driver = { .pm = &sdhci_pxav3_pmops, }, .probe = sdhci_pxav3_probe, - .remove = sdhci_pxav3_remove, + .remove_new = sdhci_pxav3_remove, }; module_platform_driver(sdhci_pxav3_driver); diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 504015e84308..0e8a8ac14e56 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -20,7 +20,6 @@ #include <linux/gpio.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_gpio.h> #include <linux/pm.h> #include <linux/pm_runtime.h> @@ -668,7 +667,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev) return ret; } -static int sdhci_s3c_remove(struct platform_device *pdev) +static void sdhci_s3c_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_s3c *sc = sdhci_priv(host); @@ -688,8 +687,6 @@ static int sdhci_s3c_remove(struct platform_device *pdev) clk_disable_unprepare(sc->clk_io); sdhci_free_host(host); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -776,7 +773,7 @@ MODULE_DEVICE_TABLE(of, sdhci_s3c_dt_match); static struct platform_driver sdhci_s3c_driver = { .probe = sdhci_s3c_probe, - .remove = sdhci_s3c_remove, + .remove_new = sdhci_s3c_remove, .id_table = sdhci_s3c_driver_ids, .driver = { .name = "s3c-sdhci", diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c index c79035727b20..c81bdfa97b89 100644 --- a/drivers/mmc/host/sdhci-spear.c +++ b/drivers/mmc/host/sdhci-spear.c @@ -117,7 +117,7 @@ err: return ret; } -static int sdhci_remove(struct platform_device *pdev) +static void sdhci_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct spear_sdhci *sdhci = sdhci_priv(host); @@ -131,8 +131,6 @@ static int sdhci_remove(struct platform_device *pdev) sdhci_remove_host(host, dead); clk_disable_unprepare(sdhci->clk); sdhci_free_host(host); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -170,23 +168,21 @@ static int sdhci_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(sdhci_pm_ops, sdhci_suspend, sdhci_resume); -#ifdef CONFIG_OF static const struct of_device_id sdhci_spear_id_table[] = { { .compatible = "st,spear300-sdhci" }, {} }; MODULE_DEVICE_TABLE(of, sdhci_spear_id_table); -#endif static struct platform_driver sdhci_driver = { .driver = { .name = "sdhci", .probe_type = PROBE_PREFER_ASYNCHRONOUS, .pm = &sdhci_pm_ops, - .of_match_table = of_match_ptr(sdhci_spear_id_table), + .of_match_table = sdhci_spear_id_table, }, .probe = sdhci_probe, - .remove = sdhci_remove, + .remove_new = sdhci_remove, }; module_platform_driver(sdhci_driver); diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index 7f4ee2e12735..649ae075e229 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -9,9 +9,10 @@ #include <linux/dma-mapping.h> #include <linux/highmem.h> #include <linux/iopoll.h> +#include <linux/mmc/host.h> +#include <linux/mmc/mmc.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_gpio.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> @@ -73,6 +74,11 @@ #define SDHCI_SPRD_CLK_DEF_RATE 26000000 #define SDHCI_SPRD_PHY_DLL_CLK 52000000 +#define SDHCI_SPRD_MAX_RANGE 0xff +#define SDHCI_SPRD_CMD_DLY_MASK GENMASK(15, 8) +#define SDHCI_SPRD_POSRD_DLY_MASK GENMASK(23, 16) +#define SDHCI_SPRD_CPST_EN GENMASK(27, 24) + struct sdhci_sprd_host { u32 version; struct clk *clk_sdio; @@ -86,6 +92,11 @@ struct sdhci_sprd_host { u32 phy_delay[MMC_TIMING_MMC_HS400 + 2]; }; +enum sdhci_sprd_tuning_type { + SDHCI_SPRD_TUNING_SD_HS_CMD, + SDHCI_SPRD_TUNING_SD_HS_DATA, +}; + struct sdhci_sprd_phy_cfg { const char *property; u8 timing; @@ -533,6 +544,138 @@ static void sdhci_sprd_hs400_enhanced_strobe(struct mmc_host *mmc, SDHCI_SPRD_REG_32_DLL_DLY); } +static int mmc_send_tuning_cmd(struct mmc_card *card) +{ + return mmc_send_status(card, NULL); +} + +static int mmc_send_tuning_data(struct mmc_card *card) +{ + u8 *status; + int ret; + + status = kmalloc(64, GFP_KERNEL); + if (!status) + return -ENOMEM; + + ret = mmc_sd_switch(card, 0, 0, 0, status); + + kfree(status); + + return ret; +} + +static int sdhci_sprd_get_best_clk_sample(struct mmc_host *mmc, u8 *value) +{ + int range_end = SDHCI_SPRD_MAX_RANGE; + int range_length = 0; + int middle_range = 0; + int count = 0; + int i; + + for (i = 0; i <= SDHCI_SPRD_MAX_RANGE; i++) { + if (value[i]) { + pr_debug("%s: tuning ok: %d\n", mmc_hostname(mmc), i); + count++; + } else { + pr_debug("%s: tuning fail: %d\n", mmc_hostname(mmc), i); + if (range_length < count) { + range_length = count; + range_end = i - 1; + count = 0; + } + } + } + + if (!count) + return -EIO; + + if (count > range_length) { + range_length = count; + range_end = i - 1; + } + + middle_range = range_end - (range_length - 1) / 2; + + return middle_range; +} + +static int sdhci_sprd_tuning(struct mmc_host *mmc, struct mmc_card *card, + enum sdhci_sprd_tuning_type type) +{ + struct sdhci_host *host = mmc_priv(mmc); + struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host); + u32 *p = sprd_host->phy_delay; + u32 dll_cfg, dll_dly; + int best_clk_sample; + int err = 0; + u8 *value; + int i; + + value = kmalloc(SDHCI_SPRD_MAX_RANGE + 1, GFP_KERNEL); + if (!value) + return -ENOMEM; + + sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + + dll_cfg = sdhci_readl(host, SDHCI_SPRD_REG_32_DLL_CFG); + dll_cfg &= ~SDHCI_SPRD_CPST_EN; + sdhci_writel(host, dll_cfg, SDHCI_SPRD_REG_32_DLL_CFG); + + dll_dly = p[mmc->ios.timing]; + + for (i = 0; i <= SDHCI_SPRD_MAX_RANGE; i++) { + if (type == SDHCI_SPRD_TUNING_SD_HS_CMD) { + dll_dly &= ~SDHCI_SPRD_CMD_DLY_MASK; + dll_dly |= ((i << 8) & SDHCI_SPRD_CMD_DLY_MASK); + } else { + dll_dly &= ~SDHCI_SPRD_POSRD_DLY_MASK; + dll_dly |= ((i << 16) & SDHCI_SPRD_POSRD_DLY_MASK); + } + + sdhci_writel(host, dll_dly, SDHCI_SPRD_REG_32_DLL_DLY); + + if (type == SDHCI_SPRD_TUNING_SD_HS_CMD) + value[i] = !mmc_send_tuning_cmd(card); + else + value[i] = !mmc_send_tuning_data(card); + } + + best_clk_sample = sdhci_sprd_get_best_clk_sample(mmc, value); + if (best_clk_sample < 0) { + dev_err(mmc_dev(host->mmc), "all tuning phase fail!\n"); + goto out; + } + + if (type == SDHCI_SPRD_TUNING_SD_HS_CMD) { + p[mmc->ios.timing] &= ~SDHCI_SPRD_CMD_DLY_MASK; + p[mmc->ios.timing] |= ((best_clk_sample << 8) & SDHCI_SPRD_CMD_DLY_MASK); + } else { + p[mmc->ios.timing] &= ~(SDHCI_SPRD_POSRD_DLY_MASK); + p[mmc->ios.timing] |= ((best_clk_sample << 16) & SDHCI_SPRD_POSRD_DLY_MASK); + } + + pr_debug("%s: the best clk sample %d, delay value 0x%08x\n", + mmc_hostname(host->mmc), best_clk_sample, p[mmc->ios.timing]); + +out: + sdhci_writel(host, p[mmc->ios.timing], SDHCI_SPRD_REG_32_DLL_DLY); + + kfree(value); + + return err; +} + +static int sdhci_sprd_prepare_sd_hs_cmd_tuning(struct mmc_host *mmc, struct mmc_card *card) +{ + return sdhci_sprd_tuning(mmc, card, SDHCI_SPRD_TUNING_SD_HS_CMD); +} + +static int sdhci_sprd_execute_sd_hs_data_tuning(struct mmc_host *mmc, struct mmc_card *card) +{ + return sdhci_sprd_tuning(mmc, card, SDHCI_SPRD_TUNING_SD_HS_DATA); +} + static void sdhci_sprd_phy_param_parse(struct sdhci_sprd_host *sprd_host, struct device_node *np) { @@ -577,6 +720,11 @@ static int sdhci_sprd_probe(struct platform_device *pdev) host->mmc_host_ops.request = sdhci_sprd_request; host->mmc_host_ops.hs400_enhanced_strobe = sdhci_sprd_hs400_enhanced_strobe; + host->mmc_host_ops.prepare_sd_hs_tuning = + sdhci_sprd_prepare_sd_hs_cmd_tuning; + host->mmc_host_ops.execute_sd_hs_tuning = + sdhci_sprd_execute_sd_hs_data_tuning; + /* * We can not use the standard ops to change and detect the voltage * signal for Spreadtrum SD host controller, since our voltage regulator @@ -720,7 +868,7 @@ pltfm_free: return ret; } -static int sdhci_sprd_remove(struct platform_device *pdev) +static void sdhci_sprd_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_sprd_host *sprd_host = TO_SPRD_HOST(host); @@ -732,8 +880,6 @@ static int sdhci_sprd_remove(struct platform_device *pdev) clk_disable_unprepare(sprd_host->clk_2x_enable); sdhci_pltfm_free(pdev); - - return 0; } static const struct of_device_id sdhci_sprd_of_match[] = { @@ -800,7 +946,7 @@ static const struct dev_pm_ops sdhci_sprd_pm_ops = { static struct platform_driver sdhci_sprd_driver = { .probe = sdhci_sprd_probe, - .remove = sdhci_sprd_remove, + .remove_new = sdhci_sprd_remove, .driver = { .name = "sdhci_sprd_r11", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index 6415916fbd91..d12532b96b51 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c @@ -348,7 +348,6 @@ static int sdhci_st_probe(struct platform_device *pdev) struct clk *clk, *icnclk; int ret = 0; u16 host_version; - struct resource *res; struct reset_control *rstc; clk = devm_clk_get(&pdev->dev, "mmc"); @@ -397,9 +396,7 @@ static int sdhci_st_probe(struct platform_device *pdev) } /* Configure the FlashSS Top registers for setting eMMC TX/RX delay */ - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "top-mmc-delay"); - pdata->top_ioaddr = devm_ioremap_resource(&pdev->dev, res); + pdata->top_ioaddr = devm_platform_ioremap_resource_byname(pdev, "top-mmc-delay"); if (IS_ERR(pdata->top_ioaddr)) pdata->top_ioaddr = NULL; @@ -434,20 +431,20 @@ err_pltfm_init: return ret; } -static int sdhci_st_remove(struct platform_device *pdev) +static void sdhci_st_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct st_mmc_platform_data *pdata = sdhci_pltfm_priv(pltfm_host); struct reset_control *rstc = pdata->rstc; + struct clk *clk = pltfm_host->clk; - sdhci_pltfm_unregister(pdev); + sdhci_pltfm_remove(pdev); clk_disable_unprepare(pdata->icnclk); + clk_disable_unprepare(clk); reset_control_assert(rstc); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -510,7 +507,7 @@ MODULE_DEVICE_TABLE(of, st_sdhci_match); static struct platform_driver sdhci_st_driver = { .probe = sdhci_st_probe, - .remove = sdhci_st_remove, + .remove_new = sdhci_st_remove, .driver = { .name = "sdhci-st", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index bff084f178c9..1ad0a6b3a2eb 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -19,7 +19,6 @@ #include <linux/mmc/mmc.h> #include <linux/mmc/slot-gpio.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/of.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> @@ -1818,7 +1817,7 @@ err_parse_dt: return rc; } -static int sdhci_tegra_remove(struct platform_device *pdev) +static void sdhci_tegra_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -1834,8 +1833,6 @@ static int sdhci_tegra_remove(struct platform_device *pdev) clk_disable_unprepare(tegra_host->tmclk); sdhci_pltfm_free(pdev); - - return 0; } static int __maybe_unused sdhci_tegra_runtime_suspend(struct device *dev) @@ -1933,7 +1930,7 @@ static struct platform_driver sdhci_tegra_driver = { .pm = &sdhci_tegra_dev_pm_ops, }, .probe = sdhci_tegra_probe, - .remove = sdhci_tegra_remove, + .remove_new = sdhci_tegra_remove, }; module_platform_driver(sdhci_tegra_driver); diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c index 08e838400b52..25ba7aecc3be 100644 --- a/drivers/mmc/host/sdhci-xenon.c +++ b/drivers/mmc/host/sdhci-xenon.c @@ -578,7 +578,7 @@ free_pltfm: return err; } -static int xenon_remove(struct platform_device *pdev) +static void xenon_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -595,8 +595,6 @@ static int xenon_remove(struct platform_device *pdev) clk_disable_unprepare(pltfm_host->clk); sdhci_pltfm_free(pdev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -705,7 +703,7 @@ static struct platform_driver sdhci_xenon_driver = { .pm = &sdhci_xenon_dev_pm_ops, }, .probe = xenon_probe, - .remove = xenon_remove, + .remove_new = xenon_remove, }; module_platform_driver(sdhci_xenon_driver); diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index 7cdf0f54e3a5..c125485ba80e 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -866,22 +866,22 @@ err_pltfm_free: return ret; } -static int sdhci_am654_remove(struct platform_device *pdev) +static void sdhci_am654_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct device *dev = &pdev->dev; int ret; - ret = pm_runtime_resume_and_get(&pdev->dev); + ret = pm_runtime_get_sync(dev); if (ret < 0) - return ret; + dev_err(dev, "pm_runtime_get_sync() Failed\n"); sdhci_remove_host(host, true); clk_disable_unprepare(pltfm_host->clk); - pm_runtime_disable(&pdev->dev); - pm_runtime_put_noidle(&pdev->dev); + pm_runtime_disable(dev); + pm_runtime_put_noidle(dev); sdhci_pltfm_free(pdev); - return 0; } #ifdef CONFIG_PM @@ -993,7 +993,7 @@ static struct platform_driver sdhci_am654_driver = { .of_match_table = sdhci_am654_of_match, }, .probe = sdhci_am654_probe, - .remove = sdhci_am654_remove, + .remove_new = sdhci_am654_remove, }; module_platform_driver(sdhci_am654_driver); diff --git a/drivers/mmc/host/sdhci_f_sdh30.c b/drivers/mmc/host/sdhci_f_sdh30.c index 3215063bcf86..c58e7cb1e2a7 100644 --- a/drivers/mmc/host/sdhci_f_sdh30.c +++ b/drivers/mmc/host/sdhci_f_sdh30.c @@ -206,7 +206,7 @@ err: return ret; } -static int sdhci_f_sdh30_remove(struct platform_device *pdev) +static void sdhci_f_sdh30_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct f_sdhost_priv *priv = sdhci_f_sdhost_priv(host); @@ -214,13 +214,11 @@ static int sdhci_f_sdh30_remove(struct platform_device *pdev) struct reset_control *rst = priv->rst; struct clk *clk = priv->clk; - sdhci_pltfm_unregister(pdev); + sdhci_pltfm_remove(pdev); reset_control_assert(rst); clk_disable_unprepare(clk); clk_disable_unprepare(clk_iface); - - return 0; } #ifdef CONFIG_OF @@ -248,8 +246,8 @@ static struct platform_driver sdhci_f_sdh30_driver = { .acpi_match_table = ACPI_PTR(f_sdh30_acpi_ids), .pm = &sdhci_pltfm_pmops, }, - .probe = sdhci_f_sdh30_probe, - .remove = sdhci_f_sdh30_remove, + .probe = sdhci_f_sdh30_probe, + .remove_new = sdhci_f_sdh30_remove, }; module_platform_driver(sdhci_f_sdh30_driver); diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 5cf53348372a..077d711e964e 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -46,7 +46,6 @@ #include <linux/mmc/slot-gpio.h> #include <linux/mod_devicetable.h> #include <linux/mutex.h> -#include <linux/of_device.h> #include <linux/pagemap.h> #include <linux/platform_data/sh_mmcif.h> #include <linux/platform_device.h> @@ -1509,7 +1508,7 @@ err_host: return ret; } -static int sh_mmcif_remove(struct platform_device *pdev) +static void sh_mmcif_remove(struct platform_device *pdev) { struct sh_mmcif_host *host = platform_get_drvdata(pdev); @@ -1533,8 +1532,6 @@ static int sh_mmcif_remove(struct platform_device *pdev) mmc_free_host(host->mmc); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -1561,7 +1558,7 @@ static const struct dev_pm_ops sh_mmcif_dev_pm_ops = { static struct platform_driver sh_mmcif_driver = { .probe = sh_mmcif_probe, - .remove = sh_mmcif_remove, + .remove_new = sh_mmcif_remove, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/sunplus-mmc.c b/drivers/mmc/host/sunplus-mmc.c index 2bdebeb1f8e4..13c7cc0b6180 100644 --- a/drivers/mmc/host/sunplus-mmc.c +++ b/drivers/mmc/host/sunplus-mmc.c @@ -885,7 +885,7 @@ static int spmmc_drv_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, PTR_ERR(host->rstc), "rst get fail\n"); host->irq = platform_get_irq(pdev, 0); - if (host->irq <= 0) + if (host->irq < 0) return host->irq; ret = devm_request_threaded_irq(&pdev->dev, host->irq, @@ -939,7 +939,7 @@ clk_disable: return ret; } -static int spmmc_drv_remove(struct platform_device *dev) +static void spmmc_drv_remove(struct platform_device *dev) { struct spmmc_host *host = platform_get_drvdata(dev); @@ -948,9 +948,6 @@ static int spmmc_drv_remove(struct platform_device *dev) clk_disable_unprepare(host->clk); pm_runtime_put_noidle(&dev->dev); pm_runtime_disable(&dev->dev); - platform_set_drvdata(dev, NULL); - - return 0; } static int spmmc_pm_runtime_suspend(struct device *dev) @@ -985,7 +982,7 @@ MODULE_DEVICE_TABLE(of, spmmc_of_table); static struct platform_driver spmmc_driver = { .probe = spmmc_drv_probe, - .remove = spmmc_drv_remove, + .remove_new = spmmc_drv_remove, .driver = { .name = "spmmc", .pm = pm_ptr(&spmmc_pm_ops), diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index 69dcb8805e05..d3bd0ac99ec4 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -1486,7 +1486,7 @@ error_free_host: return ret; } -static int sunxi_mmc_remove(struct platform_device *pdev) +static void sunxi_mmc_remove(struct platform_device *pdev) { struct mmc_host *mmc = platform_get_drvdata(pdev); struct sunxi_mmc_host *host = mmc_priv(mmc); @@ -1499,8 +1499,6 @@ static int sunxi_mmc_remove(struct platform_device *pdev) } dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); mmc_free_host(mmc); - - return 0; } #ifdef CONFIG_PM @@ -1556,7 +1554,7 @@ static struct platform_driver sunxi_mmc_driver = { .pm = &sunxi_mmc_pm_ops, }, .probe = sunxi_mmc_probe, - .remove = sunxi_mmc_remove, + .remove_new = sunxi_mmc_remove, }; module_platform_driver(sunxi_mmc_driver); diff --git a/drivers/mmc/host/uniphier-sd.c b/drivers/mmc/host/uniphier-sd.c index 61acd69fac0e..1404989e6151 100644 --- a/drivers/mmc/host/uniphier-sd.c +++ b/drivers/mmc/host/uniphier-sd.c @@ -13,7 +13,6 @@ #include <linux/mmc/host.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> #include <linux/regmap.h> @@ -706,19 +705,19 @@ static int uniphier_sd_probe(struct platform_device *pdev) tmio_data->max_segs = 1; tmio_data->max_blk_count = U16_MAX; - ret = tmio_mmc_host_probe(host); - if (ret) - goto disable_clk; + sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, TMIO_MASK_ALL); ret = devm_request_irq(dev, irq, tmio_mmc_irq, IRQF_SHARED, dev_name(dev), host); if (ret) - goto remove_host; + goto disable_clk; + + ret = tmio_mmc_host_probe(host); + if (ret) + goto disable_clk; return 0; -remove_host: - tmio_mmc_host_remove(host); disable_clk: uniphier_sd_clk_disable(host); free_host: @@ -727,15 +726,13 @@ free_host: return ret; } -static int uniphier_sd_remove(struct platform_device *pdev) +static void uniphier_sd_remove(struct platform_device *pdev) { struct tmio_mmc_host *host = platform_get_drvdata(pdev); tmio_mmc_host_remove(host); uniphier_sd_clk_disable(host); tmio_mmc_host_free(host); - - return 0; } static const struct of_device_id uniphier_sd_match[] = { @@ -757,7 +754,7 @@ MODULE_DEVICE_TABLE(of, uniphier_sd_match); static struct platform_driver uniphier_sd_driver = { .probe = uniphier_sd_probe, - .remove = uniphier_sd_remove, + .remove_new = uniphier_sd_remove, .driver = { .name = "uniphier-sd", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c index 2e17903658fc..6e421445d56c 100644 --- a/drivers/mmc/host/usdhi6rol0.c +++ b/drivers/mmc/host/usdhi6rol0.c @@ -1884,7 +1884,7 @@ e_free_mmc: return ret; } -static int usdhi6_remove(struct platform_device *pdev) +static void usdhi6_remove(struct platform_device *pdev) { struct usdhi6_host *host = platform_get_drvdata(pdev); @@ -1895,13 +1895,11 @@ static int usdhi6_remove(struct platform_device *pdev) usdhi6_dma_release(host); clk_disable_unprepare(host->clk); mmc_free_host(host->mmc); - - return 0; } static struct platform_driver usdhi6_driver = { .probe = usdhi6_probe, - .remove = usdhi6_remove, + .remove_new = usdhi6_remove, .driver = { .name = "usdhi6rol0", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index a2b0d9461665..ba6044b16e07 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c @@ -1160,7 +1160,6 @@ static int via_sd_probe(struct pci_dev *pcidev, unmap: iounmap(sdhost->mmiobase); free_mmc_host: - dev_set_drvdata(&pcidev->dev, NULL); mmc_free_host(mmc); release: pci_release_regions(pcidev); @@ -1212,7 +1211,6 @@ static void via_sd_remove(struct pci_dev *pcidev) writeb(gatt, sdhost->pcictrl_mmiobase + VIA_CRDR_PCICLKGATT); iounmap(sdhost->mmiobase); - dev_set_drvdata(&pcidev->dev, NULL); mmc_free_host(sdhost->mmc); pci_release_regions(pcidev); pci_disable_device(pcidev); diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c index bf2a92fba0ed..001a468bc149 100644 --- a/drivers/mmc/host/wbsd.c +++ b/drivers/mmc/host/wbsd.c @@ -1264,8 +1264,6 @@ static void wbsd_free_mmc(struct device *dev) del_timer_sync(&host->ignore_timer); mmc_free_host(mmc); - - dev_set_drvdata(dev, NULL); } /* @@ -1756,11 +1754,9 @@ static int wbsd_probe(struct platform_device *dev) return wbsd_init(&dev->dev, param_io, param_irq, param_dma, 0); } -static int wbsd_remove(struct platform_device *dev) +static void wbsd_remove(struct platform_device *dev) { wbsd_shutdown(&dev->dev, 0); - - return 0; } /* @@ -1902,8 +1898,7 @@ static struct platform_device *wbsd_device; static struct platform_driver wbsd_driver = { .probe = wbsd_probe, - .remove = wbsd_remove, - + .remove_new = wbsd_remove, .suspend = wbsd_platform_suspend, .resume = wbsd_platform_resume, .driver = { diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c index 68525d900046..77d5f1d24489 100644 --- a/drivers/mmc/host/wmt-sdmmc.c +++ b/drivers/mmc/host/wmt-sdmmc.c @@ -21,7 +21,6 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> -#include <linux/of_device.h> #include <linux/mmc/host.h> #include <linux/mmc/mmc.h> @@ -880,7 +879,7 @@ fail1: return ret; } -static int wmt_mci_remove(struct platform_device *pdev) +static void wmt_mci_remove(struct platform_device *pdev) { struct mmc_host *mmc; struct wmt_mci_priv *priv; @@ -918,8 +917,6 @@ static int wmt_mci_remove(struct platform_device *pdev) mmc_free_host(mmc); dev_info(&pdev->dev, "WMT MCI device removed\n"); - - return 0; } #ifdef CONFIG_PM @@ -989,7 +986,7 @@ static const struct dev_pm_ops wmt_mci_pm = { static struct platform_driver wmt_mci_driver = { .probe = wmt_mci_probe, - .remove = wmt_mci_remove, + .remove_new = wmt_mci_remove, .driver = { .name = DRIVER_NAME, .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 99265667538c..d9e052c49ba1 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -464,7 +464,7 @@ static void arcnet_reply_tasklet(struct tasklet_struct *t) ret = sock_queue_err_skb(sk, ackskb); if (ret) - kfree_skb(ackskb); + dev_kfree_skb_irq(ackskb); local_irq_enable(); }; diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c index f2c79456d745..36f9b932b9e2 100644 --- a/drivers/net/ethernet/amd/pds_core/core.c +++ b/drivers/net/ethernet/amd/pds_core/core.c @@ -464,7 +464,8 @@ void pdsc_teardown(struct pdsc *pdsc, bool removing) { int i; - pdsc_devcmd_reset(pdsc); + if (!pdsc->pdev->is_virtfn) + pdsc_devcmd_reset(pdsc); pdsc_qcq_free(pdsc, &pdsc->notifyqcq); pdsc_qcq_free(pdsc, &pdsc->adminqcq); @@ -524,7 +525,8 @@ static void pdsc_fw_down(struct pdsc *pdsc) } /* Notify clients of fw_down */ - devlink_health_report(pdsc->fw_reporter, "FW down reported", pdsc); + if (pdsc->fw_reporter) + devlink_health_report(pdsc->fw_reporter, "FW down reported", pdsc); pdsc_notify(PDS_EVENT_RESET, &reset_event); pdsc_stop(pdsc); @@ -554,8 +556,9 @@ static void pdsc_fw_up(struct pdsc *pdsc) /* Notify clients of fw_up */ pdsc->fw_recoveries++; - devlink_health_reporter_state_update(pdsc->fw_reporter, - DEVLINK_HEALTH_REPORTER_STATE_HEALTHY); + if (pdsc->fw_reporter) + devlink_health_reporter_state_update(pdsc->fw_reporter, + DEVLINK_HEALTH_REPORTER_STATE_HEALTHY); pdsc_notify(PDS_EVENT_RESET, &reset_event); return; diff --git a/drivers/net/ethernet/amd/pds_core/dev.c b/drivers/net/ethernet/amd/pds_core/dev.c index debe5216fe29..f77cd9f5a2fd 100644 --- a/drivers/net/ethernet/amd/pds_core/dev.c +++ b/drivers/net/ethernet/amd/pds_core/dev.c @@ -121,7 +121,7 @@ static const char *pdsc_devcmd_str(int opcode) } } -static int pdsc_devcmd_wait(struct pdsc *pdsc, int max_seconds) +static int pdsc_devcmd_wait(struct pdsc *pdsc, u8 opcode, int max_seconds) { struct device *dev = pdsc->dev; unsigned long start_time; @@ -131,9 +131,6 @@ static int pdsc_devcmd_wait(struct pdsc *pdsc, int max_seconds) int done = 0; int err = 0; int status; - int opcode; - - opcode = ioread8(&pdsc->cmd_regs->cmd.opcode); start_time = jiffies; max_wait = start_time + (max_seconds * HZ); @@ -180,10 +177,10 @@ int pdsc_devcmd_locked(struct pdsc *pdsc, union pds_core_dev_cmd *cmd, memcpy_toio(&pdsc->cmd_regs->cmd, cmd, sizeof(*cmd)); pdsc_devcmd_dbell(pdsc); - err = pdsc_devcmd_wait(pdsc, max_seconds); + err = pdsc_devcmd_wait(pdsc, cmd->opcode, max_seconds); memcpy_fromio(comp, &pdsc->cmd_regs->comp, sizeof(*comp)); - if (err == -ENXIO || err == -ETIMEDOUT) + if ((err == -ENXIO || err == -ETIMEDOUT) && pdsc->wq) queue_work(pdsc->wq, &pdsc->health_work); return err; diff --git a/drivers/net/ethernet/amd/pds_core/devlink.c b/drivers/net/ethernet/amd/pds_core/devlink.c index 9c6b3653c1c7..d9607033bbf2 100644 --- a/drivers/net/ethernet/amd/pds_core/devlink.c +++ b/drivers/net/ethernet/amd/pds_core/devlink.c @@ -10,6 +10,9 @@ pdsc_viftype *pdsc_dl_find_viftype_by_id(struct pdsc *pdsc, { int vt; + if (!pdsc->viftype_status) + return NULL; + for (vt = 0; vt < PDS_DEV_TYPE_MAX; vt++) { if (pdsc->viftype_status[vt].dl_id == dl_id) return &pdsc->viftype_status[vt]; diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index e388bffda2dd..14b311196b8f 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -17794,10 +17794,7 @@ static int tg3_init_one(struct pci_dev *pdev, tnapi->tx_pending = TG3_DEF_TX_RING_PENDING; tnapi->int_mbox = intmbx; - if (i <= 4) - intmbx += 0x8; - else - intmbx += 0x4; + intmbx += 0x8; tnapi->consmbox = rcvmbx; tnapi->prodmbox = sndmbx; diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c index 5a6ffa738396..f818dd215c05 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c @@ -131,6 +131,8 @@ static void ice_ptp_src_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) case READ_TIME: cmd_val |= GLTSYN_CMD_READ_TIME; break; + case ICE_PTP_NOP: + break; } wr32(hw, GLTSYN_CMD, cmd_val); @@ -1226,18 +1228,18 @@ ice_ptp_read_port_capture(struct ice_hw *hw, u8 port, u64 *tx_ts, u64 *rx_ts) } /** - * ice_ptp_one_port_cmd - Prepare a single PHY port for a timer command + * ice_ptp_write_port_cmd_e822 - Prepare a single PHY port for a timer command * @hw: pointer to HW struct * @port: Port to which cmd has to be sent * @cmd: Command to be sent to the port * * Prepare the requested port for an upcoming timer sync command. * - * Note there is no equivalent of this operation on E810, as that device - * always handles all external PHYs internally. + * Do not use this function directly. If you want to configure exactly one + * port, use ice_ptp_one_port_cmd() instead. */ static int -ice_ptp_one_port_cmd(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd) +ice_ptp_write_port_cmd_e822(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd) { u32 cmd_val, val; u8 tmr_idx; @@ -1261,6 +1263,8 @@ ice_ptp_one_port_cmd(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd) case ADJ_TIME_AT_TIME: cmd_val |= PHY_CMD_ADJ_TIME_AT_TIME; break; + case ICE_PTP_NOP: + break; } /* Tx case */ @@ -1307,6 +1311,39 @@ ice_ptp_one_port_cmd(struct ice_hw *hw, u8 port, enum ice_ptp_tmr_cmd cmd) } /** + * ice_ptp_one_port_cmd - Prepare one port for a timer command + * @hw: pointer to the HW struct + * @configured_port: the port to configure with configured_cmd + * @configured_cmd: timer command to prepare on the configured_port + * + * Prepare the configured_port for the configured_cmd, and prepare all other + * ports for ICE_PTP_NOP. This causes the configured_port to execute the + * desired command while all other ports perform no operation. + */ +static int +ice_ptp_one_port_cmd(struct ice_hw *hw, u8 configured_port, + enum ice_ptp_tmr_cmd configured_cmd) +{ + u8 port; + + for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { + enum ice_ptp_tmr_cmd cmd; + int err; + + if (port == configured_port) + cmd = configured_cmd; + else + cmd = ICE_PTP_NOP; + + err = ice_ptp_write_port_cmd_e822(hw, port, cmd); + if (err) + return err; + } + + return 0; +} + +/** * ice_ptp_port_cmd_e822 - Prepare all ports for a timer command * @hw: pointer to the HW struct * @cmd: timer command to prepare @@ -1322,7 +1359,7 @@ ice_ptp_port_cmd_e822(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) for (port = 0; port < ICE_NUM_EXTERNAL_PORTS; port++) { int err; - err = ice_ptp_one_port_cmd(hw, port, cmd); + err = ice_ptp_write_port_cmd_e822(hw, port, cmd); if (err) return err; } @@ -2252,6 +2289,9 @@ static int ice_sync_phy_timer_e822(struct ice_hw *hw, u8 port) if (err) goto err_unlock; + /* Do not perform any action on the main timer */ + ice_ptp_src_cmd(hw, ICE_PTP_NOP); + /* Issue the sync to activate the time adjustment */ ice_ptp_exec_tmr_cmd(hw); @@ -2372,6 +2412,9 @@ int ice_start_phy_timer_e822(struct ice_hw *hw, u8 port) if (err) return err; + /* Do not perform any action on the main timer */ + ice_ptp_src_cmd(hw, ICE_PTP_NOP); + ice_ptp_exec_tmr_cmd(hw); err = ice_read_phy_reg_e822(hw, port, P_REG_PS, &val); @@ -2847,6 +2890,8 @@ static int ice_ptp_port_cmd_e810(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd) case ADJ_TIME_AT_TIME: cmd_val = GLTSYN_CMD_ADJ_INIT_TIME; break; + case ICE_PTP_NOP: + return 0; } /* Read, modify, write */ diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h index 13547707b8e3..9aa10b0426fd 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h +++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h @@ -9,7 +9,8 @@ enum ice_ptp_tmr_cmd { INIT_INCVAL, ADJ_TIME, ADJ_TIME_AT_TIME, - READ_TIME + READ_TIME, + ICE_PTP_NOP, }; enum ice_ptp_serdes { diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 9f63a10c6f80..1ab787ed254d 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -4814,6 +4814,10 @@ void igb_configure_rx_ring(struct igb_adapter *adapter, static void igb_set_rx_buffer_len(struct igb_adapter *adapter, struct igb_ring *rx_ring) { +#if (PAGE_SIZE < 8192) + struct e1000_hw *hw = &adapter->hw; +#endif + /* set build_skb and buffer size flags */ clear_ring_build_skb_enabled(rx_ring); clear_ring_uses_large_buffer(rx_ring); @@ -4824,10 +4828,9 @@ static void igb_set_rx_buffer_len(struct igb_adapter *adapter, set_ring_build_skb_enabled(rx_ring); #if (PAGE_SIZE < 8192) - if (adapter->max_frame_size <= IGB_MAX_FRAME_BUILD_SKB) - return; - - set_ring_uses_large_buffer(rx_ring); + if (adapter->max_frame_size > IGB_MAX_FRAME_BUILD_SKB || + rd32(E1000_RCTL) & E1000_RCTL_SBP) + set_ring_uses_large_buffer(rx_ring); #endif } diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c index 988383e20bb8..e06f77ad6106 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c @@ -55,6 +55,7 @@ static const char *cgx_lmactype_string[LMAC_MODE_MAX] = { [LMAC_MODE_50G_R] = "50G_R", [LMAC_MODE_100G_R] = "100G_R", [LMAC_MODE_USXGMII] = "USXGMII", + [LMAC_MODE_USGMII] = "USGMII", }; /* CGX PHY management internal APIs */ @@ -231,6 +232,9 @@ int cgx_lmac_addr_set(u8 cgx_id, u8 lmac_id, u8 *mac_addr) int index, id; u64 cfg; + if (!lmac) + return -ENODEV; + /* access mac_ops to know csr_offset */ mac_ops = cgx_dev->mac_ops; @@ -549,15 +553,16 @@ void cgx_lmac_promisc_config(int cgx_id, int lmac_id, bool enable) { struct cgx *cgx = cgx_get_pdata(cgx_id); struct lmac *lmac = lmac_pdata(lmac_id, cgx); - u16 max_dmac = lmac->mac_to_index_bmap.max; struct mac_ops *mac_ops; + u16 max_dmac; int index, i; u64 cfg = 0; int id; - if (!cgx) + if (!cgx || !lmac) return; + max_dmac = lmac->mac_to_index_bmap.max; id = get_sequence_id_of_lmac(cgx, lmac_id); mac_ops = cgx->mac_ops; @@ -730,7 +735,7 @@ int cgx_get_fec_stats(void *cgxd, int lmac_id, struct cgx_fec_stats_rsp *rsp) int corr_reg, uncorr_reg; struct cgx *cgx = cgxd; - if (!cgx || lmac_id >= cgx->lmac_count) + if (!is_lmac_valid(cgx, lmac_id)) return -ENODEV; if (cgx->lmac_idmap[lmac_id]->link_info.fec == OTX2_FEC_NONE) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h index 574114179688..6f7d1dee5830 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h @@ -110,6 +110,7 @@ enum LMAC_TYPE { LMAC_MODE_50G_R = 8, LMAC_MODE_100G_R = 9, LMAC_MODE_USXGMII = 10, + LMAC_MODE_USGMII = 11, LMAC_MODE_MAX, }; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c index b4fcb20c3f4f..af21e2030cff 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c @@ -355,8 +355,8 @@ int rpm_lmac_enadis_pause_frm(void *rpmd, int lmac_id, u8 tx_pause, void rpm_lmac_pause_frm_config(void *rpmd, int lmac_id, bool enable) { + u64 cfg, pfc_class_mask_cfg; rpm_t *rpm = rpmd; - u64 cfg; /* ALL pause frames received are completely ignored */ cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); @@ -380,9 +380,11 @@ void rpm_lmac_pause_frm_config(void *rpmd, int lmac_id, bool enable) rpm_write(rpm, 0, RPMX_CMR_CHAN_MSK_OR, ~0ULL); /* Disable all PFC classes */ - cfg = rpm_read(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL); + pfc_class_mask_cfg = is_dev_rpm2(rpm) ? RPM2_CMRX_PRT_CBFC_CTL : + RPMX_CMRX_PRT_CBFC_CTL; + cfg = rpm_read(rpm, lmac_id, pfc_class_mask_cfg); cfg = FIELD_SET(RPM_PFC_CLASS_MASK, 0, cfg); - rpm_write(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL, cfg); + rpm_write(rpm, lmac_id, pfc_class_mask_cfg, cfg); } int rpm_get_rx_stats(void *rpmd, int lmac_id, int idx, u64 *rx_stat) @@ -605,8 +607,11 @@ int rpm_lmac_pfc_config(void *rpmd, int lmac_id, u8 tx_pause, u8 rx_pause, u16 p if (!is_lmac_valid(rpm, lmac_id)) return -ENODEV; + pfc_class_mask_cfg = is_dev_rpm2(rpm) ? RPM2_CMRX_PRT_CBFC_CTL : + RPMX_CMRX_PRT_CBFC_CTL; + cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); - class_en = rpm_read(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL); + class_en = rpm_read(rpm, lmac_id, pfc_class_mask_cfg); pfc_en |= FIELD_GET(RPM_PFC_CLASS_MASK, class_en); if (rx_pause) { @@ -635,10 +640,6 @@ int rpm_lmac_pfc_config(void *rpmd, int lmac_id, u8 tx_pause, u8 rx_pause, u16 p cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_PFC_MODE; rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); - - pfc_class_mask_cfg = is_dev_rpm2(rpm) ? RPM2_CMRX_PRT_CBFC_CTL : - RPMX_CMRX_PRT_CBFC_CTL; - rpm_write(rpm, lmac_id, pfc_class_mask_cfg, class_en); return 0; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c index b3f766b970ca..f2b1edf1bb43 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c @@ -236,6 +236,11 @@ static void cgx_notify_pfs(struct cgx_link_event *event, struct rvu *rvu) linfo = &event->link_uinfo; pfmap = cgxlmac_to_pfmap(rvu, event->cgx_id, event->lmac_id); + if (!pfmap) { + dev_err(rvu->dev, "CGX port%d:%d not mapped with PF\n", + event->cgx_id, event->lmac_id); + return; + } do { pfid = find_first_bit(&pfmap, @@ -345,7 +350,7 @@ int rvu_cgx_init(struct rvu *rvu) rvu->cgx_cnt_max = cgx_get_cgxcnt_max(); if (!rvu->cgx_cnt_max) { dev_info(rvu->dev, "No CGX devices found!\n"); - return -ENODEV; + return 0; } rvu->cgx_idmap = devm_kzalloc(rvu->dev, rvu->cgx_cnt_max * diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c index dce3cea00032..8511906cb4e2 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c @@ -806,6 +806,7 @@ void otx2_txschq_free_one(struct otx2_nic *pfvf, u16 lvl, u16 schq) mutex_unlock(&pfvf->mbox.lock); } +EXPORT_SYMBOL(otx2_txschq_free_one); void otx2_txschq_stop(struct otx2_nic *pfvf) { @@ -1434,7 +1435,7 @@ int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id, } pp_params.flags = PP_FLAG_PAGE_FRAG | PP_FLAG_DMA_MAP; - pp_params.pool_size = numptrs; + pp_params.pool_size = min(OTX2_PAGE_POOL_SZ, numptrs); pp_params.nid = NUMA_NO_NODE; pp_params.dev = pfvf->dev; pp_params.dma_dir = DMA_FROM_DEVICE; diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c index ccaf97bb1ce0..bfddbff7bcdf 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c @@ -70,7 +70,7 @@ static int otx2_pfc_txschq_alloc_one(struct otx2_nic *pfvf, u8 prio) * link config level. These rest of the scheduler can be * same as hw.txschq_list. */ - for (lvl = 0; lvl < pfvf->hw.txschq_link_cfg_lvl; lvl++) + for (lvl = 0; lvl <= pfvf->hw.txschq_link_cfg_lvl; lvl++) req->schq[lvl] = 1; rc = otx2_sync_mbox_msg(&pfvf->mbox); @@ -83,7 +83,7 @@ static int otx2_pfc_txschq_alloc_one(struct otx2_nic *pfvf, u8 prio) return PTR_ERR(rsp); /* Setup transmit scheduler list */ - for (lvl = 0; lvl < pfvf->hw.txschq_link_cfg_lvl; lvl++) { + for (lvl = 0; lvl <= pfvf->hw.txschq_link_cfg_lvl; lvl++) { if (!rsp->schq[lvl]) return -ENOSPC; @@ -125,19 +125,12 @@ int otx2_pfc_txschq_alloc(struct otx2_nic *pfvf) static int otx2_pfc_txschq_stop_one(struct otx2_nic *pfvf, u8 prio) { - struct nix_txsch_free_req *free_req; + int lvl; - mutex_lock(&pfvf->mbox.lock); /* free PFC TLx nodes */ - free_req = otx2_mbox_alloc_msg_nix_txsch_free(&pfvf->mbox); - if (!free_req) { - mutex_unlock(&pfvf->mbox.lock); - return -ENOMEM; - } - - free_req->flags = TXSCHQ_FREE_ALL; - otx2_sync_mbox_msg(&pfvf->mbox); - mutex_unlock(&pfvf->mbox.lock); + for (lvl = 0; lvl <= pfvf->hw.txschq_link_cfg_lvl; lvl++) + otx2_txschq_free_one(pfvf, lvl, + pfvf->pfc_schq_list[lvl][prio]); pfvf->pfc_alloc_status[prio] = false; return 0; diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h index b5d689eeff80..9e3bfbe5c480 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h @@ -23,6 +23,8 @@ #define OTX2_ETH_HLEN (VLAN_ETH_HLEN + VLAN_HLEN) #define OTX2_MIN_MTU 60 +#define OTX2_PAGE_POOL_SZ 2048 + #define OTX2_MAX_GSO_SEGS 255 #define OTX2_MAX_FRAGS_IN_SQE 9 diff --git a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c index b244c02c5b51..e24afeaea0da 100644 --- a/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c +++ b/drivers/net/ethernet/mediatek/mtk_wed_debugfs.c @@ -84,7 +84,6 @@ dump_wed_regs(struct seq_file *s, struct mtk_wed_device *dev, } } - static int wed_txinfo_show(struct seq_file *s, void *data) { @@ -127,16 +126,23 @@ wed_txinfo_show(struct seq_file *s, void *data) DUMP_WDMA_RING(WDMA_RING_RX(0)), DUMP_WDMA_RING(WDMA_RING_RX(1)), - DUMP_STR("TX FREE"), + DUMP_STR("WED TX FREE"), DUMP_WED(WED_RX_MIB(0)), + DUMP_WED_RING(WED_RING_RX(0)), + DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(0)), + DUMP_WED(WED_RX_MIB(1)), + DUMP_WED_RING(WED_RING_RX(1)), + DUMP_WED(WED_WPDMA_RX_COHERENT_MIB(1)), + + DUMP_STR("WED WPDMA TX FREE"), + DUMP_WED_RING(WED_WPDMA_RING_RX(0)), + DUMP_WED_RING(WED_WPDMA_RING_RX(1)), }; struct mtk_wed_hw *hw = s->private; struct mtk_wed_device *dev = hw->wed_dev; - if (!dev) - return 0; - - dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); + if (dev) + dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); return 0; } @@ -208,10 +214,8 @@ wed_rxinfo_show(struct seq_file *s, void *data) struct mtk_wed_hw *hw = s->private; struct mtk_wed_device *dev = hw->wed_dev; - if (!dev) - return 0; - - dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); + if (dev) + dump_wed_regs(s, dev, regs, ARRAY_SIZE(regs)); return 0; } diff --git a/drivers/net/ethernet/mediatek/mtk_wed_regs.h b/drivers/net/ethernet/mediatek/mtk_wed_regs.h index 0a50bb98c5ea..47ea69feb3b2 100644 --- a/drivers/net/ethernet/mediatek/mtk_wed_regs.h +++ b/drivers/net/ethernet/mediatek/mtk_wed_regs.h @@ -266,6 +266,8 @@ struct mtk_wdma_desc { #define MTK_WED_WPDMA_TX_MIB(_n) (0x5a0 + (_n) * 4) #define MTK_WED_WPDMA_TX_COHERENT_MIB(_n) (0x5d0 + (_n) * 4) +#define MTK_WED_WPDMA_RX_MIB(_n) (0x5e0 + (_n) * 4) +#define MTK_WED_WPDMA_RX_COHERENT_MIB(_n) (0x5f0 + (_n) * 4) #define MTK_WED_WPDMA_RING_TX(_n) (0x600 + (_n) * 0x10) #define MTK_WED_WPDMA_RING_RX(_n) (0x700 + (_n) * 0x10) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index b56b187a9097..7e94caca4888 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -69,7 +69,7 @@ mlx5_core-$(CONFIG_MLX5_TC_SAMPLE) += en/tc/sample.o # mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o eswitch_offloads_termtbl.o \ ecpf.o rdma.o esw/legacy.o \ - esw/devlink_port.o esw/vporttbl.o esw/qos.o + esw/devlink_port.o esw/vporttbl.o esw/qos.o esw/ipsec.o mlx5_core-$(CONFIG_MLX5_ESWITCH) += esw/acl/helper.o \ esw/acl/egress_lgcy.o esw/acl/egress_ofld.o \ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c index 3b88a8bb7082..7d4ceb9b9c16 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c @@ -38,6 +38,7 @@ #include <net/netevent.h> #include "en.h" +#include "eswitch.h" #include "ipsec.h" #include "ipsec_rxtx.h" #include "en_rep.h" @@ -670,6 +671,11 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x, if (err) goto err_xfrm; + if (!mlx5_eswitch_block_ipsec(priv->mdev)) { + err = -EBUSY; + goto err_xfrm; + } + /* check esn */ if (x->props.flags & XFRM_STATE_ESN) mlx5e_ipsec_update_esn_state(sa_entry); @@ -678,7 +684,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x, err = mlx5_ipsec_create_work(sa_entry); if (err) - goto err_xfrm; + goto unblock_ipsec; err = mlx5e_ipsec_create_dwork(sa_entry); if (err) @@ -735,6 +741,8 @@ release_work: if (sa_entry->work) kfree(sa_entry->work->data); kfree(sa_entry->work); +unblock_ipsec: + mlx5_eswitch_unblock_ipsec(priv->mdev); err_xfrm: kfree(sa_entry); NL_SET_ERR_MSG_WEAK_MOD(extack, "Device failed to offload this state"); @@ -764,6 +772,7 @@ static void mlx5e_xfrm_del_state(struct xfrm_state *x) static void mlx5e_xfrm_free_state(struct xfrm_state *x) { struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x); + struct mlx5e_ipsec *ipsec = sa_entry->ipsec; if (x->xso.flags & XFRM_DEV_OFFLOAD_FLAG_ACQ) goto sa_entry_free; @@ -780,6 +789,7 @@ static void mlx5e_xfrm_free_state(struct xfrm_state *x) if (sa_entry->work) kfree(sa_entry->work->data); kfree(sa_entry->work); + mlx5_eswitch_unblock_ipsec(ipsec->mdev); sa_entry_free: kfree(sa_entry); } @@ -1055,6 +1065,11 @@ static int mlx5e_xfrm_add_policy(struct xfrm_policy *x, pol_entry->x = x; pol_entry->ipsec = priv->ipsec; + if (!mlx5_eswitch_block_ipsec(priv->mdev)) { + err = -EBUSY; + goto ipsec_busy; + } + mlx5e_ipsec_build_accel_pol_attrs(pol_entry, &pol_entry->attrs); err = mlx5e_accel_ipsec_fs_add_pol(pol_entry); if (err) @@ -1064,6 +1079,8 @@ static int mlx5e_xfrm_add_policy(struct xfrm_policy *x, return 0; err_fs: + mlx5_eswitch_unblock_ipsec(priv->mdev); +ipsec_busy: kfree(pol_entry); NL_SET_ERR_MSG_MOD(extack, "Device failed to offload this policy"); return err; @@ -1074,6 +1091,7 @@ static void mlx5e_xfrm_del_policy(struct xfrm_policy *x) struct mlx5e_ipsec_pol_entry *pol_entry = to_ipsec_pol_entry(x); mlx5e_accel_ipsec_fs_del_pol(pol_entry); + mlx5_eswitch_unblock_ipsec(pol_entry->ipsec->mdev); } static void mlx5e_xfrm_free_policy(struct xfrm_policy *x) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c index a1cfddd05bc4..7dba4221993f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c @@ -254,6 +254,8 @@ static void rx_destroy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, mlx5_del_flow_rules(rx->sa.rule); mlx5_destroy_flow_group(rx->sa.group); mlx5_destroy_flow_table(rx->ft.sa); + if (rx->allow_tunnel_mode) + mlx5_eswitch_unblock_encap(mdev); if (rx == ipsec->rx_esw) { mlx5_esw_ipsec_rx_status_destroy(ipsec, rx); } else { @@ -357,6 +359,8 @@ static int rx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, goto err_add; /* Create FT */ + if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_TUNNEL) + rx->allow_tunnel_mode = mlx5_eswitch_block_encap(mdev); if (rx->allow_tunnel_mode) flags = MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; ft = ipsec_ft_create(attr.ns, attr.sa_level, attr.prio, 2, flags); @@ -411,6 +415,8 @@ err_pol_ft: err_fs: mlx5_destroy_flow_table(rx->ft.sa); err_fs_ft: + if (rx->allow_tunnel_mode) + mlx5_eswitch_unblock_encap(mdev); mlx5_del_flow_rules(rx->status.rule); mlx5_modify_header_dealloc(mdev, rx->status.modify_hdr); err_add: @@ -428,26 +434,19 @@ static int rx_get(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, if (rx->ft.refcnt) goto skip; - if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_TUNNEL) - rx->allow_tunnel_mode = mlx5_eswitch_block_encap(mdev); - - err = mlx5_eswitch_block_mode_trylock(mdev); + err = mlx5_eswitch_block_mode(mdev); if (err) - goto err_out; + return err; err = rx_create(mdev, ipsec, rx, family); - mlx5_eswitch_block_mode_unlock(mdev, err); - if (err) - goto err_out; + if (err) { + mlx5_eswitch_unblock_mode(mdev); + return err; + } skip: rx->ft.refcnt++; return 0; - -err_out: - if (rx->allow_tunnel_mode) - mlx5_eswitch_unblock_encap(mdev); - return err; } static void rx_put(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_rx *rx, @@ -456,12 +455,8 @@ static void rx_put(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_rx *rx, if (--rx->ft.refcnt) return; - mlx5_eswitch_unblock_mode_lock(ipsec->mdev); rx_destroy(ipsec->mdev, ipsec, rx, family); - mlx5_eswitch_unblock_mode_unlock(ipsec->mdev); - - if (rx->allow_tunnel_mode) - mlx5_eswitch_unblock_encap(ipsec->mdev); + mlx5_eswitch_unblock_mode(ipsec->mdev); } static struct mlx5e_ipsec_rx *rx_ft_get(struct mlx5_core_dev *mdev, @@ -581,6 +576,8 @@ static void tx_destroy(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx, mlx5_destroy_flow_group(tx->sa.group); } mlx5_destroy_flow_table(tx->ft.sa); + if (tx->allow_tunnel_mode) + mlx5_eswitch_unblock_encap(ipsec->mdev); mlx5_del_flow_rules(tx->status.rule); mlx5_destroy_flow_table(tx->ft.status); } @@ -621,6 +618,8 @@ static int tx_create(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx, if (err) goto err_status_rule; + if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_TUNNEL) + tx->allow_tunnel_mode = mlx5_eswitch_block_encap(mdev); if (tx->allow_tunnel_mode) flags = MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; ft = ipsec_ft_create(tx->ns, attr.sa_level, attr.prio, 4, flags); @@ -687,6 +686,8 @@ err_pol_ft: err_sa_miss: mlx5_destroy_flow_table(tx->ft.sa); err_sa_ft: + if (tx->allow_tunnel_mode) + mlx5_eswitch_unblock_encap(mdev); mlx5_del_flow_rules(tx->status.rule); err_status_rule: mlx5_destroy_flow_table(tx->ft.status); @@ -720,32 +721,22 @@ static int tx_get(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, if (tx->ft.refcnt) goto skip; - if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_TUNNEL) - tx->allow_tunnel_mode = mlx5_eswitch_block_encap(mdev); - - err = mlx5_eswitch_block_mode_trylock(mdev); + err = mlx5_eswitch_block_mode(mdev); if (err) - goto err_out; + return err; err = tx_create(ipsec, tx, ipsec->roce); if (err) { - mlx5_eswitch_block_mode_unlock(mdev, err); - goto err_out; + mlx5_eswitch_unblock_mode(mdev); + return err; } if (tx == ipsec->tx_esw) ipsec_esw_tx_ft_policy_set(mdev, tx->ft.pol); - mlx5_eswitch_block_mode_unlock(mdev, err); - skip: tx->ft.refcnt++; return 0; - -err_out: - if (tx->allow_tunnel_mode) - mlx5_eswitch_unblock_encap(mdev); - return err; } static void tx_put(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx) @@ -753,19 +744,13 @@ static void tx_put(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx) if (--tx->ft.refcnt) return; - mlx5_eswitch_unblock_mode_lock(ipsec->mdev); - if (tx == ipsec->tx_esw) { mlx5_esw_ipsec_restore_dest_uplink(ipsec->mdev); ipsec_esw_tx_ft_policy_set(ipsec->mdev, NULL); } tx_destroy(ipsec, tx, ipsec->roce); - - mlx5_eswitch_unblock_mode_unlock(ipsec->mdev); - - if (tx->allow_tunnel_mode) - mlx5_eswitch_unblock_encap(ipsec->mdev); + mlx5_eswitch_unblock_mode(ipsec->mdev); } static struct mlx5_flow_table *tx_ft_get_policy(struct mlx5_core_dev *mdev, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index 3c254a710006..d8e739cbcbce 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -92,6 +92,12 @@ static const struct devlink_port_ops mlx5_esw_pf_vf_dl_port_ops = { .port_fn_roce_set = mlx5_devlink_port_fn_roce_set, .port_fn_migratable_get = mlx5_devlink_port_fn_migratable_get, .port_fn_migratable_set = mlx5_devlink_port_fn_migratable_set, +#ifdef CONFIG_XFRM_OFFLOAD + .port_fn_ipsec_crypto_get = mlx5_devlink_port_fn_ipsec_crypto_get, + .port_fn_ipsec_crypto_set = mlx5_devlink_port_fn_ipsec_crypto_set, + .port_fn_ipsec_packet_get = mlx5_devlink_port_fn_ipsec_packet_get, + .port_fn_ipsec_packet_set = mlx5_devlink_port_fn_ipsec_packet_set, +#endif /* CONFIG_XFRM_OFFLOAD */ }; static void mlx5_esw_offloads_sf_devlink_port_attrs_set(struct mlx5_eswitch *esw, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec.c new file mode 100644 index 000000000000..da10e04777cf --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec.c @@ -0,0 +1,369 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +// Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + +#include <linux/mlx5/device.h> +#include <linux/mlx5/vport.h> +#include "mlx5_core.h" +#include "eswitch.h" + +static int esw_ipsec_vf_query_generic(struct mlx5_core_dev *dev, u16 vport_num, bool *result) +{ + int query_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); + void *hca_cap, *query_cap; + int err; + + if (!MLX5_CAP_GEN(dev, vhca_resource_manager)) + return -EOPNOTSUPP; + + if (!mlx5_esw_ipsec_vf_offload_supported(dev)) { + *result = false; + return 0; + } + + query_cap = kvzalloc(query_sz, GFP_KERNEL); + if (!query_cap) + return -ENOMEM; + + err = mlx5_vport_get_other_func_general_cap(dev, vport_num, query_cap); + if (err) + goto free; + + hca_cap = MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability); + *result = MLX5_GET(cmd_hca_cap, hca_cap, ipsec_offload); +free: + kvfree(query_cap); + return err; +} + +enum esw_vport_ipsec_offload { + MLX5_ESW_VPORT_IPSEC_CRYPTO_OFFLOAD, + MLX5_ESW_VPORT_IPSEC_PACKET_OFFLOAD, +}; + +int mlx5_esw_ipsec_vf_offload_get(struct mlx5_core_dev *dev, struct mlx5_vport *vport) +{ + int query_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); + void *hca_cap, *query_cap; + bool ipsec_enabled; + int err; + + /* Querying IPsec caps only makes sense when generic ipsec_offload + * HCA cap is enabled + */ + err = esw_ipsec_vf_query_generic(dev, vport->vport, &ipsec_enabled); + if (err) + return err; + + if (!ipsec_enabled) { + vport->info.ipsec_crypto_enabled = false; + vport->info.ipsec_packet_enabled = false; + return 0; + } + + query_cap = kvzalloc(query_sz, GFP_KERNEL); + if (!query_cap) + return -ENOMEM; + + err = mlx5_vport_get_other_func_cap(dev, vport->vport, query_cap, MLX5_CAP_IPSEC); + if (err) + goto free; + + hca_cap = MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability); + vport->info.ipsec_crypto_enabled = + MLX5_GET(ipsec_cap, hca_cap, ipsec_crypto_offload); + vport->info.ipsec_packet_enabled = + MLX5_GET(ipsec_cap, hca_cap, ipsec_full_offload); +free: + kvfree(query_cap); + return err; +} + +static int esw_ipsec_vf_set_generic(struct mlx5_core_dev *dev, u16 vport_num, bool ipsec_ofld) +{ + int query_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); + int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in); + void *hca_cap, *query_cap, *cap; + int ret; + + if (!MLX5_CAP_GEN(dev, vhca_resource_manager)) + return -EOPNOTSUPP; + + query_cap = kvzalloc(query_sz, GFP_KERNEL); + hca_cap = kvzalloc(set_sz, GFP_KERNEL); + if (!hca_cap || !query_cap) { + ret = -ENOMEM; + goto free; + } + + ret = mlx5_vport_get_other_func_general_cap(dev, vport_num, query_cap); + if (ret) + goto free; + + cap = MLX5_ADDR_OF(set_hca_cap_in, hca_cap, capability); + memcpy(cap, MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability), + MLX5_UN_SZ_BYTES(hca_cap_union)); + MLX5_SET(cmd_hca_cap, cap, ipsec_offload, ipsec_ofld); + + MLX5_SET(set_hca_cap_in, hca_cap, opcode, MLX5_CMD_OP_SET_HCA_CAP); + MLX5_SET(set_hca_cap_in, hca_cap, other_function, 1); + MLX5_SET(set_hca_cap_in, hca_cap, function_id, vport_num); + + MLX5_SET(set_hca_cap_in, hca_cap, op_mod, + MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE << 1); + ret = mlx5_cmd_exec_in(dev, set_hca_cap, hca_cap); +free: + kvfree(hca_cap); + kvfree(query_cap); + return ret; +} + +static int esw_ipsec_vf_set_bytype(struct mlx5_core_dev *dev, struct mlx5_vport *vport, + bool enable, enum esw_vport_ipsec_offload type) +{ + int query_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); + int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in); + void *hca_cap, *query_cap, *cap; + int ret; + + if (!MLX5_CAP_GEN(dev, vhca_resource_manager)) + return -EOPNOTSUPP; + + query_cap = kvzalloc(query_sz, GFP_KERNEL); + hca_cap = kvzalloc(set_sz, GFP_KERNEL); + if (!hca_cap || !query_cap) { + ret = -ENOMEM; + goto free; + } + + ret = mlx5_vport_get_other_func_cap(dev, vport->vport, query_cap, MLX5_CAP_IPSEC); + if (ret) + goto free; + + cap = MLX5_ADDR_OF(set_hca_cap_in, hca_cap, capability); + memcpy(cap, MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability), + MLX5_UN_SZ_BYTES(hca_cap_union)); + + switch (type) { + case MLX5_ESW_VPORT_IPSEC_CRYPTO_OFFLOAD: + MLX5_SET(ipsec_cap, cap, ipsec_crypto_offload, enable); + break; + case MLX5_ESW_VPORT_IPSEC_PACKET_OFFLOAD: + MLX5_SET(ipsec_cap, cap, ipsec_full_offload, enable); + break; + default: + ret = -EOPNOTSUPP; + goto free; + } + + MLX5_SET(set_hca_cap_in, hca_cap, opcode, MLX5_CMD_OP_SET_HCA_CAP); + MLX5_SET(set_hca_cap_in, hca_cap, other_function, 1); + MLX5_SET(set_hca_cap_in, hca_cap, function_id, vport->vport); + + MLX5_SET(set_hca_cap_in, hca_cap, op_mod, + MLX5_SET_HCA_CAP_OP_MOD_IPSEC << 1); + ret = mlx5_cmd_exec_in(dev, set_hca_cap, hca_cap); +free: + kvfree(hca_cap); + kvfree(query_cap); + return ret; +} + +static int esw_ipsec_vf_crypto_aux_caps_set(struct mlx5_core_dev *dev, u16 vport_num, bool enable) +{ + int query_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); + int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in); + struct mlx5_eswitch *esw = dev->priv.eswitch; + void *hca_cap, *query_cap, *cap; + int ret; + + query_cap = kvzalloc(query_sz, GFP_KERNEL); + hca_cap = kvzalloc(set_sz, GFP_KERNEL); + if (!hca_cap || !query_cap) { + ret = -ENOMEM; + goto free; + } + + ret = mlx5_vport_get_other_func_cap(dev, vport_num, query_cap, MLX5_CAP_ETHERNET_OFFLOADS); + if (ret) + goto free; + + cap = MLX5_ADDR_OF(set_hca_cap_in, hca_cap, capability); + memcpy(cap, MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability), + MLX5_UN_SZ_BYTES(hca_cap_union)); + MLX5_SET(per_protocol_networking_offload_caps, cap, insert_trailer, enable); + MLX5_SET(set_hca_cap_in, hca_cap, opcode, MLX5_CMD_OP_SET_HCA_CAP); + MLX5_SET(set_hca_cap_in, hca_cap, other_function, 1); + MLX5_SET(set_hca_cap_in, hca_cap, function_id, vport_num); + MLX5_SET(set_hca_cap_in, hca_cap, op_mod, + MLX5_SET_HCA_CAP_OP_MOD_ETHERNET_OFFLOADS << 1); + ret = mlx5_cmd_exec_in(esw->dev, set_hca_cap, hca_cap); +free: + kvfree(hca_cap); + kvfree(query_cap); + return ret; +} + +static int esw_ipsec_vf_offload_set_bytype(struct mlx5_eswitch *esw, struct mlx5_vport *vport, + bool enable, enum esw_vport_ipsec_offload type) +{ + struct mlx5_core_dev *dev = esw->dev; + int err; + + if (vport->vport == MLX5_VPORT_PF) + return -EOPNOTSUPP; + + if (type == MLX5_ESW_VPORT_IPSEC_CRYPTO_OFFLOAD) { + err = esw_ipsec_vf_crypto_aux_caps_set(dev, vport->vport, enable); + if (err) + return err; + } + + if (enable) { + err = esw_ipsec_vf_set_generic(dev, vport->vport, enable); + if (err) + return err; + err = esw_ipsec_vf_set_bytype(dev, vport, enable, type); + if (err) + return err; + } else { + err = esw_ipsec_vf_set_bytype(dev, vport, enable, type); + if (err) + return err; + err = mlx5_esw_ipsec_vf_offload_get(dev, vport); + if (err) + return err; + + /* The generic ipsec_offload cap can be disabled only if both + * ipsec_crypto_offload and ipsec_full_offload aren't enabled. + */ + if (!vport->info.ipsec_crypto_enabled && + !vport->info.ipsec_packet_enabled) { + err = esw_ipsec_vf_set_generic(dev, vport->vport, enable); + if (err) + return err; + } + } + + switch (type) { + case MLX5_ESW_VPORT_IPSEC_CRYPTO_OFFLOAD: + vport->info.ipsec_crypto_enabled = enable; + break; + case MLX5_ESW_VPORT_IPSEC_PACKET_OFFLOAD: + vport->info.ipsec_packet_enabled = enable; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int esw_ipsec_offload_supported(struct mlx5_core_dev *dev, u16 vport_num) +{ + int query_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); + void *hca_cap, *query_cap; + int ret; + + query_cap = kvzalloc(query_sz, GFP_KERNEL); + if (!query_cap) + return -ENOMEM; + + ret = mlx5_vport_get_other_func_cap(dev, vport_num, query_cap, MLX5_CAP_GENERAL); + if (ret) + goto free; + + hca_cap = MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability); + if (!MLX5_GET(cmd_hca_cap, hca_cap, log_max_dek)) + ret = -EOPNOTSUPP; +free: + kvfree(query_cap); + return ret; +} + +bool mlx5_esw_ipsec_vf_offload_supported(struct mlx5_core_dev *dev) +{ + /* Old firmware doesn't support ipsec_offload capability for VFs. This + * can be detected by checking reformat_add_esp_trasport capability - + * when this cap isn't supported it means firmware cannot be trusted + * about what it reports for ipsec_offload cap. + */ + return MLX5_CAP_FLOWTABLE_NIC_TX(dev, reformat_add_esp_trasport); +} + +int mlx5_esw_ipsec_vf_crypto_offload_supported(struct mlx5_core_dev *dev, + u16 vport_num) +{ + int query_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); + void *hca_cap, *query_cap; + int err; + + if (!mlx5_esw_ipsec_vf_offload_supported(dev)) + return -EOPNOTSUPP; + + err = esw_ipsec_offload_supported(dev, vport_num); + if (err) + return err; + + query_cap = kvzalloc(query_sz, GFP_KERNEL); + if (!query_cap) + return -ENOMEM; + + err = mlx5_vport_get_other_func_cap(dev, vport_num, query_cap, MLX5_CAP_ETHERNET_OFFLOADS); + if (err) + goto free; + + hca_cap = MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability); + if (!MLX5_GET(per_protocol_networking_offload_caps, hca_cap, swp)) + goto free; + +free: + kvfree(query_cap); + return err; +} + +int mlx5_esw_ipsec_vf_packet_offload_supported(struct mlx5_core_dev *dev, + u16 vport_num) +{ + int query_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out); + void *hca_cap, *query_cap; + int ret; + + if (!mlx5_esw_ipsec_vf_offload_supported(dev)) + return -EOPNOTSUPP; + + ret = esw_ipsec_offload_supported(dev, vport_num); + if (ret) + return ret; + + query_cap = kvzalloc(query_sz, GFP_KERNEL); + if (!query_cap) + return -ENOMEM; + + ret = mlx5_vport_get_other_func_cap(dev, vport_num, query_cap, MLX5_CAP_FLOW_TABLE); + if (ret) + goto out; + + hca_cap = MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability); + if (!MLX5_GET(flow_table_nic_cap, hca_cap, flow_table_properties_nic_receive.decap)) { + ret = -EOPNOTSUPP; + goto out; + } + +out: + kvfree(query_cap); + return ret; +} + +int mlx5_esw_ipsec_vf_crypto_offload_set(struct mlx5_eswitch *esw, struct mlx5_vport *vport, + bool enable) +{ + return esw_ipsec_vf_offload_set_bytype(esw, vport, enable, + MLX5_ESW_VPORT_IPSEC_CRYPTO_OFFLOAD); +} + +int mlx5_esw_ipsec_vf_packet_offload_set(struct mlx5_eswitch *esw, struct mlx5_vport *vport, + bool enable) +{ + return esw_ipsec_vf_offload_set_bytype(esw, vport, enable, + MLX5_ESW_VPORT_IPSEC_PACKET_OFFLOAD); +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index db1c2a076364..6cd7d6497e10 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -48,6 +48,7 @@ #include "devlink.h" #include "ecpf.h" #include "en/mod_hdr.h" +#include "en_accel/ipsec.h" enum { MLX5_ACTION_NONE = 0, @@ -831,6 +832,8 @@ static int mlx5_esw_vport_caps_get(struct mlx5_eswitch *esw, struct mlx5_vport * hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability); vport->info.mig_enabled = MLX5_GET(cmd_hca_cap_2, hca_caps, migratable); + + err = mlx5_esw_ipsec_vf_offload_get(esw->dev, vport); out_free: kfree(query_ctx); return err; @@ -913,6 +916,9 @@ int mlx5_esw_vport_enable(struct mlx5_eswitch *esw, struct mlx5_vport *vport, /* Sync with current vport context */ vport->enabled_events = enabled_events; vport->enabled = true; + if (vport->vport != MLX5_VPORT_PF && + (vport->info.ipsec_crypto_enabled || vport->info.ipsec_packet_enabled)) + esw->enabled_ipsec_vf_count++; /* Esw manager is trusted by default. Host PF (vport 0) is trusted as well * in smartNIC as it's a vport group manager. @@ -969,6 +975,10 @@ void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, struct mlx5_vport *vport) MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) mlx5_esw_vport_vhca_id_clear(esw, vport_num); + if (vport->vport != MLX5_VPORT_PF && + (vport->info.ipsec_crypto_enabled || vport->info.ipsec_packet_enabled)) + esw->enabled_ipsec_vf_count--; + /* We don't assume VFs will cleanup after themselves. * Calling vport change handler while vport is disabled will cleanup * the vport resources. @@ -2336,3 +2346,34 @@ struct mlx5_core_dev *mlx5_eswitch_get_core_dev(struct mlx5_eswitch *esw) return mlx5_esw_allowed(esw) ? esw->dev : NULL; } EXPORT_SYMBOL(mlx5_eswitch_get_core_dev); + +bool mlx5_eswitch_block_ipsec(struct mlx5_core_dev *dev) +{ + struct mlx5_eswitch *esw = dev->priv.eswitch; + + if (!mlx5_esw_allowed(esw)) + return true; + + mutex_lock(&esw->state_lock); + if (esw->enabled_ipsec_vf_count) { + mutex_unlock(&esw->state_lock); + return false; + } + + dev->num_ipsec_offloads++; + mutex_unlock(&esw->state_lock); + return true; +} + +void mlx5_eswitch_unblock_ipsec(struct mlx5_core_dev *dev) +{ + struct mlx5_eswitch *esw = dev->priv.eswitch; + + if (!mlx5_esw_allowed(esw)) + /* Failure means no eswitch => core dev is not a PF */ + return; + + mutex_lock(&esw->state_lock); + dev->num_ipsec_offloads--; + mutex_unlock(&esw->state_lock); +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 6fcece69d3be..37ab66e7b403 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -163,6 +163,8 @@ struct mlx5_vport_info { u8 trusted: 1; u8 roce_enabled: 1; u8 mig_enabled: 1; + u8 ipsec_crypto_enabled: 1; + u8 ipsec_packet_enabled: 1; }; /* Vport context events */ @@ -380,6 +382,7 @@ struct mlx5_eswitch { struct blocking_notifier_head n_head; struct xarray paired; struct mlx5_devcom_comp_dev *devcom; + u16 enabled_ipsec_vf_count; }; void esw_offloads_disable(struct mlx5_eswitch *esw); @@ -558,6 +561,16 @@ int mlx5_devlink_port_fn_migratable_get(struct devlink_port *port, bool *is_enab struct netlink_ext_ack *extack); int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable, struct netlink_ext_ack *extack); +#ifdef CONFIG_XFRM_OFFLOAD +int mlx5_devlink_port_fn_ipsec_crypto_get(struct devlink_port *port, bool *is_enabled, + struct netlink_ext_ack *extack); +int mlx5_devlink_port_fn_ipsec_crypto_set(struct devlink_port *port, bool enable, + struct netlink_ext_ack *extack); +int mlx5_devlink_port_fn_ipsec_packet_get(struct devlink_port *port, bool *is_enabled, + struct netlink_ext_ack *extack); +int mlx5_devlink_port_fn_ipsec_packet_set(struct devlink_port *port, bool enable, + struct netlink_ext_ack *extack); +#endif /* CONFIG_XFRM_OFFLOAD */ void *mlx5_eswitch_get_uplink_priv(struct mlx5_eswitch *esw, u8 rep_type); int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw, @@ -829,10 +842,8 @@ int mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw); bool mlx5_eswitch_block_encap(struct mlx5_core_dev *dev); void mlx5_eswitch_unblock_encap(struct mlx5_core_dev *dev); -int mlx5_eswitch_block_mode_trylock(struct mlx5_core_dev *dev); -void mlx5_eswitch_block_mode_unlock(struct mlx5_core_dev *dev, int err); -void mlx5_eswitch_unblock_mode_lock(struct mlx5_core_dev *dev); -void mlx5_eswitch_unblock_mode_unlock(struct mlx5_core_dev *dev); +int mlx5_eswitch_block_mode(struct mlx5_core_dev *dev); +void mlx5_eswitch_unblock_mode(struct mlx5_core_dev *dev); static inline int mlx5_eswitch_num_vfs(struct mlx5_eswitch *esw) { @@ -857,6 +868,22 @@ mlx5_eswitch_get_slow_fdb(struct mlx5_eswitch *esw) int mlx5_eswitch_restore_ipsec_rule(struct mlx5_eswitch *esw, struct mlx5_flow_handle *rule, struct mlx5_esw_flow_attr *esw_attr, int attr_idx); +bool mlx5_eswitch_block_ipsec(struct mlx5_core_dev *dev); +void mlx5_eswitch_unblock_ipsec(struct mlx5_core_dev *dev); +bool mlx5_esw_ipsec_vf_offload_supported(struct mlx5_core_dev *dev); +int mlx5_esw_ipsec_vf_offload_get(struct mlx5_core_dev *dev, + struct mlx5_vport *vport); +int mlx5_esw_ipsec_vf_crypto_offload_supported(struct mlx5_core_dev *dev, + u16 vport_num); +int mlx5_esw_ipsec_vf_crypto_offload_set(struct mlx5_eswitch *esw, struct mlx5_vport *vport, + bool enable); +int mlx5_esw_ipsec_vf_packet_offload_set(struct mlx5_eswitch *esw, struct mlx5_vport *vport, + bool enable); +int mlx5_esw_ipsec_vf_packet_offload_supported(struct mlx5_core_dev *dev, + u16 vport_num); +void mlx5_esw_vport_ipsec_offload_enable(struct mlx5_eswitch *esw); +void mlx5_esw_vport_ipsec_offload_disable(struct mlx5_eswitch *esw); + #else /* CONFIG_MLX5_ESWITCH */ /* eswitch API stubs */ static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; } @@ -916,13 +943,14 @@ static inline void mlx5_eswitch_unblock_encap(struct mlx5_core_dev *dev) { } -static inline int mlx5_eswitch_block_mode_trylock(struct mlx5_core_dev *dev) { return 0; } - -static inline void mlx5_eswitch_block_mode_unlock(struct mlx5_core_dev *dev, int err) {} - -static inline void mlx5_eswitch_unblock_mode_lock(struct mlx5_core_dev *dev) {} +static inline int mlx5_eswitch_block_mode(struct mlx5_core_dev *dev) { return 0; } +static inline void mlx5_eswitch_unblock_mode(struct mlx5_core_dev *dev) {} +static inline bool mlx5_eswitch_block_ipsec(struct mlx5_core_dev *dev) +{ + return false; +} -static inline void mlx5_eswitch_unblock_mode_unlock(struct mlx5_core_dev *dev) {} +static inline void mlx5_eswitch_unblock_ipsec(struct mlx5_core_dev *dev) {} #endif /* CONFIG_MLX5_ESWITCH */ #endif /* __MLX5_ESWITCH_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 67eab99f95b1..752fb0dfb111 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -3641,65 +3641,32 @@ static bool esw_offloads_devlink_ns_eq_netdev_ns(struct devlink *devlink) return net_eq(devl_net, netdev_net); } -int mlx5_eswitch_block_mode_trylock(struct mlx5_core_dev *dev) +int mlx5_eswitch_block_mode(struct mlx5_core_dev *dev) { - struct devlink *devlink = priv_to_devlink(dev); - struct mlx5_eswitch *esw; + struct mlx5_eswitch *esw = dev->priv.eswitch; int err; - devl_lock(devlink); - esw = mlx5_devlink_eswitch_get(devlink); - if (IS_ERR(esw)) { - /* Failure means no eswitch => not possible to change eswitch mode */ - devl_unlock(devlink); + if (!mlx5_esw_allowed(esw)) return 0; - } + /* Take TC into account */ err = mlx5_esw_try_lock(esw); - if (err < 0) { - devl_unlock(devlink); + if (err < 0) return err; - } - - return 0; -} -void mlx5_eswitch_block_mode_unlock(struct mlx5_core_dev *dev, int err) -{ - struct devlink *devlink = priv_to_devlink(dev); - struct mlx5_eswitch *esw; - - esw = mlx5_devlink_eswitch_get(devlink); - if (IS_ERR(esw)) - return; - - if (!err) - esw->offloads.num_block_mode++; + esw->offloads.num_block_mode++; mlx5_esw_unlock(esw); - devl_unlock(devlink); + return 0; } -void mlx5_eswitch_unblock_mode_lock(struct mlx5_core_dev *dev) +void mlx5_eswitch_unblock_mode(struct mlx5_core_dev *dev) { - struct devlink *devlink = priv_to_devlink(dev); - struct mlx5_eswitch *esw; + struct mlx5_eswitch *esw = dev->priv.eswitch; - esw = mlx5_devlink_eswitch_get(devlink); - if (IS_ERR(esw)) + if (!mlx5_esw_allowed(esw)) return; down_write(&esw->mode_lock); -} - -void mlx5_eswitch_unblock_mode_unlock(struct mlx5_core_dev *dev) -{ - struct devlink *devlink = priv_to_devlink(dev); - struct mlx5_eswitch *esw; - - esw = mlx5_devlink_eswitch_get(devlink); - if (IS_ERR(esw)) - return; - esw->offloads.num_block_mode--; up_write(&esw->mode_lock); } @@ -3903,38 +3870,28 @@ int mlx5_devlink_eswitch_inline_mode_get(struct devlink *devlink, u8 *mode) bool mlx5_eswitch_block_encap(struct mlx5_core_dev *dev) { - struct devlink *devlink = priv_to_devlink(dev); - struct mlx5_eswitch *esw; + struct mlx5_eswitch *esw = dev->priv.eswitch; - devl_lock(devlink); - esw = mlx5_devlink_eswitch_get(devlink); - if (IS_ERR(esw)) { - devl_unlock(devlink); - /* Failure means no eswitch => not possible to change encap */ + if (!mlx5_esw_allowed(esw)) return true; - } down_write(&esw->mode_lock); if (esw->mode != MLX5_ESWITCH_LEGACY && esw->offloads.encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE) { up_write(&esw->mode_lock); - devl_unlock(devlink); return false; } esw->offloads.num_block_encap++; up_write(&esw->mode_lock); - devl_unlock(devlink); return true; } void mlx5_eswitch_unblock_encap(struct mlx5_core_dev *dev) { - struct devlink *devlink = priv_to_devlink(dev); - struct mlx5_eswitch *esw; + struct mlx5_eswitch *esw = dev->priv.eswitch; - esw = mlx5_devlink_eswitch_get(devlink); - if (IS_ERR(esw)) + if (!mlx5_esw_allowed(esw)) return; down_write(&esw->mode_lock); @@ -4410,3 +4367,172 @@ mlx5_eswitch_restore_ipsec_rule(struct mlx5_eswitch *esw, struct mlx5_flow_handl return mlx5_modify_rule_destination(rule, &new_dest, &old_dest); } + +#ifdef CONFIG_XFRM_OFFLOAD +int mlx5_devlink_port_fn_ipsec_crypto_get(struct devlink_port *port, bool *is_enabled, + struct netlink_ext_ack *extack) +{ + struct mlx5_eswitch *esw; + struct mlx5_vport *vport; + int err = 0; + + esw = mlx5_devlink_eswitch_get(port->devlink); + if (IS_ERR(esw)) + return PTR_ERR(esw); + + if (!mlx5_esw_ipsec_vf_offload_supported(esw->dev)) { + NL_SET_ERR_MSG_MOD(extack, "Device doesn't support IPSec crypto"); + return -EOPNOTSUPP; + } + + vport = mlx5_devlink_port_vport_get(port); + + mutex_lock(&esw->state_lock); + if (!vport->enabled) { + err = -EOPNOTSUPP; + goto unlock; + } + + *is_enabled = vport->info.ipsec_crypto_enabled; +unlock: + mutex_unlock(&esw->state_lock); + return err; +} + +int mlx5_devlink_port_fn_ipsec_crypto_set(struct devlink_port *port, bool enable, + struct netlink_ext_ack *extack) +{ + struct mlx5_eswitch *esw; + struct mlx5_vport *vport; + u16 vport_num; + int err; + + esw = mlx5_devlink_eswitch_get(port->devlink); + if (IS_ERR(esw)) + return PTR_ERR(esw); + + vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index); + err = mlx5_esw_ipsec_vf_crypto_offload_supported(esw->dev, vport_num); + if (err) { + NL_SET_ERR_MSG_MOD(extack, + "Device doesn't support IPsec crypto"); + return err; + } + + vport = mlx5_devlink_port_vport_get(port); + + mutex_lock(&esw->state_lock); + if (!vport->enabled) { + err = -EOPNOTSUPP; + NL_SET_ERR_MSG_MOD(extack, "Eswitch vport is disabled"); + goto unlock; + } + + if (vport->info.ipsec_crypto_enabled == enable) + goto unlock; + + if (!esw->enabled_ipsec_vf_count && esw->dev->num_ipsec_offloads) { + err = -EBUSY; + goto unlock; + } + + err = mlx5_esw_ipsec_vf_crypto_offload_set(esw, vport, enable); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Failed to set IPsec crypto"); + goto unlock; + } + + vport->info.ipsec_crypto_enabled = enable; + if (enable) + esw->enabled_ipsec_vf_count++; + else + esw->enabled_ipsec_vf_count--; +unlock: + mutex_unlock(&esw->state_lock); + return err; +} + +int mlx5_devlink_port_fn_ipsec_packet_get(struct devlink_port *port, bool *is_enabled, + struct netlink_ext_ack *extack) +{ + struct mlx5_eswitch *esw; + struct mlx5_vport *vport; + int err = 0; + + esw = mlx5_devlink_eswitch_get(port->devlink); + if (IS_ERR(esw)) + return PTR_ERR(esw); + + if (!mlx5_esw_ipsec_vf_offload_supported(esw->dev)) { + NL_SET_ERR_MSG_MOD(extack, "Device doesn't support IPsec packet"); + return -EOPNOTSUPP; + } + + vport = mlx5_devlink_port_vport_get(port); + + mutex_lock(&esw->state_lock); + if (!vport->enabled) { + err = -EOPNOTSUPP; + goto unlock; + } + + *is_enabled = vport->info.ipsec_packet_enabled; +unlock: + mutex_unlock(&esw->state_lock); + return err; +} + +int mlx5_devlink_port_fn_ipsec_packet_set(struct devlink_port *port, + bool enable, + struct netlink_ext_ack *extack) +{ + struct mlx5_eswitch *esw; + struct mlx5_vport *vport; + u16 vport_num; + int err; + + esw = mlx5_devlink_eswitch_get(port->devlink); + if (IS_ERR(esw)) + return PTR_ERR(esw); + + vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index); + err = mlx5_esw_ipsec_vf_packet_offload_supported(esw->dev, vport_num); + if (err) { + NL_SET_ERR_MSG_MOD(extack, + "Device doesn't support IPsec packet mode"); + return err; + } + + vport = mlx5_devlink_port_vport_get(port); + mutex_lock(&esw->state_lock); + if (!vport->enabled) { + err = -EOPNOTSUPP; + NL_SET_ERR_MSG_MOD(extack, "Eswitch vport is disabled"); + goto unlock; + } + + if (vport->info.ipsec_packet_enabled == enable) + goto unlock; + + if (!esw->enabled_ipsec_vf_count && esw->dev->num_ipsec_offloads) { + err = -EBUSY; + goto unlock; + } + + err = mlx5_esw_ipsec_vf_packet_offload_set(esw, vport, enable); + if (err) { + NL_SET_ERR_MSG_MOD(extack, + "Failed to set IPsec packet mode"); + goto unlock; + } + + vport->info.ipsec_packet_enabled = enable; + if (enable) + esw->enabled_ipsec_vf_count++; + else + esw->enabled_ipsec_vf_count--; +unlock: + mutex_unlock(&esw->state_lock); + return err; +} +#endif /* CONFIG_XFRM_OFFLOAD */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c index 377372f0578a..aa29f09e8356 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c @@ -32,6 +32,7 @@ #include <linux/clocksource.h> #include <linux/highmem.h> +#include <linux/log2.h> #include <linux/ptp_clock_kernel.h> #include <rdma/mlx5-abi.h> #include "lib/eq.h" @@ -39,10 +40,6 @@ #include "clock.h" enum { - MLX5_CYCLES_SHIFT = 31 -}; - -enum { MLX5_PIN_MODE_IN = 0x0, MLX5_PIN_MODE_OUT = 0x1, }; @@ -93,6 +90,31 @@ static bool mlx5_modify_mtutc_allowed(struct mlx5_core_dev *mdev) return MLX5_CAP_MCAM_FEATURE(mdev, ptpcyc2realtime_modify); } +static u32 mlx5_ptp_shift_constant(u32 dev_freq_khz) +{ + /* Optimal shift constant leads to corrections above just 1 scaled ppm. + * + * Two sets of equations are needed to derive the optimal shift + * constant for the cyclecounter. + * + * dev_freq_khz * 1000 / 2^shift_constant = 1 scaled_ppm + * ppb = scaled_ppm * 1000 / 2^16 + * + * Using the two equations together + * + * dev_freq_khz * 1000 / 1 scaled_ppm = 2^shift_constant + * dev_freq_khz * 2^16 / 1 ppb = 2^shift_constant + * dev_freq_khz = 2^(shift_constant - 16) + * + * then yields + * + * shift_constant = ilog2(dev_freq_khz) + 16 + */ + + return min(ilog2(dev_freq_khz) + 16, + ilog2((U32_MAX / NSEC_PER_MSEC) * dev_freq_khz)); +} + static s32 mlx5_ptp_getmaxphase(struct ptp_clock_info *ptp) { struct mlx5_clock *clock = container_of(ptp, struct mlx5_clock, ptp_info); @@ -909,7 +931,7 @@ static void mlx5_timecounter_init(struct mlx5_core_dev *mdev) dev_freq = MLX5_CAP_GEN(mdev, device_frequency_khz); timer->cycles.read = read_internal_timer; - timer->cycles.shift = MLX5_CYCLES_SHIFT; + timer->cycles.shift = mlx5_ptp_shift_constant(dev_freq); timer->cycles.mult = clocksource_khz2mult(dev_freq, timer->cycles.shift); timer->nominal_c_mult = timer->cycles.mult; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c index 70735068cf29..0fd290d776ff 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -405,7 +405,8 @@ mlxsw_hwmon_module_temp_label_show(struct device *dev, container_of(attr, struct mlxsw_hwmon_attr, dev_attr); return sprintf(buf, "front panel %03u\n", - mlxsw_hwmon_attr->type_index); + mlxsw_hwmon_attr->type_index + 1 - + mlxsw_hwmon_attr->mlxsw_hwmon_dev->sensor_count); } static ssize_t diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c index 41298835a11e..d23f293e285c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c +++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c @@ -48,6 +48,7 @@ #define MLXSW_I2C_MBOX_SIZE_BITS 12 #define MLXSW_I2C_ADDR_BUF_SIZE 4 #define MLXSW_I2C_BLK_DEF 32 +#define MLXSW_I2C_BLK_MAX 100 #define MLXSW_I2C_RETRY 5 #define MLXSW_I2C_TIMEOUT_MSECS 5000 #define MLXSW_I2C_MAX_DATA_SIZE 256 @@ -444,7 +445,7 @@ mlxsw_i2c_cmd(struct device *dev, u16 opcode, u32 in_mod, size_t in_mbox_size, } else { /* No input mailbox is case of initialization query command. */ reg_size = MLXSW_I2C_MAX_DATA_SIZE; - num = reg_size / mlxsw_i2c->block_size; + num = DIV_ROUND_UP(reg_size, mlxsw_i2c->block_size); if (mutex_lock_interruptible(&mlxsw_i2c->cmd.lock) < 0) { dev_err(&client->dev, "Could not acquire lock"); @@ -653,7 +654,7 @@ static int mlxsw_i2c_probe(struct i2c_client *client) return -EOPNOTSUPP; } - mlxsw_i2c->block_size = max_t(u16, MLXSW_I2C_BLK_DEF, + mlxsw_i2c->block_size = min_t(u16, MLXSW_I2C_BLK_MAX, min_t(u16, quirks->max_read_len, quirks->max_write_len)); } else { diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 5eb50b265c0b..6351a2dc13bc 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -5239,13 +5239,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* Disable ASPM L1 as that cause random device stop working * problems as well as full system hangs for some PCIe devices users. - * Chips from RTL8168h partially have issues with L1.2, but seem - * to work fine with L1 and L1.1. */ if (rtl_aspm_is_safe(tp)) rc = 0; - else if (tp->mac_version >= RTL_GIGA_MAC_VER_46) - rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_2); else rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1); tp->aspm_manageable = !rc; diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c index 3b8780c76b6e..c3e2b4a21d10 100644 --- a/drivers/net/ethernet/sfc/mae.c +++ b/drivers/net/ethernet/sfc/mae.c @@ -1219,6 +1219,71 @@ fail: return rc; } +/** + * efx_mae_allocate_pedit_mac() - allocate pedit MAC address in HW. + * @efx: NIC we're installing a pedit MAC address on + * @ped: pedit MAC action to be installed + * + * Attempts to install @ped in HW and populates its id with an index of this + * entry in the firmware MAC address table on success. + * + * Return: negative value on error, 0 in success. + */ +int efx_mae_allocate_pedit_mac(struct efx_nic *efx, + struct efx_tc_mac_pedit_action *ped) +{ + MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_LEN); + MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_MAC_ADDR_ALLOC_IN_LEN); + size_t outlen; + int rc; + + BUILD_BUG_ON(MC_CMD_MAE_MAC_ADDR_ALLOC_IN_MAC_ADDR_LEN != + sizeof(ped->h_addr)); + memcpy(MCDI_PTR(inbuf, MAE_MAC_ADDR_ALLOC_IN_MAC_ADDR), ped->h_addr, + sizeof(ped->h_addr)); + rc = efx_mcdi_rpc(efx, MC_CMD_MAE_MAC_ADDR_ALLOC, inbuf, sizeof(inbuf), + outbuf, sizeof(outbuf), &outlen); + if (rc) + return rc; + if (outlen < sizeof(outbuf)) + return -EIO; + ped->fw_id = MCDI_DWORD(outbuf, MAE_MAC_ADDR_ALLOC_OUT_MAC_ID); + return 0; +} + +/** + * efx_mae_free_pedit_mac() - free pedit MAC address in HW. + * @efx: NIC we're installing a pedit MAC address on + * @ped: pedit MAC action that needs to be freed + * + * Frees @ped in HW, check that firmware did not free a different one and clears + * the id (which denotes the index of the entry in the MAC address table). + */ +void efx_mae_free_pedit_mac(struct efx_nic *efx, + struct efx_tc_mac_pedit_action *ped) +{ + MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_MAC_ADDR_FREE_OUT_LEN(1)); + MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_MAC_ADDR_FREE_IN_LEN(1)); + size_t outlen; + int rc; + + MCDI_SET_DWORD(inbuf, MAE_MAC_ADDR_FREE_IN_MAC_ID, ped->fw_id); + rc = efx_mcdi_rpc(efx, MC_CMD_MAE_MAC_ADDR_FREE, inbuf, + sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); + if (rc || outlen < sizeof(outbuf)) + return; + /* FW freed a different ID than we asked for, should also never happen. + * Warn because it means we've now got a different idea to the FW of + * what MAC addresses exist, which could cause mayhem later. + */ + if (WARN_ON(MCDI_DWORD(outbuf, MAE_MAC_ADDR_FREE_OUT_FREED_MAC_ID) != ped->fw_id)) + return; + /* We're probably about to free @ped, but let's just make sure its + * fw_id is blatted so that it won't look valid if it leaks out. + */ + ped->fw_id = MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL; +} + int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act) { MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_SET_ALLOC_OUT_LEN); @@ -1226,15 +1291,27 @@ int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act) size_t outlen; int rc; - MCDI_POPULATE_DWORD_3(inbuf, MAE_ACTION_SET_ALLOC_IN_FLAGS, + MCDI_POPULATE_DWORD_4(inbuf, MAE_ACTION_SET_ALLOC_IN_FLAGS, MAE_ACTION_SET_ALLOC_IN_VLAN_PUSH, act->vlan_push, MAE_ACTION_SET_ALLOC_IN_VLAN_POP, act->vlan_pop, - MAE_ACTION_SET_ALLOC_IN_DECAP, act->decap); + MAE_ACTION_SET_ALLOC_IN_DECAP, act->decap, + MAE_ACTION_SET_ALLOC_IN_DO_DECR_IP_TTL, + act->do_ttl_dec); + + if (act->src_mac) + MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID, + act->src_mac->fw_id); + else + MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID, + MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL); + + if (act->dst_mac) + MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID, + act->dst_mac->fw_id); + else + MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID, + MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL); - MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_SRC_MAC_ID, - MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL); - MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DST_MAC_ID, - MC_CMD_MAE_MAC_ADDR_ALLOC_OUT_MAC_ID_NULL); if (act->count && !WARN_ON(!act->count->cnt)) MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_COUNTER_ID, act->count->cnt->fw_id); diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h index e88e80574f15..8df30bc4f3ba 100644 --- a/drivers/net/ethernet/sfc/mae.h +++ b/drivers/net/ethernet/sfc/mae.h @@ -103,6 +103,10 @@ int efx_mae_update_encap_md(struct efx_nic *efx, int efx_mae_free_encap_md(struct efx_nic *efx, struct efx_tc_encap_action *encap); +int efx_mae_allocate_pedit_mac(struct efx_nic *efx, + struct efx_tc_mac_pedit_action *ped); +void efx_mae_free_pedit_mac(struct efx_nic *efx, + struct efx_tc_mac_pedit_action *ped); int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act); int efx_mae_free_action_set(struct efx_nic *efx, u32 fw_id); diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c index 3eab1802f6b0..f54200f03e15 100644 --- a/drivers/net/ethernet/sfc/ptp.c +++ b/drivers/net/ethernet/sfc/ptp.c @@ -1359,7 +1359,9 @@ static int efx_ptp_insert_multicast_filters(struct efx_nic *efx) goto fail; rc = efx_ptp_insert_eth_multicast_filter(efx); - if (rc < 0) + + /* Not all firmware variants support this filter */ + if (rc < 0 && rc != -EPROTONOSUPPORT) goto fail; } diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index 039180c61c83..047322b04d4f 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -31,6 +31,9 @@ enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev) return EFX_ENCAP_TYPE_NONE; } +#define EFX_TC_HDR_TYPE_TTL_MASK ((u32)0xff) +/* Hoplimit is stored in the most significant byte in the pedit ipv6 header action */ +#define EFX_TC_HDR_TYPE_HLIMIT_MASK ~((u32)0xff000000) #define EFX_EFV_PF NULL /* Look up the representor information (efv) for a device. * May return NULL for the PF (us), or an error pointer for a device that @@ -86,6 +89,12 @@ s64 efx_tc_flower_external_mport(struct efx_nic *efx, struct efx_rep *efv) return mport; } +static const struct rhashtable_params efx_tc_mac_ht_params = { + .key_len = offsetofend(struct efx_tc_mac_pedit_action, h_addr), + .key_offset = 0, + .head_offset = offsetof(struct efx_tc_mac_pedit_action, linkage), +}; + static const struct rhashtable_params efx_tc_encap_match_ht_params = { .key_len = offsetof(struct efx_tc_encap_match, linkage), .key_offset = 0, @@ -110,6 +119,56 @@ static const struct rhashtable_params efx_tc_recirc_ht_params = { .head_offset = offsetof(struct efx_tc_recirc_id, linkage), }; +static struct efx_tc_mac_pedit_action *efx_tc_flower_get_mac(struct efx_nic *efx, + unsigned char h_addr[ETH_ALEN], + struct netlink_ext_ack *extack) +{ + struct efx_tc_mac_pedit_action *ped, *old; + int rc; + + ped = kzalloc(sizeof(*ped), GFP_USER); + if (!ped) + return ERR_PTR(-ENOMEM); + memcpy(ped->h_addr, h_addr, ETH_ALEN); + old = rhashtable_lookup_get_insert_fast(&efx->tc->mac_ht, + &ped->linkage, + efx_tc_mac_ht_params); + if (old) { + /* don't need our new entry */ + kfree(ped); + if (!refcount_inc_not_zero(&old->ref)) + return ERR_PTR(-EAGAIN); + /* existing entry found, ref taken */ + return old; + } + + rc = efx_mae_allocate_pedit_mac(efx, ped); + if (rc < 0) { + NL_SET_ERR_MSG_MOD(extack, "Failed to store pedit MAC address in hw"); + goto out_remove; + } + + /* ref and return */ + refcount_set(&ped->ref, 1); + return ped; +out_remove: + rhashtable_remove_fast(&efx->tc->mac_ht, &ped->linkage, + efx_tc_mac_ht_params); + kfree(ped); + return ERR_PTR(rc); +} + +static void efx_tc_flower_put_mac(struct efx_nic *efx, + struct efx_tc_mac_pedit_action *ped) +{ + if (!refcount_dec_and_test(&ped->ref)) + return; /* still in use */ + rhashtable_remove_fast(&efx->tc->mac_ht, &ped->linkage, + efx_tc_mac_ht_params); + efx_mae_free_pedit_mac(efx, ped); + kfree(ped); +} + static void efx_tc_free_action_set(struct efx_nic *efx, struct efx_tc_action_set *act, bool in_hw) { @@ -135,6 +194,10 @@ static void efx_tc_free_action_set(struct efx_nic *efx, list_del(&act->encap_user); efx_tc_flower_release_encap_md(efx, act->encap_md); } + if (act->src_mac) + efx_tc_flower_put_mac(efx, act->src_mac); + if (act->dst_mac) + efx_tc_flower_put_mac(efx, act->dst_mac); kfree(act); } @@ -697,6 +760,8 @@ static const char *efx_tc_encap_type_name(enum efx_encap_type typ) /* For details of action order constraints refer to SF-123102-TC-1§12.6.1 */ enum efx_tc_action_order { EFX_TC_AO_DECAP, + EFX_TC_AO_DEC_TTL, + EFX_TC_AO_PEDIT_MAC_ADDRS, EFX_TC_AO_VLAN_POP, EFX_TC_AO_VLAN_PUSH, EFX_TC_AO_COUNT, @@ -711,6 +776,15 @@ static bool efx_tc_flower_action_order_ok(const struct efx_tc_action_set *act, case EFX_TC_AO_DECAP: if (act->decap) return false; + /* PEDIT_MAC_ADDRS must not happen before DECAP, though it + * can wait until much later + */ + if (act->dst_mac || act->src_mac) + return false; + + /* Decrementing ttl must not happen before DECAP */ + if (act->do_ttl_dec) + return false; fallthrough; case EFX_TC_AO_VLAN_POP: if (act->vlan_pop >= 2) @@ -730,12 +804,17 @@ static bool efx_tc_flower_action_order_ok(const struct efx_tc_action_set *act, if (act->count) return false; fallthrough; + case EFX_TC_AO_PEDIT_MAC_ADDRS: case EFX_TC_AO_ENCAP: if (act->encap_md) return false; fallthrough; case EFX_TC_AO_DELIVER: return !act->deliver; + case EFX_TC_AO_DEC_TTL: + if (act->encap_md) + return false; + return !act->do_ttl_dec; default: /* Bad caller. Whatever they wanted to do, say they can't. */ WARN_ON_ONCE(1); @@ -900,6 +979,375 @@ static void efx_tc_flower_release_lhs_actions(struct efx_nic *efx, efx_tc_flower_put_counter_index(efx, act->count); } +/** + * struct efx_tc_mangler_state - accumulates 32-bit pedits into fields + * + * @dst_mac_32: dst_mac[0:3] has been populated + * @dst_mac_16: dst_mac[4:5] has been populated + * @src_mac_16: src_mac[0:1] has been populated + * @src_mac_32: src_mac[2:5] has been populated + * @dst_mac: h_dest field of ethhdr + * @src_mac: h_source field of ethhdr + * + * Since FLOW_ACTION_MANGLE comes in 32-bit chunks that do not + * necessarily equate to whole fields of the packet header, this + * structure is used to hold the cumulative effect of the partial + * field pedits that have been processed so far. + */ +struct efx_tc_mangler_state { + u8 dst_mac_32:1; /* eth->h_dest[0:3] */ + u8 dst_mac_16:1; /* eth->h_dest[4:5] */ + u8 src_mac_16:1; /* eth->h_source[0:1] */ + u8 src_mac_32:1; /* eth->h_source[2:5] */ + unsigned char dst_mac[ETH_ALEN]; + unsigned char src_mac[ETH_ALEN]; +}; + +/** efx_tc_complete_mac_mangle() - pull complete field pedits out of @mung + * @efx: NIC we're installing a flow rule on + * @act: action set (cursor) to update + * @mung: accumulated partial mangles + * @extack: netlink extended ack for reporting errors + * + * Check @mung to find any combinations of partial mangles that can be + * combined into a complete packet field edit, add that edit to @act, + * and consume the partial mangles from @mung. + */ + +static int efx_tc_complete_mac_mangle(struct efx_nic *efx, + struct efx_tc_action_set *act, + struct efx_tc_mangler_state *mung, + struct netlink_ext_ack *extack) +{ + struct efx_tc_mac_pedit_action *ped; + + if (mung->dst_mac_32 && mung->dst_mac_16) { + ped = efx_tc_flower_get_mac(efx, mung->dst_mac, extack); + if (IS_ERR(ped)) + return PTR_ERR(ped); + + /* Check that we have not already populated dst_mac */ + if (act->dst_mac) + efx_tc_flower_put_mac(efx, act->dst_mac); + + act->dst_mac = ped; + + /* consume the incomplete state */ + mung->dst_mac_32 = 0; + mung->dst_mac_16 = 0; + } + if (mung->src_mac_16 && mung->src_mac_32) { + ped = efx_tc_flower_get_mac(efx, mung->src_mac, extack); + if (IS_ERR(ped)) + return PTR_ERR(ped); + + /* Check that we have not already populated src_mac */ + if (act->src_mac) + efx_tc_flower_put_mac(efx, act->src_mac); + + act->src_mac = ped; + + /* consume the incomplete state */ + mung->src_mac_32 = 0; + mung->src_mac_16 = 0; + } + return 0; +} + +static int efx_tc_pedit_add(struct efx_nic *efx, struct efx_tc_action_set *act, + const struct flow_action_entry *fa, + struct netlink_ext_ack *extack) +{ + switch (fa->mangle.htype) { + case FLOW_ACT_MANGLE_HDR_TYPE_IP4: + switch (fa->mangle.offset) { + case offsetof(struct iphdr, ttl): + /* check that pedit applies to ttl only */ + if (fa->mangle.mask != ~EFX_TC_HDR_TYPE_TTL_MASK) + break; + + /* Adding 0xff is equivalent to decrementing the ttl. + * Other added values are not supported. + */ + if ((fa->mangle.val & EFX_TC_HDR_TYPE_TTL_MASK) != U8_MAX) + break; + + /* check that we do not decrement ttl twice */ + if (!efx_tc_flower_action_order_ok(act, + EFX_TC_AO_DEC_TTL)) { + NL_SET_ERR_MSG_MOD(extack, "Unsupported: multiple dec ttl"); + return -EOPNOTSUPP; + } + act->do_ttl_dec = 1; + return 0; + default: + break; + } + break; + case FLOW_ACT_MANGLE_HDR_TYPE_IP6: + switch (fa->mangle.offset) { + case round_down(offsetof(struct ipv6hdr, hop_limit), 4): + /* check that pedit applies to hoplimit only */ + if (fa->mangle.mask != EFX_TC_HDR_TYPE_HLIMIT_MASK) + break; + + /* Adding 0xff is equivalent to decrementing the hoplimit. + * Other added values are not supported. + */ + if ((fa->mangle.val >> 24) != U8_MAX) + break; + + /* check that we do not decrement hoplimit twice */ + if (!efx_tc_flower_action_order_ok(act, + EFX_TC_AO_DEC_TTL)) { + NL_SET_ERR_MSG_MOD(extack, "Unsupported: multiple dec ttl"); + return -EOPNOTSUPP; + } + act->do_ttl_dec = 1; + return 0; + default: + break; + } + break; + default: + break; + } + + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: ttl add action type %x %x %x/%x", + fa->mangle.htype, fa->mangle.offset, + fa->mangle.val, fa->mangle.mask); + return -EOPNOTSUPP; +} + +/** + * efx_tc_mangle() - handle a single 32-bit (or less) pedit + * @efx: NIC we're installing a flow rule on + * @act: action set (cursor) to update + * @fa: FLOW_ACTION_MANGLE action metadata + * @mung: accumulator for partial mangles + * @extack: netlink extended ack for reporting errors + * @match: original match used along with the mangle action + * + * Identify the fields written by a FLOW_ACTION_MANGLE, and record + * the partial mangle state in @mung. If this mangle completes an + * earlier partial mangle, consume and apply to @act by calling + * efx_tc_complete_mac_mangle(). + */ + +static int efx_tc_mangle(struct efx_nic *efx, struct efx_tc_action_set *act, + const struct flow_action_entry *fa, + struct efx_tc_mangler_state *mung, + struct netlink_ext_ack *extack, + struct efx_tc_match *match) +{ + __le32 mac32; + __le16 mac16; + u8 tr_ttl; + + switch (fa->mangle.htype) { + case FLOW_ACT_MANGLE_HDR_TYPE_ETH: + BUILD_BUG_ON(offsetof(struct ethhdr, h_dest) != 0); + BUILD_BUG_ON(offsetof(struct ethhdr, h_source) != 6); + if (!efx_tc_flower_action_order_ok(act, EFX_TC_AO_PEDIT_MAC_ADDRS)) { + NL_SET_ERR_MSG_MOD(extack, + "Pedit mangle mac action violates action order"); + return -EOPNOTSUPP; + } + switch (fa->mangle.offset) { + case 0: + if (fa->mangle.mask) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: mask (%#x) of eth.dst32 mangle", + fa->mangle.mask); + return -EOPNOTSUPP; + } + /* Ethernet address is little-endian */ + mac32 = cpu_to_le32(fa->mangle.val); + memcpy(mung->dst_mac, &mac32, sizeof(mac32)); + mung->dst_mac_32 = 1; + return efx_tc_complete_mac_mangle(efx, act, mung, extack); + case 4: + if (fa->mangle.mask == 0xffff) { + mac16 = cpu_to_le16(fa->mangle.val >> 16); + memcpy(mung->src_mac, &mac16, sizeof(mac16)); + mung->src_mac_16 = 1; + } else if (fa->mangle.mask == 0xffff0000) { + mac16 = cpu_to_le16((u16)fa->mangle.val); + memcpy(mung->dst_mac + 4, &mac16, sizeof(mac16)); + mung->dst_mac_16 = 1; + } else { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: mask (%#x) of eth+4 mangle is not high or low 16b", + fa->mangle.mask); + return -EOPNOTSUPP; + } + return efx_tc_complete_mac_mangle(efx, act, mung, extack); + case 8: + if (fa->mangle.mask) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: mask (%#x) of eth.src32 mangle", + fa->mangle.mask); + return -EOPNOTSUPP; + } + mac32 = cpu_to_le32(fa->mangle.val); + memcpy(mung->src_mac + 2, &mac32, sizeof(mac32)); + mung->src_mac_32 = 1; + return efx_tc_complete_mac_mangle(efx, act, mung, extack); + default: + NL_SET_ERR_MSG_FMT_MOD(extack, "Unsupported: mangle eth+%u %x/%x", + fa->mangle.offset, fa->mangle.val, fa->mangle.mask); + return -EOPNOTSUPP; + } + break; + case FLOW_ACT_MANGLE_HDR_TYPE_IP4: + switch (fa->mangle.offset) { + case offsetof(struct iphdr, ttl): + /* we currently only support pedit IP4 when it applies + * to TTL and then only when it can be achieved with a + * decrement ttl action + */ + + /* check that pedit applies to ttl only */ + if (fa->mangle.mask != ~EFX_TC_HDR_TYPE_TTL_MASK) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: mask (%#x) out of range, only support mangle action on ipv4.ttl", + fa->mangle.mask); + return -EOPNOTSUPP; + } + + /* we can only convert to a dec ttl when we have an + * exact match on the ttl field + */ + if (match->mask.ip_ttl != U8_MAX) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: only support mangle ipv4.ttl when we have an exact match on ttl, mask used for match (%#x)", + match->mask.ip_ttl); + return -EOPNOTSUPP; + } + + /* check that we don't try to decrement 0, which equates + * to setting the ttl to 0xff + */ + if (match->value.ip_ttl == 0) { + NL_SET_ERR_MSG_MOD(extack, + "Unsupported: we cannot decrement ttl past 0"); + return -EOPNOTSUPP; + } + + /* check that we do not decrement ttl twice */ + if (!efx_tc_flower_action_order_ok(act, + EFX_TC_AO_DEC_TTL)) { + NL_SET_ERR_MSG_MOD(extack, + "Unsupported: multiple dec ttl"); + return -EOPNOTSUPP; + } + + /* check pedit can be achieved with decrement action */ + tr_ttl = match->value.ip_ttl - 1; + if ((fa->mangle.val & EFX_TC_HDR_TYPE_TTL_MASK) == tr_ttl) { + act->do_ttl_dec = 1; + return 0; + } + + fallthrough; + default: + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: only support mangle on the ttl field (offset is %u)", + fa->mangle.offset); + return -EOPNOTSUPP; + } + break; + case FLOW_ACT_MANGLE_HDR_TYPE_IP6: + switch (fa->mangle.offset) { + case round_down(offsetof(struct ipv6hdr, hop_limit), 4): + /* we currently only support pedit IP6 when it applies + * to the hoplimit and then only when it can be achieved + * with a decrement hoplimit action + */ + + /* check that pedit applies to ttl only */ + if (fa->mangle.mask != EFX_TC_HDR_TYPE_HLIMIT_MASK) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: mask (%#x) out of range, only support mangle action on ipv6.hop_limit", + fa->mangle.mask); + + return -EOPNOTSUPP; + } + + /* we can only convert to a dec ttl when we have an + * exact match on the ttl field + */ + if (match->mask.ip_ttl != U8_MAX) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: only support mangle ipv6.hop_limit when we have an exact match on ttl, mask used for match (%#x)", + match->mask.ip_ttl); + return -EOPNOTSUPP; + } + + /* check that we don't try to decrement 0, which equates + * to setting the ttl to 0xff + */ + if (match->value.ip_ttl == 0) { + NL_SET_ERR_MSG_MOD(extack, + "Unsupported: we cannot decrement hop_limit past 0"); + return -EOPNOTSUPP; + } + + /* check that we do not decrement hoplimit twice */ + if (!efx_tc_flower_action_order_ok(act, + EFX_TC_AO_DEC_TTL)) { + NL_SET_ERR_MSG_MOD(extack, + "Unsupported: multiple dec ttl"); + return -EOPNOTSUPP; + } + + /* check pedit can be achieved with decrement action */ + tr_ttl = match->value.ip_ttl - 1; + if ((fa->mangle.val >> 24) == tr_ttl) { + act->do_ttl_dec = 1; + return 0; + } + + fallthrough; + default: + NL_SET_ERR_MSG_FMT_MOD(extack, + "Unsupported: only support mangle on the hop_limit field"); + return -EOPNOTSUPP; + } + default: + NL_SET_ERR_MSG_FMT_MOD(extack, "Unhandled mangle htype %u for action rule", + fa->mangle.htype); + return -EOPNOTSUPP; + } + return 0; +} + +/** + * efx_tc_incomplete_mangle() - check for leftover partial pedits + * @mung: accumulator for partial mangles + * @extack: netlink extended ack for reporting errors + * + * Since the MAE can only overwrite whole fields, any partial + * field mangle left over on reaching packet delivery (mirred or + * end of TC actions) cannot be offloaded. Check for any such + * and reject them with -%EOPNOTSUPP. + */ + +static int efx_tc_incomplete_mangle(struct efx_tc_mangler_state *mung, + struct netlink_ext_ack *extack) +{ + if (mung->dst_mac_32 || mung->dst_mac_16) { + NL_SET_ERR_MSG_MOD(extack, "Incomplete pedit of destination MAC address"); + return -EOPNOTSUPP; + } + if (mung->src_mac_16 || mung->src_mac_32) { + NL_SET_ERR_MSG_MOD(extack, "Incomplete pedit of source MAC address"); + return -EOPNOTSUPP; + } + return 0; +} + static int efx_tc_flower_replace_foreign(struct efx_nic *efx, struct net_device *net_dev, struct flow_cls_offload *tc) @@ -1295,6 +1743,7 @@ static int efx_tc_flower_replace(struct efx_nic *efx, struct netlink_ext_ack *extack = tc->common.extack; const struct ip_tunnel_info *encap_info = NULL; struct efx_tc_flow_rule *rule = NULL, *old; + struct efx_tc_mangler_state mung = {}; struct efx_tc_action_set *act = NULL; const struct flow_action_entry *fa; struct efx_rep *from_efv, *to_efv; @@ -1631,6 +2080,16 @@ static int efx_tc_flower_replace(struct efx_nic *efx, act->vlan_proto[act->vlan_push] = fa->vlan.proto; act->vlan_push++; break; + case FLOW_ACTION_ADD: + rc = efx_tc_pedit_add(efx, act, fa, extack); + if (rc < 0) + goto release; + break; + case FLOW_ACTION_MANGLE: + rc = efx_tc_mangle(efx, act, fa, &mung, extack, &match); + if (rc < 0) + goto release; + break; case FLOW_ACTION_TUNNEL_ENCAP: if (encap_info) { /* Can't specify encap multiple times. @@ -1670,6 +2129,9 @@ static int efx_tc_flower_replace(struct efx_nic *efx, } } + rc = efx_tc_incomplete_mangle(&mung, extack); + if (rc < 0) + goto release; if (act) { /* Not shot/redirected, so deliver to default dest */ if (from_efv == EFX_EFV_PF) @@ -2156,6 +2618,14 @@ static void efx_tc_lhs_free(void *ptr, void *arg) kfree(rule); } +static void efx_tc_mac_free(void *ptr, void *__unused) +{ + struct efx_tc_mac_pedit_action *ped = ptr; + + WARN_ON(refcount_read(&ped->ref)); + kfree(ped); +} + static void efx_tc_flow_free(void *ptr, void *arg) { struct efx_tc_flow_rule *rule = ptr; @@ -2196,6 +2666,9 @@ int efx_init_struct_tc(struct efx_nic *efx) rc = efx_tc_init_counters(efx); if (rc < 0) goto fail_counters; + rc = rhashtable_init(&efx->tc->mac_ht, &efx_tc_mac_ht_params); + if (rc < 0) + goto fail_mac_ht; rc = rhashtable_init(&efx->tc->encap_match_ht, &efx_tc_encap_match_ht_params); if (rc < 0) goto fail_encap_match_ht; @@ -2233,6 +2706,8 @@ fail_lhs_rule_ht: fail_match_action_ht: rhashtable_destroy(&efx->tc->encap_match_ht); fail_encap_match_ht: + rhashtable_destroy(&efx->tc->mac_ht); +fail_mac_ht: efx_tc_destroy_counters(efx); fail_counters: efx_tc_destroy_encap_actions(efx); @@ -2268,6 +2743,7 @@ void efx_fini_struct_tc(struct efx_nic *efx) rhashtable_free_and_destroy(&efx->tc->recirc_ht, efx_tc_recirc_free, efx); WARN_ON(!ida_is_empty(&efx->tc->recirc_ida)); ida_destroy(&efx->tc->recirc_ida); + rhashtable_free_and_destroy(&efx->tc->mac_ht, efx_tc_mac_free, NULL); efx_tc_fini_counters(efx); efx_tc_fini_encap_actions(efx); mutex_unlock(&efx->tc->mutex); diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h index 40d2c803fca8..4dd2c378fd9f 100644 --- a/drivers/net/ethernet/sfc/tc.h +++ b/drivers/net/ethernet/sfc/tc.h @@ -18,6 +18,23 @@ #define IS_ALL_ONES(v) (!(typeof (v))~(v)) +/** + * struct efx_tc_mac_pedit_action - mac pedit action fields + * + * @h_addr: mac address field of ethernet header + * @linkage: rhashtable reference + * @ref: reference count + * @fw_id: index of this entry in firmware MAC address table + * + * MAC address edits are indirected through a table in the hardware + */ +struct efx_tc_mac_pedit_action { + u8 h_addr[ETH_ALEN]; + struct rhash_head linkage; + refcount_t ref; + u32 fw_id; /* index of this entry in firmware MAC address table */ +}; + static inline bool efx_ipv6_addr_all_ones(struct in6_addr *addr) { return !memchr_inv(addr, 0xff, sizeof(*addr)); @@ -25,20 +42,45 @@ static inline bool efx_ipv6_addr_all_ones(struct in6_addr *addr) struct efx_tc_encap_action; /* see tc_encap_actions.h */ +/** + * struct efx_tc_action_set - collection of tc action fields + * + * @vlan_push: the number of vlan headers to push + * @vlan_pop: the number of vlan headers to pop + * @decap: used to indicate a tunnel header decapsulation should take place + * @do_ttl_dec: used to indicate IP TTL / Hop Limit should be decremented + * @deliver: used to indicate a deliver action should take place + * @vlan_tci: tci fields for vlan push actions + * @vlan_proto: ethernet types for vlan push actions + * @count: counter mapping + * @encap_md: encap entry in tc_encap_ht table + * @encap_user: linked list of encap users (encap_md->users) + * @user: owning action-set-list. Only populated if @encap_md is; used by efx_tc_update_encap() fallback handling + * @count_user: linked list of counter users (counter->users) + * @dest_mport: destination mport + * @src_mac: source mac entry in tc_mac_ht table + * @dst_mac: destination mac entry in tc_mac_ht table + * @fw_id: index of this entry in firmware actions table + * @list: linked list of tc actions + * + */ struct efx_tc_action_set { u16 vlan_push:2; u16 vlan_pop:2; u16 decap:1; + u16 do_ttl_dec:1; u16 deliver:1; - __be16 vlan_tci[2]; /* TCIs for vlan_push */ - __be16 vlan_proto[2]; /* Ethertypes for vlan_push */ + __be16 vlan_tci[2]; + __be16 vlan_proto[2]; struct efx_tc_counter_index *count; - struct efx_tc_encap_action *encap_md; /* entry in tc_encap_ht table */ - struct list_head encap_user; /* entry on encap_md->users list */ - struct efx_tc_action_set_list *user; /* Only populated if encap_md */ - struct list_head count_user; /* entry on counter->users list, if encap */ + struct efx_tc_encap_action *encap_md; + struct list_head encap_user; + struct efx_tc_action_set_list *user; + struct list_head count_user; u32 dest_mport; - u32 fw_id; /* index of this entry in firmware actions table */ + struct efx_tc_mac_pedit_action *src_mac; + struct efx_tc_mac_pedit_action *dst_mac; + u32 fw_id; struct list_head list; }; @@ -220,6 +262,7 @@ struct efx_tc_table_ct { /* TABLE_ID_CONNTRACK_TABLE */ * @counter_ht: Hashtable of TC counters (FW IDs and counter values) * @counter_id_ht: Hashtable mapping TC counter cookies to counters * @encap_ht: Hashtable of TC encap actions + * @mac_ht: Hashtable of MAC address entries (for pedits) * @encap_match_ht: Hashtable of TC encap matches * @match_action_ht: Hashtable of TC match-action rules * @lhs_rule_ht: Hashtable of TC left-hand (act ct & goto chain) rules @@ -257,6 +300,7 @@ struct efx_tc_state { struct rhashtable counter_ht; struct rhashtable counter_id_ht; struct rhashtable encap_ht; + struct rhashtable mac_ht; struct rhashtable encap_match_ht; struct rhashtable match_action_ht; struct rhashtable lhs_rule_ht; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c index 535856fffaea..df34e34cc14f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c @@ -70,7 +70,7 @@ static int imx8mp_set_intf_mode(struct plat_stmmacenet_data *plat_dat) struct imx_priv_data *dwmac = plat_dat->bsp_priv; int val; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_MII: val = GPR_ENET_QOS_INTF_SEL_MII; break; @@ -87,7 +87,7 @@ static int imx8mp_set_intf_mode(struct plat_stmmacenet_data *plat_dat) break; default: pr_debug("imx dwmac doesn't support %d interface\n", - plat_dat->interface); + plat_dat->mac_interface); return -EINVAL; } @@ -110,7 +110,7 @@ static int imx93_set_intf_mode(struct plat_stmmacenet_data *plat_dat) struct imx_priv_data *dwmac = plat_dat->bsp_priv; int val; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_MII: val = MX93_GPR_ENET_QOS_INTF_SEL_MII; break; @@ -125,7 +125,7 @@ static int imx93_set_intf_mode(struct plat_stmmacenet_data *plat_dat) break; default: dev_dbg(dwmac->dev, "imx dwmac doesn't support %d interface\n", - plat_dat->interface); + plat_dat->mac_interface); return -EINVAL; } @@ -192,8 +192,8 @@ static void imx_dwmac_fix_speed(void *priv, unsigned int speed, unsigned int mod plat_dat = dwmac->plat_dat; if (dwmac->ops->mac_rgmii_txclk_auto_adj || - (plat_dat->interface == PHY_INTERFACE_MODE_RMII) || - (plat_dat->interface == PHY_INTERFACE_MODE_MII)) + (plat_dat->mac_interface == PHY_INTERFACE_MODE_RMII) || + (plat_dat->mac_interface == PHY_INTERFACE_MODE_MII)) return; switch (speed) { @@ -260,7 +260,7 @@ static int imx_dwmac_mx93_reset(void *priv, void __iomem *ioaddr) value |= DMA_BUS_MODE_SFT_RESET; writel(value, ioaddr + DMA_BUS_MODE); - if (plat_dat->interface == PHY_INTERFACE_MODE_RMII) { + if (plat_dat->mac_interface == PHY_INTERFACE_MODE_RMII) { usleep_range(100, 200); writel(RMII_RESET_SPEED, ioaddr + MAC_CTRL_REG); } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c index e22ef0d6bc73..0a20c3d24722 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ingenic.c @@ -89,7 +89,7 @@ static int jz4775_mac_set_mode(struct plat_stmmacenet_data *plat_dat) struct ingenic_mac *mac = plat_dat->bsp_priv; unsigned int val; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_MII: val = FIELD_PREP(MACPHYC_TXCLK_SEL_MASK, MACPHYC_TXCLK_SEL_INPUT) | FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_MII); @@ -118,7 +118,7 @@ static int jz4775_mac_set_mode(struct plat_stmmacenet_data *plat_dat) break; default: - dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface); + dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface); return -EINVAL; } @@ -130,13 +130,13 @@ static int x1000_mac_set_mode(struct plat_stmmacenet_data *plat_dat) { struct ingenic_mac *mac = plat_dat->bsp_priv; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_RMII: dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n"); break; default: - dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface); + dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface); return -EINVAL; } @@ -149,14 +149,14 @@ static int x1600_mac_set_mode(struct plat_stmmacenet_data *plat_dat) struct ingenic_mac *mac = plat_dat->bsp_priv; unsigned int val; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_RMII: val = FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII); dev_dbg(mac->dev, "MAC PHY Control Register: PHY_INTERFACE_MODE_RMII\n"); break; default: - dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface); + dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface); return -EINVAL; } @@ -169,7 +169,7 @@ static int x1830_mac_set_mode(struct plat_stmmacenet_data *plat_dat) struct ingenic_mac *mac = plat_dat->bsp_priv; unsigned int val; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_RMII: val = FIELD_PREP(MACPHYC_MODE_SEL_MASK, MACPHYC_MODE_SEL_RMII) | FIELD_PREP(MACPHYC_PHY_INFT_MASK, MACPHYC_PHY_INFT_RMII); @@ -177,7 +177,7 @@ static int x1830_mac_set_mode(struct plat_stmmacenet_data *plat_dat) break; default: - dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface); + dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface); return -EINVAL; } @@ -190,7 +190,7 @@ static int x2000_mac_set_mode(struct plat_stmmacenet_data *plat_dat) struct ingenic_mac *mac = plat_dat->bsp_priv; unsigned int val; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_RMII: val = FIELD_PREP(MACPHYC_TX_SEL_MASK, MACPHYC_TX_SEL_ORIGIN) | FIELD_PREP(MACPHYC_RX_SEL_MASK, MACPHYC_RX_SEL_ORIGIN) | @@ -220,7 +220,7 @@ static int x2000_mac_set_mode(struct plat_stmmacenet_data *plat_dat) break; default: - dev_err(mac->dev, "Unsupported interface %d", plat_dat->interface); + dev_err(mac->dev, "Unsupported interface %d", plat_dat->mac_interface); return -EINVAL; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index a25c187d3185..2cd6fce5c993 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -117,7 +117,7 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id } plat->phy_interface = phy_mode; - plat->interface = PHY_INTERFACE_MODE_GMII; + plat->mac_interface = PHY_INTERFACE_MODE_GMII; pci_set_master(pdev); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c index 18e84ba693a6..d0aa674ce705 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c @@ -50,9 +50,9 @@ static int lpc18xx_dwmac_probe(struct platform_device *pdev) goto err_remove_config_dt; } - if (plat_dat->interface == PHY_INTERFACE_MODE_MII) { + if (plat_dat->mac_interface == PHY_INTERFACE_MODE_MII) { ethmode = LPC18XX_CREG_CREG6_ETHMODE_MII; - } else if (plat_dat->interface == PHY_INTERFACE_MODE_RMII) { + } else if (plat_dat->mac_interface == PHY_INTERFACE_MODE_RMII) { ethmode = LPC18XX_CREG_CREG6_ETHMODE_RMII; } else { dev_err(&pdev->dev, "Only MII and RMII mode supported\n"); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c index 7580077383c0..cd796ec04132 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c @@ -587,7 +587,7 @@ static int mediatek_dwmac_common_data(struct platform_device *pdev, { int i; - plat->interface = priv_plat->phy_mode; + plat->mac_interface = priv_plat->phy_mode; if (priv_plat->mac_wol) plat->flags |= STMMAC_FLAG_USE_PHY_WOL; else diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c index 7db176e8691f..9bf102bbc6a0 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c @@ -236,7 +236,7 @@ static int socfpga_get_plat_phymode(struct socfpga_dwmac *dwmac) struct net_device *ndev = dev_get_drvdata(dwmac->dev); struct stmmac_priv *priv = netdev_priv(ndev); - return priv->plat->interface; + return priv->plat->mac_interface; } static void socfpga_sgmii_config(struct socfpga_dwmac *dwmac, bool enable) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c index 892612564694..9289bb87c3e3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c @@ -60,7 +60,7 @@ static int starfive_dwmac_set_mode(struct plat_stmmacenet_data *plat_dat) unsigned int mode; int err; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_RMII: mode = STARFIVE_DWMAC_PHY_INFT_RMII; break; @@ -72,7 +72,7 @@ static int starfive_dwmac_set_mode(struct plat_stmmacenet_data *plat_dat) default: dev_err(dwmac->dev, "unsupported interface %d\n", - plat_dat->interface); + plat_dat->mac_interface); return -EINVAL; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c index 3a09085819dc..26ea8c687881 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c @@ -171,7 +171,7 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat) clk_rate = clk_get_rate(dwmac->clk_eth_ck); dwmac->enable_eth_ck = false; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_MII: if (clk_rate == ETH_CK_F_25M && dwmac->ext_phyclk) dwmac->enable_eth_ck = true; @@ -210,7 +210,7 @@ static int stm32mp1_set_mode(struct plat_stmmacenet_data *plat_dat) break; default: pr_debug("SYSCFG init : Do not manage %d interface\n", - plat_dat->interface); + plat_dat->mac_interface); /* Do not manage others interfaces */ return -EINVAL; } @@ -230,7 +230,7 @@ static int stm32mcu_set_mode(struct plat_stmmacenet_data *plat_dat) u32 reg = dwmac->mode_reg; int val; - switch (plat_dat->interface) { + switch (plat_dat->mac_interface) { case PHY_INTERFACE_MODE_MII: val = SYSCFG_MCU_ETH_SEL_MII; pr_debug("SYSCFG init : PHY_INTERFACE_MODE_MII\n"); @@ -241,7 +241,7 @@ static int stm32mcu_set_mode(struct plat_stmmacenet_data *plat_dat) break; default: pr_debug("SYSCFG init : Do not manage %d interface\n", - plat_dat->interface); + plat_dat->mac_interface); /* Do not manage others interfaces */ return -EINVAL; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index c23420863a8d..01e77368eef1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -1016,7 +1016,7 @@ static int sun8i_dwmac_set_syscon(struct device *dev, if (gmac->variant->support_rmii) reg &= ~SYSCON_RMII_EN; - switch (plat->interface) { + switch (plat->mac_interface) { case PHY_INTERFACE_MODE_MII: /* default */ break; @@ -1031,7 +1031,7 @@ static int sun8i_dwmac_set_syscon(struct device *dev, break; default: dev_err(dev, "Unsupported interface mode: %s", - phy_modes(plat->interface)); + phy_modes(plat->mac_interface)); return -EINVAL; } @@ -1231,7 +1231,7 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) /* platform data specifying hardware features and callbacks. * hardware features were copied from Allwinner drivers. */ - plat_dat->interface = interface; + plat_dat->mac_interface = interface; plat_dat->rx_coe = STMMAC_RX_COE_TYPE2; plat_dat->tx_coe = 1; plat_dat->flags |= STMMAC_FLAG_HAS_SUN8I; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 33ca5c50bdcd..9a3182b9e767 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1119,7 +1119,7 @@ static const struct phylink_mac_ops stmmac_phylink_mac_ops = { */ static void stmmac_check_pcs_mode(struct stmmac_priv *priv) { - int interface = priv->plat->interface; + int interface = priv->plat->mac_interface; if (priv->dma_cap.pcs) { if ((interface == PHY_INTERFACE_MODE_RGMII) || @@ -1214,7 +1214,9 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) priv->phylink_config.ovr_an_inband = mdio_bus_data->xpcs_an_inband; - /* Set the platform/firmware specified interface mode */ + /* Set the platform/firmware specified interface mode. Note, phylink + * deals with the PHY interface mode, not the MAC interface mode. + */ __set_bit(mode, priv->phylink_config.supported_interfaces); /* If we have an xpcs, it defines which PHY interfaces are supported. */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index ff330423ee66..35f4b1484029 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -419,9 +419,9 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac) return ERR_PTR(phy_mode); plat->phy_interface = phy_mode; - plat->interface = stmmac_of_get_mac_mode(np); - if (plat->interface < 0) - plat->interface = plat->phy_interface; + plat->mac_interface = stmmac_of_get_mac_mode(np); + if (plat->mac_interface < 0) + plat->mac_interface = plat->phy_interface; /* Some wrapper drivers still rely on phy_node. Let's save it while * they are not converted to phylink. */ diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig index 63e510b6860f..88b5b1b47779 100644 --- a/drivers/net/ethernet/ti/Kconfig +++ b/drivers/net/ethernet/ti/Kconfig @@ -186,6 +186,7 @@ config CPMAC config TI_ICSSG_PRUETH tristate "TI Gigabit PRU Ethernet driver" select PHYLIB + select TI_ICSS_IEP depends on PRU_REMOTEPROC depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER help @@ -196,4 +197,15 @@ config TI_ICSSG_PRUETH to support the Ethernet operation. Currently, it supports Ethernet with 1G and 100M link speed. +config TI_ICSS_IEP + tristate "TI PRU ICSS IEP driver" + depends on TI_PRUSS + default TI_PRUSS + help + This driver enables support for the PRU-ICSS Industrial Ethernet + Peripheral within a PRU-ICSS subsystem present on various TI SoCs. + + To compile this driver as a module, choose M here. The module + will be called icss_iep. + endif # NET_VENDOR_TI diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile index 9176d79c36e1..34fd7a716ba6 100644 --- a/drivers/net/ethernet/ti/Makefile +++ b/drivers/net/ethernet/ti/Makefile @@ -38,3 +38,4 @@ icssg-prueth-y := k3-cppi-desc-pool.o \ icssg/icssg_mii_cfg.o \ icssg/icssg_stats.o \ icssg/icssg_ethtool.o +obj-$(CONFIG_TI_ICSS_IEP) += icssg/icss_iep.o diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.c b/drivers/net/ethernet/ti/icssg/icss_iep.c new file mode 100644 index 000000000000..4cf2a52e4378 --- /dev/null +++ b/drivers/net/ethernet/ti/icssg/icss_iep.c @@ -0,0 +1,965 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* Texas Instruments ICSSG Industrial Ethernet Peripheral (IEP) Driver + * + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com + * + */ + +#include <linux/bitops.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/timekeeping.h> +#include <linux/interrupt.h> +#include <linux/of_irq.h> + +#include "icss_iep.h" + +#define IEP_MAX_DEF_INC 0xf +#define IEP_MAX_COMPEN_INC 0xfff +#define IEP_MAX_COMPEN_COUNT 0xffffff + +#define IEP_GLOBAL_CFG_CNT_ENABLE BIT(0) +#define IEP_GLOBAL_CFG_DEFAULT_INC_MASK GENMASK(7, 4) +#define IEP_GLOBAL_CFG_DEFAULT_INC_SHIFT 4 +#define IEP_GLOBAL_CFG_COMPEN_INC_MASK GENMASK(19, 8) +#define IEP_GLOBAL_CFG_COMPEN_INC_SHIFT 8 + +#define IEP_GLOBAL_STATUS_CNT_OVF BIT(0) + +#define IEP_CMP_CFG_SHADOW_EN BIT(17) +#define IEP_CMP_CFG_CMP0_RST_CNT_EN BIT(0) +#define IEP_CMP_CFG_CMP_EN(cmp) (GENMASK(16, 1) & (1 << ((cmp) + 1))) + +#define IEP_CMP_STATUS(cmp) (1 << (cmp)) + +#define IEP_SYNC_CTRL_SYNC_EN BIT(0) +#define IEP_SYNC_CTRL_SYNC_N_EN(n) (GENMASK(2, 1) & (BIT(1) << (n))) + +#define IEP_MIN_CMP 0 +#define IEP_MAX_CMP 15 + +#define ICSS_IEP_64BIT_COUNTER_SUPPORT BIT(0) +#define ICSS_IEP_SLOW_COMPEN_REG_SUPPORT BIT(1) +#define ICSS_IEP_SHADOW_MODE_SUPPORT BIT(2) + +#define LATCH_INDEX(ts_index) ((ts_index) + 6) +#define IEP_CAP_CFG_CAPNR_1ST_EVENT_EN(n) BIT(LATCH_INDEX(n)) +#define IEP_CAP_CFG_CAP_ASYNC_EN(n) BIT(LATCH_INDEX(n) + 10) + +enum { + ICSS_IEP_GLOBAL_CFG_REG, + ICSS_IEP_GLOBAL_STATUS_REG, + ICSS_IEP_COMPEN_REG, + ICSS_IEP_SLOW_COMPEN_REG, + ICSS_IEP_COUNT_REG0, + ICSS_IEP_COUNT_REG1, + ICSS_IEP_CAPTURE_CFG_REG, + ICSS_IEP_CAPTURE_STAT_REG, + + ICSS_IEP_CAP6_RISE_REG0, + ICSS_IEP_CAP6_RISE_REG1, + + ICSS_IEP_CAP7_RISE_REG0, + ICSS_IEP_CAP7_RISE_REG1, + + ICSS_IEP_CMP_CFG_REG, + ICSS_IEP_CMP_STAT_REG, + ICSS_IEP_CMP0_REG0, + ICSS_IEP_CMP0_REG1, + ICSS_IEP_CMP1_REG0, + ICSS_IEP_CMP1_REG1, + + ICSS_IEP_CMP8_REG0, + ICSS_IEP_CMP8_REG1, + ICSS_IEP_SYNC_CTRL_REG, + ICSS_IEP_SYNC0_STAT_REG, + ICSS_IEP_SYNC1_STAT_REG, + ICSS_IEP_SYNC_PWIDTH_REG, + ICSS_IEP_SYNC0_PERIOD_REG, + ICSS_IEP_SYNC1_DELAY_REG, + ICSS_IEP_SYNC_START_REG, + ICSS_IEP_MAX_REGS, +}; + +/** + * struct icss_iep_plat_data - Plat data to handle SoC variants + * @config: Regmap configuration data + * @reg_offs: register offsets to capture offset differences across SoCs + * @flags: Flags to represent IEP properties + */ +struct icss_iep_plat_data { + struct regmap_config *config; + u32 reg_offs[ICSS_IEP_MAX_REGS]; + u32 flags; +}; + +struct icss_iep { + struct device *dev; + void __iomem *base; + const struct icss_iep_plat_data *plat_data; + struct regmap *map; + struct device_node *client_np; + unsigned long refclk_freq; + int clk_tick_time; /* one refclk tick time in ns */ + struct ptp_clock_info ptp_info; + struct ptp_clock *ptp_clock; + struct mutex ptp_clk_mutex; /* PHC access serializer */ + spinlock_t irq_lock; /* CMP IRQ vs icss_iep_ptp_enable access */ + u32 def_inc; + s16 slow_cmp_inc; + u32 slow_cmp_count; + const struct icss_iep_clockops *ops; + void *clockops_data; + u32 cycle_time_ns; + u32 perout_enabled; + bool pps_enabled; + int cap_cmp_irq; + u64 period; + u32 latch_enable; +}; + +/** + * icss_iep_get_count_hi() - Get the upper 32 bit IEP counter + * @iep: Pointer to structure representing IEP. + * + * Return: upper 32 bit IEP counter + */ +int icss_iep_get_count_hi(struct icss_iep *iep) +{ + u32 val = 0; + + if (iep && (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)) + val = readl(iep->base + iep->plat_data->reg_offs[ICSS_IEP_COUNT_REG1]); + + return val; +} +EXPORT_SYMBOL_GPL(icss_iep_get_count_hi); + +/** + * icss_iep_get_count_low() - Get the lower 32 bit IEP counter + * @iep: Pointer to structure representing IEP. + * + * Return: lower 32 bit IEP counter + */ +int icss_iep_get_count_low(struct icss_iep *iep) +{ + u32 val = 0; + + if (iep) + val = readl(iep->base + iep->plat_data->reg_offs[ICSS_IEP_COUNT_REG0]); + + return val; +} +EXPORT_SYMBOL_GPL(icss_iep_get_count_low); + +/** + * icss_iep_get_ptp_clock_idx() - Get PTP clock index using IEP driver + * @iep: Pointer to structure representing IEP. + * + * Return: PTP clock index, -1 if not registered + */ +int icss_iep_get_ptp_clock_idx(struct icss_iep *iep) +{ + if (!iep || !iep->ptp_clock) + return -1; + return ptp_clock_index(iep->ptp_clock); +} +EXPORT_SYMBOL_GPL(icss_iep_get_ptp_clock_idx); + +static void icss_iep_set_counter(struct icss_iep *iep, u64 ns) +{ + if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) + writel(upper_32_bits(ns), iep->base + + iep->plat_data->reg_offs[ICSS_IEP_COUNT_REG1]); + writel(upper_32_bits(ns), iep->base + iep->plat_data->reg_offs[ICSS_IEP_COUNT_REG0]); +} + +static void icss_iep_update_to_next_boundary(struct icss_iep *iep, u64 start_ns); + +/** + * icss_iep_settime() - Set time of the PTP clock using IEP driver + * @iep: Pointer to structure representing IEP. + * @ns: Time to be set in nanoseconds + * + * This API uses writel() instead of regmap_write() for write operations as + * regmap_write() is too slow and this API is time sensitive. + */ +static void icss_iep_settime(struct icss_iep *iep, u64 ns) +{ + unsigned long flags; + + if (iep->ops && iep->ops->settime) { + iep->ops->settime(iep->clockops_data, ns); + return; + } + + spin_lock_irqsave(&iep->irq_lock, flags); + if (iep->pps_enabled || iep->perout_enabled) + writel(0, iep->base + iep->plat_data->reg_offs[ICSS_IEP_SYNC_CTRL_REG]); + + icss_iep_set_counter(iep, ns); + + if (iep->pps_enabled || iep->perout_enabled) { + icss_iep_update_to_next_boundary(iep, ns); + writel(IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN, + iep->base + iep->plat_data->reg_offs[ICSS_IEP_SYNC_CTRL_REG]); + } + spin_unlock_irqrestore(&iep->irq_lock, flags); +} + +/** + * icss_iep_gettime() - Get time of the PTP clock using IEP driver + * @iep: Pointer to structure representing IEP. + * @sts: Pointer to structure representing PTP system timestamp. + * + * This API uses readl() instead of regmap_read() for read operations as + * regmap_read() is too slow and this API is time sensitive. + * + * Return: The current timestamp of the PTP clock using IEP driver + */ +static u64 icss_iep_gettime(struct icss_iep *iep, + struct ptp_system_timestamp *sts) +{ + u32 ts_hi = 0, ts_lo; + unsigned long flags; + + if (iep->ops && iep->ops->gettime) + return iep->ops->gettime(iep->clockops_data, sts); + + /* use local_irq_x() to make it work for both RT/non-RT */ + local_irq_save(flags); + + /* no need to play with hi-lo, hi is latched when lo is read */ + ptp_read_system_prets(sts); + ts_lo = readl(iep->base + iep->plat_data->reg_offs[ICSS_IEP_COUNT_REG0]); + ptp_read_system_postts(sts); + if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) + ts_hi = readl(iep->base + iep->plat_data->reg_offs[ICSS_IEP_COUNT_REG1]); + + local_irq_restore(flags); + + return (u64)ts_lo | (u64)ts_hi << 32; +} + +static void icss_iep_enable(struct icss_iep *iep) +{ + regmap_update_bits(iep->map, ICSS_IEP_GLOBAL_CFG_REG, + IEP_GLOBAL_CFG_CNT_ENABLE, + IEP_GLOBAL_CFG_CNT_ENABLE); +} + +static void icss_iep_disable(struct icss_iep *iep) +{ + regmap_update_bits(iep->map, ICSS_IEP_GLOBAL_CFG_REG, + IEP_GLOBAL_CFG_CNT_ENABLE, + 0); +} + +static void icss_iep_enable_shadow_mode(struct icss_iep *iep) +{ + u32 cycle_time; + int cmp; + + cycle_time = iep->cycle_time_ns - iep->def_inc; + + icss_iep_disable(iep); + + /* disable shadow mode */ + regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, + IEP_CMP_CFG_SHADOW_EN, 0); + + /* enable shadow mode */ + regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, + IEP_CMP_CFG_SHADOW_EN, IEP_CMP_CFG_SHADOW_EN); + + /* clear counters */ + icss_iep_set_counter(iep, 0); + + /* clear overflow status */ + regmap_update_bits(iep->map, ICSS_IEP_GLOBAL_STATUS_REG, + IEP_GLOBAL_STATUS_CNT_OVF, + IEP_GLOBAL_STATUS_CNT_OVF); + + /* clear compare status */ + for (cmp = IEP_MIN_CMP; cmp < IEP_MAX_CMP; cmp++) { + regmap_update_bits(iep->map, ICSS_IEP_CMP_STAT_REG, + IEP_CMP_STATUS(cmp), IEP_CMP_STATUS(cmp)); + } + + /* enable reset counter on CMP0 event */ + regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, + IEP_CMP_CFG_CMP0_RST_CNT_EN, + IEP_CMP_CFG_CMP0_RST_CNT_EN); + /* enable compare */ + regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, + IEP_CMP_CFG_CMP_EN(0), + IEP_CMP_CFG_CMP_EN(0)); + + /* set CMP0 value to cycle time */ + regmap_write(iep->map, ICSS_IEP_CMP0_REG0, cycle_time); + if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) + regmap_write(iep->map, ICSS_IEP_CMP0_REG1, cycle_time); + + icss_iep_set_counter(iep, 0); + icss_iep_enable(iep); +} + +static void icss_iep_set_default_inc(struct icss_iep *iep, u8 def_inc) +{ + regmap_update_bits(iep->map, ICSS_IEP_GLOBAL_CFG_REG, + IEP_GLOBAL_CFG_DEFAULT_INC_MASK, + def_inc << IEP_GLOBAL_CFG_DEFAULT_INC_SHIFT); +} + +static void icss_iep_set_compensation_inc(struct icss_iep *iep, u16 compen_inc) +{ + struct device *dev = regmap_get_device(iep->map); + + if (compen_inc > IEP_MAX_COMPEN_INC) { + dev_err(dev, "%s: too high compensation inc %d\n", + __func__, compen_inc); + compen_inc = IEP_MAX_COMPEN_INC; + } + + regmap_update_bits(iep->map, ICSS_IEP_GLOBAL_CFG_REG, + IEP_GLOBAL_CFG_COMPEN_INC_MASK, + compen_inc << IEP_GLOBAL_CFG_COMPEN_INC_SHIFT); +} + +static void icss_iep_set_compensation_count(struct icss_iep *iep, + u32 compen_count) +{ + struct device *dev = regmap_get_device(iep->map); + + if (compen_count > IEP_MAX_COMPEN_COUNT) { + dev_err(dev, "%s: too high compensation count %d\n", + __func__, compen_count); + compen_count = IEP_MAX_COMPEN_COUNT; + } + + regmap_write(iep->map, ICSS_IEP_COMPEN_REG, compen_count); +} + +static void icss_iep_set_slow_compensation_count(struct icss_iep *iep, + u32 compen_count) +{ + regmap_write(iep->map, ICSS_IEP_SLOW_COMPEN_REG, compen_count); +} + +/* PTP PHC operations */ +static int icss_iep_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) +{ + struct icss_iep *iep = container_of(ptp, struct icss_iep, ptp_info); + s32 ppb = scaled_ppm_to_ppb(scaled_ppm); + u32 cyc_count; + u16 cmp_inc; + + mutex_lock(&iep->ptp_clk_mutex); + + /* ppb is amount of frequency we want to adjust in 1GHz (billion) + * e.g. 100ppb means we need to speed up clock by 100Hz + * i.e. at end of 1 second (1 billion ns) clock time, we should be + * counting 100 more ns. + * We use IEP slow compensation to achieve continuous freq. adjustment. + * There are 2 parts. Cycle time and adjustment per cycle. + * Simplest case would be 1 sec Cycle time. Then adjustment + * pre cycle would be (def_inc + ppb) value. + * Cycle time will have to be chosen based on how worse the ppb is. + * e.g. smaller the ppb, cycle time has to be large. + * The minimum adjustment we can do is +-1ns per cycle so let's + * reduce the cycle time to get 1ns per cycle adjustment. + * 1ppb = 1sec cycle time & 1ns adjust + * 1000ppb = 1/1000 cycle time & 1ns adjust per cycle + */ + + if (iep->cycle_time_ns) + iep->slow_cmp_inc = iep->clk_tick_time; /* 4ns adj per cycle */ + else + iep->slow_cmp_inc = 1; /* 1ns adjust per cycle */ + + if (ppb < 0) { + iep->slow_cmp_inc = -iep->slow_cmp_inc; + ppb = -ppb; + } + + cyc_count = NSEC_PER_SEC; /* 1s cycle time @1GHz */ + cyc_count /= ppb; /* cycle time per ppb */ + + /* slow_cmp_count is decremented every clock cycle, e.g. @250MHz */ + if (!iep->cycle_time_ns) + cyc_count /= iep->clk_tick_time; + iep->slow_cmp_count = cyc_count; + + /* iep->clk_tick_time is def_inc */ + cmp_inc = iep->clk_tick_time + iep->slow_cmp_inc; + icss_iep_set_compensation_inc(iep, cmp_inc); + icss_iep_set_slow_compensation_count(iep, iep->slow_cmp_count); + + mutex_unlock(&iep->ptp_clk_mutex); + + return 0; +} + +static int icss_iep_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) +{ + struct icss_iep *iep = container_of(ptp, struct icss_iep, ptp_info); + s64 ns; + + mutex_lock(&iep->ptp_clk_mutex); + if (iep->ops && iep->ops->adjtime) { + iep->ops->adjtime(iep->clockops_data, delta); + } else { + ns = icss_iep_gettime(iep, NULL); + ns += delta; + icss_iep_settime(iep, ns); + } + mutex_unlock(&iep->ptp_clk_mutex); + + return 0; +} + +static int icss_iep_ptp_gettimeex(struct ptp_clock_info *ptp, + struct timespec64 *ts, + struct ptp_system_timestamp *sts) +{ + struct icss_iep *iep = container_of(ptp, struct icss_iep, ptp_info); + u64 ns; + + mutex_lock(&iep->ptp_clk_mutex); + ns = icss_iep_gettime(iep, sts); + *ts = ns_to_timespec64(ns); + mutex_unlock(&iep->ptp_clk_mutex); + + return 0; +} + +static int icss_iep_ptp_settime(struct ptp_clock_info *ptp, + const struct timespec64 *ts) +{ + struct icss_iep *iep = container_of(ptp, struct icss_iep, ptp_info); + u64 ns; + + mutex_lock(&iep->ptp_clk_mutex); + ns = timespec64_to_ns(ts); + icss_iep_settime(iep, ns); + mutex_unlock(&iep->ptp_clk_mutex); + + return 0; +} + +static void icss_iep_update_to_next_boundary(struct icss_iep *iep, u64 start_ns) +{ + u64 ns, p_ns; + u32 offset; + + ns = icss_iep_gettime(iep, NULL); + if (start_ns < ns) + start_ns = ns; + p_ns = iep->period; + /* Round up to next period boundary */ + start_ns += p_ns - 1; + offset = do_div(start_ns, p_ns); + start_ns = start_ns * p_ns; + /* If it is too close to update, shift to next boundary */ + if (p_ns - offset < 10) + start_ns += p_ns; + + regmap_write(iep->map, ICSS_IEP_CMP1_REG0, lower_32_bits(start_ns)); + if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) + regmap_write(iep->map, ICSS_IEP_CMP1_REG1, upper_32_bits(start_ns)); +} + +static int icss_iep_perout_enable_hw(struct icss_iep *iep, + struct ptp_perout_request *req, int on) +{ + int ret; + u64 cmp; + + if (iep->ops && iep->ops->perout_enable) { + ret = iep->ops->perout_enable(iep->clockops_data, req, on, &cmp); + if (ret) + return ret; + + if (on) { + /* Configure CMP */ + regmap_write(iep->map, ICSS_IEP_CMP1_REG0, lower_32_bits(cmp)); + if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) + regmap_write(iep->map, ICSS_IEP_CMP1_REG1, upper_32_bits(cmp)); + /* Configure SYNC, 1ms pulse width */ + regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, 1000000); + regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0); + regmap_write(iep->map, ICSS_IEP_SYNC_START_REG, 0); + regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); /* one-shot mode */ + /* Enable CMP 1 */ + regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, + IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1)); + } else { + /* Disable CMP 1 */ + regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, + IEP_CMP_CFG_CMP_EN(1), 0); + + /* clear regs */ + regmap_write(iep->map, ICSS_IEP_CMP1_REG0, 0); + if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) + regmap_write(iep->map, ICSS_IEP_CMP1_REG1, 0); + } + } else { + if (on) { + u64 start_ns; + + iep->period = ((u64)req->period.sec * NSEC_PER_SEC) + + req->period.nsec; + start_ns = ((u64)req->period.sec * NSEC_PER_SEC) + + req->period.nsec; + icss_iep_update_to_next_boundary(iep, start_ns); + + /* Enable Sync in single shot mode */ + regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, + IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN); + /* Enable CMP 1 */ + regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, + IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1)); + } else { + /* Disable CMP 1 */ + regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG, + IEP_CMP_CFG_CMP_EN(1), 0); + + /* clear CMP regs */ + regmap_write(iep->map, ICSS_IEP_CMP1_REG0, 0); + if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) + regmap_write(iep->map, ICSS_IEP_CMP1_REG1, 0); + + /* Disable sync */ + regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); + } + } + + return 0; +} + +static int icss_iep_perout_enable(struct icss_iep *iep, + struct ptp_perout_request *req, int on) +{ + unsigned long flags; + int ret = 0; + + mutex_lock(&iep->ptp_clk_mutex); + + if (iep->pps_enabled) { + ret = -EBUSY; + goto exit; + } + + if (iep->perout_enabled == !!on) + goto exit; + + spin_lock_irqsave(&iep->irq_lock, flags); + ret = icss_iep_perout_enable_hw(iep, req, on); + if (!ret) + iep->perout_enabled = !!on; + spin_unlock_irqrestore(&iep->irq_lock, flags); + +exit: + mutex_unlock(&iep->ptp_clk_mutex); + + return ret; +} + +static int icss_iep_pps_enable(struct icss_iep *iep, int on) +{ + struct ptp_clock_request rq; + struct timespec64 ts; + unsigned long flags; + int ret = 0; + u64 ns; + + mutex_lock(&iep->ptp_clk_mutex); + + if (iep->perout_enabled) { + ret = -EBUSY; + goto exit; + } + + if (iep->pps_enabled == !!on) + goto exit; + + spin_lock_irqsave(&iep->irq_lock, flags); + + rq.perout.index = 0; + if (on) { + ns = icss_iep_gettime(iep, NULL); + ts = ns_to_timespec64(ns); + rq.perout.period.sec = 1; + rq.perout.period.nsec = 0; + rq.perout.start.sec = ts.tv_sec + 2; + rq.perout.start.nsec = 0; + ret = icss_iep_perout_enable_hw(iep, &rq.perout, on); + } else { + ret = icss_iep_perout_enable_hw(iep, &rq.perout, on); + } + + if (!ret) + iep->pps_enabled = !!on; + + spin_unlock_irqrestore(&iep->irq_lock, flags); + +exit: + mutex_unlock(&iep->ptp_clk_mutex); + + return ret; +} + +static int icss_iep_extts_enable(struct icss_iep *iep, u32 index, int on) +{ + u32 val, cap, ret = 0; + + mutex_lock(&iep->ptp_clk_mutex); + + if (iep->ops && iep->ops->extts_enable) { + ret = iep->ops->extts_enable(iep->clockops_data, index, on); + goto exit; + } + + if (((iep->latch_enable & BIT(index)) >> index) == on) + goto exit; + + regmap_read(iep->map, ICSS_IEP_CAPTURE_CFG_REG, &val); + cap = IEP_CAP_CFG_CAP_ASYNC_EN(index) | IEP_CAP_CFG_CAPNR_1ST_EVENT_EN(index); + if (on) { + val |= cap; + iep->latch_enable |= BIT(index); + } else { + val &= ~cap; + iep->latch_enable &= ~BIT(index); + } + regmap_write(iep->map, ICSS_IEP_CAPTURE_CFG_REG, val); + +exit: + mutex_unlock(&iep->ptp_clk_mutex); + + return ret; +} + +static int icss_iep_ptp_enable(struct ptp_clock_info *ptp, + struct ptp_clock_request *rq, int on) +{ + struct icss_iep *iep = container_of(ptp, struct icss_iep, ptp_info); + + switch (rq->type) { + case PTP_CLK_REQ_PEROUT: + return icss_iep_perout_enable(iep, &rq->perout, on); + case PTP_CLK_REQ_PPS: + return icss_iep_pps_enable(iep, on); + case PTP_CLK_REQ_EXTTS: + return icss_iep_extts_enable(iep, rq->extts.index, on); + default: + break; + } + + return -EOPNOTSUPP; +} + +static struct ptp_clock_info icss_iep_ptp_info = { + .owner = THIS_MODULE, + .name = "ICSS IEP timer", + .max_adj = 10000000, + .adjfine = icss_iep_ptp_adjfine, + .adjtime = icss_iep_ptp_adjtime, + .gettimex64 = icss_iep_ptp_gettimeex, + .settime64 = icss_iep_ptp_settime, + .enable = icss_iep_ptp_enable, +}; + +struct icss_iep *icss_iep_get_idx(struct device_node *np, int idx) +{ + struct platform_device *pdev; + struct device_node *iep_np; + struct icss_iep *iep; + + iep_np = of_parse_phandle(np, "ti,iep", idx); + if (!iep_np || !of_device_is_available(iep_np)) + return ERR_PTR(-ENODEV); + + pdev = of_find_device_by_node(iep_np); + of_node_put(iep_np); + + if (!pdev) + /* probably IEP not yet probed */ + return ERR_PTR(-EPROBE_DEFER); + + iep = platform_get_drvdata(pdev); + if (!iep) + return ERR_PTR(-EPROBE_DEFER); + + device_lock(iep->dev); + if (iep->client_np) { + device_unlock(iep->dev); + dev_err(iep->dev, "IEP is already acquired by %s", + iep->client_np->name); + return ERR_PTR(-EBUSY); + } + iep->client_np = np; + device_unlock(iep->dev); + get_device(iep->dev); + + return iep; +} +EXPORT_SYMBOL_GPL(icss_iep_get_idx); + +struct icss_iep *icss_iep_get(struct device_node *np) +{ + return icss_iep_get_idx(np, 0); +} +EXPORT_SYMBOL_GPL(icss_iep_get); + +void icss_iep_put(struct icss_iep *iep) +{ + device_lock(iep->dev); + iep->client_np = NULL; + device_unlock(iep->dev); + put_device(iep->dev); +} +EXPORT_SYMBOL_GPL(icss_iep_put); + +void icss_iep_init_fw(struct icss_iep *iep) +{ + /* start IEP for FW use in raw 64bit mode, no PTP support */ + iep->clk_tick_time = iep->def_inc; + iep->cycle_time_ns = 0; + iep->ops = NULL; + iep->clockops_data = NULL; + icss_iep_set_default_inc(iep, iep->def_inc); + icss_iep_set_compensation_inc(iep, iep->def_inc); + icss_iep_set_compensation_count(iep, 0); + regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, iep->refclk_freq / 10); /* 100 ms pulse */ + regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0); + if (iep->plat_data->flags & ICSS_IEP_SLOW_COMPEN_REG_SUPPORT) + icss_iep_set_slow_compensation_count(iep, 0); + + icss_iep_enable(iep); + icss_iep_settime(iep, 0); +} +EXPORT_SYMBOL_GPL(icss_iep_init_fw); + +void icss_iep_exit_fw(struct icss_iep *iep) +{ + icss_iep_disable(iep); +} +EXPORT_SYMBOL_GPL(icss_iep_exit_fw); + +int icss_iep_init(struct icss_iep *iep, const struct icss_iep_clockops *clkops, + void *clockops_data, u32 cycle_time_ns) +{ + int ret = 0; + + iep->cycle_time_ns = cycle_time_ns; + iep->clk_tick_time = iep->def_inc; + iep->ops = clkops; + iep->clockops_data = clockops_data; + icss_iep_set_default_inc(iep, iep->def_inc); + icss_iep_set_compensation_inc(iep, iep->def_inc); + icss_iep_set_compensation_count(iep, 0); + regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, iep->refclk_freq / 10); /* 100 ms pulse */ + regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0); + if (iep->plat_data->flags & ICSS_IEP_SLOW_COMPEN_REG_SUPPORT) + icss_iep_set_slow_compensation_count(iep, 0); + + if (!(iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) || + !(iep->plat_data->flags & ICSS_IEP_SLOW_COMPEN_REG_SUPPORT)) + goto skip_perout; + + if (iep->ops && iep->ops->perout_enable) { + iep->ptp_info.n_per_out = 1; + iep->ptp_info.pps = 1; + } + + if (iep->ops && iep->ops->extts_enable) + iep->ptp_info.n_ext_ts = 2; + +skip_perout: + if (cycle_time_ns) + icss_iep_enable_shadow_mode(iep); + else + icss_iep_enable(iep); + icss_iep_settime(iep, ktime_get_real_ns()); + + iep->ptp_clock = ptp_clock_register(&iep->ptp_info, iep->dev); + if (IS_ERR(iep->ptp_clock)) { + ret = PTR_ERR(iep->ptp_clock); + iep->ptp_clock = NULL; + dev_err(iep->dev, "Failed to register ptp clk %d\n", ret); + } + + return ret; +} +EXPORT_SYMBOL_GPL(icss_iep_init); + +int icss_iep_exit(struct icss_iep *iep) +{ + if (iep->ptp_clock) { + ptp_clock_unregister(iep->ptp_clock); + iep->ptp_clock = NULL; + } + icss_iep_disable(iep); + + return 0; +} +EXPORT_SYMBOL_GPL(icss_iep_exit); + +static int icss_iep_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct icss_iep *iep; + struct clk *iep_clk; + + iep = devm_kzalloc(dev, sizeof(*iep), GFP_KERNEL); + if (!iep) + return -ENOMEM; + + iep->dev = dev; + iep->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(iep->base)) + return -ENODEV; + + iep_clk = devm_clk_get(dev, NULL); + if (IS_ERR(iep_clk)) + return PTR_ERR(iep_clk); + + iep->refclk_freq = clk_get_rate(iep_clk); + + iep->def_inc = NSEC_PER_SEC / iep->refclk_freq; /* ns per clock tick */ + if (iep->def_inc > IEP_MAX_DEF_INC) { + dev_err(dev, "Failed to set def_inc %d. IEP_clock is too slow to be supported\n", + iep->def_inc); + return -EINVAL; + } + + iep->plat_data = device_get_match_data(dev); + if (!iep->plat_data) + return -EINVAL; + + iep->map = devm_regmap_init(dev, NULL, iep, iep->plat_data->config); + if (IS_ERR(iep->map)) { + dev_err(dev, "Failed to create regmap for IEP %ld\n", + PTR_ERR(iep->map)); + return PTR_ERR(iep->map); + } + + iep->ptp_info = icss_iep_ptp_info; + mutex_init(&iep->ptp_clk_mutex); + spin_lock_init(&iep->irq_lock); + dev_set_drvdata(dev, iep); + icss_iep_disable(iep); + + return 0; +} + +static bool am654_icss_iep_valid_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ICSS_IEP_GLOBAL_CFG_REG ... ICSS_IEP_SYNC_START_REG: + return true; + default: + return false; + } + + return false; +} + +static int icss_iep_regmap_write(void *context, unsigned int reg, + unsigned int val) +{ + struct icss_iep *iep = context; + + writel(val, iep->base + iep->plat_data->reg_offs[reg]); + + return 0; +} + +static int icss_iep_regmap_read(void *context, unsigned int reg, + unsigned int *val) +{ + struct icss_iep *iep = context; + + *val = readl(iep->base + iep->plat_data->reg_offs[reg]); + + return 0; +} + +static struct regmap_config am654_icss_iep_regmap_config = { + .name = "icss iep", + .reg_stride = 1, + .reg_write = icss_iep_regmap_write, + .reg_read = icss_iep_regmap_read, + .writeable_reg = am654_icss_iep_valid_reg, + .readable_reg = am654_icss_iep_valid_reg, + .fast_io = 1, +}; + +static const struct icss_iep_plat_data am654_icss_iep_plat_data = { + .flags = ICSS_IEP_64BIT_COUNTER_SUPPORT | + ICSS_IEP_SLOW_COMPEN_REG_SUPPORT | + ICSS_IEP_SHADOW_MODE_SUPPORT, + .reg_offs = { + [ICSS_IEP_GLOBAL_CFG_REG] = 0x00, + [ICSS_IEP_COMPEN_REG] = 0x08, + [ICSS_IEP_SLOW_COMPEN_REG] = 0x0C, + [ICSS_IEP_COUNT_REG0] = 0x10, + [ICSS_IEP_COUNT_REG1] = 0x14, + [ICSS_IEP_CAPTURE_CFG_REG] = 0x18, + [ICSS_IEP_CAPTURE_STAT_REG] = 0x1c, + + [ICSS_IEP_CAP6_RISE_REG0] = 0x50, + [ICSS_IEP_CAP6_RISE_REG1] = 0x54, + + [ICSS_IEP_CAP7_RISE_REG0] = 0x60, + [ICSS_IEP_CAP7_RISE_REG1] = 0x64, + + [ICSS_IEP_CMP_CFG_REG] = 0x70, + [ICSS_IEP_CMP_STAT_REG] = 0x74, + [ICSS_IEP_CMP0_REG0] = 0x78, + [ICSS_IEP_CMP0_REG1] = 0x7c, + [ICSS_IEP_CMP1_REG0] = 0x80, + [ICSS_IEP_CMP1_REG1] = 0x84, + + [ICSS_IEP_CMP8_REG0] = 0xc0, + [ICSS_IEP_CMP8_REG1] = 0xc4, + [ICSS_IEP_SYNC_CTRL_REG] = 0x180, + [ICSS_IEP_SYNC0_STAT_REG] = 0x188, + [ICSS_IEP_SYNC1_STAT_REG] = 0x18c, + [ICSS_IEP_SYNC_PWIDTH_REG] = 0x190, + [ICSS_IEP_SYNC0_PERIOD_REG] = 0x194, + [ICSS_IEP_SYNC1_DELAY_REG] = 0x198, + [ICSS_IEP_SYNC_START_REG] = 0x19c, + }, + .config = &am654_icss_iep_regmap_config, +}; + +static const struct of_device_id icss_iep_of_match[] = { + { + .compatible = "ti,am654-icss-iep", + .data = &am654_icss_iep_plat_data, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, icss_iep_of_match); + +static struct platform_driver icss_iep_driver = { + .driver = { + .name = "icss-iep", + .of_match_table = icss_iep_of_match, + }, + .probe = icss_iep_probe, +}; +module_platform_driver(icss_iep_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("TI ICSS IEP driver"); +MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>"); +MODULE_AUTHOR("Md Danish Anwar <danishanwar@ti.com>"); diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.h b/drivers/net/ethernet/ti/icssg/icss_iep.h new file mode 100644 index 000000000000..803a4b714893 --- /dev/null +++ b/drivers/net/ethernet/ti/icssg/icss_iep.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Texas Instruments ICSSG Industrial Ethernet Peripheral (IEP) Driver + * + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ + * + */ + +#ifndef __NET_TI_ICSS_IEP_H +#define __NET_TI_ICSS_IEP_H + +#include <linux/mutex.h> +#include <linux/ptp_clock_kernel.h> +#include <linux/regmap.h> + +struct icss_iep; +extern const struct icss_iep_clockops prueth_iep_clockops; + +/* Firmware specific clock operations */ +struct icss_iep_clockops { + void (*settime)(void *clockops_data, u64 ns); + void (*adjtime)(void *clockops_data, s64 delta); + u64 (*gettime)(void *clockops_data, struct ptp_system_timestamp *sts); + int (*perout_enable)(void *clockops_data, + struct ptp_perout_request *req, int on, + u64 *cmp); + int (*extts_enable)(void *clockops_data, u32 index, int on); +}; + +struct icss_iep *icss_iep_get(struct device_node *np); +struct icss_iep *icss_iep_get_idx(struct device_node *np, int idx); +void icss_iep_put(struct icss_iep *iep); +int icss_iep_init(struct icss_iep *iep, const struct icss_iep_clockops *clkops, + void *clockops_data, u32 cycle_time_ns); +int icss_iep_exit(struct icss_iep *iep); +int icss_iep_get_count_low(struct icss_iep *iep); +int icss_iep_get_count_hi(struct icss_iep *iep); +int icss_iep_get_ptp_clock_idx(struct icss_iep *iep); +void icss_iep_init_fw(struct icss_iep *iep); +void icss_iep_exit_fw(struct icss_iep *iep); + +#endif /* __NET_TI_ICSS_IEP_H */ diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.c b/drivers/net/ethernet/ti/icssg/icssg_config.c index ab648d3efe85..933b84666574 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_config.c +++ b/drivers/net/ethernet/ti/icssg/icssg_config.c @@ -210,6 +210,10 @@ void icssg_config_ipg(struct prueth_emac *emac) case SPEED_100: icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_100M); break; + case SPEED_10: + /* IPG for 10M is same as 100M */ + icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_100M); + break; default: /* Other links speeds not supported */ netdev_err(emac->ndev, "Unsupported link speed\n"); @@ -440,6 +444,9 @@ void icssg_config_set_speed(struct prueth_emac *emac) case SPEED_100: fw_speed = FW_LINK_SPEED_100M; break; + case SPEED_10: + fw_speed = FW_LINK_SPEED_10M; + break; default: /* Other links speeds not supported */ netdev_err(emac->ndev, "Unsupported link speed\n"); diff --git a/drivers/net/ethernet/ti/icssg/icssg_ethtool.c b/drivers/net/ethernet/ti/icssg/icssg_ethtool.c index 02c312f01d10..a27ec1dcc8d5 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_ethtool.c +++ b/drivers/net/ethernet/ti/icssg/icssg_ethtool.c @@ -109,6 +109,26 @@ static void emac_get_ethtool_stats(struct net_device *ndev, *(data++) = emac->stats[i]; } +static int emac_get_ts_info(struct net_device *ndev, + struct ethtool_ts_info *info) +{ + struct prueth_emac *emac = netdev_priv(ndev); + + info->so_timestamping = + SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + + info->phc_index = icss_iep_get_ptp_clock_idx(emac->iep); + info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON); + info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL); + + return 0; +} + static int emac_set_channels(struct net_device *ndev, struct ethtool_channels *ch) { @@ -176,6 +196,7 @@ const struct ethtool_ops icssg_ethtool_ops = { .get_sset_count = emac_get_sset_count, .get_ethtool_stats = emac_get_ethtool_stats, .get_strings = emac_get_strings, + .get_ts_info = emac_get_ts_info, .get_channels = emac_get_channels, .set_channels = emac_set_channels, .get_link_ksettings = emac_get_link_ksettings, diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c index 47b941fb0198..410612f43cbd 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c @@ -56,6 +56,8 @@ /* CTRLMMR_ICSSG_RGMII_CTRL register bits */ #define ICSSG_CTRL_RGMII_ID_MODE BIT(24) +#define IEP_DEFAULT_CYCLE_TIME_NS 1000000 /* 1 ms */ + static void prueth_cleanup_rx_chns(struct prueth_emac *emac, struct prueth_rx_chn *rx_chn, int max_rflows) @@ -471,6 +473,37 @@ static int prueth_dma_rx_push(struct prueth_emac *emac, desc_rx, desc_dma); } +static u64 icssg_ts_to_ns(u32 hi_sw, u32 hi, u32 lo, u32 cycle_time_ns) +{ + u32 iepcount_lo, iepcount_hi, hi_rollover_count; + u64 ns; + + iepcount_lo = lo & GENMASK(19, 0); + iepcount_hi = (hi & GENMASK(11, 0)) << 12 | lo >> 20; + hi_rollover_count = hi >> 11; + + ns = ((u64)hi_rollover_count) << 23 | (iepcount_hi + hi_sw); + ns = ns * cycle_time_ns + iepcount_lo; + + return ns; +} + +static void emac_rx_timestamp(struct prueth_emac *emac, + struct sk_buff *skb, u32 *psdata) +{ + struct skb_shared_hwtstamps *ssh; + u64 ns; + + u32 hi_sw = readl(emac->prueth->shram.va + + TIMESYNC_FW_WC_COUNT_HI_SW_OFFSET_OFFSET); + ns = icssg_ts_to_ns(hi_sw, psdata[1], psdata[0], + IEP_DEFAULT_CYCLE_TIME_NS); + + ssh = skb_hwtstamps(skb); + memset(ssh, 0, sizeof(*ssh)); + ssh->hwtstamp = ns_to_ktime(ns); +} + static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id) { struct prueth_rx_chn *rx_chn = &emac->rx_chns; @@ -480,6 +513,7 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id) struct sk_buff *skb, *new_skb; dma_addr_t desc_dma, buf_dma; void **swdata; + u32 *psdata; int ret; ret = k3_udma_glue_pop_rx_chn(rx_chn->rx_chn, flow_id, &desc_dma); @@ -497,6 +531,11 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id) swdata = cppi5_hdesc_get_swdata(desc_rx); skb = *swdata; + psdata = cppi5_hdesc_get_psdata(desc_rx); + /* RX HW timestamp */ + if (emac->rx_ts_enabled) + emac_rx_timestamp(emac, skb, psdata); + cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len); k3_udma_glue_rx_cppi5_to_dma_addr(rx_chn->rx_chn, &buf_dma); pkt_len = cppi5_hdesc_get_pktlen(desc_rx); @@ -557,6 +596,86 @@ static void prueth_rx_cleanup(void *data, dma_addr_t desc_dma) dev_kfree_skb_any(skb); } +static int emac_get_tx_ts(struct prueth_emac *emac, + struct emac_tx_ts_response *rsp) +{ + struct prueth *prueth = emac->prueth; + int slice = prueth_emac_slice(emac); + int addr; + + addr = icssg_queue_pop(prueth, slice == 0 ? + ICSSG_TS_POP_SLICE0 : ICSSG_TS_POP_SLICE1); + if (addr < 0) + return addr; + + memcpy_fromio(rsp, prueth->shram.va + addr, sizeof(*rsp)); + /* return buffer back for to pool */ + icssg_queue_push(prueth, slice == 0 ? + ICSSG_TS_PUSH_SLICE0 : ICSSG_TS_PUSH_SLICE1, addr); + + return 0; +} + +static void tx_ts_work(struct prueth_emac *emac) +{ + struct skb_shared_hwtstamps ssh; + struct emac_tx_ts_response tsr; + struct sk_buff *skb; + int ret = 0; + u32 hi_sw; + u64 ns; + + /* There may be more than one pending requests */ + while (1) { + ret = emac_get_tx_ts(emac, &tsr); + if (ret) /* nothing more */ + break; + + if (tsr.cookie >= PRUETH_MAX_TX_TS_REQUESTS || + !emac->tx_ts_skb[tsr.cookie]) { + netdev_err(emac->ndev, "Invalid TX TS cookie 0x%x\n", + tsr.cookie); + break; + } + + skb = emac->tx_ts_skb[tsr.cookie]; + emac->tx_ts_skb[tsr.cookie] = NULL; /* free slot */ + if (!skb) { + netdev_err(emac->ndev, "Driver Bug! got NULL skb\n"); + break; + } + + hi_sw = readl(emac->prueth->shram.va + + TIMESYNC_FW_WC_COUNT_HI_SW_OFFSET_OFFSET); + ns = icssg_ts_to_ns(hi_sw, tsr.hi_ts, tsr.lo_ts, + IEP_DEFAULT_CYCLE_TIME_NS); + + memset(&ssh, 0, sizeof(ssh)); + ssh.hwtstamp = ns_to_ktime(ns); + + skb_tstamp_tx(skb, &ssh); + dev_consume_skb_any(skb); + + if (atomic_dec_and_test(&emac->tx_ts_pending)) /* no more? */ + break; + } +} + +static int prueth_tx_ts_cookie_get(struct prueth_emac *emac) +{ + int i; + + /* search and get the next free slot */ + for (i = 0; i < PRUETH_MAX_TX_TS_REQUESTS; i++) { + if (!emac->tx_ts_skb[i]) { + emac->tx_ts_skb[i] = ERR_PTR(-EBUSY); /* reserve slot */ + return i; + } + } + + return -EBUSY; +} + /** * emac_ndo_start_xmit - EMAC Transmit function * @skb: SKB pointer @@ -577,6 +696,8 @@ static enum netdev_tx emac_ndo_start_xmit(struct sk_buff *skb, struct net_device struct prueth_tx_chn *tx_chn; dma_addr_t desc_dma, buf_dma; int i, ret = 0, q_idx; + bool in_tx_ts = 0; + int tx_ts_cookie; void **swdata; u32 pkt_len; u32 *epib; @@ -608,6 +729,18 @@ static enum netdev_tx emac_ndo_start_xmit(struct sk_buff *skb, struct net_device epib = first_desc->epib; epib[0] = 0; epib[1] = 0; + if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && + emac->tx_ts_enabled) { + tx_ts_cookie = prueth_tx_ts_cookie_get(emac); + if (tx_ts_cookie >= 0) { + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + /* Request TX timestamp */ + epib[0] = (u32)tx_ts_cookie; + epib[1] = 0x80000000; /* TX TS request */ + emac->tx_ts_skb[tx_ts_cookie] = skb_get(skb); + in_tx_ts = 1; + } + } /* set dst tag to indicate internal qid at the firmware which is at * bit8..bit15. bit0..bit7 indicates port num for directed @@ -629,7 +762,7 @@ static enum netdev_tx emac_ndo_start_xmit(struct sk_buff *skb, struct net_device if (!next_desc) { netdev_err(ndev, "tx: failed to allocate frag. descriptor\n"); - goto free_desc_stop_q_busy; + goto free_desc_stop_q_busy_cleanup_tx_ts; } buf_dma = skb_frag_dma_map(tx_chn->dma_dev, frag, 0, frag_size, @@ -638,7 +771,7 @@ static enum netdev_tx emac_ndo_start_xmit(struct sk_buff *skb, struct net_device netdev_err(ndev, "tx: Failed to map skb page\n"); k3_cppi_desc_pool_free(tx_chn->desc_pool, next_desc); ret = NETDEV_TX_OK; - goto drop_free_descs; + goto cleanup_tx_ts; } cppi5_hdesc_reset_hbdesc(next_desc); @@ -670,6 +803,9 @@ static enum netdev_tx emac_ndo_start_xmit(struct sk_buff *skb, struct net_device goto drop_free_descs; } + if (in_tx_ts) + atomic_inc(&emac->tx_ts_pending); + if (k3_cppi_desc_pool_avail(tx_chn->desc_pool) < MAX_SKB_FRAGS) { netif_tx_stop_queue(netif_txq); /* Barrier, so that stop_queue visible to other cpus */ @@ -682,6 +818,12 @@ static enum netdev_tx emac_ndo_start_xmit(struct sk_buff *skb, struct net_device return NETDEV_TX_OK; +cleanup_tx_ts: + if (in_tx_ts) { + dev_kfree_skb_any(emac->tx_ts_skb[tx_ts_cookie]); + emac->tx_ts_skb[tx_ts_cookie] = NULL; + } + drop_free_descs: prueth_xmit_free(tx_chn, first_desc); @@ -694,7 +836,11 @@ drop_free_skb: return ret; -free_desc_stop_q_busy: +free_desc_stop_q_busy_cleanup_tx_ts: + if (in_tx_ts) { + dev_kfree_skb_any(emac->tx_ts_skb[tx_ts_cookie]); + emac->tx_ts_skb[tx_ts_cookie] = NULL; + } prueth_xmit_free(tx_chn, first_desc); drop_stop_q_busy: @@ -717,6 +863,16 @@ static void prueth_tx_cleanup(void *data, dma_addr_t desc_dma) dev_kfree_skb_any(skb); } +static irqreturn_t prueth_tx_ts_irq(int irq, void *dev_id) +{ + struct prueth_emac *emac = dev_id; + + /* currently only TX timestamp is being returned */ + tx_ts_work(emac); + + return IRQ_HANDLED; +} + static irqreturn_t prueth_rx_irq(int irq, void *dev_id) { struct prueth_emac *emac = dev_id; @@ -820,6 +976,18 @@ static void prueth_emac_stop(struct prueth_emac *emac) rproc_shutdown(prueth->pru[slice]); } +static void prueth_cleanup_tx_ts(struct prueth_emac *emac) +{ + int i; + + for (i = 0; i < PRUETH_MAX_TX_TS_REQUESTS; i++) { + if (emac->tx_ts_skb[i]) { + dev_kfree_skb_any(emac->tx_ts_skb[i]); + emac->tx_ts_skb[i] = NULL; + } + } +} + /* called back by PHY layer if there is change in link state of hw port*/ static void emac_adjust_link(struct net_device *ndev) { @@ -881,6 +1049,7 @@ static void emac_adjust_link(struct net_device *ndev) netif_tx_wake_all_queues(ndev); } else { netif_tx_stop_all_queues(ndev); + prueth_cleanup_tx_ts(emac); } } @@ -980,7 +1149,6 @@ static int emac_phy_connect(struct prueth_emac *emac) /* remove unsupported modes */ phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT); - phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT); phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT); phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT); phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_Pause_BIT); @@ -992,6 +1160,139 @@ static int emac_phy_connect(struct prueth_emac *emac) return 0; } +static u64 prueth_iep_gettime(void *clockops_data, struct ptp_system_timestamp *sts) +{ + u32 hi_rollover_count, hi_rollover_count_r; + struct prueth_emac *emac = clockops_data; + struct prueth *prueth = emac->prueth; + void __iomem *fw_hi_r_count_addr; + void __iomem *fw_count_hi_addr; + u32 iepcount_hi, iepcount_hi_r; + unsigned long flags; + u32 iepcount_lo; + u64 ts = 0; + + fw_count_hi_addr = prueth->shram.va + TIMESYNC_FW_WC_COUNT_HI_SW_OFFSET_OFFSET; + fw_hi_r_count_addr = prueth->shram.va + TIMESYNC_FW_WC_HI_ROLLOVER_COUNT_OFFSET; + + local_irq_save(flags); + do { + iepcount_hi = icss_iep_get_count_hi(emac->iep); + iepcount_hi += readl(fw_count_hi_addr); + hi_rollover_count = readl(fw_hi_r_count_addr); + ptp_read_system_prets(sts); + iepcount_lo = icss_iep_get_count_low(emac->iep); + ptp_read_system_postts(sts); + + iepcount_hi_r = icss_iep_get_count_hi(emac->iep); + iepcount_hi_r += readl(fw_count_hi_addr); + hi_rollover_count_r = readl(fw_hi_r_count_addr); + } while ((iepcount_hi_r != iepcount_hi) || + (hi_rollover_count != hi_rollover_count_r)); + local_irq_restore(flags); + + ts = ((u64)hi_rollover_count) << 23 | iepcount_hi; + ts = ts * (u64)IEP_DEFAULT_CYCLE_TIME_NS + iepcount_lo; + + return ts; +} + +static void prueth_iep_settime(void *clockops_data, u64 ns) +{ + struct icssg_setclock_desc __iomem *sc_descp; + struct prueth_emac *emac = clockops_data; + struct icssg_setclock_desc sc_desc; + u64 cyclecount; + u32 cycletime; + int timeout; + + if (!emac->fw_running) + return; + + sc_descp = emac->prueth->shram.va + TIMESYNC_FW_WC_SETCLOCK_DESC_OFFSET; + + cycletime = IEP_DEFAULT_CYCLE_TIME_NS; + cyclecount = ns / cycletime; + + memset(&sc_desc, 0, sizeof(sc_desc)); + sc_desc.margin = cycletime - 1000; + sc_desc.cyclecounter0_set = cyclecount & GENMASK(31, 0); + sc_desc.cyclecounter1_set = (cyclecount & GENMASK(63, 32)) >> 32; + sc_desc.iepcount_set = ns % cycletime; + sc_desc.CMP0_current = cycletime - 4; //Count from 0 to (cycle time)-4 + + memcpy_toio(sc_descp, &sc_desc, sizeof(sc_desc)); + + writeb(1, &sc_descp->request); + + timeout = 5; /* fw should take 2-3 ms */ + while (timeout--) { + if (readb(&sc_descp->acknowledgment)) + return; + + usleep_range(500, 1000); + } + + dev_err(emac->prueth->dev, "settime timeout\n"); +} + +static int prueth_perout_enable(void *clockops_data, + struct ptp_perout_request *req, int on, + u64 *cmp) +{ + struct prueth_emac *emac = clockops_data; + u32 reduction_factor = 0, offset = 0; + struct timespec64 ts; + u64 ns_period; + + if (!on) + return 0; + + /* Any firmware specific stuff for PPS/PEROUT handling */ + ts.tv_sec = req->period.sec; + ts.tv_nsec = req->period.nsec; + ns_period = timespec64_to_ns(&ts); + + /* f/w doesn't support period less than cycle time */ + if (ns_period < IEP_DEFAULT_CYCLE_TIME_NS) + return -ENXIO; + + reduction_factor = ns_period / IEP_DEFAULT_CYCLE_TIME_NS; + offset = ns_period % IEP_DEFAULT_CYCLE_TIME_NS; + + /* f/w requires at least 1uS within a cycle so CMP + * can trigger after SYNC is enabled + */ + if (offset < 5 * NSEC_PER_USEC) + offset = 5 * NSEC_PER_USEC; + + /* if offset is close to cycle time then we will miss + * the CMP event for last tick when IEP rolls over. + * In normal mode, IEP tick is 4ns. + * In slow compensation it could be 0ns or 8ns at + * every slow compensation cycle. + */ + if (offset > IEP_DEFAULT_CYCLE_TIME_NS - 8) + offset = IEP_DEFAULT_CYCLE_TIME_NS - 8; + + /* we're in shadow mode so need to set upper 32-bits */ + *cmp = (u64)offset << 32; + + writel(reduction_factor, emac->prueth->shram.va + + TIMESYNC_FW_WC_SYNCOUT_REDUCTION_FACTOR_OFFSET); + + writel(0, emac->prueth->shram.va + + TIMESYNC_FW_WC_SYNCOUT_START_TIME_CYCLECOUNT_OFFSET); + + return 0; +} + +const struct icss_iep_clockops prueth_iep_clockops = { + .settime = prueth_iep_settime, + .gettime = prueth_iep_gettime, + .perout_enable = prueth_perout_enable, +}; + /** * emac_ndo_open - EMAC device open * @ndev: network adapter device @@ -1066,10 +1367,20 @@ static int emac_ndo_open(struct net_device *ndev) icssg_mii_update_mtu(prueth->mii_rt, slice, ndev->max_mtu); + if (!prueth->emacs_initialized) { + ret = icss_iep_init(emac->iep, &prueth_iep_clockops, + emac, IEP_DEFAULT_CYCLE_TIME_NS); + } + + ret = request_threaded_irq(emac->tx_ts_irq, NULL, prueth_tx_ts_irq, + IRQF_ONESHOT, dev_name(dev), emac); + if (ret) + goto stop; + /* Prepare RX */ ret = prueth_prepare_rx_chan(emac, &emac->rx_chns, PRUETH_MAX_PKT_SIZE); if (ret) - goto stop; + goto free_tx_ts_irq; ret = k3_udma_glue_enable_rx_chn(emac->rx_chns.rx_chn); if (ret) @@ -1102,6 +1413,8 @@ reset_tx_chan: prueth_reset_tx_chan(emac, i, false); reset_rx_chn: prueth_reset_rx_chan(&emac->rx_chns, max_rx_flows, false); +free_tx_ts_irq: + free_irq(emac->tx_ts_irq, emac); stop: prueth_emac_stop(emac); free_rx_irq: @@ -1173,6 +1486,14 @@ static int emac_ndo_stop(struct net_device *ndev) /* stop PRUs */ prueth_emac_stop(emac); + if (prueth->emacs_initialized == 1) + icss_iep_exit(emac->iep); + + /* stop PRUs */ + prueth_emac_stop(emac); + + free_irq(emac->tx_ts_irq, emac); + free_irq(emac->rx_chns.irq[rx_flow], emac); prueth_ndev_del_tx_napi(emac, emac->tx_ch_num); prueth_cleanup_tx_chns(emac); @@ -1235,8 +1556,79 @@ static void emac_ndo_set_rx_mode(struct net_device *ndev) queue_work(emac->cmd_wq, &emac->rx_mode_work); } +static int emac_set_ts_config(struct net_device *ndev, struct ifreq *ifr) +{ + struct prueth_emac *emac = netdev_priv(ndev); + struct hwtstamp_config config; + + if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) + return -EFAULT; + + switch (config.tx_type) { + case HWTSTAMP_TX_OFF: + emac->tx_ts_enabled = 0; + break; + case HWTSTAMP_TX_ON: + emac->tx_ts_enabled = 1; + break; + default: + return -ERANGE; + } + + switch (config.rx_filter) { + case HWTSTAMP_FILTER_NONE: + emac->rx_ts_enabled = 0; + break; + case HWTSTAMP_FILTER_ALL: + case HWTSTAMP_FILTER_SOME: + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: + case HWTSTAMP_FILTER_NTP_ALL: + emac->rx_ts_enabled = 1; + config.rx_filter = HWTSTAMP_FILTER_ALL; + break; + default: + return -ERANGE; + } + + return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? + -EFAULT : 0; +} + +static int emac_get_ts_config(struct net_device *ndev, struct ifreq *ifr) +{ + struct prueth_emac *emac = netdev_priv(ndev); + struct hwtstamp_config config; + + config.flags = 0; + config.tx_type = emac->tx_ts_enabled ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF; + config.rx_filter = emac->rx_ts_enabled ? HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE; + + return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? + -EFAULT : 0; +} + static int emac_ndo_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) { + switch (cmd) { + case SIOCGHWTSTAMP: + return emac_get_ts_config(ndev, ifr); + case SIOCSHWTSTAMP: + return emac_set_ts_config(ndev, ifr); + default: + break; + } + return phy_do_ioctl(ndev, ifr, cmd); } @@ -1316,6 +1708,7 @@ static int prueth_netdev_init(struct prueth *prueth, struct prueth_emac *emac; struct net_device *ndev; enum prueth_port port; + const char *irq_name; enum prueth_mac mac; port = prueth_node_port(eth_node); @@ -1355,6 +1748,15 @@ static int prueth_netdev_init(struct prueth *prueth, emac->tx_ch_num = 1; + irq_name = "tx_ts0"; + if (emac->port_id == PRUETH_PORT_MII1) + irq_name = "tx_ts1"; + emac->tx_ts_irq = platform_get_irq_byname_optional(prueth->pdev, irq_name); + if (emac->tx_ts_irq < 0) { + ret = dev_err_probe(prueth->dev, emac->tx_ts_irq, "could not get tx_ts_irq\n"); + goto free; + } + SET_NETDEV_DEV(ndev, prueth->dev); spin_lock_init(&emac->lock); mutex_init(&emac->cmd_lock); @@ -1680,14 +2082,38 @@ static int prueth_probe(struct platform_device *pdev) dev_dbg(dev, "sram: pa %llx va %p size %zx\n", prueth->msmcram.pa, prueth->msmcram.va, prueth->msmcram.size); + prueth->iep0 = icss_iep_get_idx(np, 0); + if (IS_ERR(prueth->iep0)) { + ret = dev_err_probe(dev, PTR_ERR(prueth->iep0), "iep0 get failed\n"); + prueth->iep0 = NULL; + goto free_pool; + } + + prueth->iep1 = icss_iep_get_idx(np, 1); + if (IS_ERR(prueth->iep1)) { + ret = dev_err_probe(dev, PTR_ERR(prueth->iep1), "iep1 get failed\n"); + icss_iep_put(prueth->iep0); + prueth->iep0 = NULL; + prueth->iep1 = NULL; + goto free_pool; + } + + if (prueth->pdata.quirk_10m_link_issue) { + /* Enable IEP1 for FW in 64bit mode as W/A for 10M FD link detect issue under TX + * traffic. + */ + icss_iep_init_fw(prueth->iep1); + } + /* setup netdev interfaces */ if (eth0_node) { ret = prueth_netdev_init(prueth, eth0_node); if (ret) { dev_err_probe(dev, ret, "netdev init %s failed\n", eth0_node->name); - goto netdev_exit; + goto exit_iep; } + prueth->emac[PRUETH_MAC0]->iep = prueth->iep0; } if (eth1_node) { @@ -1697,6 +2123,8 @@ static int prueth_probe(struct platform_device *pdev) eth1_node->name); goto netdev_exit; } + + prueth->emac[PRUETH_MAC1]->iep = prueth->iep0; } /* register the network devices */ @@ -1754,6 +2182,11 @@ netdev_exit: prueth_netdev_exit(prueth, eth_node); } +exit_iep: + if (prueth->pdata.quirk_10m_link_issue) + icss_iep_exit_fw(prueth->iep1); + +free_pool: gen_pool_free(prueth->sram_pool, (unsigned long)prueth->msmcram.va, msmc_ram_size); @@ -1798,6 +2231,12 @@ static void prueth_remove(struct platform_device *pdev) prueth_netdev_exit(prueth, eth_node); } + if (prueth->pdata.quirk_10m_link_issue) + icss_iep_exit_fw(prueth->iep1); + + icss_iep_put(prueth->iep1); + icss_iep_put(prueth->iep0); + gen_pool_free(prueth->sram_pool, (unsigned long)prueth->msmcram.va, MSMC_RAM_SIZE); diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h index a8ce4d01ef16..3fe80a8758d3 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h @@ -35,6 +35,7 @@ #include <net/devlink.h> #include "icssg_config.h" +#include "icss_iep.h" #include "icssg_switch_map.h" #define PRUETH_MAX_MTU (2000 - ETH_HLEN - ETH_FCS_LEN) @@ -122,6 +123,8 @@ struct prueth_rx_chn { */ #define PRUETH_MAX_TX_QUEUES 4 +#define PRUETH_MAX_TX_TS_REQUESTS 50 /* Max simultaneous TX_TS requests */ + /* data for each emac port */ struct prueth_emac { bool fw_running; @@ -139,6 +142,9 @@ struct prueth_emac { struct device_node *phy_node; phy_interface_t phy_if; enum prueth_port port_id; + struct icss_iep *iep; + unsigned int rx_ts_enabled : 1; + unsigned int tx_ts_enabled : 1; /* DMA related */ struct prueth_tx_chn tx_chns[PRUETH_MAX_TX_QUEUES]; @@ -150,7 +156,15 @@ struct prueth_emac { spinlock_t lock; /* serialize access */ - unsigned long state; + /* TX HW Timestamping */ + /* TX TS cookie will be index to the tx_ts_skb array */ + struct sk_buff *tx_ts_skb[PRUETH_MAX_TX_TS_REQUESTS]; + atomic_t tx_ts_pending; + int tx_ts_irq; + + u8 cmd_seq; + /* shutdown related */ + u32 cmd_data[4]; struct completion cmd_complete; /* Mutex to serialize access to firmware command interface */ struct mutex cmd_lock; @@ -193,6 +207,8 @@ struct prueth_pdata { * @pdata: pointer to platform data for ICSSG driver * @icssg_hwcmdseq: seq counter or HWQ messages * @emacs_initialized: num of EMACs/ext ports that are up/running + * @iep0: pointer to IEP0 device + * @iep1: pointer to IEP1 device */ struct prueth { struct device *dev; @@ -214,8 +230,16 @@ struct prueth { struct platform_device *pdev; struct prueth_pdata pdata; u8 icssg_hwcmdseq; - int emacs_initialized; + struct icss_iep *iep0; + struct icss_iep *iep1; +}; + +struct emac_tx_ts_response { + u32 reserved[2]; + u32 cookie; + u32 lo_ts; + u32 hi_ts; }; /* get PRUSS SLICE number from prueth_emac */ diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index bb234cf0cea0..332c853ca99b 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -9832,6 +9832,7 @@ static const struct usb_device_id rtl8152_table[] = { { USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041) }, { USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff) }, { USB_DEVICE(VENDOR_ID_TPLINK, 0x0601) }, + { USB_DEVICE(VENDOR_ID_DLINK, 0xb301) }, {} }; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h index 6eef6bc430e2..9d248ba1c0b2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h @@ -442,7 +442,12 @@ struct brcmf_scan_params_v2_le { * fixed parameter portion is assumed, otherwise * ssid in the fixed portion is ignored */ - __le16 channel_list[1]; /* list of chanspecs */ + union { + __le16 padding; /* Reserve space for at least 1 entry for abort + * which uses an on stack brcmf_scan_params_v2_le + */ + DECLARE_FLEX_ARRAY(__le16, channel_list); /* chanspecs */ + }; }; struct brcmf_scan_results { @@ -702,7 +707,7 @@ struct brcmf_sta_info_le { struct brcmf_chanspec_list { __le32 count; /* # of entries */ - __le32 element[1]; /* variable length uint32 list */ + __le32 element[]; /* variable length uint32 list */ }; /* diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index f5e08988dc7b..06d6f7f66430 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -310,9 +310,9 @@ struct iwl_fw_ini_fifo_hdr { struct iwl_fw_ini_error_dump_range { __le32 range_data_size; union { - __le32 internal_base_addr; - __le64 dram_base_addr; - __le32 page_num; + __le32 internal_base_addr __packed; + __le64 dram_base_addr __packed; + __le32 page_num __packed; struct iwl_fw_ini_fifo_hdr fifo_hdr; struct iwl_cmd_header fw_pkt_hdr; }; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 5c719636c9bd..a5348b015310 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -819,7 +819,7 @@ out: mvm->nvm_data->bands[0].n_channels = 1; mvm->nvm_data->bands[0].n_bitrates = 1; mvm->nvm_data->bands[0].bitrates = - (void *)((u8 *)mvm->nvm_data->channels + 1); + (void *)(mvm->nvm_data->channels + 1); mvm->nvm_data->bands[0].bitrates->hw_value = 10; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c index 5449deb3c2d6..46e207211f21 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c @@ -731,73 +731,78 @@ static void iwl_mvm_mld_vif_cfg_changed_station(struct iwl_mvm *mvm, mvmvif->associated = vif->cfg.assoc; - if (!(changes & BSS_CHANGED_ASSOC)) - return; - - if (vif->cfg.assoc) { - /* clear statistics to get clean beacon counter */ - iwl_mvm_request_statistics(mvm, true); - iwl_mvm_sf_update(mvm, vif, false); - iwl_mvm_power_vif_assoc(mvm, vif); - - for_each_mvm_vif_valid_link(mvmvif, i) { - memset(&mvmvif->link[i]->beacon_stats, 0, - sizeof(mvmvif->link[i]->beacon_stats)); + if (changes & BSS_CHANGED_ASSOC) { + if (vif->cfg.assoc) { + /* clear statistics to get clean beacon counter */ + iwl_mvm_request_statistics(mvm, true); + iwl_mvm_sf_update(mvm, vif, false); + iwl_mvm_power_vif_assoc(mvm, vif); + + for_each_mvm_vif_valid_link(mvmvif, i) { + memset(&mvmvif->link[i]->beacon_stats, 0, + sizeof(mvmvif->link[i]->beacon_stats)); + + if (vif->p2p) { + iwl_mvm_update_smps(mvm, vif, + IWL_MVM_SMPS_REQ_PROT, + IEEE80211_SMPS_DYNAMIC, i); + } + + rcu_read_lock(); + link_conf = rcu_dereference(vif->link_conf[i]); + if (link_conf && !link_conf->dtim_period) + protect = true; + rcu_read_unlock(); + } - if (vif->p2p) { - iwl_mvm_update_smps(mvm, vif, - IWL_MVM_SMPS_REQ_PROT, - IEEE80211_SMPS_DYNAMIC, i); + if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && + protect) { + /* If we're not restarting and still haven't + * heard a beacon (dtim period unknown) then + * make sure we still have enough minimum time + * remaining in the time event, since the auth + * might actually have taken quite a while + * (especially for SAE) and so the remaining + * time could be small without us having heard + * a beacon yet. + */ + iwl_mvm_protect_assoc(mvm, vif, 0); } - rcu_read_lock(); - link_conf = rcu_dereference(vif->link_conf[i]); - if (link_conf && !link_conf->dtim_period) - protect = true; - rcu_read_unlock(); - } + iwl_mvm_sf_update(mvm, vif, false); + + /* FIXME: need to decide about misbehaving AP handling */ + iwl_mvm_power_vif_assoc(mvm, vif); + } else if (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) { + iwl_mvm_mei_host_disassociated(mvm); - if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) && - protect) { - /* If we're not restarting and still haven't - * heard a beacon (dtim period unknown) then - * make sure we still have enough minimum time - * remaining in the time event, since the auth - * might actually have taken quite a while - * (especially for SAE) and so the remaining - * time could be small without us having heard - * a beacon yet. + /* If update fails - SF might be running in associated + * mode while disassociated - which is forbidden. */ - iwl_mvm_protect_assoc(mvm, vif, 0); + ret = iwl_mvm_sf_update(mvm, vif, false); + WARN_ONCE(ret && + !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, + &mvm->status), + "Failed to update SF upon disassociation\n"); + + /* If we get an assert during the connection (after the + * station has been added, but before the vif is set + * to associated), mac80211 will re-add the station and + * then configure the vif. Since the vif is not + * associated, we would remove the station here and + * this would fail the recovery. + */ + iwl_mvm_mld_vif_delete_all_stas(mvm, vif); } - iwl_mvm_sf_update(mvm, vif, false); - - /* FIXME: need to decide about misbehaving AP handling */ - iwl_mvm_power_vif_assoc(mvm, vif); - } else if (iwl_mvm_mld_vif_have_valid_ap_sta(mvmvif)) { - iwl_mvm_mei_host_disassociated(mvm); - - /* If update fails - SF might be running in associated - * mode while disassociated - which is forbidden. - */ - ret = iwl_mvm_sf_update(mvm, vif, false); - WARN_ONCE(ret && - !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, - &mvm->status), - "Failed to update SF upon disassociation\n"); - - /* If we get an assert during the connection (after the - * station has been added, but before the vif is set - * to associated), mac80211 will re-add the station and - * then configure the vif. Since the vif is not - * associated, we would remove the station here and - * this would fail the recovery. - */ - iwl_mvm_mld_vif_delete_all_stas(mvm, vif); + iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes); } - iwl_mvm_bss_info_changed_station_assoc(mvm, vif, changes); + if (changes & BSS_CHANGED_PS) { + ret = iwl_mvm_power_update_mac(mvm); + if (ret) + IWL_ERR(mvm, "failed to update power mode\n"); + } } static void diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index c1d9ce753468..3cbe2c0b8d6b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -2342,7 +2342,7 @@ iwl_mvm_scan_umac_fill_general_p_v12(struct iwl_mvm *mvm, if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2) gp->num_of_fragments[SCAN_HB_LMAC_IDX] = IWL_SCAN_NUM_OF_FRAGS; - if (version < 12) { + if (version < 16) { gp->scan_start_mac_or_link_id = scan_vif->id; } else { struct iwl_mvm_vif_link_info *link_info; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index ec18e348553d..674ddf951b79 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -1636,6 +1636,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, iwl_trans_free_tx_cmd(mvm->trans, info->driver_data[1]); memset(&info->status, 0, sizeof(info->status)); + info->flags &= ~(IEEE80211_TX_STAT_ACK | IEEE80211_TX_STAT_TX_FILTERED); /* inform mac80211 about what happened with the frame */ switch (status & TX_STATUS_MSK) { @@ -1988,6 +1989,8 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid, */ if (!is_flush) info->flags |= IEEE80211_TX_STAT_ACK; + else + info->flags &= ~IEEE80211_TX_STAT_ACK; } /* diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c index 391793a16adc..10690e82358b 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c @@ -918,9 +918,17 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv, mwifiex_dbg_dump(priv->adapter, EVT_D, "RXBA_SYNC event:", event_buf, len); - while (tlv_buf_left >= sizeof(*tlv_rxba)) { + while (tlv_buf_left > sizeof(*tlv_rxba)) { tlv_type = le16_to_cpu(tlv_rxba->header.type); tlv_len = le16_to_cpu(tlv_rxba->header.len); + if (size_add(sizeof(tlv_rxba->header), tlv_len) > tlv_buf_left) { + mwifiex_dbg(priv->adapter, WARN, + "TLV size (%zu) overflows event_buf buf_left=%d\n", + size_add(sizeof(tlv_rxba->header), tlv_len), + tlv_buf_left); + return; + } + if (tlv_type != TLV_TYPE_RXBA_SYNC) { mwifiex_dbg(priv->adapter, ERROR, "Wrong TLV id=0x%x\n", tlv_type); @@ -929,6 +937,14 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv, tlv_seq_num = le16_to_cpu(tlv_rxba->seq_num); tlv_bitmap_len = le16_to_cpu(tlv_rxba->bitmap_len); + if (size_add(sizeof(*tlv_rxba), tlv_bitmap_len) > tlv_buf_left) { + mwifiex_dbg(priv->adapter, WARN, + "TLV size (%zu) overflows event_buf buf_left=%d\n", + size_add(sizeof(*tlv_rxba), tlv_bitmap_len), + tlv_buf_left); + return; + } + mwifiex_dbg(priv->adapter, INFO, "%pM tid=%d seq_num=%d bitmap_len=%d\n", tlv_rxba->mac, tlv_rxba->tid, tlv_seq_num, @@ -965,8 +981,8 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv, } } - tlv_buf_left -= (sizeof(*tlv_rxba) + tlv_len); - tmp = (u8 *)tlv_rxba + tlv_len + sizeof(*tlv_rxba); + tlv_buf_left -= (sizeof(tlv_rxba->header) + tlv_len); + tmp = (u8 *)tlv_rxba + sizeof(tlv_rxba->header) + tlv_len; tlv_rxba = (struct mwifiex_ie_types_rxba_sync *)tmp; } } diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index f2168fac95ed..8e6db904e5b2 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -779,7 +779,7 @@ struct mwifiex_ie_types_rxba_sync { u8 reserved; __le16 seq_num; __le16 bitmap_len; - u8 bitmap[1]; + u8 bitmap[]; } __packed; struct chan_band_param_set { diff --git a/drivers/net/wireless/marvell/mwifiex/sta_rx.c b/drivers/net/wireless/marvell/mwifiex/sta_rx.c index 65420ad67416..257737137cd7 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_rx.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_rx.c @@ -86,7 +86,8 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length); rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off; - if (sizeof(*rx_pkt_hdr) + rx_pkt_off > skb->len) { + if (sizeof(rx_pkt_hdr->eth803_hdr) + sizeof(rfc1042_header) + + rx_pkt_off > skb->len) { mwifiex_dbg(priv->adapter, ERROR, "wrong rx packet offset: len=%d, rx_pkt_off=%d\n", skb->len, rx_pkt_off); @@ -95,12 +96,13 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, return -1; } - if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, - sizeof(bridge_tunnel_header))) || - (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, - sizeof(rfc1042_header)) && - ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP && - ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) { + if (sizeof(*rx_pkt_hdr) + rx_pkt_off <= skb->len && + ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, + sizeof(bridge_tunnel_header))) || + (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, + sizeof(rfc1042_header)) && + ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP && + ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX))) { /* * Replace the 803 header and rfc1042 header (llc/snap) with an * EthernetII header, keep the src/dst and snap_type diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 05d9ab3ce819..dc8f4e157eb2 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -93,13 +93,13 @@ __mt76_get_rxwi(struct mt76_dev *dev) { struct mt76_txwi_cache *t = NULL; - spin_lock(&dev->wed_lock); + spin_lock_bh(&dev->wed_lock); if (!list_empty(&dev->rxwi_cache)) { t = list_first_entry(&dev->rxwi_cache, struct mt76_txwi_cache, list); list_del(&t->list); } - spin_unlock(&dev->wed_lock); + spin_unlock_bh(&dev->wed_lock); return t; } @@ -145,9 +145,9 @@ mt76_put_rxwi(struct mt76_dev *dev, struct mt76_txwi_cache *t) if (!t) return; - spin_lock(&dev->wed_lock); + spin_lock_bh(&dev->wed_lock); list_add(&t->list, &dev->rxwi_cache); - spin_unlock(&dev->wed_lock); + spin_unlock_bh(&dev->wed_lock); } EXPORT_SYMBOL_GPL(mt76_put_rxwi); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c index 0acabba2d1a5..5d402cf2951c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c @@ -131,15 +131,8 @@ u8 mt76x02_get_lna_gain(struct mt76x02_dev *dev, s8 *lna_2g, s8 *lna_5g, struct ieee80211_channel *chan) { - u16 val; u8 lna; - val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1); - if (val & MT_EE_NIC_CONF_1_LNA_EXT_2G) - *lna_2g = 0; - if (val & MT_EE_NIC_CONF_1_LNA_EXT_5G) - memset(lna_5g, 0, sizeof(s8) * 3); - if (chan->band == NL80211_BAND_2GHZ) lna = *lna_2g; else if (chan->hw_value <= 64) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c index d5809408d1d3..8c01855885ce 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c @@ -256,7 +256,8 @@ void mt76x2_read_rx_gain(struct mt76x02_dev *dev) struct ieee80211_channel *chan = dev->mphy.chandef.chan; int channel = chan->hw_value; s8 lna_5g[3], lna_2g; - u8 lna; + bool use_lna; + u8 lna = 0; u16 val; if (chan->band == NL80211_BAND_2GHZ) @@ -275,7 +276,15 @@ void mt76x2_read_rx_gain(struct mt76x02_dev *dev) dev->cal.rx.mcu_gain |= (lna_5g[1] & 0xff) << 16; dev->cal.rx.mcu_gain |= (lna_5g[2] & 0xff) << 24; - lna = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan); + val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1); + if (chan->band == NL80211_BAND_2GHZ) + use_lna = !(val & MT_EE_NIC_CONF_1_LNA_EXT_2G); + else + use_lna = !(val & MT_EE_NIC_CONF_1_LNA_EXT_5G); + + if (use_lna) + lna = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan); + dev->cal.rx.lna_gain = mt76x02_sign_extend(lna, 8); } EXPORT_SYMBOL_GPL(mt76x2_read_rx_gain); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h index 3642a2c7f80c..2434e2480cbe 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h @@ -46,6 +46,7 @@ struct rtw8723du_efuse { u8 vender_id[2]; /* 0x100 */ u8 product_id[2]; /* 0x102 */ u8 usb_option; /* 0x104 */ + u8 res5[2]; /* 0x105 */ u8 mac_addr[ETH_ALEN]; /* 0x107 */ }; diff --git a/drivers/opp/core.c b/drivers/opp/core.c index 3f46e499d615..919cc53bc02e 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c @@ -177,25 +177,24 @@ unsigned long dev_pm_opp_get_power(struct dev_pm_opp *opp) EXPORT_SYMBOL_GPL(dev_pm_opp_get_power); /** - * dev_pm_opp_get_freq() - Gets the frequency corresponding to an available opp - * @opp: opp for which frequency has to be returned for + * dev_pm_opp_get_freq_indexed() - Gets the frequency corresponding to an + * available opp with specified index + * @opp: opp for which frequency has to be returned for + * @index: index of the frequency within the required opp * - * Return: frequency in hertz corresponding to the opp, else - * return 0 + * Return: frequency in hertz corresponding to the opp with specified index, + * else return 0 */ -unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp) +unsigned long dev_pm_opp_get_freq_indexed(struct dev_pm_opp *opp, u32 index) { - if (IS_ERR_OR_NULL(opp)) { + if (IS_ERR_OR_NULL(opp) || index >= opp->opp_table->clk_count) { pr_err("%s: Invalid parameters\n", __func__); return 0; } - if (!assert_single_clk(opp->opp_table)) - return 0; - - return opp->rates[0]; + return opp->rates[index]; } -EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq); +EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq_indexed); /** * dev_pm_opp_get_level() - Gets the level corresponding to an available opp @@ -227,20 +226,18 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_level); unsigned int dev_pm_opp_get_required_pstate(struct dev_pm_opp *opp, unsigned int index) { - struct opp_table *opp_table = opp->opp_table; - if (IS_ERR_OR_NULL(opp) || !opp->available || - index >= opp_table->required_opp_count) { + index >= opp->opp_table->required_opp_count) { pr_err("%s: Invalid parameters\n", __func__); return 0; } /* required-opps not fully initialized yet */ - if (lazy_linking_pending(opp_table)) + if (lazy_linking_pending(opp->opp_table)) return 0; /* The required OPP table must belong to a genpd */ - if (unlikely(!opp_table->required_opp_tables[index]->is_genpd)) { + if (unlikely(!opp->opp_table->required_opp_tables[index]->is_genpd)) { pr_err("%s: Performance state is only valid for genpds.\n", __func__); return 0; } @@ -450,7 +447,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_count); /* Helpers to read keys */ static unsigned long _read_freq(struct dev_pm_opp *opp, int index) { - return opp->rates[0]; + return opp->rates[index]; } static unsigned long _read_level(struct dev_pm_opp *opp, int index) @@ -626,6 +623,34 @@ struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev, } EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact); +/** + * dev_pm_opp_find_freq_exact_indexed() - Search for an exact freq for the + * clock corresponding to the index + * @dev: Device for which we do this operation + * @freq: frequency to search for + * @index: Clock index + * @available: true/false - match for available opp + * + * Search for the matching exact OPP for the clock corresponding to the + * specified index from a starting freq for a device. + * + * Return: matching *opp , else returns ERR_PTR in case of error and should be + * handled using IS_ERR. Error return values can be: + * EINVAL: for bad pointer + * ERANGE: no match found for search + * ENODEV: if device not found in list of registered devices + * + * The callers are required to call dev_pm_opp_put() for the returned OPP after + * use. + */ +struct dev_pm_opp * +dev_pm_opp_find_freq_exact_indexed(struct device *dev, unsigned long freq, + u32 index, bool available) +{ + return _find_key_exact(dev, freq, index, available, _read_freq, NULL); +} +EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact_indexed); + static noinline struct dev_pm_opp *_find_freq_ceil(struct opp_table *opp_table, unsigned long *freq) { @@ -659,6 +684,34 @@ struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev, EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil); /** + * dev_pm_opp_find_freq_ceil_indexed() - Search for a rounded ceil freq for the + * clock corresponding to the index + * @dev: Device for which we do this operation + * @freq: Start frequency + * @index: Clock index + * + * Search for the matching ceil *available* OPP for the clock corresponding to + * the specified index from a starting freq for a device. + * + * Return: matching *opp and refreshes *freq accordingly, else returns + * ERR_PTR in case of error and should be handled using IS_ERR. Error return + * values can be: + * EINVAL: for bad pointer + * ERANGE: no match found for search + * ENODEV: if device not found in list of registered devices + * + * The callers are required to call dev_pm_opp_put() for the returned OPP after + * use. + */ +struct dev_pm_opp * +dev_pm_opp_find_freq_ceil_indexed(struct device *dev, unsigned long *freq, + u32 index) +{ + return _find_key_ceil(dev, freq, index, true, _read_freq, NULL); +} +EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil_indexed); + +/** * dev_pm_opp_find_freq_floor() - Search for a rounded floor freq * @dev: device for which we do this operation * @freq: Start frequency @@ -684,6 +737,34 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev, EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor); /** + * dev_pm_opp_find_freq_floor_indexed() - Search for a rounded floor freq for the + * clock corresponding to the index + * @dev: Device for which we do this operation + * @freq: Start frequency + * @index: Clock index + * + * Search for the matching floor *available* OPP for the clock corresponding to + * the specified index from a starting freq for a device. + * + * Return: matching *opp and refreshes *freq accordingly, else returns + * ERR_PTR in case of error and should be handled using IS_ERR. Error return + * values can be: + * EINVAL: for bad pointer + * ERANGE: no match found for search + * ENODEV: if device not found in list of registered devices + * + * The callers are required to call dev_pm_opp_put() for the returned OPP after + * use. + */ +struct dev_pm_opp * +dev_pm_opp_find_freq_floor_indexed(struct device *dev, unsigned long *freq, + u32 index) +{ + return _find_key_floor(dev, freq, index, true, _read_freq, NULL); +} +EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor_indexed); + +/** * dev_pm_opp_find_level_exact() - search for an exact level * @dev: device for which we do this operation * @level: level to search for @@ -2379,7 +2460,7 @@ static int _opp_attach_genpd(struct opp_table *opp_table, struct device *dev, virt_dev = dev_pm_domain_attach_by_name(dev, *name); if (IS_ERR_OR_NULL(virt_dev)) { - ret = PTR_ERR(virt_dev) ? : -ENODEV; + ret = virt_dev ? PTR_ERR(virt_dev) : -ENODEV; dev_err(dev, "Couldn't attach to pm_domain: %d\n", ret); goto err; } diff --git a/drivers/opp/cpu.c b/drivers/opp/cpu.c index 3c3506021501..12c429b407ca 100644 --- a/drivers/opp/cpu.c +++ b/drivers/opp/cpu.c @@ -24,7 +24,7 @@ /** * dev_pm_opp_init_cpufreq_table() - create a cpufreq table for a device * @dev: device for which we do this operation - * @table: Cpufreq table returned back to caller + * @opp_table: Cpufreq table returned back to caller * * Generate a cpufreq table for a provided device- this assumes that the * opp table is already initialized and ready for usage. @@ -89,7 +89,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_init_cpufreq_table); /** * dev_pm_opp_free_cpufreq_table() - free the cpufreq table * @dev: device for which we do this operation - * @table: table to free + * @opp_table: table to free * * Free up the table allocated by dev_pm_opp_init_cpufreq_table */ diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig index f4572a5cca72..273d67ecf6d2 100644 --- a/drivers/perf/Kconfig +++ b/drivers/perf/Kconfig @@ -92,7 +92,7 @@ config ARM_PMU_ACPI config ARM_SMMU_V3_PMU tristate "ARM SMMUv3 Performance Monitors Extension" - depends on (ARM64 && ACPI) || (COMPILE_TEST && 64BIT) + depends on ARM64 || (COMPILE_TEST && 64BIT) depends on GENERIC_MSI_IRQ help Provides support for the ARM SMMUv3 Performance Monitor Counter diff --git a/drivers/perf/alibaba_uncore_drw_pmu.c b/drivers/perf/alibaba_uncore_drw_pmu.c index 5c5be9fc1b15..19d459a36be5 100644 --- a/drivers/perf/alibaba_uncore_drw_pmu.c +++ b/drivers/perf/alibaba_uncore_drw_pmu.c @@ -236,10 +236,37 @@ static const struct attribute_group ali_drw_pmu_cpumask_attr_group = { .attrs = ali_drw_pmu_cpumask_attrs, }; +static ssize_t ali_drw_pmu_identifier_show(struct device *dev, + struct device_attribute *attr, + char *page) +{ + return sysfs_emit(page, "%s\n", "ali_drw_pmu"); +} + +static umode_t ali_drw_pmu_identifier_attr_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + return attr->mode; +} + +static struct device_attribute ali_drw_pmu_identifier_attr = + __ATTR(identifier, 0444, ali_drw_pmu_identifier_show, NULL); + +static struct attribute *ali_drw_pmu_identifier_attrs[] = { + &ali_drw_pmu_identifier_attr.attr, + NULL +}; + +static const struct attribute_group ali_drw_pmu_identifier_attr_group = { + .attrs = ali_drw_pmu_identifier_attrs, + .is_visible = ali_drw_pmu_identifier_attr_visible +}; + static const struct attribute_group *ali_drw_pmu_attr_groups[] = { &ali_drw_pmu_events_attr_group, &ali_drw_pmu_cpumask_attr_group, &ali_drw_pmu_format_group, + &ali_drw_pmu_identifier_attr_group, NULL, }; diff --git a/drivers/perf/amlogic/meson_ddr_pmu_core.c b/drivers/perf/amlogic/meson_ddr_pmu_core.c index 0b24dee1ed3c..bbc7285fd934 100644 --- a/drivers/perf/amlogic/meson_ddr_pmu_core.c +++ b/drivers/perf/amlogic/meson_ddr_pmu_core.c @@ -9,8 +9,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> #include <linux/perf_event.h> #include <linux/platform_device.h> #include <linux/printk.h> diff --git a/drivers/perf/arm-cci.c b/drivers/perf/arm-cci.c index 998259f1d973..61de861eaf91 100644 --- a/drivers/perf/arm-cci.c +++ b/drivers/perf/arm-cci.c @@ -7,10 +7,7 @@ #include <linux/io.h> #include <linux/interrupt.h> #include <linux/module.h> -#include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> -#include <linux/of_platform.h> +#include <linux/of.h> #include <linux/perf_event.h> #include <linux/platform_device.h> #include <linux/slab.h> diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c index b8c15878bc86..913dc04b3a40 100644 --- a/drivers/perf/arm-cmn.c +++ b/drivers/perf/arm-cmn.c @@ -72,6 +72,8 @@ /* For most nodes, this is all there is */ #define CMN_PMU_EVENT_SEL 0x000 #define CMN__PMU_CBUSY_SNTHROTTLE_SEL GENMASK_ULL(44, 42) +#define CMN__PMU_SN_HOME_SEL GENMASK_ULL(40, 39) +#define CMN__PMU_HBT_LBT_SEL GENMASK_ULL(38, 37) #define CMN__PMU_CLASS_OCCUP_ID GENMASK_ULL(36, 35) /* Technically this is 4 bits wide on DNs, but we only use 2 there anyway */ #define CMN__PMU_OCCUP1_ID GENMASK_ULL(34, 32) @@ -226,6 +228,7 @@ enum cmn_revision { REV_CMN700_R0P0 = 0, REV_CMN700_R1P0, REV_CMN700_R2P0, + REV_CMN700_R3P0, REV_CI700_R0P0 = 0, REV_CI700_R1P0, REV_CI700_R2P0, @@ -254,6 +257,9 @@ enum cmn_node_type { CMN_TYPE_CCHA, CMN_TYPE_CCLA, CMN_TYPE_CCLA_RNI, + CMN_TYPE_HNS = 0x200, + CMN_TYPE_HNS_MPAM_S, + CMN_TYPE_HNS_MPAM_NS, /* Not a real node type */ CMN_TYPE_WP = 0x7770 }; @@ -263,6 +269,8 @@ enum cmn_filter_select { SEL_OCCUP1ID, SEL_CLASS_OCCUP_ID, SEL_CBUSY_SNTHROTTLE_SEL, + SEL_HBT_LBT_SEL, + SEL_SN_HOME_SEL, SEL_MAX }; @@ -742,8 +750,8 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj, _CMN_EVENT_ATTR(_model, dn_##_name, CMN_TYPE_DVM, _event, _occup, _fsel) #define CMN_EVENT_DTC(_name) \ CMN_EVENT_ATTR(CMN_ANY, dtc_##_name, CMN_TYPE_DTC, 0) -#define _CMN_EVENT_HNF(_model, _name, _event, _occup, _fsel) \ - _CMN_EVENT_ATTR(_model, hnf_##_name, CMN_TYPE_HNF, _event, _occup, _fsel) +#define CMN_EVENT_HNF(_model, _name, _event) \ + CMN_EVENT_ATTR(_model, hnf_##_name, CMN_TYPE_HNF, _event) #define CMN_EVENT_HNI(_name, _event) \ CMN_EVENT_ATTR(CMN_ANY, hni_##_name, CMN_TYPE_HNI, _event) #define CMN_EVENT_HNP(_name, _event) \ @@ -768,6 +776,8 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj, CMN_EVENT_ATTR(CMN_ANY, ccla_##_name, CMN_TYPE_CCLA, _event) #define CMN_EVENT_CCLA_RNI(_name, _event) \ CMN_EVENT_ATTR(CMN_ANY, ccla_rni_##_name, CMN_TYPE_CCLA_RNI, _event) +#define CMN_EVENT_HNS(_name, _event) \ + CMN_EVENT_ATTR(CMN_ANY, hns_##_name, CMN_TYPE_HNS, _event) #define CMN_EVENT_DVM(_model, _name, _event) \ _CMN_EVENT_DVM(_model, _name, _event, 0, SEL_NONE) @@ -775,32 +785,68 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj, _CMN_EVENT_DVM(_model, _name##_all, _event, 0, SEL_OCCUP1ID), \ _CMN_EVENT_DVM(_model, _name##_dvmop, _event, 1, SEL_OCCUP1ID), \ _CMN_EVENT_DVM(_model, _name##_dvmsync, _event, 2, SEL_OCCUP1ID) -#define CMN_EVENT_HNF(_model, _name, _event) \ - _CMN_EVENT_HNF(_model, _name, _event, 0, SEL_NONE) + +#define CMN_EVENT_HN_OCC(_model, _name, _type, _event) \ + _CMN_EVENT_ATTR(_model, _name##_all, _type, _event, 0, SEL_OCCUP1ID), \ + _CMN_EVENT_ATTR(_model, _name##_read, _type, _event, 1, SEL_OCCUP1ID), \ + _CMN_EVENT_ATTR(_model, _name##_write, _type, _event, 2, SEL_OCCUP1ID), \ + _CMN_EVENT_ATTR(_model, _name##_atomic, _type, _event, 3, SEL_OCCUP1ID), \ + _CMN_EVENT_ATTR(_model, _name##_stash, _type, _event, 4, SEL_OCCUP1ID) +#define CMN_EVENT_HN_CLS(_model, _name, _type, _event) \ + _CMN_EVENT_ATTR(_model, _name##_class0, _type, _event, 0, SEL_CLASS_OCCUP_ID), \ + _CMN_EVENT_ATTR(_model, _name##_class1, _type, _event, 1, SEL_CLASS_OCCUP_ID), \ + _CMN_EVENT_ATTR(_model, _name##_class2, _type, _event, 2, SEL_CLASS_OCCUP_ID), \ + _CMN_EVENT_ATTR(_model, _name##_class3, _type, _event, 3, SEL_CLASS_OCCUP_ID) +#define CMN_EVENT_HN_SNT(_model, _name, _type, _event) \ + _CMN_EVENT_ATTR(_model, _name##_all, _type, _event, 0, SEL_CBUSY_SNTHROTTLE_SEL), \ + _CMN_EVENT_ATTR(_model, _name##_group0_read, _type, _event, 1, SEL_CBUSY_SNTHROTTLE_SEL), \ + _CMN_EVENT_ATTR(_model, _name##_group0_write, _type, _event, 2, SEL_CBUSY_SNTHROTTLE_SEL), \ + _CMN_EVENT_ATTR(_model, _name##_group1_read, _type, _event, 3, SEL_CBUSY_SNTHROTTLE_SEL), \ + _CMN_EVENT_ATTR(_model, _name##_group1_write, _type, _event, 4, SEL_CBUSY_SNTHROTTLE_SEL), \ + _CMN_EVENT_ATTR(_model, _name##_read, _type, _event, 5, SEL_CBUSY_SNTHROTTLE_SEL), \ + _CMN_EVENT_ATTR(_model, _name##_write, _type, _event, 6, SEL_CBUSY_SNTHROTTLE_SEL) + +#define CMN_EVENT_HNF_OCC(_model, _name, _event) \ + CMN_EVENT_HN_OCC(_model, hnf_##_name, CMN_TYPE_HNF, _event) #define CMN_EVENT_HNF_CLS(_model, _name, _event) \ - _CMN_EVENT_HNF(_model, _name##_class0, _event, 0, SEL_CLASS_OCCUP_ID), \ - _CMN_EVENT_HNF(_model, _name##_class1, _event, 1, SEL_CLASS_OCCUP_ID), \ - _CMN_EVENT_HNF(_model, _name##_class2, _event, 2, SEL_CLASS_OCCUP_ID), \ - _CMN_EVENT_HNF(_model, _name##_class3, _event, 3, SEL_CLASS_OCCUP_ID) + CMN_EVENT_HN_CLS(_model, hnf_##_name, CMN_TYPE_HNS, _event) #define CMN_EVENT_HNF_SNT(_model, _name, _event) \ - _CMN_EVENT_HNF(_model, _name##_all, _event, 0, SEL_CBUSY_SNTHROTTLE_SEL), \ - _CMN_EVENT_HNF(_model, _name##_group0_read, _event, 1, SEL_CBUSY_SNTHROTTLE_SEL), \ - _CMN_EVENT_HNF(_model, _name##_group0_write, _event, 2, SEL_CBUSY_SNTHROTTLE_SEL), \ - _CMN_EVENT_HNF(_model, _name##_group1_read, _event, 3, SEL_CBUSY_SNTHROTTLE_SEL), \ - _CMN_EVENT_HNF(_model, _name##_group1_write, _event, 4, SEL_CBUSY_SNTHROTTLE_SEL), \ - _CMN_EVENT_HNF(_model, _name##_read, _event, 5, SEL_CBUSY_SNTHROTTLE_SEL), \ - _CMN_EVENT_HNF(_model, _name##_write, _event, 6, SEL_CBUSY_SNTHROTTLE_SEL) - -#define _CMN_EVENT_XP(_name, _event) \ + CMN_EVENT_HN_SNT(_model, hnf_##_name, CMN_TYPE_HNF, _event) + +#define CMN_EVENT_HNS_OCC(_name, _event) \ + CMN_EVENT_HN_OCC(CMN_ANY, hns_##_name, CMN_TYPE_HNS, _event), \ + _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_rxsnp, CMN_TYPE_HNS, _event, 5, SEL_OCCUP1ID), \ + _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_lbt, CMN_TYPE_HNS, _event, 6, SEL_OCCUP1ID), \ + _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_hbt, CMN_TYPE_HNS, _event, 7, SEL_OCCUP1ID) +#define CMN_EVENT_HNS_CLS( _name, _event) \ + CMN_EVENT_HN_CLS(CMN_ANY, hns_##_name, CMN_TYPE_HNS, _event) +#define CMN_EVENT_HNS_SNT(_name, _event) \ + CMN_EVENT_HN_SNT(CMN_ANY, hns_##_name, CMN_TYPE_HNS, _event) +#define CMN_EVENT_HNS_HBT(_name, _event) \ + _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_all, CMN_TYPE_HNS, _event, 0, SEL_HBT_LBT_SEL), \ + _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_hbt, CMN_TYPE_HNS, _event, 1, SEL_HBT_LBT_SEL), \ + _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_lbt, CMN_TYPE_HNS, _event, 2, SEL_HBT_LBT_SEL) +#define CMN_EVENT_HNS_SNH(_name, _event) \ + _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_all, CMN_TYPE_HNS, _event, 0, SEL_SN_HOME_SEL), \ + _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_sn, CMN_TYPE_HNS, _event, 1, SEL_SN_HOME_SEL), \ + _CMN_EVENT_ATTR(CMN_ANY, hns_##_name##_home, CMN_TYPE_HNS, _event, 2, SEL_SN_HOME_SEL) + +#define _CMN_EVENT_XP_MESH(_name, _event) \ __CMN_EVENT_XP(e_##_name, (_event) | (0 << 2)), \ __CMN_EVENT_XP(w_##_name, (_event) | (1 << 2)), \ __CMN_EVENT_XP(n_##_name, (_event) | (2 << 2)), \ - __CMN_EVENT_XP(s_##_name, (_event) | (3 << 2)), \ + __CMN_EVENT_XP(s_##_name, (_event) | (3 << 2)) + +#define _CMN_EVENT_XP_PORT(_name, _event) \ __CMN_EVENT_XP(p0_##_name, (_event) | (4 << 2)), \ __CMN_EVENT_XP(p1_##_name, (_event) | (5 << 2)), \ __CMN_EVENT_XP(p2_##_name, (_event) | (6 << 2)), \ __CMN_EVENT_XP(p3_##_name, (_event) | (7 << 2)) +#define _CMN_EVENT_XP(_name, _event) \ + _CMN_EVENT_XP_MESH(_name, _event), \ + _CMN_EVENT_XP_PORT(_name, _event) + /* Good thing there are only 3 fundamental XP events... */ #define CMN_EVENT_XP(_name, _event) \ _CMN_EVENT_XP(req_##_name, (_event) | (0 << 5)), \ @@ -813,6 +859,10 @@ static umode_t arm_cmn_event_attr_is_visible(struct kobject *kobj, _CMN_EVENT_XP(snp2_##_name, (_event) | (7 << 5)), \ _CMN_EVENT_XP(req2_##_name, (_event) | (8 << 5)) +#define CMN_EVENT_XP_DAT(_name, _event) \ + _CMN_EVENT_XP_PORT(dat_##_name, (_event) | (3 << 5)), \ + _CMN_EVENT_XP_PORT(dat2_##_name, (_event) | (6 << 5)) + static struct attribute *arm_cmn_event_attrs[] = { CMN_EVENT_DTC(cycles), @@ -862,11 +912,7 @@ static struct attribute *arm_cmn_event_attrs[] = { CMN_EVENT_HNF(CMN_ANY, mc_retries, 0x0c), CMN_EVENT_HNF(CMN_ANY, mc_reqs, 0x0d), CMN_EVENT_HNF(CMN_ANY, qos_hh_retry, 0x0e), - _CMN_EVENT_HNF(CMN_ANY, qos_pocq_occupancy_all, 0x0f, 0, SEL_OCCUP1ID), - _CMN_EVENT_HNF(CMN_ANY, qos_pocq_occupancy_read, 0x0f, 1, SEL_OCCUP1ID), - _CMN_EVENT_HNF(CMN_ANY, qos_pocq_occupancy_write, 0x0f, 2, SEL_OCCUP1ID), - _CMN_EVENT_HNF(CMN_ANY, qos_pocq_occupancy_atomic, 0x0f, 3, SEL_OCCUP1ID), - _CMN_EVENT_HNF(CMN_ANY, qos_pocq_occupancy_stash, 0x0f, 4, SEL_OCCUP1ID), + CMN_EVENT_HNF_OCC(CMN_ANY, qos_pocq_occupancy, 0x0f), CMN_EVENT_HNF(CMN_ANY, pocq_addrhaz, 0x10), CMN_EVENT_HNF(CMN_ANY, pocq_atomic_addrhaz, 0x11), CMN_EVENT_HNF(CMN_ANY, ld_st_swp_adq_full, 0x12), @@ -943,7 +989,7 @@ static struct attribute *arm_cmn_event_attrs[] = { CMN_EVENT_XP(txflit_valid, 0x01), CMN_EVENT_XP(txflit_stall, 0x02), - CMN_EVENT_XP(partial_dat_flit, 0x03), + CMN_EVENT_XP_DAT(partial_dat_flit, 0x03), /* We treat watchpoints as a special made-up class of XP events */ CMN_EVENT_ATTR(CMN_ANY, watchpoint_up, CMN_TYPE_WP, CMN_WP_UP), CMN_EVENT_ATTR(CMN_ANY, watchpoint_down, CMN_TYPE_WP, CMN_WP_DOWN), @@ -1132,6 +1178,66 @@ static struct attribute *arm_cmn_event_attrs[] = { CMN_EVENT_CCLA(pfwd_sndr_stalls_static_crd, 0x2a), CMN_EVENT_CCLA(pfwd_sndr_stalls_dynmaic_crd, 0x2b), + CMN_EVENT_HNS_HBT(cache_miss, 0x01), + CMN_EVENT_HNS_HBT(slc_sf_cache_access, 0x02), + CMN_EVENT_HNS_HBT(cache_fill, 0x03), + CMN_EVENT_HNS_HBT(pocq_retry, 0x04), + CMN_EVENT_HNS_HBT(pocq_reqs_recvd, 0x05), + CMN_EVENT_HNS_HBT(sf_hit, 0x06), + CMN_EVENT_HNS_HBT(sf_evictions, 0x07), + CMN_EVENT_HNS(dir_snoops_sent, 0x08), + CMN_EVENT_HNS(brd_snoops_sent, 0x09), + CMN_EVENT_HNS_HBT(slc_eviction, 0x0a), + CMN_EVENT_HNS_HBT(slc_fill_invalid_way, 0x0b), + CMN_EVENT_HNS(mc_retries_local, 0x0c), + CMN_EVENT_HNS_SNH(mc_reqs_local, 0x0d), + CMN_EVENT_HNS(qos_hh_retry, 0x0e), + CMN_EVENT_HNS_OCC(qos_pocq_occupancy, 0x0f), + CMN_EVENT_HNS(pocq_addrhaz, 0x10), + CMN_EVENT_HNS(pocq_atomic_addrhaz, 0x11), + CMN_EVENT_HNS(ld_st_swp_adq_full, 0x12), + CMN_EVENT_HNS(cmp_adq_full, 0x13), + CMN_EVENT_HNS(txdat_stall, 0x14), + CMN_EVENT_HNS(txrsp_stall, 0x15), + CMN_EVENT_HNS(seq_full, 0x16), + CMN_EVENT_HNS(seq_hit, 0x17), + CMN_EVENT_HNS(snp_sent, 0x18), + CMN_EVENT_HNS(sfbi_dir_snp_sent, 0x19), + CMN_EVENT_HNS(sfbi_brd_snp_sent, 0x1a), + CMN_EVENT_HNS(intv_dirty, 0x1c), + CMN_EVENT_HNS(stash_snp_sent, 0x1d), + CMN_EVENT_HNS(stash_data_pull, 0x1e), + CMN_EVENT_HNS(snp_fwded, 0x1f), + CMN_EVENT_HNS(atomic_fwd, 0x20), + CMN_EVENT_HNS(mpam_hardlim, 0x21), + CMN_EVENT_HNS(mpam_softlim, 0x22), + CMN_EVENT_HNS(snp_sent_cluster, 0x23), + CMN_EVENT_HNS(sf_imprecise_evict, 0x24), + CMN_EVENT_HNS(sf_evict_shared_line, 0x25), + CMN_EVENT_HNS_CLS(pocq_class_occup, 0x26), + CMN_EVENT_HNS_CLS(pocq_class_retry, 0x27), + CMN_EVENT_HNS_CLS(class_mc_reqs_local, 0x28), + CMN_EVENT_HNS_CLS(class_cgnt_cmin, 0x29), + CMN_EVENT_HNS_SNT(sn_throttle, 0x2a), + CMN_EVENT_HNS_SNT(sn_throttle_min, 0x2b), + CMN_EVENT_HNS(sf_precise_to_imprecise, 0x2c), + CMN_EVENT_HNS(snp_intv_cln, 0x2d), + CMN_EVENT_HNS(nc_excl, 0x2e), + CMN_EVENT_HNS(excl_mon_ovfl, 0x2f), + CMN_EVENT_HNS(snp_req_recvd, 0x30), + CMN_EVENT_HNS(snp_req_byp_pocq, 0x31), + CMN_EVENT_HNS(dir_ccgha_snp_sent, 0x32), + CMN_EVENT_HNS(brd_ccgha_snp_sent, 0x33), + CMN_EVENT_HNS(ccgha_snp_stall, 0x34), + CMN_EVENT_HNS(lbt_req_hardlim, 0x35), + CMN_EVENT_HNS(hbt_req_hardlim, 0x36), + CMN_EVENT_HNS(sf_reupdate, 0x37), + CMN_EVENT_HNS(excl_sf_imprecise, 0x38), + CMN_EVENT_HNS(snp_pocq_addrhaz, 0x39), + CMN_EVENT_HNS(mc_retries_remote, 0x3a), + CMN_EVENT_HNS_SNH(mc_reqs_remote, 0x3b), + CMN_EVENT_HNS_CLS(class_mc_reqs_remote, 0x3c), + NULL }; @@ -1373,6 +1479,10 @@ static int arm_cmn_set_event_sel_hi(struct arm_cmn_node *dn, dn->occupid[fsel].val = occupid; reg = FIELD_PREP(CMN__PMU_CBUSY_SNTHROTTLE_SEL, dn->occupid[SEL_CBUSY_SNTHROTTLE_SEL].val) | + FIELD_PREP(CMN__PMU_SN_HOME_SEL, + dn->occupid[SEL_SN_HOME_SEL].val) | + FIELD_PREP(CMN__PMU_HBT_LBT_SEL, + dn->occupid[SEL_HBT_LBT_SEL].val) | FIELD_PREP(CMN__PMU_CLASS_OCCUP_ID, dn->occupid[SEL_CLASS_OCCUP_ID].val) | FIELD_PREP(CMN__PMU_OCCUP1_ID, @@ -2200,6 +2310,7 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset) case CMN_TYPE_CCRA: case CMN_TYPE_CCHA: case CMN_TYPE_CCLA: + case CMN_TYPE_HNS: dn++; break; /* Nothing to see here */ @@ -2207,6 +2318,8 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset) case CMN_TYPE_MPAM_NS: case CMN_TYPE_RNSAM: case CMN_TYPE_CXLA: + case CMN_TYPE_HNS_MPAM_S: + case CMN_TYPE_HNS_MPAM_NS: break; /* * Split "optimised" combination nodes into separate diff --git a/drivers/perf/arm_dmc620_pmu.c b/drivers/perf/arm_dmc620_pmu.c index 9d0f01c4455a..30cea6859574 100644 --- a/drivers/perf/arm_dmc620_pmu.c +++ b/drivers/perf/arm_dmc620_pmu.c @@ -66,8 +66,13 @@ #define DMC620_PMU_COUNTERn_OFFSET(n) \ (DMC620_PMU_COUNTERS_BASE + 0x28 * (n)) -static LIST_HEAD(dmc620_pmu_irqs); +/* + * dmc620_pmu_irqs_lock: protects dmc620_pmu_irqs list + * dmc620_pmu_node_lock: protects pmus_node lists in all dmc620_pmu instances + */ static DEFINE_MUTEX(dmc620_pmu_irqs_lock); +static DEFINE_MUTEX(dmc620_pmu_node_lock); +static LIST_HEAD(dmc620_pmu_irqs); struct dmc620_pmu_irq { struct hlist_node node; @@ -475,9 +480,9 @@ static int dmc620_pmu_get_irq(struct dmc620_pmu *dmc620_pmu, int irq_num) return PTR_ERR(irq); dmc620_pmu->irq = irq; - mutex_lock(&dmc620_pmu_irqs_lock); + mutex_lock(&dmc620_pmu_node_lock); list_add_rcu(&dmc620_pmu->pmus_node, &irq->pmus_node); - mutex_unlock(&dmc620_pmu_irqs_lock); + mutex_unlock(&dmc620_pmu_node_lock); return 0; } @@ -486,9 +491,11 @@ static void dmc620_pmu_put_irq(struct dmc620_pmu *dmc620_pmu) { struct dmc620_pmu_irq *irq = dmc620_pmu->irq; - mutex_lock(&dmc620_pmu_irqs_lock); + mutex_lock(&dmc620_pmu_node_lock); list_del_rcu(&dmc620_pmu->pmus_node); + mutex_unlock(&dmc620_pmu_node_lock); + mutex_lock(&dmc620_pmu_irqs_lock); if (!refcount_dec_and_test(&irq->refcount)) { mutex_unlock(&dmc620_pmu_irqs_lock); return; @@ -638,10 +645,10 @@ static int dmc620_pmu_cpu_teardown(unsigned int cpu, return 0; /* We're only reading, but this isn't the place to be involving RCU */ - mutex_lock(&dmc620_pmu_irqs_lock); + mutex_lock(&dmc620_pmu_node_lock); list_for_each_entry(dmc620_pmu, &irq->pmus_node, pmus_node) perf_pmu_migrate_context(&dmc620_pmu->pmu, irq->cpu, target); - mutex_unlock(&dmc620_pmu_irqs_lock); + mutex_unlock(&dmc620_pmu_node_lock); WARN_ON(irq_set_affinity(irq->irq_num, cpumask_of(target))); irq->cpu = target; diff --git a/drivers/perf/arm_dsu_pmu.c b/drivers/perf/arm_dsu_pmu.c index fe2abb412c00..8223c49bd082 100644 --- a/drivers/perf/arm_dsu_pmu.c +++ b/drivers/perf/arm_dsu_pmu.c @@ -20,7 +20,7 @@ #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/perf_event.h> #include <linux/platform_device.h> #include <linux/spinlock.h> diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c index f6ccb2cd4dfc..d712a19e47ac 100644 --- a/drivers/perf/arm_pmu.c +++ b/drivers/perf/arm_pmu.c @@ -877,11 +877,13 @@ struct arm_pmu *armpmu_alloc(void) .attr_groups = pmu->attr_groups, /* * This is a CPU PMU potentially in a heterogeneous - * configuration (e.g. big.LITTLE). This is not an uncore PMU, - * and we have taken ctx sharing into account (e.g. with our - * pmu::filter callback and pmu::event_init group validation). + * configuration (e.g. big.LITTLE) so + * PERF_PMU_CAP_EXTENDED_HW_TYPE is required to open + * PERF_TYPE_HARDWARE and PERF_TYPE_HW_CACHE events on a + * specific PMU. */ - .capabilities = PERF_PMU_CAP_HETEROGENEOUS_CPUS | PERF_PMU_CAP_EXTENDED_REGS, + .capabilities = PERF_PMU_CAP_EXTENDED_REGS | + PERF_PMU_CAP_EXTENDED_HW_TYPE, }; pmu->attr_groups[ARMPMU_ATTR_GROUP_COMMON] = diff --git a/drivers/perf/arm_pmu_acpi.c b/drivers/perf/arm_pmu_acpi.c index 90815ad762eb..05dda19c5359 100644 --- a/drivers/perf/arm_pmu_acpi.c +++ b/drivers/perf/arm_pmu_acpi.c @@ -69,6 +69,62 @@ static void arm_pmu_acpi_unregister_irq(int cpu) acpi_unregister_gsi(gsi); } +static int __maybe_unused +arm_acpi_register_pmu_device(struct platform_device *pdev, u8 len, + u16 (*parse_gsi)(struct acpi_madt_generic_interrupt *)) +{ + int cpu, this_hetid, hetid, irq, ret; + u16 this_gsi = 0, gsi = 0; + + /* + * Ensure that platform device must have IORESOURCE_IRQ + * resource to hold gsi interrupt. + */ + if (pdev->num_resources != 1) + return -ENXIO; + + if (pdev->resource[0].flags != IORESOURCE_IRQ) + return -ENXIO; + + /* + * Sanity check all the GICC tables for the same interrupt + * number. For now, only support homogeneous ACPI machines. + */ + for_each_possible_cpu(cpu) { + struct acpi_madt_generic_interrupt *gicc; + + gicc = acpi_cpu_get_madt_gicc(cpu); + if (gicc->header.length < len) + return gsi ? -ENXIO : 0; + + this_gsi = parse_gsi(gicc); + this_hetid = find_acpi_cpu_topology_hetero_id(cpu); + if (!gsi) { + hetid = this_hetid; + gsi = this_gsi; + } else if (hetid != this_hetid || gsi != this_gsi) { + pr_warn("ACPI: %s: must be homogeneous\n", pdev->name); + return -ENXIO; + } + } + + if (!this_gsi) + return 0; + + irq = acpi_register_gsi(NULL, gsi, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH); + if (irq < 0) { + pr_warn("ACPI: %s Unable to register interrupt: %d\n", pdev->name, gsi); + return -ENXIO; + } + + pdev->resource[0].start = irq; + ret = platform_device_register(pdev); + if (ret) + acpi_unregister_gsi(gsi); + + return ret; +} + #if IS_ENABLED(CONFIG_ARM_SPE_PMU) static struct resource spe_resources[] = { { @@ -84,6 +140,11 @@ static struct platform_device spe_dev = { .num_resources = ARRAY_SIZE(spe_resources) }; +static u16 arm_spe_parse_gsi(struct acpi_madt_generic_interrupt *gicc) +{ + return gicc->spe_interrupt; +} + /* * For lack of a better place, hook the normal PMU MADT walk * and create a SPE device if we detect a recent MADT with @@ -91,53 +152,50 @@ static struct platform_device spe_dev = { */ static void arm_spe_acpi_register_device(void) { - int cpu, hetid, irq, ret; - bool first = true; - u16 gsi = 0; - - /* - * Sanity check all the GICC tables for the same interrupt number. - * For now, we only support homogeneous ACPI/SPE machines. - */ - for_each_possible_cpu(cpu) { - struct acpi_madt_generic_interrupt *gicc; + int ret = arm_acpi_register_pmu_device(&spe_dev, ACPI_MADT_GICC_SPE, + arm_spe_parse_gsi); + if (ret) + pr_warn("ACPI: SPE: Unable to register device\n"); +} +#else +static inline void arm_spe_acpi_register_device(void) +{ +} +#endif /* CONFIG_ARM_SPE_PMU */ - gicc = acpi_cpu_get_madt_gicc(cpu); - if (gicc->header.length < ACPI_MADT_GICC_SPE) - return; - - if (first) { - gsi = gicc->spe_interrupt; - if (!gsi) - return; - hetid = find_acpi_cpu_topology_hetero_id(cpu); - first = false; - } else if ((gsi != gicc->spe_interrupt) || - (hetid != find_acpi_cpu_topology_hetero_id(cpu))) { - pr_warn("ACPI: SPE must be homogeneous\n"); - return; - } +#if IS_ENABLED(CONFIG_CORESIGHT_TRBE) +static struct resource trbe_resources[] = { + { + /* irq */ + .flags = IORESOURCE_IRQ, } +}; - irq = acpi_register_gsi(NULL, gsi, ACPI_LEVEL_SENSITIVE, - ACPI_ACTIVE_HIGH); - if (irq < 0) { - pr_warn("ACPI: SPE Unable to register interrupt: %d\n", gsi); - return; - } +static struct platform_device trbe_dev = { + .name = ARMV8_TRBE_PDEV_NAME, + .id = -1, + .resource = trbe_resources, + .num_resources = ARRAY_SIZE(trbe_resources) +}; - spe_resources[0].start = irq; - ret = platform_device_register(&spe_dev); - if (ret < 0) { - pr_warn("ACPI: SPE: Unable to register device\n"); - acpi_unregister_gsi(gsi); - } +static u16 arm_trbe_parse_gsi(struct acpi_madt_generic_interrupt *gicc) +{ + return gicc->trbe_interrupt; +} + +static void arm_trbe_acpi_register_device(void) +{ + int ret = arm_acpi_register_pmu_device(&trbe_dev, ACPI_MADT_GICC_TRBE, + arm_trbe_parse_gsi); + if (ret) + pr_warn("ACPI: TRBE: Unable to register device\n"); } #else -static inline void arm_spe_acpi_register_device(void) +static inline void arm_trbe_acpi_register_device(void) { + } -#endif /* CONFIG_ARM_SPE_PMU */ +#endif /* CONFIG_CORESIGHT_TRBE */ static int arm_pmu_acpi_parse_irqs(void) { @@ -374,6 +432,7 @@ static int arm_pmu_acpi_init(void) return 0; arm_spe_acpi_register_device(); + arm_trbe_acpi_register_device(); return 0; } diff --git a/drivers/perf/arm_pmu_platform.c b/drivers/perf/arm_pmu_platform.c index 933b96e243b8..3596db36cbff 100644 --- a/drivers/perf/arm_pmu_platform.c +++ b/drivers/perf/arm_pmu_platform.c @@ -16,7 +16,6 @@ #include <linux/irqdesc.h> #include <linux/kconfig.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/percpu.h> #include <linux/perf/arm_pmu.h> #include <linux/platform_device.h> diff --git a/drivers/perf/arm_pmuv3.c b/drivers/perf/arm_pmuv3.c index 08b3a1bf0ef6..e5a2ac4155f6 100644 --- a/drivers/perf/arm_pmuv3.c +++ b/drivers/perf/arm_pmuv3.c @@ -721,38 +721,15 @@ static void armv8pmu_enable_event(struct perf_event *event) * Enable counter and interrupt, and set the counter to count * the event that we're interested in. */ - - /* - * Disable counter - */ armv8pmu_disable_event_counter(event); - - /* - * Set event. - */ armv8pmu_write_event_type(event); - - /* - * Enable interrupt for this counter - */ armv8pmu_enable_event_irq(event); - - /* - * Enable counter - */ armv8pmu_enable_event_counter(event); } static void armv8pmu_disable_event(struct perf_event *event) { - /* - * Disable counter - */ armv8pmu_disable_event_counter(event); - - /* - * Disable interrupt for this counter - */ armv8pmu_disable_event_irq(event); } @@ -1266,9 +1243,14 @@ PMUV3_INIT_SIMPLE(armv8_cortex_a76) PMUV3_INIT_SIMPLE(armv8_cortex_a77) PMUV3_INIT_SIMPLE(armv8_cortex_a78) PMUV3_INIT_SIMPLE(armv9_cortex_a510) +PMUV3_INIT_SIMPLE(armv9_cortex_a520) PMUV3_INIT_SIMPLE(armv9_cortex_a710) +PMUV3_INIT_SIMPLE(armv9_cortex_a715) +PMUV3_INIT_SIMPLE(armv9_cortex_a720) PMUV3_INIT_SIMPLE(armv8_cortex_x1) PMUV3_INIT_SIMPLE(armv9_cortex_x2) +PMUV3_INIT_SIMPLE(armv9_cortex_x3) +PMUV3_INIT_SIMPLE(armv9_cortex_x4) PMUV3_INIT_SIMPLE(armv8_neoverse_e1) PMUV3_INIT_SIMPLE(armv8_neoverse_n1) PMUV3_INIT_SIMPLE(armv9_neoverse_n2) @@ -1334,9 +1316,14 @@ static const struct of_device_id armv8_pmu_of_device_ids[] = { {.compatible = "arm,cortex-a77-pmu", .data = armv8_cortex_a77_pmu_init}, {.compatible = "arm,cortex-a78-pmu", .data = armv8_cortex_a78_pmu_init}, {.compatible = "arm,cortex-a510-pmu", .data = armv9_cortex_a510_pmu_init}, + {.compatible = "arm,cortex-a520-pmu", .data = armv9_cortex_a520_pmu_init}, {.compatible = "arm,cortex-a710-pmu", .data = armv9_cortex_a710_pmu_init}, + {.compatible = "arm,cortex-a715-pmu", .data = armv9_cortex_a715_pmu_init}, + {.compatible = "arm,cortex-a720-pmu", .data = armv9_cortex_a720_pmu_init}, {.compatible = "arm,cortex-x1-pmu", .data = armv8_cortex_x1_pmu_init}, {.compatible = "arm,cortex-x2-pmu", .data = armv9_cortex_x2_pmu_init}, + {.compatible = "arm,cortex-x3-pmu", .data = armv9_cortex_x3_pmu_init}, + {.compatible = "arm,cortex-x4-pmu", .data = armv9_cortex_x4_pmu_init}, {.compatible = "arm,neoverse-e1-pmu", .data = armv8_neoverse_e1_pmu_init}, {.compatible = "arm,neoverse-n1-pmu", .data = armv8_neoverse_n1_pmu_init}, {.compatible = "arm,neoverse-n2-pmu", .data = armv9_neoverse_n2_pmu_init}, diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c index 25a269d431e4..6303b82566f9 100644 --- a/drivers/perf/arm_smmuv3_pmu.c +++ b/drivers/perf/arm_smmuv3_pmu.c @@ -115,6 +115,7 @@ #define SMMU_PMCG_PA_SHIFT 12 #define SMMU_PMCG_EVCNTR_RDONLY BIT(0) +#define SMMU_PMCG_HARDEN_DISABLE BIT(1) static int cpuhp_state_num; @@ -159,6 +160,20 @@ static inline void smmu_pmu_enable(struct pmu *pmu) writel(SMMU_PMCG_CR_ENABLE, smmu_pmu->reg_base + SMMU_PMCG_CR); } +static int smmu_pmu_apply_event_filter(struct smmu_pmu *smmu_pmu, + struct perf_event *event, int idx); + +static inline void smmu_pmu_enable_quirk_hip08_09(struct pmu *pmu) +{ + struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu); + unsigned int idx; + + for_each_set_bit(idx, smmu_pmu->used_counters, smmu_pmu->num_counters) + smmu_pmu_apply_event_filter(smmu_pmu, smmu_pmu->events[idx], idx); + + smmu_pmu_enable(pmu); +} + static inline void smmu_pmu_disable(struct pmu *pmu) { struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu); @@ -167,6 +182,22 @@ static inline void smmu_pmu_disable(struct pmu *pmu) writel(0, smmu_pmu->reg_base + SMMU_PMCG_IRQ_CTRL); } +static inline void smmu_pmu_disable_quirk_hip08_09(struct pmu *pmu) +{ + struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu); + unsigned int idx; + + /* + * The global disable of PMU sometimes fail to stop the counting. + * Harden this by writing an invalid event type to each used counter + * to forcibly stop counting. + */ + for_each_set_bit(idx, smmu_pmu->used_counters, smmu_pmu->num_counters) + writel(0xffff, smmu_pmu->reg_base + SMMU_PMCG_EVTYPER(idx)); + + smmu_pmu_disable(pmu); +} + static inline void smmu_pmu_counter_set_value(struct smmu_pmu *smmu_pmu, u32 idx, u64 value) { @@ -765,7 +796,10 @@ static void smmu_pmu_get_acpi_options(struct smmu_pmu *smmu_pmu) switch (model) { case IORT_SMMU_V3_PMCG_HISI_HIP08: /* HiSilicon Erratum 162001800 */ - smmu_pmu->options |= SMMU_PMCG_EVCNTR_RDONLY; + smmu_pmu->options |= SMMU_PMCG_EVCNTR_RDONLY | SMMU_PMCG_HARDEN_DISABLE; + break; + case IORT_SMMU_V3_PMCG_HISI_HIP09: + smmu_pmu->options |= SMMU_PMCG_HARDEN_DISABLE; break; } @@ -890,6 +924,16 @@ static int smmu_pmu_probe(struct platform_device *pdev) if (!dev->of_node) smmu_pmu_get_acpi_options(smmu_pmu); + /* + * For platforms suffer this quirk, the PMU disable sometimes fails to + * stop the counters. This will leads to inaccurate or error counting. + * Forcibly disable the counters with these quirk handler. + */ + if (smmu_pmu->options & SMMU_PMCG_HARDEN_DISABLE) { + smmu_pmu->pmu.pmu_enable = smmu_pmu_enable_quirk_hip08_09; + smmu_pmu->pmu.pmu_disable = smmu_pmu_disable_quirk_hip08_09; + } + /* Pick one CPU to be the preferred one to use */ smmu_pmu->on_cpu = raw_smp_processor_id(); WARN_ON(irq_set_affinity(smmu_pmu->irq, cpumask_of(smmu_pmu->on_cpu))); @@ -984,6 +1028,7 @@ static void __exit arm_smmu_pmu_exit(void) module_exit(arm_smmu_pmu_exit); +MODULE_ALIAS("platform:arm-smmu-v3-pmcg"); MODULE_DESCRIPTION("PMU driver for ARM SMMUv3 Performance Monitors Extension"); MODULE_AUTHOR("Neil Leeder <nleeder@codeaurora.org>"); MODULE_AUTHOR("Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>"); diff --git a/drivers/perf/arm_spe_pmu.c b/drivers/perf/arm_spe_pmu.c index b9ba4c4fe5a2..d2b0cbf0e0c4 100644 --- a/drivers/perf/arm_spe_pmu.c +++ b/drivers/perf/arm_spe_pmu.c @@ -25,8 +25,7 @@ #include <linux/kernel.h> #include <linux/list.h> #include <linux/module.h> -#include <linux/of_address.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/perf_event.h> #include <linux/perf/arm_pmu.h> #include <linux/platform_device.h> diff --git a/drivers/perf/fsl_imx8_ddr_perf.c b/drivers/perf/fsl_imx8_ddr_perf.c index 5222ba1e79d0..92611c98120f 100644 --- a/drivers/perf/fsl_imx8_ddr_perf.c +++ b/drivers/perf/fsl_imx8_ddr_perf.c @@ -10,10 +10,9 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/perf_event.h> +#include <linux/platform_device.h> #include <linux/slab.h> #define COUNTER_CNTL 0x0 @@ -28,6 +27,8 @@ #define CNTL_CLEAR_MASK 0xFFFFFFFD #define CNTL_OVER_MASK 0xFFFFFFFE +#define CNTL_CP_SHIFT 16 +#define CNTL_CP_MASK (0xFF << CNTL_CP_SHIFT) #define CNTL_CSV_SHIFT 24 #define CNTL_CSV_MASK (0xFFU << CNTL_CSV_SHIFT) @@ -35,6 +36,8 @@ #define EVENT_CYCLES_COUNTER 0 #define NUM_COUNTERS 4 +/* For removing bias if cycle counter CNTL.CP is set to 0xf0 */ +#define CYCLES_COUNTER_MASK 0x0FFFFFFF #define AXI_MASKING_REVERT 0xffff0000 /* AXI_MASKING(MSB 16bits) + AXI_ID(LSB 16bits) */ #define to_ddr_pmu(p) container_of(p, struct ddr_pmu, pmu) @@ -101,6 +104,7 @@ struct ddr_pmu { const struct fsl_ddr_devtype_data *devtype_data; int irq; int id; + int active_counter; }; static ssize_t ddr_perf_identifier_show(struct device *dev, @@ -427,6 +431,17 @@ static void ddr_perf_counter_enable(struct ddr_pmu *pmu, int config, writel(0, pmu->base + reg); val = CNTL_EN | CNTL_CLEAR; val |= FIELD_PREP(CNTL_CSV_MASK, config); + + /* + * On i.MX8MP we need to bias the cycle counter to overflow more often. + * We do this by initializing bits [23:16] of the counter value via the + * COUNTER_CTRL Counter Parameter (CP) field. + */ + if (pmu->devtype_data->quirks & DDR_CAP_AXI_ID_FILTER_ENHANCED) { + if (counter == EVENT_CYCLES_COUNTER) + val |= FIELD_PREP(CNTL_CP_MASK, 0xf0); + } + writel(val, pmu->base + reg); } else { /* Disable counter */ @@ -466,6 +481,12 @@ static void ddr_perf_event_update(struct perf_event *event) int ret; new_raw_count = ddr_perf_read_counter(pmu, counter); + /* Remove the bias applied in ddr_perf_counter_enable(). */ + if (pmu->devtype_data->quirks & DDR_CAP_AXI_ID_FILTER_ENHANCED) { + if (counter == EVENT_CYCLES_COUNTER) + new_raw_count &= CYCLES_COUNTER_MASK; + } + local64_add(new_raw_count, &event->count); /* @@ -495,6 +516,10 @@ static void ddr_perf_event_start(struct perf_event *event, int flags) ddr_perf_counter_enable(pmu, event->attr.config, counter, true); + if (!pmu->active_counter++) + ddr_perf_counter_enable(pmu, EVENT_CYCLES_ID, + EVENT_CYCLES_COUNTER, true); + hwc->state = 0; } @@ -548,6 +573,10 @@ static void ddr_perf_event_stop(struct perf_event *event, int flags) ddr_perf_counter_enable(pmu, event->attr.config, counter, false); ddr_perf_event_update(event); + if (!--pmu->active_counter) + ddr_perf_counter_enable(pmu, EVENT_CYCLES_ID, + EVENT_CYCLES_COUNTER, false); + hwc->state |= PERF_HES_STOPPED; } @@ -565,25 +594,10 @@ static void ddr_perf_event_del(struct perf_event *event, int flags) static void ddr_perf_pmu_enable(struct pmu *pmu) { - struct ddr_pmu *ddr_pmu = to_ddr_pmu(pmu); - - /* enable cycle counter if cycle is not active event list */ - if (ddr_pmu->events[EVENT_CYCLES_COUNTER] == NULL) - ddr_perf_counter_enable(ddr_pmu, - EVENT_CYCLES_ID, - EVENT_CYCLES_COUNTER, - true); } static void ddr_perf_pmu_disable(struct pmu *pmu) { - struct ddr_pmu *ddr_pmu = to_ddr_pmu(pmu); - - if (ddr_pmu->events[EVENT_CYCLES_COUNTER] == NULL) - ddr_perf_counter_enable(ddr_pmu, - EVENT_CYCLES_ID, - EVENT_CYCLES_COUNTER, - false); } static int ddr_perf_init(struct ddr_pmu *pmu, void __iomem *base, diff --git a/drivers/perf/fsl_imx9_ddr_perf.c b/drivers/perf/fsl_imx9_ddr_perf.c index 71d5b07e3aff..5cf770a1bc31 100644 --- a/drivers/perf/fsl_imx9_ddr_perf.c +++ b/drivers/perf/fsl_imx9_ddr_perf.c @@ -7,9 +7,7 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> +#include <linux/platform_device.h> #include <linux/perf_event.h> /* Performance monitor configuration */ diff --git a/drivers/perf/hisilicon/hisi_pcie_pmu.c b/drivers/perf/hisilicon/hisi_pcie_pmu.c index e10fc7cb9493..5a00adb2de8c 100644 --- a/drivers/perf/hisilicon/hisi_pcie_pmu.c +++ b/drivers/perf/hisilicon/hisi_pcie_pmu.c @@ -665,8 +665,8 @@ static int hisi_pcie_pmu_online_cpu(unsigned int cpu, struct hlist_node *node) struct hisi_pcie_pmu *pcie_pmu = hlist_entry_safe(node, struct hisi_pcie_pmu, node); if (pcie_pmu->on_cpu == -1) { - pcie_pmu->on_cpu = cpu; - WARN_ON(irq_set_affinity(pcie_pmu->irq, cpumask_of(cpu))); + pcie_pmu->on_cpu = cpumask_local_spread(0, dev_to_node(&pcie_pmu->pdev->dev)); + WARN_ON(irq_set_affinity(pcie_pmu->irq, cpumask_of(pcie_pmu->on_cpu))); } return 0; @@ -676,14 +676,23 @@ static int hisi_pcie_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node) { struct hisi_pcie_pmu *pcie_pmu = hlist_entry_safe(node, struct hisi_pcie_pmu, node); unsigned int target; + cpumask_t mask; + int numa_node; /* Nothing to do if this CPU doesn't own the PMU */ if (pcie_pmu->on_cpu != cpu) return 0; pcie_pmu->on_cpu = -1; - /* Choose a new CPU from all online cpus. */ - target = cpumask_any_but(cpu_online_mask, cpu); + + /* Choose a local CPU from all online cpus. */ + numa_node = dev_to_node(&pcie_pmu->pdev->dev); + if (cpumask_and(&mask, cpumask_of_node(numa_node), cpu_online_mask) && + cpumask_andnot(&mask, &mask, cpumask_of(cpu))) + target = cpumask_any(&mask); + else + target = cpumask_any_but(cpu_online_mask, cpu); + if (target >= nr_cpu_ids) { pci_err(pcie_pmu->pdev, "There is no CPU to set\n"); return 0; diff --git a/drivers/perf/marvell_cn10k_ddr_pmu.c b/drivers/perf/marvell_cn10k_ddr_pmu.c index b94a5f6cc22b..524ba82bfce2 100644 --- a/drivers/perf/marvell_cn10k_ddr_pmu.c +++ b/drivers/perf/marvell_cn10k_ddr_pmu.c @@ -8,11 +8,10 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_device.h> #include <linux/perf_event.h> #include <linux/hrtimer.h> #include <linux/acpi.h> +#include <linux/platform_device.h> /* Performance Counters Operating Mode Control Registers */ #define DDRC_PERF_CNT_OP_MODE_CTRL 0x8020 diff --git a/drivers/perf/marvell_cn10k_tad_pmu.c b/drivers/perf/marvell_cn10k_tad_pmu.c index 3972197e2210..fec8e82edb95 100644 --- a/drivers/perf/marvell_cn10k_tad_pmu.c +++ b/drivers/perf/marvell_cn10k_tad_pmu.c @@ -6,10 +6,9 @@ #define pr_fmt(fmt) "tad_pmu: " fmt +#include <linux/io.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_device.h> #include <linux/cpuhotplug.h> #include <linux/perf_event.h> #include <linux/platform_device.h> diff --git a/drivers/perf/xgene_pmu.c b/drivers/perf/xgene_pmu.c index 0c32dffc7ede..9972bfc11a5c 100644 --- a/drivers/perf/xgene_pmu.c +++ b/drivers/perf/xgene_pmu.c @@ -1833,7 +1833,6 @@ static int xgene_pmu_probe(struct platform_device *pdev) const struct xgene_pmu_data *dev_data; const struct of_device_id *of_id; struct xgene_pmu *xgene_pmu; - struct resource *res; int irq, rc; int version; @@ -1883,8 +1882,7 @@ static int xgene_pmu_probe(struct platform_device *pdev) xgene_pmu->version = version; dev_info(&pdev->dev, "X-Gene PMU version %d\n", xgene_pmu->version); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - xgene_pmu->pcppmu_csr = devm_ioremap_resource(&pdev->dev, res); + xgene_pmu->pcppmu_csr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(xgene_pmu->pcppmu_csr)) { dev_err(&pdev->dev, "ioremap failed for PCP PMU resource\n"); return PTR_ERR(xgene_pmu->pcppmu_csr); diff --git a/drivers/pinctrl/cirrus/Kconfig b/drivers/pinctrl/cirrus/Kconfig index 530426a74f75..d6318cb57aff 100644 --- a/drivers/pinctrl/cirrus/Kconfig +++ b/drivers/pinctrl/cirrus/Kconfig @@ -1,4 +1,15 @@ # SPDX-License-Identifier: GPL-2.0-only +config PINCTRL_CS42L43 + tristate "Cirrus Logic CS42L43 Pinctrl Driver" + depends on MFD_CS42L43 + select GPIOLIB + select PINMUX + select PINCONF + select GENERIC_PINCONF + help + Select this to support the GPIO/Pinctrl functions of the Cirrus + Logic CS42L43 PC CODEC. + config PINCTRL_LOCHNAGAR tristate "Cirrus Logic Lochnagar pinctrl driver" depends on MFD_LOCHNAGAR diff --git a/drivers/pinctrl/cirrus/Makefile b/drivers/pinctrl/cirrus/Makefile index a484518c840e..9b618d766907 100644 --- a/drivers/pinctrl/cirrus/Makefile +++ b/drivers/pinctrl/cirrus/Makefile @@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only # Cirrus Logic pinctrl drivers +obj-$(CONFIG_PINCTRL_CS42L43) += pinctrl-cs42l43.o + obj-$(CONFIG_PINCTRL_LOCHNAGAR) += pinctrl-lochnagar.o pinctrl-madera-objs := pinctrl-madera-core.o diff --git a/drivers/pinctrl/cirrus/pinctrl-cs42l43.c b/drivers/pinctrl/cirrus/pinctrl-cs42l43.c new file mode 100644 index 000000000000..c09646318419 --- /dev/null +++ b/drivers/pinctrl/cirrus/pinctrl-cs42l43.c @@ -0,0 +1,609 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// CS42L43 Pinctrl and GPIO driver +// +// Copyright (c) 2023 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. + +#include <linux/bits.h> +#include <linux/build_bug.h> +#include <linux/err.h> +#include <linux/errno.h> +#include <linux/gpio/driver.h> +#include <linux/mfd/cs42l43.h> +#include <linux/mfd/cs42l43-regs.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/string_helpers.h> + +#include <linux/pinctrl/consumer.h> +#include <linux/pinctrl/pinctrl.h> +#include <linux/pinctrl/pinconf.h> +#include <linux/pinctrl/pinconf-generic.h> +#include <linux/pinctrl/pinmux.h> + +#include "../pinctrl-utils.h" + +#define CS42L43_NUM_GPIOS 3 + +struct cs42l43_pin { + struct gpio_chip gpio_chip; + + struct device *dev; + struct regmap *regmap; + bool shutters_locked; +}; + +struct cs42l43_pin_data { + unsigned int reg; + unsigned int shift; + unsigned int mask; +}; + +#define CS42L43_PIN(_number, _name, _reg, _field) { \ + .number = _number, .name = _name, \ + .drv_data = &((struct cs42l43_pin_data){ \ + .reg = CS42L43_##_reg, \ + .shift = CS42L43_##_field##_DRV_SHIFT, \ + .mask = CS42L43_##_field##_DRV_MASK, \ + }), \ +} + +static const struct pinctrl_pin_desc cs42l43_pin_pins[] = { + CS42L43_PIN(0, "gpio1", DRV_CTRL4, GPIO1), + CS42L43_PIN(1, "gpio2", DRV_CTRL4, GPIO2), + CS42L43_PIN(2, "gpio3", DRV_CTRL4, GPIO3), + CS42L43_PIN(3, "asp_dout", DRV_CTRL1, ASP_DOUT), + CS42L43_PIN(4, "asp_fsync", DRV_CTRL1, ASP_FSYNC), + CS42L43_PIN(5, "asp_bclk", DRV_CTRL1, ASP_BCLK), + CS42L43_PIN(6, "pdmout2_clk", DRV_CTRL3, PDMOUT2_CLK), + CS42L43_PIN(7, "pdmout2_data", DRV_CTRL3, PDMOUT2_DATA), + CS42L43_PIN(8, "pdmout1_clk", DRV_CTRL3, PDMOUT1_CLK), + CS42L43_PIN(9, "pdmout1_data", DRV_CTRL3, PDMOUT1_DATA), + CS42L43_PIN(10, "i2c_sda", DRV_CTRL3, I2C_SDA), + CS42L43_PIN(11, "i2c_scl", DRV_CTRL_5, I2C_SCL), + CS42L43_PIN(12, "spi_miso", DRV_CTRL3, SPI_MISO), + CS42L43_PIN(13, "spi_sck", DRV_CTRL_5, SPI_SCK), + CS42L43_PIN(14, "spi_ssb", DRV_CTRL_5, SPI_SSB), +}; + +static const unsigned int cs42l43_pin_gpio1_pins[] = { 0 }; +static const unsigned int cs42l43_pin_gpio2_pins[] = { 1 }; +static const unsigned int cs42l43_pin_gpio3_pins[] = { 2 }; +static const unsigned int cs42l43_pin_asp_pins[] = { 3, 4, 5 }; +static const unsigned int cs42l43_pin_pdmout2_pins[] = { 6, 7 }; +static const unsigned int cs42l43_pin_pdmout1_pins[] = { 8, 9 }; +static const unsigned int cs42l43_pin_i2c_pins[] = { 10, 11 }; +static const unsigned int cs42l43_pin_spi_pins[] = { 12, 13, 14 }; + +#define CS42L43_PINGROUP(_name) \ + PINCTRL_PINGROUP(#_name, cs42l43_pin_##_name##_pins, \ + ARRAY_SIZE(cs42l43_pin_##_name##_pins)) + +static const struct pingroup cs42l43_pin_groups[] = { + CS42L43_PINGROUP(gpio1), + CS42L43_PINGROUP(gpio2), + CS42L43_PINGROUP(gpio3), + CS42L43_PINGROUP(asp), + CS42L43_PINGROUP(pdmout2), + CS42L43_PINGROUP(pdmout1), + CS42L43_PINGROUP(i2c), + CS42L43_PINGROUP(spi), +}; + +static int cs42l43_pin_get_groups_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(cs42l43_pin_groups); +} + +static const char *cs42l43_pin_get_group_name(struct pinctrl_dev *pctldev, + unsigned int group_idx) +{ + return cs42l43_pin_groups[group_idx].name; +} + +static int cs42l43_pin_get_group_pins(struct pinctrl_dev *pctldev, + unsigned int group_idx, + const unsigned int **pins, + unsigned int *num_pins) +{ + *pins = cs42l43_pin_groups[group_idx].pins; + *num_pins = cs42l43_pin_groups[group_idx].npins; + + return 0; +} + +static const struct pinctrl_ops cs42l43_pin_group_ops = { + .get_groups_count = cs42l43_pin_get_groups_count, + .get_group_name = cs42l43_pin_get_group_name, + .get_group_pins = cs42l43_pin_get_group_pins, +#if IS_ENABLED(CONFIG_OF) + .dt_node_to_map = pinconf_generic_dt_node_to_map_all, + .dt_free_map = pinconf_generic_dt_free_map, +#endif +}; + +enum cs42l43_pin_funcs { + CS42L43_FUNC_GPIO, + CS42L43_FUNC_SPDIF, + CS42L43_FUNC_IRQ, + CS42L43_FUNC_MIC_SHT, + CS42L43_FUNC_SPK_SHT, + CS42L43_FUNC_MAX +}; + +static const char * const cs42l43_pin_funcs[] = { + "gpio", "spdif", "irq", "mic-shutter", "spk-shutter", +}; + +static const char * const cs42l43_pin_gpio_groups[] = { "gpio1", "gpio3" }; +static const char * const cs42l43_pin_spdif_groups[] = { "gpio3" }; +static const char * const cs42l43_pin_irq_groups[] = { "gpio1" }; +static const char * const cs42l43_pin_shutter_groups[] = { "gpio1", "gpio2", "gpio3" }; + +static const struct pinfunction cs42l43_pin_func_groups[] = { + PINCTRL_PINFUNCTION("gpio", cs42l43_pin_gpio_groups, + ARRAY_SIZE(cs42l43_pin_gpio_groups)), + PINCTRL_PINFUNCTION("spdif", cs42l43_pin_spdif_groups, + ARRAY_SIZE(cs42l43_pin_spdif_groups)), + PINCTRL_PINFUNCTION("irq", cs42l43_pin_irq_groups, + ARRAY_SIZE(cs42l43_pin_irq_groups)), + PINCTRL_PINFUNCTION("mic-shutter", cs42l43_pin_shutter_groups, + ARRAY_SIZE(cs42l43_pin_shutter_groups)), + PINCTRL_PINFUNCTION("spk-shutter", cs42l43_pin_shutter_groups, + ARRAY_SIZE(cs42l43_pin_shutter_groups)), +}; + +static_assert(ARRAY_SIZE(cs42l43_pin_funcs) == CS42L43_FUNC_MAX); +static_assert(ARRAY_SIZE(cs42l43_pin_func_groups) == CS42L43_FUNC_MAX); + +static int cs42l43_pin_get_func_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(cs42l43_pin_funcs); +} + +static const char *cs42l43_pin_get_func_name(struct pinctrl_dev *pctldev, + unsigned int func_idx) +{ + return cs42l43_pin_funcs[func_idx]; +} + +static int cs42l43_pin_get_func_groups(struct pinctrl_dev *pctldev, + unsigned int func_idx, + const char * const **groups, + unsigned int * const num_groups) +{ + *groups = cs42l43_pin_func_groups[func_idx].groups; + *num_groups = cs42l43_pin_func_groups[func_idx].ngroups; + + return 0; +} + +static int cs42l43_pin_set_mux(struct pinctrl_dev *pctldev, + unsigned int func_idx, unsigned int group_idx) +{ + struct cs42l43_pin *priv = pinctrl_dev_get_drvdata(pctldev); + unsigned int reg, mask, val; + + dev_dbg(priv->dev, "Setting %s to %s\n", + cs42l43_pin_groups[group_idx].name, cs42l43_pin_funcs[func_idx]); + + switch (func_idx) { + case CS42L43_FUNC_MIC_SHT: + reg = CS42L43_SHUTTER_CONTROL; + mask = CS42L43_MIC_SHUTTER_CFG_MASK; + val = 0x2 << (group_idx + CS42L43_MIC_SHUTTER_CFG_SHIFT); + break; + case CS42L43_FUNC_SPK_SHT: + reg = CS42L43_SHUTTER_CONTROL; + mask = CS42L43_SPK_SHUTTER_CFG_MASK; + val = 0x2 << (group_idx + CS42L43_SPK_SHUTTER_CFG_SHIFT); + break; + default: + reg = CS42L43_GPIO_FN_SEL; + mask = BIT(group_idx + CS42L43_GPIO1_FN_SEL_SHIFT); + val = (func_idx == CS42L43_FUNC_GPIO) ? + (0x1 << (group_idx + CS42L43_GPIO1_FN_SEL_SHIFT)) : 0; + break; + } + + if (priv->shutters_locked && reg == CS42L43_SHUTTER_CONTROL) { + dev_err(priv->dev, "Shutter configuration not available\n"); + return -EPERM; + } + + return regmap_update_bits(priv->regmap, reg, mask, val); +} + +static int cs42l43_gpio_set_direction(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int offset, bool input) +{ + struct cs42l43_pin *priv = pinctrl_dev_get_drvdata(pctldev); + unsigned int shift = offset + CS42L43_GPIO1_DIR_SHIFT; + int ret; + + dev_dbg(priv->dev, "Setting gpio%d to %s\n", + offset + 1, input ? "input" : "output"); + + ret = pm_runtime_resume_and_get(priv->dev); + if (ret) { + dev_err(priv->dev, "Failed to resume for direction: %d\n", ret); + return ret; + } + + ret = regmap_update_bits(priv->regmap, CS42L43_GPIO_CTRL1, + BIT(shift), !!input << shift); + if (ret) + dev_err(priv->dev, "Failed to set gpio%d direction: %d\n", + offset + 1, ret); + + pm_runtime_put(priv->dev); + + return ret; +} + +static int cs42l43_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int offset) +{ + return cs42l43_pin_set_mux(pctldev, 0, offset); +} + +static void cs42l43_gpio_disable_free(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int offset) +{ + cs42l43_gpio_set_direction(pctldev, range, offset, true); +} + +static const struct pinmux_ops cs42l43_pin_mux_ops = { + .get_functions_count = cs42l43_pin_get_func_count, + .get_function_name = cs42l43_pin_get_func_name, + .get_function_groups = cs42l43_pin_get_func_groups, + + .set_mux = cs42l43_pin_set_mux, + + .gpio_request_enable = cs42l43_gpio_request_enable, + .gpio_disable_free = cs42l43_gpio_disable_free, + .gpio_set_direction = cs42l43_gpio_set_direction, + + .strict = true, +}; + +static const unsigned int cs42l43_pin_drv_str_ma[] = { 1, 2, 4, 8, 9, 10, 12, 16 }; + +static inline int cs42l43_pin_get_drv_str(struct cs42l43_pin *priv, unsigned int pin) +{ + const struct cs42l43_pin_data *pdat = cs42l43_pin_pins[pin].drv_data; + unsigned int val; + int ret; + + ret = regmap_read(priv->regmap, pdat->reg, &val); + if (ret) + return ret; + + return cs42l43_pin_drv_str_ma[(val & pdat->mask) >> pdat->shift]; +} + +static inline int cs42l43_pin_set_drv_str(struct cs42l43_pin *priv, unsigned int pin, + unsigned int ma) +{ + const struct cs42l43_pin_data *pdat = cs42l43_pin_pins[pin].drv_data; + int i; + + for (i = 0; i < ARRAY_SIZE(cs42l43_pin_drv_str_ma); i++) { + if (ma == cs42l43_pin_drv_str_ma[i]) { + if ((i << pdat->shift) > pdat->mask) + goto err; + + dev_dbg(priv->dev, "Set drive strength for %s to %d mA\n", + cs42l43_pin_pins[pin].name, ma); + + return regmap_update_bits(priv->regmap, pdat->reg, + pdat->mask, i << pdat->shift); + } + } + +err: + dev_err(priv->dev, "Invalid drive strength for %s: %d mA\n", + cs42l43_pin_pins[pin].name, ma); + return -EINVAL; +} + +static inline int cs42l43_pin_get_db(struct cs42l43_pin *priv, unsigned int pin) +{ + unsigned int val; + int ret; + + if (pin >= CS42L43_NUM_GPIOS) + return -ENOTSUPP; + + ret = regmap_read(priv->regmap, CS42L43_GPIO_CTRL2, &val); + if (ret) + return ret; + + if (val & (CS42L43_GPIO1_DEGLITCH_BYP_MASK << pin)) + return 0; + + return 85; // Debounce is roughly 85uS +} + +static inline int cs42l43_pin_set_db(struct cs42l43_pin *priv, unsigned int pin, + unsigned int us) +{ + if (pin >= CS42L43_NUM_GPIOS) + return -ENOTSUPP; + + dev_dbg(priv->dev, "Set debounce %s for %s\n", + str_on_off(us), cs42l43_pin_pins[pin].name); + + return regmap_update_bits(priv->regmap, CS42L43_GPIO_CTRL2, + CS42L43_GPIO1_DEGLITCH_BYP_MASK << pin, + !!us << pin); +} + +static int cs42l43_pin_config_get(struct pinctrl_dev *pctldev, + unsigned int pin, unsigned long *config) +{ + struct cs42l43_pin *priv = pinctrl_dev_get_drvdata(pctldev); + unsigned int param = pinconf_to_config_param(*config); + int ret; + + switch (param) { + case PIN_CONFIG_DRIVE_STRENGTH: + ret = cs42l43_pin_get_drv_str(priv, pin); + if (ret < 0) + return ret; + break; + case PIN_CONFIG_INPUT_DEBOUNCE: + ret = cs42l43_pin_get_db(priv, pin); + if (ret < 0) + return ret; + break; + default: + return -ENOTSUPP; + } + + *config = pinconf_to_config_packed(param, ret); + + return 0; +} + +static int cs42l43_pin_config_set(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long *configs, unsigned int num_configs) +{ + struct cs42l43_pin *priv = pinctrl_dev_get_drvdata(pctldev); + unsigned int val; + int ret; + + while (num_configs) { + val = pinconf_to_config_argument(*configs); + + switch (pinconf_to_config_param(*configs)) { + case PIN_CONFIG_DRIVE_STRENGTH: + ret = cs42l43_pin_set_drv_str(priv, pin, val); + if (ret) + return ret; + break; + case PIN_CONFIG_INPUT_DEBOUNCE: + ret = cs42l43_pin_set_db(priv, pin, val); + if (ret) + return ret; + break; + default: + return -ENOTSUPP; + } + + configs++; + num_configs--; + } + + return 0; +} + +static int cs42l43_pin_config_group_get(struct pinctrl_dev *pctldev, + unsigned int selector, unsigned long *config) +{ + int i, ret; + + for (i = 0; i < cs42l43_pin_groups[selector].npins; ++i) { + ret = cs42l43_pin_config_get(pctldev, + cs42l43_pin_groups[selector].pins[i], + config); + if (ret) + return ret; + } + + return 0; +} + +static int cs42l43_pin_config_group_set(struct pinctrl_dev *pctldev, + unsigned int selector, + unsigned long *configs, + unsigned int num_configs) +{ + int i, ret; + + for (i = 0; i < cs42l43_pin_groups[selector].npins; ++i) { + ret = cs42l43_pin_config_set(pctldev, + cs42l43_pin_groups[selector].pins[i], + configs, num_configs); + if (ret) + return ret; + } + + return 0; +} + +static const struct pinconf_ops cs42l43_pin_conf_ops = { + .is_generic = true, + + .pin_config_get = cs42l43_pin_config_get, + .pin_config_set = cs42l43_pin_config_set, + .pin_config_group_get = cs42l43_pin_config_group_get, + .pin_config_group_set = cs42l43_pin_config_group_set, +}; + +static struct pinctrl_desc cs42l43_pin_desc = { + .name = "cs42l43-pinctrl", + .owner = THIS_MODULE, + + .pins = cs42l43_pin_pins, + .npins = ARRAY_SIZE(cs42l43_pin_pins), + + .pctlops = &cs42l43_pin_group_ops, + .pmxops = &cs42l43_pin_mux_ops, + .confops = &cs42l43_pin_conf_ops, +}; + +static int cs42l43_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + struct cs42l43_pin *priv = gpiochip_get_data(chip); + unsigned int val; + int ret; + + ret = pm_runtime_resume_and_get(priv->dev); + if (ret) { + dev_err(priv->dev, "Failed to resume for get: %d\n", ret); + return ret; + } + + ret = regmap_read(priv->regmap, CS42L43_GPIO_STS, &val); + if (ret) + dev_err(priv->dev, "Failed to get gpio%d: %d\n", offset + 1, ret); + else + ret = !!(val & BIT(offset + CS42L43_GPIO1_STS_SHIFT)); + + pm_runtime_put(priv->dev); + + return ret; +} + +static void cs42l43_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) +{ + struct cs42l43_pin *priv = gpiochip_get_data(chip); + unsigned int shift = offset + CS42L43_GPIO1_LVL_SHIFT; + int ret; + + dev_dbg(priv->dev, "Setting gpio%d to %s\n", + offset + 1, value ? "high" : "low"); + + ret = pm_runtime_resume_and_get(priv->dev); + if (ret) { + dev_err(priv->dev, "Failed to resume for set: %d\n", ret); + return; + } + + ret = regmap_update_bits(priv->regmap, CS42L43_GPIO_CTRL1, + BIT(shift), value << shift); + if (ret) + dev_err(priv->dev, "Failed to set gpio%d: %d\n", offset + 1, ret); + + pm_runtime_put(priv->dev); +} + +static int cs42l43_gpio_direction_in(struct gpio_chip *chip, unsigned int offset) +{ + return pinctrl_gpio_direction_input(chip->base + offset); +} + +static int cs42l43_gpio_direction_out(struct gpio_chip *chip, + unsigned int offset, int value) +{ + cs42l43_gpio_set(chip, offset, value); + + return pinctrl_gpio_direction_output(chip->base + offset); +} + +static int cs42l43_gpio_add_pin_ranges(struct gpio_chip *chip) +{ + struct cs42l43_pin *priv = gpiochip_get_data(chip); + int ret; + + ret = gpiochip_add_pin_range(&priv->gpio_chip, priv->gpio_chip.label, + 0, 0, CS42L43_NUM_GPIOS); + if (ret) + dev_err(priv->dev, "Failed to add GPIO pin range: %d\n", ret); + + return ret; +} + +static int cs42l43_pin_probe(struct platform_device *pdev) +{ + struct cs42l43 *cs42l43 = dev_get_drvdata(pdev->dev.parent); + struct cs42l43_pin *priv; + struct pinctrl_dev *pctldev; + struct fwnode_handle *fwnode = dev_fwnode(cs42l43->dev); + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = &pdev->dev; + priv->regmap = cs42l43->regmap; + + priv->shutters_locked = cs42l43->hw_lock; + + priv->gpio_chip.request = gpiochip_generic_request; + priv->gpio_chip.free = gpiochip_generic_free; + priv->gpio_chip.direction_input = cs42l43_gpio_direction_in; + priv->gpio_chip.direction_output = cs42l43_gpio_direction_out; + priv->gpio_chip.add_pin_ranges = cs42l43_gpio_add_pin_ranges; + priv->gpio_chip.get = cs42l43_gpio_get; + priv->gpio_chip.set = cs42l43_gpio_set; + priv->gpio_chip.label = dev_name(priv->dev); + priv->gpio_chip.parent = priv->dev; + priv->gpio_chip.can_sleep = true; + priv->gpio_chip.base = -1; + priv->gpio_chip.ngpio = CS42L43_NUM_GPIOS; + + if (is_of_node(fwnode)) { + fwnode = fwnode_get_named_child_node(fwnode, "pinctrl"); + + if (fwnode && !fwnode->dev) + fwnode->dev = priv->dev; + } + + priv->gpio_chip.fwnode = fwnode; + + device_set_node(priv->dev, fwnode); + + devm_pm_runtime_enable(priv->dev); + pm_runtime_idle(priv->dev); + + pctldev = devm_pinctrl_register(priv->dev, &cs42l43_pin_desc, priv); + if (IS_ERR(pctldev)) + return dev_err_probe(priv->dev, PTR_ERR(pctldev), + "Failed to register pinctrl\n"); + + ret = devm_gpiochip_add_data(priv->dev, &priv->gpio_chip, priv); + if (ret) + return dev_err_probe(priv->dev, ret, + "Failed to register gpiochip\n"); + + return 0; +} + +static const struct platform_device_id cs42l43_pin_id_table[] = { + { "cs42l43-pinctrl", }, + {} +}; +MODULE_DEVICE_TABLE(platform, cs42l43_pin_id_table); + +static struct platform_driver cs42l43_pin_driver = { + .driver = { + .name = "cs42l43-pinctrl", + }, + .probe = cs42l43_pin_probe, + .id_table = cs42l43_pin_id_table, +}; +module_platform_driver(cs42l43_pin_driver); + +MODULE_DESCRIPTION("CS42L43 Pinctrl Driver"); +MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index 4a8c1b57a90d..4dff656af3ad 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -862,6 +862,33 @@ static const struct pinconf_ops amd_pinconf_ops = { .pin_config_group_set = amd_pinconf_group_set, }; +static void amd_gpio_irq_init(struct amd_gpio *gpio_dev) +{ + struct pinctrl_desc *desc = gpio_dev->pctrl->desc; + unsigned long flags; + u32 pin_reg, mask; + int i; + + mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3) | + BIT(WAKE_CNTRL_OFF_S4); + + for (i = 0; i < desc->npins; i++) { + int pin = desc->pins[i].number; + const struct pin_desc *pd = pin_desc_get(gpio_dev->pctrl, pin); + + if (!pd) + continue; + + raw_spin_lock_irqsave(&gpio_dev->lock, flags); + + pin_reg = readl(gpio_dev->base + pin * 4); + pin_reg &= ~mask; + writel(pin_reg, gpio_dev->base + pin * 4); + + raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); + } +} + #ifdef CONFIG_PM_SLEEP static bool amd_gpio_should_save(struct amd_gpio *gpio_dev, unsigned int pin) { @@ -1099,6 +1126,9 @@ static int amd_gpio_probe(struct platform_device *pdev) return PTR_ERR(gpio_dev->pctrl); } + /* Disable and mask interrupts */ + amd_gpio_irq_init(gpio_dev); + girq = &gpio_dev->gc.irq; gpio_irq_chip_set_chip(girq, &amd_gpio_irqchip); /* This will let us handle the parent IRQ in the driver */ diff --git a/drivers/pinctrl/renesas/pinctrl-rza2.c b/drivers/pinctrl/renesas/pinctrl-rza2.c index 40b1326a1077..5591ddf16fdf 100644 --- a/drivers/pinctrl/renesas/pinctrl-rza2.c +++ b/drivers/pinctrl/renesas/pinctrl-rza2.c @@ -14,6 +14,7 @@ #include <linux/gpio/driver.h> #include <linux/io.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/of_device.h> #include <linux/pinctrl/pinmux.h> @@ -46,6 +47,7 @@ struct rza2_pinctrl_priv { struct pinctrl_dev *pctl; struct pinctrl_gpio_range gpio_range; int npins; + struct mutex mutex; /* serialize adding groups and functions */ }; #define RZA2_PDR(port) (0x0000 + (port) * 2) /* Direction 16-bit */ @@ -358,10 +360,14 @@ static int rza2_dt_node_to_map(struct pinctrl_dev *pctldev, psel_val[i] = MUX_FUNC(value); } + mutex_lock(&priv->mutex); + /* Register a single pin group listing all the pins we read from DT */ gsel = pinctrl_generic_add_group(pctldev, np->name, pins, npins, NULL); - if (gsel < 0) - return gsel; + if (gsel < 0) { + ret = gsel; + goto unlock; + } /* * Register a single group function where the 'data' is an array PSEL @@ -390,6 +396,8 @@ static int rza2_dt_node_to_map(struct pinctrl_dev *pctldev, (*map)->data.mux.function = np->name; *num_maps = 1; + mutex_unlock(&priv->mutex); + return 0; remove_function: @@ -398,6 +406,9 @@ remove_function: remove_group: pinctrl_generic_remove_group(pctldev, gsel); +unlock: + mutex_unlock(&priv->mutex); + dev_err(priv->dev, "Unable to parse DT node %s\n", np->name); return ret; @@ -473,6 +484,8 @@ static int rza2_pinctrl_probe(struct platform_device *pdev) if (IS_ERR(priv->base)) return PTR_ERR(priv->base); + mutex_init(&priv->mutex); + platform_set_drvdata(pdev, priv); priv->npins = (int)(uintptr_t)of_device_get_match_data(&pdev->dev) * diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c index b53d26167da5..6e8a76556e23 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c +++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c @@ -11,6 +11,7 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/seq_file.h> @@ -149,10 +150,11 @@ struct rzg2l_pinctrl { struct gpio_chip gpio_chip; struct pinctrl_gpio_range gpio_range; DECLARE_BITMAP(tint_slot, RZG2L_TINT_MAX_INTERRUPT); - spinlock_t bitmap_lock; + spinlock_t bitmap_lock; /* protect tint_slot bitmap */ unsigned int hwirq[RZG2L_TINT_MAX_INTERRUPT]; - spinlock_t lock; + spinlock_t lock; /* lock read/write registers */ + struct mutex mutex; /* serialize adding groups and functions */ }; static const unsigned int iolh_groupa_mA[] = { 2, 4, 8, 12 }; @@ -362,11 +364,13 @@ static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev, name = np->name; } + mutex_lock(&pctrl->mutex); + /* Register a single pin group listing all the pins we read from DT */ gsel = pinctrl_generic_add_group(pctldev, name, pins, num_pinmux, NULL); if (gsel < 0) { ret = gsel; - goto done; + goto unlock; } /* @@ -380,6 +384,8 @@ static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev, goto remove_group; } + mutex_unlock(&pctrl->mutex); + maps[idx].type = PIN_MAP_TYPE_MUX_GROUP; maps[idx].data.mux.group = name; maps[idx].data.mux.function = name; @@ -391,6 +397,8 @@ static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev, remove_group: pinctrl_generic_remove_group(pctldev, gsel); +unlock: + mutex_unlock(&pctrl->mutex); done: *index = idx; kfree(configs); @@ -1509,6 +1517,7 @@ static int rzg2l_pinctrl_probe(struct platform_device *pdev) spin_lock_init(&pctrl->lock); spin_lock_init(&pctrl->bitmap_lock); + mutex_init(&pctrl->mutex); platform_set_drvdata(pdev, pctrl); diff --git a/drivers/pinctrl/renesas/pinctrl-rzv2m.c b/drivers/pinctrl/renesas/pinctrl-rzv2m.c index 35b23c1a5684..9146101ea9e2 100644 --- a/drivers/pinctrl/renesas/pinctrl-rzv2m.c +++ b/drivers/pinctrl/renesas/pinctrl-rzv2m.c @@ -14,6 +14,7 @@ #include <linux/gpio/driver.h> #include <linux/io.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/of_device.h> #include <linux/spinlock.h> @@ -123,7 +124,8 @@ struct rzv2m_pinctrl { struct gpio_chip gpio_chip; struct pinctrl_gpio_range gpio_range; - spinlock_t lock; + spinlock_t lock; /* lock read/write registers */ + struct mutex mutex; /* serialize adding groups and functions */ }; static const unsigned int drv_1_8V_group2_uA[] = { 1800, 3800, 7800, 11000 }; @@ -322,11 +324,13 @@ static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev, name = np->name; } + mutex_lock(&pctrl->mutex); + /* Register a single pin group listing all the pins we read from DT */ gsel = pinctrl_generic_add_group(pctldev, name, pins, num_pinmux, NULL); if (gsel < 0) { ret = gsel; - goto done; + goto unlock; } /* @@ -340,6 +344,8 @@ static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev, goto remove_group; } + mutex_unlock(&pctrl->mutex); + maps[idx].type = PIN_MAP_TYPE_MUX_GROUP; maps[idx].data.mux.group = name; maps[idx].data.mux.function = name; @@ -351,6 +357,8 @@ static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev, remove_group: pinctrl_generic_remove_group(pctldev, gsel); +unlock: + mutex_unlock(&pctrl->mutex); done: *index = idx; kfree(configs); @@ -1071,6 +1079,7 @@ static int rzv2m_pinctrl_probe(struct platform_device *pdev) } spin_lock_init(&pctrl->lock); + mutex_init(&pctrl->mutex); platform_set_drvdata(pdev, pctrl); diff --git a/drivers/platform/chrome/chromeos_acpi.c b/drivers/platform/chrome/chromeos_acpi.c index 50d8a4d4352d..e6e6dcfc74d1 100644 --- a/drivers/platform/chrome/chromeos_acpi.c +++ b/drivers/platform/chrome/chromeos_acpi.c @@ -90,7 +90,36 @@ static int chromeos_acpi_handle_package(struct device *dev, union acpi_object *o case ACPI_TYPE_STRING: return sysfs_emit(buf, "%s\n", element->string.pointer); case ACPI_TYPE_BUFFER: - return sysfs_emit(buf, "%s\n", element->buffer.pointer); + { + int i, r, at, room_left; + const int byte_per_line = 16; + + at = 0; + room_left = PAGE_SIZE - 1; + for (i = 0; i < element->buffer.length && room_left; i += byte_per_line) { + r = hex_dump_to_buffer(element->buffer.pointer + i, + element->buffer.length - i, + byte_per_line, 1, buf + at, room_left, + false); + if (r > room_left) + goto truncating; + at += r; + room_left -= r; + + r = sysfs_emit_at(buf, at, "\n"); + if (!r) + goto truncating; + at += r; + room_left -= r; + } + + buf[at] = 0; + return at; +truncating: + dev_info_once(dev, "truncating sysfs content for %s\n", name); + sysfs_emit_at(buf, PAGE_SIZE - 4, "..\n"); + return PAGE_SIZE - 1; + } default: dev_err(dev, "element type %d not supported\n", element->type); return -EINVAL; @@ -235,9 +264,9 @@ static int chromeos_acpi_device_probe(struct platform_device *pdev) return 0; } -/* GGL is valid PNP ID of Google. PNP ID can be used with the ACPI devices. */ static const struct acpi_device_id chromeos_device_ids[] = { { "GGL0001", 0 }, + { "GOOG0016", 0 }, {} }; MODULE_DEVICE_TABLE(acpi, chromeos_device_ids); diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c index 500a61b093e4..356572452898 100644 --- a/drivers/platform/chrome/cros_ec_lpc.c +++ b/drivers/platform/chrome/cros_ec_lpc.c @@ -327,8 +327,8 @@ static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data) dev_emerg(ec_dev->dev, "CrOS EC Panic Reported. Shutdown is imminent!"); blocking_notifier_call_chain(&ec_dev->panic_notifier, 0, ec_dev); kobject_uevent_env(&ec_dev->dev->kobj, KOBJ_CHANGE, (char **)env); - /* Begin orderly shutdown. Force shutdown after 1 second. */ - hw_protection_shutdown("CrOS EC Panic", 1000); + /* Begin orderly shutdown. EC will force reset after a short period. */ + hw_protection_shutdown("CrOS EC Panic", -1); /* Do not query for other events after a panic is reported */ return; } diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c index e6ae8265f3a3..cefd0d886cfd 100644 --- a/drivers/platform/x86/intel/ifs/load.c +++ b/drivers/platform/x86/intel/ifs/load.c @@ -3,7 +3,7 @@ #include <linux/firmware.h> #include <asm/cpu.h> -#include <asm/microcode_intel.h> +#include <asm/microcode.h> #include "ifs.h" @@ -56,12 +56,13 @@ struct metadata_header { static struct metadata_header *find_meta_data(void *ucode, unsigned int meta_type) { + struct microcode_header_intel *hdr = &((struct microcode_intel *)ucode)->hdr; struct metadata_header *meta_header; unsigned long data_size, total_meta; unsigned long meta_size = 0; - data_size = get_datasize(ucode); - total_meta = ((struct microcode_intel *)ucode)->hdr.metasize; + data_size = intel_microcode_get_datasize(hdr); + total_meta = hdr->metasize; if (!total_meta) return NULL; diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c index 5a36b3f77bc5..84c175b9721a 100644 --- a/drivers/platform/x86/intel/pmc/core.c +++ b/drivers/platform/x86/intel/pmc/core.c @@ -1123,7 +1123,7 @@ static const struct x86_cpu_id intel_pmc_core_ids[] = { X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_L, icl_core_init), X86_MATCH_INTEL_FAM6_MODEL(ROCKETLAKE, tgl_core_init), X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, tgl_core_init), - X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, tgl_core_init), + X86_MATCH_INTEL_FAM6_MODEL(ATOM_GRACEMONT, tgl_core_init), X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, adl_core_init), X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, tgl_core_init), X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, adl_core_init), diff --git a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c index a95004e3d80b..08df9494603c 100644 --- a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c +++ b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c @@ -720,7 +720,7 @@ static struct miscdevice isst_if_char_driver = { static const struct x86_cpu_id hpm_cpu_ids[] = { X86_MATCH_INTEL_FAM6_MODEL(GRANITERAPIDS_X, NULL), - X86_MATCH_INTEL_FAM6_MODEL(SIERRAFOREST_X, NULL), + X86_MATCH_INTEL_FAM6_MODEL(ATOM_CRESTMONT_X, NULL), {} }; diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 38928ff7472b..6ab272c84b7b 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -254,6 +254,9 @@ static int __init pnpacpi_add_device(struct acpi_device *device) else strncpy(dev->name, acpi_device_bid(device), sizeof(dev->name)); + /* Handle possible string truncation */ + dev->name[sizeof(dev->name) - 1] = '\0'; + if (dev->active) pnpacpi_parse_allocated_resource(dev); diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index fff07b2bd77b..59e1ebb7842e 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -148,13 +148,6 @@ config POWER_RESET_ODROID_GO_ULTRA_POWEROFF help This driver supports Power off for Odroid Go Ultra device. -config POWER_RESET_OXNAS - bool "OXNAS SoC restart driver" - depends on ARCH_OXNAS - default MACH_OX820 - help - Restart support for OXNAS/PLXTECH OX820 SoC. - config POWER_RESET_PIIX4_POWEROFF tristate "Intel PIIX4 power-off driver" depends on PCI diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile index d763e6735ee3..a95d1bd275d1 100644 --- a/drivers/power/reset/Makefile +++ b/drivers/power/reset/Makefile @@ -14,7 +14,6 @@ obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o obj-$(CONFIG_POWER_RESET_LINKSTATION) += linkstation-poweroff.o obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o obj-$(CONFIG_POWER_RESET_MT6323) += mt6323-poweroff.o -obj-$(CONFIG_POWER_RESET_OXNAS) += oxnas-restart.o obj-$(CONFIG_POWER_RESET_QCOM_PON) += qcom-pon.o obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o obj-$(CONFIG_POWER_RESET_ODROID_GO_ULTRA_POWEROFF) += odroid-go-ultra-poweroff.o diff --git a/drivers/power/reset/as3722-poweroff.c b/drivers/power/reset/as3722-poweroff.c index 80edff1a556f..829e0dba2fda 100644 --- a/drivers/power/reset/as3722-poweroff.c +++ b/drivers/power/reset/as3722-poweroff.c @@ -10,7 +10,6 @@ #include <linux/mfd/as3722.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/slab.h> diff --git a/drivers/power/reset/at91-poweroff.c b/drivers/power/reset/at91-poweroff.c index 9e74e131c675..dd5399785b69 100644 --- a/drivers/power/reset/at91-poweroff.c +++ b/drivers/power/reset/at91-poweroff.c @@ -151,13 +151,11 @@ static void at91_poweroff_dt_set_wakeup_mode(struct platform_device *pdev) static int __init at91_poweroff_probe(struct platform_device *pdev) { - struct resource *res; struct device_node *np; u32 ddr_type; int ret; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - at91_shdwc.shdwc_base = devm_ioremap_resource(&pdev->dev, res); + at91_shdwc.shdwc_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(at91_shdwc.shdwc_base)) return PTR_ERR(at91_shdwc.shdwc_base); diff --git a/drivers/power/reset/at91-reset.c b/drivers/power/reset/at91-reset.c index d6884841a6dc..aa9b012d3d00 100644 --- a/drivers/power/reset/at91-reset.c +++ b/drivers/power/reset/at91-reset.c @@ -18,6 +18,7 @@ #include <linux/platform_device.h> #include <linux/reboot.h> #include <linux/reset-controller.h> +#include <linux/power/power_on_reason.h> #include <soc/at91/at91sam9_ddrsdr.h> #include <soc/at91/at91sam9_sdramc.h> @@ -149,44 +150,54 @@ static int at91_reset(struct notifier_block *this, unsigned long mode, return NOTIFY_DONE; } -static const char * __init at91_reset_reason(struct at91_reset *reset) +static const char *at91_reset_reason(struct at91_reset *reset) { u32 reg = readl(reset->rstc_base + AT91_RSTC_SR); const char *reason; switch ((reg & AT91_RSTC_RSTTYP) >> 8) { case RESET_TYPE_GENERAL: - reason = "general reset"; + reason = POWER_ON_REASON_REGULAR; break; case RESET_TYPE_WAKEUP: - reason = "wakeup"; + reason = POWER_ON_REASON_RTC; break; case RESET_TYPE_WATCHDOG: - reason = "watchdog reset"; + reason = POWER_ON_REASON_WATCHDOG; break; case RESET_TYPE_SOFTWARE: - reason = "software reset"; + reason = POWER_ON_REASON_SOFTWARE; break; case RESET_TYPE_USER: - reason = "user reset"; + reason = POWER_ON_REASON_RST_BTN; break; case RESET_TYPE_CPU_FAIL: - reason = "CPU clock failure detection"; + reason = POWER_ON_REASON_CPU_CLK_FAIL; break; case RESET_TYPE_XTAL_FAIL: - reason = "32.768 kHz crystal failure detection"; + reason = POWER_ON_REASON_XTAL_FAIL; break; case RESET_TYPE_ULP2: - reason = "ULP2 reset"; + reason = POWER_ON_REASON_BROWN_OUT; break; default: - reason = "unknown reset"; + reason = POWER_ON_REASON_UNKNOWN; break; } return reason; } +static ssize_t power_on_reason_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct platform_device *pdev = to_platform_device(dev); + struct at91_reset *reset = platform_get_drvdata(pdev); + + return sprintf(buf, "%s\n", at91_reset_reason(reset)); +} +static DEVICE_ATTR_RO(power_on_reason); + static const struct of_device_id at91_ramc_of_match[] = { { .compatible = "atmel,at91sam9260-sdramc", @@ -391,6 +402,12 @@ static int __init at91_reset_probe(struct platform_device *pdev) if (ret) goto disable_clk; + ret = device_create_file(&pdev->dev, &dev_attr_power_on_reason); + if (ret) { + dev_err(&pdev->dev, "Could not create sysfs entry\n"); + return ret; + } + dev_info(&pdev->dev, "Starting after %s\n", at91_reset_reason(reset)); return 0; diff --git a/drivers/power/reset/at91-sama5d2_shdwc.c b/drivers/power/reset/at91-sama5d2_shdwc.c index d8ecffe72f16..e76b102b57b1 100644 --- a/drivers/power/reset/at91-sama5d2_shdwc.c +++ b/drivers/power/reset/at91-sama5d2_shdwc.c @@ -331,7 +331,6 @@ static const struct of_device_id at91_pmc_ids[] = { static int __init at91_shdwc_probe(struct platform_device *pdev) { - struct resource *res; const struct of_device_id *match; struct device_node *np; u32 ddr_type; @@ -349,8 +348,7 @@ static int __init at91_shdwc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, at91_shdwc); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - at91_shdwc->shdwc_base = devm_ioremap_resource(&pdev->dev, res); + at91_shdwc->shdwc_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(at91_shdwc->shdwc_base)) return PTR_ERR(at91_shdwc->shdwc_base); diff --git a/drivers/power/reset/brcm-kona-reset.c b/drivers/power/reset/brcm-kona-reset.c index 3de024e3ceb7..d05728b1db09 100644 --- a/drivers/power/reset/brcm-kona-reset.c +++ b/drivers/power/reset/brcm-kona-reset.c @@ -2,8 +2,8 @@ // Copyright (C) 2016 Broadcom #include <linux/io.h> -#include <linux/of_address.h> -#include <linux/of_platform.h> +#include <linux/mod_devicetable.h> +#include <linux/platform_device.h> #include <linux/reboot.h> #define RSTMGR_REG_WR_ACCESS_OFFSET 0 @@ -38,9 +38,7 @@ static struct notifier_block kona_reset_nb = { static int kona_reset_probe(struct platform_device *pdev) { - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - kona_reset_base = devm_ioremap_resource(&pdev->dev, res); + kona_reset_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(kona_reset_base)) return PTR_ERR(kona_reset_base); diff --git a/drivers/power/reset/gemini-poweroff.c b/drivers/power/reset/gemini-poweroff.c index b7f7a8225f22..d309b610142c 100644 --- a/drivers/power/reset/gemini-poweroff.c +++ b/drivers/power/reset/gemini-poweroff.c @@ -91,7 +91,6 @@ static void gemini_poweroff(void) static int gemini_poweroff_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct resource *res; struct gemini_powercon *gpw; u32 val; int irq; @@ -101,8 +100,7 @@ static int gemini_poweroff_probe(struct platform_device *pdev) if (!gpw) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - gpw->base = devm_ioremap_resource(dev, res); + gpw->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(gpw->base)) return PTR_ERR(gpw->base); diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c index 84b3c3528afa..b28f24da1b3c 100644 --- a/drivers/power/reset/gpio-poweroff.c +++ b/drivers/power/reset/gpio-poweroff.c @@ -11,8 +11,9 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/platform_device.h> +#include <linux/property.h> #include <linux/gpio/consumer.h> -#include <linux/of_platform.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #define DEFAULT_TIMEOUT_MS 3000 diff --git a/drivers/power/reset/gpio-restart.c b/drivers/power/reset/gpio-restart.c index a479d3536eb1..3aa19765772d 100644 --- a/drivers/power/reset/gpio-restart.c +++ b/drivers/power/reset/gpio-restart.c @@ -12,8 +12,8 @@ #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/gpio/consumer.h> -#include <linux/of_platform.h> #include <linux/module.h> +#include <linux/of.h> struct gpio_restart { struct gpio_desc *reset_gpio; diff --git a/drivers/power/reset/keystone-reset.c b/drivers/power/reset/keystone-reset.c index 83a4e1c9bf94..dbc4ff61cd74 100644 --- a/drivers/power/reset/keystone-reset.c +++ b/drivers/power/reset/keystone-reset.c @@ -10,10 +10,11 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/notifier.h> +#include <linux/platform_device.h> #include <linux/reboot.h> #include <linux/regmap.h> #include <linux/mfd/syscon.h> -#include <linux/of_platform.h> +#include <linux/of.h> #define RSTYPE_RG 0x0 #define RSCTRL_RG 0x4 diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index 0c439f83bf65..b9a401bd280b 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -35,11 +35,7 @@ static void do_msm_poweroff(void) static int msm_restart_probe(struct platform_device *pdev) { - struct device *dev = &pdev->dev; - struct resource *mem; - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - msm_ps_hold = devm_ioremap_resource(dev, mem); + msm_ps_hold = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(msm_ps_hold)) return PTR_ERR(msm_ps_hold); diff --git a/drivers/power/reset/ocelot-reset.c b/drivers/power/reset/ocelot-reset.c index 8caa90cb58fc..56be64decf54 100644 --- a/drivers/power/reset/ocelot-reset.c +++ b/drivers/power/reset/ocelot-reset.c @@ -8,10 +8,10 @@ #include <linux/delay.h> #include <linux/io.h> #include <linux/notifier.h> +#include <linux/mod_devicetable.h> #include <linux/mfd/syscon.h> -#include <linux/of_address.h> -#include <linux/of_device.h> #include <linux/platform_device.h> +#include <linux/property.h> #include <linux/reboot.h> #include <linux/regmap.h> @@ -69,8 +69,6 @@ static int ocelot_restart_handle(struct notifier_block *this, static int ocelot_reset_probe(struct platform_device *pdev) { struct ocelot_reset_context *ctx; - struct resource *res; - struct device *dev = &pdev->dev; int err; @@ -78,8 +76,7 @@ static int ocelot_reset_probe(struct platform_device *pdev) if (!ctx) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ctx->base = devm_ioremap_resource(dev, res); + ctx->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(ctx->base)) return PTR_ERR(ctx->base); diff --git a/drivers/power/reset/odroid-go-ultra-poweroff.c b/drivers/power/reset/odroid-go-ultra-poweroff.c index f46271da4e8e..9cac7aef77f0 100644 --- a/drivers/power/reset/odroid-go-ultra-poweroff.c +++ b/drivers/power/reset/odroid-go-ultra-poweroff.c @@ -4,7 +4,8 @@ */ #include <linux/kernel.h> #include <linux/init.h> -#include <linux/of_platform.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/mfd/rk808.h> #include <linux/regmap.h> #include <linux/module.h> diff --git a/drivers/power/reset/oxnas-restart.c b/drivers/power/reset/oxnas-restart.c deleted file mode 100644 index 13090bec058a..000000000000 --- a/drivers/power/reset/oxnas-restart.c +++ /dev/null @@ -1,233 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0) -/* - * oxnas SoC reset driver - * based on: - * Microsemi MIPS SoC reset driver - * and ox820_assert_system_reset() written by Ma Hajun <mahaijuns@gmail.com> - * - * Copyright (c) 2013 Ma Hajun <mahaijuns@gmail.com> - * Copyright (c) 2017 Microsemi Corporation - * Copyright (c) 2020 Daniel Golle <daniel@makrotopia.org> - */ -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/notifier.h> -#include <linux/mfd/syscon.h> -#include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> -#include <linux/reboot.h> -#include <linux/regmap.h> - -/* bit numbers of reset control register */ -#define OX820_SYS_CTRL_RST_SCU 0 -#define OX820_SYS_CTRL_RST_COPRO 1 -#define OX820_SYS_CTRL_RST_ARM0 2 -#define OX820_SYS_CTRL_RST_ARM1 3 -#define OX820_SYS_CTRL_RST_USBHS 4 -#define OX820_SYS_CTRL_RST_USBHSPHYA 5 -#define OX820_SYS_CTRL_RST_MACA 6 -#define OX820_SYS_CTRL_RST_MAC OX820_SYS_CTRL_RST_MACA -#define OX820_SYS_CTRL_RST_PCIEA 7 -#define OX820_SYS_CTRL_RST_SGDMA 8 -#define OX820_SYS_CTRL_RST_CIPHER 9 -#define OX820_SYS_CTRL_RST_DDR 10 -#define OX820_SYS_CTRL_RST_SATA 11 -#define OX820_SYS_CTRL_RST_SATA_LINK 12 -#define OX820_SYS_CTRL_RST_SATA_PHY 13 -#define OX820_SYS_CTRL_RST_PCIEPHY 14 -#define OX820_SYS_CTRL_RST_STATIC 15 -#define OX820_SYS_CTRL_RST_GPIO 16 -#define OX820_SYS_CTRL_RST_UART1 17 -#define OX820_SYS_CTRL_RST_UART2 18 -#define OX820_SYS_CTRL_RST_MISC 19 -#define OX820_SYS_CTRL_RST_I2S 20 -#define OX820_SYS_CTRL_RST_SD 21 -#define OX820_SYS_CTRL_RST_MACB 22 -#define OX820_SYS_CTRL_RST_PCIEB 23 -#define OX820_SYS_CTRL_RST_VIDEO 24 -#define OX820_SYS_CTRL_RST_DDR_PHY 25 -#define OX820_SYS_CTRL_RST_USBHSPHYB 26 -#define OX820_SYS_CTRL_RST_USBDEV 27 -#define OX820_SYS_CTRL_RST_ARMDBG 29 -#define OX820_SYS_CTRL_RST_PLLA 30 -#define OX820_SYS_CTRL_RST_PLLB 31 - -/* bit numbers of clock control register */ -#define OX820_SYS_CTRL_CLK_COPRO 0 -#define OX820_SYS_CTRL_CLK_DMA 1 -#define OX820_SYS_CTRL_CLK_CIPHER 2 -#define OX820_SYS_CTRL_CLK_SD 3 -#define OX820_SYS_CTRL_CLK_SATA 4 -#define OX820_SYS_CTRL_CLK_I2S 5 -#define OX820_SYS_CTRL_CLK_USBHS 6 -#define OX820_SYS_CTRL_CLK_MACA 7 -#define OX820_SYS_CTRL_CLK_MAC OX820_SYS_CTRL_CLK_MACA -#define OX820_SYS_CTRL_CLK_PCIEA 8 -#define OX820_SYS_CTRL_CLK_STATIC 9 -#define OX820_SYS_CTRL_CLK_MACB 10 -#define OX820_SYS_CTRL_CLK_PCIEB 11 -#define OX820_SYS_CTRL_CLK_REF600 12 -#define OX820_SYS_CTRL_CLK_USBDEV 13 -#define OX820_SYS_CTRL_CLK_DDR 14 -#define OX820_SYS_CTRL_CLK_DDRPHY 15 -#define OX820_SYS_CTRL_CLK_DDRCK 16 - -/* Regmap offsets */ -#define OX820_CLK_SET_REGOFFSET 0x2c -#define OX820_CLK_CLR_REGOFFSET 0x30 -#define OX820_RST_SET_REGOFFSET 0x34 -#define OX820_RST_CLR_REGOFFSET 0x38 -#define OX820_SECONDARY_SEL_REGOFFSET 0x14 -#define OX820_TERTIARY_SEL_REGOFFSET 0x8c -#define OX820_QUATERNARY_SEL_REGOFFSET 0x94 -#define OX820_DEBUG_SEL_REGOFFSET 0x9c -#define OX820_ALTERNATIVE_SEL_REGOFFSET 0xa4 -#define OX820_PULLUP_SEL_REGOFFSET 0xac -#define OX820_SEC_SECONDARY_SEL_REGOFFSET 0x100014 -#define OX820_SEC_TERTIARY_SEL_REGOFFSET 0x10008c -#define OX820_SEC_QUATERNARY_SEL_REGOFFSET 0x100094 -#define OX820_SEC_DEBUG_SEL_REGOFFSET 0x10009c -#define OX820_SEC_ALTERNATIVE_SEL_REGOFFSET 0x1000a4 -#define OX820_SEC_PULLUP_SEL_REGOFFSET 0x1000ac - -struct oxnas_restart_context { - struct regmap *sys_ctrl; - struct notifier_block restart_handler; -}; - -static int ox820_restart_handle(struct notifier_block *this, - unsigned long mode, void *cmd) -{ - struct oxnas_restart_context *ctx = container_of(this, struct - oxnas_restart_context, - restart_handler); - u32 value; - - /* - * Assert reset to cores as per power on defaults - * Don't touch the DDR interface as things will come to an impromptu - * stop NB Possibly should be asserting reset for PLLB, but there are - * timing concerns here according to the docs - */ - value = BIT(OX820_SYS_CTRL_RST_COPRO) | - BIT(OX820_SYS_CTRL_RST_USBHS) | - BIT(OX820_SYS_CTRL_RST_USBHSPHYA) | - BIT(OX820_SYS_CTRL_RST_MACA) | - BIT(OX820_SYS_CTRL_RST_PCIEA) | - BIT(OX820_SYS_CTRL_RST_SGDMA) | - BIT(OX820_SYS_CTRL_RST_CIPHER) | - BIT(OX820_SYS_CTRL_RST_SATA) | - BIT(OX820_SYS_CTRL_RST_SATA_LINK) | - BIT(OX820_SYS_CTRL_RST_SATA_PHY) | - BIT(OX820_SYS_CTRL_RST_PCIEPHY) | - BIT(OX820_SYS_CTRL_RST_STATIC) | - BIT(OX820_SYS_CTRL_RST_UART1) | - BIT(OX820_SYS_CTRL_RST_UART2) | - BIT(OX820_SYS_CTRL_RST_MISC) | - BIT(OX820_SYS_CTRL_RST_I2S) | - BIT(OX820_SYS_CTRL_RST_SD) | - BIT(OX820_SYS_CTRL_RST_MACB) | - BIT(OX820_SYS_CTRL_RST_PCIEB) | - BIT(OX820_SYS_CTRL_RST_VIDEO) | - BIT(OX820_SYS_CTRL_RST_USBHSPHYB) | - BIT(OX820_SYS_CTRL_RST_USBDEV); - - regmap_write(ctx->sys_ctrl, OX820_RST_SET_REGOFFSET, value); - - /* Release reset to cores as per power on defaults */ - regmap_write(ctx->sys_ctrl, OX820_RST_CLR_REGOFFSET, - BIT(OX820_SYS_CTRL_RST_GPIO)); - - /* - * Disable clocks to cores as per power-on defaults - must leave DDR - * related clocks enabled otherwise we'll stop rather abruptly. - */ - value = BIT(OX820_SYS_CTRL_CLK_COPRO) | - BIT(OX820_SYS_CTRL_CLK_DMA) | - BIT(OX820_SYS_CTRL_CLK_CIPHER) | - BIT(OX820_SYS_CTRL_CLK_SD) | - BIT(OX820_SYS_CTRL_CLK_SATA) | - BIT(OX820_SYS_CTRL_CLK_I2S) | - BIT(OX820_SYS_CTRL_CLK_USBHS) | - BIT(OX820_SYS_CTRL_CLK_MAC) | - BIT(OX820_SYS_CTRL_CLK_PCIEA) | - BIT(OX820_SYS_CTRL_CLK_STATIC) | - BIT(OX820_SYS_CTRL_CLK_MACB) | - BIT(OX820_SYS_CTRL_CLK_PCIEB) | - BIT(OX820_SYS_CTRL_CLK_REF600) | - BIT(OX820_SYS_CTRL_CLK_USBDEV); - - regmap_write(ctx->sys_ctrl, OX820_CLK_CLR_REGOFFSET, value); - - /* Enable clocks to cores as per power-on defaults */ - - /* Set sys-control pin mux'ing as per power-on defaults */ - regmap_write(ctx->sys_ctrl, OX820_SECONDARY_SEL_REGOFFSET, 0); - regmap_write(ctx->sys_ctrl, OX820_TERTIARY_SEL_REGOFFSET, 0); - regmap_write(ctx->sys_ctrl, OX820_QUATERNARY_SEL_REGOFFSET, 0); - regmap_write(ctx->sys_ctrl, OX820_DEBUG_SEL_REGOFFSET, 0); - regmap_write(ctx->sys_ctrl, OX820_ALTERNATIVE_SEL_REGOFFSET, 0); - regmap_write(ctx->sys_ctrl, OX820_PULLUP_SEL_REGOFFSET, 0); - - regmap_write(ctx->sys_ctrl, OX820_SEC_SECONDARY_SEL_REGOFFSET, 0); - regmap_write(ctx->sys_ctrl, OX820_SEC_TERTIARY_SEL_REGOFFSET, 0); - regmap_write(ctx->sys_ctrl, OX820_SEC_QUATERNARY_SEL_REGOFFSET, 0); - regmap_write(ctx->sys_ctrl, OX820_SEC_DEBUG_SEL_REGOFFSET, 0); - regmap_write(ctx->sys_ctrl, OX820_SEC_ALTERNATIVE_SEL_REGOFFSET, 0); - regmap_write(ctx->sys_ctrl, OX820_SEC_PULLUP_SEL_REGOFFSET, 0); - - /* - * No need to save any state, as the ROM loader can determine whether - * reset is due to power cycling or programatic action, just hit the - * (self-clearing) CPU reset bit of the block reset register - */ - value = - BIT(OX820_SYS_CTRL_RST_SCU) | - BIT(OX820_SYS_CTRL_RST_ARM0) | - BIT(OX820_SYS_CTRL_RST_ARM1); - - regmap_write(ctx->sys_ctrl, OX820_RST_SET_REGOFFSET, value); - - pr_emerg("Unable to restart system\n"); - return NOTIFY_DONE; -} - -static int ox820_restart_probe(struct platform_device *pdev) -{ - struct oxnas_restart_context *ctx; - struct regmap *sys_ctrl; - struct device *dev = &pdev->dev; - int err = 0; - - sys_ctrl = syscon_node_to_regmap(pdev->dev.of_node); - if (IS_ERR(sys_ctrl)) - return PTR_ERR(sys_ctrl); - - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - ctx->sys_ctrl = sys_ctrl; - ctx->restart_handler.notifier_call = ox820_restart_handle; - ctx->restart_handler.priority = 192; - err = register_restart_handler(&ctx->restart_handler); - if (err) - dev_err(dev, "can't register restart notifier (err=%d)\n", err); - - return err; -} - -static const struct of_device_id ox820_restart_of_match[] = { - { .compatible = "oxsemi,ox820-sys-ctrl" }, - {} -}; - -static struct platform_driver ox820_restart_driver = { - .probe = ox820_restart_probe, - .driver = { - .name = "ox820-chip-reset", - .of_match_table = ox820_restart_of_match, - }, -}; -builtin_platform_driver(ox820_restart_driver); diff --git a/drivers/power/reset/st-poweroff.c b/drivers/power/reset/st-poweroff.c index 5ccaacffab54..56ba21873882 100644 --- a/drivers/power/reset/st-poweroff.c +++ b/drivers/power/reset/st-poweroff.c @@ -9,7 +9,7 @@ #include <linux/module.h> #include <linux/of.h> -#include <linux/of_platform.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/mfd/syscon.h> #include <linux/reboot.h> diff --git a/drivers/power/reset/syscon-poweroff.c b/drivers/power/reset/syscon-poweroff.c index ed58bdf41e27..430d440d55c6 100644 --- a/drivers/power/reset/syscon-poweroff.c +++ b/drivers/power/reset/syscon-poweroff.c @@ -10,8 +10,7 @@ #include <linux/io.h> #include <linux/notifier.h> #include <linux/mfd/syscon.h> -#include <linux/of_address.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm.h> #include <linux/regmap.h> diff --git a/drivers/power/reset/syscon-reboot.c b/drivers/power/reset/syscon-reboot.c index 45e34e6885f7..4d622c19bc48 100644 --- a/drivers/power/reset/syscon-reboot.c +++ b/drivers/power/reset/syscon-reboot.c @@ -9,8 +9,7 @@ #include <linux/io.h> #include <linux/notifier.h> #include <linux/mfd/syscon.h> -#include <linux/of_address.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/reboot.h> #include <linux/regmap.h> diff --git a/drivers/power/reset/xgene-reboot.c b/drivers/power/reset/xgene-reboot.c index 0b0d2fd2bd0c..3260bd93158e 100644 --- a/drivers/power/reset/xgene-reboot.c +++ b/drivers/power/reset/xgene-reboot.c @@ -13,7 +13,7 @@ #include <linux/delay.h> #include <linux/io.h> #include <linux/notifier.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/of_address.h> #include <linux/platform_device.h> #include <linux/reboot.h> diff --git a/drivers/power/supply/axp20x_ac_power.c b/drivers/power/supply/axp20x_ac_power.c index 57e50208d537..19a118633115 100644 --- a/drivers/power/supply/axp20x_ac_power.c +++ b/drivers/power/supply/axp20x_ac_power.c @@ -13,7 +13,6 @@ #include <linux/mfd/axp20x.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm.h> #include <linux/power_supply.h> diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c index 9106077c0dbb..6ac5c80cfda2 100644 --- a/drivers/power/supply/axp20x_battery.c +++ b/drivers/power/supply/axp20x_battery.c @@ -22,7 +22,6 @@ #include <linux/irq.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/power_supply.h> #include <linux/regmap.h> diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c index 51c3f9b6458d..bde17406c130 100644 --- a/drivers/power/supply/axp20x_usb_power.c +++ b/drivers/power/supply/axp20x_usb_power.c @@ -15,7 +15,6 @@ #include <linux/mfd/axp20x.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm.h> #include <linux/power_supply.h> diff --git a/drivers/power/supply/bd99954-charger.c b/drivers/power/supply/bd99954-charger.c index 086dcf4033c1..1ed1d9f99fb3 100644 --- a/drivers/power/supply/bd99954-charger.c +++ b/drivers/power/supply/bd99954-charger.c @@ -536,7 +536,7 @@ static irqreturn_t bd9995x_irq_handler_thread(int irq, void *private) for_each_set_bit(i, &tmp, 7) { int sub_status, sub_mask; - int sub_status_reg[] = { + static const int sub_status_reg[] = { INT1_STATUS, INT2_STATUS, INT3_STATUS, INT4_STATUS, INT5_STATUS, INT6_STATUS, INT7_STATUS, }; diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index ef8235848f56..3f99cb9590ba 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -965,7 +965,7 @@ static int bq24190_charger_get_precharge(struct bq24190_dev_info *bdi, union power_supply_propval *val) { u8 v; - int ret; + int curr, ret; ret = bq24190_read_mask(bdi, BQ24190_REG_PCTCC, BQ24190_REG_PCTCC_IPRECHG_MASK, @@ -973,7 +973,20 @@ static int bq24190_charger_get_precharge(struct bq24190_dev_info *bdi, if (ret < 0) return ret; - val->intval = ++v * 128 * 1000; + curr = ++v * 128 * 1000; + + ret = bq24190_read_mask(bdi, BQ24190_REG_CCC, + BQ24190_REG_CCC_FORCE_20PCT_MASK, + BQ24190_REG_CCC_FORCE_20PCT_SHIFT, &v); + if (ret < 0) + return ret; + + /* If FORCE_20PCT is enabled, then current is 50% of IPRECHG value */ + if (v) + curr /= 2; + + val->intval = curr; + return 0; } diff --git a/drivers/power/supply/cpcap-battery.c b/drivers/power/supply/cpcap-battery.c index d98d9244e394..5dd76c0ac98d 100644 --- a/drivers/power/supply/cpcap-battery.c +++ b/drivers/power/supply/cpcap-battery.c @@ -15,7 +15,7 @@ #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/power_supply.h> #include <linux/reboot.h> diff --git a/drivers/power/supply/da9150-charger.c b/drivers/power/supply/da9150-charger.c index a87aeaea38e1..27f897067aa3 100644 --- a/drivers/power/supply/da9150-charger.c +++ b/drivers/power/supply/da9150-charger.c @@ -11,8 +11,6 @@ #include <linux/slab.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/of.h> -#include <linux/of_platform.h> #include <linux/interrupt.h> #include <linux/power_supply.h> #include <linux/notifier.h> diff --git a/drivers/power/supply/da9150-fg.c b/drivers/power/supply/da9150-fg.c index 8c5e2c49d6c1..652c1f213af1 100644 --- a/drivers/power/supply/da9150-fg.c +++ b/drivers/power/supply/da9150-fg.c @@ -11,7 +11,6 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/of.h> -#include <linux/of_platform.h> #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/delay.h> diff --git a/drivers/power/supply/lego_ev3_battery.c b/drivers/power/supply/lego_ev3_battery.c index ccb00be38e2c..9085de0ae1b2 100644 --- a/drivers/power/supply/lego_ev3_battery.c +++ b/drivers/power/supply/lego_ev3_battery.c @@ -20,7 +20,7 @@ #include <linux/iio/types.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/mod_devicetable.h> #include <linux/platform_device.h> #include <linux/power_supply.h> diff --git a/drivers/power/supply/ltc2941-battery-gauge.c b/drivers/power/supply/ltc2941-battery-gauge.c index cad39a8f829d..a1ddc4b060ce 100644 --- a/drivers/power/supply/ltc2941-battery-gauge.c +++ b/drivers/power/supply/ltc2941-battery-gauge.c @@ -11,7 +11,7 @@ #include <linux/devm-helpers.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/swab.h> diff --git a/drivers/power/supply/ltc4162-l-charger.c b/drivers/power/supply/ltc4162-l-charger.c index ec5b4a20ad43..f0eace731480 100644 --- a/drivers/power/supply/ltc4162-l-charger.c +++ b/drivers/power/supply/ltc4162-l-charger.c @@ -6,7 +6,7 @@ #include <linux/module.h> #include <linux/delay.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/pm_runtime.h> #include <linux/power_supply.h> #include <linux/i2c.h> diff --git a/drivers/power/supply/max14656_charger_detector.c b/drivers/power/supply/max14656_charger_detector.c index fbdf12cf64eb..89f2af72dfcd 100644 --- a/drivers/power/supply/max14656_charger_detector.c +++ b/drivers/power/supply/max14656_charger_detector.c @@ -14,8 +14,8 @@ #include <linux/delay.h> #include <linux/i2c.h> #include <linux/interrupt.h> +#include <linux/mod_devicetable.h> #include <linux/slab.h> -#include <linux/of_device.h> #include <linux/workqueue.h> #include <linux/power_supply.h> #include <linux/devm-helpers.h> diff --git a/drivers/power/supply/max17040_battery.c b/drivers/power/supply/max17040_battery.c index 22ea7de47a53..ff42db672899 100644 --- a/drivers/power/supply/max17040_battery.c +++ b/drivers/power/supply/max17040_battery.c @@ -15,7 +15,7 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/power_supply.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regmap.h> #include <linux/slab.h> diff --git a/drivers/power/supply/max8903_charger.c b/drivers/power/supply/max8903_charger.c index 54d50b55fbae..e65d0141f260 100644 --- a/drivers/power/supply/max8903_charger.c +++ b/drivers/power/supply/max8903_charger.c @@ -10,7 +10,6 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/slab.h> #include <linux/power_supply.h> #include <linux/platform_device.h> diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index 3791aec69ddc..4aa466c945e2 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -1305,8 +1305,12 @@ static int psy_register_thermal(struct power_supply *psy) /* Register battery zone device psy reports temperature */ if (psy_has_property(psy->desc, POWER_SUPPLY_PROP_TEMP)) { + /* Prefer our hwmon device and avoid duplicates */ + struct thermal_zone_params tzp = { + .no_hwmon = IS_ENABLED(CONFIG_POWER_SUPPLY_HWMON) + }; psy->tzd = thermal_zone_device_register(psy->desc->name, - 0, 0, psy, &psy_tzd_ops, NULL, 0, 0); + 0, 0, psy, &psy_tzd_ops, &tzp, 0, 0); if (IS_ERR(psy->tzd)) return PTR_ERR(psy->tzd); ret = thermal_zone_device_enable(psy->tzd); diff --git a/drivers/power/supply/qcom_pmi8998_charger.c b/drivers/power/supply/qcom_pmi8998_charger.c index d16c5ee17249..10f4dd0caca1 100644 --- a/drivers/power/supply/qcom_pmi8998_charger.c +++ b/drivers/power/supply/qcom_pmi8998_charger.c @@ -409,8 +409,6 @@ static enum power_supply_property smb2_properties[] = { POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_PROP_ONLINE, POWER_SUPPLY_PROP_USB_TYPE, - POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT, - POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX, }; static enum power_supply_usb_type smb2_usb_types[] = { @@ -519,9 +517,9 @@ static int smb2_get_prop_status(struct smb2_chip *chip, int *val) *val = POWER_SUPPLY_STATUS_NOT_CHARGING; return rc; case TERMINATE_CHARGE: + case INHIBIT_CHARGE: *val = POWER_SUPPLY_STATUS_FULL; return rc; - case INHIBIT_CHARGE: default: *val = POWER_SUPPLY_STATUS_UNKNOWN; return rc; @@ -556,7 +554,8 @@ static int smb2_set_current_limit(struct smb2_chip *chip, unsigned int val) static void smb2_status_change_work(struct work_struct *work) { unsigned int charger_type, current_ua; - int usb_online, count, rc; + int usb_online = 0; + int count, rc; struct smb2_chip *chip; chip = container_of(work, struct smb2_chip, status_change_work.work); @@ -673,11 +672,7 @@ static int smb2_get_property(struct power_supply *psy, val->strval = chip->name; return 0; case POWER_SUPPLY_PROP_CURRENT_MAX: - case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: return smb2_get_current_limit(chip, &val->intval); - case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX: - val->intval = DCP_CURRENT_UA; - return 0; case POWER_SUPPLY_PROP_CURRENT_NOW: return smb2_get_iio_chan(chip, chip->usb_in_i_chan, &val->intval); @@ -706,7 +701,6 @@ static int smb2_set_property(struct power_supply *psy, switch (psp) { case POWER_SUPPLY_PROP_CURRENT_MAX: - case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: return smb2_set_current_limit(chip, val->intval); default: dev_err(chip->dev, "No setter for property: %d\n", psp); @@ -719,7 +713,6 @@ static int smb2_property_is_writable(struct power_supply *psy, { switch (psp) { case POWER_SUPPLY_PROP_CURRENT_MAX: - case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT: return 1; default: return 0; diff --git a/drivers/power/supply/rn5t618_power.c b/drivers/power/supply/rn5t618_power.c index a5e09ac78a50..ebea3522a2ac 100644 --- a/drivers/power/supply/rn5t618_power.c +++ b/drivers/power/supply/rn5t618_power.c @@ -14,7 +14,6 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/mfd/rn5t618.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/power_supply.h> #include <linux/regmap.h> diff --git a/drivers/power/supply/rt5033_charger.c b/drivers/power/supply/rt5033_charger.c index 5218dfbf5e1b..c0c516f22c66 100644 --- a/drivers/power/supply/rt5033_charger.c +++ b/drivers/power/supply/rt5033_charger.c @@ -6,8 +6,8 @@ * Author: Beomho Seo <beomho.seo@samsung.com> */ +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/power_supply.h> #include <linux/regmap.h> diff --git a/drivers/power/supply/rt9455_charger.c b/drivers/power/supply/rt9455_charger.c index ff4dcf77c788..c345a77f9f78 100644 --- a/drivers/power/supply/rt9455_charger.c +++ b/drivers/power/supply/rt9455_charger.c @@ -8,8 +8,7 @@ #include <linux/module.h> #include <linux/interrupt.h> #include <linux/delay.h> -#include <linux/of_irq.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/pm_runtime.h> #include <linux/power_supply.h> #include <linux/i2c.h> diff --git a/drivers/power/supply/sbs-battery.c b/drivers/power/supply/sbs-battery.c index 62a354e01204..cdfc8466d129 100644 --- a/drivers/power/supply/sbs-battery.c +++ b/drivers/power/supply/sbs-battery.c @@ -16,7 +16,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/property.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/power/sbs-battery.h> #include <linux/power_supply.h> #include <linux/slab.h> diff --git a/drivers/power/supply/tps65090-charger.c b/drivers/power/supply/tps65090-charger.c index 0990b2fa6cd8..f96c705e0a9f 100644 --- a/drivers/power/supply/tps65090-charger.c +++ b/drivers/power/supply/tps65090-charger.c @@ -13,7 +13,7 @@ #include <linux/kernel.h> #include <linux/kthread.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/power_supply.h> #include <linux/slab.h> diff --git a/drivers/power/supply/tps65217_charger.c b/drivers/power/supply/tps65217_charger.c index a4bc9f2a10bc..96341cbde4fa 100644 --- a/drivers/power/supply/tps65217_charger.c +++ b/drivers/power/supply/tps65217_charger.c @@ -17,7 +17,6 @@ #include <linux/slab.h> #include <linux/err.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/power_supply.h> #include <linux/mfd/core.h> diff --git a/drivers/power/supply/twl4030_charger.c b/drivers/power/supply/twl4030_charger.c index 7adfd69fe649..e78d061d8d32 100644 --- a/drivers/power/supply/twl4030_charger.c +++ b/drivers/power/supply/twl4030_charger.c @@ -12,6 +12,7 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/err.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/interrupt.h> #include <linux/mfd/twl.h> diff --git a/drivers/powercap/arm_scmi_powercap.c b/drivers/powercap/arm_scmi_powercap.c index 5231f6d52ae3..a081f177e702 100644 --- a/drivers/powercap/arm_scmi_powercap.c +++ b/drivers/powercap/arm_scmi_powercap.c @@ -12,6 +12,7 @@ #include <linux/module.h> #include <linux/powercap.h> #include <linux/scmi_protocol.h> +#include <linux/slab.h> #define to_scmi_powercap_zone(z) \ container_of(z, struct scmi_powercap_zone, zone) @@ -19,6 +20,8 @@ static const struct scmi_powercap_proto_ops *powercap_ops; struct scmi_powercap_zone { + bool registered; + bool invalid; unsigned int height; struct device *dev; struct scmi_protocol_handle *ph; @@ -32,6 +35,7 @@ struct scmi_powercap_root { unsigned int num_zones; struct scmi_powercap_zone *spzones; struct list_head *registered_zones; + struct list_head scmi_zones; }; static struct powercap_control_type *scmi_top_pcntrl; @@ -271,12 +275,6 @@ static void scmi_powercap_unregister_all_zones(struct scmi_powercap_root *pr) } } -static inline bool -scmi_powercap_is_zone_registered(struct scmi_powercap_zone *spz) -{ - return !list_empty(&spz->node); -} - static inline unsigned int scmi_powercap_get_zone_height(struct scmi_powercap_zone *spz) { @@ -295,11 +293,46 @@ scmi_powercap_get_parent_zone(struct scmi_powercap_zone *spz) return &spz->spzones[spz->info->parent_id]; } +static int scmi_powercap_register_zone(struct scmi_powercap_root *pr, + struct scmi_powercap_zone *spz, + struct scmi_powercap_zone *parent) +{ + int ret = 0; + struct powercap_zone *z; + + if (spz->invalid) { + list_del(&spz->node); + return -EINVAL; + } + + z = powercap_register_zone(&spz->zone, scmi_top_pcntrl, spz->info->name, + parent ? &parent->zone : NULL, + &zone_ops, 1, &constraint_ops); + if (!IS_ERR(z)) { + spz->height = scmi_powercap_get_zone_height(spz); + spz->registered = true; + list_move(&spz->node, &pr->registered_zones[spz->height]); + dev_dbg(spz->dev, "Registered node %s - parent %s - height:%d\n", + spz->info->name, parent ? parent->info->name : "ROOT", + spz->height); + } else { + list_del(&spz->node); + ret = PTR_ERR(z); + dev_err(spz->dev, + "Error registering node:%s - parent:%s - h:%d - ret:%d\n", + spz->info->name, + parent ? parent->info->name : "ROOT", + spz->height, ret); + } + + return ret; +} + /** - * scmi_powercap_register_zone - Register an SCMI powercap zone recursively + * scmi_zones_register- Register SCMI powercap zones starting from parent zones * + * @dev: A reference to the SCMI device * @pr: A reference to the root powercap zones descriptors - * @spz: A reference to the SCMI powercap zone to register * * When registering SCMI powercap zones with the powercap framework we should * take care to always register zones starting from the root ones and to @@ -309,10 +342,10 @@ scmi_powercap_get_parent_zone(struct scmi_powercap_zone *spz) * zones provided by the SCMI platform firmware is built to comply with such * requirement. * - * This function, given an SCMI powercap zone to register, takes care to walk - * the SCMI powercap zones tree up to the root looking recursively for - * unregistered parent zones before registering the provided zone; at the same - * time each registered zone height in such a tree is accounted for and each + * This function, given the set of SCMI powercap zones to register, takes care + * to walk the SCMI powercap zones trees up to the root registering any + * unregistered parent zone before registering the child zones; at the same + * time each registered-zone height in such a tree is accounted for and each * zone, once registered, is stored in the @registered_zones array that is * indexed by zone height: this way will be trivial, at unregister time, to walk * the @registered_zones array backward and unregister all the zones starting @@ -330,57 +363,55 @@ scmi_powercap_get_parent_zone(struct scmi_powercap_zone *spz) * * Return: 0 on Success */ -static int scmi_powercap_register_zone(struct scmi_powercap_root *pr, - struct scmi_powercap_zone *spz) +static int scmi_zones_register(struct device *dev, + struct scmi_powercap_root *pr) { int ret = 0; - struct scmi_powercap_zone *parent; - - if (!spz->info) - return ret; + unsigned int sp = 0, reg_zones = 0; + struct scmi_powercap_zone *spz, **zones_stack; - parent = scmi_powercap_get_parent_zone(spz); - if (parent && !scmi_powercap_is_zone_registered(parent)) { - /* - * Bail out if a parent domain was marked as unsupported: - * only domains participating as leaves can be skipped. - */ - if (!parent->info) - return -ENODEV; + zones_stack = kcalloc(pr->num_zones, sizeof(spz), GFP_KERNEL); + if (!zones_stack) + return -ENOMEM; - ret = scmi_powercap_register_zone(pr, parent); - if (ret) - return ret; - } + spz = list_first_entry_or_null(&pr->scmi_zones, + struct scmi_powercap_zone, node); + while (spz) { + struct scmi_powercap_zone *parent; - if (!scmi_powercap_is_zone_registered(spz)) { - struct powercap_zone *z; - - z = powercap_register_zone(&spz->zone, - scmi_top_pcntrl, - spz->info->name, - parent ? &parent->zone : NULL, - &zone_ops, 1, &constraint_ops); - if (!IS_ERR(z)) { - spz->height = scmi_powercap_get_zone_height(spz); - list_add(&spz->node, - &pr->registered_zones[spz->height]); - dev_dbg(spz->dev, - "Registered node %s - parent %s - height:%d\n", - spz->info->name, - parent ? parent->info->name : "ROOT", - spz->height); - ret = 0; + parent = scmi_powercap_get_parent_zone(spz); + if (parent && !parent->registered) { + zones_stack[sp++] = spz; + spz = parent; } else { - ret = PTR_ERR(z); - dev_err(spz->dev, - "Error registering node:%s - parent:%s - h:%d - ret:%d\n", - spz->info->name, - parent ? parent->info->name : "ROOT", - spz->height, ret); + ret = scmi_powercap_register_zone(pr, spz, parent); + if (!ret) { + reg_zones++; + } else if (sp) { + /* Failed to register a non-leaf zone. + * Bail-out. + */ + dev_err(dev, + "Failed to register non-leaf zone - ret:%d\n", + ret); + scmi_powercap_unregister_all_zones(pr); + reg_zones = 0; + goto out; + } + /* Pick next zone to process */ + if (sp) + spz = zones_stack[--sp]; + else + spz = list_first_entry_or_null(&pr->scmi_zones, + struct scmi_powercap_zone, + node); } } +out: + kfree(zones_stack); + dev_info(dev, "Registered %d SCMI Powercap domains !\n", reg_zones); + return ret; } @@ -424,6 +455,8 @@ static int scmi_powercap_probe(struct scmi_device *sdev) if (!pr->registered_zones) return -ENOMEM; + INIT_LIST_HEAD(&pr->scmi_zones); + for (i = 0, spz = pr->spzones; i < pr->num_zones; i++, spz++) { /* * Powercap domains are validate by the protocol layer, i.e. @@ -438,6 +471,7 @@ static int scmi_powercap_probe(struct scmi_device *sdev) INIT_LIST_HEAD(&spz->node); INIT_LIST_HEAD(&pr->registered_zones[i]); + list_add_tail(&spz->node, &pr->scmi_zones); /* * Forcibly skip powercap domains using an abstract scale. * Note that only leaves domains can be skipped, so this could @@ -448,7 +482,7 @@ static int scmi_powercap_probe(struct scmi_device *sdev) dev_warn(dev, "Abstract power scale not supported. Skip %s.\n", spz->info->name); - spz->info = NULL; + spz->invalid = true; continue; } } @@ -457,21 +491,12 @@ static int scmi_powercap_probe(struct scmi_device *sdev) * Scan array of retrieved SCMI powercap domains and register them * recursively starting from the root domains. */ - for (i = 0, spz = pr->spzones; i < pr->num_zones; i++, spz++) { - ret = scmi_powercap_register_zone(pr, spz); - if (ret) { - dev_err(dev, - "Failed to register powercap zone %s - ret:%d\n", - spz->info->name, ret); - scmi_powercap_unregister_all_zones(pr); - return ret; - } - } + ret = scmi_zones_register(dev, pr); + if (ret) + return ret; dev_set_drvdata(dev, pr); - dev_info(dev, "Registered %d SCMI Powercap domains !\n", pr->num_zones); - return ret; } diff --git a/drivers/powercap/intel_rapl_common.c b/drivers/powercap/intel_rapl_common.c index 8fac57b28f8a..5c2e6d5eea2a 100644 --- a/drivers/powercap/intel_rapl_common.c +++ b/drivers/powercap/intel_rapl_common.c @@ -1250,7 +1250,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = { X86_MATCH_INTEL_FAM6_MODEL(ROCKETLAKE, &rapl_defaults_core), X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, &rapl_defaults_core), X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, &rapl_defaults_core), - X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, &rapl_defaults_core), + X86_MATCH_INTEL_FAM6_MODEL(ATOM_GRACEMONT, &rapl_defaults_core), X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, &rapl_defaults_core), X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, &rapl_defaults_core), X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_S, &rapl_defaults_core), @@ -1485,7 +1485,7 @@ static int rapl_detect_domains(struct rapl_package *rp) } pr_debug("found %d domains on %s\n", rp->nr_domains, rp->name); - rp->domains = kcalloc(rp->nr_domains + 1, sizeof(struct rapl_domain), + rp->domains = kcalloc(rp->nr_domains, sizeof(struct rapl_domain), GFP_KERNEL); if (!rp->domains) return -ENOMEM; diff --git a/drivers/powercap/intel_rapl_msr.c b/drivers/powercap/intel_rapl_msr.c index dd471021f237..250bd41a588c 100644 --- a/drivers/powercap/intel_rapl_msr.c +++ b/drivers/powercap/intel_rapl_msr.c @@ -142,7 +142,7 @@ static const struct x86_cpu_id pl4_support_ids[] = { X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, NULL), X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, NULL), X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, NULL), - X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, NULL), + X86_MATCH_INTEL_FAM6_MODEL(ATOM_GRACEMONT, NULL), X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, NULL), X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, NULL), X86_MATCH_INTEL_FAM6_MODEL(METEORLAKE, NULL), diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 823f8e6e4801..965d4f0c18a6 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -178,6 +178,14 @@ config REGULATOR_ATC260X ATC260x PMICs. This will enable support for all the software controllable DCDC/LDO regulators. +config REGULATOR_AW37503 + tristate "Awinic AW37503 Dual Output Power regulators" + depends on I2C && GPIOLIB + select REGMAP_I2C + help + This driver supports AW37503 single inductor - dual output + power supply specifically designed for display panels. + config REGULATOR_AXP20X tristate "X-POWERS AXP20X PMIC Regulators" depends on MFD_AXP20X @@ -546,11 +554,11 @@ config REGULATOR_MAX1586 regulator via I2C bus. The provided regulator is suitable for PXA27x chips to control VCC_CORE and VCC_USIM voltages. -config REGULATOR_MAX597X - tristate "Maxim 597x power switch and monitor" +config REGULATOR_MAX5970 + tristate "Maxim 5970/5978 power switch and monitor" depends on I2C depends on OF - depends on MFD_MAX597X + depends on MFD_MAX5970 help This driver controls a Maxim 5970/5978 switch via I2C bus. The MAX5970/5978 is a smart switch with no output regulation, but @@ -584,6 +592,16 @@ config REGULATOR_MAX77650 Semiconductor. This device has a SIMO with three independent power rails and an LDO. +config REGULATOR_MAX77857 + tristate "ADI MAX77857/MAX77831 regulator support" + depends on I2C + select REGMAP_I2C + help + This driver controls a ADI MAX77857 and MAX77831 regulators. + via I2C bus. MAX77857 and MAX77831 are high efficiency buck-boost + converters with input voltage range (2.5V to 16V). Say Y here to + enable the regulator driver + config REGULATOR_MAX8649 tristate "Maxim 8649 voltage regulator" depends on I2C @@ -989,6 +1007,18 @@ config REGULATOR_PWM This driver supports PWM controlled voltage regulators. PWM duty cycle can increase or decrease the voltage. +config REGULATOR_QCOM_REFGEN + tristate "Qualcomm REFGEN regulator driver" + depends on ARCH_QCOM || COMPILE_TEST + depends on HAS_IOMEM + depends on REGMAP + help + This driver supports the MMIO-mapped reference voltage regulator, + used internally by some PHYs on many Qualcomm SoCs. + + Say M here if you want to include support for this regulator as + a module. The module will be named "qcom-refgen-regulator". + config REGULATOR_QCOM_RPM tristate "Qualcomm RPM regulator driver" depends on MFD_QCOM_RPM @@ -1050,7 +1080,11 @@ config REGULATOR_RAA215300 depends on COMMON_CLK depends on I2C help - Support for the Renesas RAA215300 PMIC. + If you say yes to this option, support will be included for the + Renesas RAA215300 PMIC. + + Say M here if you want to include support for Renesas RAA215300 PMIC + as a module. The module will be named "raa215300". config REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY tristate "Raspberry Pi 7-inch touchscreen panel ATTINY regulator" @@ -1232,6 +1266,17 @@ config REGULATOR_RTQ6752 synchronous boost converters for PAVDD, and one synchronous NAVDD buck-boost. This device is suitable for automotive TFT-LCD panel. +config REGULATOR_RTQ2208 + tristate "Richtek RTQ2208 SubPMIC Regulator" + depends on I2C + select REGMAP_I2C + help + This driver adds support for RTQ2208 SubPMIC regulators. + The RTQ2208 is a multi-phase, programmable power management IC that + integrate with dual multi-configurable, synchronous buck converters + and two ldos. It features wide output voltage range from 0.4V to 2.05V + and the capability to configure the corresponding power stages. + config REGULATOR_S2MPA01 tristate "Samsung S2MPA01 voltage regulator" depends on MFD_SEC_CORE || COMPILE_TEST diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 15e0d614ff66..23074714a81a 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_REGULATOR_ARM_SCMI) += scmi-regulator.o obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o obj-$(CONFIG_REGULATOR_ATC260X) += atc260x-regulator.o +obj-$(CONFIG_REGULATOR_AW37503) += aw37503-regulator.o obj-$(CONFIG_REGULATOR_AXP20X) += axp20x-regulator.o obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o obj-$(CONFIG_REGULATOR_BD71815) += bd71815-regulator.o @@ -67,7 +68,7 @@ obj-$(CONFIG_REGULATOR_LTC3589) += ltc3589.o obj-$(CONFIG_REGULATOR_LTC3676) += ltc3676.o obj-$(CONFIG_REGULATOR_MAX14577) += max14577-regulator.o obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o -obj-$(CONFIG_REGULATOR_MAX597X) += max597x-regulator.o +obj-$(CONFIG_REGULATOR_MAX5970) += max5970-regulator.o obj-$(CONFIG_REGULATOR_MAX77541) += max77541-regulator.o obj-$(CONFIG_REGULATOR_MAX77620) += max77620-regulator.o obj-$(CONFIG_REGULATOR_MAX77650) += max77650-regulator.o @@ -86,6 +87,7 @@ obj-$(CONFIG_REGULATOR_MAX77686) += max77686-regulator.o obj-$(CONFIG_REGULATOR_MAX77693) += max77693-regulator.o obj-$(CONFIG_REGULATOR_MAX77802) += max77802-regulator.o obj-$(CONFIG_REGULATOR_MAX77826) += max77826-regulator.o +obj-$(CONFIG_REGULATOR_MAX77857) += max77857-regulator.o obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o @@ -108,6 +110,7 @@ obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o obj-$(CONFIG_REGULATOR_MTK_DVFSRC) += mtk-dvfsrc-regulator.o obj-$(CONFIG_REGULATOR_QCOM_LABIBB) += qcom-labibb-regulator.o +obj-$(CONFIG_REGULATOR_QCOM_REFGEN) += qcom-refgen-regulator.o obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o obj-$(CONFIG_REGULATOR_QCOM_RPMH) += qcom-rpmh-regulator.o obj-$(CONFIG_REGULATOR_QCOM_SMD_RPM) += qcom_smd-regulator.o @@ -145,6 +148,7 @@ obj-$(CONFIG_REGULATOR_RT6245) += rt6245-regulator.o obj-$(CONFIG_REGULATOR_RTMV20) += rtmv20-regulator.o obj-$(CONFIG_REGULATOR_RTQ2134) += rtq2134-regulator.o obj-$(CONFIG_REGULATOR_RTQ6752) += rtq6752-regulator.o +obj-$(CONFIG_REGULATOR_RTQ2208) += rtq2208-regulator.o obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o diff --git a/drivers/regulator/act8945a-regulator.c b/drivers/regulator/act8945a-regulator.c index e26264529b74..24cbdd833863 100644 --- a/drivers/regulator/act8945a-regulator.c +++ b/drivers/regulator/act8945a-regulator.c @@ -8,7 +8,7 @@ */ #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/regulator/driver.h> diff --git a/drivers/regulator/atc260x-regulator.c b/drivers/regulator/atc260x-regulator.c index 87e237d740bc..3e9f8fd54fca 100644 --- a/drivers/regulator/atc260x-regulator.c +++ b/drivers/regulator/atc260x-regulator.c @@ -7,7 +7,8 @@ #include <linux/mfd/atc260x/core.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/regulator/driver.h> @@ -37,7 +38,7 @@ static const struct linear_range atc2609a_ldo_voltage_ranges1[] = { }; static const unsigned int atc260x_ldo_voltage_range_sel[] = { - 0x0, 0x20, + 0x0, 0x1, }; static int atc260x_dcdc_set_voltage_time_sel(struct regulator_dev *rdev, @@ -427,7 +428,7 @@ enum atc2609a_reg_ids { .vsel_mask = GENMASK(4, 1), \ .vsel_range_reg = ATC2609A_PMU_LDO##num##_CTL0, \ .vsel_range_mask = BIT(5), \ - .linear_range_selectors = atc260x_ldo_voltage_range_sel, \ + .linear_range_selectors_bitfield = atc260x_ldo_voltage_range_sel, \ .enable_reg = ATC2609A_PMU_LDO##num##_CTL0, \ .enable_mask = BIT(0), \ .enable_time = 2000, \ diff --git a/drivers/regulator/aw37503-regulator.c b/drivers/regulator/aw37503-regulator.c new file mode 100644 index 000000000000..a5ff6dfd29b5 --- /dev/null +++ b/drivers/regulator/aw37503-regulator.c @@ -0,0 +1,240 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// AWINIC AW37503 Regulator Driver +// +// Copyright (C) 2023 awinic. All Rights Reserved +// +// Author: <like@awinic.com> + +#include <linux/err.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> + +#define AW37503_REG_VPOS 0x00 +#define AW37503_REG_VNEG 0x01 +#define AW37503_REG_APPS 0x03 +#define AW37503_REG_CONTROL 0x04 +#define AW37503_REG_WPRTEN 0x21 + +#define AW37503_VOUT_MASK 0x1F +#define AW37503_VOUT_N_VOLTAGE 0x15 +#define AW37503_VOUT_VMIN 4000000 +#define AW37503_VOUT_VMAX 6000000 +#define AW37503_VOUT_STEP 100000 + +#define AW37503_REG_APPS_DIS_VPOS BIT(1) +#define AW37503_REG_APPS_DIS_VNEG BIT(0) + +#define AW37503_REGULATOR_ID_VPOS 0 +#define AW37503_REGULATOR_ID_VNEG 1 +#define AW37503_MAX_REGULATORS 2 + +struct aw37503_reg_pdata { + struct gpio_desc *en_gpiod; + int ena_gpio_state; +}; + +struct aw37503_regulator { + struct device *dev; + struct aw37503_reg_pdata reg_pdata[AW37503_MAX_REGULATORS]; +}; + +static int aw37503_regulator_enable(struct regulator_dev *rdev) +{ + struct aw37503_regulator *chip = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); + struct aw37503_reg_pdata *rpdata = &chip->reg_pdata[id]; + int ret; + + if (!IS_ERR(rpdata->en_gpiod)) { + gpiod_set_value_cansleep(rpdata->en_gpiod, 1); + rpdata->ena_gpio_state = 1; + } + + /* Hardware automatically enable discharge bit in enable */ + if (rdev->constraints->active_discharge == + REGULATOR_ACTIVE_DISCHARGE_DISABLE) { + ret = regulator_set_active_discharge_regmap(rdev, false); + if (ret < 0) { + dev_err(chip->dev, "Failed to disable active discharge: %d\n", + ret); + return ret; + } + } + + return 0; +} + +static int aw37503_regulator_disable(struct regulator_dev *rdev) +{ + struct aw37503_regulator *chip = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); + struct aw37503_reg_pdata *rpdata = &chip->reg_pdata[id]; + + if (!IS_ERR(rpdata->en_gpiod)) { + gpiod_set_value_cansleep(rpdata->en_gpiod, 0); + rpdata->ena_gpio_state = 0; + } + + return 0; +} + +static int aw37503_regulator_is_enabled(struct regulator_dev *rdev) +{ + struct aw37503_regulator *chip = rdev_get_drvdata(rdev); + int id = rdev_get_id(rdev); + struct aw37503_reg_pdata *rpdata = &chip->reg_pdata[id]; + + if (!IS_ERR(rpdata->en_gpiod)) + return rpdata->ena_gpio_state; + + return 1; +} + +static const struct regulator_ops aw37503_regulator_ops = { + .enable = aw37503_regulator_enable, + .disable = aw37503_regulator_disable, + .is_enabled = aw37503_regulator_is_enabled, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .set_active_discharge = regulator_set_active_discharge_regmap, +}; + +static int aw37503_of_parse_cb(struct device_node *np, + const struct regulator_desc *desc, + struct regulator_config *config) +{ + struct aw37503_regulator *chip = config->driver_data; + struct aw37503_reg_pdata *rpdata = &chip->reg_pdata[desc->id]; + int ret; + + rpdata->en_gpiod = devm_fwnode_gpiod_get(chip->dev, of_fwnode_handle(np), + "enable", GPIOD_OUT_LOW, + "enable"); + + if (IS_ERR(rpdata->en_gpiod)) { + ret = PTR_ERR(rpdata->en_gpiod); + + /* Ignore the error other than probe defer */ + if (ret == -EPROBE_DEFER) + return ret; + return 0; + } + + return 0; +} + +#define AW37503_REGULATOR_DESC(_id, _name) \ + [AW37503_REGULATOR_ID_##_id] = { \ + .name = "aw37503-"#_name, \ + .supply_name = "vin", \ + .id = AW37503_REGULATOR_ID_##_id, \ + .of_match = of_match_ptr(#_name), \ + .of_parse_cb = aw37503_of_parse_cb, \ + .ops = &aw37503_regulator_ops, \ + .n_voltages = AW37503_VOUT_N_VOLTAGE, \ + .min_uV = AW37503_VOUT_VMIN, \ + .uV_step = AW37503_VOUT_STEP, \ + .enable_time = 500, \ + .vsel_mask = AW37503_VOUT_MASK, \ + .vsel_reg = AW37503_REG_##_id, \ + .active_discharge_off = 0, \ + .active_discharge_on = AW37503_REG_APPS_DIS_##_id, \ + .active_discharge_mask = AW37503_REG_APPS_DIS_##_id, \ + .active_discharge_reg = AW37503_REG_APPS, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + } + +static const struct regulator_desc aw_regs_desc[AW37503_MAX_REGULATORS] = { + AW37503_REGULATOR_DESC(VPOS, outp), + AW37503_REGULATOR_DESC(VNEG, outn), +}; + +static const struct regmap_range aw37503_no_reg_ranges[] = { + regmap_reg_range(AW37503_REG_CONTROL + 1, + AW37503_REG_WPRTEN - 1), +}; + +static const struct regmap_access_table aw37503_no_reg_table = { + .no_ranges = aw37503_no_reg_ranges, + .n_no_ranges = ARRAY_SIZE(aw37503_no_reg_ranges), +}; + +static const struct regmap_config aw37503_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = AW37503_REG_WPRTEN, + .rd_table = &aw37503_no_reg_table, + .wr_table = &aw37503_no_reg_table, +}; + +static int aw37503_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct aw37503_regulator *chip; + struct regulator_dev *rdev; + struct regmap *regmap; + struct regulator_config config = { }; + int id; + + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + regmap = devm_regmap_init_i2c(client, &aw37503_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), + "Failed to init regmap\n"); + + i2c_set_clientdata(client, chip); + chip->dev = dev; + + config.regmap = regmap; + config.dev = dev; + config.driver_data = chip; + + for (id = 0; id < AW37503_MAX_REGULATORS; ++id) { + rdev = devm_regulator_register(dev, &aw_regs_desc[id], + &config); + if (IS_ERR(rdev)) + return dev_err_probe(dev, PTR_ERR(rdev), + "Failed to register regulator %s\n", + aw_regs_desc[id].name); + } + return 0; +} + +static const struct i2c_device_id aw37503_id[] = { + {.name = "aw37503",}, + {}, +}; +MODULE_DEVICE_TABLE(i2c, aw37503_id); + +static const struct of_device_id aw37503_of_match[] = { + {.compatible = "awinic,aw37503",}, + { /* Sentinel */ }, +}; + +MODULE_DEVICE_TABLE(of, aw37503_of_match); + +static struct i2c_driver aw37503_i2c_driver = { + .driver = { + .name = "aw37503", + .of_match_table = aw37503_of_match, + }, + .probe = aw37503_probe, + .id_table = aw37503_id, +}; + +module_i2c_driver(aw37503_i2c_driver); + +MODULE_DESCRIPTION("aw37503 regulator driver"); +MODULE_AUTHOR("Alec Li <like@awinic.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index 810f90f3e2a1..c657820b0bbb 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -20,7 +20,6 @@ #include <linux/mfd/axp20x.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/regulator/driver.h> diff --git a/drivers/regulator/bd71815-regulator.c b/drivers/regulator/bd71815-regulator.c index 475b1e0110e7..26192d55a685 100644 --- a/drivers/regulator/bd71815-regulator.c +++ b/drivers/regulator/bd71815-regulator.c @@ -18,7 +18,6 @@ #include <linux/regulator/driver.h> #include <linux/delay.h> #include <linux/slab.h> -#include <linux/gpio.h> #include <linux/mfd/rohm-generic.h> #include <linux/mfd/rohm-bd71815.h> #include <linux/regulator/of_regulator.h> diff --git a/drivers/regulator/bd71828-regulator.c b/drivers/regulator/bd71828-regulator.c index f3205dc9d4fc..08d4ee369287 100644 --- a/drivers/regulator/bd71828-regulator.c +++ b/drivers/regulator/bd71828-regulator.c @@ -5,7 +5,6 @@ #include <linux/delay.h> #include <linux/err.h> -#include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/mfd/rohm-bd71828.h> diff --git a/drivers/regulator/bd718x7-regulator.c b/drivers/regulator/bd718x7-regulator.c index b0b9938c20a1..c3fb05dce40c 100644 --- a/drivers/regulator/bd718x7-regulator.c +++ b/drivers/regulator/bd718x7-regulator.c @@ -289,7 +289,7 @@ static const struct linear_range bd71837_buck5_volts[] = { * and 0x1 for last 3 ranges. */ static const unsigned int bd71837_buck5_volt_range_sel[] = { - 0x0, 0x0, 0x0, 0x80, 0x80, 0x80 + 0x0, 0x0, 0x0, 0x1, 0x1, 0x1 }; /* @@ -309,7 +309,7 @@ static const struct linear_range bd71847_buck3_volts[] = { }; static const unsigned int bd71847_buck3_volt_range_sel[] = { - 0x0, 0x0, 0x0, 0x40, 0x80, 0x80, 0x80 + 0x0, 0x0, 0x0, 0x1, 0x2, 0x2, 0x2 }; static const struct linear_range bd71847_buck4_volts[] = { @@ -317,7 +317,7 @@ static const struct linear_range bd71847_buck4_volts[] = { REGULATOR_LINEAR_RANGE(2600000, 0x00, 0x03, 100000), }; -static const unsigned int bd71847_buck4_volt_range_sel[] = { 0x0, 0x40 }; +static const unsigned int bd71847_buck4_volt_range_sel[] = { 0x0, 0x1 }; /* * BUCK6 @@ -360,7 +360,7 @@ static const struct linear_range bd718xx_ldo1_volts[] = { REGULATOR_LINEAR_RANGE(1600000, 0x00, 0x03, 100000), }; -static const unsigned int bd718xx_ldo1_volt_range_sel[] = { 0x0, 0x20 }; +static const unsigned int bd718xx_ldo1_volt_range_sel[] = { 0x0, 0x1 }; /* * LDO2 @@ -403,7 +403,7 @@ static const struct linear_range bd71847_ldo5_volts[] = { REGULATOR_LINEAR_RANGE(800000, 0x00, 0x0F, 100000), }; -static const unsigned int bd71847_ldo5_volt_range_sel[] = { 0x0, 0x20 }; +static const unsigned int bd71847_ldo5_volt_range_sel[] = { 0x0, 0x1 }; /* * LDO6 @@ -817,7 +817,7 @@ static struct bd718xx_regulator_data bd71847_regulators[] = { .vsel_mask = BD718XX_1ST_NODVS_BUCK_MASK, .vsel_range_reg = BD718XX_REG_1ST_NODVS_BUCK_VOLT, .vsel_range_mask = BD71847_BUCK3_RANGE_MASK, - .linear_range_selectors = bd71847_buck3_volt_range_sel, + .linear_range_selectors_bitfield = bd71847_buck3_volt_range_sel, .enable_reg = BD718XX_REG_1ST_NODVS_BUCK_CTRL, .enable_mask = BD718XX_BUCK_EN, .enable_time = BD71847_BUCK3_STARTUP_TIME, @@ -845,7 +845,7 @@ static struct bd718xx_regulator_data bd71847_regulators[] = { .vsel_mask = BD71847_BUCK4_MASK, .vsel_range_reg = BD718XX_REG_2ND_NODVS_BUCK_VOLT, .vsel_range_mask = BD71847_BUCK4_RANGE_MASK, - .linear_range_selectors = bd71847_buck4_volt_range_sel, + .linear_range_selectors_bitfield = bd71847_buck4_volt_range_sel, .enable_mask = BD718XX_BUCK_EN, .enable_time = BD71847_BUCK4_STARTUP_TIME, .owner = THIS_MODULE, @@ -916,7 +916,7 @@ static struct bd718xx_regulator_data bd71847_regulators[] = { .vsel_mask = BD718XX_LDO1_MASK, .vsel_range_reg = BD718XX_REG_LDO1_VOLT, .vsel_range_mask = BD718XX_LDO1_RANGE_MASK, - .linear_range_selectors = bd718xx_ldo1_volt_range_sel, + .linear_range_selectors_bitfield = bd718xx_ldo1_volt_range_sel, .enable_reg = BD718XX_REG_LDO1_VOLT, .enable_mask = BD718XX_LDO_EN, .enable_time = BD71847_LDO1_STARTUP_TIME, @@ -1010,7 +1010,7 @@ static struct bd718xx_regulator_data bd71847_regulators[] = { .vsel_mask = BD71847_LDO5_MASK, .vsel_range_reg = BD718XX_REG_LDO5_VOLT, .vsel_range_mask = BD71847_LDO5_RANGE_MASK, - .linear_range_selectors = bd71847_ldo5_volt_range_sel, + .linear_range_selectors_bitfield = bd71847_ldo5_volt_range_sel, .enable_reg = BD718XX_REG_LDO5_VOLT, .enable_mask = BD718XX_LDO_EN, .enable_time = BD71847_LDO5_STARTUP_TIME, @@ -1232,7 +1232,7 @@ static struct bd718xx_regulator_data bd71837_regulators[] = { .vsel_mask = BD71837_BUCK5_MASK, .vsel_range_reg = BD718XX_REG_1ST_NODVS_BUCK_VOLT, .vsel_range_mask = BD71837_BUCK5_RANGE_MASK, - .linear_range_selectors = bd71837_buck5_volt_range_sel, + .linear_range_selectors_bitfield = bd71837_buck5_volt_range_sel, .enable_reg = BD718XX_REG_1ST_NODVS_BUCK_CTRL, .enable_mask = BD718XX_BUCK_EN, .enable_time = BD71837_BUCK5_STARTUP_TIME, @@ -1328,7 +1328,7 @@ static struct bd718xx_regulator_data bd71837_regulators[] = { .vsel_mask = BD718XX_LDO1_MASK, .vsel_range_reg = BD718XX_REG_LDO1_VOLT, .vsel_range_mask = BD718XX_LDO1_RANGE_MASK, - .linear_range_selectors = bd718xx_ldo1_volt_range_sel, + .linear_range_selectors_bitfield = bd718xx_ldo1_volt_range_sel, .enable_reg = BD718XX_REG_LDO1_VOLT, .enable_mask = BD718XX_LDO_EN, .enable_time = BD71837_LDO1_STARTUP_TIME, diff --git a/drivers/regulator/cpcap-regulator.c b/drivers/regulator/cpcap-regulator.c index 1fd79fb17303..6958d154442b 100644 --- a/drivers/regulator/cpcap-regulator.c +++ b/drivers/regulator/cpcap-regulator.c @@ -12,7 +12,7 @@ #include <linux/err.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> diff --git a/drivers/regulator/da9062-regulator.c b/drivers/regulator/da9062-regulator.c index c28b061eef02..1d354db0c1bd 100644 --- a/drivers/regulator/da9062-regulator.c +++ b/drivers/regulator/da9062-regulator.c @@ -924,7 +924,7 @@ static int da9062_regulator_probe(struct platform_device *pdev) struct da9062_regulator *regl; struct regulator_config config = { }; const struct da9062_regulator_info *rinfo; - int irq, n, ret; + int n, ret; int max_regulators; switch (chip->chip_type) { @@ -1012,12 +1012,11 @@ static int da9062_regulator_probe(struct platform_device *pdev) } /* LDOs overcurrent event support */ - irq = platform_get_irq_byname(pdev, "LDO_LIM"); - if (irq < 0) - return irq; - regulators->irq_ldo_lim = irq; + regulators->irq_ldo_lim = platform_get_irq_byname_optional(pdev, "LDO_LIM"); + if (regulators->irq_ldo_lim < 0) + return 0; - ret = devm_request_threaded_irq(&pdev->dev, irq, + ret = devm_request_threaded_irq(&pdev->dev, regulators->irq_ldo_lim, NULL, da9062_ldo_lim_event, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "LDO_LIM", regulators); diff --git a/drivers/regulator/da9121-regulator.c b/drivers/regulator/da9121-regulator.c index 122124944749..80098035bb13 100644 --- a/drivers/regulator/da9121-regulator.c +++ b/drivers/regulator/da9121-regulator.c @@ -440,7 +440,7 @@ static const struct regulator_desc da9121_reg = { .of_match = "buck1", .of_parse_cb = da9121_of_parse_cb, .owner = THIS_MODULE, - .regulators_node = of_match_ptr("regulators"), + .regulators_node = "regulators", .of_map_mode = da9121_map_mode, .ops = &da9121_buck_ops, .type = REGULATOR_VOLTAGE, @@ -465,7 +465,7 @@ static const struct regulator_desc da9220_reg[2] = { .of_match = "buck1", .of_parse_cb = da9121_of_parse_cb, .owner = THIS_MODULE, - .regulators_node = of_match_ptr("regulators"), + .regulators_node = "regulators", .of_map_mode = da9121_map_mode, .ops = &da9121_buck_ops, .type = REGULATOR_VOLTAGE, @@ -484,7 +484,7 @@ static const struct regulator_desc da9220_reg[2] = { .of_match = "buck2", .of_parse_cb = da9121_of_parse_cb, .owner = THIS_MODULE, - .regulators_node = of_match_ptr("regulators"), + .regulators_node = "regulators", .of_map_mode = da9121_map_mode, .ops = &da9121_buck_ops, .type = REGULATOR_VOLTAGE, @@ -506,7 +506,7 @@ static const struct regulator_desc da9122_reg[2] = { .of_match = "buck1", .of_parse_cb = da9121_of_parse_cb, .owner = THIS_MODULE, - .regulators_node = of_match_ptr("regulators"), + .regulators_node = "regulators", .of_map_mode = da9121_map_mode, .ops = &da9121_buck_ops, .type = REGULATOR_VOLTAGE, @@ -525,7 +525,7 @@ static const struct regulator_desc da9122_reg[2] = { .of_match = "buck2", .of_parse_cb = da9121_of_parse_cb, .owner = THIS_MODULE, - .regulators_node = of_match_ptr("regulators"), + .regulators_node = "regulators", .of_map_mode = da9121_map_mode, .ops = &da9121_buck_ops, .type = REGULATOR_VOLTAGE, @@ -546,7 +546,7 @@ static const struct regulator_desc da9217_reg = { .of_match = "buck1", .of_parse_cb = da9121_of_parse_cb, .owner = THIS_MODULE, - .regulators_node = of_match_ptr("regulators"), + .regulators_node = "regulators", .of_map_mode = da9121_map_mode, .ops = &da9121_buck_ops, .type = REGULATOR_VOLTAGE, @@ -573,7 +573,7 @@ static const struct regulator_desc da9141_reg = { .of_match = "buck1", .of_parse_cb = da9121_of_parse_cb, .owner = THIS_MODULE, - .regulators_node = of_match_ptr("regulators"), + .regulators_node = "regulators", .of_map_mode = da9121_map_mode, .ops = &da9121_buck_ops, .type = REGULATOR_VOLTAGE, @@ -593,7 +593,7 @@ static const struct regulator_desc da9142_reg = { .of_match = "buck1", .of_parse_cb = da9121_of_parse_cb, .owner = THIS_MODULE, - .regulators_node = of_match_ptr("regulators"), + .regulators_node = "regulators", .of_map_mode = da9121_map_mode, .ops = &da9121_buck_ops, .type = REGULATOR_VOLTAGE, @@ -1195,7 +1195,7 @@ static struct i2c_driver da9121_regulator_driver = { .driver = { .name = "da9121", .probe_type = PROBE_PREFER_ASYNCHRONOUS, - .of_match_table = of_match_ptr(da9121_dt_ids), + .of_match_table = da9121_dt_ids, }, .probe = da9121_i2c_probe, .remove = da9121_i2c_remove, diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c index 289c06e09f47..48f312167e53 100644 --- a/drivers/regulator/fan53555.c +++ b/drivers/regulator/fan53555.c @@ -12,7 +12,7 @@ #include <linux/err.h> #include <linux/i2c.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/param.h> #include <linux/platform_device.h> #include <linux/regmap.h> diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 364d1a2683b7..55130efae9b8 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -25,7 +25,6 @@ #include <linux/gpio/consumer.h> #include <linux/slab.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/regulator/of_regulator.h> #include <linux/regulator/machine.h> #include <linux/clk.h> diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c index e6c999ba3fa2..5ad5f3b3a6b5 100644 --- a/drivers/regulator/helpers.c +++ b/drivers/regulator/helpers.c @@ -5,13 +5,14 @@ // Copyright 2007, 2008 Wolfson Microelectronics PLC. // Copyright 2008 SlimLogic Ltd. -#include <linux/kernel.h> -#include <linux/err.h> +#include <linux/bitops.h> #include <linux/delay.h> +#include <linux/err.h> +#include <linux/export.h> +#include <linux/kernel.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/regulator/driver.h> -#include <linux/module.h> #include "internal.h" @@ -104,13 +105,14 @@ static int regulator_range_selector_to_index(struct regulator_dev *rdev, { int i; - if (!rdev->desc->linear_range_selectors) + if (!rdev->desc->linear_range_selectors_bitfield) return -EINVAL; rval &= rdev->desc->vsel_range_mask; + rval >>= ffs(rdev->desc->vsel_range_mask) - 1; for (i = 0; i < rdev->desc->n_linear_ranges; i++) { - if (rdev->desc->linear_range_selectors[i] == rval) + if (rdev->desc->linear_range_selectors_bitfield[i] == rval) return i; } return -EINVAL; @@ -194,7 +196,8 @@ int regulator_set_voltage_sel_pickable_regmap(struct regulator_dev *rdev, sel <<= ffs(rdev->desc->vsel_mask) - 1; sel += rdev->desc->linear_ranges[i].min_sel; - range = rdev->desc->linear_range_selectors[i]; + range = rdev->desc->linear_range_selectors_bitfield[i]; + range <<= ffs(rdev->desc->vsel_mask) - 1; if (rdev->desc->vsel_reg == rdev->desc->vsel_range_reg) { ret = regmap_update_bits(rdev->regmap, diff --git a/drivers/regulator/hi6421-regulator.c b/drivers/regulator/hi6421-regulator.c index 1b52423598d3..82e9e364d4d4 100644 --- a/drivers/regulator/hi6421-regulator.c +++ b/drivers/regulator/hi6421-regulator.c @@ -131,8 +131,8 @@ static const struct regulator_ops hi6421_buck345_ops; [HI6421_##_id] = { \ .desc = { \ .name = #_id, \ - .of_match = of_match_ptr(#_match), \ - .regulators_node = of_match_ptr("regulators"), \ + .of_match = #_match, \ + .regulators_node = "regulators", \ .ops = &hi6421_ldo_ops, \ .type = REGULATOR_VOLTAGE, \ .id = HI6421_##_id, \ @@ -170,8 +170,8 @@ static const struct regulator_ops hi6421_buck345_ops; [HI6421_##_id] = { \ .desc = { \ .name = #_id, \ - .of_match = of_match_ptr(#_match), \ - .regulators_node = of_match_ptr("regulators"), \ + .of_match = #_match, \ + .regulators_node = "regulators", \ .ops = &hi6421_ldo_linear_ops, \ .type = REGULATOR_VOLTAGE, \ .id = HI6421_##_id, \ @@ -210,8 +210,8 @@ static const struct regulator_ops hi6421_buck345_ops; [HI6421_##_id] = { \ .desc = { \ .name = #_id, \ - .of_match = of_match_ptr(#_match), \ - .regulators_node = of_match_ptr("regulators"), \ + .of_match = #_match, \ + .regulators_node = "regulators", \ .ops = &hi6421_ldo_linear_range_ops, \ .type = REGULATOR_VOLTAGE, \ .id = HI6421_##_id, \ @@ -247,8 +247,8 @@ static const struct regulator_ops hi6421_buck345_ops; [HI6421_##_id] = { \ .desc = { \ .name = #_id, \ - .of_match = of_match_ptr(#_match), \ - .regulators_node = of_match_ptr("regulators"), \ + .of_match = #_match, \ + .regulators_node = "regulators", \ .ops = &hi6421_buck012_ops, \ .type = REGULATOR_VOLTAGE, \ .id = HI6421_##_id, \ @@ -284,8 +284,8 @@ static const struct regulator_ops hi6421_buck345_ops; [HI6421_##_id] = { \ .desc = { \ .name = #_id, \ - .of_match = of_match_ptr(#_match), \ - .regulators_node = of_match_ptr("regulators"), \ + .of_match = #_match, \ + .regulators_node = "regulators", \ .ops = &hi6421_buck345_ops, \ .type = REGULATOR_VOLTAGE, \ .id = HI6421_##_id, \ diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 63aa227b1813..942f37082cb1 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c @@ -864,7 +864,7 @@ static struct lp872x_platform_data for (i = 0; i < num_matches; i++) { pdata->regulator_data[i].id = - (enum lp872x_regulator_id)match[i].driver_data; + (uintptr_t)match[i].driver_data; pdata->regulator_data[i].init_data = match[i].init_data; } out: diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c index 4bc310f972ed..8d01e18046f3 100644 --- a/drivers/regulator/lp8755.c +++ b/drivers/regulator/lp8755.c @@ -13,7 +13,6 @@ #include <linux/err.h> #include <linux/irq.h> #include <linux/interrupt.h> -#include <linux/gpio.h> #include <linux/regmap.h> #include <linux/uaccess.h> #include <linux/regulator/driver.h> diff --git a/drivers/regulator/lp87565-regulator.c b/drivers/regulator/lp87565-regulator.c index bdb60d8a7f3d..61ee5cf3f241 100644 --- a/drivers/regulator/lp87565-regulator.c +++ b/drivers/regulator/lp87565-regulator.c @@ -29,8 +29,8 @@ enum LP87565_regulator_id { .name = _name, \ .supply_name = _of "-in", \ .id = _id, \ - .of_match = of_match_ptr(_of), \ - .regulators_node = of_match_ptr("regulators"),\ + .of_match = _of, \ + .regulators_node = "regulators", \ .ops = &_ops, \ .n_voltages = _n, \ .type = REGULATOR_VOLTAGE, \ diff --git a/drivers/regulator/ltc3589.c b/drivers/regulator/ltc3589.c index e9751c206d95..d892c2a5df7b 100644 --- a/drivers/regulator/ltc3589.c +++ b/drivers/regulator/ltc3589.c @@ -10,7 +10,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/regmap.h> #include <linux/regulator/driver.h> #include <linux/regulator/of_regulator.h> @@ -392,8 +391,7 @@ static int ltc3589_probe(struct i2c_client *client) i2c_set_clientdata(client, ltc3589); if (client->dev.of_node) - ltc3589->variant = (enum ltc3589_variant) - of_device_get_match_data(&client->dev); + ltc3589->variant = (uintptr_t)of_device_get_match_data(&client->dev); else ltc3589->variant = id->driver_data; ltc3589->dev = dev; diff --git a/drivers/regulator/max20086-regulator.c b/drivers/regulator/max20086-regulator.c index fad31f5f435e..32f47b896fd1 100644 --- a/drivers/regulator/max20086-regulator.c +++ b/drivers/regulator/max20086-regulator.c @@ -6,7 +6,6 @@ // Copyright (C) 2018 Avnet, Inc. #include <linux/err.h> -#include <linux/gpio.h> #include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/module.h> diff --git a/drivers/regulator/max597x-regulator.c b/drivers/regulator/max5970-regulator.c index 7873a5267555..b56a174cde3d 100644 --- a/drivers/regulator/max597x-regulator.c +++ b/drivers/regulator/max5970-regulator.c @@ -20,9 +20,9 @@ #include <linux/regulator/of_regulator.h> #include <linux/platform_device.h> -#include <linux/mfd/max597x.h> +#include <linux/mfd/max5970.h> -struct max597x_regulator { +struct max5970_regulator { int num_switches, mon_rng, irng, shunt_micro_ohms, lim_uA; struct regmap *regmap; }; @@ -58,7 +58,7 @@ static int max597x_set_vp(struct regulator_dev *rdev, int lim_uV, int severity, bool enable, bool overvoltage) { int off_h, off_l, reg, ret; - struct max597x_regulator *data = rdev_get_drvdata(rdev); + struct max5970_regulator *data = rdev_get_drvdata(rdev); int channel = rdev_get_id(rdev); if (overvoltage) { @@ -140,7 +140,7 @@ static int max597x_set_ocp(struct regulator_dev *rdev, int lim_uA, int val, reg; unsigned int vthst, vthfst; - struct max597x_regulator *data = rdev_get_drvdata(rdev); + struct max5970_regulator *data = rdev_get_drvdata(rdev); int rdev_id = rdev_get_id(rdev); /* * MAX5970 doesn't has enable control for ocp. @@ -222,7 +222,7 @@ static int max597x_dt_parse(struct device_node *np, const struct regulator_desc *desc, struct regulator_config *cfg) { - struct max597x_regulator *data = cfg->driver_data; + struct max5970_regulator *data = cfg->driver_data; int ret = 0; ret = @@ -274,7 +274,7 @@ static int max597x_irq_handler(int irq, struct regulator_irq_data *rid, unsigned long *dev_mask) { struct regulator_err_state *stat; - struct max597x_regulator *d = (struct max597x_regulator *)rid->data; + struct max5970_regulator *d = (struct max5970_regulator *)rid->data; int val, ret, i; ret = max597x_regmap_read_clear(d->regmap, MAX5970_REG_FAULT0, &val); @@ -394,7 +394,7 @@ static int max597x_adc_range(struct regmap *regmap, const int ch, static int max597x_setup_irq(struct device *dev, int irq, struct regulator_dev *rdevs[MAX5970_NUM_SWITCHES], - int num_switches, struct max597x_regulator *data) + int num_switches, struct max5970_regulator *data) { struct regulator_irq_desc max597x_notif = { .name = "max597x-irq", @@ -425,9 +425,9 @@ static int max597x_setup_irq(struct device *dev, static int max597x_regulator_probe(struct platform_device *pdev) { - struct max597x_data *max597x; + struct max5970_data *max597x; struct regmap *regmap = dev_get_regmap(pdev->dev.parent, NULL); - struct max597x_regulator *data; + struct max5970_regulator *data; struct i2c_client *i2c = to_i2c_client(pdev->dev.parent); struct regulator_config config = { }; struct regulator_dev *rdev; @@ -438,16 +438,16 @@ static int max597x_regulator_probe(struct platform_device *pdev) if (!regmap) return -EPROBE_DEFER; - max597x = devm_kzalloc(&i2c->dev, sizeof(struct max597x_data), GFP_KERNEL); + max597x = devm_kzalloc(&i2c->dev, sizeof(struct max5970_data), GFP_KERNEL); if (!max597x) return -ENOMEM; i2c_set_clientdata(i2c, max597x); if (of_device_is_compatible(i2c->dev.of_node, "maxim,max5978")) - max597x->num_switches = MAX597x_TYPE_MAX5978; + max597x->num_switches = MAX5978_NUM_SWITCHES; else if (of_device_is_compatible(i2c->dev.of_node, "maxim,max5970")) - max597x->num_switches = MAX597x_TYPE_MAX5970; + max597x->num_switches = MAX5970_NUM_SWITCHES; else return -ENODEV; @@ -456,7 +456,7 @@ static int max597x_regulator_probe(struct platform_device *pdev) for (i = 0; i < num_switches; i++) { data = - devm_kzalloc(&i2c->dev, sizeof(struct max597x_regulator), + devm_kzalloc(&i2c->dev, sizeof(struct max5970_regulator), GFP_KERNEL); if (!data) return -ENOMEM; @@ -500,7 +500,7 @@ static int max597x_regulator_probe(struct platform_device *pdev) static struct platform_driver max597x_regulator_driver = { .driver = { - .name = "max597x-regulator", + .name = "max5970-regulator", .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, .probe = max597x_regulator_probe, diff --git a/drivers/regulator/max77541-regulator.c b/drivers/regulator/max77541-regulator.c index 2976f9cb3e26..e6b3d9147c37 100644 --- a/drivers/regulator/max77541-regulator.c +++ b/drivers/regulator/max77541-regulator.c @@ -44,7 +44,7 @@ static const struct linear_range max77541_buck_ranges[] = { }; static const unsigned int max77541_buck_volt_range_sel[] = { - 0x00, 0x00, 0x40, 0x40, 0x80, 0x80, + 0x0, 0x0, 0x1, 0x1, 0x2, 0x2, }; enum max77541_regulators { @@ -67,7 +67,7 @@ enum max77541_regulators { .vsel_mask = MAX77541_BITS_MX_VOUT, \ .vsel_range_reg = MAX77541_REG_M ## _id ## _CFG1, \ .vsel_range_mask = MAX77541_BITS_MX_CFG1_RNG, \ - .linear_range_selectors = max77541_buck_volt_range_sel, \ + .linear_range_selectors_bitfield = max77541_buck_volt_range_sel, \ .owner = THIS_MODULE, \ } @@ -86,7 +86,7 @@ enum max77541_regulators { .vsel_mask = MAX77541_BITS_MX_VOUT, \ .vsel_range_reg = MAX77541_REG_M ## _id ## _CFG1, \ .vsel_range_mask = MAX77541_BITS_MX_CFG1_RNG, \ - .linear_range_selectors = max77541_buck_volt_range_sel, \ + .linear_range_selectors_bitfield = max77541_buck_volt_range_sel, \ .owner = THIS_MODULE, \ } diff --git a/drivers/regulator/max77650-regulator.c b/drivers/regulator/max77650-regulator.c index f6539b945037..94abfbb2bc1e 100644 --- a/drivers/regulator/max77650-regulator.c +++ b/drivers/regulator/max77650-regulator.c @@ -239,7 +239,7 @@ static struct max77650_regulator_desc max77651_SBB1_desc = { .supply_name = "in-sbb1", .id = MAX77650_REGULATOR_ID_SBB1, .ops = &max77651_SBB1_regulator_ops, - .linear_range_selectors = max77651_sbb1_volt_range_sel, + .linear_range_selectors_bitfield = max77651_sbb1_volt_range_sel, .linear_ranges = max77651_sbb1_volt_ranges, .n_linear_ranges = ARRAY_SIZE(max77651_sbb1_volt_ranges), .n_voltages = 58, diff --git a/drivers/regulator/max77826-regulator.c b/drivers/regulator/max77826-regulator.c index 3855f5e686d8..5590cdf615b7 100644 --- a/drivers/regulator/max77826-regulator.c +++ b/drivers/regulator/max77826-regulator.c @@ -9,7 +9,6 @@ #include <linux/init.h> #include <linux/err.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/of_regulator.h> diff --git a/drivers/regulator/max77857-regulator.c b/drivers/regulator/max77857-regulator.c new file mode 100644 index 000000000000..145ad0281857 --- /dev/null +++ b/drivers/regulator/max77857-regulator.c @@ -0,0 +1,461 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2023 Analog Devices, Inc. + * ADI Regulator driver for the MAX77857 + * MAX77859 and MAX77831. + */ +#include <linux/bitfield.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> +#include <linux/util_macros.h> + +#define MAX77857_REG_INT_SRC 0x10 +#define MAX77857_REG_INT_MASK 0x11 +#define MAX77857_REG_CONT1 0x12 +#define MAX77857_REG_CONT2 0x13 +#define MAX77857_REG_CONT3 0x14 + +#define MAX77857_INT_SRC_OCP BIT(0) +#define MAX77857_INT_SRC_THS BIT(1) +#define MAX77857_INT_SRC_HARDSHORT BIT(2) +#define MAX77857_INT_SRC_OVP BIT(3) +#define MAX77857_INT_SRC_POK BIT(4) + +#define MAX77857_ILIM_MASK GENMASK(2, 0) +#define MAX77857_CONT1_FREQ GENMASK(4, 3) +#define MAX77857_CONT3_FPWM BIT(5) + +#define MAX77859_REG_INT_SRC 0x11 +#define MAX77859_REG_CONT1 0x13 +#define MAX77859_REG_CONT2 0x14 +#define MAX77859_REG_CONT3 0x15 +#define MAX77859_REG_CONT5 0x17 +#define MAX77859_CONT2_FPWM BIT(2) +#define MAX77859_CONT2_INTB BIT(3) +#define MAX77859_CONT3_DVS_START BIT(2) +#define MAX77859_VOLTAGE_SEL_MASK GENMASK(9, 0) + +#define MAX77859_CURRENT_MIN 1000000 +#define MAX77859_CURRENT_MAX 5000000 +#define MAX77859_CURRENT_STEP 50000 + +enum max77857_id { + ID_MAX77831 = 1, + ID_MAX77857, + ID_MAX77859, + ID_MAX77859A, +}; + +static bool max77857_volatile_reg(struct device *dev, unsigned int reg) +{ + enum max77857_id id = (uintptr_t)dev_get_drvdata(dev); + + switch (id) { + case ID_MAX77831: + case ID_MAX77857: + return reg == MAX77857_REG_INT_SRC; + case ID_MAX77859: + case ID_MAX77859A: + return reg == MAX77859_REG_INT_SRC; + default: + return true; + } +} + +static struct regmap_config max77857_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .cache_type = REGCACHE_MAPLE, + .volatile_reg = max77857_volatile_reg, +}; + +static int max77857_get_status(struct regulator_dev *rdev) +{ + unsigned int val; + int ret; + + ret = regmap_read(rdev->regmap, MAX77857_REG_INT_SRC, &val); + if (ret) + return ret; + + if (FIELD_GET(MAX77857_INT_SRC_POK, val)) + return REGULATOR_STATUS_ON; + + return REGULATOR_STATUS_ERROR; +} + +static unsigned int max77857_get_mode(struct regulator_dev *rdev) +{ + enum max77857_id id = (uintptr_t)rdev_get_drvdata(rdev); + unsigned int regval; + int ret; + + switch (id) { + case ID_MAX77831: + case ID_MAX77857: + ret = regmap_read(rdev->regmap, MAX77857_REG_CONT3, ®val); + if (ret) + return ret; + + if (FIELD_GET(MAX77857_CONT3_FPWM, regval)) + return REGULATOR_MODE_FAST; + + break; + case ID_MAX77859: + case ID_MAX77859A: + ret = regmap_read(rdev->regmap, MAX77859_REG_CONT2, ®val); + if (ret) + return ret; + + if (FIELD_GET(MAX77859_CONT2_FPWM, regval)) + return REGULATOR_MODE_FAST; + + break; + default: + return -EINVAL; + } + + return REGULATOR_MODE_NORMAL; +} + +static int max77857_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + enum max77857_id id = (uintptr_t)rdev_get_drvdata(rdev); + unsigned int reg, val; + + switch (id) { + case ID_MAX77831: + case ID_MAX77857: + reg = MAX77857_REG_CONT3; + val = MAX77857_CONT3_FPWM; + break; + case ID_MAX77859: + case ID_MAX77859A: + reg = MAX77859_REG_CONT2; + val = MAX77859_CONT2_FPWM; + break; + default: + return -EINVAL; + } + + switch (mode) { + case REGULATOR_MODE_FAST: + return regmap_set_bits(rdev->regmap, reg, val); + case REGULATOR_MODE_NORMAL: + return regmap_clear_bits(rdev->regmap, reg, val); + default: + return -EINVAL; + } +} + +static int max77857_get_error_flags(struct regulator_dev *rdev, + unsigned int *flags) +{ + unsigned int val; + int ret; + + ret = regmap_read(rdev->regmap, MAX77857_REG_INT_SRC, &val); + if (ret) + return ret; + + *flags = 0; + + if (FIELD_GET(MAX77857_INT_SRC_OVP, val)) + *flags |= REGULATOR_ERROR_OVER_VOLTAGE_WARN; + + if (FIELD_GET(MAX77857_INT_SRC_OCP, val) || + FIELD_GET(MAX77857_INT_SRC_HARDSHORT, val)) + *flags |= REGULATOR_ERROR_OVER_CURRENT; + + if (FIELD_GET(MAX77857_INT_SRC_THS, val)) + *flags |= REGULATOR_ERROR_OVER_TEMP; + + if (!FIELD_GET(MAX77857_INT_SRC_POK, val)) + *flags |= REGULATOR_ERROR_FAIL; + + return 0; +} + +static struct linear_range max77859_lin_ranges[] = { + REGULATOR_LINEAR_RANGE(3200000, 0x0A0, 0x320, 20000) +}; + +static const unsigned int max77859_ramp_table[4] = { + 1000, 500, 250, 125 +}; + +static int max77859_set_voltage_sel(struct regulator_dev *rdev, + unsigned int sel) +{ + __be16 reg; + int ret; + + reg = cpu_to_be16(sel); + + ret = regmap_bulk_write(rdev->regmap, MAX77859_REG_CONT3, ®, 2); + if (ret) + return ret; + + /* actually apply new voltage */ + return regmap_set_bits(rdev->regmap, MAX77859_REG_CONT3, + MAX77859_CONT3_DVS_START); +} + +static int max77859_get_voltage_sel(struct regulator_dev *rdev) +{ + __be16 reg; + int ret; + + ret = regmap_bulk_read(rdev->regmap, MAX77859_REG_CONT3, ®, 2); + if (ret) + return ret; + + return FIELD_GET(MAX77859_VOLTAGE_SEL_MASK, __be16_to_cpu(reg)); +} + +static int max77859_set_current_limit(struct regulator_dev *rdev, int min_uA, int max_uA) +{ + u32 selector; + + if (max_uA < MAX77859_CURRENT_MIN) + return -EINVAL; + + selector = 0x12 + (max_uA - MAX77859_CURRENT_MIN) / MAX77859_CURRENT_STEP; + + selector = clamp_val(selector, 0x00, 0x7F); + + return regmap_write(rdev->regmap, MAX77859_REG_CONT5, selector); +} + +static int max77859_get_current_limit(struct regulator_dev *rdev) +{ + u32 selector; + int ret; + + ret = regmap_read(rdev->regmap, MAX77859_REG_CONT5, &selector); + if (ret) + return ret; + + if (selector <= 0x12) + return MAX77859_CURRENT_MIN; + + if (selector >= 0x64) + return MAX77859_CURRENT_MAX; + + return MAX77859_CURRENT_MIN + (selector - 0x12) * MAX77859_CURRENT_STEP; +} + +static const struct regulator_ops max77859_regulator_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .set_voltage_sel = max77859_set_voltage_sel, + .get_voltage_sel = max77859_get_voltage_sel, + .set_ramp_delay = regulator_set_ramp_delay_regmap, + .get_status = max77857_get_status, + .set_mode = max77857_set_mode, + .get_mode = max77857_get_mode, + .get_error_flags = max77857_get_error_flags, +}; + +static const struct regulator_ops max77859a_regulator_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .set_voltage_sel = max77859_set_voltage_sel, + .get_voltage_sel = max77859_get_voltage_sel, + .set_current_limit = max77859_set_current_limit, + .get_current_limit = max77859_get_current_limit, + .set_ramp_delay = regulator_set_ramp_delay_regmap, + .get_status = max77857_get_status, + .set_mode = max77857_set_mode, + .get_mode = max77857_get_mode, + .get_error_flags = max77857_get_error_flags, +}; + +static const struct regulator_ops max77857_regulator_ops = { + .list_voltage = regulator_list_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_ramp_delay = regulator_set_ramp_delay_regmap, + .get_status = max77857_get_status, + .set_mode = max77857_set_mode, + .get_mode = max77857_get_mode, + .get_error_flags = max77857_get_error_flags, +}; + +static struct linear_range max77857_lin_ranges[] = { + REGULATOR_LINEAR_RANGE(4485000, 0x3D, 0xCC, 73500) +}; + +static const unsigned int max77857_switch_freq[] = { + 1200000, 1500000, 1800000, 2100000 +}; + +#define RAMAP_DELAY_INIT_VAL 1333 + +static const unsigned int max77857_ramp_table[2][4] = { + { RAMAP_DELAY_INIT_VAL, 667, 333, 227 }, /* when switch freq is 1.8MHz or 2.1MHz */ + { 1166, 667, 333, 167 }, /* when switch freq is 1.2MHz or 1.5MHz */ +}; + +static struct regulator_desc max77857_regulator_desc = { + .ops = &max77857_regulator_ops, + .name = "max77857", + .linear_ranges = max77857_lin_ranges, + .n_linear_ranges = ARRAY_SIZE(max77857_lin_ranges), + .vsel_mask = 0xFF, + .vsel_reg = MAX77857_REG_CONT2, + .ramp_delay_table = max77857_ramp_table[0], + .n_ramp_values = ARRAY_SIZE(max77857_ramp_table[0]), + .ramp_reg = MAX77857_REG_CONT3, + .ramp_mask = GENMASK(1, 0), + .ramp_delay = RAMAP_DELAY_INIT_VAL, + .owner = THIS_MODULE, +}; + +static void max77857_calc_range(struct device *dev, enum max77857_id id) +{ + struct linear_range *range; + unsigned long vref_step; + u32 rtop = 0; + u32 rbot = 0; + + device_property_read_u32(dev, "adi,rtop-ohms", &rtop); + device_property_read_u32(dev, "adi,rbot-ohms", &rbot); + + if (!rbot || !rtop) + return; + + switch (id) { + case ID_MAX77831: + case ID_MAX77857: + range = max77857_lin_ranges; + vref_step = 4900UL; + break; + case ID_MAX77859: + case ID_MAX77859A: + range = max77859_lin_ranges; + vref_step = 1250UL; + break; + } + + range->step = DIV_ROUND_CLOSEST(vref_step * (rbot + rtop), rbot); + range->min = range->step * range->min_sel; +} + +static int max77857_probe(struct i2c_client *client) +{ + const struct i2c_device_id *i2c_id; + struct device *dev = &client->dev; + struct regulator_config cfg = { }; + struct regulator_dev *rdev; + struct regmap *regmap; + enum max77857_id id; + u32 switch_freq = 0; + int ret; + + i2c_id = i2c_client_get_device_id(client); + if (!i2c_id) + return -EINVAL; + + id = i2c_id->driver_data; + + dev_set_drvdata(dev, (void *)id); + + if (id == ID_MAX77859 || id == ID_MAX77859A) { + max77857_regulator_desc.ops = &max77859_regulator_ops; + max77857_regulator_desc.linear_ranges = max77859_lin_ranges; + max77857_regulator_desc.ramp_delay_table = max77859_ramp_table; + max77857_regulator_desc.ramp_delay = max77859_ramp_table[0]; + } + + if (id == ID_MAX77859A) + max77857_regulator_desc.ops = &max77859a_regulator_ops; + + max77857_calc_range(dev, id); + + regmap = devm_regmap_init_i2c(client, &max77857_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), + "cannot initialize regmap\n"); + + device_property_read_u32(dev, "adi,switch-frequency-hz", &switch_freq); + if (switch_freq) { + switch_freq = find_closest(switch_freq, max77857_switch_freq, + ARRAY_SIZE(max77857_switch_freq)); + + if (id == ID_MAX77831 && switch_freq == 3) + switch_freq = 2; + + switch (id) { + case ID_MAX77831: + case ID_MAX77857: + ret = regmap_update_bits(regmap, MAX77857_REG_CONT1, + MAX77857_CONT1_FREQ, switch_freq); + + if (switch_freq >= 2) + break; + + max77857_regulator_desc.ramp_delay_table = max77857_ramp_table[1]; + max77857_regulator_desc.ramp_delay = max77857_ramp_table[1][0]; + break; + case ID_MAX77859: + case ID_MAX77859A: + ret = regmap_update_bits(regmap, MAX77859_REG_CONT1, + MAX77857_CONT1_FREQ, switch_freq); + break; + } + if (ret) + return ret; + } + + cfg.dev = dev; + cfg.driver_data = (void *)id; + cfg.regmap = regmap; + cfg.init_data = of_get_regulator_init_data(dev, dev->of_node, + &max77857_regulator_desc); + if (!cfg.init_data) + return -ENOMEM; + + rdev = devm_regulator_register(dev, &max77857_regulator_desc, &cfg); + if (IS_ERR(rdev)) + return dev_err_probe(dev, PTR_ERR(rdev), + "cannot register regulator\n"); + + return 0; +} + +const struct i2c_device_id max77857_id[] = { + { "max77831", ID_MAX77831 }, + { "max77857", ID_MAX77857 }, + { "max77859", ID_MAX77859 }, + { "max77859a", ID_MAX77859A }, + { } +}; +MODULE_DEVICE_TABLE(i2c, max77857_id); + +static const struct of_device_id max77857_of_id[] = { + { .compatible = "adi,max77831", .data = (void *)ID_MAX77831 }, + { .compatible = "adi,max77857", .data = (void *)ID_MAX77857 }, + { .compatible = "adi,max77859", .data = (void *)ID_MAX77859 }, + { .compatible = "adi,max77859a", .data = (void *)ID_MAX77859A }, + { } +}; +MODULE_DEVICE_TABLE(of, max77857_of_id); + +static struct i2c_driver max77857_driver = { + .driver = { + .name = "max77857", + .of_match_table = max77857_of_id, + }, + .id_table = max77857_id, + .probe = max77857_probe, +}; +module_i2c_driver(max77857_driver); + +MODULE_DESCRIPTION("Analog Devices MAX77857 Buck-Boost Converter Driver"); +MODULE_AUTHOR("Ibrahim Tilki <Ibrahim.Tilki@analog.com>"); +MODULE_AUTHOR("Okan Sahin <Okan.Sahin@analog.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/max8893.c b/drivers/regulator/max8893.c index cb0e72948dd4..30592425e193 100644 --- a/drivers/regulator/max8893.c +++ b/drivers/regulator/max8893.c @@ -125,7 +125,7 @@ static const struct regmap_config max8893_regmap = { .val_bits = 8, }; -static int max8893_probe_new(struct i2c_client *i2c) +static int max8893_probe(struct i2c_client *i2c) { int id, ret; struct regulator_config config = {.dev = &i2c->dev}; @@ -168,7 +168,7 @@ static const struct i2c_device_id max8893_ids[] = { MODULE_DEVICE_TABLE(i2c, max8893_ids); static struct i2c_driver max8893_driver = { - .probe = max8893_probe_new, + .probe = max8893_probe, .driver = { .name = "max8893", .probe_type = PROBE_PREFER_ASYNCHRONOUS, diff --git a/drivers/regulator/mcp16502.c b/drivers/regulator/mcp16502.c index 6c6f5a21362b..0c15a19fe83a 100644 --- a/drivers/regulator/mcp16502.c +++ b/drivers/regulator/mcp16502.c @@ -8,7 +8,6 @@ // // Inspired from tps65086-regulator.c -#include <linux/gpio.h> #include <linux/i2c.h> #include <linux/init.h> #include <linux/kernel.h> @@ -111,7 +110,7 @@ static unsigned int mcp16502_of_map_mode(unsigned int mode) #define MCP16502_REGULATOR(_name, _id, _ranges, _ops, _ramp_table) \ [_id] = { \ .name = _name, \ - .regulators_node = of_match_ptr("regulators"), \ + .regulators_node = "regulators", \ .id = _id, \ .ops = &(_ops), \ .type = REGULATOR_VOLTAGE, \ @@ -120,7 +119,7 @@ static unsigned int mcp16502_of_map_mode(unsigned int mode) .linear_ranges = _ranges, \ .linear_min_sel = VDD_LOW_SEL, \ .n_linear_ranges = ARRAY_SIZE(_ranges), \ - .of_match = of_match_ptr(_name), \ + .of_match = _name, \ .of_map_mode = mcp16502_of_map_mode, \ .vsel_reg = (((_id) + 1) << 4), \ .vsel_mask = MCP16502_VSEL, \ @@ -588,7 +587,7 @@ static struct i2c_driver mcp16502_drv = { .driver = { .name = "mcp16502-regulator", .probe_type = PROBE_PREFER_ASYNCHRONOUS, - .of_match_table = of_match_ptr(mcp16502_ids), + .of_match_table = mcp16502_ids, #ifdef CONFIG_PM .pm = &mcp16502_pm_ops, #endif diff --git a/drivers/regulator/mp5416.c b/drivers/regulator/mp5416.c index 3886b252fbe7..d068ac93d373 100644 --- a/drivers/regulator/mp5416.c +++ b/drivers/regulator/mp5416.c @@ -10,7 +10,7 @@ #include <linux/i2c.h> #include <linux/init.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/regulator/driver.h> diff --git a/drivers/regulator/mp886x.c b/drivers/regulator/mp886x.c index ede1b1e58002..9911be2e6bac 100644 --- a/drivers/regulator/mp886x.c +++ b/drivers/regulator/mp886x.c @@ -9,7 +9,7 @@ #include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regmap.h> #include <linux/regulator/driver.h> #include <linux/regulator/of_regulator.h> diff --git a/drivers/regulator/mpq7920.c b/drivers/regulator/mpq7920.c index bf677c535edc..a670e09891e7 100644 --- a/drivers/regulator/mpq7920.c +++ b/drivers/regulator/mpq7920.c @@ -11,7 +11,6 @@ #include <linux/init.h> #include <linux/err.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/of_regulator.h> @@ -319,7 +318,7 @@ static struct i2c_driver mpq7920_regulator_driver = { .driver = { .name = "mpq7920", .probe_type = PROBE_PREFER_ASYNCHRONOUS, - .of_match_table = of_match_ptr(mpq7920_of_match), + .of_match_table = mpq7920_of_match, }, .probe = mpq7920_i2c_probe, .id_table = mpq7920_id, diff --git a/drivers/regulator/mt6311-regulator.c b/drivers/regulator/mt6311-regulator.c index b0771770cc26..63a51485f2cc 100644 --- a/drivers/regulator/mt6311-regulator.c +++ b/drivers/regulator/mt6311-regulator.c @@ -4,7 +4,6 @@ // Author: Henry Chen <henryc.chen@mediatek.com> #include <linux/err.h> -#include <linux/gpio.h> #include <linux/i2c.h> #include <linux/init.h> #include <linux/interrupt.h> diff --git a/drivers/regulator/mt6315-regulator.c b/drivers/regulator/mt6315-regulator.c index 8047081ea2f7..2608a6652d77 100644 --- a/drivers/regulator/mt6315-regulator.c +++ b/drivers/regulator/mt6315-regulator.c @@ -3,7 +3,7 @@ // Copyright (c) 2021 MediaTek Inc. #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regmap.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> diff --git a/drivers/regulator/mt6359-regulator.c b/drivers/regulator/mt6359-regulator.c index 3eb86ec21d08..c8a788858824 100644 --- a/drivers/regulator/mt6359-regulator.c +++ b/drivers/regulator/mt6359-regulator.c @@ -7,7 +7,7 @@ #include <linux/mfd/mt6359p/registers.h> #include <linux/mfd/mt6397/core.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regmap.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> diff --git a/drivers/regulator/mtk-dvfsrc-regulator.c b/drivers/regulator/mtk-dvfsrc-regulator.c index efca67207a5a..f1280d45265d 100644 --- a/drivers/regulator/mtk-dvfsrc-regulator.c +++ b/drivers/regulator/mtk-dvfsrc-regulator.c @@ -6,8 +6,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/of_device.h> -#include <linux/of_platform.h> +#include <linux/of_.h> #include <linux/regulator/driver.h> #include <linux/regulator/of_regulator.h> #include <linux/soc/mediatek/mtk_dvfsrc.h> diff --git a/drivers/regulator/pbias-regulator.c b/drivers/regulator/pbias-regulator.c index 0c9873e9abdc..cd5a0d7e4455 100644 --- a/drivers/regulator/pbias-regulator.c +++ b/drivers/regulator/pbias-regulator.c @@ -25,7 +25,6 @@ #include <linux/regmap.h> #include <linux/slab.h> #include <linux/of.h> -#include <linux/of_device.h> struct pbias_reg_info { u32 enable; diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c index 91bfb7e026c9..2ab365d2749f 100644 --- a/drivers/regulator/pca9450-regulator.c +++ b/drivers/regulator/pca9450-regulator.c @@ -11,7 +11,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index 8d7e6c323324..46854602b3ea 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -699,8 +699,7 @@ static int pfuze100_regulator_probe(struct i2c_client *client) return -ENOMEM; if (client->dev.of_node) { - match = of_match_device(of_match_ptr(pfuze_dt_ids), - &client->dev); + match = of_match_device(pfuze_dt_ids, &client->dev); if (!match) { dev_err(&client->dev, "Error: No device match found\n"); return -ENODEV; diff --git a/drivers/regulator/pwm-regulator.c b/drivers/regulator/pwm-regulator.c index b64d99695b84..2aff6db748e2 100644 --- a/drivers/regulator/pwm-regulator.c +++ b/drivers/regulator/pwm-regulator.c @@ -10,11 +10,11 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/err.h> +#include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/pwm.h> #include <linux/gpio/consumer.h> diff --git a/drivers/regulator/qcom-refgen-regulator.c b/drivers/regulator/qcom-refgen-regulator.c new file mode 100644 index 000000000000..656fe330d38f --- /dev/null +++ b/drivers/regulator/qcom-refgen-regulator.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2017, 2019-2020, The Linux Foundation. All rights reserved. +// Copyright (c) 2023, Linaro Limited + +#include <linux/bitfield.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> + +#define REFGEN_REG_BIAS_EN 0x08 +#define REFGEN_BIAS_EN_MASK GENMASK(2, 0) + #define REFGEN_BIAS_EN_ENABLE 0x7 + #define REFGEN_BIAS_EN_DISABLE 0x6 + +#define REFGEN_REG_BG_CTRL 0x14 +#define REFGEN_BG_CTRL_MASK GENMASK(2, 1) + #define REFGEN_BG_CTRL_ENABLE 0x3 + #define REFGEN_BG_CTRL_DISABLE 0x2 + +#define REFGEN_REG_PWRDWN_CTRL5 0x80 +#define REFGEN_PWRDWN_CTRL5_MASK BIT(0) + #define REFGEN_PWRDWN_CTRL5_ENABLE 0x1 + +static int qcom_sdm845_refgen_enable(struct regulator_dev *rdev) +{ + regmap_update_bits(rdev->regmap, REFGEN_REG_BG_CTRL, REFGEN_BG_CTRL_MASK, + FIELD_PREP(REFGEN_BG_CTRL_MASK, REFGEN_BG_CTRL_ENABLE)); + + regmap_write(rdev->regmap, REFGEN_REG_BIAS_EN, + FIELD_PREP(REFGEN_BIAS_EN_MASK, REFGEN_BIAS_EN_ENABLE)); + + return 0; +} + +static int qcom_sdm845_refgen_disable(struct regulator_dev *rdev) +{ + regmap_write(rdev->regmap, REFGEN_REG_BIAS_EN, + FIELD_PREP(REFGEN_BIAS_EN_MASK, REFGEN_BIAS_EN_DISABLE)); + + regmap_update_bits(rdev->regmap, REFGEN_REG_BG_CTRL, REFGEN_BG_CTRL_MASK, + FIELD_PREP(REFGEN_BG_CTRL_MASK, REFGEN_BG_CTRL_DISABLE)); + + return 0; +} + +static int qcom_sdm845_refgen_is_enabled(struct regulator_dev *rdev) +{ + u32 val; + + regmap_read(rdev->regmap, REFGEN_REG_BG_CTRL, &val); + if (FIELD_GET(REFGEN_BG_CTRL_MASK, val) != REFGEN_BG_CTRL_ENABLE) + return 0; + + regmap_read(rdev->regmap, REFGEN_REG_BIAS_EN, &val); + if (FIELD_GET(REFGEN_BIAS_EN_MASK, val) != REFGEN_BIAS_EN_ENABLE) + return 0; + + return 1; +} + +static struct regulator_desc sdm845_refgen_desc = { + .enable_time = 5, + .name = "refgen", + .owner = THIS_MODULE, + .type = REGULATOR_VOLTAGE, + .ops = &(const struct regulator_ops) { + .enable = qcom_sdm845_refgen_enable, + .disable = qcom_sdm845_refgen_disable, + .is_enabled = qcom_sdm845_refgen_is_enabled, + }, +}; + +static struct regulator_desc sm8250_refgen_desc = { + .enable_reg = REFGEN_REG_PWRDWN_CTRL5, + .enable_mask = REFGEN_PWRDWN_CTRL5_MASK, + .enable_val = REFGEN_PWRDWN_CTRL5_ENABLE, + .disable_val = 0, + .enable_time = 5, + .name = "refgen", + .owner = THIS_MODULE, + .type = REGULATOR_VOLTAGE, + .ops = &(const struct regulator_ops) { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + }, +}; + +static const struct regmap_config qcom_refgen_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, +}; + +static int qcom_refgen_probe(struct platform_device *pdev) +{ + struct regulator_init_data *init_data; + struct regulator_config config = {}; + const struct regulator_desc *rdesc; + struct device *dev = &pdev->dev; + struct regulator_dev *rdev; + struct regmap *regmap; + void __iomem *base; + + rdesc = of_device_get_match_data(dev); + if (!rdesc) + return -ENODATA; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + regmap = devm_regmap_init_mmio(dev, base, &qcom_refgen_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + init_data = of_get_regulator_init_data(dev, dev->of_node, rdesc); + if (!init_data) + return -ENOMEM; + + config.dev = dev; + config.init_data = init_data; + config.of_node = dev->of_node; + config.regmap = regmap; + + rdev = devm_regulator_register(dev, rdesc, &config); + if (IS_ERR(rdev)) + return PTR_ERR(rdev); + + return 0; +} + +static const struct of_device_id qcom_refgen_match_table[] = { + { .compatible = "qcom,sdm845-refgen-regulator", .data = &sdm845_refgen_desc }, + { .compatible = "qcom,sm8250-refgen-regulator", .data = &sm8250_refgen_desc }, + { } +}; + +static struct platform_driver qcom_refgen_driver = { + .probe = qcom_refgen_probe, + .driver = { + .name = "qcom-refgen-regulator", + .of_match_table = qcom_refgen_match_table, + }, +}; +module_platform_driver(qcom_refgen_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Qualcomm REFGEN regulator driver"); diff --git a/drivers/regulator/qcom-rpmh-regulator.c b/drivers/regulator/qcom-rpmh-regulator.c index cd077b7c4aff..d990ba19c50e 100644 --- a/drivers/regulator/qcom-rpmh-regulator.c +++ b/drivers/regulator/qcom-rpmh-regulator.c @@ -7,7 +7,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/string.h> @@ -1273,6 +1272,40 @@ static const struct rpmh_vreg_init_data pmx65_vreg_data[] = { {} }; +static const struct rpmh_vreg_init_data pmx75_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps525_lv, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps525_lv, "vdd-s2"), + RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps525_lv, "vdd-s3"), + RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525_mv, "vdd-s4"), + RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps525_lv, "vdd-s5"), + RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps525_lv, "vdd-s6"), + RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps525_lv, "vdd-s7"), + RPMH_VREG("smps8", "smp%s8", &pmic5_ftsmps525_lv, "vdd-s8"), + RPMH_VREG("smps9", "smp%s9", &pmic5_ftsmps525_lv, "vdd-s9"), + RPMH_VREG("smps10", "smp%s10", &pmic5_ftsmps525_lv, "vdd-s10"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo515, "vdd-l1"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo515, "vdd-l2-18"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo515, "vdd-l3"), + RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo515, "vdd-l4-l16"), + RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo_lv, "vdd-l5-l6"), + RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo_lv, "vdd-l5-l6"), + RPMH_VREG("ldo7", "ldo%s7", &pmic5_nldo515, "vdd-l7"), + RPMH_VREG("ldo8", "ldo%s8", &pmic5_nldo515, "vdd-l8-l9"), + RPMH_VREG("ldo9", "ldo%s9", &pmic5_nldo515, "vdd-l8-l9"), + RPMH_VREG("ldo10", "ldo%s10", &pmic5_pldo, "vdd-l10"), + RPMH_VREG("ldo11", "ldo%s11", &pmic5_pldo, "vdd-l11-l13"), + RPMH_VREG("ldo12", "ldo%s12", &pmic5_nldo515, "vdd-l12"), + RPMH_VREG("ldo13", "ldo%s13", &pmic5_pldo, "vdd-l11-l13"), + RPMH_VREG("ldo14", "ldo%s14", &pmic5_nldo515, "vdd-l14"), + RPMH_VREG("ldo15", "ldo%s15", &pmic5_nldo515, "vdd-l15"), + RPMH_VREG("ldo16", "ldo%s16", &pmic5_nldo515, "vdd-l4-l16"), + RPMH_VREG("ldo17", "ldo%s17", &pmic5_nldo515, "vdd-l17"), + /* ldo18 not configured */ + RPMH_VREG("ldo19", "ldo%s19", &pmic5_nldo515, "vdd-l19"), + RPMH_VREG("ldo20", "ldo%s20", &pmic5_nldo515, "vdd-l20-l21"), + RPMH_VREG("ldo21", "ldo%s21", &pmic5_nldo515, "vdd-l20-l21"), +}; + static const struct rpmh_vreg_init_data pm7325_vreg_data[] = { RPMH_VREG("smps1", "smp%s1", &pmic5_hfsmps510, "vdd-s1"), RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps520, "vdd-s2"), @@ -1495,6 +1528,10 @@ static const struct of_device_id __maybe_unused rpmh_regulator_match_table[] = { .data = pmx65_vreg_data, }, { + .compatible = "qcom,pmx75-rpmh-regulators", + .data = pmx75_vreg_data, + }, + { .compatible = "qcom,pm7325-rpmh-regulators", .data = pm7325_vreg_data, }, diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c index f95bc9208c13..9366488f0383 100644 --- a/drivers/regulator/qcom_rpm-regulator.c +++ b/drivers/regulator/qcom_rpm-regulator.c @@ -956,11 +956,10 @@ static int rpm_reg_probe(struct platform_device *pdev) } for (reg = match->data; reg->name; reg++) { - vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL); + vreg = devm_kmemdup(&pdev->dev, reg->template, sizeof(*vreg), GFP_KERNEL); if (!vreg) return -ENOMEM; - memcpy(vreg, reg->template, sizeof(*vreg)); mutex_init(&vreg->lock); vreg->dev = &pdev->dev; diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c index 18189f35db68..f53ada076252 100644 --- a/drivers/regulator/qcom_smd-regulator.c +++ b/drivers/regulator/qcom_smd-regulator.c @@ -6,7 +6,6 @@ #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/of_regulator.h> diff --git a/drivers/regulator/qcom_usb_vbus-regulator.c b/drivers/regulator/qcom_usb_vbus-regulator.c index 57ec613f4a0a..cd94ed67621f 100644 --- a/drivers/regulator/qcom_usb_vbus-regulator.c +++ b/drivers/regulator/qcom_usb_vbus-regulator.c @@ -8,7 +8,6 @@ #include <linux/err.h> #include <linux/kernel.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/of_regulator.h> diff --git a/drivers/regulator/raa215300.c b/drivers/regulator/raa215300.c index 24a1c89f5dbc..6982565c8aa4 100644 --- a/drivers/regulator/raa215300.c +++ b/drivers/regulator/raa215300.c @@ -38,10 +38,6 @@ #define RAA215300_REG_BLOCK_EN_RTC_EN BIT(6) #define RAA215300_RTC_DEFAULT_ADDR 0x6f -const char *clkin_name = "clkin"; -const char *xin_name = "xin"; -static struct clk *clk; - static const struct regmap_config raa215300_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -51,10 +47,6 @@ static const struct regmap_config raa215300_regmap_config = { static void raa215300_rtc_unregister_device(void *data) { i2c_unregister_device(data); - if (!clk) { - clk_unregister_fixed_rate(clk); - clk = NULL; - } } static int raa215300_clk_present(struct i2c_client *client, const char *name) @@ -71,8 +63,10 @@ static int raa215300_clk_present(struct i2c_client *client, const char *name) static int raa215300_i2c_probe(struct i2c_client *client) { struct device *dev = &client->dev; - const char *clk_name = xin_name; + const char *clkin_name = "clkin"; unsigned int pmic_version, val; + const char *xin_name = "xin"; + const char *clk_name = NULL; struct regmap *regmap; int ret; @@ -92,7 +86,7 @@ static int raa215300_i2c_probe(struct i2c_client *client) val &= RAA215300_REG_BLOCK_EN_RTC_EN; regmap_write(regmap, RAA215300_REG_BLOCK_EN, val); - /*Clear the latched registers */ + /* Clear the latched registers */ regmap_read(regmap, RAA215300_FAULT_LATCHED_STATUS_1, &val); regmap_write(regmap, RAA215300_FAULT_LATCHED_STATUS_1, val); regmap_read(regmap, RAA215300_FAULT_LATCHED_STATUS_2, &val); @@ -114,24 +108,32 @@ static int raa215300_i2c_probe(struct i2c_client *client) ret = raa215300_clk_present(client, xin_name); if (ret < 0) { return ret; - } else if (!ret) { + } else if (ret) { + clk_name = xin_name; + } else { ret = raa215300_clk_present(client, clkin_name); if (ret < 0) return ret; - - clk_name = clkin_name; + if (ret) + clk_name = clkin_name; } - if (ret) { - char *name = pmic_version >= 0x12 ? "isl1208" : "raa215300_a0"; + if (clk_name) { + const char *name = pmic_version >= 0x12 ? "isl1208" : "raa215300_a0"; struct device_node *np = client->dev.of_node; u32 addr = RAA215300_RTC_DEFAULT_ADDR; struct i2c_board_info info = {}; struct i2c_client *rtc_client; + struct clk_hw *hw; ssize_t size; - clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 32000); - clk_register_clkdev(clk, clk_name, NULL); + hw = devm_clk_hw_register_fixed_rate(dev, clk_name, NULL, 0, 32768); + if (IS_ERR(hw)) + return PTR_ERR(hw); + + ret = devm_clk_hw_register_clkdev(dev, hw, clk_name, NULL); + if (ret) + return dev_err_probe(dev, ret, "Failed to initialize clkdev\n"); if (np) { int i; @@ -180,7 +182,7 @@ static struct i2c_driver raa215300_i2c_driver = { .name = "raa215300", .of_match_table = raa215300_dt_match, }, - .probe_new = raa215300_i2c_probe, + .probe = raa215300_i2c_probe, }; module_i2c_driver(raa215300_i2c_driver); diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c index a5afca73715d..a25a141e86c4 100644 --- a/drivers/regulator/rc5t583-regulator.c +++ b/drivers/regulator/rc5t583-regulator.c @@ -16,7 +16,6 @@ #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> -#include <linux/gpio.h> #include <linux/mfd/rc5t583.h> struct rc5t583_regulator_info { diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 460525ed006c..867a2cf243f6 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -17,9 +17,10 @@ #include <linux/delay.h> #include <linux/gpio.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/of_gpio.h> #include <linux/mfd/rk808.h> +#include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/of_regulator.h> #include <linux/gpio/consumer.h> diff --git a/drivers/regulator/rohm-regulator.c b/drivers/regulator/rohm-regulator.c index f97a9a51ee76..0e2418ed957c 100644 --- a/drivers/regulator/rohm-regulator.c +++ b/drivers/regulator/rohm-regulator.c @@ -36,7 +36,7 @@ static int set_dvs_level(const struct regulator_desc *desc, } for (i = 0; i < desc->n_voltages; i++) { /* NOTE to next hacker - Does not support pickable ranges */ - if (desc->linear_range_selectors) + if (desc->linear_range_selectors_bitfield) return -EINVAL; if (desc->n_linear_ranges) ret = regulator_desc_list_voltage_linear_range(desc, i); diff --git a/drivers/regulator/rpi-panel-attiny-regulator.c b/drivers/regulator/rpi-panel-attiny-regulator.c index e9719a378a0b..f52c3d47ecea 100644 --- a/drivers/regulator/rpi-panel-attiny-regulator.c +++ b/drivers/regulator/rpi-panel-attiny-regulator.c @@ -7,7 +7,6 @@ #include <linux/backlight.h> #include <linux/err.h> -#include <linux/gpio.h> #include <linux/gpio/driver.h> #include <linux/i2c.h> #include <linux/init.h> @@ -397,7 +396,7 @@ static struct i2c_driver attiny_regulator_driver = { .driver = { .name = "rpi_touchscreen_attiny", .probe_type = PROBE_PREFER_ASYNCHRONOUS, - .of_match_table = of_match_ptr(attiny_dt_ids), + .of_match_table = attiny_dt_ids, }, .probe = attiny_i2c_probe, .remove = attiny_i2c_remove, diff --git a/drivers/regulator/rt5739.c b/drivers/regulator/rt5739.c index 0ce6a1666752..91412c905ce6 100644 --- a/drivers/regulator/rt5739.c +++ b/drivers/regulator/rt5739.c @@ -31,10 +31,17 @@ #define RT5739_MODEVSEL1_MASK BIT(1) #define RT5739_MODEVSEL0_MASK BIT(0) #define RT5739_VID_MASK GENMASK(7, 5) +#define RT5739_DID_MASK GENMASK(3, 0) #define RT5739_ACTD_MASK BIT(7) #define RT5739_ENVSEL1_MASK BIT(1) #define RT5739_ENVSEL0_MASK BIT(0) +#define RT5733_CHIPDIE_ID 0x1 +#define RT5733_VOLT_MINUV 270000 +#define RT5733_VOLT_MAXUV 1401250 +#define RT5733_VOLT_STPUV 6250 +#define RT5733_N_VOLTS 182 + #define RT5739_VOLT_MINUV 300000 #define RT5739_VOLT_MAXUV 1300000 #define RT5739_VOLT_STPUV 5000 @@ -93,8 +100,11 @@ static int rt5739_set_suspend_voltage(struct regulator_dev *rdev, int uV) const struct regulator_desc *desc = rdev->desc; struct regmap *regmap = rdev_get_regmap(rdev); unsigned int reg, vsel; + int max_uV; + + max_uV = desc->min_uV + desc->uV_step * (desc->n_voltages - 1); - if (uV < RT5739_VOLT_MINUV || uV > RT5739_VOLT_MAXUV) + if (uV < desc->min_uV || uV > max_uV) return -EINVAL; if (desc->vsel_reg == RT5739_REG_NSEL0) @@ -102,7 +112,7 @@ static int rt5739_set_suspend_voltage(struct regulator_dev *rdev, int uV) else reg = RT5739_REG_NSEL0; - vsel = (uV - RT5739_VOLT_MINUV) / RT5739_VOLT_STPUV; + vsel = (uV - desc->min_uV) / desc->uV_step; return regmap_write(regmap, reg, vsel); } @@ -189,15 +199,12 @@ static unsigned int rt5739_of_map_mode(unsigned int mode) } static void rt5739_init_regulator_desc(struct regulator_desc *desc, - bool vsel_active_high) + bool vsel_active_high, u8 did) { /* Fixed */ desc->name = "rt5739-regulator"; desc->owner = THIS_MODULE; desc->ops = &rt5739_regulator_ops; - desc->n_voltages = RT5739_N_VOLTS; - desc->min_uV = RT5739_VOLT_MINUV; - desc->uV_step = RT5739_VOLT_STPUV; desc->vsel_mask = RT5739_VSEL_MASK; desc->enable_reg = RT5739_REG_CNTL2; desc->active_discharge_reg = RT5739_REG_CNTL1; @@ -213,6 +220,20 @@ static void rt5739_init_regulator_desc(struct regulator_desc *desc, desc->vsel_reg = RT5739_REG_NSEL0; desc->enable_mask = RT5739_ENVSEL0_MASK; } + + /* Assigned by CHIPDIE ID */ + switch (did) { + case RT5733_CHIPDIE_ID: + desc->n_voltages = RT5733_N_VOLTS; + desc->min_uV = RT5733_VOLT_MINUV; + desc->uV_step = RT5733_VOLT_STPUV; + break; + default: + desc->n_voltages = RT5739_N_VOLTS; + desc->min_uV = RT5739_VOLT_MINUV; + desc->uV_step = RT5739_VOLT_STPUV; + break; + } } static const struct regmap_config rt5739_regmap_config = { @@ -258,7 +279,7 @@ static int rt5739_probe(struct i2c_client *i2c) vsel_acth = device_property_read_bool(dev, "richtek,vsel-active-high"); - rt5739_init_regulator_desc(desc, vsel_acth); + rt5739_init_regulator_desc(desc, vsel_acth, vid & RT5739_DID_MASK); cfg.dev = dev; cfg.of_node = dev_of_node(dev); @@ -271,6 +292,7 @@ static int rt5739_probe(struct i2c_client *i2c) } static const struct of_device_id rt5739_device_table[] = { + { .compatible = "richtek,rt5733" }, { .compatible = "richtek,rt5739" }, { /* sentinel */ } }; diff --git a/drivers/regulator/rt5759-regulator.c b/drivers/regulator/rt5759-regulator.c index 90555a9ef1b0..c2553dcee050 100644 --- a/drivers/regulator/rt5759-regulator.c +++ b/drivers/regulator/rt5759-regulator.c @@ -4,7 +4,7 @@ #include <linux/i2c.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regmap.h> #include <linux/regulator/driver.h> #include <linux/regulator/of_regulator.h> diff --git a/drivers/regulator/rtq2208-regulator.c b/drivers/regulator/rtq2208-regulator.c new file mode 100644 index 000000000000..2d54844c4226 --- /dev/null +++ b/drivers/regulator/rtq2208-regulator.c @@ -0,0 +1,583 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <linux/bitops.h> +#include <linux/bitfield.h> +#include <linux/util_macros.h> +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/regmap.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/regulator/of_regulator.h> +#include <linux/mod_devicetable.h> + +/* Register */ +#define RTQ2208_REG_GLOBAL_INT1 0x12 +#define RTQ2208_REG_FLT_RECORDBUCK_CB 0x18 +#define RTQ2208_REG_GLOBAL_INT1_MASK 0x1D +#define RTQ2208_REG_FLT_MASKBUCK_CB 0x1F +#define RTQ2208_REG_BUCK_C_CFG0 0x32 +#define RTQ2208_REG_BUCK_B_CFG0 0x42 +#define RTQ2208_REG_BUCK_A_CFG0 0x52 +#define RTQ2208_REG_BUCK_D_CFG0 0x62 +#define RTQ2208_REG_BUCK_G_CFG0 0x72 +#define RTQ2208_REG_BUCK_F_CFG0 0x82 +#define RTQ2208_REG_BUCK_E_CFG0 0x92 +#define RTQ2208_REG_BUCK_H_CFG0 0xA2 +#define RTQ2208_REG_LDO1_CFG 0xB1 +#define RTQ2208_REG_LDO2_CFG 0xC1 + +/* Mask */ +#define RTQ2208_BUCK_NR_MTP_SEL_MASK GENMASK(7, 0) +#define RTQ2208_BUCK_EN_NR_MTP_SEL0_MASK BIT(0) +#define RTQ2208_BUCK_EN_NR_MTP_SEL1_MASK BIT(1) +#define RTQ2208_BUCK_RSPUP_MASK GENMASK(6, 4) +#define RTQ2208_BUCK_RSPDN_MASK GENMASK(2, 0) +#define RTQ2208_BUCK_NRMODE_MASK BIT(5) +#define RTQ2208_BUCK_STRMODE_MASK BIT(5) +#define RTQ2208_BUCK_EN_STR_MASK BIT(0) +#define RTQ2208_LDO_EN_STR_MASK BIT(7) +#define RTQ2208_EN_DIS_MASK BIT(0) +#define RTQ2208_BUCK_RAMP_SEL_MASK GENMASK(2, 0) +#define RTQ2208_HD_INT_MASK BIT(0) + +/* Size */ +#define RTQ2208_VOUT_MAXNUM 256 +#define RTQ2208_BUCK_NUM_IRQ_REGS 5 +#define RTQ2208_STS_NUM_IRQ_REGS 2 + +/* Value */ +#define RTQ2208_RAMP_VALUE_MIN_uV 500 +#define RTQ2208_RAMP_VALUE_MAX_uV 64000 + +#define RTQ2208_BUCK_MASK(uv_irq, ov_irq) (1 << ((uv_irq) % 8) | 1 << ((ov_irq) % 8)) + +enum { + RTQ2208_BUCK_B = 0, + RTQ2208_BUCK_C, + RTQ2208_BUCK_D, + RTQ2208_BUCK_A, + RTQ2208_BUCK_F, + RTQ2208_BUCK_G, + RTQ2208_BUCK_H, + RTQ2208_BUCK_E, + RTQ2208_LDO2, + RTQ2208_LDO1, + RTQ2208_LDO_MAX, +}; + +enum { + RTQ2208_AUTO_MODE = 0, + RTQ2208_FCCM, +}; + +struct rtq2208_regulator_desc { + struct regulator_desc desc; + unsigned int mtp_sel_reg; + unsigned int mtp_sel_mask; + unsigned int mode_reg; + unsigned int mode_mask; + unsigned int suspend_config_reg; + unsigned int suspend_enable_mask; + unsigned int suspend_mode_mask; +}; + +struct rtq2208_rdev_map { + struct regulator_dev *rdev[RTQ2208_LDO_MAX]; + struct regmap *regmap; + struct device *dev; +}; + +/* set Normal Auto/FCCM mode */ +static int rtq2208_set_mode(struct regulator_dev *rdev, unsigned int mode) +{ + const struct rtq2208_regulator_desc *rdesc = + (const struct rtq2208_regulator_desc *)rdev->desc; + unsigned int val, shift; + + switch (mode) { + case REGULATOR_MODE_NORMAL: + val = RTQ2208_AUTO_MODE; + break; + case REGULATOR_MODE_FAST: + val = RTQ2208_FCCM; + break; + default: + return -EINVAL; + } + + shift = ffs(rdesc->mode_mask) - 1; + return regmap_update_bits(rdev->regmap, rdesc->mode_reg, + rdesc->mode_mask, val << shift); +} + +static unsigned int rtq2208_get_mode(struct regulator_dev *rdev) +{ + const struct rtq2208_regulator_desc *rdesc = + (const struct rtq2208_regulator_desc *)rdev->desc; + unsigned int mode_val; + int ret; + + ret = regmap_read(rdev->regmap, rdesc->mode_reg, &mode_val); + if (ret) + return REGULATOR_MODE_INVALID; + + return (mode_val & rdesc->mode_mask) ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL; +} + +static int rtq2208_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) +{ + const struct regulator_desc *desc = rdev->desc; + unsigned int sel = 0, val; + + ramp_delay = max(ramp_delay, RTQ2208_RAMP_VALUE_MIN_uV); + ramp_delay = min(ramp_delay, RTQ2208_RAMP_VALUE_MAX_uV); + + ramp_delay /= RTQ2208_RAMP_VALUE_MIN_uV; + + /* + * fls(ramp_delay) - 1: doing LSB shift, let it starts from 0 + * + * RTQ2208_BUCK_RAMP_SEL_MASK - sel: doing descending order shifting. + * Because the relation of seleltion and value is like that + * + * seletion: value + * 000: 64mv + * 001: 32mv + * ... + * 111: 0.5mv + * + * For example, if I would like to select 64mv, the fls(ramp_delay) - 1 will be 0b111, + * and I need to use 0b111 - sel to do the shifting + */ + + sel = fls(ramp_delay) - 1; + sel = RTQ2208_BUCK_RAMP_SEL_MASK - sel; + + val = FIELD_PREP(RTQ2208_BUCK_RSPUP_MASK, sel) | FIELD_PREP(RTQ2208_BUCK_RSPDN_MASK, sel); + + return regmap_update_bits(rdev->regmap, desc->ramp_reg, + RTQ2208_BUCK_RSPUP_MASK | RTQ2208_BUCK_RSPDN_MASK, val); +} + +static int rtq2208_set_suspend_enable(struct regulator_dev *rdev) +{ + const struct rtq2208_regulator_desc *rdesc = + (const struct rtq2208_regulator_desc *)rdev->desc; + + return regmap_set_bits(rdev->regmap, rdesc->suspend_config_reg, rdesc->suspend_enable_mask); +} + +static int rtq2208_set_suspend_disable(struct regulator_dev *rdev) +{ + const struct rtq2208_regulator_desc *rdesc = + (const struct rtq2208_regulator_desc *)rdev->desc; + + return regmap_update_bits(rdev->regmap, rdesc->suspend_config_reg, rdesc->suspend_enable_mask, 0); +} + +static int rtq2208_set_suspend_mode(struct regulator_dev *rdev, unsigned int mode) +{ + const struct rtq2208_regulator_desc *rdesc = + (const struct rtq2208_regulator_desc *)rdev->desc; + unsigned int val, shift; + + switch (mode) { + case REGULATOR_MODE_NORMAL: + val = RTQ2208_AUTO_MODE; + break; + case REGULATOR_MODE_FAST: + val = RTQ2208_FCCM; + break; + default: + return -EINVAL; + } + + shift = ffs(rdesc->suspend_mode_mask) - 1; + + return regmap_update_bits(rdev->regmap, rdesc->suspend_config_reg, + rdesc->suspend_mode_mask, val << shift); +} + +static const struct regulator_ops rtq2208_regulator_buck_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .list_voltage = regulator_list_voltage_linear_range, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_mode = rtq2208_set_mode, + .get_mode = rtq2208_get_mode, + .set_ramp_delay = rtq2208_set_ramp_delay, + .set_active_discharge = regulator_set_active_discharge_regmap, + .set_suspend_enable = rtq2208_set_suspend_enable, + .set_suspend_disable = rtq2208_set_suspend_disable, + .set_suspend_mode = rtq2208_set_suspend_mode, +}; + +static const struct regulator_ops rtq2208_regulator_ldo_ops = { + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, + .set_active_discharge = regulator_set_active_discharge_regmap, + .set_suspend_enable = rtq2208_set_suspend_enable, + .set_suspend_disable = rtq2208_set_suspend_disable, +}; + +static unsigned int rtq2208_of_map_mode(unsigned int mode) +{ + switch (mode) { + case RTQ2208_AUTO_MODE: + return REGULATOR_MODE_NORMAL; + case RTQ2208_FCCM: + return REGULATOR_MODE_FAST; + default: + return REGULATOR_MODE_INVALID; + } +} + +static int rtq2208_init_irq_mask(struct rtq2208_rdev_map *rdev_map, unsigned int *buck_masks) +{ + unsigned char buck_clr_masks[5] = {0x33, 0x33, 0x33, 0x33, 0x33}, + sts_clr_masks[2] = {0xE7, 0xF7}, sts_masks[2] = {0xE6, 0xF6}; + int ret; + + /* write clear all buck irq once */ + ret = regmap_bulk_write(rdev_map->regmap, RTQ2208_REG_FLT_RECORDBUCK_CB, buck_clr_masks, 5); + if (ret) + return dev_err_probe(rdev_map->dev, ret, "Failed to clr buck irqs\n"); + + /* write clear general irq once */ + ret = regmap_bulk_write(rdev_map->regmap, RTQ2208_REG_GLOBAL_INT1, sts_clr_masks, 2); + if (ret) + return dev_err_probe(rdev_map->dev, ret, "Failed to clr general irqs\n"); + + /* unmask buck ov/uv irq */ + ret = regmap_bulk_write(rdev_map->regmap, RTQ2208_REG_FLT_MASKBUCK_CB, buck_masks, 5); + if (ret) + return dev_err_probe(rdev_map->dev, ret, "Failed to unmask buck irqs\n"); + + /* unmask needed general irq */ + return regmap_bulk_write(rdev_map->regmap, RTQ2208_REG_GLOBAL_INT1_MASK, sts_masks, 2); +} + +static irqreturn_t rtq2208_irq_handler(int irqno, void *devid) +{ + unsigned char buck_flags[RTQ2208_BUCK_NUM_IRQ_REGS], sts_flags[RTQ2208_STS_NUM_IRQ_REGS]; + int ret = 0, i, uv_bit, ov_bit; + struct rtq2208_rdev_map *rdev_map = devid; + struct regulator_dev *rdev; + + if (!rdev_map) + return IRQ_NONE; + + /* read irq event */ + ret = regmap_bulk_read(rdev_map->regmap, RTQ2208_REG_FLT_RECORDBUCK_CB, + buck_flags, ARRAY_SIZE(buck_flags)); + if (ret) + return IRQ_NONE; + + ret = regmap_bulk_read(rdev_map->regmap, RTQ2208_REG_GLOBAL_INT1, + sts_flags, ARRAY_SIZE(sts_flags)); + if (ret) + return IRQ_NONE; + + /* clear irq event */ + ret = regmap_bulk_write(rdev_map->regmap, RTQ2208_REG_FLT_RECORDBUCK_CB, + buck_flags, ARRAY_SIZE(buck_flags)); + if (ret) + return IRQ_NONE; + + ret = regmap_bulk_write(rdev_map->regmap, RTQ2208_REG_GLOBAL_INT1, + sts_flags, ARRAY_SIZE(sts_flags)); + if (ret) + return IRQ_NONE; + + for (i = 0; i < RTQ2208_LDO_MAX; i++) { + if (!rdev_map->rdev[i]) + continue; + + rdev = rdev_map->rdev[i]; + /* uv irq */ + uv_bit = (i & 1) ? 4 : 0; + if (buck_flags[i >> 1] & (1 << uv_bit)) + regulator_notifier_call_chain(rdev, + REGULATOR_EVENT_UNDER_VOLTAGE, NULL); + /* ov irq */ + ov_bit = uv_bit + 1; + if (buck_flags[i >> 1] & (1 << ov_bit)) + regulator_notifier_call_chain(rdev, + REGULATOR_EVENT_REGULATION_OUT, NULL); + + /* hd irq */ + if (sts_flags[1] & RTQ2208_HD_INT_MASK) + regulator_notifier_call_chain(rdev, + REGULATOR_EVENT_OVER_TEMP, NULL); + } + + return IRQ_HANDLED; +} + +#define RTQ2208_REGULATOR_INFO(_name, _base) \ +{ \ + .name = #_name, \ + .base = _base, \ +} +#define BUCK_RG_BASE(_id) RTQ2208_REG_BUCK_##_id##_CFG0 +#define BUCK_RG_SHIFT(_base, _shift) (_base + _shift) +#define LDO_RG_BASE(_id) RTQ2208_REG_LDO##_id##_CFG +#define LDO_RG_SHIFT(_base, _shift) (_base + _shift) +#define VSEL_SHIFT(_sel) (_sel ? 3 : 1) +#define MTP_SEL_MASK(_sel) RTQ2208_BUCK_EN_NR_MTP_SEL##_sel##_MASK + +static const struct linear_range rtq2208_vout_range[] = { + REGULATOR_LINEAR_RANGE(400000, 0, 180, 5000), + REGULATOR_LINEAR_RANGE(1310000, 181, 255, 10000), +}; + +static int rtq2208_of_get_fixed_voltage(struct device *dev, + struct of_regulator_match *rtq2208_ldo_match, int n_fixed) +{ + struct device_node *np; + struct of_regulator_match *match; + struct rtq2208_regulator_desc *rdesc; + struct regulator_init_data *init_data; + int ret, i; + + if (!dev->of_node) + return -ENODEV; + + np = of_get_child_by_name(dev->of_node, "regulators"); + if (!np) + np = dev->of_node; + + ret = of_regulator_match(dev, np, rtq2208_ldo_match, n_fixed); + + of_node_put(np); + + if (ret < 0) + return ret; + + for (i = 0; i < n_fixed; i++) { + match = rtq2208_ldo_match + i; + init_data = match->init_data; + rdesc = (struct rtq2208_regulator_desc *)match->driver_data; + + if (!init_data || !rdesc) + continue; + + if (init_data->constraints.min_uV == init_data->constraints.max_uV) + rdesc->desc.fixed_uV = init_data->constraints.min_uV; + } + + return 0; +} + +static void rtq2208_init_regulator_desc(struct rtq2208_regulator_desc *rdesc, int mtp_sel, + int idx, struct of_regulator_match *rtq2208_ldo_match, int *ldo_idx) +{ + struct regulator_desc *desc; + static const struct { + char *name; + int base; + } regulator_info[] = { + RTQ2208_REGULATOR_INFO(buck-b, BUCK_RG_BASE(B)), + RTQ2208_REGULATOR_INFO(buck-c, BUCK_RG_BASE(C)), + RTQ2208_REGULATOR_INFO(buck-d, BUCK_RG_BASE(D)), + RTQ2208_REGULATOR_INFO(buck-a, BUCK_RG_BASE(A)), + RTQ2208_REGULATOR_INFO(buck-f, BUCK_RG_BASE(F)), + RTQ2208_REGULATOR_INFO(buck-g, BUCK_RG_BASE(G)), + RTQ2208_REGULATOR_INFO(buck-h, BUCK_RG_BASE(H)), + RTQ2208_REGULATOR_INFO(buck-e, BUCK_RG_BASE(E)), + RTQ2208_REGULATOR_INFO(ldo2, LDO_RG_BASE(2)), + RTQ2208_REGULATOR_INFO(ldo1, LDO_RG_BASE(1)), + }, *curr_info; + + curr_info = regulator_info + idx; + desc = &rdesc->desc; + desc->name = curr_info->name; + desc->of_match = of_match_ptr(curr_info->name); + desc->regulators_node = of_match_ptr("regulators"); + desc->id = idx; + desc->owner = THIS_MODULE; + desc->type = REGULATOR_VOLTAGE; + desc->enable_mask = mtp_sel ? MTP_SEL_MASK(1) : MTP_SEL_MASK(0); + desc->active_discharge_on = RTQ2208_EN_DIS_MASK; + desc->active_discharge_off = 0; + desc->active_discharge_mask = RTQ2208_EN_DIS_MASK; + + rdesc->mode_mask = RTQ2208_BUCK_NRMODE_MASK; + + if (idx >= RTQ2208_BUCK_B && idx <= RTQ2208_BUCK_E) { + /* init buck desc */ + desc->enable_reg = BUCK_RG_SHIFT(curr_info->base, 2); + desc->ops = &rtq2208_regulator_buck_ops; + desc->vsel_reg = curr_info->base + VSEL_SHIFT(mtp_sel); + desc->vsel_mask = RTQ2208_BUCK_NR_MTP_SEL_MASK; + desc->n_voltages = RTQ2208_VOUT_MAXNUM; + desc->linear_ranges = rtq2208_vout_range; + desc->n_linear_ranges = ARRAY_SIZE(rtq2208_vout_range); + desc->ramp_reg = BUCK_RG_SHIFT(curr_info->base, 5); + desc->active_discharge_reg = curr_info->base; + desc->of_map_mode = rtq2208_of_map_mode; + + rdesc->mode_reg = BUCK_RG_SHIFT(curr_info->base, 2); + rdesc->suspend_config_reg = BUCK_RG_SHIFT(curr_info->base, 4); + rdesc->suspend_enable_mask = RTQ2208_BUCK_EN_STR_MASK; + rdesc->suspend_mode_mask = RTQ2208_BUCK_STRMODE_MASK; + } else { + /* init ldo desc */ + desc->enable_reg = curr_info->base; + desc->ops = &rtq2208_regulator_ldo_ops; + desc->n_voltages = 1; + desc->active_discharge_reg = LDO_RG_SHIFT(curr_info->base, 2); + + rtq2208_ldo_match[*ldo_idx].name = desc->name; + rtq2208_ldo_match[*ldo_idx].driver_data = rdesc; + rtq2208_ldo_match[(*ldo_idx)++].desc = desc; + + rdesc->suspend_config_reg = curr_info->base; + rdesc->suspend_enable_mask = RTQ2208_LDO_EN_STR_MASK; + } +} + +static int rtq2208_parse_regulator_dt_data(int n_regulator, const unsigned int *regulator_idx_table, + struct rtq2208_regulator_desc *rdesc[RTQ2208_LDO_MAX], struct device *dev) +{ + struct of_regulator_match rtq2208_ldo_match[2]; + int mtp_sel, ret, i, idx, ldo_idx = 0; + + /* get mtp_sel0 or mtp_sel1 */ + mtp_sel = device_property_read_bool(dev, "richtek,mtp-sel-high"); + + for (i = 0; i < n_regulator; i++) { + idx = regulator_idx_table[i]; + + rdesc[i] = devm_kcalloc(dev, 1, sizeof(*rdesc[0]), GFP_KERNEL); + if (!rdesc[i]) + return -ENOMEM; + + rtq2208_init_regulator_desc(rdesc[i], mtp_sel, idx, rtq2208_ldo_match, &ldo_idx); + } + + /* init ldo fixed_uV */ + ret = rtq2208_of_get_fixed_voltage(dev, rtq2208_ldo_match, ldo_idx); + if (ret) + return dev_err_probe(dev, ret, "Failed to get ldo fixed_uV\n"); + + return 0; + +} + +/** different slave address corresponds different used bucks + * slave address 0x10: BUCK[BCA FGE] + * slave address 0x20: BUCK[BC FGHE] + * slave address 0x40: BUCK[C G] + */ +static int rtq2208_regulator_check(int slave_addr, int *num, + int *regulator_idx_table, unsigned int *buck_masks) +{ + static bool rtq2208_used_table[3][RTQ2208_LDO_MAX] = { + /* BUCK[BCA FGE], LDO[12] */ + {1, 1, 0, 1, 1, 1, 0, 1, 1, 1}, + /* BUCK[BC FGHE], LDO[12]*/ + {1, 1, 0, 0, 1, 1, 1, 1, 1, 1}, + /* BUCK[C G], LDO[12] */ + {0, 1, 0, 0, 0, 1, 0, 0, 1, 1}, + }; + int i, idx = ffs(slave_addr >> 4) - 1; + u8 mask; + + for (i = 0; i < RTQ2208_LDO_MAX; i++) { + if (!rtq2208_used_table[idx][i]) + continue; + + regulator_idx_table[(*num)++] = i; + + mask = RTQ2208_BUCK_MASK(4 * i, 4 * i + 1); + buck_masks[i >> 1] &= ~mask; + } + + return 0; +} + +static const struct regmap_config rtq2208_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0xEF, +}; + +static int rtq2208_probe(struct i2c_client *i2c) +{ + struct device *dev = &i2c->dev; + struct regmap *regmap; + struct rtq2208_regulator_desc *rdesc[RTQ2208_LDO_MAX]; + struct regulator_dev *rdev; + struct regulator_config cfg; + struct rtq2208_rdev_map *rdev_map; + int i, ret = 0, idx, n_regulator = 0; + unsigned int regulator_idx_table[RTQ2208_LDO_MAX], + buck_masks[RTQ2208_BUCK_NUM_IRQ_REGS] = {0x33, 0x33, 0x33, 0x33, 0x33}; + + rdev_map = devm_kzalloc(dev, sizeof(struct rtq2208_rdev_map), GFP_KERNEL); + if (!rdev_map) + return -ENOMEM; + + regmap = devm_regmap_init_i2c(i2c, &rtq2208_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), "Failed to allocate regmap\n"); + + /* get needed regulator */ + ret = rtq2208_regulator_check(i2c->addr, &n_regulator, regulator_idx_table, buck_masks); + if (ret) + return dev_err_probe(dev, ret, "Failed to check used regulators\n"); + + rdev_map->regmap = regmap; + rdev_map->dev = dev; + + cfg.dev = dev; + + /* init regulator desc */ + ret = rtq2208_parse_regulator_dt_data(n_regulator, regulator_idx_table, rdesc, dev); + if (ret) + return ret; + + for (i = 0; i < n_regulator; i++) { + idx = regulator_idx_table[i]; + + /* register regulator */ + rdev = devm_regulator_register(dev, &rdesc[i]->desc, &cfg); + if (IS_ERR(rdev)) + return PTR_ERR(rdev); + + rdev_map->rdev[idx] = rdev; + } + + /* init interrupt mask */ + ret = rtq2208_init_irq_mask(rdev_map, buck_masks); + if (ret) + return ret; + + /* register interrupt */ + return devm_request_threaded_irq(dev, i2c->irq, NULL, rtq2208_irq_handler, + IRQF_ONESHOT, dev_name(dev), rdev_map); +} + +static const struct of_device_id rtq2208_device_tables[] = { + { .compatible = "richtek,rtq2208" }, + {} +}; +MODULE_DEVICE_TABLE(of, rtq2208_device_tables); + +static struct i2c_driver rtq2208_driver = { + .driver = { + .name = "rtq2208", + .of_match_table = rtq2208_device_tables, + }, + .probe = rtq2208_probe, +}; +module_i2c_driver(rtq2208_driver); + +MODULE_AUTHOR("Alina Yu <alina_yu@richtek.com>"); +MODULE_DESCRIPTION("Richtek RTQ2208 Regulator Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/regulator/s2mpa01.c b/drivers/regulator/s2mpa01.c index b147ff6a16b1..c22fdde67f9c 100644 --- a/drivers/regulator/s2mpa01.c +++ b/drivers/regulator/s2mpa01.c @@ -5,7 +5,6 @@ #include <linux/bug.h> #include <linux/err.h> -#include <linux/gpio.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/of.h> diff --git a/drivers/regulator/stm32-pwr.c b/drivers/regulator/stm32-pwr.c index 4c60eddad60d..85b0102fb9b1 100644 --- a/drivers/regulator/stm32-pwr.c +++ b/drivers/regulator/stm32-pwr.c @@ -6,8 +6,7 @@ #include <linux/io.h> #include <linux/iopoll.h> #include <linux/module.h> -#include <linux/of_address.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/of_regulator.h> diff --git a/drivers/regulator/stm32-vrefbuf.c b/drivers/regulator/stm32-vrefbuf.c index f5ccc7dd309a..717144cbe0f9 100644 --- a/drivers/regulator/stm32-vrefbuf.c +++ b/drivers/regulator/stm32-vrefbuf.c @@ -10,7 +10,7 @@ #include <linux/io.h> #include <linux/iopoll.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/of_regulator.h> diff --git a/drivers/regulator/sy8824x.c b/drivers/regulator/sy8824x.c index d0703105c439..d49c0cba09fb 100644 --- a/drivers/regulator/sy8824x.c +++ b/drivers/regulator/sy8824x.c @@ -8,7 +8,7 @@ #include <linux/module.h> #include <linux/i2c.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regmap.h> #include <linux/regulator/driver.h> #include <linux/regulator/of_regulator.h> diff --git a/drivers/regulator/sy8827n.c b/drivers/regulator/sy8827n.c index 433959b43549..f11ff38b36c9 100644 --- a/drivers/regulator/sy8827n.c +++ b/drivers/regulator/sy8827n.c @@ -9,7 +9,7 @@ #include <linux/gpio/consumer.h> #include <linux/module.h> #include <linux/i2c.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regmap.h> #include <linux/regulator/driver.h> #include <linux/regulator/of_regulator.h> diff --git a/drivers/regulator/tps6286x-regulator.c b/drivers/regulator/tps6286x-regulator.c index b1c4b5120745..758c70269653 100644 --- a/drivers/regulator/tps6286x-regulator.c +++ b/drivers/regulator/tps6286x-regulator.c @@ -4,7 +4,7 @@ #include <linux/err.h> #include <linux/i2c.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/regmap.h> #include <linux/regulator/of_regulator.h> #include <linux/regulator/machine.h> @@ -84,11 +84,11 @@ static unsigned int tps6286x_of_map_mode(unsigned int mode) static const struct regulator_desc tps6286x_reg = { .name = "tps6286x", - .of_match = of_match_ptr("SW"), + .of_match = "SW", .owner = THIS_MODULE, .ops = &tps6286x_regulator_ops, .of_map_mode = tps6286x_of_map_mode, - .regulators_node = of_match_ptr("regulators"), + .regulators_node = "regulators", .type = REGULATOR_VOLTAGE, .n_voltages = ((TPS6286X_MAX_MV - TPS6286X_MIN_MV) / TPS6286X_STEP_MV) + 1, .min_uV = TPS6286X_MIN_MV * 1000, @@ -148,7 +148,7 @@ static struct i2c_driver tps6286x_regulator_driver = { .driver = { .name = "tps6286x", .probe_type = PROBE_PREFER_ASYNCHRONOUS, - .of_match_table = of_match_ptr(tps6286x_dt_ids), + .of_match_table = tps6286x_dt_ids, }, .probe = tps6286x_i2c_probe, .id_table = tps6286x_i2c_id, diff --git a/drivers/regulator/tps6287x-regulator.c b/drivers/regulator/tps6287x-regulator.c index b1c0963586ac..d022184a8e7d 100644 --- a/drivers/regulator/tps6287x-regulator.c +++ b/drivers/regulator/tps6287x-regulator.c @@ -8,8 +8,8 @@ #include <linux/err.h> #include <linux/i2c.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/regmap.h> #include <linux/regulator/of_regulator.h> #include <linux/regulator/machine.h> @@ -41,7 +41,7 @@ static const struct linear_range tps6287x_voltage_ranges[] = { }; static const unsigned int tps6287x_voltage_range_sel[] = { - 0x0, 0x4, 0x8, 0xC + 0x0, 0x1, 0x2, 0x3 }; static const unsigned int tps6287x_ramp_table[] = { @@ -122,7 +122,7 @@ static struct regulator_desc tps6287x_reg = { .n_voltages = 256, .linear_ranges = tps6287x_voltage_ranges, .n_linear_ranges = ARRAY_SIZE(tps6287x_voltage_ranges), - .linear_range_selectors = tps6287x_voltage_range_sel, + .linear_range_selectors_bitfield = tps6287x_voltage_range_sel, }; static int tps6287x_i2c_probe(struct i2c_client *i2c) diff --git a/drivers/regulator/tps65086-regulator.c b/drivers/regulator/tps65086-regulator.c index 663789198ba5..2d284c64eeb7 100644 --- a/drivers/regulator/tps65086-regulator.c +++ b/drivers/regulator/tps65086-regulator.c @@ -15,7 +15,15 @@ #include <linux/mfd/tps65086.h> enum tps65086_regulators { BUCK1, BUCK2, BUCK3, BUCK4, BUCK5, BUCK6, LDOA1, - LDOA2, LDOA3, SWA1, SWB1, SWB2, VTT }; + LDOA2, LDOA3, VTT, SWA1, SWB1, SWB2 }; + +/* Selector for regulator configuration regarding PMIC chip ID. */ +enum tps65086_ids { + TPS6508640 = 0, + TPS65086401, + TPS6508641, + TPS65086470, +}; #define TPS65086_REGULATOR(_name, _of, _id, _nv, _vr, _vm, _er, _em, _lr, _dr, _dm) \ [_id] = { \ @@ -57,12 +65,24 @@ enum tps65086_regulators { BUCK1, BUCK2, BUCK3, BUCK4, BUCK5, BUCK6, LDOA1, }, \ } + +#define TPS65086_REGULATOR_CONFIG(_chip_id, _config) \ + [_chip_id] = { \ + .config = _config, \ + .num_elems = ARRAY_SIZE(_config), \ + } + struct tps65086_regulator { struct regulator_desc desc; unsigned int decay_reg; unsigned int decay_mask; }; +struct tps65086_regulator_config { + struct tps65086_regulator * const config; + const unsigned int num_elems; +}; + static const struct linear_range tps65086_10mv_ranges[] = { REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0), REGULATOR_LINEAR_RANGE(410000, 0x1, 0x7F, 10000), @@ -114,7 +134,125 @@ static int tps65086_of_parse_cb(struct device_node *dev, const struct regulator_desc *desc, struct regulator_config *config); -static struct tps65086_regulator regulators[] = { +static struct tps65086_regulator tps6508640_regulator_config[] = { + TPS65086_REGULATOR("BUCK1", "buck1", BUCK1, 0x80, TPS65086_BUCK1CTRL, + BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(0), + tps65086_10mv_ranges, TPS65086_BUCK1CTRL, + BIT(0)), + TPS65086_REGULATOR("BUCK2", "buck2", BUCK2, 0x80, TPS65086_BUCK2CTRL, + BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(1), + tps65086_10mv_ranges, TPS65086_BUCK2CTRL, + BIT(0)), + TPS65086_REGULATOR("BUCK3", "buck3", BUCK3, 0x80, TPS65086_BUCK3VID, + BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(2), + tps65086_10mv_ranges, TPS65086_BUCK3DECAY, + BIT(0)), + TPS65086_REGULATOR("BUCK4", "buck4", BUCK4, 0x80, TPS65086_BUCK4VID, + BUCK_VID_MASK, TPS65086_BUCK4CTRL, BIT(0), + tps65086_10mv_ranges, TPS65086_BUCK4VID, + BIT(0)), + TPS65086_REGULATOR("BUCK5", "buck5", BUCK5, 0x80, TPS65086_BUCK5VID, + BUCK_VID_MASK, TPS65086_BUCK5CTRL, BIT(0), + tps65086_10mv_ranges, TPS65086_BUCK5CTRL, + BIT(0)), + TPS65086_REGULATOR("BUCK6", "buck6", BUCK6, 0x80, TPS65086_BUCK6VID, + BUCK_VID_MASK, TPS65086_BUCK6CTRL, BIT(0), + tps65086_10mv_ranges, TPS65086_BUCK6CTRL, + BIT(0)), + TPS65086_REGULATOR("LDOA1", "ldoa1", LDOA1, 0xF, TPS65086_LDOA1CTRL, + VDOA1_VID_MASK, TPS65086_SWVTT_EN, BIT(7), + tps65086_ldoa1_ranges, 0, 0), + TPS65086_REGULATOR("LDOA2", "ldoa2", LDOA2, 0x10, TPS65086_LDOA2VID, + VDOA23_VID_MASK, TPS65086_LDOA2CTRL, BIT(0), + tps65086_ldoa23_ranges, 0, 0), + TPS65086_REGULATOR("LDOA3", "ldoa3", LDOA3, 0x10, TPS65086_LDOA3VID, + VDOA23_VID_MASK, TPS65086_LDOA3CTRL, BIT(0), + tps65086_ldoa23_ranges, 0, 0), + TPS65086_SWITCH("VTT", "vtt", VTT, TPS65086_SWVTT_EN, BIT(4)), + TPS65086_SWITCH("SWA1", "swa1", SWA1, TPS65086_SWVTT_EN, BIT(5)), + TPS65086_SWITCH("SWB1", "swb1", SWB1, TPS65086_SWVTT_EN, BIT(6)), + TPS65086_SWITCH("SWB2", "swb2", SWB2, TPS65086_LDOA1CTRL, BIT(0)), +}; + +static struct tps65086_regulator tps65086401_regulator_config[] = { + TPS65086_REGULATOR("BUCK1", "buck1", BUCK1, 0x80, TPS65086_BUCK1CTRL, + BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(0), + tps65086_10mv_ranges, TPS65086_BUCK1CTRL, + BIT(0)), + TPS65086_REGULATOR("BUCK2", "buck2", BUCK2, 0x80, TPS65086_BUCK2CTRL, + BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(1), + tps65086_10mv_ranges, TPS65086_BUCK2CTRL, + BIT(0)), + TPS65086_REGULATOR("BUCK3", "buck3", BUCK3, 0x80, TPS65086_BUCK3VID, + BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(2), + tps65086_10mv_ranges, TPS65086_BUCK3DECAY, + BIT(0)), + TPS65086_REGULATOR("BUCK4", "buck4", BUCK4, 0x80, TPS65086_BUCK4VID, + BUCK_VID_MASK, TPS65086_BUCK4CTRL, BIT(0), + tps65086_10mv_ranges, TPS65086_BUCK4VID, + BIT(0)), + TPS65086_REGULATOR("BUCK5", "buck5", BUCK5, 0x80, TPS65086_BUCK5VID, + BUCK_VID_MASK, TPS65086_BUCK5CTRL, BIT(0), + tps65086_10mv_ranges, TPS65086_BUCK5CTRL, + BIT(0)), + TPS65086_REGULATOR("BUCK6", "buck6", BUCK6, 0x80, TPS65086_BUCK6VID, + BUCK_VID_MASK, TPS65086_BUCK6CTRL, BIT(0), + tps65086_10mv_ranges, TPS65086_BUCK6CTRL, + BIT(0)), + TPS65086_REGULATOR("LDOA1", "ldoa1", LDOA1, 0xF, TPS65086_LDOA1CTRL, + VDOA1_VID_MASK, TPS65086_SWVTT_EN, BIT(7), + tps65086_ldoa1_ranges, 0, 0), + TPS65086_REGULATOR("LDOA2", "ldoa2", LDOA2, 0x10, TPS65086_LDOA2VID, + VDOA23_VID_MASK, TPS65086_LDOA2CTRL, BIT(0), + tps65086_ldoa23_ranges, 0, 0), + TPS65086_REGULATOR("LDOA3", "ldoa3", LDOA3, 0x10, TPS65086_LDOA3VID, + VDOA23_VID_MASK, TPS65086_LDOA3CTRL, BIT(0), + tps65086_ldoa23_ranges, 0, 0), + TPS65086_SWITCH("VTT", "vtt", VTT, TPS65086_SWVTT_EN, BIT(4)), + TPS65086_SWITCH("SWA1", "swa1", SWA1, TPS65086_SWVTT_EN, BIT(5)), + TPS65086_SWITCH("SWB1", "swb1", SWB1, TPS65086_SWVTT_EN, BIT(6)), +}; + +static struct tps65086_regulator tps6508641_regulator_config[] = { + TPS65086_REGULATOR("BUCK1", "buck1", BUCK1, 0x80, TPS65086_BUCK1CTRL, + BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(0), + tps65086_10mv_ranges, TPS65086_BUCK1CTRL, + BIT(0)), + TPS65086_REGULATOR("BUCK2", "buck2", BUCK2, 0x80, TPS65086_BUCK2CTRL, + BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(1), + tps65086_10mv_ranges, TPS65086_BUCK2CTRL, + BIT(0)), + TPS65086_REGULATOR("BUCK3", "buck3", BUCK3, 0x80, TPS65086_BUCK3VID, + BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(2), + tps65086_10mv_ranges, TPS65086_BUCK3DECAY, + BIT(0)), + TPS65086_REGULATOR("BUCK4", "buck4", BUCK4, 0x80, TPS65086_BUCK4VID, + BUCK_VID_MASK, TPS65086_BUCK4CTRL, BIT(0), + tps65086_10mv_ranges, TPS65086_BUCK4VID, + BIT(0)), + TPS65086_REGULATOR("BUCK5", "buck5", BUCK5, 0x80, TPS65086_BUCK5VID, + BUCK_VID_MASK, TPS65086_BUCK5CTRL, BIT(0), + tps65086_10mv_ranges, TPS65086_BUCK5CTRL, + BIT(0)), + TPS65086_REGULATOR("BUCK6", "buck6", BUCK6, 0x80, TPS65086_BUCK6VID, + BUCK_VID_MASK, TPS65086_BUCK6CTRL, BIT(0), + tps65086_10mv_ranges, TPS65086_BUCK6CTRL, + BIT(0)), + TPS65086_REGULATOR("LDOA1", "ldoa1", LDOA1, 0xF, TPS65086_LDOA1CTRL, + VDOA1_VID_MASK, TPS65086_SWVTT_EN, BIT(7), + tps65086_ldoa1_ranges, 0, 0), + TPS65086_REGULATOR("LDOA2", "ldoa2", LDOA2, 0x10, TPS65086_LDOA2VID, + VDOA23_VID_MASK, TPS65086_LDOA2CTRL, BIT(0), + tps65086_ldoa23_ranges, 0, 0), + TPS65086_REGULATOR("LDOA3", "ldoa3", LDOA3, 0x10, TPS65086_LDOA3VID, + VDOA23_VID_MASK, TPS65086_LDOA3CTRL, BIT(0), + tps65086_ldoa23_ranges, 0, 0), + TPS65086_SWITCH("VTT", "vtt", VTT, TPS65086_SWVTT_EN, BIT(4)), + TPS65086_SWITCH("SWA1", "swa1", SWA1, TPS65086_SWVTT_EN, BIT(5)), + TPS65086_SWITCH("SWB1", "swb1", SWB1, TPS65086_SWVTT_EN, BIT(6)), +}; + +static struct tps65086_regulator tps65086470_regulator_config[] = { TPS65086_REGULATOR("BUCK1", "buck1", BUCK1, 0x80, TPS65086_BUCK1CTRL, BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(0), tps65086_10mv_ranges, TPS65086_BUCK1CTRL, @@ -148,16 +286,25 @@ static struct tps65086_regulator regulators[] = { TPS65086_REGULATOR("LDOA3", "ldoa3", LDOA3, 0x10, TPS65086_LDOA3VID, VDOA23_VID_MASK, TPS65086_LDOA3CTRL, BIT(0), tps65086_ldoa23_ranges, 0, 0), + TPS65086_SWITCH("VTT", "vtt", VTT, TPS65086_SWVTT_EN, BIT(4)), TPS65086_SWITCH("SWA1", "swa1", SWA1, TPS65086_SWVTT_EN, BIT(5)), TPS65086_SWITCH("SWB1", "swb1", SWB1, TPS65086_SWVTT_EN, BIT(6)), TPS65086_SWITCH("SWB2", "swb2", SWB2, TPS65086_SWVTT_EN, BIT(7)), - TPS65086_SWITCH("VTT", "vtt", VTT, TPS65086_SWVTT_EN, BIT(4)), +}; + +static const struct tps65086_regulator_config regulator_configs[] = { + TPS65086_REGULATOR_CONFIG(TPS6508640, tps6508640_regulator_config), + TPS65086_REGULATOR_CONFIG(TPS65086401, tps65086401_regulator_config), + TPS65086_REGULATOR_CONFIG(TPS6508641, tps6508641_regulator_config), + TPS65086_REGULATOR_CONFIG(TPS65086470, tps65086470_regulator_config) }; static int tps65086_of_parse_cb(struct device_node *node, const struct regulator_desc *desc, struct regulator_config *config) { + struct tps65086 * const tps = dev_get_drvdata(config->dev); + struct tps65086_regulator *regulators = tps->reg_config->config; int ret; /* Check for 25mV step mode */ @@ -203,9 +350,30 @@ static int tps65086_regulator_probe(struct platform_device *pdev) { struct tps65086 *tps = dev_get_drvdata(pdev->dev.parent); struct regulator_config config = { }; + unsigned int selector_reg_config; struct regulator_dev *rdev; int i; + /* Select regulator configuration for used PMIC device */ + switch (tps->chip_id) { + case TPS6508640_ID: + selector_reg_config = TPS6508640; + break; + case TPS65086401_ID: + selector_reg_config = TPS65086401; + break; + case TPS6508641_ID: + selector_reg_config = TPS6508641; + break; + case TPS65086470_ID: + selector_reg_config = TPS65086470; + break; + default: + dev_err(tps->dev, "Unknown device ID. Cannot determine regulator config.\n"); + return -ENODEV; + } + tps->reg_config = ®ulator_configs[selector_reg_config]; + platform_set_drvdata(pdev, tps); config.dev = &pdev->dev; @@ -213,12 +381,16 @@ static int tps65086_regulator_probe(struct platform_device *pdev) config.driver_data = tps; config.regmap = tps->regmap; - for (i = 0; i < ARRAY_SIZE(regulators); i++) { - rdev = devm_regulator_register(&pdev->dev, ®ulators[i].desc, - &config); + for (i = 0; i < tps->reg_config->num_elems; ++i) { + struct regulator_desc * const desc_ptr = &tps->reg_config->config[i].desc; + + dev_dbg(tps->dev, "Index: %u; Regulator name: \"%s\"; Regulator ID: %d\n", + i, desc_ptr->name, desc_ptr->id); + + rdev = devm_regulator_register(&pdev->dev, desc_ptr, &config); if (IS_ERR(rdev)) { - dev_err(tps->dev, "failed to register %s regulator\n", - pdev->name); + dev_err(tps->dev, "failed to register %d \"%s\" regulator\n", + i, desc_ptr->name); return PTR_ERR(rdev); } } diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c index 13985883e5f0..f44b5767099c 100644 --- a/drivers/regulator/tps65218-regulator.c +++ b/drivers/regulator/tps65218-regulator.c @@ -8,12 +8,12 @@ */ #include <linux/kernel.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> #include <linux/device.h> #include <linux/init.h> #include <linux/err.h> #include <linux/platform_device.h> -#include <linux/of_device.h> #include <linux/regmap.h> #include <linux/regulator/of_regulator.h> #include <linux/regulator/driver.h> diff --git a/drivers/regulator/tps65219-regulator.c b/drivers/regulator/tps65219-regulator.c index 8971b507a79a..b4065356392f 100644 --- a/drivers/regulator/tps65219-regulator.c +++ b/drivers/regulator/tps65219-regulator.c @@ -15,8 +15,8 @@ #include <linux/device.h> #include <linux/init.h> #include <linux/err.h> +#include <linux/of.h> #include <linux/platform_device.h> -#include <linux/of_device.h> #include <linux/regmap.h> #include <linux/regulator/of_regulator.h> #include <linux/regulator/driver.h> diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 2a0965ba1570..3a3027e0b94e 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c @@ -17,7 +17,6 @@ #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/slab.h> -#include <linux/gpio.h> #include <linux/mfd/tps65910.h> #include <linux/regulator/of_regulator.h> diff --git a/drivers/regulator/tps6594-regulator.c b/drivers/regulator/tps6594-regulator.c index d5a574ec6d12..25ef102c8270 100644 --- a/drivers/regulator/tps6594-regulator.c +++ b/drivers/regulator/tps6594-regulator.c @@ -9,7 +9,7 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/regulator/driver.h> diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 3e724f5345de..5bacfcebf59a 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -12,7 +12,6 @@ #include <linux/err.h> #include <linux/platform_device.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> diff --git a/drivers/regulator/twl6030-regulator.c b/drivers/regulator/twl6030-regulator.c index f9c695f9bde8..6eed0f6e0adb 100644 --- a/drivers/regulator/twl6030-regulator.c +++ b/drivers/regulator/twl6030-regulator.c @@ -13,7 +13,6 @@ #include <linux/err.h> #include <linux/platform_device.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> diff --git a/drivers/regulator/uniphier-regulator.c b/drivers/regulator/uniphier-regulator.c index 7e2785e10dc6..1d8304b88bd6 100644 --- a/drivers/regulator/uniphier-regulator.c +++ b/drivers/regulator/uniphier-regulator.c @@ -7,7 +7,7 @@ #include <linux/clk.h> #include <linux/io.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/regulator/driver.h> diff --git a/drivers/regulator/vctrl-regulator.c b/drivers/regulator/vctrl-regulator.c index 85dca90233f6..2796580a3a3c 100644 --- a/drivers/regulator/vctrl-regulator.c +++ b/drivers/regulator/vctrl-regulator.c @@ -10,7 +10,7 @@ #include <linux/init.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> #include <linux/regulator/coupler.h> #include <linux/regulator/driver.h> #include <linux/regulator/of_regulator.h> diff --git a/drivers/regulator/vexpress-regulator.c b/drivers/regulator/vexpress-regulator.c index b545dbc70a4d..6687077e9a97 100644 --- a/drivers/regulator/vexpress-regulator.c +++ b/drivers/regulator/vexpress-regulator.c @@ -8,7 +8,8 @@ #include <linux/device.h> #include <linux/err.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/mod_devicetable.h> +#include <linux/platform_device.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> #include <linux/regulator/of_regulator.h> diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 50a5ff70814a..215597f73be4 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -3636,11 +3636,8 @@ int dasd_generic_set_offline(struct ccw_device *cdev) * so sync bdev first and then wait for our queues to become * empty */ - if (device->block) { - rc = fsync_bdev(device->block->bdev); - if (rc != 0) - goto interrupted; - } + if (device->block) + bdev_mark_dead(device->block->bdev, false); dasd_schedule_device_bh(device); rc = wait_event_interruptible(shutdown_waitq, _wait_for_empty_queues(device)); diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 09acf3853a77..06bcb6c78909 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -412,6 +412,7 @@ removeseg: } list_del(&dev_info->lh); + dax_remove_host(dev_info->gd); kill_dax(dev_info->dax_dev); put_dax(dev_info->dax_dev); del_gendisk(dev_info->gd); @@ -707,9 +708,9 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char goto out; out_dax_host: + put_device(&dev_info->dev); dax_remove_host(dev_info->gd); out_dax: - put_device(&dev_info->dev); kill_dax(dev_info->dax_dev); put_dax(dev_info->dax_dev); put_dev: @@ -789,6 +790,7 @@ dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const ch } list_del(&dev_info->lh); + dax_remove_host(dev_info->gd); kill_dax(dev_info->dax_dev); put_dax(dev_info->dax_dev); del_gendisk(dev_info->gd); @@ -860,7 +862,7 @@ dcssblk_submit_bio(struct bio *bio) struct bio_vec bvec; struct bvec_iter iter; unsigned long index; - unsigned long page_addr; + void *page_addr; unsigned long source_addr; unsigned long bytes_done; @@ -868,8 +870,8 @@ dcssblk_submit_bio(struct bio *bio) dev_info = bio->bi_bdev->bd_disk->private_data; if (dev_info == NULL) goto fail; - if ((bio->bi_iter.bi_sector & 7) != 0 || - (bio->bi_iter.bi_size & 4095) != 0) + if (!IS_ALIGNED(bio->bi_iter.bi_sector, 8) || + !IS_ALIGNED(bio->bi_iter.bi_size, PAGE_SIZE)) /* Request is not page-aligned. */ goto fail; /* verify data transfer direction */ @@ -889,18 +891,16 @@ dcssblk_submit_bio(struct bio *bio) index = (bio->bi_iter.bi_sector >> 3); bio_for_each_segment(bvec, bio, iter) { - page_addr = (unsigned long)bvec_virt(&bvec); + page_addr = bvec_virt(&bvec); source_addr = dev_info->start + (index<<12) + bytes_done; - if (unlikely((page_addr & 4095) != 0) || (bvec.bv_len & 4095) != 0) + if (unlikely(!IS_ALIGNED((unsigned long)page_addr, PAGE_SIZE) || + !IS_ALIGNED(bvec.bv_len, PAGE_SIZE))) // More paranoia. goto fail; - if (bio_data_dir(bio) == READ) { - memcpy((void*)page_addr, (void*)source_addr, - bvec.bv_len); - } else { - memcpy((void*)source_addr, (void*)page_addr, - bvec.bv_len); - } + if (bio_data_dir(bio) == READ) + memcpy(page_addr, __va(source_addr), bvec.bv_len); + else + memcpy(__va(source_addr), page_addr, bvec.bv_len); bytes_done += bvec.bv_len; } bio_endio(bio); diff --git a/drivers/s390/block/scm_blk.c b/drivers/s390/block/scm_blk.c index 0c1df1d5f1ac..3a9cc8a4a230 100644 --- a/drivers/s390/block/scm_blk.c +++ b/drivers/s390/block/scm_blk.c @@ -134,7 +134,7 @@ static void scm_request_done(struct scm_request *scmrq) if ((msb->flags & MSB_FLAG_IDA) && aidaw && IS_ALIGNED(aidaw, PAGE_SIZE)) - mempool_free(virt_to_page(aidaw), aidaw_pool); + mempool_free(virt_to_page((void *)aidaw), aidaw_pool); } spin_lock_irqsave(&list_lock, flags); diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index 3c87057436d5..8b4575a0db9f 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c @@ -392,10 +392,6 @@ static void __init add_memory_merged(u16 rn) goto skip_add; start = rn2addr(first_rn); size = (unsigned long long) num * sclp.rzm; - if (start >= VMEM_MAX_PHYS) - goto skip_add; - if (start + size > VMEM_MAX_PHYS) - size = VMEM_MAX_PHYS - start; if (start >= ident_map_size) goto skip_add; if (start + size > ident_map_size) diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index f480d6c7fd39..fdc8668f3fba 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -55,6 +55,7 @@ static void __init sclp_early_facilities_detect(void) S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_GUEST; if (sccb->cpuoff > 134) { sclp.has_diag318 = !!(sccb->byte_134 & 0x80); + sclp.has_diag320 = !!(sccb->byte_134 & 0x04); sclp.has_iplcc = !!(sccb->byte_134 & 0x02); } if (sccb->cpuoff > 137) { diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c index 4cebfaaa22b4..eb0520a9d4af 100644 --- a/drivers/s390/char/vmcp.c +++ b/drivers/s390/char/vmcp.c @@ -89,7 +89,7 @@ static void vmcp_response_free(struct vmcp_session *session) order = get_order(session->bufsize); nr_pages = ALIGN(session->bufsize, PAGE_SIZE) >> PAGE_SHIFT; if (session->cma_alloc) { - page = virt_to_page((unsigned long)session->response); + page = virt_to_page(session->response); cma_release(vmcp_cma, page, nr_pages); session->cma_alloc = 0; } else { diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 942c73a11ca3..bc3be0330f1d 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c @@ -3,7 +3,7 @@ * zcore module to export memory content and register sets for creating system * dumps on SCSI/NVMe disks (zfcp/nvme dump). * - * For more information please refer to Documentation/s390/zfcpdump.rst + * For more information please refer to Documentation/arch/s390/zfcpdump.rst * * Copyright IBM Corp. 2003, 2008 * Author(s): Michael Holzheu diff --git a/drivers/s390/crypto/Makefile b/drivers/s390/crypto/Makefile index 22d2db690cd3..0edacd101c12 100644 --- a/drivers/s390/crypto/Makefile +++ b/drivers/s390/crypto/Makefile @@ -11,7 +11,7 @@ zcrypt-objs += zcrypt_msgtype6.o zcrypt_msgtype50.o zcrypt-objs += zcrypt_ccamisc.o zcrypt_ep11misc.o obj-$(CONFIG_ZCRYPT) += zcrypt.o # adapter drivers depend on ap.o and zcrypt.o -obj-$(CONFIG_ZCRYPT) += zcrypt_cex2c.o zcrypt_cex2a.o zcrypt_cex4.o +obj-$(CONFIG_ZCRYPT) += zcrypt_cex4.o # pkey kernel module pkey-objs := pkey_api.o diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 420120be300f..339812efe822 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright IBM Corp. 2006, 2021 + * Copyright IBM Corp. 2006, 2023 * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> * Martin Schwidefsky <schwidefsky@de.ibm.com> * Ralph Wuerthner <rwuerthn@de.ibm.com> @@ -219,6 +219,15 @@ int ap_sb_available(void) } /* + * ap_is_se_guest(): Check for SE guest with AP pass-through support. + */ +bool ap_is_se_guest(void) +{ + return is_prot_virt_guest() && ap_sb_available(); +} +EXPORT_SYMBOL(ap_is_se_guest); + +/* * ap_fetch_qci_info(): Fetch cryptographic config info * * Returns the ap configuration info fetched via PQAP(QCI). @@ -387,23 +396,6 @@ static int ap_queue_info(ap_qid_t qid, int *q_type, unsigned int *q_fac, *q_ml = tapq_info.ml; *q_decfg = status.response_code == AP_RESPONSE_DECONFIGURED; *q_cstop = status.response_code == AP_RESPONSE_CHECKSTOPPED; - switch (*q_type) { - /* For CEX2 and CEX3 the available functions - * are not reflected by the facilities bits. - * Instead it is coded into the type. So here - * modify the function bits based on the type. - */ - case AP_DEVICE_TYPE_CEX2A: - case AP_DEVICE_TYPE_CEX3A: - *q_fac |= 0x08000000; - break; - case AP_DEVICE_TYPE_CEX2C: - case AP_DEVICE_TYPE_CEX3C: - *q_fac |= 0x10000000; - break; - default: - break; - } return 1; default: /* @@ -1678,8 +1670,8 @@ static int ap_get_compatible_type(ap_qid_t qid, int rawtype, unsigned int func) { int comp_type = 0; - /* < CEX2A is not supported */ - if (rawtype < AP_DEVICE_TYPE_CEX2A) { + /* < CEX4 is not supported */ + if (rawtype < AP_DEVICE_TYPE_CEX4) { AP_DBF_WARN("%s queue=%02x.%04x unsupported type %d\n", __func__, AP_QID_CARD(qid), AP_QID_QUEUE(qid), rawtype); @@ -1701,7 +1693,7 @@ static int ap_get_compatible_type(ap_qid_t qid, int rawtype, unsigned int func) apinfo.cat = AP_DEVICE_TYPE_CEX8; status = ap_qact(qid, 0, &apinfo); if (status.response_code == AP_RESPONSE_NORMAL && - apinfo.cat >= AP_DEVICE_TYPE_CEX2A && + apinfo.cat >= AP_DEVICE_TYPE_CEX4 && apinfo.cat <= AP_DEVICE_TYPE_CEX8) comp_type = apinfo.cat; } diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 0d7b7eb374ad..be54b070c031 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Copyright IBM Corp. 2006, 2019 + * Copyright IBM Corp. 2006, 2023 * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> * Martin Schwidefsky <schwidefsky@de.ibm.com> * Ralph Wuerthner <rwuerthn@de.ibm.com> @@ -67,15 +67,8 @@ static inline int ap_test_bit(unsigned int *ptr, unsigned int nr) #define AP_RESPONSE_INVALID_DOMAIN 0x42 /* - * Known device types + * Supported AP device types */ -#define AP_DEVICE_TYPE_PCICC 3 -#define AP_DEVICE_TYPE_PCICA 4 -#define AP_DEVICE_TYPE_PCIXCC 5 -#define AP_DEVICE_TYPE_CEX2A 6 -#define AP_DEVICE_TYPE_CEX2C 7 -#define AP_DEVICE_TYPE_CEX3A 8 -#define AP_DEVICE_TYPE_CEX3C 9 #define AP_DEVICE_TYPE_CEX4 10 #define AP_DEVICE_TYPE_CEX5 11 #define AP_DEVICE_TYPE_CEX6 12 @@ -272,14 +265,6 @@ static inline void ap_release_message(struct ap_message *ap_msg) kfree_sensitive(ap_msg->private); } -/* - * Note: don't use ap_send/ap_recv after using ap_queue_message - * for the first time. Otherwise the ap message queue will get - * confused. - */ -int ap_send(ap_qid_t qid, unsigned long psmid, void *msg, size_t msglen); -int ap_recv(ap_qid_t qid, unsigned long *psmid, void *msg, size_t msglen); - enum ap_sm_wait ap_sm_event(struct ap_queue *aq, enum ap_sm_event event); enum ap_sm_wait ap_sm_event_loop(struct ap_queue *aq, enum ap_sm_event event); @@ -289,6 +274,7 @@ void ap_flush_queue(struct ap_queue *aq); void *ap_airq_ptr(void); int ap_sb_available(void); +bool ap_is_se_guest(void); void ap_wait(enum ap_sm_wait wait); void ap_request_timeout(struct timer_list *t); void ap_bus_force_rescan(void); diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c index 30df83735adf..1336e632adc4 100644 --- a/drivers/s390/crypto/ap_queue.c +++ b/drivers/s390/crypto/ap_queue.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright IBM Corp. 2016 + * Copyright IBM Corp. 2016, 2023 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> * * Adjunct processor bus, queue related code. @@ -93,51 +93,6 @@ __ap_send(ap_qid_t qid, unsigned long psmid, void *msg, size_t msglen, return ap_nqap(qid, psmid, msg, msglen); } -int ap_send(ap_qid_t qid, unsigned long psmid, void *msg, size_t msglen) -{ - struct ap_queue_status status; - - status = __ap_send(qid, psmid, msg, msglen, 0); - if (status.async) - return -EPERM; - switch (status.response_code) { - case AP_RESPONSE_NORMAL: - return 0; - case AP_RESPONSE_Q_FULL: - case AP_RESPONSE_RESET_IN_PROGRESS: - return -EBUSY; - case AP_RESPONSE_REQ_FAC_NOT_INST: - return -EINVAL; - default: /* Device is gone. */ - return -ENODEV; - } -} -EXPORT_SYMBOL(ap_send); - -int ap_recv(ap_qid_t qid, unsigned long *psmid, void *msg, size_t msglen) -{ - struct ap_queue_status status; - - if (!msg) - return -EINVAL; - status = ap_dqap(qid, psmid, msg, msglen, NULL, NULL, NULL); - if (status.async) - return -EPERM; - switch (status.response_code) { - case AP_RESPONSE_NORMAL: - return 0; - case AP_RESPONSE_NO_PENDING_REPLY: - if (status.queue_empty) - return -ENOENT; - return -EBUSY; - case AP_RESPONSE_RESET_IN_PROGRESS: - return -EBUSY; - default: - return -ENODEV; - } -} -EXPORT_SYMBOL(ap_recv); - /* State machine definitions and helpers */ static enum ap_sm_wait ap_sm_nop(struct ap_queue *aq) diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index e58bfd225323..6cfb6b2340c9 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c @@ -263,7 +263,9 @@ static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen, /* build a list of apqns suitable for ep11 keys with cpacf support */ rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, - ZCRYPT_CEX7, EP11_API_V, NULL); + ZCRYPT_CEX7, + ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4, + NULL); if (rc) goto out; @@ -272,7 +274,8 @@ static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen, card = apqns[i] >> 16; dom = apqns[i] & 0xFFFF; rc = ep11_clr2keyblob(card, dom, clrkeylen * 8, - 0, clrkey, keybuf, keybuflen); + 0, clrkey, keybuf, keybuflen, + PKEY_TYPE_EP11); if (rc == 0) break; } @@ -287,10 +290,9 @@ out: /* * Find card and transform EP11 secure key into protected key. */ -static int pkey_ep11key2pkey(const u8 *key, u8 *protkey, - u32 *protkeylen, u32 *protkeytype) +static int pkey_ep11key2pkey(const u8 *key, size_t keylen, + u8 *protkey, u32 *protkeylen, u32 *protkeytype) { - struct ep11keyblob *kb = (struct ep11keyblob *)key; u32 nr_apqns, *apqns = NULL; u16 card, dom; int i, rc; @@ -299,7 +301,9 @@ static int pkey_ep11key2pkey(const u8 *key, u8 *protkey, /* build a list of apqns suitable for this key */ rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, - ZCRYPT_CEX7, EP11_API_V, kb->wkvp); + ZCRYPT_CEX7, + ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4, + ep11_kb_wkvp(key, keylen)); if (rc) goto out; @@ -307,7 +311,7 @@ static int pkey_ep11key2pkey(const u8 *key, u8 *protkey, for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { card = apqns[i] >> 16; dom = apqns[i] & 0xFFFF; - rc = ep11_kblob2protkey(card, dom, key, kb->head.len, + rc = ep11_kblob2protkey(card, dom, key, keylen, protkey, protkeylen, protkeytype); if (rc == 0) break; @@ -495,7 +499,7 @@ try_via_ep11: tmpbuf, &tmpbuflen); if (rc) goto failure; - rc = pkey_ep11key2pkey(tmpbuf, + rc = pkey_ep11key2pkey(tmpbuf, tmpbuflen, protkey, protkeylen, protkeytype); if (!rc) goto out; @@ -611,7 +615,7 @@ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); if (rc) goto out; - rc = pkey_ep11key2pkey(key, + rc = pkey_ep11key2pkey(key, keylen, protkey, protkeylen, protkeytype); break; } @@ -620,7 +624,7 @@ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, rc = ep11_check_aes_key_with_hdr(debug_info, 3, key, keylen, 1); if (rc) goto out; - rc = pkey_ep11key2pkey(key + sizeof(struct ep11kblob_header), + rc = pkey_ep11key2pkey(key, keylen, protkey, protkeylen, protkeytype); break; default: @@ -713,6 +717,11 @@ static int pkey_genseckey2(const struct pkey_apqn *apqns, size_t nr_apqns, if (*keybufsize < MINEP11AESKEYBLOBSIZE) return -EINVAL; break; + case PKEY_TYPE_EP11_AES: + if (*keybufsize < (sizeof(struct ep11kblob_header) + + MINEP11AESKEYBLOBSIZE)) + return -EINVAL; + break; default: return -EINVAL; } @@ -729,9 +738,10 @@ static int pkey_genseckey2(const struct pkey_apqn *apqns, size_t nr_apqns, for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { card = apqns[i].card; dom = apqns[i].domain; - if (ktype == PKEY_TYPE_EP11) { + if (ktype == PKEY_TYPE_EP11 || + ktype == PKEY_TYPE_EP11_AES) { rc = ep11_genaeskey(card, dom, ksize, kflags, - keybuf, keybufsize); + keybuf, keybufsize, ktype); } else if (ktype == PKEY_TYPE_CCA_DATA) { rc = cca_genseckey(card, dom, ksize, keybuf); *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); @@ -769,6 +779,11 @@ static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns, if (*keybufsize < MINEP11AESKEYBLOBSIZE) return -EINVAL; break; + case PKEY_TYPE_EP11_AES: + if (*keybufsize < (sizeof(struct ep11kblob_header) + + MINEP11AESKEYBLOBSIZE)) + return -EINVAL; + break; default: return -EINVAL; } @@ -787,9 +802,11 @@ static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns, for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { card = apqns[i].card; dom = apqns[i].domain; - if (ktype == PKEY_TYPE_EP11) { + if (ktype == PKEY_TYPE_EP11 || + ktype == PKEY_TYPE_EP11_AES) { rc = ep11_clr2keyblob(card, dom, ksize, kflags, - clrkey, keybuf, keybufsize); + clrkey, keybuf, keybufsize, + ktype); } else if (ktype == PKEY_TYPE_CCA_DATA) { rc = cca_clr2seckey(card, dom, ksize, clrkey, keybuf); @@ -888,6 +905,7 @@ static int pkey_verifykey2(const u8 *key, size_t keylen, } else if (hdr->type == TOKTYPE_NON_CCA && hdr->version == TOKVER_EP11_AES) { struct ep11keyblob *kb = (struct ep11keyblob *)key; + int api; rc = ep11_check_aes_key(debug_info, 3, key, keylen, 1); if (rc) @@ -895,10 +913,12 @@ static int pkey_verifykey2(const u8 *key, size_t keylen, if (ktype) *ktype = PKEY_TYPE_EP11; if (ksize) - *ksize = kb->head.keybitlen; + *ksize = kb->head.bitlen; + api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, - ZCRYPT_CEX7, EP11_API_V, kb->wkvp); + ZCRYPT_CEX7, api, + ep11_kb_wkvp(key, keylen)); if (rc) goto out; @@ -908,6 +928,32 @@ static int pkey_verifykey2(const u8 *key, size_t keylen, *cardnr = ((struct pkey_apqn *)_apqns)->card; *domain = ((struct pkey_apqn *)_apqns)->domain; + } else if (hdr->type == TOKTYPE_NON_CCA && + hdr->version == TOKVER_EP11_AES_WITH_HEADER) { + struct ep11kblob_header *kh = (struct ep11kblob_header *)key; + int api; + + rc = ep11_check_aes_key_with_hdr(debug_info, 3, + key, keylen, 1); + if (rc) + goto out; + if (ktype) + *ktype = PKEY_TYPE_EP11_AES; + if (ksize) + *ksize = kh->bitlen; + + api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; + rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, + ZCRYPT_CEX7, api, + ep11_kb_wkvp(key, keylen)); + if (rc) + goto out; + + if (flags) + *flags = PKEY_FLAGS_MATCH_CUR_MKVP; + + *cardnr = ((struct pkey_apqn *)_apqns)->card; + *domain = ((struct pkey_apqn *)_apqns)->domain; } else { rc = -EINVAL; } @@ -949,10 +995,12 @@ static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, } } else if (hdr->type == TOKTYPE_NON_CCA) { if (hdr->version == TOKVER_EP11_AES) { - if (keylen < sizeof(struct ep11keyblob)) - return -EINVAL; if (ep11_check_aes_key(debug_info, 3, key, keylen, 1)) return -EINVAL; + } else if (hdr->version == TOKVER_EP11_AES_WITH_HEADER) { + if (ep11_check_aes_key_with_hdr(debug_info, 3, + key, keylen, 1)) + return -EINVAL; } else { return pkey_nonccatok2pkey(key, keylen, protkey, protkeylen, @@ -980,10 +1028,7 @@ static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, protkey, protkeylen, protkeytype); } else { - /* EP11 AES secure key blob */ - struct ep11keyblob *kb = (struct ep11keyblob *)key; - - rc = ep11_kblob2protkey(card, dom, key, kb->head.len, + rc = ep11_kblob2protkey(card, dom, key, keylen, protkey, protkeylen, protkeytype); } @@ -1018,7 +1063,7 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, return -EINVAL; if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { minhwtype = ZCRYPT_CEX7; - api = EP11_API_V; + api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; } rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, minhwtype, api, kb->wkvp); @@ -1034,7 +1079,7 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, return -EINVAL; if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { minhwtype = ZCRYPT_CEX7; - api = EP11_API_V; + api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; } rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, minhwtype, api, kb->wkvp); @@ -1144,11 +1189,13 @@ static int pkey_apqns4keytype(enum pkey_key_type ktype, ktype == PKEY_TYPE_EP11_AES || ktype == PKEY_TYPE_EP11_ECC) { u8 *wkvp = NULL; + int api; if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) wkvp = cur_mkvp; + api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, - ZCRYPT_CEX7, EP11_API_V, wkvp); + ZCRYPT_CEX7, api, wkvp); if (rc) goto out; @@ -1243,12 +1290,14 @@ static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns, hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) rc = ep11_kblob2protkey(card, dom, key, hdr->len, - protkey, protkeylen, protkeytype); + protkey, protkeylen, + protkeytype); else if (hdr->type == TOKTYPE_NON_CCA && hdr->version == TOKVER_EP11_AES && is_ep11_keyblob(key)) rc = ep11_kblob2protkey(card, dom, key, hdr->len, - protkey, protkeylen, protkeytype); + protkey, protkeylen, + protkeytype); else if (hdr->type == TOKTYPE_CCA_INTERNAL && hdr->version == TOKVER_CCA_AES) rc = cca_sec2protkey(card, dom, key, protkey, @@ -1466,7 +1515,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries); if (IS_ERR(apqns)) return PTR_ERR(apqns); - kkey = kmalloc(klen, GFP_KERNEL); + kkey = kzalloc(klen, GFP_KERNEL); if (!kkey) { kfree(apqns); return -ENOMEM; @@ -1508,7 +1557,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries); if (IS_ERR(apqns)) return PTR_ERR(apqns); - kkey = kmalloc(klen, GFP_KERNEL); + kkey = kzalloc(klen, GFP_KERNEL); if (!kkey) { kfree(apqns); return -ENOMEM; @@ -2102,7 +2151,7 @@ static struct attribute_group ccacipher_attr_group = { * (i.e. off != 0 or count < key blob size) -EINVAL is returned. * This function and the sysfs attributes using it provide EP11 key blobs * padded to the upper limit of MAXEP11AESKEYBLOBSIZE which is currently - * 320 bytes. + * 336 bytes. */ static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits, bool is_xts, char *buf, loff_t off, @@ -2120,7 +2169,9 @@ static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits, /* build a list of apqns able to generate an cipher key */ rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, - ZCRYPT_CEX7, EP11_API_V, NULL); + ZCRYPT_CEX7, + ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4, + NULL); if (rc) return rc; @@ -2130,7 +2181,8 @@ static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits, for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { card = apqns[i] >> 16; dom = apqns[i] & 0xFFFF; - rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize); + rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize, + PKEY_TYPE_EP11_AES); if (rc == 0) break; } @@ -2140,7 +2192,8 @@ static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits, if (is_xts) { keysize = MAXEP11AESKEYBLOBSIZE; buf += MAXEP11AESKEYBLOBSIZE; - rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize); + rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize, + PKEY_TYPE_EP11_AES); if (rc == 0) return 2 * MAXEP11AESKEYBLOBSIZE; } diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c index b441745b0418..0509f80622cd 100644 --- a/drivers/s390/crypto/vfio_ap_ops.c +++ b/drivers/s390/crypto/vfio_ap_ops.c @@ -30,13 +30,12 @@ #define AP_QUEUE_UNASSIGNED "unassigned" #define AP_QUEUE_IN_USE "in use" -#define MAX_RESET_CHECK_WAIT 200 /* Sleep max 200ms for reset check */ #define AP_RESET_INTERVAL 20 /* Reset sleep interval (20ms) */ static int vfio_ap_mdev_reset_queues(struct ap_queue_table *qtable); static struct vfio_ap_queue *vfio_ap_find_queue(int apqn); static const struct vfio_device_ops vfio_ap_matrix_dev_ops; -static int vfio_ap_mdev_reset_queue(struct vfio_ap_queue *q); +static void vfio_ap_mdev_reset_queue(struct vfio_ap_queue *q); /** * get_update_locks_for_kvm: Acquire the locks required to dynamically update a @@ -360,6 +359,28 @@ static int vfio_ap_validate_nib(struct kvm_vcpu *vcpu, dma_addr_t *nib) return 0; } +static int ensure_nib_shared(unsigned long addr, struct gmap *gmap) +{ + int ret; + + /* + * The nib has to be located in shared storage since guest and + * host access it. vfio_pin_pages() will do a pin shared and + * if that fails (possibly because it's not a shared page) it + * calls export. We try to do a second pin shared here so that + * the UV gives us an error code if we try to pin a non-shared + * page. + * + * If the page is already pinned shared the UV will return a success. + */ + ret = uv_pin_shared(addr); + if (ret) { + /* vfio_pin_pages() likely exported the page so let's re-import */ + gmap_convert_to_secure(gmap, addr); + } + return ret; +} + /** * vfio_ap_irq_enable - Enable Interruption for a APQN * @@ -423,6 +444,14 @@ static struct ap_queue_status vfio_ap_irq_enable(struct vfio_ap_queue *q, h_nib = page_to_phys(h_page) | (nib & ~PAGE_MASK); aqic_gisa.gisc = isc; + /* NIB in non-shared storage is a rc 6 for PV guests */ + if (kvm_s390_pv_cpu_is_protected(vcpu) && + ensure_nib_shared(h_nib & PAGE_MASK, kvm->arch.gmap)) { + vfio_unpin_pages(&q->matrix_mdev->vdev, nib, 1); + status.response_code = AP_RESPONSE_INVALID_ADDRESS; + return status; + } + nisc = kvm_s390_gisc_register(kvm, isc); if (nisc < 0) { VFIO_AP_DBF_WARN("%s: gisc registration failed: nisc=%d, isc=%d, apqn=%#04x\n", @@ -675,7 +704,7 @@ static bool vfio_ap_mdev_filter_matrix(unsigned long *apm, unsigned long *aqm, */ apqn = AP_MKQID(apid, apqi); q = vfio_ap_mdev_get_queue(matrix_mdev, apqn); - if (!q || q->reset_rc) { + if (!q || q->reset_status.response_code) { clear_bit_inv(apid, matrix_mdev->shadow_apcb.apm); break; @@ -1608,19 +1637,21 @@ static int apq_status_check(int apqn, struct ap_queue_status *status) { switch (status->response_code) { case AP_RESPONSE_NORMAL: + case AP_RESPONSE_DECONFIGURED: + return 0; case AP_RESPONSE_RESET_IN_PROGRESS: - if (status->queue_empty && !status->irq_enabled) - return 0; + case AP_RESPONSE_BUSY: return -EBUSY; - case AP_RESPONSE_DECONFIGURED: + case AP_RESPONSE_ASSOC_SECRET_NOT_UNIQUE: + case AP_RESPONSE_ASSOC_FAILED: /* - * If the AP queue is deconfigured, any subsequent AP command - * targeting the queue will fail with the same response code. On the - * other hand, when an AP adapter is deconfigured, the associated - * queues are reset, so let's return a value indicating the reset - * for which we're waiting completed successfully. + * These asynchronous response codes indicate a PQAP(AAPQ) + * instruction to associate a secret with the guest failed. All + * subsequent AP instructions will end with the asynchronous + * response code until the AP queue is reset; so, let's return + * a value indicating a reset needs to be performed again. */ - return 0; + return -EAGAIN; default: WARN(true, "failed to verify reset of queue %02x.%04x: TAPQ rc=%u\n", @@ -1630,91 +1661,105 @@ static int apq_status_check(int apqn, struct ap_queue_status *status) } } -static int apq_reset_check(struct vfio_ap_queue *q) +#define WAIT_MSG "Waited %dms for reset of queue %02x.%04x (%u, %u, %u)" + +static void apq_reset_check(struct work_struct *reset_work) { - int ret; - int iters = MAX_RESET_CHECK_WAIT / AP_RESET_INTERVAL; + int ret = -EBUSY, elapsed = 0; struct ap_queue_status status; + struct vfio_ap_queue *q; - for (; iters > 0; iters--) { + q = container_of(reset_work, struct vfio_ap_queue, reset_work); + memcpy(&status, &q->reset_status, sizeof(status)); + while (true) { msleep(AP_RESET_INTERVAL); + elapsed += AP_RESET_INTERVAL; status = ap_tapq(q->apqn, NULL); ret = apq_status_check(q->apqn, &status); - if (ret != -EBUSY) - return ret; + if (ret == -EIO) + return; + if (ret == -EBUSY) { + pr_notice_ratelimited(WAIT_MSG, elapsed, + AP_QID_CARD(q->apqn), + AP_QID_QUEUE(q->apqn), + status.response_code, + status.queue_empty, + status.irq_enabled); + } else { + if (q->reset_status.response_code == AP_RESPONSE_RESET_IN_PROGRESS || + q->reset_status.response_code == AP_RESPONSE_BUSY || + q->reset_status.response_code == AP_RESPONSE_STATE_CHANGE_IN_PROGRESS || + ret == -EAGAIN) { + status = ap_zapq(q->apqn, 0); + memcpy(&q->reset_status, &status, sizeof(status)); + continue; + } + /* + * When an AP adapter is deconfigured, the + * associated queues are reset, so let's set the + * status response code to 0 so the queue may be + * passed through (i.e., not filtered) + */ + if (status.response_code == AP_RESPONSE_DECONFIGURED) + q->reset_status.response_code = 0; + if (q->saved_isc != VFIO_AP_ISC_INVALID) + vfio_ap_free_aqic_resources(q); + break; + } } - WARN_ONCE(iters <= 0, - "timeout verifying reset of queue %02x.%04x (%u, %u, %u)", - AP_QID_CARD(q->apqn), AP_QID_QUEUE(q->apqn), - status.queue_empty, status.irq_enabled, status.response_code); - return ret; } -static int vfio_ap_mdev_reset_queue(struct vfio_ap_queue *q) +static void vfio_ap_mdev_reset_queue(struct vfio_ap_queue *q) { struct ap_queue_status status; - int ret; if (!q) - return 0; -retry_zapq: + return; status = ap_zapq(q->apqn, 0); - q->reset_rc = status.response_code; + memcpy(&q->reset_status, &status, sizeof(status)); switch (status.response_code) { case AP_RESPONSE_NORMAL: - ret = 0; - /* if the reset has not completed, wait for it to take effect */ - if (!status.queue_empty || status.irq_enabled) - ret = apq_reset_check(q); - break; case AP_RESPONSE_RESET_IN_PROGRESS: + case AP_RESPONSE_BUSY: + case AP_RESPONSE_STATE_CHANGE_IN_PROGRESS: /* - * There is a reset issued by another process in progress. Let's wait - * for that to complete. Since we have no idea whether it was a RAPQ or - * ZAPQ, then if it completes successfully, let's issue the ZAPQ. + * Let's verify whether the ZAPQ completed successfully on a work queue. */ - ret = apq_reset_check(q); - if (ret) - break; - goto retry_zapq; + queue_work(system_long_wq, &q->reset_work); + break; case AP_RESPONSE_DECONFIGURED: /* * When an AP adapter is deconfigured, the associated - * queues are reset, so let's return a value indicating the reset - * completed successfully. + * queues are reset, so let's set the status response code to 0 + * so the queue may be passed through (i.e., not filtered). */ - ret = 0; + q->reset_status.response_code = 0; + vfio_ap_free_aqic_resources(q); break; default: WARN(true, "PQAP/ZAPQ for %02x.%04x failed with invalid rc=%u\n", AP_QID_CARD(q->apqn), AP_QID_QUEUE(q->apqn), status.response_code); - return -EIO; } - - vfio_ap_free_aqic_resources(q); - - return ret; } static int vfio_ap_mdev_reset_queues(struct ap_queue_table *qtable) { - int ret, loop_cursor, rc = 0; + int ret = 0, loop_cursor; struct vfio_ap_queue *q; + hash_for_each(qtable->queues, loop_cursor, q, mdev_qnode) + vfio_ap_mdev_reset_queue(q); + hash_for_each(qtable->queues, loop_cursor, q, mdev_qnode) { - ret = vfio_ap_mdev_reset_queue(q); - /* - * Regardless whether a queue turns out to be busy, or - * is not operational, we need to continue resetting - * the remaining queues. - */ - if (ret) - rc = ret; + flush_work(&q->reset_work); + + if (q->reset_status.response_code) + ret = -EIO; } - return rc; + return ret; } static int vfio_ap_mdev_open_device(struct vfio_device *vdev) @@ -2038,6 +2083,8 @@ int vfio_ap_mdev_probe_queue(struct ap_device *apdev) q->apqn = to_ap_queue(&apdev->device)->qid; q->saved_isc = VFIO_AP_ISC_INVALID; + memset(&q->reset_status, 0, sizeof(q->reset_status)); + INIT_WORK(&q->reset_work, apq_reset_check); matrix_mdev = get_update_locks_by_apqn(q->apqn); if (matrix_mdev) { @@ -2087,6 +2134,7 @@ void vfio_ap_mdev_remove_queue(struct ap_device *apdev) } vfio_ap_mdev_reset_queue(q); + flush_work(&q->reset_work); dev_set_drvdata(&apdev->device, NULL); kfree(q); release_update_locks_for_mdev(matrix_mdev); diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h index 4642bbdbd1b2..88aff8b81f2f 100644 --- a/drivers/s390/crypto/vfio_ap_private.h +++ b/drivers/s390/crypto/vfio_ap_private.h @@ -133,7 +133,8 @@ struct ap_matrix_mdev { * @apqn: the APQN of the AP queue device * @saved_isc: the guest ISC registered with the GIB interface * @mdev_qnode: allows the vfio_ap_queue struct to be added to a hashtable - * @reset_rc: the status response code from the last reset of the queue + * @reset_status: the status from the last reset of the queue + * @reset_work: work to wait for queue reset to complete */ struct vfio_ap_queue { struct ap_matrix_mdev *matrix_mdev; @@ -142,7 +143,8 @@ struct vfio_ap_queue { #define VFIO_AP_ISC_INVALID 0xff unsigned char saved_isc; struct hlist_node mdev_qnode; - unsigned int reset_rc; + struct ap_queue_status reset_status; + struct work_struct reset_work; }; int vfio_ap_mdev_register(void); diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c index 83f692c9c197..e69de29bb2d1 100644 --- a/drivers/s390/crypto/zcrypt_cex2a.c +++ b/drivers/s390/crypto/zcrypt_cex2a.c @@ -1,227 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright IBM Corp. 2001, 2012 - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> - * Ralph Wuerthner <rwuerthn@de.ibm.com> - * MSGTYPE restruct: Holger Dengler <hd@linux.vnet.ibm.com> - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/err.h> -#include <linux/atomic.h> -#include <linux/uaccess.h> -#include <linux/mod_devicetable.h> - -#include "ap_bus.h" -#include "zcrypt_api.h" -#include "zcrypt_error.h" -#include "zcrypt_cex2a.h" -#include "zcrypt_msgtype50.h" - -#define CEX2A_MIN_MOD_SIZE 1 /* 8 bits */ -#define CEX2A_MAX_MOD_SIZE 256 /* 2048 bits */ -#define CEX3A_MIN_MOD_SIZE CEX2A_MIN_MOD_SIZE -#define CEX3A_MAX_MOD_SIZE 512 /* 4096 bits */ - -#define CEX2A_MAX_MESSAGE_SIZE 0x390 /* sizeof(struct type50_crb2_msg) */ -#define CEX2A_MAX_RESPONSE_SIZE 0x110 /* max outputdatalength + type80_hdr */ - -#define CEX3A_MAX_RESPONSE_SIZE 0x210 /* 512 bit modulus - * (max outputdatalength) + - * type80_hdr - */ -#define CEX3A_MAX_MESSAGE_SIZE sizeof(struct type50_crb3_msg) - -#define CEX2A_CLEANUP_TIME (15 * HZ) -#define CEX3A_CLEANUP_TIME CEX2A_CLEANUP_TIME - -MODULE_AUTHOR("IBM Corporation"); -MODULE_DESCRIPTION("CEX2A/CEX3A Cryptographic Coprocessor device driver, " \ - "Copyright IBM Corp. 2001, 2018"); -MODULE_LICENSE("GPL"); - -static struct ap_device_id zcrypt_cex2a_card_ids[] = { - { .dev_type = AP_DEVICE_TYPE_CEX2A, - .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE }, - { .dev_type = AP_DEVICE_TYPE_CEX3A, - .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE }, - { /* end of list */ }, -}; - -MODULE_DEVICE_TABLE(ap, zcrypt_cex2a_card_ids); - -static struct ap_device_id zcrypt_cex2a_queue_ids[] = { - { .dev_type = AP_DEVICE_TYPE_CEX2A, - .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE }, - { .dev_type = AP_DEVICE_TYPE_CEX3A, - .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE }, - { /* end of list */ }, -}; - -MODULE_DEVICE_TABLE(ap, zcrypt_cex2a_queue_ids); - -/* - * Probe function for CEX2A card devices. It always accepts the AP device - * since the bus_match already checked the card type. - * @ap_dev: pointer to the AP device. - */ -static int zcrypt_cex2a_card_probe(struct ap_device *ap_dev) -{ - /* - * Normalized speed ratings per crypto adapter - * MEX_1k, MEX_2k, MEX_4k, CRT_1k, CRT_2k, CRT_4k, RNG, SECKEY - */ - static const int CEX2A_SPEED_IDX[] = { - 800, 1000, 2000, 900, 1200, 2400, 0, 0}; - static const int CEX3A_SPEED_IDX[] = { - 400, 500, 1000, 450, 550, 1200, 0, 0}; - - struct ap_card *ac = to_ap_card(&ap_dev->device); - struct zcrypt_card *zc; - int rc = 0; - - zc = zcrypt_card_alloc(); - if (!zc) - return -ENOMEM; - zc->card = ac; - dev_set_drvdata(&ap_dev->device, zc); - - if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX2A) { - zc->min_mod_size = CEX2A_MIN_MOD_SIZE; - zc->max_mod_size = CEX2A_MAX_MOD_SIZE; - zc->speed_rating = CEX2A_SPEED_IDX; - zc->max_exp_bit_length = CEX2A_MAX_MOD_SIZE; - zc->type_string = "CEX2A"; - zc->user_space_type = ZCRYPT_CEX2A; - } else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX3A) { - zc->min_mod_size = CEX2A_MIN_MOD_SIZE; - zc->max_mod_size = CEX2A_MAX_MOD_SIZE; - zc->max_exp_bit_length = CEX2A_MAX_MOD_SIZE; - if (ap_test_bit(&ac->functions, AP_FUNC_MEX4K) && - ap_test_bit(&ac->functions, AP_FUNC_CRT4K)) { - zc->max_mod_size = CEX3A_MAX_MOD_SIZE; - zc->max_exp_bit_length = CEX3A_MAX_MOD_SIZE; - } - zc->speed_rating = CEX3A_SPEED_IDX; - zc->type_string = "CEX3A"; - zc->user_space_type = ZCRYPT_CEX3A; - } else { - zcrypt_card_free(zc); - return -ENODEV; - } - zc->online = 1; - - rc = zcrypt_card_register(zc); - if (rc) - zcrypt_card_free(zc); - - return rc; -} - -/* - * This is called to remove the CEX2A card driver information - * if an AP card device is removed. - */ -static void zcrypt_cex2a_card_remove(struct ap_device *ap_dev) -{ - struct zcrypt_card *zc = dev_get_drvdata(&ap_dev->device); - - zcrypt_card_unregister(zc); -} - -static struct ap_driver zcrypt_cex2a_card_driver = { - .probe = zcrypt_cex2a_card_probe, - .remove = zcrypt_cex2a_card_remove, - .ids = zcrypt_cex2a_card_ids, - .flags = AP_DRIVER_FLAG_DEFAULT, -}; - -/* - * Probe function for CEX2A queue devices. It always accepts the AP device - * since the bus_match already checked the queue type. - * @ap_dev: pointer to the AP device. - */ -static int zcrypt_cex2a_queue_probe(struct ap_device *ap_dev) -{ - struct ap_queue *aq = to_ap_queue(&ap_dev->device); - struct zcrypt_queue *zq = NULL; - int rc; - - switch (ap_dev->device_type) { - case AP_DEVICE_TYPE_CEX2A: - zq = zcrypt_queue_alloc(CEX2A_MAX_RESPONSE_SIZE); - if (!zq) - return -ENOMEM; - break; - case AP_DEVICE_TYPE_CEX3A: - zq = zcrypt_queue_alloc(CEX3A_MAX_RESPONSE_SIZE); - if (!zq) - return -ENOMEM; - break; - } - if (!zq) - return -ENODEV; - zq->ops = zcrypt_msgtype(MSGTYPE50_NAME, MSGTYPE50_VARIANT_DEFAULT); - zq->queue = aq; - zq->online = 1; - atomic_set(&zq->load, 0); - ap_queue_init_state(aq); - ap_queue_init_reply(aq, &zq->reply); - aq->request_timeout = CEX2A_CLEANUP_TIME; - dev_set_drvdata(&ap_dev->device, zq); - rc = zcrypt_queue_register(zq); - if (rc) - zcrypt_queue_free(zq); - - return rc; -} - -/* - * This is called to remove the CEX2A queue driver information - * if an AP queue device is removed. - */ -static void zcrypt_cex2a_queue_remove(struct ap_device *ap_dev) -{ - struct zcrypt_queue *zq = dev_get_drvdata(&ap_dev->device); - - zcrypt_queue_unregister(zq); -} - -static struct ap_driver zcrypt_cex2a_queue_driver = { - .probe = zcrypt_cex2a_queue_probe, - .remove = zcrypt_cex2a_queue_remove, - .ids = zcrypt_cex2a_queue_ids, - .flags = AP_DRIVER_FLAG_DEFAULT, -}; - -int __init zcrypt_cex2a_init(void) -{ - int rc; - - rc = ap_driver_register(&zcrypt_cex2a_card_driver, - THIS_MODULE, "cex2acard"); - if (rc) - return rc; - - rc = ap_driver_register(&zcrypt_cex2a_queue_driver, - THIS_MODULE, "cex2aqueue"); - if (rc) - ap_driver_unregister(&zcrypt_cex2a_card_driver); - - return rc; -} - -void __exit zcrypt_cex2a_exit(void) -{ - ap_driver_unregister(&zcrypt_cex2a_queue_driver); - ap_driver_unregister(&zcrypt_cex2a_card_driver); -} - -module_init(zcrypt_cex2a_init); -module_exit(zcrypt_cex2a_exit); diff --git a/drivers/s390/crypto/zcrypt_cex2a.h b/drivers/s390/crypto/zcrypt_cex2a.h index 7842214d9d09..e69de29bb2d1 100644 --- a/drivers/s390/crypto/zcrypt_cex2a.h +++ b/drivers/s390/crypto/zcrypt_cex2a.h @@ -1,134 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright IBM Corp. 2001, 2006 - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> - */ - -#ifndef _ZCRYPT_CEX2A_H_ -#define _ZCRYPT_CEX2A_H_ - -/** - * The type 50 message family is associated with CEXxA cards. - * - * The four members of the family are described below. - * - * Note that all unsigned char arrays are right-justified and left-padded - * with zeroes. - * - * Note that all reserved fields must be zeroes. - */ -struct type50_hdr { - unsigned char reserved1; - unsigned char msg_type_code; /* 0x50 */ - unsigned short msg_len; - unsigned char reserved2; - unsigned char ignored; - unsigned short reserved3; -} __packed; - -#define TYPE50_TYPE_CODE 0x50 - -#define TYPE50_MEB1_FMT 0x0001 -#define TYPE50_MEB2_FMT 0x0002 -#define TYPE50_MEB3_FMT 0x0003 -#define TYPE50_CRB1_FMT 0x0011 -#define TYPE50_CRB2_FMT 0x0012 -#define TYPE50_CRB3_FMT 0x0013 - -/* Mod-Exp, with a small modulus */ -struct type50_meb1_msg { - struct type50_hdr header; - unsigned short keyblock_type; /* 0x0001 */ - unsigned char reserved[6]; - unsigned char exponent[128]; - unsigned char modulus[128]; - unsigned char message[128]; -} __packed; - -/* Mod-Exp, with a large modulus */ -struct type50_meb2_msg { - struct type50_hdr header; - unsigned short keyblock_type; /* 0x0002 */ - unsigned char reserved[6]; - unsigned char exponent[256]; - unsigned char modulus[256]; - unsigned char message[256]; -} __packed; - -/* Mod-Exp, with a larger modulus */ -struct type50_meb3_msg { - struct type50_hdr header; - unsigned short keyblock_type; /* 0x0003 */ - unsigned char reserved[6]; - unsigned char exponent[512]; - unsigned char modulus[512]; - unsigned char message[512]; -} __packed; - -/* CRT, with a small modulus */ -struct type50_crb1_msg { - struct type50_hdr header; - unsigned short keyblock_type; /* 0x0011 */ - unsigned char reserved[6]; - unsigned char p[64]; - unsigned char q[64]; - unsigned char dp[64]; - unsigned char dq[64]; - unsigned char u[64]; - unsigned char message[128]; -} __packed; - -/* CRT, with a large modulus */ -struct type50_crb2_msg { - struct type50_hdr header; - unsigned short keyblock_type; /* 0x0012 */ - unsigned char reserved[6]; - unsigned char p[128]; - unsigned char q[128]; - unsigned char dp[128]; - unsigned char dq[128]; - unsigned char u[128]; - unsigned char message[256]; -} __packed; - -/* CRT, with a larger modulus */ -struct type50_crb3_msg { - struct type50_hdr header; - unsigned short keyblock_type; /* 0x0013 */ - unsigned char reserved[6]; - unsigned char p[256]; - unsigned char q[256]; - unsigned char dp[256]; - unsigned char dq[256]; - unsigned char u[256]; - unsigned char message[512]; -} __packed; - -/** - * The type 80 response family is associated with a CEXxA cards. - * - * Note that all unsigned char arrays are right-justified and left-padded - * with zeroes. - * - * Note that all reserved fields must be zeroes. - */ - -#define TYPE80_RSP_CODE 0x80 - -struct type80_hdr { - unsigned char reserved1; - unsigned char type; /* 0x80 */ - unsigned short len; - unsigned char code; /* 0x00 */ - unsigned char reserved2[3]; - unsigned char reserved3[8]; -} __packed; - -int zcrypt_cex2a_init(void); -void zcrypt_cex2a_exit(void); - -#endif /* _ZCRYPT_CEX2A_H_ */ diff --git a/drivers/s390/crypto/zcrypt_cex2c.c b/drivers/s390/crypto/zcrypt_cex2c.c index 251b5bd3d19c..e69de29bb2d1 100644 --- a/drivers/s390/crypto/zcrypt_cex2c.c +++ b/drivers/s390/crypto/zcrypt_cex2c.c @@ -1,421 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright IBM Corp. 2001, 2018 - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> - * Ralph Wuerthner <rwuerthn@de.ibm.com> - * MSGTYPE restruct: Holger Dengler <hd@linux.vnet.ibm.com> - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/err.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/atomic.h> -#include <linux/uaccess.h> -#include <linux/mod_devicetable.h> - -#include "ap_bus.h" -#include "zcrypt_api.h" -#include "zcrypt_error.h" -#include "zcrypt_msgtype6.h" -#include "zcrypt_cex2c.h" -#include "zcrypt_cca_key.h" -#include "zcrypt_ccamisc.h" - -#define CEX2C_MIN_MOD_SIZE 16 /* 128 bits */ -#define CEX2C_MAX_MOD_SIZE 256 /* 2048 bits */ -#define CEX3C_MIN_MOD_SIZE 16 /* 128 bits */ -#define CEX3C_MAX_MOD_SIZE 512 /* 4096 bits */ -#define CEX2C_MAX_XCRB_MESSAGE_SIZE (12 * 1024) -#define CEX2C_CLEANUP_TIME (15 * HZ) - -MODULE_AUTHOR("IBM Corporation"); -MODULE_DESCRIPTION("CEX2C/CEX3C Cryptographic Coprocessor device driver, " \ - "Copyright IBM Corp. 2001, 2018"); -MODULE_LICENSE("GPL"); - -static struct ap_device_id zcrypt_cex2c_card_ids[] = { - { .dev_type = AP_DEVICE_TYPE_CEX2C, - .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE }, - { .dev_type = AP_DEVICE_TYPE_CEX3C, - .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE }, - { /* end of list */ }, -}; - -MODULE_DEVICE_TABLE(ap, zcrypt_cex2c_card_ids); - -static struct ap_device_id zcrypt_cex2c_queue_ids[] = { - { .dev_type = AP_DEVICE_TYPE_CEX2C, - .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE }, - { .dev_type = AP_DEVICE_TYPE_CEX3C, - .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE }, - { /* end of list */ }, -}; - -MODULE_DEVICE_TABLE(ap, zcrypt_cex2c_queue_ids); - -/* - * CCA card additional device attributes - */ -static ssize_t cca_serialnr_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct zcrypt_card *zc = dev_get_drvdata(dev); - struct cca_info ci; - struct ap_card *ac = to_ap_card(dev); - - memset(&ci, 0, sizeof(ci)); - - if (ap_domain_index >= 0) - cca_get_info(ac->id, ap_domain_index, &ci, zc->online); - - return sysfs_emit(buf, "%s\n", ci.serial); -} - -static struct device_attribute dev_attr_cca_serialnr = - __ATTR(serialnr, 0444, cca_serialnr_show, NULL); - -static struct attribute *cca_card_attrs[] = { - &dev_attr_cca_serialnr.attr, - NULL, -}; - -static const struct attribute_group cca_card_attr_grp = { - .attrs = cca_card_attrs, -}; - - /* - * CCA queue additional device attributes - */ -static ssize_t cca_mkvps_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct zcrypt_queue *zq = dev_get_drvdata(dev); - int n = 0; - struct cca_info ci; - static const char * const cao_state[] = { "invalid", "valid" }; - static const char * const new_state[] = { "empty", "partial", "full" }; - - memset(&ci, 0, sizeof(ci)); - - cca_get_info(AP_QID_CARD(zq->queue->qid), - AP_QID_QUEUE(zq->queue->qid), - &ci, zq->online); - - if (ci.new_aes_mk_state >= '1' && ci.new_aes_mk_state <= '3') - n = sysfs_emit(buf, "AES NEW: %s 0x%016llx\n", - new_state[ci.new_aes_mk_state - '1'], - ci.new_aes_mkvp); - else - n = sysfs_emit(buf, "AES NEW: - -\n"); - - if (ci.cur_aes_mk_state >= '1' && ci.cur_aes_mk_state <= '2') - n += sysfs_emit_at(buf, n, "AES CUR: %s 0x%016llx\n", - cao_state[ci.cur_aes_mk_state - '1'], - ci.cur_aes_mkvp); - else - n += sysfs_emit_at(buf, n, "AES CUR: - -\n"); - - if (ci.old_aes_mk_state >= '1' && ci.old_aes_mk_state <= '2') - n += sysfs_emit_at(buf, n, "AES OLD: %s 0x%016llx\n", - cao_state[ci.old_aes_mk_state - '1'], - ci.old_aes_mkvp); - else - n += sysfs_emit_at(buf, n, "AES OLD: - -\n"); - - if (ci.new_apka_mk_state >= '1' && ci.new_apka_mk_state <= '3') - n += sysfs_emit_at(buf, n, "APKA NEW: %s 0x%016llx\n", - new_state[ci.new_apka_mk_state - '1'], - ci.new_apka_mkvp); - else - n += sysfs_emit_at(buf, n, "APKA NEW: - -\n"); - - if (ci.cur_apka_mk_state >= '1' && ci.cur_apka_mk_state <= '2') - n += sysfs_emit_at(buf, n, "APKA CUR: %s 0x%016llx\n", - cao_state[ci.cur_apka_mk_state - '1'], - ci.cur_apka_mkvp); - else - n += sysfs_emit_at(buf, n, "APKA CUR: - -\n"); - - if (ci.old_apka_mk_state >= '1' && ci.old_apka_mk_state <= '2') - n += sysfs_emit_at(buf, n, "APKA OLD: %s 0x%016llx\n", - cao_state[ci.old_apka_mk_state - '1'], - ci.old_apka_mkvp); - else - n += sysfs_emit_at(buf, n, "APKA OLD: - -\n"); - - return n; -} - -static struct device_attribute dev_attr_cca_mkvps = - __ATTR(mkvps, 0444, cca_mkvps_show, NULL); - -static struct attribute *cca_queue_attrs[] = { - &dev_attr_cca_mkvps.attr, - NULL, -}; - -static const struct attribute_group cca_queue_attr_grp = { - .attrs = cca_queue_attrs, -}; - -/* - * Large random number detection function. Its sends a message to a CEX2C/CEX3C - * card to find out if large random numbers are supported. - * @ap_dev: pointer to the AP device. - * - * Returns 1 if large random numbers are supported, 0 if not and < 0 on error. - */ -static int zcrypt_cex2c_rng_supported(struct ap_queue *aq) -{ - struct ap_message ap_msg; - unsigned long psmid; - unsigned int domain; - struct { - struct type86_hdr hdr; - struct type86_fmt2_ext fmt2; - struct CPRBX cprbx; - } __packed *reply; - struct { - struct type6_hdr hdr; - struct CPRBX cprbx; - char function_code[2]; - short int rule_length; - char rule[8]; - short int verb_length; - short int key_length; - } __packed *msg; - int rc, i; - - ap_init_message(&ap_msg); - ap_msg.msg = (void *)get_zeroed_page(GFP_KERNEL); - if (!ap_msg.msg) - return -ENOMEM; - ap_msg.bufsize = PAGE_SIZE; - - rng_type6cprb_msgx(&ap_msg, 4, &domain); - - msg = ap_msg.msg; - msg->cprbx.domain = AP_QID_QUEUE(aq->qid); - - rc = ap_send(aq->qid, 0x0102030405060708UL, ap_msg.msg, ap_msg.len); - if (rc) - goto out_free; - - /* Wait for the test message to complete. */ - for (i = 0; i < 2 * HZ; i++) { - msleep(1000 / HZ); - rc = ap_recv(aq->qid, &psmid, ap_msg.msg, ap_msg.bufsize); - if (rc == 0 && psmid == 0x0102030405060708UL) - break; - } - - if (i >= 2 * HZ) { - /* Got no answer. */ - rc = -ENODEV; - goto out_free; - } - - reply = ap_msg.msg; - if (reply->cprbx.ccp_rtcode == 0 && reply->cprbx.ccp_rscode == 0) - rc = 1; - else - rc = 0; -out_free: - free_page((unsigned long)ap_msg.msg); - return rc; -} - -/* - * Probe function for CEX2C/CEX3C card devices. It always accepts the - * AP device since the bus_match already checked the hardware type. - * @ap_dev: pointer to the AP card device. - */ -static int zcrypt_cex2c_card_probe(struct ap_device *ap_dev) -{ - /* - * Normalized speed ratings per crypto adapter - * MEX_1k, MEX_2k, MEX_4k, CRT_1k, CRT_2k, CRT_4k, RNG, SECKEY - */ - static const int CEX2C_SPEED_IDX[] = { - 1000, 1400, 2400, 1100, 1500, 2600, 100, 12}; - static const int CEX3C_SPEED_IDX[] = { - 500, 700, 1400, 550, 800, 1500, 80, 10}; - - struct ap_card *ac = to_ap_card(&ap_dev->device); - struct zcrypt_card *zc; - int rc = 0; - - zc = zcrypt_card_alloc(); - if (!zc) - return -ENOMEM; - zc->card = ac; - dev_set_drvdata(&ap_dev->device, zc); - switch (ac->ap_dev.device_type) { - case AP_DEVICE_TYPE_CEX2C: - zc->user_space_type = ZCRYPT_CEX2C; - zc->type_string = "CEX2C"; - zc->speed_rating = CEX2C_SPEED_IDX; - zc->min_mod_size = CEX2C_MIN_MOD_SIZE; - zc->max_mod_size = CEX2C_MAX_MOD_SIZE; - zc->max_exp_bit_length = CEX2C_MAX_MOD_SIZE; - break; - case AP_DEVICE_TYPE_CEX3C: - zc->user_space_type = ZCRYPT_CEX3C; - zc->type_string = "CEX3C"; - zc->speed_rating = CEX3C_SPEED_IDX; - zc->min_mod_size = CEX3C_MIN_MOD_SIZE; - zc->max_mod_size = CEX3C_MAX_MOD_SIZE; - zc->max_exp_bit_length = CEX3C_MAX_MOD_SIZE; - break; - default: - zcrypt_card_free(zc); - return -ENODEV; - } - zc->online = 1; - - rc = zcrypt_card_register(zc); - if (rc) { - zcrypt_card_free(zc); - return rc; - } - - if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) { - rc = sysfs_create_group(&ap_dev->device.kobj, - &cca_card_attr_grp); - if (rc) { - zcrypt_card_unregister(zc); - zcrypt_card_free(zc); - } - } - - return rc; -} - -/* - * This is called to remove the CEX2C/CEX3C card driver information - * if an AP card device is removed. - */ -static void zcrypt_cex2c_card_remove(struct ap_device *ap_dev) -{ - struct zcrypt_card *zc = dev_get_drvdata(&ap_dev->device); - struct ap_card *ac = to_ap_card(&ap_dev->device); - - if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) - sysfs_remove_group(&ap_dev->device.kobj, &cca_card_attr_grp); - - zcrypt_card_unregister(zc); -} - -static struct ap_driver zcrypt_cex2c_card_driver = { - .probe = zcrypt_cex2c_card_probe, - .remove = zcrypt_cex2c_card_remove, - .ids = zcrypt_cex2c_card_ids, - .flags = AP_DRIVER_FLAG_DEFAULT, -}; - -/* - * Probe function for CEX2C/CEX3C queue devices. It always accepts the - * AP device since the bus_match already checked the hardware type. - * @ap_dev: pointer to the AP card device. - */ -static int zcrypt_cex2c_queue_probe(struct ap_device *ap_dev) -{ - struct ap_queue *aq = to_ap_queue(&ap_dev->device); - struct zcrypt_queue *zq; - int rc; - - zq = zcrypt_queue_alloc(CEX2C_MAX_XCRB_MESSAGE_SIZE); - if (!zq) - return -ENOMEM; - zq->queue = aq; - zq->online = 1; - atomic_set(&zq->load, 0); - ap_rapq(aq->qid, 0); - rc = zcrypt_cex2c_rng_supported(aq); - if (rc < 0) { - zcrypt_queue_free(zq); - return rc; - } - if (rc) - zq->ops = zcrypt_msgtype(MSGTYPE06_NAME, - MSGTYPE06_VARIANT_DEFAULT); - else - zq->ops = zcrypt_msgtype(MSGTYPE06_NAME, - MSGTYPE06_VARIANT_NORNG); - ap_queue_init_state(aq); - ap_queue_init_reply(aq, &zq->reply); - aq->request_timeout = CEX2C_CLEANUP_TIME; - dev_set_drvdata(&ap_dev->device, zq); - rc = zcrypt_queue_register(zq); - if (rc) { - zcrypt_queue_free(zq); - return rc; - } - - if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) { - rc = sysfs_create_group(&ap_dev->device.kobj, - &cca_queue_attr_grp); - if (rc) { - zcrypt_queue_unregister(zq); - zcrypt_queue_free(zq); - } - } - - return rc; -} - -/* - * This is called to remove the CEX2C/CEX3C queue driver information - * if an AP queue device is removed. - */ -static void zcrypt_cex2c_queue_remove(struct ap_device *ap_dev) -{ - struct zcrypt_queue *zq = dev_get_drvdata(&ap_dev->device); - struct ap_queue *aq = to_ap_queue(&ap_dev->device); - - if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) - sysfs_remove_group(&ap_dev->device.kobj, &cca_queue_attr_grp); - - zcrypt_queue_unregister(zq); -} - -static struct ap_driver zcrypt_cex2c_queue_driver = { - .probe = zcrypt_cex2c_queue_probe, - .remove = zcrypt_cex2c_queue_remove, - .ids = zcrypt_cex2c_queue_ids, - .flags = AP_DRIVER_FLAG_DEFAULT, -}; - -int __init zcrypt_cex2c_init(void) -{ - int rc; - - rc = ap_driver_register(&zcrypt_cex2c_card_driver, - THIS_MODULE, "cex2card"); - if (rc) - return rc; - - rc = ap_driver_register(&zcrypt_cex2c_queue_driver, - THIS_MODULE, "cex2cqueue"); - if (rc) - ap_driver_unregister(&zcrypt_cex2c_card_driver); - - return rc; -} - -void zcrypt_cex2c_exit(void) -{ - ap_driver_unregister(&zcrypt_cex2c_queue_driver); - ap_driver_unregister(&zcrypt_cex2c_card_driver); -} - -module_init(zcrypt_cex2c_init); -module_exit(zcrypt_cex2c_exit); diff --git a/drivers/s390/crypto/zcrypt_cex2c.h b/drivers/s390/crypto/zcrypt_cex2c.h index 6ec405c2bec2..e69de29bb2d1 100644 --- a/drivers/s390/crypto/zcrypt_cex2c.h +++ b/drivers/s390/crypto/zcrypt_cex2c.h @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright IBM Corp. 2001, 2018 - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> - * MSGTYPE restruct: Holger Dengler <hd@linux.vnet.ibm.com> - */ - -#ifndef _ZCRYPT_CEX2C_H_ -#define _ZCRYPT_CEX2C_H_ - -int zcrypt_cex2c_init(void); -void zcrypt_cex2c_exit(void); - -#endif /* _ZCRYPT_CEX2C_H_ */ diff --git a/drivers/s390/crypto/zcrypt_ep11misc.c b/drivers/s390/crypto/zcrypt_ep11misc.c index 958f5ee47f1b..0a877f9792c2 100644 --- a/drivers/s390/crypto/zcrypt_ep11misc.c +++ b/drivers/s390/crypto/zcrypt_ep11misc.c @@ -29,6 +29,8 @@ #define DEBUG_WARN(...) ZCRYPT_DBF(DBF_WARN, ##__VA_ARGS__) #define DEBUG_ERR(...) ZCRYPT_DBF(DBF_ERR, ##__VA_ARGS__) +#define EP11_PINBLOB_V1_BYTES 56 + /* default iv used here */ static const u8 def_iv[16] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }; @@ -113,6 +115,109 @@ static void __exit card_cache_free(void) spin_unlock_bh(&card_list_lock); } +static int ep11_kb_split(const u8 *kb, size_t kblen, u32 kbver, + struct ep11kblob_header **kbhdr, size_t *kbhdrsize, + u8 **kbpl, size_t *kbplsize) +{ + struct ep11kblob_header *hdr = NULL; + size_t hdrsize, plsize = 0; + int rc = -EINVAL; + u8 *pl = NULL; + + if (kblen < sizeof(struct ep11kblob_header)) + goto out; + hdr = (struct ep11kblob_header *)kb; + + switch (kbver) { + case TOKVER_EP11_AES: + /* header overlays the payload */ + hdrsize = 0; + break; + case TOKVER_EP11_ECC_WITH_HEADER: + case TOKVER_EP11_AES_WITH_HEADER: + /* payload starts after the header */ + hdrsize = sizeof(struct ep11kblob_header); + break; + default: + goto out; + } + + plsize = kblen - hdrsize; + pl = (u8 *)kb + hdrsize; + + if (kbhdr) + *kbhdr = hdr; + if (kbhdrsize) + *kbhdrsize = hdrsize; + if (kbpl) + *kbpl = pl; + if (kbplsize) + *kbplsize = plsize; + + rc = 0; +out: + return rc; +} + +static int ep11_kb_decode(const u8 *kb, size_t kblen, + struct ep11kblob_header **kbhdr, size_t *kbhdrsize, + struct ep11keyblob **kbpl, size_t *kbplsize) +{ + struct ep11kblob_header *tmph, *hdr = NULL; + size_t hdrsize = 0, plsize = 0; + struct ep11keyblob *pl = NULL; + int rc = -EINVAL; + u8 *tmpp; + + if (kblen < sizeof(struct ep11kblob_header)) + goto out; + tmph = (struct ep11kblob_header *)kb; + + if (tmph->type != TOKTYPE_NON_CCA && + tmph->len > kblen) + goto out; + + if (ep11_kb_split(kb, kblen, tmph->version, + &hdr, &hdrsize, &tmpp, &plsize)) + goto out; + + if (plsize < sizeof(struct ep11keyblob)) + goto out; + + if (!is_ep11_keyblob(tmpp)) + goto out; + + pl = (struct ep11keyblob *)tmpp; + plsize = hdr->len - hdrsize; + + if (kbhdr) + *kbhdr = hdr; + if (kbhdrsize) + *kbhdrsize = hdrsize; + if (kbpl) + *kbpl = pl; + if (kbplsize) + *kbplsize = plsize; + + rc = 0; +out: + return rc; +} + +/* + * For valid ep11 keyblobs, returns a reference to the wrappingkey verification + * pattern. Otherwise NULL. + */ +const u8 *ep11_kb_wkvp(const u8 *keyblob, size_t keybloblen) +{ + struct ep11keyblob *kb; + + if (ep11_kb_decode(keyblob, keybloblen, NULL, NULL, &kb, NULL)) + return NULL; + return kb->wkvp; +} +EXPORT_SYMBOL(ep11_kb_wkvp); + /* * Simple check if the key blob is a valid EP11 AES key blob with header. */ @@ -489,7 +594,7 @@ static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type, struct ep11_cprb *req = NULL, *rep = NULL; struct ep11_target_dev target; struct ep11_urb *urb = NULL; - int api = 1, rc = -ENOMEM; + int api = EP11_API_V1, rc = -ENOMEM; /* request cprb and payload */ req = alloc_cprb(sizeof(struct ep11_info_req_pl)); @@ -664,8 +769,9 @@ EXPORT_SYMBOL(ep11_get_domain_info); */ #define KEY_ATTR_DEFAULTS 0x00200c00 -int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags, - u8 *keybuf, size_t *keybufsize) +static int _ep11_genaeskey(u16 card, u16 domain, + u32 keybitsize, u32 keygenflags, + u8 *keybuf, size_t *keybufsize) { struct keygen_req_pl { struct pl_head head; @@ -685,8 +791,7 @@ int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags, u32 attr_bool_bits; u32 attr_val_len_type; u32 attr_val_len_value; - u8 pin_tag; - u8 pin_len; + /* followed by empty pin tag or empty pinblob tag */ } __packed * req_pl; struct keygen_rep_pl { struct pl_head head; @@ -699,10 +804,11 @@ int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags, u8 data[512]; } __packed * rep_pl; struct ep11_cprb *req = NULL, *rep = NULL; + size_t req_pl_size, pinblob_size = 0; struct ep11_target_dev target; struct ep11_urb *urb = NULL; - struct ep11keyblob *kb; int api, rc = -ENOMEM; + u8 *p; switch (keybitsize) { case 128: @@ -718,12 +824,22 @@ int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags, } /* request cprb and payload */ - req = alloc_cprb(sizeof(struct keygen_req_pl)); + api = (!keygenflags || keygenflags & 0x00200000) ? + EP11_API_V4 : EP11_API_V1; + if (ap_is_se_guest()) { + /* + * genkey within SE environment requires API ordinal 6 + * with empty pinblob + */ + api = EP11_API_V6; + pinblob_size = EP11_PINBLOB_V1_BYTES; + } + req_pl_size = sizeof(struct keygen_req_pl) + ASN1TAGLEN(pinblob_size); + req = alloc_cprb(req_pl_size); if (!req) goto out; req_pl = (struct keygen_req_pl *)(((u8 *)req) + sizeof(*req)); - api = (!keygenflags || keygenflags & 0x00200000) ? 4 : 1; - prep_head(&req_pl->head, sizeof(*req_pl), api, 21); /* GenerateKey */ + prep_head(&req_pl->head, req_pl_size, api, 21); /* GenerateKey */ req_pl->var_tag = 0x04; req_pl->var_len = sizeof(u32); req_pl->keybytes_tag = 0x04; @@ -739,7 +855,10 @@ int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags, req_pl->attr_bool_bits = keygenflags ? keygenflags : KEY_ATTR_DEFAULTS; req_pl->attr_val_len_type = 0x00000161; /* CKA_VALUE_LEN */ req_pl->attr_val_len_value = keybitsize / 8; - req_pl->pin_tag = 0x04; + p = ((u8 *)req_pl) + sizeof(*req_pl); + /* pin tag */ + *p++ = 0x04; + *p++ = pinblob_size; /* reply cprb and payload */ rep = alloc_cprb(sizeof(struct keygen_rep_pl)); @@ -754,7 +873,7 @@ int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags, target.ap_id = card; target.dom_id = domain; prep_urb(urb, &target, 1, - req, sizeof(*req) + sizeof(*req_pl), + req, sizeof(*req) + req_pl_size, rep, sizeof(*rep) + sizeof(*rep_pl)); rc = zcrypt_send_ep11_cprb(urb); @@ -780,14 +899,9 @@ int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags, goto out; } - /* copy key blob and set header values */ + /* copy key blob */ memcpy(keybuf, rep_pl->data, rep_pl->data_len); *keybufsize = rep_pl->data_len; - kb = (struct ep11keyblob *)keybuf; - kb->head.type = TOKTYPE_NON_CCA; - kb->head.len = rep_pl->data_len; - kb->head.version = TOKVER_EP11_AES; - kb->head.keybitlen = keybitsize; out: kfree(req); @@ -795,6 +909,43 @@ out: kfree(urb); return rc; } + +int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags, + u8 *keybuf, size_t *keybufsize, u32 keybufver) +{ + struct ep11kblob_header *hdr; + size_t hdr_size, pl_size; + u8 *pl; + int rc; + + switch (keybufver) { + case TOKVER_EP11_AES: + case TOKVER_EP11_AES_WITH_HEADER: + break; + default: + return -EINVAL; + } + + rc = ep11_kb_split(keybuf, *keybufsize, keybufver, + &hdr, &hdr_size, &pl, &pl_size); + if (rc) + return rc; + + rc = _ep11_genaeskey(card, domain, keybitsize, keygenflags, + pl, &pl_size); + if (rc) + return rc; + + *keybufsize = hdr_size + pl_size; + + /* update header information */ + hdr->type = TOKTYPE_NON_CCA; + hdr->len = *keybufsize; + hdr->version = keybufver; + hdr->bitlen = keybitsize; + + return 0; +} EXPORT_SYMBOL(ep11_genaeskey); static int ep11_cryptsingle(u16 card, u16 domain, @@ -830,7 +981,7 @@ static int ep11_cryptsingle(u16 card, u16 domain, struct ep11_target_dev target; struct ep11_urb *urb = NULL; size_t req_pl_size, rep_pl_size; - int n, api = 1, rc = -ENOMEM; + int n, api = EP11_API_V1, rc = -ENOMEM; u8 *p; /* the simple asn1 coding used has length limits */ @@ -924,12 +1075,12 @@ out: return rc; } -static int ep11_unwrapkey(u16 card, u16 domain, - const u8 *kek, size_t keksize, - const u8 *enckey, size_t enckeysize, - u32 mech, const u8 *iv, - u32 keybitsize, u32 keygenflags, - u8 *keybuf, size_t *keybufsize) +static int _ep11_unwrapkey(u16 card, u16 domain, + const u8 *kek, size_t keksize, + const u8 *enckey, size_t enckeysize, + u32 mech, const u8 *iv, + u32 keybitsize, u32 keygenflags, + u8 *keybuf, size_t *keybufsize) { struct uw_req_pl { struct pl_head head; @@ -949,7 +1100,7 @@ static int ep11_unwrapkey(u16 card, u16 domain, * maybe followed by iv data * followed by kek tag + kek blob * followed by empty mac tag - * followed by empty pin tag + * followed by empty pin tag or empty pinblob tag * followed by encryted key tag + bytes */ } __packed * req_pl; @@ -964,21 +1115,30 @@ static int ep11_unwrapkey(u16 card, u16 domain, u8 data[512]; } __packed * rep_pl; struct ep11_cprb *req = NULL, *rep = NULL; + size_t req_pl_size, pinblob_size = 0; struct ep11_target_dev target; struct ep11_urb *urb = NULL; - struct ep11keyblob *kb; - size_t req_pl_size; int api, rc = -ENOMEM; u8 *p; /* request cprb and payload */ + api = (!keygenflags || keygenflags & 0x00200000) ? + EP11_API_V4 : EP11_API_V1; + if (ap_is_se_guest()) { + /* + * unwrap within SE environment requires API ordinal 6 + * with empty pinblob + */ + api = EP11_API_V6; + pinblob_size = EP11_PINBLOB_V1_BYTES; + } req_pl_size = sizeof(struct uw_req_pl) + (iv ? 16 : 0) - + ASN1TAGLEN(keksize) + 4 + ASN1TAGLEN(enckeysize); + + ASN1TAGLEN(keksize) + ASN1TAGLEN(0) + + ASN1TAGLEN(pinblob_size) + ASN1TAGLEN(enckeysize); req = alloc_cprb(req_pl_size); if (!req) goto out; req_pl = (struct uw_req_pl *)(((u8 *)req) + sizeof(*req)); - api = (!keygenflags || keygenflags & 0x00200000) ? 4 : 1; prep_head(&req_pl->head, req_pl_size, api, 34); /* UnwrapKey */ req_pl->attr_tag = 0x04; req_pl->attr_len = 7 * sizeof(u32); @@ -1003,9 +1163,10 @@ static int ep11_unwrapkey(u16 card, u16 domain, /* empty mac key tag */ *p++ = 0x04; *p++ = 0; - /* empty pin tag */ + /* pin tag */ *p++ = 0x04; - *p++ = 0; + *p++ = pinblob_size; + p += pinblob_size; /* encrypted key value tag and bytes */ p += asn1tag_write(p, 0x04, enckey, enckeysize); @@ -1048,14 +1209,9 @@ static int ep11_unwrapkey(u16 card, u16 domain, goto out; } - /* copy key blob and set header values */ + /* copy key blob */ memcpy(keybuf, rep_pl->data, rep_pl->data_len); *keybufsize = rep_pl->data_len; - kb = (struct ep11keyblob *)keybuf; - kb->head.type = TOKTYPE_NON_CCA; - kb->head.len = rep_pl->data_len; - kb->head.version = TOKVER_EP11_AES; - kb->head.keybitlen = keybitsize; out: kfree(req); @@ -1064,10 +1220,46 @@ out: return rc; } -static int ep11_wrapkey(u16 card, u16 domain, - const u8 *key, size_t keysize, - u32 mech, const u8 *iv, - u8 *databuf, size_t *datasize) +static int ep11_unwrapkey(u16 card, u16 domain, + const u8 *kek, size_t keksize, + const u8 *enckey, size_t enckeysize, + u32 mech, const u8 *iv, + u32 keybitsize, u32 keygenflags, + u8 *keybuf, size_t *keybufsize, + u8 keybufver) +{ + struct ep11kblob_header *hdr; + size_t hdr_size, pl_size; + u8 *pl; + int rc; + + rc = ep11_kb_split(keybuf, *keybufsize, keybufver, + &hdr, &hdr_size, &pl, &pl_size); + if (rc) + return rc; + + rc = _ep11_unwrapkey(card, domain, kek, keksize, enckey, enckeysize, + mech, iv, keybitsize, keygenflags, + pl, &pl_size); + if (rc) + return rc; + + *keybufsize = hdr_size + pl_size; + + /* update header information */ + hdr = (struct ep11kblob_header *)keybuf; + hdr->type = TOKTYPE_NON_CCA; + hdr->len = *keybufsize; + hdr->version = keybufver; + hdr->bitlen = keybitsize; + + return 0; +} + +static int _ep11_wrapkey(u16 card, u16 domain, + const u8 *key, size_t keysize, + u32 mech, const u8 *iv, + u8 *databuf, size_t *datasize) { struct wk_req_pl { struct pl_head head; @@ -1097,20 +1289,10 @@ static int ep11_wrapkey(u16 card, u16 domain, struct ep11_cprb *req = NULL, *rep = NULL; struct ep11_target_dev target; struct ep11_urb *urb = NULL; - struct ep11keyblob *kb; size_t req_pl_size; int api, rc = -ENOMEM; - bool has_header = false; u8 *p; - /* maybe the session field holds a header with key info */ - kb = (struct ep11keyblob *)key; - if (kb->head.type == TOKTYPE_NON_CCA && - kb->head.version == TOKVER_EP11_AES) { - has_header = true; - keysize = min_t(size_t, kb->head.len, keysize); - } - /* request cprb and payload */ req_pl_size = sizeof(struct wk_req_pl) + (iv ? 16 : 0) + ASN1TAGLEN(keysize) + 4; @@ -1120,7 +1302,8 @@ static int ep11_wrapkey(u16 card, u16 domain, if (!mech || mech == 0x80060001) req->flags |= 0x20; /* CPACF_WRAP needs special bit */ req_pl = (struct wk_req_pl *)(((u8 *)req) + sizeof(*req)); - api = (!mech || mech == 0x80060001) ? 4 : 1; /* CKM_IBM_CPACF_WRAP */ + api = (!mech || mech == 0x80060001) ? /* CKM_IBM_CPACF_WRAP */ + EP11_API_V4 : EP11_API_V1; prep_head(&req_pl->head, req_pl_size, api, 33); /* WrapKey */ req_pl->var_tag = 0x04; req_pl->var_len = sizeof(u32); @@ -1135,11 +1318,6 @@ static int ep11_wrapkey(u16 card, u16 domain, } /* key blob */ p += asn1tag_write(p, 0x04, key, keysize); - /* maybe the key argument needs the head data cleaned out */ - if (has_header) { - kb = (struct ep11keyblob *)(p - keysize); - memset(&kb->head, 0, sizeof(kb->head)); - } /* empty kek tag */ *p++ = 0x04; *p++ = 0; @@ -1198,10 +1376,10 @@ out: } int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags, - const u8 *clrkey, u8 *keybuf, size_t *keybufsize) + const u8 *clrkey, u8 *keybuf, size_t *keybufsize, + u32 keytype) { int rc; - struct ep11keyblob *kb; u8 encbuf[64], *kek = NULL; size_t clrkeylen, keklen, encbuflen = sizeof(encbuf); @@ -1223,17 +1401,15 @@ int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags, } /* Step 1: generate AES 256 bit random kek key */ - rc = ep11_genaeskey(card, domain, 256, - 0x00006c00, /* EN/DECRYPT, WRAP/UNWRAP */ - kek, &keklen); + rc = _ep11_genaeskey(card, domain, 256, + 0x00006c00, /* EN/DECRYPT, WRAP/UNWRAP */ + kek, &keklen); if (rc) { DEBUG_ERR( "%s generate kek key failed, rc=%d\n", __func__, rc); goto out; } - kb = (struct ep11keyblob *)kek; - memset(&kb->head, 0, sizeof(kb->head)); /* Step 2: encrypt clear key value with the kek key */ rc = ep11_cryptsingle(card, domain, 0, 0, def_iv, kek, keklen, @@ -1248,7 +1424,7 @@ int ep11_clr2keyblob(u16 card, u16 domain, u32 keybitsize, u32 keygenflags, /* Step 3: import the encrypted key value as a new key */ rc = ep11_unwrapkey(card, domain, kek, keklen, encbuf, encbuflen, 0, def_iv, - keybitsize, 0, keybuf, keybufsize); + keybitsize, 0, keybuf, keybufsize, keytype); if (rc) { DEBUG_ERR( "%s importing key value as new key failed,, rc=%d\n", @@ -1262,11 +1438,12 @@ out: } EXPORT_SYMBOL(ep11_clr2keyblob); -int ep11_kblob2protkey(u16 card, u16 dom, const u8 *keyblob, size_t keybloblen, +int ep11_kblob2protkey(u16 card, u16 dom, + const u8 *keyblob, size_t keybloblen, u8 *protkey, u32 *protkeylen, u32 *protkeytype) { - int rc = -EIO; - u8 *wkbuf = NULL; + struct ep11kblob_header *hdr; + struct ep11keyblob *key; size_t wkbuflen, keylen; struct wk_info { u16 version; @@ -1277,31 +1454,17 @@ int ep11_kblob2protkey(u16 card, u16 dom, const u8 *keyblob, size_t keybloblen, u8 res2[8]; u8 pkey[]; } __packed * wki; - const u8 *key; - struct ep11kblob_header *hdr; + u8 *wkbuf = NULL; + int rc = -EIO; - /* key with or without header ? */ - hdr = (struct ep11kblob_header *)keyblob; - if (hdr->type == TOKTYPE_NON_CCA && - (hdr->version == TOKVER_EP11_AES_WITH_HEADER || - hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && - is_ep11_keyblob(keyblob + sizeof(struct ep11kblob_header))) { - /* EP11 AES or ECC key with header */ - key = keyblob + sizeof(struct ep11kblob_header); - keylen = hdr->len - sizeof(struct ep11kblob_header); - } else if (hdr->type == TOKTYPE_NON_CCA && - hdr->version == TOKVER_EP11_AES && - is_ep11_keyblob(keyblob)) { - /* EP11 AES key (old style) */ - key = keyblob; - keylen = hdr->len; - } else if (is_ep11_keyblob(keyblob)) { - /* raw EP11 key blob */ - key = keyblob; - keylen = keybloblen; - } else { + if (ep11_kb_decode((u8 *)keyblob, keybloblen, &hdr, NULL, &key, &keylen)) return -EINVAL; + + if (hdr->version == TOKVER_EP11_AES) { + /* wipe overlayed header */ + memset(hdr, 0, sizeof(*hdr)); } + /* !!! hdr is no longer a valid header !!! */ /* alloc temp working buffer */ wkbuflen = (keylen + AES_BLOCK_SIZE) & (~(AES_BLOCK_SIZE - 1)); @@ -1310,8 +1473,8 @@ int ep11_kblob2protkey(u16 card, u16 dom, const u8 *keyblob, size_t keybloblen, return -ENOMEM; /* ep11 secure key -> protected key + info */ - rc = ep11_wrapkey(card, dom, key, keylen, - 0, def_iv, wkbuf, &wkbuflen); + rc = _ep11_wrapkey(card, dom, (u8 *)key, keylen, + 0, def_iv, wkbuf, &wkbuflen); if (rc) { DEBUG_ERR( "%s rewrapping ep11 key to pkey failed, rc=%d\n", diff --git a/drivers/s390/crypto/zcrypt_ep11misc.h b/drivers/s390/crypto/zcrypt_ep11misc.h index a3eddf51242d..9d17fd5228a7 100644 --- a/drivers/s390/crypto/zcrypt_ep11misc.h +++ b/drivers/s390/crypto/zcrypt_ep11misc.h @@ -12,7 +12,9 @@ #include <asm/zcrypt.h> #include <asm/pkey.h> -#define EP11_API_V 4 /* highest known and supported EP11 API version */ +#define EP11_API_V1 1 /* min EP11 API, default if no higher api required */ +#define EP11_API_V4 4 /* supported EP11 API for the ep11misc cprbs */ +#define EP11_API_V6 6 /* min EP11 API for some cprbs in SE environment */ #define EP11_STRUCT_MAGIC 0x1234 #define EP11_BLOB_PKEY_EXTRACTABLE 0x00200000 @@ -29,14 +31,7 @@ struct ep11keyblob { union { u8 session[32]; /* only used for PKEY_TYPE_EP11: */ - struct { - u8 type; /* 0x00 (TOKTYPE_NON_CCA) */ - u8 res0; /* unused */ - u16 len; /* total length in bytes of this blob */ - u8 version; /* 0x03 (TOKVER_EP11_AES) */ - u8 res1; /* unused */ - u16 keybitlen; /* clear key bit len, 0 for unknown */ - } head; + struct ep11kblob_header head; }; u8 wkvp[16]; /* wrapping key verification pattern */ u64 attr; /* boolean key attributes */ @@ -56,6 +51,12 @@ static inline bool is_ep11_keyblob(const u8 *key) } /* + * For valid ep11 keyblobs, returns a reference to the wrappingkey verification + * pattern. Otherwise NULL. + */ +const u8 *ep11_kb_wkvp(const u8 *kblob, size_t kbloblen); + +/* * Simple check if the key blob is a valid EP11 AES key blob with header. * If checkcpacfexport is enabled, the key is also checked for the * attributes needed to export this key for CPACF use. @@ -114,13 +115,14 @@ int ep11_get_domain_info(u16 card, u16 domain, struct ep11_domain_info *info); * Generate (random) EP11 AES secure key. */ int ep11_genaeskey(u16 card, u16 domain, u32 keybitsize, u32 keygenflags, - u8 *keybuf, size_t *keybufsize); + u8 *keybuf, size_t *keybufsize, u32 keybufver); /* * Generate EP11 AES secure key with given clear key value. */ int ep11_clr2keyblob(u16 cardnr, u16 domain, u32 keybitsize, u32 keygenflags, - const u8 *clrkey, u8 *keybuf, size_t *keybufsize); + const u8 *clrkey, u8 *keybuf, size_t *keybufsize, + u32 keytype); /* * Build a list of ep11 apqns meeting the following constrains: diff --git a/drivers/s390/crypto/zcrypt_msgtype50.c b/drivers/s390/crypto/zcrypt_msgtype50.c index 51f8f7a463f7..2e155de8abe5 100644 --- a/drivers/s390/crypto/zcrypt_msgtype50.c +++ b/drivers/s390/crypto/zcrypt_msgtype50.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright IBM Corp. 2001, 2012 + * Copyright IBM Corp. 2001, 2023 * Author(s): Robert Burroughs * Eric Rossman (edrossma@us.ibm.com) * @@ -28,15 +28,12 @@ /* >= CEX3A: 4096 bits */ #define CEX3A_MAX_MOD_SIZE 512 -/* CEX2A: max outputdatalength + type80_hdr */ -#define CEX2A_MAX_RESPONSE_SIZE 0x110 - /* >= CEX3A: 512 bit modulus, (max outputdatalength) + type80_hdr */ #define CEX3A_MAX_RESPONSE_SIZE 0x210 MODULE_AUTHOR("IBM Corporation"); MODULE_DESCRIPTION("Cryptographic Accelerator (message type 50), " \ - "Copyright IBM Corp. 2001, 2012"); + "Copyright IBM Corp. 2001, 2023"); MODULE_LICENSE("GPL"); /* @@ -366,20 +363,17 @@ static int convert_type80(struct zcrypt_queue *zq, ap_send_online_uevent(&zq->queue->ap_dev, zq->online); return -EAGAIN; } - if (zq->zcard->user_space_type == ZCRYPT_CEX2A) - BUG_ON(t80h->len > CEX2A_MAX_RESPONSE_SIZE); - else - BUG_ON(t80h->len > CEX3A_MAX_RESPONSE_SIZE); + BUG_ON(t80h->len > CEX3A_MAX_RESPONSE_SIZE); data = reply->msg + t80h->len - outputdatalength; if (copy_to_user(outputdata, data, outputdatalength)) return -EFAULT; return 0; } -static int convert_response_cex2a(struct zcrypt_queue *zq, - struct ap_message *reply, - char __user *outputdata, - unsigned int outputdatalength) +static int convert_response(struct zcrypt_queue *zq, + struct ap_message *reply, + char __user *outputdata, + unsigned int outputdatalength) { /* Response type byte is the second byte in the response. */ unsigned char rtype = ((unsigned char *)reply->msg)[1]; @@ -414,9 +408,9 @@ static int convert_response_cex2a(struct zcrypt_queue *zq, * @msg: pointer to the AP message * @reply: pointer to the AP reply message */ -static void zcrypt_cex2a_receive(struct ap_queue *aq, - struct ap_message *msg, - struct ap_message *reply) +static void zcrypt_msgtype50_receive(struct ap_queue *aq, + struct ap_message *msg, + struct ap_message *reply) { static struct error_hdr error_reply = { .type = TYPE82_RSP_CODE, @@ -456,19 +450,18 @@ static atomic_t zcrypt_step = ATOMIC_INIT(0); * CEXxA device to the request distributor * @mex: pointer to the modexpo request buffer */ -static long zcrypt_cex2a_modexpo(struct zcrypt_queue *zq, - struct ica_rsa_modexpo *mex, - struct ap_message *ap_msg) +static long zcrypt_msgtype50_modexpo(struct zcrypt_queue *zq, + struct ica_rsa_modexpo *mex, + struct ap_message *ap_msg) { struct completion work; int rc; - ap_msg->bufsize = (zq->zcard->user_space_type == ZCRYPT_CEX2A) ? - MSGTYPE50_CRB2_MAX_MSG_SIZE : MSGTYPE50_CRB3_MAX_MSG_SIZE; + ap_msg->bufsize = MSGTYPE50_CRB3_MAX_MSG_SIZE; ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL); if (!ap_msg->msg) return -ENOMEM; - ap_msg->receive = zcrypt_cex2a_receive; + ap_msg->receive = zcrypt_msgtype50_receive; ap_msg->psmid = (((unsigned long)current->pid) << 32) + atomic_inc_return(&zcrypt_step); ap_msg->private = &work; @@ -483,9 +476,9 @@ static long zcrypt_cex2a_modexpo(struct zcrypt_queue *zq, if (rc == 0) { rc = ap_msg->rc; if (rc == 0) - rc = convert_response_cex2a(zq, ap_msg, - mex->outputdata, - mex->outputdatalength); + rc = convert_response(zq, ap_msg, + mex->outputdata, + mex->outputdatalength); } else { /* Signal pending. */ ap_cancel_message(zq->queue, ap_msg); @@ -507,19 +500,18 @@ out: * CEXxA device to the request distributor * @crt: pointer to the modexpoc_crt request buffer */ -static long zcrypt_cex2a_modexpo_crt(struct zcrypt_queue *zq, - struct ica_rsa_modexpo_crt *crt, - struct ap_message *ap_msg) +static long zcrypt_msgtype50_modexpo_crt(struct zcrypt_queue *zq, + struct ica_rsa_modexpo_crt *crt, + struct ap_message *ap_msg) { struct completion work; int rc; - ap_msg->bufsize = (zq->zcard->user_space_type == ZCRYPT_CEX2A) ? - MSGTYPE50_CRB2_MAX_MSG_SIZE : MSGTYPE50_CRB3_MAX_MSG_SIZE; + ap_msg->bufsize = MSGTYPE50_CRB3_MAX_MSG_SIZE; ap_msg->msg = kmalloc(ap_msg->bufsize, GFP_KERNEL); if (!ap_msg->msg) return -ENOMEM; - ap_msg->receive = zcrypt_cex2a_receive; + ap_msg->receive = zcrypt_msgtype50_receive; ap_msg->psmid = (((unsigned long)current->pid) << 32) + atomic_inc_return(&zcrypt_step); ap_msg->private = &work; @@ -534,9 +526,9 @@ static long zcrypt_cex2a_modexpo_crt(struct zcrypt_queue *zq, if (rc == 0) { rc = ap_msg->rc; if (rc == 0) - rc = convert_response_cex2a(zq, ap_msg, - crt->outputdata, - crt->outputdatalength); + rc = convert_response(zq, ap_msg, + crt->outputdata, + crt->outputdatalength); } else { /* Signal pending. */ ap_cancel_message(zq->queue, ap_msg); @@ -555,8 +547,8 @@ out: * The crypto operations for message type 50. */ static struct zcrypt_ops zcrypt_msgtype50_ops = { - .rsa_modexpo = zcrypt_cex2a_modexpo, - .rsa_modexpo_crt = zcrypt_cex2a_modexpo_crt, + .rsa_modexpo = zcrypt_msgtype50_modexpo, + .rsa_modexpo_crt = zcrypt_msgtype50_modexpo_crt, .owner = THIS_MODULE, .name = MSGTYPE50_NAME, .variant = MSGTYPE50_VARIANT_DEFAULT, diff --git a/drivers/s390/crypto/zcrypt_msgtype50.h b/drivers/s390/crypto/zcrypt_msgtype50.h index eb49f06bed29..323e93b90b12 100644 --- a/drivers/s390/crypto/zcrypt_msgtype50.h +++ b/drivers/s390/crypto/zcrypt_msgtype50.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Copyright IBM Corp. 2001, 2012 + * Copyright IBM Corp. 2001, 2023 * Author(s): Robert Burroughs * Eric Rossman (edrossma@us.ibm.com) * @@ -15,7 +15,6 @@ #define MSGTYPE50_NAME "zcrypt_msgtype50" #define MSGTYPE50_VARIANT_DEFAULT 0 -#define MSGTYPE50_CRB2_MAX_MSG_SIZE 0x390 /* sizeof(struct type50_crb2_msg) */ #define MSGTYPE50_CRB3_MAX_MSG_SIZE 0x710 /* sizeof(struct type50_crb3_msg) */ #define MSGTYPE_ADJUSTMENT 0x08 /* type04 extension (not needed in type50) */ diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c index e668ff5eb384..3c53abbdc342 100644 --- a/drivers/s390/crypto/zcrypt_msgtype6.c +++ b/drivers/s390/crypto/zcrypt_msgtype6.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright IBM Corp. 2001, 2022 + * Copyright IBM Corp. 2001, 2023 * Author(s): Robert Burroughs * Eric Rossman (edrossma@us.ibm.com) * @@ -42,7 +42,7 @@ struct response_type { MODULE_AUTHOR("IBM Corporation"); MODULE_DESCRIPTION("Cryptographic Coprocessor (message type 6), " \ - "Copyright IBM Corp. 2001, 2012"); + "Copyright IBM Corp. 2001, 2023"); MODULE_LICENSE("GPL"); struct function_and_rules_block { @@ -1348,14 +1348,6 @@ out: /* * The crypto operations for a CEXxC card. */ -static struct zcrypt_ops zcrypt_msgtype6_norng_ops = { - .owner = THIS_MODULE, - .name = MSGTYPE06_NAME, - .variant = MSGTYPE06_VARIANT_NORNG, - .rsa_modexpo = zcrypt_msgtype6_modexpo, - .rsa_modexpo_crt = zcrypt_msgtype6_modexpo_crt, - .send_cprb = zcrypt_msgtype6_send_cprb, -}; static struct zcrypt_ops zcrypt_msgtype6_ops = { .owner = THIS_MODULE, @@ -1378,14 +1370,12 @@ static struct zcrypt_ops zcrypt_msgtype6_ep11_ops = { void __init zcrypt_msgtype6_init(void) { - zcrypt_msgtype_register(&zcrypt_msgtype6_norng_ops); zcrypt_msgtype_register(&zcrypt_msgtype6_ops); zcrypt_msgtype_register(&zcrypt_msgtype6_ep11_ops); } void __exit zcrypt_msgtype6_exit(void) { - zcrypt_msgtype_unregister(&zcrypt_msgtype6_norng_ops); zcrypt_msgtype_unregister(&zcrypt_msgtype6_ops); zcrypt_msgtype_unregister(&zcrypt_msgtype6_ep11_ops); } diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c index 711252e52d8e..95a86e0dfd77 100644 --- a/drivers/scsi/raid_class.c +++ b/drivers/scsi/raid_class.c @@ -209,54 +209,6 @@ raid_attr_ro_state(level); raid_attr_ro_fn(resync); raid_attr_ro_state_fn(state); -static void raid_component_release(struct device *dev) -{ - struct raid_component *rc = - container_of(dev, struct raid_component, dev); - dev_printk(KERN_ERR, rc->dev.parent, "COMPONENT RELEASE\n"); - put_device(rc->dev.parent); - kfree(rc); -} - -int raid_component_add(struct raid_template *r,struct device *raid_dev, - struct device *component_dev) -{ - struct device *cdev = - attribute_container_find_class_device(&r->raid_attrs.ac, - raid_dev); - struct raid_component *rc; - struct raid_data *rd = dev_get_drvdata(cdev); - int err; - - rc = kzalloc(sizeof(*rc), GFP_KERNEL); - if (!rc) - return -ENOMEM; - - INIT_LIST_HEAD(&rc->node); - device_initialize(&rc->dev); - rc->dev.release = raid_component_release; - rc->dev.parent = get_device(component_dev); - rc->num = rd->component_count++; - - dev_set_name(&rc->dev, "component-%d", rc->num); - list_add_tail(&rc->node, &rd->component_list); - rc->dev.class = &raid_class.class; - err = device_add(&rc->dev); - if (err) - goto err_out; - - return 0; - -err_out: - put_device(&rc->dev); - list_del(&rc->node); - rd->component_count--; - put_device(component_dev); - kfree(rc); - return err; -} -EXPORT_SYMBOL(raid_component_add); - struct raid_template * raid_class_attach(struct raid_function_template *ft) { diff --git a/drivers/scsi/snic/snic_disc.c b/drivers/scsi/snic/snic_disc.c index e429ad23c396..4db3ba62fcd3 100644 --- a/drivers/scsi/snic/snic_disc.c +++ b/drivers/scsi/snic/snic_disc.c @@ -303,12 +303,11 @@ snic_tgt_create(struct snic *snic, struct snic_tgt_id *tgtid) "Snic Tgt: device_add, with err = %d\n", ret); - put_device(&tgt->dev); put_device(&snic->shost->shost_gendev); spin_lock_irqsave(snic->shost->host_lock, flags); list_del(&tgt->list); spin_unlock_irqrestore(snic->shost->host_lock, flags); - kfree(tgt); + put_device(&tgt->dev); tgt = NULL; return tgt; diff --git a/drivers/soc/fsl/qe/qe.c b/drivers/soc/fsl/qe/qe.c index b3c226eb5292..58746e570d14 100644 --- a/drivers/soc/fsl/qe/qe.c +++ b/drivers/soc/fsl/qe/qe.c @@ -524,7 +524,7 @@ int qe_upload_firmware(const struct qe_firmware *firmware) * saved microcode information and put in the new. */ memset(&qe_firmware_info, 0, sizeof(qe_firmware_info)); - strlcpy(qe_firmware_info.id, firmware->id, sizeof(qe_firmware_info.id)); + strscpy(qe_firmware_info.id, firmware->id, sizeof(qe_firmware_info.id)); qe_firmware_info.extended_modes = be64_to_cpu(firmware->extended_modes); memcpy(qe_firmware_info.vtraps, firmware->vtraps, sizeof(firmware->vtraps)); @@ -599,7 +599,7 @@ struct qe_firmware_info *qe_get_firmware_info(void) /* Copy the data into qe_firmware_info*/ sprop = of_get_property(fw, "id", NULL); if (sprop) - strlcpy(qe_firmware_info.id, sprop, + strscpy(qe_firmware_info.id, sprop, sizeof(qe_firmware_info.id)); of_property_read_u64(fw, "extended-modes", diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index cf78839b3f74..1cc2281cb370 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -3,6 +3,7 @@ #include <linux/acpi.h> #include <linux/delay.h> +#include <linux/irq.h> #include <linux/mod_devicetable.h> #include <linux/pm_runtime.h> #include <linux/soundwire/sdw_registers.h> @@ -25,6 +26,23 @@ static int sdw_get_id(struct sdw_bus *bus) return 0; } +static int sdw_irq_map(struct irq_domain *h, unsigned int virq, + irq_hw_number_t hw) +{ + struct sdw_bus *bus = h->host_data; + + irq_set_chip_data(virq, bus); + irq_set_chip(virq, &bus->irq_chip); + irq_set_nested_thread(virq, 1); + irq_set_noprobe(virq); + + return 0; +} + +static const struct irq_domain_ops sdw_domain_ops = { + .map = sdw_irq_map, +}; + /** * sdw_bus_master_add() - add a bus Master instance * @bus: bus instance @@ -151,6 +169,14 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent, bus->params.curr_bank = SDW_BANK0; bus->params.next_bank = SDW_BANK1; + bus->irq_chip.name = dev_name(bus->dev); + bus->domain = irq_domain_create_linear(fwnode, SDW_MAX_DEVICES, + &sdw_domain_ops, bus); + if (!bus->domain) { + dev_err(bus->dev, "Failed to add IRQ domain\n"); + return -EINVAL; + } + return 0; } EXPORT_SYMBOL(sdw_bus_master_add); @@ -187,6 +213,9 @@ static int sdw_delete_slave(struct device *dev, void *data) void sdw_bus_master_delete(struct sdw_bus *bus) { device_for_each_child(bus->dev, NULL, sdw_delete_slave); + + irq_domain_remove(bus->domain); + sdw_master_device_del(bus); sdw_bus_debugfs_exit(bus); @@ -1725,6 +1754,9 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave) struct device *dev = &slave->dev; struct sdw_driver *drv = drv_to_sdw_driver(dev->driver); + if (slave->prop.use_domain_irq && slave->irq) + handle_nested_irq(slave->irq); + if (drv->ops && drv->ops->interrupt_callback) { slave_intr.sdca_cascade = sdca_cascade; slave_intr.control_port = clear; diff --git a/drivers/soundwire/bus_type.c b/drivers/soundwire/bus_type.c index 1f43ee848eac..fafbc284e82d 100644 --- a/drivers/soundwire/bus_type.c +++ b/drivers/soundwire/bus_type.c @@ -122,6 +122,12 @@ static int sdw_drv_probe(struct device *dev) if (drv->ops && drv->ops->read_prop) drv->ops->read_prop(slave); + if (slave->prop.use_domain_irq) { + slave->irq = irq_create_mapping(slave->bus->domain, slave->dev_num); + if (!slave->irq) + dev_warn(dev, "Failed to map IRQ\n"); + } + /* init the sysfs as we have properties now */ ret = sdw_slave_sysfs_init(slave); if (ret < 0) @@ -166,7 +172,13 @@ static int sdw_drv_remove(struct device *dev) int ret = 0; mutex_lock(&slave->sdw_dev_lock); + slave->probed = false; + + if (slave->prop.use_domain_irq) + irq_dispose_mapping(irq_find_mapping(slave->bus->domain, + slave->dev_num)); + mutex_unlock(&slave->sdw_dev_lock); if (drv->remove) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 8962b2557615..2c21d5b96fdc 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -281,6 +281,13 @@ config SPI_COLDFIRE_QSPI This enables support for the Coldfire QSPI controller in master mode. +config SPI_CS42L43 + tristate "Cirrus Logic CS42L43 SPI controller" + depends on MFD_CS42L43 && PINCTRL_CS42L43 + help + This enables support for the SPI controller inside the Cirrus Logic + CS42L43 audio codec. + config SPI_DAVINCI tristate "Texas Instruments DaVinci/DA8x/OMAP-L/AM1x SoC SPI controller" depends on ARCH_DAVINCI || ARCH_KEYSTONE || COMPILE_TEST @@ -516,6 +523,32 @@ config SPI_LM70_LLP which interfaces to an LM70 temperature sensor using a parallel port. +config SPI_LOONGSON_CORE + tristate + depends on LOONGARCH || COMPILE_TEST + +config SPI_LOONGSON_PCI + tristate "Loongson SPI Controller PCI Driver Support" + select SPI_LOONGSON_CORE + depends on PCI && (LOONGARCH || COMPILE_TEST) + help + This bus driver supports the Loongson SPI hardware controller in + the Loongson platforms and supports to use PCI framework to + register SPI device resources. + Say Y or M here if you want to use the SPI controller on + Loongson platform. + +config SPI_LOONGSON_PLATFORM + tristate "Loongson SPI Controller Platform Driver Support" + select SPI_LOONGSON_CORE + depends on OF && (LOONGARCH || COMPILE_TEST) + help + This bus driver supports the Loongson SPI hardware controller in + the Loongson platforms and supports to use DTS framework to + register SPI device resources. + Say Y or M here if you want to use the SPI controller on + Loongson platform. + config SPI_LP8841_RTC tristate "ICP DAS LP-8841 SPI Controller for RTC" depends on MACH_PXA27X_DT || COMPILE_TEST diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 080c2c1b3ec1..6af54842b9fa 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_SPI_CADENCE_QUADSPI) += spi-cadence-quadspi.o obj-$(CONFIG_SPI_CADENCE_XSPI) += spi-cadence-xspi.o obj-$(CONFIG_SPI_CLPS711X) += spi-clps711x.o obj-$(CONFIG_SPI_COLDFIRE_QSPI) += spi-coldfire-qspi.o +obj-$(CONFIG_SPI_CS42L43) += spi-cs42l43.o obj-$(CONFIG_SPI_DAVINCI) += spi-davinci.o obj-$(CONFIG_SPI_DLN2) += spi-dln2.o obj-$(CONFIG_SPI_DESIGNWARE) += spi-dw.o @@ -71,6 +72,9 @@ obj-$(CONFIG_SPI_INTEL_PLATFORM) += spi-intel-platform.o obj-$(CONFIG_SPI_LANTIQ_SSC) += spi-lantiq-ssc.o obj-$(CONFIG_SPI_JCORE) += spi-jcore.o obj-$(CONFIG_SPI_LM70_LLP) += spi-lm70llp.o +obj-$(CONFIG_SPI_LOONGSON_CORE) += spi-loongson-core.o +obj-$(CONFIG_SPI_LOONGSON_PCI) += spi-loongson-pci.o +obj-$(CONFIG_SPI_LOONGSON_PLATFORM) += spi-loongson-plat.o obj-$(CONFIG_SPI_LP8841_RTC) += spi-lp8841-rtc.o obj-$(CONFIG_SPI_MESON_SPICC) += spi-meson-spicc.o obj-$(CONFIG_SPI_MESON_SPIFC) += spi-meson-spifc.o diff --git a/drivers/spi/spi-amd.c b/drivers/spi/spi-amd.c index fecead757a3c..5d9b246b6963 100644 --- a/drivers/spi/spi-amd.c +++ b/drivers/spi/spi-amd.c @@ -215,9 +215,9 @@ static int amd_spi_execute_opcode(struct amd_spi *amd_spi) } } -static int amd_spi_master_setup(struct spi_device *spi) +static int amd_spi_host_setup(struct spi_device *spi) { - struct amd_spi *amd_spi = spi_master_get_devdata(spi->master); + struct amd_spi *amd_spi = spi_controller_get_devdata(spi->controller); amd_spi_clear_fifo_ptr(amd_spi); @@ -272,7 +272,7 @@ static int amd_set_spi_freq(struct amd_spi *amd_spi, u32 speed_hz) } static inline int amd_spi_fifo_xfer(struct amd_spi *amd_spi, - struct spi_master *master, + struct spi_controller *host, struct spi_message *message) { struct spi_transfer *xfer = NULL; @@ -353,15 +353,15 @@ fin_msg: return -ENODEV; } - spi_finalize_current_message(master); + spi_finalize_current_message(host); return message->status; } -static int amd_spi_master_transfer(struct spi_master *master, +static int amd_spi_host_transfer(struct spi_controller *host, struct spi_message *msg) { - struct amd_spi *amd_spi = spi_master_get_devdata(master); + struct amd_spi *amd_spi = spi_controller_get_devdata(host); struct spi_device *spi = msg->spi; amd_spi_select_chip(amd_spi, spi_get_chipselect(spi, 0)); @@ -370,7 +370,7 @@ static int amd_spi_master_transfer(struct spi_master *master, * Extract spi_transfers from the spi message and * program the controller. */ - return amd_spi_fifo_xfer(amd_spi, master, msg); + return amd_spi_fifo_xfer(amd_spi, host, msg); } static size_t amd_spi_max_transfer_size(struct spi_device *spi) @@ -381,16 +381,16 @@ static size_t amd_spi_max_transfer_size(struct spi_device *spi) static int amd_spi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct spi_master *master; + struct spi_controller *host; struct amd_spi *amd_spi; int err; - /* Allocate storage for spi_master and driver private data */ - master = devm_spi_alloc_master(dev, sizeof(struct amd_spi)); - if (!master) - return dev_err_probe(dev, -ENOMEM, "Error allocating SPI master\n"); + /* Allocate storage for host and driver private data */ + host = devm_spi_alloc_host(dev, sizeof(struct amd_spi)); + if (!host) + return dev_err_probe(dev, -ENOMEM, "Error allocating SPI host\n"); - amd_spi = spi_master_get_devdata(master); + amd_spi = spi_controller_get_devdata(host); amd_spi->io_remap_addr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(amd_spi->io_remap_addr)) return dev_err_probe(dev, PTR_ERR(amd_spi->io_remap_addr), @@ -398,22 +398,22 @@ static int amd_spi_probe(struct platform_device *pdev) dev_dbg(dev, "io_remap_address: %p\n", amd_spi->io_remap_addr); - amd_spi->version = (enum amd_spi_versions) device_get_match_data(dev); + amd_spi->version = (uintptr_t) device_get_match_data(dev); - /* Initialize the spi_master fields */ - master->bus_num = 0; - master->num_chipselect = 4; - master->mode_bits = 0; - master->flags = SPI_MASTER_HALF_DUPLEX; - master->max_speed_hz = AMD_SPI_MAX_HZ; - master->min_speed_hz = AMD_SPI_MIN_HZ; - master->setup = amd_spi_master_setup; - master->transfer_one_message = amd_spi_master_transfer; - master->max_transfer_size = amd_spi_max_transfer_size; - master->max_message_size = amd_spi_max_transfer_size; + /* Initialize the spi_controller fields */ + host->bus_num = 0; + host->num_chipselect = 4; + host->mode_bits = 0; + host->flags = SPI_CONTROLLER_HALF_DUPLEX; + host->max_speed_hz = AMD_SPI_MAX_HZ; + host->min_speed_hz = AMD_SPI_MIN_HZ; + host->setup = amd_spi_host_setup; + host->transfer_one_message = amd_spi_host_transfer; + host->max_transfer_size = amd_spi_max_transfer_size; + host->max_message_size = amd_spi_max_transfer_size; /* Register the controller with SPI framework */ - err = devm_spi_register_master(dev, master); + err = devm_spi_register_controller(dev, host); if (err) return dev_err_probe(dev, err, "error registering SPI controller\n"); diff --git a/drivers/spi/spi-amlogic-spifc-a1.c b/drivers/spi/spi-amlogic-spifc-a1.c index 3c4224c38399..fadf6667cd51 100644 --- a/drivers/spi/spi-amlogic-spifc-a1.c +++ b/drivers/spi/spi-amlogic-spifc-a1.c @@ -72,7 +72,7 @@ #define SPIFC_A1_USER_DBUF_ADDR_REG 0x248 -#define SPIFC_A1_BUFFER_SIZE 512 +#define SPIFC_A1_BUFFER_SIZE 512U #define SPIFC_A1_MAX_HZ 200000000 #define SPIFC_A1_MIN_HZ 1000000 @@ -107,6 +107,7 @@ struct amlogic_spifc_a1 { struct clk *clk; struct device *dev; void __iomem *base; + u32 curr_speed_hz; }; static int amlogic_spifc_a1_request(struct amlogic_spifc_a1 *spifc, bool read) @@ -235,66 +236,68 @@ static int amlogic_spifc_a1_write(struct amlogic_spifc_a1 *spifc, return amlogic_spifc_a1_request(spifc, false); } -static int amlogic_spifc_a1_exec_op(struct spi_mem *mem, - const struct spi_mem_op *op) +static int amlogic_spifc_a1_set_freq(struct amlogic_spifc_a1 *spifc, u32 freq) { - struct amlogic_spifc_a1 *spifc = - spi_controller_get_devdata(mem->spi->controller); - size_t off, nbytes = op->data.nbytes; - u32 cmd_cfg, addr_cfg, dummy_cfg, dmode; int ret; - amlogic_spifc_a1_user_init(spifc); - - cmd_cfg = SPIFC_A1_USER_CMD(op); - amlogic_spifc_a1_set_cmd(spifc, cmd_cfg); + if (freq == spifc->curr_speed_hz) + return 0; - if (op->addr.nbytes) { - addr_cfg = SPIFC_A1_USER_ADDR(op); - amlogic_spifc_a1_set_addr(spifc, op->addr.val, addr_cfg); - } + ret = clk_set_rate(spifc->clk, freq); + if (ret) + return ret; - if (op->dummy.nbytes) { - dummy_cfg = SPIFC_A1_USER_DUMMY(op); - amlogic_spifc_a1_set_dummy(spifc, dummy_cfg); - } + spifc->curr_speed_hz = freq; + return 0; +} - if (!op->data.nbytes) - return amlogic_spifc_a1_request(spifc, false); +static int amlogic_spifc_a1_exec_op(struct spi_mem *mem, + const struct spi_mem_op *op) +{ + struct amlogic_spifc_a1 *spifc = + spi_controller_get_devdata(mem->spi->controller); + size_t data_size = op->data.nbytes; + int ret; - dmode = ilog2(op->data.buswidth); - off = 0; + ret = amlogic_spifc_a1_set_freq(spifc, mem->spi->max_speed_hz); + if (ret) + return ret; - do { - size_t block_size = min_t(size_t, nbytes, SPIFC_A1_BUFFER_SIZE); + amlogic_spifc_a1_user_init(spifc); + amlogic_spifc_a1_set_cmd(spifc, SPIFC_A1_USER_CMD(op)); - amlogic_spifc_a1_set_cmd(spifc, cmd_cfg); + if (op->addr.nbytes) + amlogic_spifc_a1_set_addr(spifc, op->addr.val, + SPIFC_A1_USER_ADDR(op)); - if (op->addr.nbytes) - amlogic_spifc_a1_set_addr(spifc, op->addr.val + off, - addr_cfg); + if (op->dummy.nbytes) + amlogic_spifc_a1_set_dummy(spifc, SPIFC_A1_USER_DUMMY(op)); - if (op->dummy.nbytes) - amlogic_spifc_a1_set_dummy(spifc, dummy_cfg); + if (data_size) { + u32 mode = ilog2(op->data.buswidth); writel(0, spifc->base + SPIFC_A1_USER_DBUF_ADDR_REG); if (op->data.dir == SPI_MEM_DATA_IN) - ret = amlogic_spifc_a1_read(spifc, - op->data.buf.in + off, - block_size, dmode); + ret = amlogic_spifc_a1_read(spifc, op->data.buf.in, + data_size, mode); else - ret = amlogic_spifc_a1_write(spifc, - op->data.buf.out + off, - block_size, dmode); - - nbytes -= block_size; - off += block_size; - } while (nbytes != 0 && !ret); + ret = amlogic_spifc_a1_write(spifc, op->data.buf.out, + data_size, mode); + } else { + ret = amlogic_spifc_a1_request(spifc, false); + } return ret; } +static int amlogic_spifc_a1_adjust_op_size(struct spi_mem *mem, + struct spi_mem_op *op) +{ + op->data.nbytes = min(op->data.nbytes, SPIFC_A1_BUFFER_SIZE); + return 0; +} + static void amlogic_spifc_a1_hw_init(struct amlogic_spifc_a1 *spifc) { u32 regv; @@ -314,6 +317,7 @@ static void amlogic_spifc_a1_hw_init(struct amlogic_spifc_a1 *spifc) static const struct spi_controller_mem_ops amlogic_spifc_a1_mem_ops = { .exec_op = amlogic_spifc_a1_exec_op, + .adjust_op_size = amlogic_spifc_a1_adjust_op_size, }; static int amlogic_spifc_a1_probe(struct platform_device *pdev) @@ -322,7 +326,7 @@ static int amlogic_spifc_a1_probe(struct platform_device *pdev) struct amlogic_spifc_a1 *spifc; int ret; - ctrl = devm_spi_alloc_master(&pdev->dev, sizeof(*spifc)); + ctrl = devm_spi_alloc_host(&pdev->dev, sizeof(*spifc)); if (!ctrl) return -ENOMEM; diff --git a/drivers/spi/spi-ar934x.c b/drivers/spi/spi-ar934x.c index 9dcada8c4cb9..58b98cea31d9 100644 --- a/drivers/spi/spi-ar934x.c +++ b/drivers/spi/spi-ar934x.c @@ -14,7 +14,8 @@ #include <linux/iopoll.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/spi/spi.h> #define DRIVER_NAME "spi-ar934x" diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c index a7fb7c94e70e..0103ac0158c0 100644 --- a/drivers/spi/spi-armada-3700.c +++ b/drivers/spi/spi-armada-3700.c @@ -17,8 +17,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_irq.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> #include <linux/pinctrl/consumer.h> #include <linux/spi/spi.h> diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c index e75b0d51f06a..21b0fa646c7d 100644 --- a/drivers/spi/spi-aspeed-smc.c +++ b/drivers/spi/spi-aspeed-smc.c @@ -295,7 +295,7 @@ static const struct aspeed_spi_data ast2400_spi_data; static int do_aspeed_spi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) { - struct aspeed_spi *aspi = spi_controller_get_devdata(mem->spi->master); + struct aspeed_spi *aspi = spi_controller_get_devdata(mem->spi->controller); struct aspeed_spi_chip *chip = &aspi->chips[spi_get_chipselect(mem->spi, 0)]; u32 addr_mode, addr_mode_backup; u32 ctl_val; @@ -374,7 +374,7 @@ static int aspeed_spi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) static const char *aspeed_spi_get_name(struct spi_mem *mem) { - struct aspeed_spi *aspi = spi_controller_get_devdata(mem->spi->master); + struct aspeed_spi *aspi = spi_controller_get_devdata(mem->spi->controller); struct device *dev = aspi->dev; return devm_kasprintf(dev, GFP_KERNEL, "%s.%d", dev_name(dev), @@ -553,7 +553,7 @@ static int aspeed_spi_do_calibration(struct aspeed_spi_chip *chip); static int aspeed_spi_dirmap_create(struct spi_mem_dirmap_desc *desc) { - struct aspeed_spi *aspi = spi_controller_get_devdata(desc->mem->spi->master); + struct aspeed_spi *aspi = spi_controller_get_devdata(desc->mem->spi->controller); struct aspeed_spi_chip *chip = &aspi->chips[spi_get_chipselect(desc->mem->spi, 0)]; struct spi_mem_op *op = &desc->info.op_tmpl; u32 ctl_val; @@ -620,7 +620,7 @@ static int aspeed_spi_dirmap_create(struct spi_mem_dirmap_desc *desc) static ssize_t aspeed_spi_dirmap_read(struct spi_mem_dirmap_desc *desc, u64 offset, size_t len, void *buf) { - struct aspeed_spi *aspi = spi_controller_get_devdata(desc->mem->spi->master); + struct aspeed_spi *aspi = spi_controller_get_devdata(desc->mem->spi->controller); struct aspeed_spi_chip *chip = &aspi->chips[spi_get_chipselect(desc->mem->spi, 0)]; /* Switch to USER command mode if mapping window is too small */ @@ -669,7 +669,7 @@ static void aspeed_spi_chip_enable(struct aspeed_spi *aspi, unsigned int cs, boo static int aspeed_spi_setup(struct spi_device *spi) { - struct aspeed_spi *aspi = spi_controller_get_devdata(spi->master); + struct aspeed_spi *aspi = spi_controller_get_devdata(spi->controller); const struct aspeed_spi_data *data = aspi->data; unsigned int cs = spi_get_chipselect(spi, 0); struct aspeed_spi_chip *chip = &aspi->chips[cs]; @@ -697,7 +697,7 @@ static int aspeed_spi_setup(struct spi_device *spi) static void aspeed_spi_cleanup(struct spi_device *spi) { - struct aspeed_spi *aspi = spi_controller_get_devdata(spi->master); + struct aspeed_spi *aspi = spi_controller_get_devdata(spi->controller); unsigned int cs = spi_get_chipselect(spi, 0); aspeed_spi_chip_enable(aspi, cs, false); @@ -726,7 +726,7 @@ static int aspeed_spi_probe(struct platform_device *pdev) if (!data) return -ENODEV; - ctlr = devm_spi_alloc_master(dev, sizeof(*aspi)); + ctlr = devm_spi_alloc_host(dev, sizeof(*aspi)); if (!ctlr) return -ENOMEM; diff --git a/drivers/spi/spi-at91-usart.c b/drivers/spi/spi-at91-usart.c index 7854d9790fe9..b11d0f993cc7 100644 --- a/drivers/spi/spi-at91-usart.c +++ b/drivers/spi/spi-at91-usart.c @@ -13,7 +13,6 @@ #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_platform.h> #include <linux/gpio/consumer.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> @@ -486,10 +485,7 @@ static int at91_usart_gpio_setup(struct platform_device *pdev) cs_gpios = devm_gpiod_get_array_optional(&pdev->dev, "cs", GPIOD_OUT_LOW); - if (IS_ERR(cs_gpios)) - return PTR_ERR(cs_gpios); - - return 0; + return PTR_ERR_OR_ZERO(cs_gpios); } static int at91_usart_spi_probe(struct platform_device *pdev) @@ -527,7 +523,7 @@ static int at91_usart_spi_probe(struct platform_device *pdev) controller->dev.of_node = pdev->dev.parent->of_node; controller->bits_per_word_mask = SPI_BPW_MASK(8); controller->setup = at91_usart_spi_setup; - controller->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX; + controller->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX; controller->transfer_one = at91_usart_spi_transfer_one; controller->prepare_message = at91_usart_spi_prepare_message; controller->unprepare_message = at91_usart_spi_unprepare_message; diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index d3dd21386f12..1b6d977d111c 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -185,7 +185,7 @@ static int ath79_spi_probe(struct platform_device *pdev) host->use_gpio_descriptors = true; host->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); - host->flags = SPI_MASTER_GPIO_SS; + host->flags = SPI_CONTROLLER_GPIO_SS; host->num_chipselect = 3; host->mem_ops = &ath79_mem_ops; diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 152cd6773403..6aa8adbe4170 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1450,10 +1450,6 @@ static int atmel_spi_probe(struct platform_device *pdev) /* Select default pin state */ pinctrl_pm_select_default_state(&pdev->dev); - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!regs) - return -ENXIO; - irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; @@ -1475,8 +1471,8 @@ static int atmel_spi_probe(struct platform_device *pdev) host->bus_num = pdev->id; host->num_chipselect = 4; host->setup = atmel_spi_setup; - host->flags = (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX | - SPI_MASTER_GPIO_SS); + host->flags = (SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX | + SPI_CONTROLLER_GPIO_SS); host->transfer_one = atmel_spi_one_transfer; host->set_cs = atmel_spi_set_cs; host->cleanup = atmel_spi_cleanup; @@ -1490,7 +1486,7 @@ static int atmel_spi_probe(struct platform_device *pdev) spin_lock_init(&as->lock); as->pdev = pdev; - as->regs = devm_ioremap_resource(&pdev->dev, regs); + as->regs = devm_platform_get_and_ioremap_resource(pdev, 0, ®s); if (IS_ERR(as->regs)) { ret = PTR_ERR(as->regs); goto out_unmap_regs; diff --git a/drivers/spi/spi-au1550.c b/drivers/spi/spi-au1550.c index 0b57e6afce0f..1011b1a8f241 100644 --- a/drivers/spi/spi-au1550.c +++ b/drivers/spi/spi-au1550.c @@ -54,7 +54,7 @@ struct au1550_spi { int (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t); irqreturn_t (*irq_callback)(struct au1550_spi *hw); - struct completion master_done; + struct completion host_done; unsigned int usedma; u32 dma_tx_id; @@ -66,7 +66,7 @@ struct au1550_spi { unsigned int dma_rx_tmpbuf_size; u32 dma_rx_tmpbuf_addr; - struct spi_master *master; + struct spi_controller *host; struct device *dev; struct au1550_spi_info *pdata; struct resource *ioarea; @@ -159,7 +159,7 @@ static void au1550_spi_reset_fifos(struct au1550_spi *hw) */ static void au1550_spi_chipsel(struct spi_device *spi, int value) { - struct au1550_spi *hw = spi_master_get_devdata(spi->master); + struct au1550_spi *hw = spi_controller_get_devdata(spi->controller); unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0; u32 cfg, stat; @@ -219,7 +219,7 @@ static void au1550_spi_chipsel(struct spi_device *spi, int value) static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t) { - struct au1550_spi *hw = spi_master_get_devdata(spi->master); + struct au1550_spi *hw = spi_controller_get_devdata(spi->controller); unsigned int bpw, hz; u32 cfg, stat; @@ -272,7 +272,7 @@ static int au1550_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t) * no reliable way how to recognize that spi transfer is done * dma complete callbacks are called before real spi transfer is finished * and if only tx dma channel is set up (and rx fifo overflow event masked) - * spi master done event irq is not generated unless rx fifo is empty (emptied) + * spi host done event irq is not generated unless rx fifo is empty (emptied) * so we need rx tmp buffer to use for rx dma if user does not provide one */ static int au1550_spi_dma_rxtmp_alloc(struct au1550_spi *hw, unsigned int size) @@ -303,7 +303,7 @@ static void au1550_spi_dma_rxtmp_free(struct au1550_spi *hw) static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t) { - struct au1550_spi *hw = spi_master_get_devdata(spi->master); + struct au1550_spi *hw = spi_controller_get_devdata(spi->controller); dma_addr_t dma_tx_addr; dma_addr_t dma_rx_addr; u32 res; @@ -387,7 +387,7 @@ static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t) hw->regs->psc_spipcr = PSC_SPIPCR_MS; wmb(); /* drain writebuffer */ - wait_for_completion(&hw->master_done); + wait_for_completion(&hw->host_done); au1xxx_dbdma_stop(hw->dma_tx_ch); au1xxx_dbdma_stop(hw->dma_rx_ch); @@ -449,7 +449,7 @@ static irqreturn_t au1550_spi_dma_irq_callback(struct au1550_spi *hw) "dma transfer: unexpected SPI error (event=0x%x stat=0x%x)!\n", evnt, stat); - complete(&hw->master_done); + complete(&hw->host_done); return IRQ_HANDLED; } @@ -458,7 +458,7 @@ static irqreturn_t au1550_spi_dma_irq_callback(struct au1550_spi *hw) au1550_spi_mask_ack_all(hw); hw->rx_count = hw->len; hw->tx_count = hw->len; - complete(&hw->master_done); + complete(&hw->host_done); } return IRQ_HANDLED; } @@ -502,7 +502,7 @@ AU1550_SPI_TX_WORD(32, 0xffffff) static int au1550_spi_pio_txrxb(struct spi_device *spi, struct spi_transfer *t) { u32 stat, mask; - struct au1550_spi *hw = spi_master_get_devdata(spi->master); + struct au1550_spi *hw = spi_controller_get_devdata(spi->controller); hw->tx = t->tx_buf; hw->rx = t->rx_buf; @@ -537,7 +537,7 @@ static int au1550_spi_pio_txrxb(struct spi_device *spi, struct spi_transfer *t) hw->regs->psc_spipcr = PSC_SPIPCR_MS; wmb(); /* drain writebuffer */ - wait_for_completion(&hw->master_done); + wait_for_completion(&hw->host_done); return min(hw->rx_count, hw->tx_count); } @@ -568,7 +568,7 @@ static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw) dev_err(hw->dev, "pio transfer: unexpected SPI error (event=0x%x stat=0x%x)!\n", evnt, stat); - complete(&hw->master_done); + complete(&hw->host_done); return IRQ_HANDLED; } @@ -605,11 +605,11 @@ static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw) /* * Restart the SPI transmission in case of a transmit underflow. * This seems to work despite the notes in the Au1550 data book - * of Figure 8-4 with flowchart for SPI master operation: + * of Figure 8-4 with flowchart for SPI host operation: * * """Note 1: An XFR Error Interrupt occurs, unless masked, * for any of the following events: Tx FIFO Underflow, - * Rx FIFO Overflow, or Multiple-master Error + * Rx FIFO Overflow, or Multiple-host Error * Note 2: In case of a Tx Underflow Error, all zeroes are * transmitted.""" * @@ -627,14 +627,14 @@ static irqreturn_t au1550_spi_pio_irq_callback(struct au1550_spi *hw) if (hw->rx_count >= hw->len) { /* transfer completed successfully */ au1550_spi_mask_ack_all(hw); - complete(&hw->master_done); + complete(&hw->host_done); } return IRQ_HANDLED; } static int au1550_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) { - struct au1550_spi *hw = spi_master_get_devdata(spi->master); + struct au1550_spi *hw = spi_controller_get_devdata(spi->controller); return hw->txrx_bufs(spi, t); } @@ -723,24 +723,24 @@ static void au1550_spi_setup_psc_as_spi(struct au1550_spi *hw) static int au1550_spi_probe(struct platform_device *pdev) { struct au1550_spi *hw; - struct spi_master *master; + struct spi_controller *host; struct resource *r; int err = 0; - master = spi_alloc_master(&pdev->dev, sizeof(struct au1550_spi)); - if (master == NULL) { - dev_err(&pdev->dev, "No memory for spi_master\n"); + host = spi_alloc_host(&pdev->dev, sizeof(struct au1550_spi)); + if (host == NULL) { + dev_err(&pdev->dev, "No memory for spi_controller\n"); err = -ENOMEM; goto err_nomem; } /* the spi->mode bits understood by this driver: */ - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 24); + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; + host->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 24); - hw = spi_master_get_devdata(master); + hw = spi_controller_get_devdata(host); - hw->master = master; + hw->host = host; hw->pdata = dev_get_platdata(&pdev->dev); hw->dev = &pdev->dev; @@ -798,9 +798,9 @@ static int au1550_spi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, hw); - init_completion(&hw->master_done); + init_completion(&hw->host_done); - hw->bitbang.master = hw->master; + hw->bitbang.master = hw->host; hw->bitbang.setup_transfer = au1550_spi_setupxfer; hw->bitbang.chipselect = au1550_spi_chipsel; hw->bitbang.txrx_bufs = au1550_spi_txrx_bufs; @@ -858,8 +858,8 @@ static int au1550_spi_probe(struct platform_device *pdev) goto err_no_irq; } - master->bus_num = pdev->id; - master->num_chipselect = hw->pdata->num_chipselect; + host->bus_num = pdev->id; + host->num_chipselect = hw->pdata->num_chipselect; /* * precompute valid range for spi freq - from au1550 datasheet: @@ -874,8 +874,8 @@ static int au1550_spi_probe(struct platform_device *pdev) int min_div = (2 << 0) * (2 * (4 + 1)); int max_div = (2 << 3) * (2 * (63 + 1)); - master->max_speed_hz = hw->pdata->mainclk_hz / min_div; - master->min_speed_hz = + host->max_speed_hz = hw->pdata->mainclk_hz / min_div; + host->min_speed_hz = hw->pdata->mainclk_hz / (max_div + 1) + 1; } @@ -883,13 +883,13 @@ static int au1550_spi_probe(struct platform_device *pdev) err = spi_bitbang_start(&hw->bitbang); if (err) { - dev_err(&pdev->dev, "Failed to register SPI master\n"); + dev_err(&pdev->dev, "Failed to register SPI host\n"); goto err_register; } dev_info(&pdev->dev, - "spi master registered: bus_num=%d num_chipselect=%d\n", - master->bus_num, master->num_chipselect); + "spi host registered: bus_num=%d num_chipselect=%d\n", + host->bus_num, host->num_chipselect); return 0; @@ -917,7 +917,7 @@ err_ioremap: err_no_iores: err_no_pdata: - spi_master_put(hw->master); + spi_controller_put(hw->host); err_nomem: return err; @@ -927,8 +927,8 @@ static void au1550_spi_remove(struct platform_device *pdev) { struct au1550_spi *hw = platform_get_drvdata(pdev); - dev_info(&pdev->dev, "spi master remove: bus_num=%d\n", - hw->master->bus_num); + dev_info(&pdev->dev, "spi host remove: bus_num=%d\n", + hw->host->bus_num); spi_bitbang_stop(&hw->bitbang); free_irq(hw->irq, hw); @@ -941,7 +941,7 @@ static void au1550_spi_remove(struct platform_device *pdev) au1xxx_dbdma_chan_free(hw->dma_tx_ch); } - spi_master_put(hw->master); + spi_controller_put(hw->host); } /* work with hotplug and coldplug */ diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c index 89661f3b0d44..0258c9a72fdc 100644 --- a/drivers/spi/spi-axi-spi-engine.c +++ b/drivers/spi/spi-axi-spi-engine.c @@ -356,8 +356,8 @@ static bool spi_engine_read_rx_fifo(struct spi_engine *spi_engine) static irqreturn_t spi_engine_irq(int irq, void *devid) { - struct spi_master *master = devid; - struct spi_engine *spi_engine = spi_master_get_devdata(master); + struct spi_controller *host = devid; + struct spi_engine *spi_engine = spi_controller_get_devdata(host); unsigned int disable_int = 0; unsigned int pending; @@ -396,7 +396,7 @@ static irqreturn_t spi_engine_irq(int irq, void *devid) msg->status = 0; msg->actual_length = msg->frame_length; spi_engine->msg = NULL; - spi_finalize_current_message(master); + spi_finalize_current_message(host); disable_int |= SPI_ENGINE_INT_SYNC; } } @@ -412,11 +412,11 @@ static irqreturn_t spi_engine_irq(int irq, void *devid) return IRQ_HANDLED; } -static int spi_engine_transfer_one_message(struct spi_master *master, +static int spi_engine_transfer_one_message(struct spi_controller *host, struct spi_message *msg) { struct spi_engine_program p_dry, *p; - struct spi_engine *spi_engine = spi_master_get_devdata(master); + struct spi_engine *spi_engine = spi_controller_get_devdata(host); unsigned int int_enable = 0; unsigned long flags; size_t size; @@ -464,42 +464,42 @@ static int spi_engine_transfer_one_message(struct spi_master *master, static int spi_engine_probe(struct platform_device *pdev) { struct spi_engine *spi_engine; - struct spi_master *master; + struct spi_controller *host; unsigned int version; int irq; int ret; irq = platform_get_irq(pdev, 0); - if (irq <= 0) - return -ENXIO; + if (irq < 0) + return irq; spi_engine = devm_kzalloc(&pdev->dev, sizeof(*spi_engine), GFP_KERNEL); if (!spi_engine) return -ENOMEM; - master = spi_alloc_master(&pdev->dev, 0); - if (!master) + host = spi_alloc_host(&pdev->dev, 0); + if (!host) return -ENOMEM; - spi_master_set_devdata(master, spi_engine); + spi_controller_set_devdata(host, spi_engine); spin_lock_init(&spi_engine->lock); spi_engine->clk = devm_clk_get(&pdev->dev, "s_axi_aclk"); if (IS_ERR(spi_engine->clk)) { ret = PTR_ERR(spi_engine->clk); - goto err_put_master; + goto err_put_host; } spi_engine->ref_clk = devm_clk_get(&pdev->dev, "spi_clk"); if (IS_ERR(spi_engine->ref_clk)) { ret = PTR_ERR(spi_engine->ref_clk); - goto err_put_master; + goto err_put_host; } ret = clk_prepare_enable(spi_engine->clk); if (ret) - goto err_put_master; + goto err_put_host; ret = clk_prepare_enable(spi_engine->ref_clk); if (ret) @@ -525,46 +525,46 @@ static int spi_engine_probe(struct platform_device *pdev) writel_relaxed(0xff, spi_engine->base + SPI_ENGINE_REG_INT_PENDING); writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_INT_ENABLE); - ret = request_irq(irq, spi_engine_irq, 0, pdev->name, master); + ret = request_irq(irq, spi_engine_irq, 0, pdev->name, host); if (ret) goto err_ref_clk_disable; - master->dev.of_node = pdev->dev.of_node; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_3WIRE; - master->bits_per_word_mask = SPI_BPW_MASK(8); - master->max_speed_hz = clk_get_rate(spi_engine->ref_clk) / 2; - master->transfer_one_message = spi_engine_transfer_one_message; - master->num_chipselect = 8; + host->dev.of_node = pdev->dev.of_node; + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_3WIRE; + host->bits_per_word_mask = SPI_BPW_MASK(8); + host->max_speed_hz = clk_get_rate(spi_engine->ref_clk) / 2; + host->transfer_one_message = spi_engine_transfer_one_message; + host->num_chipselect = 8; - ret = spi_register_master(master); + ret = spi_register_controller(host); if (ret) goto err_free_irq; - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); return 0; err_free_irq: - free_irq(irq, master); + free_irq(irq, host); err_ref_clk_disable: clk_disable_unprepare(spi_engine->ref_clk); err_clk_disable: clk_disable_unprepare(spi_engine->clk); -err_put_master: - spi_master_put(master); +err_put_host: + spi_controller_put(host); return ret; } static void spi_engine_remove(struct platform_device *pdev) { - struct spi_master *master = spi_master_get(platform_get_drvdata(pdev)); - struct spi_engine *spi_engine = spi_master_get_devdata(master); + struct spi_controller *host = spi_controller_get(platform_get_drvdata(pdev)); + struct spi_engine *spi_engine = spi_controller_get_devdata(host); int irq = platform_get_irq(pdev, 0); - spi_unregister_master(master); + spi_unregister_controller(host); - free_irq(irq, master); + free_irq(irq, host); - spi_master_put(master); + spi_controller_put(host); writel_relaxed(0xff, spi_engine->base + SPI_ENGINE_REG_INT_PENDING); writel_relaxed(0x00, spi_engine->base + SPI_ENGINE_REG_INT_ENABLE); diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index d91dfbe47aa5..ef08fcac2f6d 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -220,7 +220,7 @@ struct qspi_trans { struct bcm_qspi { struct platform_device *pdev; - struct spi_master *master; + struct spi_controller *host; struct clk *clk; u32 base_clk; u32 max_speed_hz; @@ -732,7 +732,7 @@ static bool bcm_qspi_mspi_transfer_is_last(struct bcm_qspi *qspi, struct qspi_trans *qt) { if (qt->mspi_last_trans && - spi_transfer_is_last(qspi->master, qt->trans)) + spi_transfer_is_last(qspi->host, qt->trans)) return true; else return false; @@ -979,7 +979,7 @@ static int write_to_hw(struct bcm_qspi *qspi, struct spi_device *spi) mspi_cdram |= ((tp.trans->bits_per_word <= 8) ? 0 : MSPI_CDRAM_BITSE_BIT); - /* set 3wrire halfduplex mode data from master to slave */ + /* set 3wrire halfduplex mode data from host to target */ if ((spi->mode & SPI_3WIRE) && tp.trans->tx_buf) mspi_cdram |= MSPI_CDRAM_OUTP; @@ -1035,7 +1035,7 @@ done: static int bcm_qspi_bspi_exec_mem_op(struct spi_device *spi, const struct spi_mem_op *op) { - struct bcm_qspi *qspi = spi_master_get_devdata(spi->master); + struct bcm_qspi *qspi = spi_controller_get_devdata(spi->controller); u32 addr = 0, len, rdlen, len_words, from = 0; int ret = 0; unsigned long timeo = msecs_to_jiffies(100); @@ -1118,11 +1118,11 @@ static int bcm_qspi_bspi_exec_mem_op(struct spi_device *spi, return ret; } -static int bcm_qspi_transfer_one(struct spi_master *master, +static int bcm_qspi_transfer_one(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *trans) { - struct bcm_qspi *qspi = spi_master_get_devdata(master); + struct bcm_qspi *qspi = spi_controller_get_devdata(host); int slots; unsigned long timeo = msecs_to_jiffies(100); @@ -1150,8 +1150,8 @@ static int bcm_qspi_transfer_one(struct spi_master *master, static int bcm_qspi_mspi_exec_mem_op(struct spi_device *spi, const struct spi_mem_op *op) { - struct spi_master *master = spi->master; - struct bcm_qspi *qspi = spi_master_get_devdata(master); + struct spi_controller *host = spi->controller; + struct bcm_qspi *qspi = spi_controller_get_devdata(host); struct spi_transfer t[2]; u8 cmd[6] = { }; int ret, i; @@ -1171,7 +1171,7 @@ static int bcm_qspi_mspi_exec_mem_op(struct spi_device *spi, t[0].tx_nbits = op->cmd.buswidth; /* lets mspi know that this is not last transfer */ qspi->trans_pos.mspi_last_trans = false; - ret = bcm_qspi_transfer_one(master, spi, &t[0]); + ret = bcm_qspi_transfer_one(host, spi, &t[0]); /* rx */ qspi->trans_pos.mspi_last_trans = true; @@ -1181,7 +1181,7 @@ static int bcm_qspi_mspi_exec_mem_op(struct spi_device *spi, t[1].len = op->data.nbytes; t[1].rx_nbits = op->data.buswidth; t[1].bits_per_word = spi->bits_per_word; - ret = bcm_qspi_transfer_one(master, spi, &t[1]); + ret = bcm_qspi_transfer_one(host, spi, &t[1]); } return ret; @@ -1191,7 +1191,7 @@ static int bcm_qspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) { struct spi_device *spi = mem->spi; - struct bcm_qspi *qspi = spi_master_get_devdata(spi->master); + struct bcm_qspi *qspi = spi_controller_get_devdata(spi->controller); int ret = 0; bool mspi_read = false; u32 addr = 0, len; @@ -1486,7 +1486,7 @@ int bcm_qspi_probe(struct platform_device *pdev, const struct bcm_qspi_data *data; struct device *dev = &pdev->dev; struct bcm_qspi *qspi; - struct spi_master *master; + struct spi_controller *host; struct resource *res; int irq, ret = 0, num_ints = 0; u32 val; @@ -1504,13 +1504,13 @@ int bcm_qspi_probe(struct platform_device *pdev, data = of_id->data; - master = devm_spi_alloc_master(dev, sizeof(struct bcm_qspi)); - if (!master) { - dev_err(dev, "error allocating spi_master\n"); + host = devm_spi_alloc_host(dev, sizeof(struct bcm_qspi)); + if (!host) { + dev_err(dev, "error allocating spi_controller\n"); return -ENOMEM; } - qspi = spi_master_get_devdata(master); + qspi = spi_controller_get_devdata(host); qspi->clk = devm_clk_get_optional(&pdev->dev, NULL); if (IS_ERR(qspi->clk)) @@ -1520,23 +1520,23 @@ int bcm_qspi_probe(struct platform_device *pdev, qspi->trans_pos.trans = NULL; qspi->trans_pos.byte = 0; qspi->trans_pos.mspi_last_trans = true; - qspi->master = master; + qspi->host = host; - master->bus_num = -1; - master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_RX_DUAL | SPI_RX_QUAD | + host->bus_num = -1; + host->mode_bits = SPI_CPHA | SPI_CPOL | SPI_RX_DUAL | SPI_RX_QUAD | SPI_3WIRE; - master->setup = bcm_qspi_setup; - master->transfer_one = bcm_qspi_transfer_one; - master->mem_ops = &bcm_qspi_mem_ops; - master->cleanup = bcm_qspi_cleanup; - master->dev.of_node = dev->of_node; - master->num_chipselect = NUM_CHIPSELECT; - master->use_gpio_descriptors = true; + host->setup = bcm_qspi_setup; + host->transfer_one = bcm_qspi_transfer_one; + host->mem_ops = &bcm_qspi_mem_ops; + host->cleanup = bcm_qspi_cleanup; + host->dev.of_node = dev->of_node; + host->num_chipselect = NUM_CHIPSELECT; + host->use_gpio_descriptors = true; qspi->big_endian = of_device_is_big_endian(dev->of_node); if (!of_property_read_u32(dev->of_node, "num-cs", &val)) - master->num_chipselect = val; + host->num_chipselect = val; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hif_mspi"); if (!res) @@ -1659,9 +1659,9 @@ int bcm_qspi_probe(struct platform_device *pdev, qspi->xfer_mode.addrlen = -1; qspi->xfer_mode.hp = -1; - ret = spi_register_master(master); + ret = spi_register_controller(host); if (ret < 0) { - dev_err(dev, "can't register master\n"); + dev_err(dev, "can't register host\n"); goto qspi_reg_err; } @@ -1682,7 +1682,7 @@ void bcm_qspi_remove(struct platform_device *pdev) { struct bcm_qspi *qspi = platform_get_drvdata(pdev); - spi_unregister_master(qspi->master); + spi_unregister_controller(qspi->host); bcm_qspi_hw_uninit(qspi); clk_disable_unprepare(qspi->clk); kfree(qspi->dev_ids); @@ -1700,7 +1700,7 @@ static int __maybe_unused bcm_qspi_suspend(struct device *dev) qspi->s3_strap_override_ctrl = bcm_qspi_read(qspi, BSPI, BSPI_STRAP_OVERRIDE_CTRL); - spi_master_suspend(qspi->master); + spi_controller_suspend(qspi->host); clk_disable_unprepare(qspi->clk); bcm_qspi_hw_uninit(qspi); @@ -1721,7 +1721,7 @@ static int __maybe_unused bcm_qspi_resume(struct device *dev) ret = clk_prepare_enable(qspi->clk); if (!ret) - spi_master_resume(qspi->master); + spi_controller_resume(qspi->host); return ret; } diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index 3b253da98c05..e7bb2714678a 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -24,7 +24,7 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> #include <linux/gpio/consumer.h> #include <linux/gpio/machine.h> /* FIXME: using chip internals */ #include <linux/gpio/driver.h> /* FIXME: using chip internals */ @@ -105,7 +105,7 @@ MODULE_PARM_DESC(polling_limit_us, * These are counted as well in @count_transfer_polling and * @count_transfer_irq * @count_transfer_dma: count how often dma mode is used - * @slv: SPI slave currently selected + * @target: SPI target currently selected * (used by bcm2835_spi_dma_tx_done() to write @clear_rx_cs) * @tx_dma_active: whether a TX DMA descriptor is in progress * @rx_dma_active: whether a RX DMA descriptor is in progress @@ -135,7 +135,7 @@ struct bcm2835_spi { u64 count_transfer_irq_after_polling; u64 count_transfer_dma; - struct bcm2835_spidev *slv; + struct bcm2835_spidev *target; unsigned int tx_dma_active; unsigned int rx_dma_active; struct dma_async_tx_descriptor *fill_tx_desc; @@ -143,14 +143,14 @@ struct bcm2835_spi { }; /** - * struct bcm2835_spidev - BCM2835 SPI slave + * struct bcm2835_spidev - BCM2835 SPI target * @prepare_cs: precalculated CS register value for ->prepare_message() - * (uses slave-specific clock polarity and phase settings) + * (uses target-specific clock polarity and phase settings) * @clear_rx_desc: preallocated RX DMA descriptor used for TX-only transfers * (cyclically clears RX FIFO by writing @clear_rx_cs to CS register) * @clear_rx_addr: bus address of @clear_rx_cs * @clear_rx_cs: precalculated CS register value to clear RX FIFO - * (uses slave-specific clock polarity and phase settings) + * (uses target-specific clock polarity and phase settings) */ struct bcm2835_spidev { u32 prepare_cs; @@ -434,7 +434,7 @@ static int bcm2835_spi_transfer_one_irq(struct spi_controller *ctlr, /** * bcm2835_spi_transfer_prologue() - transfer first few bytes without DMA - * @ctlr: SPI master controller + * @ctlr: SPI host controller * @tfr: SPI transfer * @bs: BCM2835 SPI controller * @cs: CS register @@ -596,7 +596,7 @@ out: /** * bcm2835_spi_dma_rx_done() - callback for DMA RX channel - * @data: SPI master controller + * @data: SPI host controller * * Used for bidirectional and RX-only transfers. */ @@ -624,7 +624,7 @@ static void bcm2835_spi_dma_rx_done(void *data) /** * bcm2835_spi_dma_tx_done() - callback for DMA TX channel - * @data: SPI master controller + * @data: SPI host controller * * Used for TX-only transfers. */ @@ -635,7 +635,7 @@ static void bcm2835_spi_dma_tx_done(void *data) /* busy-wait for TX FIFO to empty */ while (!(bcm2835_rd(bs, BCM2835_SPI_CS) & BCM2835_SPI_CS_DONE)) - bcm2835_wr(bs, BCM2835_SPI_CS, bs->slv->clear_rx_cs); + bcm2835_wr(bs, BCM2835_SPI_CS, bs->target->clear_rx_cs); bs->tx_dma_active = false; smp_wmb(); @@ -655,10 +655,10 @@ static void bcm2835_spi_dma_tx_done(void *data) /** * bcm2835_spi_prepare_sg() - prepare and submit DMA descriptor for sglist - * @ctlr: SPI master controller + * @ctlr: SPI host controller * @tfr: SPI transfer * @bs: BCM2835 SPI controller - * @slv: BCM2835 SPI slave + * @target: BCM2835 SPI target * @is_tx: whether to submit DMA descriptor for TX or RX sglist * * Prepare and submit a DMA descriptor for the TX or RX sglist of @tfr. @@ -667,7 +667,7 @@ static void bcm2835_spi_dma_tx_done(void *data) static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr, struct spi_transfer *tfr, struct bcm2835_spi *bs, - struct bcm2835_spidev *slv, + struct bcm2835_spidev *target, bool is_tx) { struct dma_chan *chan; @@ -707,7 +707,7 @@ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr, } else if (!tfr->rx_buf) { desc->callback = bcm2835_spi_dma_tx_done; desc->callback_param = ctlr; - bs->slv = slv; + bs->target = target; } /* submit it to DMA-engine */ @@ -718,9 +718,9 @@ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr, /** * bcm2835_spi_transfer_one_dma() - perform SPI transfer using DMA engine - * @ctlr: SPI master controller + * @ctlr: SPI host controller * @tfr: SPI transfer - * @slv: BCM2835 SPI slave + * @target: BCM2835 SPI target * @cs: CS register * * For *bidirectional* transfers (both tx_buf and rx_buf are non-%NULL), set up @@ -732,7 +732,7 @@ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr, * clear the RX FIFO by setting the CLEAR_RX bit in the CS register. * * The CS register value is precalculated in bcm2835_spi_setup(). Normally - * this is called only once, on slave registration. A DMA descriptor to write + * this is called only once, on target registration. A DMA descriptor to write * this value is preallocated in bcm2835_dma_init(). All that's left to do * when performing a TX-only transfer is to submit this descriptor to the RX * DMA channel. Latency is thereby minimized. The descriptor does not @@ -765,7 +765,7 @@ static int bcm2835_spi_prepare_sg(struct spi_controller *ctlr, */ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr, struct spi_transfer *tfr, - struct bcm2835_spidev *slv, + struct bcm2835_spidev *target, u32 cs) { struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); @@ -783,7 +783,7 @@ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr, /* setup tx-DMA */ if (bs->tx_buf) { - ret = bcm2835_spi_prepare_sg(ctlr, tfr, bs, slv, true); + ret = bcm2835_spi_prepare_sg(ctlr, tfr, bs, target, true); } else { cookie = dmaengine_submit(bs->fill_tx_desc); ret = dma_submit_error(cookie); @@ -809,9 +809,9 @@ static int bcm2835_spi_transfer_one_dma(struct spi_controller *ctlr, * this saves 10us or more. */ if (bs->rx_buf) { - ret = bcm2835_spi_prepare_sg(ctlr, tfr, bs, slv, false); + ret = bcm2835_spi_prepare_sg(ctlr, tfr, bs, target, false); } else { - cookie = dmaengine_submit(slv->clear_rx_desc); + cookie = dmaengine_submit(target->clear_rx_desc); ret = dma_submit_error(cookie); } if (ret) { @@ -903,15 +903,15 @@ static int bcm2835_dma_init(struct spi_controller *ctlr, struct device *dev, /* get tx/rx dma */ ctlr->dma_tx = dma_request_chan(dev, "tx"); if (IS_ERR(ctlr->dma_tx)) { - dev_err(dev, "no tx-dma configuration found - not using dma mode\n"); - ret = PTR_ERR(ctlr->dma_tx); + ret = dev_err_probe(dev, PTR_ERR(ctlr->dma_tx), + "no tx-dma configuration found - not using dma mode\n"); ctlr->dma_tx = NULL; goto err; } ctlr->dma_rx = dma_request_chan(dev, "rx"); if (IS_ERR(ctlr->dma_rx)) { - dev_err(dev, "no rx-dma configuration found - not using dma mode\n"); - ret = PTR_ERR(ctlr->dma_rx); + ret = dev_err_probe(dev, PTR_ERR(ctlr->dma_rx), + "no rx-dma configuration found - not using dma mode\n"); ctlr->dma_rx = NULL; goto err_release; } @@ -1050,10 +1050,10 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr, struct spi_transfer *tfr) { struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); - struct bcm2835_spidev *slv = spi_get_ctldata(spi); + struct bcm2835_spidev *target = spi_get_ctldata(spi); unsigned long spi_hz, cdiv; unsigned long hz_per_byte, byte_limit; - u32 cs = slv->prepare_cs; + u32 cs = target->prepare_cs; /* set clock */ spi_hz = tfr->speed_hz; @@ -1101,7 +1101,7 @@ static int bcm2835_spi_transfer_one(struct spi_controller *ctlr, * this 1 idle clock cycle pattern but runs the spi clock without gaps */ if (ctlr->can_dma && bcm2835_spi_can_dma(ctlr, spi, tfr)) - return bcm2835_spi_transfer_one_dma(ctlr, tfr, slv, cs); + return bcm2835_spi_transfer_one_dma(ctlr, tfr, target, cs); /* run in interrupt-mode */ return bcm2835_spi_transfer_one_irq(ctlr, spi, tfr, cs, true); @@ -1112,7 +1112,7 @@ static int bcm2835_spi_prepare_message(struct spi_controller *ctlr, { struct spi_device *spi = msg->spi; struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); - struct bcm2835_spidev *slv = spi_get_ctldata(spi); + struct bcm2835_spidev *target = spi_get_ctldata(spi); int ret; if (ctlr->can_dma) { @@ -1131,7 +1131,7 @@ static int bcm2835_spi_prepare_message(struct spi_controller *ctlr, * Set up clock polarity before spi_transfer_one_message() asserts * chip select to avoid a gratuitous clock signal edge. */ - bcm2835_wr(bs, BCM2835_SPI_CS, slv->prepare_cs); + bcm2835_wr(bs, BCM2835_SPI_CS, target->prepare_cs); return 0; } @@ -1163,51 +1163,51 @@ static int chip_match_name(struct gpio_chip *chip, void *data) static void bcm2835_spi_cleanup(struct spi_device *spi) { - struct bcm2835_spidev *slv = spi_get_ctldata(spi); + struct bcm2835_spidev *target = spi_get_ctldata(spi); struct spi_controller *ctlr = spi->controller; - if (slv->clear_rx_desc) - dmaengine_desc_free(slv->clear_rx_desc); + if (target->clear_rx_desc) + dmaengine_desc_free(target->clear_rx_desc); - if (slv->clear_rx_addr) + if (target->clear_rx_addr) dma_unmap_single(ctlr->dma_rx->device->dev, - slv->clear_rx_addr, + target->clear_rx_addr, sizeof(u32), DMA_TO_DEVICE); - kfree(slv); + kfree(target); } static int bcm2835_spi_setup_dma(struct spi_controller *ctlr, struct spi_device *spi, struct bcm2835_spi *bs, - struct bcm2835_spidev *slv) + struct bcm2835_spidev *target) { int ret; if (!ctlr->dma_rx) return 0; - slv->clear_rx_addr = dma_map_single(ctlr->dma_rx->device->dev, - &slv->clear_rx_cs, - sizeof(u32), - DMA_TO_DEVICE); - if (dma_mapping_error(ctlr->dma_rx->device->dev, slv->clear_rx_addr)) { + target->clear_rx_addr = dma_map_single(ctlr->dma_rx->device->dev, + &target->clear_rx_cs, + sizeof(u32), + DMA_TO_DEVICE); + if (dma_mapping_error(ctlr->dma_rx->device->dev, target->clear_rx_addr)) { dev_err(&spi->dev, "cannot map clear_rx_cs\n"); - slv->clear_rx_addr = 0; + target->clear_rx_addr = 0; return -ENOMEM; } - slv->clear_rx_desc = dmaengine_prep_dma_cyclic(ctlr->dma_rx, - slv->clear_rx_addr, - sizeof(u32), 0, - DMA_MEM_TO_DEV, 0); - if (!slv->clear_rx_desc) { + target->clear_rx_desc = dmaengine_prep_dma_cyclic(ctlr->dma_rx, + target->clear_rx_addr, + sizeof(u32), 0, + DMA_MEM_TO_DEV, 0); + if (!target->clear_rx_desc) { dev_err(&spi->dev, "cannot prepare clear_rx_desc\n"); return -ENOMEM; } - ret = dmaengine_desc_set_reuse(slv->clear_rx_desc); + ret = dmaengine_desc_set_reuse(target->clear_rx_desc); if (ret) { dev_err(&spi->dev, "cannot reuse clear_rx_desc\n"); return ret; @@ -1220,26 +1220,26 @@ static int bcm2835_spi_setup(struct spi_device *spi) { struct spi_controller *ctlr = spi->controller; struct bcm2835_spi *bs = spi_controller_get_devdata(ctlr); - struct bcm2835_spidev *slv = spi_get_ctldata(spi); + struct bcm2835_spidev *target = spi_get_ctldata(spi); struct gpio_chip *chip; int ret; u32 cs; - if (!slv) { - slv = kzalloc(ALIGN(sizeof(*slv), dma_get_cache_alignment()), + if (!target) { + target = kzalloc(ALIGN(sizeof(*target), dma_get_cache_alignment()), GFP_KERNEL); - if (!slv) + if (!target) return -ENOMEM; - spi_set_ctldata(spi, slv); + spi_set_ctldata(spi, target); - ret = bcm2835_spi_setup_dma(ctlr, spi, bs, slv); + ret = bcm2835_spi_setup_dma(ctlr, spi, bs, target); if (ret) goto err_cleanup; } /* - * Precalculate SPI slave's CS register value for ->prepare_message(): + * Precalculate SPI target's CS register value for ->prepare_message(): * The driver always uses software-controlled GPIO chip select, hence * set the hardware-controlled native chip select to an invalid value * to prevent it from interfering. @@ -1249,18 +1249,18 @@ static int bcm2835_spi_setup(struct spi_device *spi) cs |= BCM2835_SPI_CS_CPOL; if (spi->mode & SPI_CPHA) cs |= BCM2835_SPI_CS_CPHA; - slv->prepare_cs = cs; + target->prepare_cs = cs; /* - * Precalculate SPI slave's CS register value to clear RX FIFO + * Precalculate SPI target's CS register value to clear RX FIFO * in case of a TX-only DMA transfer. */ if (ctlr->dma_rx) { - slv->clear_rx_cs = cs | BCM2835_SPI_CS_TA | + target->clear_rx_cs = cs | BCM2835_SPI_CS_TA | BCM2835_SPI_CS_DMAEN | BCM2835_SPI_CS_CLEAR_RX; dma_sync_single_for_device(ctlr->dma_rx->device->dev, - slv->clear_rx_addr, + target->clear_rx_addr, sizeof(u32), DMA_TO_DEVICE); } @@ -1328,7 +1328,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) struct bcm2835_spi *bs; int err; - ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*bs)); + ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*bs)); if (!ctlr) return -ENOMEM; @@ -1360,10 +1360,12 @@ static int bcm2835_spi_probe(struct platform_device *pdev) ctlr->max_speed_hz = clk_get_rate(bs->clk) / 2; bs->irq = platform_get_irq(pdev, 0); - if (bs->irq <= 0) - return bs->irq ? bs->irq : -ENODEV; + if (bs->irq < 0) + return bs->irq; - clk_prepare_enable(bs->clk); + err = clk_prepare_enable(bs->clk); + if (err) + return err; bs->clk_hz = clk_get_rate(bs->clk); err = bcm2835_dma_init(ctlr, &pdev->dev, bs); diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index 288f7b994b36..6d2a5d9f2498 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -20,9 +20,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> +#include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/spi/spi.h> #include <linux/spinlock.h> @@ -233,8 +231,8 @@ static void bcm2835aux_spi_transfer_helper(struct bcm2835aux_spi *bs) static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id) { - struct spi_master *master = dev_id; - struct bcm2835aux_spi *bs = spi_master_get_devdata(master); + struct spi_controller *host = dev_id; + struct bcm2835aux_spi *bs = spi_controller_get_devdata(host); /* IRQ may be shared, so return if our interrupts are disabled */ if (!(bcm2835aux_rd(bs, BCM2835_AUX_SPI_CNTL1) & @@ -253,17 +251,17 @@ static irqreturn_t bcm2835aux_spi_interrupt(int irq, void *dev_id) /* and if rx_len is 0 then disable interrupts and wake up completion */ if (!bs->rx_len) { bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1]); - spi_finalize_current_transfer(master); + spi_finalize_current_transfer(host); } return IRQ_HANDLED; } -static int __bcm2835aux_spi_transfer_one_irq(struct spi_master *master, +static int __bcm2835aux_spi_transfer_one_irq(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *tfr) { - struct bcm2835aux_spi *bs = spi_master_get_devdata(master); + struct bcm2835aux_spi *bs = spi_controller_get_devdata(host); /* enable interrupts */ bcm2835aux_wr(bs, BCM2835_AUX_SPI_CNTL1, bs->cntl[1] | @@ -274,11 +272,11 @@ static int __bcm2835aux_spi_transfer_one_irq(struct spi_master *master, return 1; } -static int bcm2835aux_spi_transfer_one_irq(struct spi_master *master, +static int bcm2835aux_spi_transfer_one_irq(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *tfr) { - struct bcm2835aux_spi *bs = spi_master_get_devdata(master); + struct bcm2835aux_spi *bs = spi_controller_get_devdata(host); /* update statistics */ bs->count_transfer_irq++; @@ -296,14 +294,14 @@ static int bcm2835aux_spi_transfer_one_irq(struct spi_master *master, } /* now run the interrupt mode */ - return __bcm2835aux_spi_transfer_one_irq(master, spi, tfr); + return __bcm2835aux_spi_transfer_one_irq(host, spi, tfr); } -static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master, +static int bcm2835aux_spi_transfer_one_poll(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *tfr) { - struct bcm2835aux_spi *bs = spi_master_get_devdata(master); + struct bcm2835aux_spi *bs = spi_controller_get_devdata(host); unsigned long timeout; /* update statistics */ @@ -330,7 +328,7 @@ static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master, bs->tx_len, bs->rx_len); /* forward to interrupt handler */ bs->count_transfer_irq_after_poll++; - return __bcm2835aux_spi_transfer_one_irq(master, + return __bcm2835aux_spi_transfer_one_irq(host, spi, tfr); } } @@ -339,11 +337,11 @@ static int bcm2835aux_spi_transfer_one_poll(struct spi_master *master, return 0; } -static int bcm2835aux_spi_transfer_one(struct spi_master *master, +static int bcm2835aux_spi_transfer_one(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *tfr) { - struct bcm2835aux_spi *bs = spi_master_get_devdata(master); + struct bcm2835aux_spi *bs = spi_controller_get_devdata(host); unsigned long spi_hz, clk_hz, speed; unsigned long hz_per_byte, byte_limit; @@ -394,17 +392,17 @@ static int bcm2835aux_spi_transfer_one(struct spi_master *master, /* run in polling mode for short transfers */ if (tfr->len < byte_limit) - return bcm2835aux_spi_transfer_one_poll(master, spi, tfr); + return bcm2835aux_spi_transfer_one_poll(host, spi, tfr); /* run in interrupt mode for all others */ - return bcm2835aux_spi_transfer_one_irq(master, spi, tfr); + return bcm2835aux_spi_transfer_one_irq(host, spi, tfr); } -static int bcm2835aux_spi_prepare_message(struct spi_master *master, +static int bcm2835aux_spi_prepare_message(struct spi_controller *host, struct spi_message *msg) { struct spi_device *spi = msg->spi; - struct bcm2835aux_spi *bs = spi_master_get_devdata(master); + struct bcm2835aux_spi *bs = spi_controller_get_devdata(host); bs->cntl[0] = BCM2835_AUX_SPI_CNTL0_ENABLE | BCM2835_AUX_SPI_CNTL0_VAR_WIDTH | @@ -424,20 +422,20 @@ static int bcm2835aux_spi_prepare_message(struct spi_master *master, return 0; } -static int bcm2835aux_spi_unprepare_message(struct spi_master *master, +static int bcm2835aux_spi_unprepare_message(struct spi_controller *host, struct spi_message *msg) { - struct bcm2835aux_spi *bs = spi_master_get_devdata(master); + struct bcm2835aux_spi *bs = spi_controller_get_devdata(host); bcm2835aux_spi_reset_hw(bs); return 0; } -static void bcm2835aux_spi_handle_err(struct spi_master *master, +static void bcm2835aux_spi_handle_err(struct spi_controller *host, struct spi_message *msg) { - struct bcm2835aux_spi *bs = spi_master_get_devdata(master); + struct bcm2835aux_spi *bs = spi_controller_get_devdata(host); bcm2835aux_spi_reset_hw(bs); } @@ -475,18 +473,18 @@ static int bcm2835aux_spi_setup(struct spi_device *spi) static int bcm2835aux_spi_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *host; struct bcm2835aux_spi *bs; unsigned long clk_hz; int err; - master = devm_spi_alloc_master(&pdev->dev, sizeof(*bs)); - if (!master) + host = devm_spi_alloc_host(&pdev->dev, sizeof(*bs)); + if (!host) return -ENOMEM; - platform_set_drvdata(pdev, master); - master->mode_bits = (SPI_CPOL | SPI_CS_HIGH | SPI_NO_CS); - master->bits_per_word_mask = SPI_BPW_MASK(8); + platform_set_drvdata(pdev, host); + host->mode_bits = (SPI_CPOL | SPI_CS_HIGH | SPI_NO_CS); + host->bits_per_word_mask = SPI_BPW_MASK(8); /* even though the driver never officially supported native CS * allow a single native CS for legacy DT support purposes when * no cs-gpio is configured. @@ -498,16 +496,16 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) * * cs_delay_usec: cs is always deasserted one SCK cycle after * a spi_transfer */ - master->num_chipselect = 1; - master->setup = bcm2835aux_spi_setup; - master->transfer_one = bcm2835aux_spi_transfer_one; - master->handle_err = bcm2835aux_spi_handle_err; - master->prepare_message = bcm2835aux_spi_prepare_message; - master->unprepare_message = bcm2835aux_spi_unprepare_message; - master->dev.of_node = pdev->dev.of_node; - master->use_gpio_descriptors = true; + host->num_chipselect = 1; + host->setup = bcm2835aux_spi_setup; + host->transfer_one = bcm2835aux_spi_transfer_one; + host->handle_err = bcm2835aux_spi_handle_err; + host->prepare_message = bcm2835aux_spi_prepare_message; + host->unprepare_message = bcm2835aux_spi_unprepare_message; + host->dev.of_node = pdev->dev.of_node; + host->use_gpio_descriptors = true; - bs = spi_master_get_devdata(master); + bs = spi_controller_get_devdata(host); /* the main area */ bs->regs = devm_platform_ioremap_resource(pdev, 0); @@ -522,8 +520,8 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) } bs->irq = platform_get_irq(pdev, 0); - if (bs->irq <= 0) - return bs->irq ? bs->irq : -ENODEV; + if (bs->irq < 0) + return bs->irq; /* this also enables the HW block */ err = clk_prepare_enable(bs->clk); @@ -546,15 +544,15 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) err = devm_request_irq(&pdev->dev, bs->irq, bcm2835aux_spi_interrupt, IRQF_SHARED, - dev_name(&pdev->dev), master); + dev_name(&pdev->dev), host); if (err) { dev_err(&pdev->dev, "could not request IRQ: %d\n", err); goto out_clk_disable; } - err = spi_register_master(master); + err = spi_register_controller(host); if (err) { - dev_err(&pdev->dev, "could not register SPI master: %d\n", err); + dev_err(&pdev->dev, "could not register SPI host: %d\n", err); goto out_clk_disable; } @@ -569,12 +567,12 @@ out_clk_disable: static void bcm2835aux_spi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct bcm2835aux_spi *bs = spi_master_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(pdev); + struct bcm2835aux_spi *bs = spi_controller_get_devdata(host); bcm2835aux_debugfs_remove(bs); - spi_unregister_master(master); + spi_unregister_controller(host); bcm2835aux_spi_reset_hw(bs); diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index 9e218e143263..1ca857c2a4aa 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -149,7 +149,7 @@ static ssize_t wait_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct spi_controller *ctrl = dev_get_drvdata(dev); - struct bcm63xx_hsspi *bs = spi_master_get_devdata(ctrl); + struct bcm63xx_hsspi *bs = spi_controller_get_devdata(ctrl); return sprintf(buf, "%d\n", bs->wait_mode); } @@ -158,7 +158,7 @@ static ssize_t wait_mode_store(struct device *dev, struct device_attribute *attr const char *buf, size_t count) { struct spi_controller *ctrl = dev_get_drvdata(dev); - struct bcm63xx_hsspi *bs = spi_master_get_devdata(ctrl); + struct bcm63xx_hsspi *bs = spi_controller_get_devdata(ctrl); u32 val; if (kstrtou32(buf, 10, &val)) @@ -185,7 +185,7 @@ static ssize_t xfer_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct spi_controller *ctrl = dev_get_drvdata(dev); - struct bcm63xx_hsspi *bs = spi_master_get_devdata(ctrl); + struct bcm63xx_hsspi *bs = spi_controller_get_devdata(ctrl); return sprintf(buf, "%d\n", bs->xfer_mode); } @@ -194,7 +194,7 @@ static ssize_t xfer_mode_store(struct device *dev, struct device_attribute *attr const char *buf, size_t count) { struct spi_controller *ctrl = dev_get_drvdata(dev); - struct bcm63xx_hsspi *bs = spi_master_get_devdata(ctrl); + struct bcm63xx_hsspi *bs = spi_controller_get_devdata(ctrl); u32 val; if (kstrtou32(buf, 10, &val)) @@ -262,12 +262,12 @@ static int bcm63xx_hsspi_wait_cmd(struct bcm63xx_hsspi *bs) return rc; } -static bool bcm63xx_prepare_prepend_transfer(struct spi_master *master, +static bool bcm63xx_prepare_prepend_transfer(struct spi_controller *host, struct spi_message *msg, struct spi_transfer *t_prepend) { - struct bcm63xx_hsspi *bs = spi_master_get_devdata(master); + struct bcm63xx_hsspi *bs = spi_controller_get_devdata(host); bool tx_only = false; struct spi_transfer *t; @@ -348,7 +348,7 @@ static bool bcm63xx_prepare_prepend_transfer(struct spi_master *master, static int bcm63xx_hsspi_do_prepend_txrx(struct spi_device *spi, struct spi_transfer *t) { - struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master); + struct bcm63xx_hsspi *bs = spi_controller_get_devdata(spi->controller); unsigned int chip_select = spi_get_chipselect(spi, 0); u16 opcode = 0, val; const u8 *tx = t->tx_buf; @@ -467,7 +467,7 @@ static void bcm63xx_hsspi_set_clk(struct bcm63xx_hsspi *bs, static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t) { - struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master); + struct bcm63xx_hsspi *bs = spi_controller_get_devdata(spi->controller); unsigned int chip_select = spi_get_chipselect(spi, 0); u16 opcode = 0, val; int pending = t->len; @@ -541,7 +541,7 @@ static int bcm63xx_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t) static int bcm63xx_hsspi_setup(struct spi_device *spi) { - struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master); + struct bcm63xx_hsspi *bs = spi_controller_get_devdata(spi->controller); u32 reg; reg = __raw_readl(bs->regs + @@ -579,7 +579,7 @@ static int bcm63xx_hsspi_setup(struct spi_device *spi) static int bcm63xx_hsspi_do_dummy_cs_txrx(struct spi_device *spi, struct spi_message *msg) { - struct bcm63xx_hsspi *bs = spi_master_get_devdata(spi->master); + struct bcm63xx_hsspi *bs = spi_controller_get_devdata(spi->controller); int status = -EINVAL; int dummy_cs; bool keep_cs = false; @@ -653,10 +653,10 @@ static int bcm63xx_hsspi_do_dummy_cs_txrx(struct spi_device *spi, return status; } -static int bcm63xx_hsspi_transfer_one(struct spi_master *master, +static int bcm63xx_hsspi_transfer_one(struct spi_controller *host, struct spi_message *msg) { - struct bcm63xx_hsspi *bs = spi_master_get_devdata(master); + struct bcm63xx_hsspi *bs = spi_controller_get_devdata(host); struct spi_device *spi = msg->spi; int status = -EINVAL; bool prependable = false; @@ -665,7 +665,7 @@ static int bcm63xx_hsspi_transfer_one(struct spi_master *master, mutex_lock(&bs->msg_mutex); if (bs->xfer_mode != HSSPI_XFER_MODE_DUMMYCS) - prependable = bcm63xx_prepare_prepend_transfer(master, msg, &t_prepend); + prependable = bcm63xx_prepare_prepend_transfer(host, msg, &t_prepend); if (prependable) { status = bcm63xx_hsspi_do_prepend_txrx(spi, &t_prepend); @@ -681,7 +681,7 @@ static int bcm63xx_hsspi_transfer_one(struct spi_master *master, mutex_unlock(&bs->msg_mutex); msg->status = status; - spi_finalize_current_message(master); + spi_finalize_current_message(host); return 0; } @@ -723,7 +723,7 @@ static irqreturn_t bcm63xx_hsspi_interrupt(int irq, void *dev_id) static int bcm63xx_hsspi_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *host; struct bcm63xx_hsspi *bs; void __iomem *regs; struct device *dev = &pdev->dev; @@ -779,13 +779,13 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) } } - master = spi_alloc_master(&pdev->dev, sizeof(*bs)); - if (!master) { + host = spi_alloc_host(&pdev->dev, sizeof(*bs)); + if (!host) { ret = -ENOMEM; goto out_disable_pll_clk; } - bs = spi_master_get_devdata(master); + bs = spi_controller_get_devdata(host); bs->pdev = pdev; bs->clk = clk; bs->pll_clk = pll_clk; @@ -796,17 +796,17 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) bs->prepend_buf = devm_kzalloc(dev, HSSPI_BUFFER_LEN, GFP_KERNEL); if (!bs->prepend_buf) { ret = -ENOMEM; - goto out_put_master; + goto out_put_host; } mutex_init(&bs->bus_mutex); mutex_init(&bs->msg_mutex); init_completion(&bs->done); - master->mem_ops = &bcm63xx_hsspi_mem_ops; - master->dev.of_node = dev->of_node; + host->mem_ops = &bcm63xx_hsspi_mem_ops; + host->dev.of_node = dev->of_node; if (!dev->of_node) - master->bus_num = HSSPI_BUS_NUM; + host->bus_num = HSSPI_BUS_NUM; of_property_read_u32(dev->of_node, "num-cs", &num_cs); if (num_cs > 8) { @@ -814,18 +814,18 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) num_cs); num_cs = HSSPI_SPI_MAX_CS; } - master->num_chipselect = num_cs; - master->setup = bcm63xx_hsspi_setup; - master->transfer_one_message = bcm63xx_hsspi_transfer_one; - master->max_transfer_size = bcm63xx_hsspi_max_message_size; - master->max_message_size = bcm63xx_hsspi_max_message_size; + host->num_chipselect = num_cs; + host->setup = bcm63xx_hsspi_setup; + host->transfer_one_message = bcm63xx_hsspi_transfer_one; + host->max_transfer_size = bcm63xx_hsspi_max_message_size; + host->max_message_size = bcm63xx_hsspi_max_message_size; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_RX_DUAL | SPI_TX_DUAL; - master->bits_per_word_mask = SPI_BPW_MASK(8); - master->auto_runtime_pm = true; + host->bits_per_word_mask = SPI_BPW_MASK(8); + host->auto_runtime_pm = true; - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); /* Initialize the hardware */ __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); @@ -844,7 +844,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) pdev->name, bs); if (ret) - goto out_put_master; + goto out_put_host; } pm_runtime_enable(&pdev->dev); @@ -856,7 +856,7 @@ static int bcm63xx_hsspi_probe(struct platform_device *pdev) } /* register and we are done */ - ret = devm_spi_register_master(dev, master); + ret = devm_spi_register_controller(dev, host); if (ret) goto out_sysgroup_disable; @@ -868,8 +868,8 @@ out_sysgroup_disable: sysfs_remove_group(&pdev->dev.kobj, &bcm63xx_hsspi_group); out_pm_disable: pm_runtime_disable(&pdev->dev); -out_put_master: - spi_master_put(master); +out_put_host: + spi_controller_put(host); out_disable_pll_clk: clk_disable_unprepare(pll_clk); out_disable_clk: @@ -880,8 +880,8 @@ out_disable_clk: static void bcm63xx_hsspi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct bcm63xx_hsspi *bs = spi_master_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(pdev); + struct bcm63xx_hsspi *bs = spi_controller_get_devdata(host); /* reset the hardware and block queue progress */ __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); @@ -893,10 +893,10 @@ static void bcm63xx_hsspi_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int bcm63xx_hsspi_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct bcm63xx_hsspi *bs = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct bcm63xx_hsspi *bs = spi_controller_get_devdata(host); - spi_master_suspend(master); + spi_controller_suspend(host); clk_disable_unprepare(bs->pll_clk); clk_disable_unprepare(bs->clk); @@ -905,8 +905,8 @@ static int bcm63xx_hsspi_suspend(struct device *dev) static int bcm63xx_hsspi_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct bcm63xx_hsspi *bs = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct bcm63xx_hsspi *bs = spi_controller_get_devdata(host); int ret; ret = clk_prepare_enable(bs->clk); @@ -921,7 +921,7 @@ static int bcm63xx_hsspi_resume(struct device *dev) } } - spi_master_resume(master); + spi_controller_resume(host); return 0; } diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 07b5b71b2352..aac41bd05f98 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -186,7 +186,7 @@ static const unsigned int bcm63xx_spi_freq_table[SPI_CLK_MASK][2] = { static void bcm63xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) { - struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); + struct bcm63xx_spi *bs = spi_controller_get_devdata(spi->controller); u8 clk_cfg, reg; int i; @@ -217,7 +217,7 @@ static void bcm63xx_spi_setup_transfer(struct spi_device *spi, static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first, unsigned int num_transfers) { - struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); + struct bcm63xx_spi *bs = spi_controller_get_devdata(spi->controller); u16 msg_ctl; u16 cmd; unsigned int i, timeout = 0, prepend_len = 0, len = 0; @@ -312,10 +312,10 @@ static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *first, return 0; } -static int bcm63xx_spi_transfer_one(struct spi_master *master, +static int bcm63xx_spi_transfer_one(struct spi_controller *host, struct spi_message *m) { - struct bcm63xx_spi *bs = spi_master_get_devdata(master); + struct bcm63xx_spi *bs = spi_controller_get_devdata(host); struct spi_transfer *t, *first = NULL; struct spi_device *spi = m->spi; int status = 0; @@ -385,18 +385,18 @@ static int bcm63xx_spi_transfer_one(struct spi_master *master, } exit: m->status = status; - spi_finalize_current_message(master); + spi_finalize_current_message(host); return 0; } -/* This driver supports single master mode only. Hence +/* This driver supports single host mode only. Hence * CMD_DONE is the only interrupt we care about */ static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id) { - struct spi_master *master = (struct spi_master *)dev_id; - struct bcm63xx_spi *bs = spi_master_get_devdata(master); + struct spi_controller *host = (struct spi_controller *)dev_id; + struct bcm63xx_spi *bs = spi_controller_get_devdata(host); u8 intr; /* Read interupts and clear them immediately */ @@ -413,7 +413,7 @@ static irqreturn_t bcm63xx_spi_interrupt(int irq, void *dev_id) static size_t bcm63xx_spi_max_length(struct spi_device *spi) { - struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master); + struct bcm63xx_spi *bs = spi_controller_get_devdata(spi->controller); return bs->fifo_size; } @@ -479,7 +479,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) const unsigned long *bcm63xx_spireg; struct device *dev = &pdev->dev; int irq, bus_num; - struct spi_master *master; + struct spi_controller *host; struct clk *clk; struct bcm63xx_spi *bs; int ret; @@ -525,16 +525,16 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) if (IS_ERR(reset)) return PTR_ERR(reset); - master = spi_alloc_master(dev, sizeof(*bs)); - if (!master) { + host = spi_alloc_host(dev, sizeof(*bs)); + if (!host) { dev_err(dev, "out of memory\n"); return -ENOMEM; } - bs = spi_master_get_devdata(master); + bs = spi_controller_get_devdata(host); init_completion(&bs->done); - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); bs->pdev = pdev; bs->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &r); @@ -549,21 +549,21 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) bs->fifo_size = bs->reg_offsets[SPI_MSG_DATA_SIZE]; ret = devm_request_irq(&pdev->dev, irq, bcm63xx_spi_interrupt, 0, - pdev->name, master); + pdev->name, host); if (ret) { dev_err(dev, "unable to request irq\n"); goto out_err; } - master->dev.of_node = dev->of_node; - master->bus_num = bus_num; - master->num_chipselect = num_cs; - master->transfer_one_message = bcm63xx_spi_transfer_one; - master->mode_bits = MODEBITS; - master->bits_per_word_mask = SPI_BPW_MASK(8); - master->max_transfer_size = bcm63xx_spi_max_length; - master->max_message_size = bcm63xx_spi_max_length; - master->auto_runtime_pm = true; + host->dev.of_node = dev->of_node; + host->bus_num = bus_num; + host->num_chipselect = num_cs; + host->transfer_one_message = bcm63xx_spi_transfer_one; + host->mode_bits = MODEBITS; + host->bits_per_word_mask = SPI_BPW_MASK(8); + host->max_transfer_size = bcm63xx_spi_max_length; + host->max_message_size = bcm63xx_spi_max_length; + host->auto_runtime_pm = true; bs->msg_type_shift = bs->reg_offsets[SPI_MSG_TYPE_SHIFT]; bs->msg_ctl_width = bs->reg_offsets[SPI_MSG_CTL_WIDTH]; bs->tx_io = (u8 *)(bs->regs + bs->reg_offsets[SPI_MSG_DATA]); @@ -585,7 +585,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); /* register and we are done */ - ret = devm_spi_register_master(dev, master); + ret = devm_spi_register_controller(dev, host); if (ret) { dev_err(dev, "spi register failed\n"); goto out_pm_disable; @@ -601,14 +601,14 @@ out_pm_disable: out_clk_disable: clk_disable_unprepare(clk); out_err: - spi_master_put(master); + spi_controller_put(host); return ret; } static void bcm63xx_spi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct bcm63xx_spi *bs = spi_master_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(pdev); + struct bcm63xx_spi *bs = spi_controller_get_devdata(host); /* reset spi block */ bcm_spi_writeb(bs, 0, SPI_INT_MASK); @@ -619,10 +619,10 @@ static void bcm63xx_spi_remove(struct platform_device *pdev) static int bcm63xx_spi_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct bcm63xx_spi *bs = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct bcm63xx_spi *bs = spi_controller_get_devdata(host); - spi_master_suspend(master); + spi_controller_suspend(host); clk_disable_unprepare(bs->clk); @@ -631,15 +631,15 @@ static int bcm63xx_spi_suspend(struct device *dev) static int bcm63xx_spi_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct bcm63xx_spi *bs = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct bcm63xx_spi *bs = spi_controller_get_devdata(host); int ret; ret = clk_prepare_enable(bs->clk); if (ret) return ret; - spi_master_resume(master); + spi_controller_resume(host); return 0; } diff --git a/drivers/spi/spi-bcmbca-hsspi.c b/drivers/spi/spi-bcmbca-hsspi.c index ca1b4741e9f4..9f64afd8164e 100644 --- a/drivers/spi/spi-bcmbca-hsspi.c +++ b/drivers/spi/spi-bcmbca-hsspi.c @@ -127,7 +127,7 @@ static ssize_t wait_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct spi_controller *ctrl = dev_get_drvdata(dev); - struct bcmbca_hsspi *bs = spi_master_get_devdata(ctrl); + struct bcmbca_hsspi *bs = spi_controller_get_devdata(ctrl); return sprintf(buf, "%d\n", bs->wait_mode); } @@ -136,7 +136,7 @@ static ssize_t wait_mode_store(struct device *dev, struct device_attribute *attr const char *buf, size_t count) { struct spi_controller *ctrl = dev_get_drvdata(dev); - struct bcmbca_hsspi *bs = spi_master_get_devdata(ctrl); + struct bcmbca_hsspi *bs = spi_controller_get_devdata(ctrl); u32 val; if (kstrtou32(buf, 10, &val)) @@ -250,7 +250,7 @@ static int bcmbca_hsspi_wait_cmd(struct bcmbca_hsspi *bs, unsigned int cs) static int bcmbca_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t, struct spi_message *msg) { - struct bcmbca_hsspi *bs = spi_master_get_devdata(spi->master); + struct bcmbca_hsspi *bs = spi_controller_get_devdata(spi->controller); unsigned int chip_select = spi_get_chipselect(spi, 0); u16 opcode = 0, val; int pending = t->len; @@ -328,7 +328,7 @@ static int bcmbca_hsspi_do_txrx(struct spi_device *spi, struct spi_transfer *t, static int bcmbca_hsspi_setup(struct spi_device *spi) { - struct bcmbca_hsspi *bs = spi_master_get_devdata(spi->master); + struct bcmbca_hsspi *bs = spi_controller_get_devdata(spi->controller); u32 reg; reg = __raw_readl(bs->regs + @@ -366,10 +366,10 @@ static int bcmbca_hsspi_setup(struct spi_device *spi) return 0; } -static int bcmbca_hsspi_transfer_one(struct spi_master *master, +static int bcmbca_hsspi_transfer_one(struct spi_controller *host, struct spi_message *msg) { - struct bcmbca_hsspi *bs = spi_master_get_devdata(master); + struct bcmbca_hsspi *bs = spi_controller_get_devdata(host); struct spi_transfer *t; struct spi_device *spi = msg->spi; int status = -EINVAL; @@ -409,7 +409,7 @@ static int bcmbca_hsspi_transfer_one(struct spi_master *master, bcmbca_hsspi_set_cs(bs, spi_get_chipselect(spi, 0), false); msg->status = status; - spi_finalize_current_message(master); + spi_finalize_current_message(host); return 0; } @@ -431,7 +431,7 @@ static irqreturn_t bcmbca_hsspi_interrupt(int irq, void *dev_id) static int bcmbca_hsspi_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *host; struct bcmbca_hsspi *bs; struct resource *res_mem; void __iomem *spim_ctrl; @@ -487,13 +487,13 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev) } } - master = spi_alloc_master(&pdev->dev, sizeof(*bs)); - if (!master) { + host = spi_alloc_host(&pdev->dev, sizeof(*bs)); + if (!host) { ret = -ENOMEM; goto out_disable_pll_clk; } - bs = spi_master_get_devdata(master); + bs = spi_controller_get_devdata(host); bs->pdev = pdev; bs->clk = clk; bs->pll_clk = pll_clk; @@ -507,9 +507,9 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev) mutex_init(&bs->msg_mutex); init_completion(&bs->done); - master->dev.of_node = dev->of_node; + host->dev.of_node = dev->of_node; if (!dev->of_node) - master->bus_num = HSSPI_BUS_NUM; + host->bus_num = HSSPI_BUS_NUM; of_property_read_u32(dev->of_node, "num-cs", &num_cs); if (num_cs > 8) { @@ -517,15 +517,15 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev) num_cs); num_cs = HSSPI_SPI_MAX_CS; } - master->num_chipselect = num_cs; - master->setup = bcmbca_hsspi_setup; - master->transfer_one_message = bcmbca_hsspi_transfer_one; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | - SPI_RX_DUAL | SPI_TX_DUAL; - master->bits_per_word_mask = SPI_BPW_MASK(8); - master->auto_runtime_pm = true; + host->num_chipselect = num_cs; + host->setup = bcmbca_hsspi_setup; + host->transfer_one_message = bcmbca_hsspi_transfer_one; + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | + SPI_RX_DUAL | SPI_TX_DUAL; + host->bits_per_word_mask = SPI_BPW_MASK(8); + host->auto_runtime_pm = true; - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); /* Initialize the hardware */ __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); @@ -543,7 +543,7 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev) ret = devm_request_irq(dev, irq, bcmbca_hsspi_interrupt, IRQF_SHARED, pdev->name, bs); if (ret) - goto out_put_master; + goto out_put_host; } pm_runtime_enable(&pdev->dev); @@ -555,7 +555,7 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev) } /* register and we are done */ - ret = devm_spi_register_master(dev, master); + ret = devm_spi_register_controller(dev, host); if (ret) goto out_sysgroup_disable; @@ -567,8 +567,8 @@ out_sysgroup_disable: sysfs_remove_group(&pdev->dev.kobj, &bcmbca_hsspi_group); out_pm_disable: pm_runtime_disable(&pdev->dev); -out_put_master: - spi_master_put(master); +out_put_host: + spi_controller_put(host); out_disable_pll_clk: clk_disable_unprepare(pll_clk); out_disable_clk: @@ -578,8 +578,8 @@ out_disable_clk: static void bcmbca_hsspi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct bcmbca_hsspi *bs = spi_master_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(pdev); + struct bcmbca_hsspi *bs = spi_controller_get_devdata(host); /* reset the hardware and block queue progress */ __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); @@ -591,10 +591,10 @@ static void bcmbca_hsspi_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int bcmbca_hsspi_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct bcmbca_hsspi *bs = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct bcmbca_hsspi *bs = spi_controller_get_devdata(host); - spi_master_suspend(master); + spi_controller_suspend(host); clk_disable_unprepare(bs->pll_clk); clk_disable_unprepare(bs->clk); @@ -603,8 +603,8 @@ static int bcmbca_hsspi_suspend(struct device *dev) static int bcmbca_hsspi_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct bcmbca_hsspi *bs = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct bcmbca_hsspi *bs = spi_controller_get_devdata(host); int ret; ret = clk_prepare_enable(bs->clk); @@ -619,7 +619,7 @@ static int bcmbca_hsspi_resume(struct device *dev) } } - spi_master_resume(master); + spi_controller_resume(host); return 0; } diff --git a/drivers/spi/spi-bitbang-txrx.h b/drivers/spi/spi-bitbang-txrx.h index 2dcbe166df63..0cab48b7875b 100644 --- a/drivers/spi/spi-bitbang-txrx.h +++ b/drivers/spi/spi-bitbang-txrx.h @@ -57,7 +57,7 @@ bitbang_txrx_be_cpha0(struct spi_device *spi, for (word <<= (32 - bits); likely(bits); bits--) { /* setup MSB (to slave) on trailing edge */ - if ((flags & SPI_MASTER_NO_TX) == 0) { + if ((flags & SPI_CONTROLLER_NO_TX) == 0) { if ((word & (1 << 31)) != oldbit) { setmosi(spi, word & (1 << 31)); oldbit = word & (1 << 31); @@ -70,7 +70,7 @@ bitbang_txrx_be_cpha0(struct spi_device *spi, /* sample MSB (from slave) on leading edge */ word <<= 1; - if ((flags & SPI_MASTER_NO_RX) == 0) + if ((flags & SPI_CONTROLLER_NO_RX) == 0) word |= getmiso(spi); setsck(spi, cpol); } @@ -90,7 +90,7 @@ bitbang_txrx_be_cpha1(struct spi_device *spi, /* setup MSB (to slave) on leading edge */ setsck(spi, !cpol); - if ((flags & SPI_MASTER_NO_TX) == 0) { + if ((flags & SPI_CONTROLLER_NO_TX) == 0) { if ((word & (1 << 31)) != oldbit) { setmosi(spi, word & (1 << 31)); oldbit = word & (1 << 31); @@ -103,7 +103,7 @@ bitbang_txrx_be_cpha1(struct spi_device *spi, /* sample MSB (from slave) on trailing edge */ word <<= 1; - if ((flags & SPI_MASTER_NO_RX) == 0) + if ((flags & SPI_CONTROLLER_NO_RX) == 0) word |= getmiso(spi); } return word; @@ -122,7 +122,7 @@ bitbang_txrx_le_cpha0(struct spi_device *spi, for (; likely(bits); bits--) { /* setup LSB (to slave) on trailing edge */ - if ((flags & SPI_MASTER_NO_TX) == 0) { + if ((flags & SPI_CONTROLLER_NO_TX) == 0) { if ((word & 1) != oldbit) { setmosi(spi, word & 1); oldbit = word & 1; @@ -135,7 +135,7 @@ bitbang_txrx_le_cpha0(struct spi_device *spi, /* sample LSB (from slave) on leading edge */ word >>= 1; - if ((flags & SPI_MASTER_NO_RX) == 0) + if ((flags & SPI_CONTROLLER_NO_RX) == 0) word |= getmiso(spi) << rxbit; setsck(spi, cpol); } @@ -156,7 +156,7 @@ bitbang_txrx_le_cpha1(struct spi_device *spi, /* setup LSB (to slave) on leading edge */ setsck(spi, !cpol); - if ((flags & SPI_MASTER_NO_TX) == 0) { + if ((flags & SPI_CONTROLLER_NO_TX) == 0) { if ((word & 1) != oldbit) { setmosi(spi, word & 1); oldbit = word & 1; @@ -169,7 +169,7 @@ bitbang_txrx_le_cpha1(struct spi_device *spi, /* sample LSB (from slave) on trailing edge */ word >>= 1; - if ((flags & SPI_MASTER_NO_RX) == 0) + if ((flags & SPI_CONTROLLER_NO_RX) == 0) word |= getmiso(spi) << rxbit; } return word; diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index 27d0087f8688..ecd44016c197 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -248,7 +248,7 @@ static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) if (spi->mode & SPI_3WIRE) { unsigned flags; - flags = t->tx_buf ? SPI_MASTER_NO_RX : SPI_MASTER_NO_TX; + flags = t->tx_buf ? SPI_CONTROLLER_NO_RX : SPI_CONTROLLER_NO_TX; return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t, flags); } return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t, 0); @@ -349,11 +349,11 @@ int spi_bitbang_init(struct spi_bitbang *bitbang) /* * We only need the chipselect callback if we are actually using it. * If we just use GPIO descriptors, it is surplus. If the - * SPI_MASTER_GPIO_SS flag is set, we always need to call the + * SPI_CONTROLLER_GPIO_SS flag is set, we always need to call the * driver-specific chipselect routine. */ custom_cs = (!master->use_gpio_descriptors || - (master->flags & SPI_MASTER_GPIO_SS)); + (master->flags & SPI_CONTROLLER_GPIO_SS)); if (custom_cs && !bitbang->chipselect) return -EINVAL; @@ -371,7 +371,7 @@ int spi_bitbang_init(struct spi_bitbang *bitbang) master->transfer_one = spi_bitbang_transfer_one; /* * When using GPIO descriptors, the ->set_cs() callback doesn't even - * get called unless SPI_MASTER_GPIO_SS is set. + * get called unless SPI_CONTROLLER_GPIO_SS is set. */ if (custom_cs) master->set_cs = spi_bitbang_set_cs; diff --git a/drivers/spi/spi-butterfly.c b/drivers/spi/spi-butterfly.c index cceae816cebc..289b4454242a 100644 --- a/drivers/spi/spi-butterfly.c +++ b/drivers/spi/spi-butterfly.c @@ -178,7 +178,7 @@ static void butterfly_attach(struct parport *p) struct pardevice *pd; int status; struct butterfly *pp; - struct spi_master *master; + struct spi_controller *host; struct device *dev = p->physport->dev; struct pardev_cb butterfly_cb; @@ -189,12 +189,12 @@ static void butterfly_attach(struct parport *p) * and no way to be selective about what it binds to. */ - master = spi_alloc_master(dev, sizeof(*pp)); - if (!master) { + host = spi_alloc_host(dev, sizeof(*pp)); + if (!host) { status = -ENOMEM; goto done; } - pp = spi_master_get_devdata(master); + pp = spi_controller_get_devdata(host); /* * SPI and bitbang hookup @@ -202,10 +202,10 @@ static void butterfly_attach(struct parport *p) * use default setup(), cleanup(), and transfer() methods; and * only bother implementing mode 0. Start it later. */ - master->bus_num = 42; - master->num_chipselect = 2; + host->bus_num = 42; + host->num_chipselect = 2; - pp->bitbang.master = master; + pp->bitbang.master = host; pp->bitbang.chipselect = butterfly_chipselect; pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0; @@ -280,7 +280,7 @@ clean2: clean1: parport_unregister_device(pd); clean0: - spi_master_put(pp->bitbang.master); + spi_controller_put(host); done: pr_debug("%s: butterfly probe, fail %d\n", p->name, status); } @@ -308,7 +308,7 @@ static void butterfly_detach(struct parport *p) parport_release(pp->pd); parport_unregister_device(pp->pd); - spi_master_put(pp->bitbang.master); + spi_controller_put(pp->bitbang.master); } static struct parport_driver butterfly_driver = { diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index abf10f92415d..b50db71ac4cc 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -21,7 +21,6 @@ #include <linux/kernel.h> #include <linux/log2.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> @@ -47,6 +46,12 @@ #define CQSPI_OP_WIDTH(part) ((part).nbytes ? ilog2((part).buswidth) : 0) +enum { + CLK_QSPI_APB = 0, + CLK_QSPI_AHB, + CLK_QSPI_NUM, +}; + struct cqspi_st; struct cqspi_flash_pdata { @@ -62,8 +67,9 @@ struct cqspi_flash_pdata { struct cqspi_st { struct platform_device *pdev; - struct spi_master *master; + struct spi_controller *host; struct clk *clk; + struct clk *clks[CLK_QSPI_NUM]; unsigned int sclk; void __iomem *iobase; @@ -92,6 +98,8 @@ struct cqspi_st { bool wr_completion; bool slow_sram; bool apb_ahb_hazard; + + bool is_jh7110; /* Flag for StarFive JH7110 SoC */ }; struct cqspi_driver_platdata { @@ -100,6 +108,8 @@ struct cqspi_driver_platdata { int (*indirect_read_dma)(struct cqspi_flash_pdata *f_pdata, u_char *rxbuf, loff_t from_addr, size_t n_rx); u32 (*get_dma_status)(struct cqspi_st *cqspi); + int (*jh7110_clk_init)(struct platform_device *pdev, + struct cqspi_st *cqspi); }; /* Operation timeout value */ @@ -1369,7 +1379,7 @@ static ssize_t cqspi_read(struct cqspi_flash_pdata *f_pdata, static int cqspi_mem_process(struct spi_mem *mem, const struct spi_mem_op *op) { - struct cqspi_st *cqspi = spi_master_get_devdata(mem->spi->master); + struct cqspi_st *cqspi = spi_controller_get_devdata(mem->spi->controller); struct cqspi_flash_pdata *f_pdata; f_pdata = &cqspi->f_pdata[spi_get_chipselect(mem->spi, 0)]; @@ -1575,7 +1585,7 @@ static int cqspi_request_mmap_dma(struct cqspi_st *cqspi) static const char *cqspi_get_name(struct spi_mem *mem) { - struct cqspi_st *cqspi = spi_master_get_devdata(mem->spi->master); + struct cqspi_st *cqspi = spi_controller_get_devdata(mem->spi->controller); struct device *dev = &cqspi->pdev->dev; return devm_kasprintf(dev, GFP_KERNEL, "%s.%d", dev_name(dev), @@ -1630,31 +1640,77 @@ static int cqspi_setup_flash(struct cqspi_st *cqspi) return 0; } +static int cqspi_jh7110_clk_init(struct platform_device *pdev, struct cqspi_st *cqspi) +{ + static struct clk_bulk_data qspiclk[] = { + { .id = "apb" }, + { .id = "ahb" }, + }; + + int ret = 0; + + ret = devm_clk_bulk_get(&pdev->dev, ARRAY_SIZE(qspiclk), qspiclk); + if (ret) { + dev_err(&pdev->dev, "%s: failed to get qspi clocks\n", __func__); + return ret; + } + + cqspi->clks[CLK_QSPI_APB] = qspiclk[0].clk; + cqspi->clks[CLK_QSPI_AHB] = qspiclk[1].clk; + + ret = clk_prepare_enable(cqspi->clks[CLK_QSPI_APB]); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable CLK_QSPI_APB\n", __func__); + return ret; + } + + ret = clk_prepare_enable(cqspi->clks[CLK_QSPI_AHB]); + if (ret) { + dev_err(&pdev->dev, "%s: failed to enable CLK_QSPI_AHB\n", __func__); + goto disable_apb_clk; + } + + cqspi->is_jh7110 = true; + + return 0; + +disable_apb_clk: + clk_disable_unprepare(cqspi->clks[CLK_QSPI_APB]); + + return ret; +} + +static void cqspi_jh7110_disable_clk(struct platform_device *pdev, struct cqspi_st *cqspi) +{ + clk_disable_unprepare(cqspi->clks[CLK_QSPI_AHB]); + clk_disable_unprepare(cqspi->clks[CLK_QSPI_APB]); +} static int cqspi_probe(struct platform_device *pdev) { const struct cqspi_driver_platdata *ddata; struct reset_control *rstc, *rstc_ocp, *rstc_ref; struct device *dev = &pdev->dev; - struct spi_master *master; + struct spi_controller *host; struct resource *res_ahb; struct cqspi_st *cqspi; int ret; int irq; - master = devm_spi_alloc_master(&pdev->dev, sizeof(*cqspi)); - if (!master) { - dev_err(&pdev->dev, "spi_alloc_master failed\n"); + host = devm_spi_alloc_host(&pdev->dev, sizeof(*cqspi)); + if (!host) { + dev_err(&pdev->dev, "devm_spi_alloc_host failed\n"); return -ENOMEM; } - master->mode_bits = SPI_RX_QUAD | SPI_RX_DUAL; - master->mem_ops = &cqspi_mem_ops; - master->mem_caps = &cqspi_mem_caps; - master->dev.of_node = pdev->dev.of_node; + host->mode_bits = SPI_RX_QUAD | SPI_RX_DUAL; + host->mem_ops = &cqspi_mem_ops; + host->mem_caps = &cqspi_mem_caps; + host->dev.of_node = pdev->dev.of_node; - cqspi = spi_master_get_devdata(master); + cqspi = spi_controller_get_devdata(host); cqspi->pdev = pdev; - cqspi->master = master; + cqspi->host = host; + cqspi->is_jh7110 = false; platform_set_drvdata(pdev, cqspi); /* Obtain configuration from OF. */ @@ -1741,7 +1797,7 @@ static int cqspi_probe(struct platform_device *pdev) reset_control_deassert(rstc_ocp); cqspi->master_ref_clk_hz = clk_get_rate(cqspi->clk); - master->max_speed_hz = cqspi->master_ref_clk_hz; + host->max_speed_hz = cqspi->master_ref_clk_hz; /* write completion is supported by default */ cqspi->wr_completion = true; @@ -1752,7 +1808,7 @@ static int cqspi_probe(struct platform_device *pdev) cqspi->wr_delay = 50 * DIV_ROUND_UP(NSEC_PER_SEC, cqspi->master_ref_clk_hz); if (ddata->hwcaps_mask & CQSPI_SUPPORTS_OCTAL) - master->mode_bits |= SPI_RX_OCTAL | SPI_TX_OCTAL; + host->mode_bits |= SPI_RX_OCTAL | SPI_TX_OCTAL; if (!(ddata->quirks & CQSPI_DISABLE_DAC_MODE)) { cqspi->use_direct_mode = true; cqspi->use_direct_mode_wr = true; @@ -1766,6 +1822,12 @@ static int cqspi_probe(struct platform_device *pdev) if (ddata->quirks & CQSPI_NEEDS_APB_AHB_HAZARD_WAR) cqspi->apb_ahb_hazard = true; + if (ddata->jh7110_clk_init) { + ret = cqspi_jh7110_clk_init(pdev, cqspi); + if (ret) + goto probe_clk_failed; + } + if (of_device_is_compatible(pdev->dev.of_node, "xlnx,versal-ospi-1.0")) { ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); @@ -1786,7 +1848,7 @@ static int cqspi_probe(struct platform_device *pdev) cqspi->current_cs = -1; cqspi->sclk = 0; - master->num_chipselect = cqspi->num_chipselect; + host->num_chipselect = cqspi->num_chipselect; ret = cqspi_setup_flash(cqspi); if (ret) { @@ -1800,7 +1862,7 @@ static int cqspi_probe(struct platform_device *pdev) goto probe_setup_failed; } - ret = spi_register_master(master); + ret = spi_register_controller(host); if (ret) { dev_err(&pdev->dev, "failed to register SPI ctlr %d\n", ret); goto probe_setup_failed; @@ -1822,7 +1884,7 @@ static void cqspi_remove(struct platform_device *pdev) { struct cqspi_st *cqspi = platform_get_drvdata(pdev); - spi_unregister_master(cqspi->master); + spi_unregister_controller(cqspi->host); cqspi_controller_enable(cqspi, 0); if (cqspi->rx_chan) @@ -1830,6 +1892,9 @@ static void cqspi_remove(struct platform_device *pdev) clk_disable_unprepare(cqspi->clk); + if (cqspi->is_jh7110) + cqspi_jh7110_disable_clk(pdev, cqspi); + pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); } @@ -1837,10 +1902,10 @@ static void cqspi_remove(struct platform_device *pdev) static int cqspi_suspend(struct device *dev) { struct cqspi_st *cqspi = dev_get_drvdata(dev); - struct spi_master *master = dev_get_drvdata(dev); + struct spi_controller *host = dev_get_drvdata(dev); int ret; - ret = spi_master_suspend(master); + ret = spi_controller_suspend(host); cqspi_controller_enable(cqspi, 0); clk_disable_unprepare(cqspi->clk); @@ -1851,7 +1916,7 @@ static int cqspi_suspend(struct device *dev) static int cqspi_resume(struct device *dev) { struct cqspi_st *cqspi = dev_get_drvdata(dev); - struct spi_master *master = dev_get_drvdata(dev); + struct spi_controller *host = dev_get_drvdata(dev); clk_prepare_enable(cqspi->clk); cqspi_wait_idle(cqspi); @@ -1860,7 +1925,7 @@ static int cqspi_resume(struct device *dev) cqspi->current_cs = -1; cqspi->sclk = 0; - return spi_master_resume(master); + return spi_controller_resume(host); } static DEFINE_SIMPLE_DEV_PM_OPS(cqspi_dev_pm_ops, cqspi_suspend, cqspi_resume); @@ -1897,6 +1962,7 @@ static const struct cqspi_driver_platdata versal_ospi = { static const struct cqspi_driver_platdata jh7110_qspi = { .quirks = CQSPI_DISABLE_DAC_MODE, + .jh7110_clk_init = cqspi_jh7110_clk_init, }; static const struct cqspi_driver_platdata pensando_cdns_qspi = { diff --git a/drivers/spi/spi-cadence-xspi.c b/drivers/spi/spi-cadence-xspi.c index ce4a3145f065..b7e04b03be58 100644 --- a/drivers/spi/spi-cadence-xspi.c +++ b/drivers/spi/spi-cadence-xspi.c @@ -11,7 +11,6 @@ #include <linux/iopoll.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> @@ -420,7 +419,7 @@ static int cdns_xspi_mem_op_execute(struct spi_mem *mem, const struct spi_mem_op *op) { struct cdns_xspi_dev *cdns_xspi = - spi_master_get_devdata(mem->spi->master); + spi_controller_get_devdata(mem->spi->controller); int ret = 0; ret = cdns_xspi_mem_op(cdns_xspi, mem, op); @@ -431,7 +430,7 @@ static int cdns_xspi_mem_op_execute(struct spi_mem *mem, static int cdns_xspi_adjust_mem_op_size(struct spi_mem *mem, struct spi_mem_op *op) { struct cdns_xspi_dev *cdns_xspi = - spi_master_get_devdata(mem->spi->master); + spi_controller_get_devdata(mem->spi->controller); op->data.nbytes = clamp_val(op->data.nbytes, 0, cdns_xspi->sdmasize); @@ -528,26 +527,26 @@ static void cdns_xspi_print_phy_config(struct cdns_xspi_dev *cdns_xspi) static int cdns_xspi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct spi_master *master = NULL; + struct spi_controller *host = NULL; struct cdns_xspi_dev *cdns_xspi = NULL; struct resource *res; int ret; - master = devm_spi_alloc_master(dev, sizeof(*cdns_xspi)); - if (!master) + host = devm_spi_alloc_host(dev, sizeof(*cdns_xspi)); + if (!host) return -ENOMEM; - master->mode_bits = SPI_3WIRE | SPI_TX_DUAL | SPI_TX_QUAD | + host->mode_bits = SPI_3WIRE | SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_OCTAL | SPI_RX_OCTAL | SPI_MODE_0 | SPI_MODE_3; - master->mem_ops = &cadence_xspi_mem_ops; - master->dev.of_node = pdev->dev.of_node; - master->bus_num = -1; + host->mem_ops = &cadence_xspi_mem_ops; + host->dev.of_node = pdev->dev.of_node; + host->bus_num = -1; - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); - cdns_xspi = spi_master_get_devdata(master); + cdns_xspi = spi_controller_get_devdata(host); cdns_xspi->pdev = pdev; cdns_xspi->dev = &pdev->dev; cdns_xspi->cur_cs = 0; @@ -597,15 +596,15 @@ static int cdns_xspi_probe(struct platform_device *pdev) return ret; } - master->num_chipselect = 1 << cdns_xspi->hw_num_banks; + host->num_chipselect = 1 << cdns_xspi->hw_num_banks; - ret = devm_spi_register_master(dev, master); + ret = devm_spi_register_controller(dev, host); if (ret) { - dev_err(dev, "Failed to register SPI master\n"); + dev_err(dev, "Failed to register SPI host\n"); return ret; } - dev_info(dev, "Successfully registered SPI master\n"); + dev_info(dev, "Successfully registered SPI host\n"); return 0; } diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index de8fe3c5becb..12c940ba074a 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Cadence SPI controller driver (master and slave mode) + * Cadence SPI controller driver (host and target mode) * * Copyright (C) 2008 - 2014 Xilinx, Inc. * @@ -59,10 +59,10 @@ CDNS_SPI_CR_BAUD_DIV_4) /* - * SPI Configuration Register - Baud rate and slave select + * SPI Configuration Register - Baud rate and target select * * These are the values used in the calculation of baud rate divisor and - * setting the slave select. + * setting the target select. */ #define CDNS_SPI_BAUD_DIV_MAX 7 /* Baud rate divisor maximum */ @@ -141,20 +141,20 @@ static inline void cdns_spi_write(struct cdns_spi *xspi, u32 offset, u32 val) /** * cdns_spi_init_hw - Initialize the hardware and configure the SPI controller * @xspi: Pointer to the cdns_spi structure - * @is_slave: Flag to indicate slave or master mode - * * On reset the SPI controller is configured to slave or master mode. - * In master mode baud rate divisor is set to 4, threshold value for TX FIFO + * @is_target: Flag to indicate target or host mode + * * On reset the SPI controller is configured to target or host mode. + * In host mode baud rate divisor is set to 4, threshold value for TX FIFO * not full interrupt is set to 1 and size of the word to be transferred as 8 bit. * * This function initializes the SPI controller to disable and clear all the - * interrupts, enable manual slave select and manual start, deselect all the + * interrupts, enable manual target select and manual start, deselect all the * chip select lines, and enable the SPI controller. */ -static void cdns_spi_init_hw(struct cdns_spi *xspi, bool is_slave) +static void cdns_spi_init_hw(struct cdns_spi *xspi, bool is_target) { u32 ctrl_reg = 0; - if (!is_slave) + if (!is_target) ctrl_reg |= CDNS_SPI_CR_DEFAULT; if (xspi->is_decoded_cs) @@ -185,10 +185,10 @@ static void cdns_spi_chipselect(struct spi_device *spi, bool is_high) ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR); if (is_high) { - /* Deselect the slave */ + /* Deselect the target */ ctrl_reg |= CDNS_SPI_CR_SSCTRL; } else { - /* Select the slave */ + /* Select the target */ ctrl_reg &= ~CDNS_SPI_CR_SSCTRL; if (!(xspi->is_decoded_cs)) ctrl_reg |= ((~(CDNS_SPI_SS0 << spi_get_chipselect(spi, 0))) << @@ -227,7 +227,7 @@ static void cdns_spi_config_clock_mode(struct spi_device *spi) /* * Just writing the CR register does not seem to apply the clock * setting changes. This is problematic when changing the clock - * polarity as it will cause the SPI slave to see spurious clock + * polarity as it will cause the SPI target to see spurious clock * transitions. To workaround the issue toggle the ER register. */ cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE); @@ -317,12 +317,6 @@ static void cdns_spi_process_fifo(struct cdns_spi *xspi, int ntx, int nrx) xspi->rx_bytes -= nrx; while (ntx || nrx) { - /* When xspi in busy condition, bytes may send failed, - * then spi control did't work thoroughly, add one byte delay - */ - if (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL) - udelay(10); - if (ntx) { if (xspi->txbuf) cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++); @@ -392,6 +386,11 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id) if (xspi->tx_bytes) { cdns_spi_process_fifo(xspi, trans_cnt, trans_cnt); } else { + /* Fixed delay due to controller limitation with + * RX_NEMPTY incorrect status + * Xilinx AR:65885 contains more details + */ + udelay(10); cdns_spi_process_fifo(xspi, 0, trans_cnt); cdns_spi_write(xspi, CDNS_SPI_IDR, CDNS_SPI_IXR_DEFAULT); @@ -406,7 +405,7 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id) static int cdns_prepare_message(struct spi_controller *ctlr, struct spi_message *msg) { - if (!spi_controller_is_slave(ctlr)) + if (!spi_controller_is_target(ctlr)) cdns_spi_config_clock_mode(msg->spi); return 0; } @@ -418,9 +417,9 @@ static int cdns_prepare_message(struct spi_controller *ctlr, * @transfer: Pointer to the spi_transfer structure which provides * information about next transfer parameters * - * This function in master mode fills the TX FIFO, starts the SPI transfer and + * This function in host mode fills the TX FIFO, starts the SPI transfer and * returns a positive transfer count so that core will wait for completion. - * This function in slave mode fills the TX FIFO and wait for transfer trigger. + * This function in target mode fills the TX FIFO and wait for transfer trigger. * * Return: Number of bytes transferred in the last transfer */ @@ -435,16 +434,22 @@ static int cdns_transfer_one(struct spi_controller *ctlr, xspi->tx_bytes = transfer->len; xspi->rx_bytes = transfer->len; - if (!spi_controller_is_slave(ctlr)) { + if (!spi_controller_is_target(ctlr)) { cdns_spi_setup_transfer(spi, transfer); } else { /* Set TX empty threshold to half of FIFO depth - * only if TX bytes are more than half FIFO depth. + * only if TX bytes are more than FIFO depth. */ if (xspi->tx_bytes > xspi->tx_fifo_depth) cdns_spi_write(xspi, CDNS_SPI_THLD, xspi->tx_fifo_depth >> 1); } + /* When xspi in busy condition, bytes may send failed, + * then spi control didn't work thoroughly, add one byte delay + */ + if (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL) + udelay(10); + cdns_spi_process_fifo(xspi, xspi->tx_fifo_depth, 0); spi_transfer_delay_exec(transfer); @@ -457,7 +462,7 @@ static int cdns_transfer_one(struct spi_controller *ctlr, * @ctlr: Pointer to the spi_controller structure which provides * information about the controller. * - * This function enables SPI master controller. + * This function enables SPI host controller. * * Return: 0 always */ @@ -475,7 +480,7 @@ static int cdns_prepare_transfer_hardware(struct spi_controller *ctlr) * @ctlr: Pointer to the spi_controller structure which provides * information about the controller. * - * This function disables the SPI master controller when no slave selected. + * This function disables the SPI host controller when no target selected. * This function flush out if any pending data in FIFO. * * Return: 0 always @@ -486,15 +491,15 @@ static int cdns_unprepare_transfer_hardware(struct spi_controller *ctlr) u32 ctrl_reg; unsigned int cnt = xspi->tx_fifo_depth; - if (spi_controller_is_slave(ctlr)) { + if (spi_controller_is_target(ctlr)) { while (cnt--) cdns_spi_read(xspi, CDNS_SPI_RXD); } - /* Disable the SPI if slave is deselected */ + /* Disable the SPI if target is deselected */ ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR); ctrl_reg = (ctrl_reg & CDNS_SPI_CR_SSCTRL) >> CDNS_SPI_SS_SHIFT; - if (ctrl_reg == CDNS_SPI_NOSS || spi_controller_is_slave(ctlr)) + if (ctrl_reg == CDNS_SPI_NOSS || spi_controller_is_target(ctlr)) cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE); /* Reset to default */ @@ -521,14 +526,14 @@ static void cdns_spi_detect_fifo_depth(struct cdns_spi *xspi) } /** - * cdns_slave_abort - Abort slave transfer + * cdns_target_abort - Abort target transfer * @ctlr: Pointer to the spi_controller structure * - * This function abort slave transfer if there any transfer timeout. + * This function abort target transfer if there any transfer timeout. * * Return: 0 always */ -static int cdns_slave_abort(struct spi_controller *ctlr) +static int cdns_target_abort(struct spi_controller *ctlr) { struct cdns_spi *xspi = spi_controller_get_devdata(ctlr); u32 intr_status; @@ -555,13 +560,13 @@ static int cdns_spi_probe(struct platform_device *pdev) struct spi_controller *ctlr; struct cdns_spi *xspi; u32 num_cs; - bool slave; + bool target; - slave = of_property_read_bool(pdev->dev.of_node, "spi-slave"); - if (slave) - ctlr = spi_alloc_slave(&pdev->dev, sizeof(*xspi)); + target = of_property_read_bool(pdev->dev.of_node, "spi-slave"); + if (target) + ctlr = spi_alloc_target(&pdev->dev, sizeof(*xspi)); else - ctlr = spi_alloc_master(&pdev->dev, sizeof(*xspi)); + ctlr = spi_alloc_host(&pdev->dev, sizeof(*xspi)); if (!ctlr) return -ENOMEM; @@ -589,7 +594,7 @@ static int cdns_spi_probe(struct platform_device *pdev) goto remove_ctlr; } - if (!spi_controller_is_slave(ctlr)) { + if (!spi_controller_is_target(ctlr)) { xspi->ref_clk = devm_clk_get(&pdev->dev, "ref_clk"); if (IS_ERR(xspi->ref_clk)) { dev_err(&pdev->dev, "ref_clk clock not found.\n"); @@ -624,11 +629,11 @@ static int cdns_spi_probe(struct platform_device *pdev) cdns_spi_detect_fifo_depth(xspi); /* SPI controller initializations */ - cdns_spi_init_hw(xspi, spi_controller_is_slave(ctlr)); + cdns_spi_init_hw(xspi, spi_controller_is_target(ctlr)); irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - ret = -ENXIO; + if (irq < 0) { + ret = irq; goto clk_dis_all; } @@ -648,7 +653,7 @@ static int cdns_spi_probe(struct platform_device *pdev) ctlr->mode_bits = SPI_CPOL | SPI_CPHA; ctlr->bits_per_word_mask = SPI_BPW_MASK(8); - if (!spi_controller_is_slave(ctlr)) { + if (!spi_controller_is_target(ctlr)) { ctlr->mode_bits |= SPI_CS_HIGH; ctlr->set_cs = cdns_spi_chipselect; ctlr->auto_runtime_pm = true; @@ -660,7 +665,7 @@ static int cdns_spi_probe(struct platform_device *pdev) pm_runtime_put_autosuspend(&pdev->dev); } else { ctlr->mode_bits |= SPI_NO_CS; - ctlr->slave_abort = cdns_slave_abort; + ctlr->target_abort = cdns_target_abort; } ret = spi_register_controller(ctlr); if (ret) { @@ -671,7 +676,7 @@ static int cdns_spi_probe(struct platform_device *pdev) return ret; clk_dis_all: - if (!spi_controller_is_slave(ctlr)) { + if (!spi_controller_is_target(ctlr)) { pm_runtime_set_suspended(&pdev->dev); pm_runtime_disable(&pdev->dev); clk_disable_unprepare(xspi->ref_clk); @@ -690,8 +695,6 @@ remove_ctlr: * This function is called if a device is physically removed from the system or * if the driver module is being unloaded. It frees all resources allocated to * the device. - * - * Return: 0 on success and error value on error */ static void cdns_spi_remove(struct platform_device *pdev) { @@ -737,7 +740,7 @@ static int __maybe_unused cdns_spi_resume(struct device *dev) struct spi_controller *ctlr = dev_get_drvdata(dev); struct cdns_spi *xspi = spi_controller_get_devdata(ctlr); - cdns_spi_init_hw(xspi, spi_controller_is_slave(ctlr)); + cdns_spi_init_hw(xspi, spi_controller_is_target(ctlr)); return spi_controller_resume(ctlr); } diff --git a/drivers/spi/spi-cavium-octeon.c b/drivers/spi/spi-cavium-octeon.c index 58060be33106..4511c3b31223 100644 --- a/drivers/spi/spi-cavium-octeon.c +++ b/drivers/spi/spi-cavium-octeon.c @@ -19,15 +19,15 @@ static int octeon_spi_probe(struct platform_device *pdev) { void __iomem *reg_base; - struct spi_master *master; + struct spi_controller *host; struct octeon_spi *p; int err = -ENOENT; - master = spi_alloc_master(&pdev->dev, sizeof(struct octeon_spi)); - if (!master) + host = spi_alloc_host(&pdev->dev, sizeof(struct octeon_spi)); + if (!host) return -ENOMEM; - p = spi_master_get_devdata(master); - platform_set_drvdata(pdev, master); + p = spi_controller_get_devdata(host); + platform_set_drvdata(pdev, host); reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg_base)) { @@ -43,21 +43,21 @@ static int octeon_spi_probe(struct platform_device *pdev) p->regs.tx = 0x10; p->regs.data = 0x80; - master->num_chipselect = 4; - master->mode_bits = SPI_CPHA | + host->num_chipselect = 4; + host->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST | SPI_3WIRE; - master->transfer_one_message = octeon_spi_transfer_one_message; - master->bits_per_word_mask = SPI_BPW_MASK(8); - master->max_speed_hz = OCTEON_SPI_MAX_CLOCK_HZ; + host->transfer_one_message = octeon_spi_transfer_one_message; + host->bits_per_word_mask = SPI_BPW_MASK(8); + host->max_speed_hz = OCTEON_SPI_MAX_CLOCK_HZ; - master->dev.of_node = pdev->dev.of_node; - err = devm_spi_register_master(&pdev->dev, master); + host->dev.of_node = pdev->dev.of_node; + err = devm_spi_register_controller(&pdev->dev, host); if (err) { - dev_err(&pdev->dev, "register master failed: %d\n", err); + dev_err(&pdev->dev, "register host failed: %d\n", err); goto fail; } @@ -65,14 +65,14 @@ static int octeon_spi_probe(struct platform_device *pdev) return 0; fail: - spi_master_put(master); + spi_controller_put(host); return err; } static void octeon_spi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct octeon_spi *p = spi_master_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(pdev); + struct octeon_spi *p = spi_controller_get_devdata(host); /* Clear the CSENA* and put everything in a known state. */ writeq(0, p->register_base + OCTEON_SPI_CFG(p)); diff --git a/drivers/spi/spi-cavium-thunderx.c b/drivers/spi/spi-cavium-thunderx.c index 60c0d6934654..f7c378a5f1bc 100644 --- a/drivers/spi/spi-cavium-thunderx.c +++ b/drivers/spi/spi-cavium-thunderx.c @@ -20,15 +20,15 @@ static int thunderx_spi_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct device *dev = &pdev->dev; - struct spi_master *master; + struct spi_controller *host; struct octeon_spi *p; int ret; - master = spi_alloc_master(dev, sizeof(struct octeon_spi)); - if (!master) + host = spi_alloc_host(dev, sizeof(struct octeon_spi)); + if (!host) return -ENOMEM; - p = spi_master_get_devdata(master); + p = spi_controller_get_devdata(host); ret = pcim_enable_device(pdev); if (ret) @@ -64,18 +64,18 @@ static int thunderx_spi_probe(struct pci_dev *pdev, p->sys_freq = SYS_FREQ_DEFAULT; dev_info(dev, "Set system clock to %u\n", p->sys_freq); - master->flags = SPI_MASTER_HALF_DUPLEX; - master->num_chipselect = 4; - master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | + host->flags = SPI_CONTROLLER_HALF_DUPLEX; + host->num_chipselect = 4; + host->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST | SPI_3WIRE; - master->transfer_one_message = octeon_spi_transfer_one_message; - master->bits_per_word_mask = SPI_BPW_MASK(8); - master->max_speed_hz = OCTEON_SPI_MAX_CLOCK_HZ; - master->dev.of_node = pdev->dev.of_node; + host->transfer_one_message = octeon_spi_transfer_one_message; + host->bits_per_word_mask = SPI_BPW_MASK(8); + host->max_speed_hz = OCTEON_SPI_MAX_CLOCK_HZ; + host->dev.of_node = pdev->dev.of_node; - pci_set_drvdata(pdev, master); + pci_set_drvdata(pdev, host); - ret = devm_spi_register_master(dev, master); + ret = devm_spi_register_controller(dev, host); if (ret) goto error; @@ -84,16 +84,16 @@ static int thunderx_spi_probe(struct pci_dev *pdev, error: clk_disable_unprepare(p->clk); pci_release_regions(pdev); - spi_master_put(master); + spi_controller_put(host); return ret; } static void thunderx_spi_remove(struct pci_dev *pdev) { - struct spi_master *master = pci_get_drvdata(pdev); + struct spi_controller *host = pci_get_drvdata(pdev); struct octeon_spi *p; - p = spi_master_get_devdata(master); + p = spi_controller_get_devdata(host); if (!p) return; diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c index c005ed26a3e1..5552ccd716fc 100644 --- a/drivers/spi/spi-clps711x.c +++ b/drivers/spi/spi-clps711x.c @@ -33,10 +33,10 @@ struct spi_clps711x_data { int len; }; -static int spi_clps711x_prepare_message(struct spi_master *master, +static int spi_clps711x_prepare_message(struct spi_controller *host, struct spi_message *msg) { - struct spi_clps711x_data *hw = spi_master_get_devdata(master); + struct spi_clps711x_data *hw = spi_controller_get_devdata(host); struct spi_device *spi = msg->spi; /* Setup mode for transfer */ @@ -45,11 +45,11 @@ static int spi_clps711x_prepare_message(struct spi_master *master, SYSCON3_ADCCKNSEN : 0); } -static int spi_clps711x_transfer_one(struct spi_master *master, +static int spi_clps711x_transfer_one(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { - struct spi_clps711x_data *hw = spi_master_get_devdata(master); + struct spi_clps711x_data *hw = spi_controller_get_devdata(host); u8 data; clk_set_rate(hw->spi_clk, xfer->speed_hz ? : spi->max_speed_hz); @@ -68,8 +68,8 @@ static int spi_clps711x_transfer_one(struct spi_master *master, static irqreturn_t spi_clps711x_isr(int irq, void *dev_id) { - struct spi_master *master = dev_id; - struct spi_clps711x_data *hw = spi_master_get_devdata(master); + struct spi_controller *host = dev_id; + struct spi_clps711x_data *hw = spi_controller_get_devdata(host); u8 data; /* Handle RX */ @@ -83,7 +83,7 @@ static irqreturn_t spi_clps711x_isr(int irq, void *dev_id) writel(data | SYNCIO_FRMLEN(hw->bpw) | SYNCIO_TXFRMEN, hw->syncio); } else - spi_finalize_current_transfer(master); + spi_finalize_current_transfer(host); return IRQ_HANDLED; } @@ -92,26 +92,26 @@ static int spi_clps711x_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct spi_clps711x_data *hw; - struct spi_master *master; + struct spi_controller *host; int irq, ret; irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; - master = spi_alloc_master(&pdev->dev, sizeof(*hw)); - if (!master) + host = spi_alloc_host(&pdev->dev, sizeof(*hw)); + if (!host) return -ENOMEM; - master->use_gpio_descriptors = true; - master->bus_num = -1; - master->mode_bits = SPI_CPHA | SPI_CS_HIGH; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 8); - master->dev.of_node = pdev->dev.of_node; - master->prepare_message = spi_clps711x_prepare_message; - master->transfer_one = spi_clps711x_transfer_one; + host->use_gpio_descriptors = true; + host->bus_num = -1; + host->mode_bits = SPI_CPHA | SPI_CS_HIGH; + host->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 8); + host->dev.of_node = pdev->dev.of_node; + host->prepare_message = spi_clps711x_prepare_message; + host->transfer_one = spi_clps711x_transfer_one; - hw = spi_master_get_devdata(master); + hw = spi_controller_get_devdata(host); hw->spi_clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(hw->spi_clk)) { @@ -138,16 +138,16 @@ static int spi_clps711x_probe(struct platform_device *pdev) readl(hw->syncio); ret = devm_request_irq(&pdev->dev, irq, spi_clps711x_isr, 0, - dev_name(&pdev->dev), master); + dev_name(&pdev->dev), host); if (ret) goto err_out; - ret = devm_spi_register_master(&pdev->dev, master); + ret = devm_spi_register_controller(&pdev->dev, host); if (!ret) return 0; err_out: - spi_master_put(master); + spi_controller_put(host); return ret; } diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index b1bd8a6b5bf9..f0b630fe16c3 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -286,7 +286,7 @@ static void mcfqspi_transfer_msg16(struct mcfqspi *mcfqspi, unsigned count, static void mcfqspi_set_cs(struct spi_device *spi, bool enable) { - struct mcfqspi *mcfqspi = spi_master_get_devdata(spi->master); + struct mcfqspi *mcfqspi = spi_controller_get_devdata(spi->controller); bool cs_high = spi->mode & SPI_CS_HIGH; if (enable) @@ -295,11 +295,11 @@ static void mcfqspi_set_cs(struct spi_device *spi, bool enable) mcfqspi_cs_deselect(mcfqspi, spi_get_chipselect(spi, 0), cs_high); } -static int mcfqspi_transfer_one(struct spi_master *master, +static int mcfqspi_transfer_one(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *t) { - struct mcfqspi *mcfqspi = spi_master_get_devdata(master); + struct mcfqspi *mcfqspi = spi_controller_get_devdata(host); u16 qmr = MCFQSPI_QMR_MSTR; qmr |= t->bits_per_word << 10; @@ -323,7 +323,7 @@ static int mcfqspi_transfer_one(struct spi_master *master, static int mcfqspi_setup(struct spi_device *spi) { - mcfqspi_cs_deselect(spi_master_get_devdata(spi->master), + mcfqspi_cs_deselect(spi_controller_get_devdata(spi->controller), spi_get_chipselect(spi, 0), spi->mode & SPI_CS_HIGH); dev_dbg(&spi->dev, @@ -337,7 +337,7 @@ static int mcfqspi_setup(struct spi_device *spi) static int mcfqspi_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *host; struct mcfqspi *mcfqspi; struct mcfqspi_platform_data *pdata; int status; @@ -353,13 +353,13 @@ static int mcfqspi_probe(struct platform_device *pdev) return -EINVAL; } - master = spi_alloc_master(&pdev->dev, sizeof(*mcfqspi)); - if (master == NULL) { - dev_dbg(&pdev->dev, "spi_alloc_master failed\n"); + host = spi_alloc_host(&pdev->dev, sizeof(*mcfqspi)); + if (host == NULL) { + dev_dbg(&pdev->dev, "spi_alloc_host failed\n"); return -ENOMEM; } - mcfqspi = spi_master_get_devdata(master); + mcfqspi = spi_controller_get_devdata(host); mcfqspi->iobase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mcfqspi->iobase)) { @@ -381,53 +381,50 @@ static int mcfqspi_probe(struct platform_device *pdev) goto fail0; } - mcfqspi->clk = devm_clk_get(&pdev->dev, "qspi_clk"); + mcfqspi->clk = devm_clk_get_enabled(&pdev->dev, "qspi_clk"); if (IS_ERR(mcfqspi->clk)) { dev_dbg(&pdev->dev, "clk_get failed\n"); status = PTR_ERR(mcfqspi->clk); goto fail0; } - clk_prepare_enable(mcfqspi->clk); - master->bus_num = pdata->bus_num; - master->num_chipselect = pdata->num_chipselect; + host->bus_num = pdata->bus_num; + host->num_chipselect = pdata->num_chipselect; mcfqspi->cs_control = pdata->cs_control; status = mcfqspi_cs_setup(mcfqspi); if (status) { dev_dbg(&pdev->dev, "error initializing cs_control\n"); - goto fail1; + goto fail0; } init_waitqueue_head(&mcfqspi->waitq); - master->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16); - master->setup = mcfqspi_setup; - master->set_cs = mcfqspi_set_cs; - master->transfer_one = mcfqspi_transfer_one; - master->auto_runtime_pm = true; + host->mode_bits = SPI_CS_HIGH | SPI_CPOL | SPI_CPHA; + host->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 16); + host->setup = mcfqspi_setup; + host->set_cs = mcfqspi_set_cs; + host->transfer_one = mcfqspi_transfer_one; + host->auto_runtime_pm = true; - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); pm_runtime_enable(&pdev->dev); - status = devm_spi_register_master(&pdev->dev, master); + status = devm_spi_register_controller(&pdev->dev, host); if (status) { - dev_dbg(&pdev->dev, "spi_register_master failed\n"); - goto fail2; + dev_dbg(&pdev->dev, "devm_spi_register_controller failed\n"); + goto fail1; } dev_info(&pdev->dev, "Coldfire QSPI bus driver\n"); return 0; -fail2: +fail1: pm_runtime_disable(&pdev->dev); mcfqspi_cs_teardown(mcfqspi); -fail1: - clk_disable_unprepare(mcfqspi->clk); fail0: - spi_master_put(master); + spi_controller_put(host); dev_dbg(&pdev->dev, "Coldfire QSPI probe failed\n"); @@ -436,8 +433,8 @@ fail0: static void mcfqspi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct mcfqspi *mcfqspi = spi_master_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(pdev); + struct mcfqspi *mcfqspi = spi_controller_get_devdata(host); pm_runtime_disable(&pdev->dev); /* disable the hardware (set the baud rate to 0) */ @@ -450,11 +447,11 @@ static void mcfqspi_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int mcfqspi_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct mcfqspi *mcfqspi = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct mcfqspi *mcfqspi = spi_controller_get_devdata(host); int ret; - ret = spi_master_suspend(master); + ret = spi_controller_suspend(host); if (ret) return ret; @@ -465,20 +462,20 @@ static int mcfqspi_suspend(struct device *dev) static int mcfqspi_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct mcfqspi *mcfqspi = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct mcfqspi *mcfqspi = spi_controller_get_devdata(host); clk_enable(mcfqspi->clk); - return spi_master_resume(master); + return spi_controller_resume(host); } #endif #ifdef CONFIG_PM static int mcfqspi_runtime_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct mcfqspi *mcfqspi = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct mcfqspi *mcfqspi = spi_controller_get_devdata(host); clk_disable(mcfqspi->clk); @@ -487,8 +484,8 @@ static int mcfqspi_runtime_suspend(struct device *dev) static int mcfqspi_runtime_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct mcfqspi *mcfqspi = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct mcfqspi *mcfqspi = spi_controller_get_devdata(host); clk_enable(mcfqspi->clk); diff --git a/drivers/spi/spi-cs42l43.c b/drivers/spi/spi-cs42l43.c new file mode 100644 index 000000000000..453a9b37ce78 --- /dev/null +++ b/drivers/spi/spi-cs42l43.c @@ -0,0 +1,284 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// CS42L43 SPI Controller Driver +// +// Copyright (C) 2022-2023 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. + +#include <linux/bits.h> +#include <linux/bitfield.h> +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/mfd/cs42l43.h> +#include <linux/mfd/cs42l43-regs.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/spi/spi.h> +#include <linux/units.h> + +#define CS42L43_FIFO_SIZE 16 +#define CS42L43_SPI_ROOT_HZ (40 * HZ_PER_MHZ) +#define CS42L43_SPI_MAX_LENGTH 65532 + +enum cs42l43_spi_cmd { + CS42L43_WRITE, + CS42L43_READ +}; + +struct cs42l43_spi { + struct device *dev; + struct regmap *regmap; + struct spi_controller *ctlr; +}; + +static const unsigned int cs42l43_clock_divs[] = { + 2, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30 +}; + +static int cs42l43_spi_tx(struct regmap *regmap, const u8 *buf, unsigned int len) +{ + const u8 *end = buf + len; + u32 val = 0; + int ret; + + while (buf < end) { + const u8 *block = min(buf + CS42L43_FIFO_SIZE, end); + + while (buf < block) { + const u8 *word = min(buf + sizeof(u32), block); + int pad = (buf + sizeof(u32)) - word; + + while (buf < word) { + val >>= BITS_PER_BYTE; + val |= FIELD_PREP(GENMASK(31, 24), *buf); + + buf++; + } + + val >>= pad * BITS_PER_BYTE; + + regmap_write(regmap, CS42L43_TX_DATA, val); + } + + regmap_write(regmap, CS42L43_TRAN_CONFIG8, CS42L43_SPI_TX_DONE_MASK); + + ret = regmap_read_poll_timeout(regmap, CS42L43_TRAN_STATUS1, + val, (val & CS42L43_SPI_TX_REQUEST_MASK), + 1000, 5000); + if (ret) + return ret; + } + + return 0; +} + +static int cs42l43_spi_rx(struct regmap *regmap, u8 *buf, unsigned int len) +{ + u8 *end = buf + len; + u32 val; + int ret; + + while (buf < end) { + u8 *block = min(buf + CS42L43_FIFO_SIZE, end); + + ret = regmap_read_poll_timeout(regmap, CS42L43_TRAN_STATUS1, + val, (val & CS42L43_SPI_RX_REQUEST_MASK), + 1000, 5000); + if (ret) + return ret; + + while (buf < block) { + u8 *word = min(buf + sizeof(u32), block); + + ret = regmap_read(regmap, CS42L43_RX_DATA, &val); + if (ret) + return ret; + + while (buf < word) { + *buf = FIELD_GET(GENMASK(7, 0), val); + + val >>= BITS_PER_BYTE; + buf++; + } + } + + regmap_write(regmap, CS42L43_TRAN_CONFIG8, CS42L43_SPI_RX_DONE_MASK); + } + + return 0; +} + +static int cs42l43_transfer_one(struct spi_controller *ctlr, struct spi_device *spi, + struct spi_transfer *tfr) +{ + struct cs42l43_spi *priv = spi_controller_get_devdata(spi->controller); + int i, ret = -EINVAL; + + for (i = 0; i < ARRAY_SIZE(cs42l43_clock_divs); i++) { + if (CS42L43_SPI_ROOT_HZ / cs42l43_clock_divs[i] <= tfr->speed_hz) + break; + } + + if (i == ARRAY_SIZE(cs42l43_clock_divs)) + return -EINVAL; + + regmap_write(priv->regmap, CS42L43_SPI_CLK_CONFIG1, i); + + if (tfr->tx_buf) { + regmap_write(priv->regmap, CS42L43_TRAN_CONFIG3, CS42L43_WRITE); + regmap_write(priv->regmap, CS42L43_TRAN_CONFIG4, tfr->len - 1); + } else if (tfr->rx_buf) { + regmap_write(priv->regmap, CS42L43_TRAN_CONFIG3, CS42L43_READ); + regmap_write(priv->regmap, CS42L43_TRAN_CONFIG5, tfr->len - 1); + } + + regmap_write(priv->regmap, CS42L43_TRAN_CONFIG1, CS42L43_SPI_START_MASK); + + if (tfr->tx_buf) + ret = cs42l43_spi_tx(priv->regmap, (const u8 *)tfr->tx_buf, tfr->len); + else if (tfr->rx_buf) + ret = cs42l43_spi_rx(priv->regmap, (u8 *)tfr->rx_buf, tfr->len); + + return ret; +} + +static void cs42l43_set_cs(struct spi_device *spi, bool is_high) +{ + struct cs42l43_spi *priv = spi_controller_get_devdata(spi->controller); + + if (spi_get_chipselect(spi, 0) == 0) + regmap_write(priv->regmap, CS42L43_SPI_CONFIG2, !is_high); +} + +static int cs42l43_prepare_message(struct spi_controller *ctlr, struct spi_message *msg) +{ + struct cs42l43_spi *priv = spi_controller_get_devdata(ctlr); + struct spi_device *spi = msg->spi; + unsigned int spi_config1 = 0; + + /* select another internal CS, which doesn't exist, so CS 0 is not used */ + if (spi_get_csgpiod(spi, 0)) + spi_config1 |= 1 << CS42L43_SPI_SS_SEL_SHIFT; + if (spi->mode & SPI_CPOL) + spi_config1 |= CS42L43_SPI_CPOL_MASK; + if (spi->mode & SPI_CPHA) + spi_config1 |= CS42L43_SPI_CPHA_MASK; + if (spi->mode & SPI_3WIRE) + spi_config1 |= CS42L43_SPI_THREE_WIRE_MASK; + + regmap_write(priv->regmap, CS42L43_SPI_CONFIG1, spi_config1); + + return 0; +} + +static int cs42l43_prepare_transfer_hardware(struct spi_controller *ctlr) +{ + struct cs42l43_spi *priv = spi_controller_get_devdata(ctlr); + int ret; + + ret = regmap_write(priv->regmap, CS42L43_BLOCK_EN2, CS42L43_SPI_MSTR_EN_MASK); + if (ret) + dev_err(priv->dev, "Failed to enable SPI controller: %d\n", ret); + + return ret; +} + +static int cs42l43_unprepare_transfer_hardware(struct spi_controller *ctlr) +{ + struct cs42l43_spi *priv = spi_controller_get_devdata(ctlr); + int ret; + + ret = regmap_write(priv->regmap, CS42L43_BLOCK_EN2, 0); + if (ret) + dev_err(priv->dev, "Failed to disable SPI controller: %d\n", ret); + + return ret; +} + +static size_t cs42l43_spi_max_length(struct spi_device *spi) +{ + return CS42L43_SPI_MAX_LENGTH; +} + +static int cs42l43_spi_probe(struct platform_device *pdev) +{ + struct cs42l43 *cs42l43 = dev_get_drvdata(pdev->dev.parent); + struct cs42l43_spi *priv; + struct fwnode_handle *fwnode = dev_fwnode(cs42l43->dev); + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*priv->ctlr)); + if (!priv->ctlr) + return -ENOMEM; + + spi_controller_set_devdata(priv->ctlr, priv); + + priv->dev = &pdev->dev; + priv->regmap = cs42l43->regmap; + + priv->ctlr->prepare_message = cs42l43_prepare_message; + priv->ctlr->prepare_transfer_hardware = cs42l43_prepare_transfer_hardware; + priv->ctlr->unprepare_transfer_hardware = cs42l43_unprepare_transfer_hardware; + priv->ctlr->transfer_one = cs42l43_transfer_one; + priv->ctlr->set_cs = cs42l43_set_cs; + priv->ctlr->max_transfer_size = cs42l43_spi_max_length; + + if (is_of_node(fwnode)) + fwnode = fwnode_get_named_child_node(fwnode, "spi"); + + device_set_node(&priv->ctlr->dev, fwnode); + + priv->ctlr->mode_bits = SPI_3WIRE | SPI_MODE_X_MASK; + priv->ctlr->flags = SPI_CONTROLLER_HALF_DUPLEX; + priv->ctlr->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16) | + SPI_BPW_MASK(32); + priv->ctlr->min_speed_hz = CS42L43_SPI_ROOT_HZ / + cs42l43_clock_divs[ARRAY_SIZE(cs42l43_clock_divs) - 1]; + priv->ctlr->max_speed_hz = CS42L43_SPI_ROOT_HZ / cs42l43_clock_divs[0]; + priv->ctlr->use_gpio_descriptors = true; + priv->ctlr->auto_runtime_pm = true; + + devm_pm_runtime_enable(priv->dev); + pm_runtime_idle(priv->dev); + + regmap_write(priv->regmap, CS42L43_TRAN_CONFIG6, CS42L43_FIFO_SIZE - 1); + regmap_write(priv->regmap, CS42L43_TRAN_CONFIG7, CS42L43_FIFO_SIZE - 1); + + // Disable Watchdog timer and enable stall + regmap_write(priv->regmap, CS42L43_SPI_CONFIG3, 0); + regmap_write(priv->regmap, CS42L43_SPI_CONFIG4, CS42L43_SPI_STALL_ENA_MASK); + + ret = devm_spi_register_controller(priv->dev, priv->ctlr); + if (ret) { + pm_runtime_disable(priv->dev); + dev_err(priv->dev, "Failed to register SPI controller: %d\n", ret); + } + + return ret; +} + +static const struct platform_device_id cs42l43_spi_id_table[] = { + { "cs42l43-spi", }, + {} +}; +MODULE_DEVICE_TABLE(platform, cs42l43_spi_id_table); + +static struct platform_driver cs42l43_spi_driver = { + .driver = { + .name = "cs42l43-spi", + }, + .probe = cs42l43_spi_probe, + .id_table = cs42l43_spi_id_table, +}; +module_platform_driver(cs42l43_spi_driver); + +MODULE_DESCRIPTION("CS42L43 SPI Driver"); +MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>"); +MODULE_AUTHOR("Maciej Strozek <mstrozek@opensource.cirrus.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index b04811c911e2..c457b550d3ad 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -15,7 +15,6 @@ #include <linux/dmaengine.h> #include <linux/dma-mapping.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/spi/spi.h> #include <linux/spi/spi_bitbang.h> #include <linux/slab.h> @@ -202,7 +201,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) u8 chip_sel = spi_get_chipselect(spi, 0); u16 spidat1 = CS_DEFAULT; - dspi = spi_master_get_devdata(spi->master); + dspi = spi_controller_get_devdata(spi->controller); /* program delay transfers if tx_delay is non zero */ if (spicfg && spicfg->wdelay) @@ -272,7 +271,7 @@ static int davinci_spi_setup_transfer(struct spi_device *spi, u32 hz = 0, spifmt = 0; int prescale; - dspi = spi_master_get_devdata(spi->master); + dspi = spi_controller_get_devdata(spi->controller); spicfg = spi->controller_data; if (!spicfg) spicfg = &davinci_spi_default_cfg; @@ -380,7 +379,7 @@ static int davinci_spi_of_setup(struct spi_device *spi) { struct davinci_spi_config *spicfg = spi->controller_data; struct device_node *np = spi->dev.of_node; - struct davinci_spi *dspi = spi_master_get_devdata(spi->master); + struct davinci_spi *dspi = spi_controller_get_devdata(spi->controller); u32 prop; if (spicfg == NULL && np) { @@ -412,7 +411,7 @@ static int davinci_spi_setup(struct spi_device *spi) struct device_node *np = spi->dev.of_node; bool internal_cs = true; - dspi = spi_master_get_devdata(spi->master); + dspi = spi_controller_get_devdata(spi->controller); if (!(spi->mode & SPI_NO_CS)) { if (np && spi_get_csgpiod(spi, 0)) @@ -442,7 +441,7 @@ static void davinci_spi_cleanup(struct spi_device *spi) kfree(spicfg); } -static bool davinci_spi_can_dma(struct spi_master *master, +static bool davinci_spi_can_dma(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { @@ -572,7 +571,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) struct davinci_spi_config *spicfg; struct davinci_spi_platform_data *pdata; - dspi = spi_master_get_devdata(spi->master); + dspi = spi_controller_get_devdata(spi->controller); pdata = &dspi->pdata; spicfg = (struct davinci_spi_config *)spi->controller_data; if (!spicfg) @@ -593,7 +592,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) reinit_completion(&dspi->done); - if (!davinci_spi_can_dma(spi->master, spi, t)) { + if (!davinci_spi_can_dma(spi->controller, spi, t)) { if (spicfg->io_type != SPI_IO_TYPE_POLL) set_io_bits(dspi->base + SPIINT, SPIINT_MASKINT); /* start the transfer */ @@ -674,7 +673,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) } clear_io_bits(dspi->base + SPIINT, SPIINT_MASKALL); - if (davinci_spi_can_dma(spi->master, spi, t)) + if (davinci_spi_can_dma(spi->controller, spi, t)) clear_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN); clear_io_bits(dspi->base + SPIGCR1, SPIGCR1_SPIENA_MASK); @@ -856,22 +855,22 @@ static int spi_davinci_get_pdata(struct platform_device *pdev, */ static int davinci_spi_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *host; struct davinci_spi *dspi; struct davinci_spi_platform_data *pdata; struct resource *r; int ret = 0; u32 spipc0; - master = spi_alloc_master(&pdev->dev, sizeof(struct davinci_spi)); - if (master == NULL) { + host = spi_alloc_host(&pdev->dev, sizeof(struct davinci_spi)); + if (host == NULL) { ret = -ENOMEM; goto err; } - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); - dspi = spi_master_get_devdata(master); + dspi = spi_controller_get_devdata(host); if (dev_get_platdata(&pdev->dev)) { pdata = dev_get_platdata(&pdev->dev); @@ -880,7 +879,7 @@ static int davinci_spi_probe(struct platform_device *pdev) /* update dspi pdata with that from the DT */ ret = spi_davinci_get_pdata(pdev, dspi); if (ret < 0) - goto free_master; + goto free_host; } /* pdata in dspi is now updated and point pdata to that */ @@ -892,57 +891,48 @@ static int davinci_spi_probe(struct platform_device *pdev) GFP_KERNEL); if (dspi->bytes_per_word == NULL) { ret = -ENOMEM; - goto free_master; + goto free_host; } - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (r == NULL) { - ret = -ENOENT; - goto free_master; - } - - dspi->pbase = r->start; - - dspi->base = devm_ioremap_resource(&pdev->dev, r); + dspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r); if (IS_ERR(dspi->base)) { ret = PTR_ERR(dspi->base); - goto free_master; + goto free_host; } + dspi->pbase = r->start; init_completion(&dspi->done); ret = platform_get_irq(pdev, 0); - if (ret == 0) - ret = -EINVAL; if (ret < 0) - goto free_master; + goto free_host; dspi->irq = ret; ret = devm_request_threaded_irq(&pdev->dev, dspi->irq, davinci_spi_irq, dummy_thread_fn, 0, dev_name(&pdev->dev), dspi); if (ret) - goto free_master; + goto free_host; - dspi->bitbang.master = master; + dspi->bitbang.master = host; dspi->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(dspi->clk)) { ret = -ENODEV; - goto free_master; + goto free_host; } ret = clk_prepare_enable(dspi->clk); if (ret) - goto free_master; - - master->use_gpio_descriptors = true; - master->dev.of_node = pdev->dev.of_node; - master->bus_num = pdev->id; - master->num_chipselect = pdata->num_chipselect; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 16); - master->flags = SPI_MASTER_MUST_RX | SPI_MASTER_GPIO_SS; - master->setup = davinci_spi_setup; - master->cleanup = davinci_spi_cleanup; - master->can_dma = davinci_spi_can_dma; + goto free_host; + + host->use_gpio_descriptors = true; + host->dev.of_node = pdev->dev.of_node; + host->bus_num = pdev->id; + host->num_chipselect = pdata->num_chipselect; + host->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 16); + host->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_GPIO_SS; + host->setup = davinci_spi_setup; + host->cleanup = davinci_spi_cleanup; + host->can_dma = davinci_spi_can_dma; dspi->bitbang.chipselect = davinci_spi_chipselect; dspi->bitbang.setup_transfer = davinci_spi_setup_transfer; @@ -983,7 +973,7 @@ static int davinci_spi_probe(struct platform_device *pdev) iowrite32(CS_DEFAULT, dspi->base + SPIDEF); - /* master mode default */ + /* host mode default */ set_io_bits(dspi->base + SPIGCR1, SPIGCR1_CLKMOD_MASK); set_io_bits(dspi->base + SPIGCR1, SPIGCR1_MASTER_MASK); set_io_bits(dspi->base + SPIGCR1, SPIGCR1_POWERDOWN_MASK); @@ -1003,8 +993,8 @@ free_dma: } free_clk: clk_disable_unprepare(dspi->clk); -free_master: - spi_master_put(master); +free_host: + spi_controller_put(host); err: return ret; } @@ -1021,10 +1011,10 @@ err: static void davinci_spi_remove(struct platform_device *pdev) { struct davinci_spi *dspi; - struct spi_master *master; + struct spi_controller *host; - master = platform_get_drvdata(pdev); - dspi = spi_master_get_devdata(master); + host = platform_get_drvdata(pdev); + dspi = spi_controller_get_devdata(host); spi_bitbang_stop(&dspi->bitbang); @@ -1035,7 +1025,7 @@ static void davinci_spi_remove(struct platform_device *pdev) dma_release_channel(dspi->dma_tx); } - spi_master_put(master); + spi_controller_put(host); } static struct platform_driver davinci_spi_driver = { diff --git a/drivers/spi/spi-dln2.c b/drivers/spi/spi-dln2.c index 6bd93c47853c..d319dc357fef 100644 --- a/drivers/spi/spi-dln2.c +++ b/drivers/spi/spi-dln2.c @@ -79,7 +79,7 @@ struct dln2_spi { struct platform_device *pdev; - struct spi_master *master; + struct spi_controller *host; u8 port; /* @@ -176,7 +176,7 @@ static int dln2_spi_cs_enable(struct dln2_spi *dln2, u8 cs_mask, bool enable) static int dln2_spi_cs_enable_all(struct dln2_spi *dln2, bool enable) { - u8 cs_mask = GENMASK(dln2->master->num_chipselect - 1, 0); + u8 cs_mask = GENMASK(dln2->host->num_chipselect - 1, 0); return dln2_spi_cs_enable(dln2, cs_mask, enable); } @@ -589,11 +589,11 @@ static int dln2_spi_rdwr(struct dln2_spi *dln2, const u8 *tx_data, return 0; } -static int dln2_spi_prepare_message(struct spi_master *master, +static int dln2_spi_prepare_message(struct spi_controller *host, struct spi_message *message) { int ret; - struct dln2_spi *dln2 = spi_master_get_devdata(master); + struct dln2_spi *dln2 = spi_controller_get_devdata(host); struct spi_device *spi = message->spi; if (dln2->cs != spi_get_chipselect(spi, 0)) { @@ -650,11 +650,11 @@ static int dln2_spi_transfer_setup(struct dln2_spi *dln2, u32 speed, return dln2_spi_enable(dln2, true); } -static int dln2_spi_transfer_one(struct spi_master *master, +static int dln2_spi_transfer_one(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { - struct dln2_spi *dln2 = spi_master_get_devdata(master); + struct dln2_spi *dln2 = spi_controller_get_devdata(host); int status; u8 attr = 0; @@ -666,7 +666,7 @@ static int dln2_spi_transfer_one(struct spi_master *master, return status; } - if (!xfer->cs_change && !spi_transfer_is_last(master, xfer)) + if (!xfer->cs_change && !spi_transfer_is_last(host, xfer)) attr = DLN2_SPI_ATTR_LEAVE_SS_LOW; status = dln2_spi_rdwr(dln2, xfer->tx_buf, xfer->rx_buf, @@ -679,29 +679,29 @@ static int dln2_spi_transfer_one(struct spi_master *master, static int dln2_spi_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *host; struct dln2_spi *dln2; struct dln2_platform_data *pdata = dev_get_platdata(&pdev->dev); struct device *dev = &pdev->dev; int ret; - master = spi_alloc_master(&pdev->dev, sizeof(*dln2)); - if (!master) + host = spi_alloc_host(&pdev->dev, sizeof(*dln2)); + if (!host) return -ENOMEM; - device_set_node(&master->dev, dev_fwnode(dev)); + device_set_node(&host->dev, dev_fwnode(dev)); - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); - dln2 = spi_master_get_devdata(master); + dln2 = spi_controller_get_devdata(host); dln2->buf = devm_kmalloc(&pdev->dev, DLN2_SPI_BUF_SIZE, GFP_KERNEL); if (!dln2->buf) { ret = -ENOMEM; - goto exit_free_master; + goto exit_free_host; } - dln2->master = master; + dln2->host = host; dln2->pdev = pdev; dln2->port = pdata->port; /* cs/mode can never be 0xff, so the first transfer will set them */ @@ -712,47 +712,47 @@ static int dln2_spi_probe(struct platform_device *pdev) ret = dln2_spi_enable(dln2, false); if (ret < 0) { dev_err(&pdev->dev, "Failed to disable SPI module\n"); - goto exit_free_master; + goto exit_free_host; } - ret = dln2_spi_get_cs_num(dln2, &master->num_chipselect); + ret = dln2_spi_get_cs_num(dln2, &host->num_chipselect); if (ret < 0) { dev_err(&pdev->dev, "Failed to get number of CS pins\n"); - goto exit_free_master; + goto exit_free_host; } ret = dln2_spi_get_speed_range(dln2, - &master->min_speed_hz, - &master->max_speed_hz); + &host->min_speed_hz, + &host->max_speed_hz); if (ret < 0) { dev_err(&pdev->dev, "Failed to read bus min/max freqs\n"); - goto exit_free_master; + goto exit_free_host; } ret = dln2_spi_get_supported_frame_sizes(dln2, - &master->bits_per_word_mask); + &host->bits_per_word_mask); if (ret < 0) { dev_err(&pdev->dev, "Failed to read supported frame sizes\n"); - goto exit_free_master; + goto exit_free_host; } ret = dln2_spi_cs_enable_all(dln2, true); if (ret < 0) { dev_err(&pdev->dev, "Failed to enable CS pins\n"); - goto exit_free_master; + goto exit_free_host; } - master->bus_num = -1; - master->mode_bits = SPI_CPOL | SPI_CPHA; - master->prepare_message = dln2_spi_prepare_message; - master->transfer_one = dln2_spi_transfer_one; - master->auto_runtime_pm = true; + host->bus_num = -1; + host->mode_bits = SPI_CPOL | SPI_CPHA; + host->prepare_message = dln2_spi_prepare_message; + host->transfer_one = dln2_spi_transfer_one; + host->auto_runtime_pm = true; /* enable SPI module, we're good to go */ ret = dln2_spi_enable(dln2, true); if (ret < 0) { dev_err(&pdev->dev, "Failed to enable SPI module\n"); - goto exit_free_master; + goto exit_free_host; } pm_runtime_set_autosuspend_delay(&pdev->dev, @@ -761,9 +761,9 @@ static int dln2_spi_probe(struct platform_device *pdev) pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); - ret = devm_spi_register_master(&pdev->dev, master); + ret = devm_spi_register_controller(&pdev->dev, host); if (ret < 0) { - dev_err(&pdev->dev, "Failed to register master\n"); + dev_err(&pdev->dev, "Failed to register host\n"); goto exit_register; } @@ -775,16 +775,16 @@ exit_register: if (dln2_spi_enable(dln2, false) < 0) dev_err(&pdev->dev, "Failed to disable SPI module\n"); -exit_free_master: - spi_master_put(master); +exit_free_host: + spi_controller_put(host); return ret; } static void dln2_spi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct dln2_spi *dln2 = spi_master_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(pdev); + struct dln2_spi *dln2 = spi_controller_get_devdata(host); pm_runtime_disable(&pdev->dev); @@ -796,10 +796,10 @@ static void dln2_spi_remove(struct platform_device *pdev) static int dln2_spi_suspend(struct device *dev) { int ret; - struct spi_master *master = dev_get_drvdata(dev); - struct dln2_spi *dln2 = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct dln2_spi *dln2 = spi_controller_get_devdata(host); - ret = spi_master_suspend(master); + ret = spi_controller_suspend(host); if (ret < 0) return ret; @@ -824,8 +824,8 @@ static int dln2_spi_suspend(struct device *dev) static int dln2_spi_resume(struct device *dev) { int ret; - struct spi_master *master = dev_get_drvdata(dev); - struct dln2_spi *dln2 = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct dln2_spi *dln2 = spi_controller_get_devdata(host); if (!pm_runtime_suspended(dev)) { ret = dln2_spi_cs_enable_all(dln2, true); @@ -837,23 +837,23 @@ static int dln2_spi_resume(struct device *dev) return ret; } - return spi_master_resume(master); + return spi_controller_resume(host); } #endif /* CONFIG_PM_SLEEP */ #ifdef CONFIG_PM static int dln2_spi_runtime_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct dln2_spi *dln2 = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct dln2_spi *dln2 = spi_controller_get_devdata(host); return dln2_spi_enable(dln2, false); } static int dln2_spi_runtime_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct dln2_spi *dln2 = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct dln2_spi *dln2 = spi_controller_get_devdata(host); return dln2_spi_enable(dln2, true); } @@ -875,7 +875,7 @@ static struct platform_driver spi_dln2_driver = { }; module_platform_driver(spi_dln2_driver); -MODULE_DESCRIPTION("Driver for the Diolan DLN2 SPI master interface"); +MODULE_DESCRIPTION("Driver for the Diolan DLN2 SPI host interface"); MODULE_AUTHOR("Laurentiu Palcu <laurentiu.palcu@intel.com>"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:dln2-spi"); diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c index a8ba41ad4541..0274c9295514 100644 --- a/drivers/spi/spi-dw-core.c +++ b/drivers/spi/spi-dw-core.c @@ -61,7 +61,7 @@ static void dw_spi_debugfs_init(struct dw_spi *dws) { char name[32]; - snprintf(name, 32, "dw_spi%d", dws->master->bus_num); + snprintf(name, 32, "dw_spi%d", dws->host->bus_num); dws->debugfs = debugfs_create_dir(name, NULL); dws->regset.regs = dw_spi_dbgfs_regs; @@ -183,25 +183,25 @@ int dw_spi_check_status(struct dw_spi *dws, bool raw) irq_status = dw_readl(dws, DW_SPI_ISR); if (irq_status & DW_SPI_INT_RXOI) { - dev_err(&dws->master->dev, "RX FIFO overflow detected\n"); + dev_err(&dws->host->dev, "RX FIFO overflow detected\n"); ret = -EIO; } if (irq_status & DW_SPI_INT_RXUI) { - dev_err(&dws->master->dev, "RX FIFO underflow detected\n"); + dev_err(&dws->host->dev, "RX FIFO underflow detected\n"); ret = -EIO; } if (irq_status & DW_SPI_INT_TXOI) { - dev_err(&dws->master->dev, "TX FIFO overflow detected\n"); + dev_err(&dws->host->dev, "TX FIFO overflow detected\n"); ret = -EIO; } /* Generically handle the erroneous situation */ if (ret) { dw_spi_reset_chip(dws); - if (dws->master->cur_msg) - dws->master->cur_msg->status = ret; + if (dws->host->cur_msg) + dws->host->cur_msg->status = ret; } return ret; @@ -213,7 +213,7 @@ static irqreturn_t dw_spi_transfer_handler(struct dw_spi *dws) u16 irq_status = dw_readl(dws, DW_SPI_ISR); if (dw_spi_check_status(dws, false)) { - spi_finalize_current_transfer(dws->master); + spi_finalize_current_transfer(dws->host); return IRQ_HANDLED; } @@ -227,7 +227,7 @@ static irqreturn_t dw_spi_transfer_handler(struct dw_spi *dws) dw_reader(dws); if (!dws->rx_len) { dw_spi_mask_intr(dws, 0xff); - spi_finalize_current_transfer(dws->master); + spi_finalize_current_transfer(dws->host); } else if (dws->rx_len <= dw_readl(dws, DW_SPI_RXFTLR)) { dw_writel(dws, DW_SPI_RXFTLR, dws->rx_len - 1); } @@ -248,14 +248,14 @@ static irqreturn_t dw_spi_transfer_handler(struct dw_spi *dws) static irqreturn_t dw_spi_irq(int irq, void *dev_id) { - struct spi_controller *master = dev_id; - struct dw_spi *dws = spi_controller_get_devdata(master); + struct spi_controller *host = dev_id; + struct dw_spi *dws = spi_controller_get_devdata(host); u16 irq_status = dw_readl(dws, DW_SPI_ISR) & DW_SPI_INT_MASK; if (!irq_status) return IRQ_NONE; - if (!master->cur_msg) { + if (!host->cur_msg) { dw_spi_mask_intr(dws, 0xff); return IRQ_HANDLED; } @@ -408,11 +408,11 @@ static int dw_spi_poll_transfer(struct dw_spi *dws, return 0; } -static int dw_spi_transfer_one(struct spi_controller *master, +static int dw_spi_transfer_one(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *transfer) { - struct dw_spi *dws = spi_controller_get_devdata(master); + struct dw_spi *dws = spi_controller_get_devdata(host); struct dw_spi_cfg cfg = { .tmode = DW_SPI_CTRLR0_TMOD_TR, .dfs = transfer->bits_per_word, @@ -440,8 +440,8 @@ static int dw_spi_transfer_one(struct spi_controller *master, transfer->effective_speed_hz = dws->current_freq; /* Check if current transfer is a DMA transaction */ - if (master->can_dma && master->can_dma(master, spi, transfer)) - dws->dma_mapped = master->cur_msg_mapped; + if (host->can_dma && host->can_dma(host, spi, transfer)) + dws->dma_mapped = host->cur_msg_mapped; /* For poll mode just disable all interrupts */ dw_spi_mask_intr(dws, 0xff); @@ -464,10 +464,10 @@ static int dw_spi_transfer_one(struct spi_controller *master, return 1; } -static void dw_spi_handle_err(struct spi_controller *master, +static void dw_spi_handle_err(struct spi_controller *host, struct spi_message *msg) { - struct dw_spi *dws = spi_controller_get_devdata(master); + struct dw_spi *dws = spi_controller_get_devdata(host); if (dws->dma_mapped) dws->dma_ops->dma_stop(dws); @@ -576,7 +576,7 @@ static int dw_spi_write_then_read(struct dw_spi *dws, struct spi_device *spi) while (len) { entries = readl_relaxed(dws->regs + DW_SPI_TXFLR); if (!entries) { - dev_err(&dws->master->dev, "CS de-assertion on Tx\n"); + dev_err(&dws->host->dev, "CS de-assertion on Tx\n"); return -EIO; } room = min(dws->fifo_len - entries, len); @@ -596,7 +596,7 @@ static int dw_spi_write_then_read(struct dw_spi *dws, struct spi_device *spi) if (!entries) { sts = readl_relaxed(dws->regs + DW_SPI_RISR); if (sts & DW_SPI_INT_RXOI) { - dev_err(&dws->master->dev, "FIFO overflow on Rx\n"); + dev_err(&dws->host->dev, "FIFO overflow on Rx\n"); return -EIO; } continue; @@ -637,7 +637,7 @@ static int dw_spi_wait_mem_op_done(struct dw_spi *dws) spi_delay_exec(&delay, NULL); if (retry < 0) { - dev_err(&dws->master->dev, "Mem op hanged up\n"); + dev_err(&dws->host->dev, "Mem op hanged up\n"); return -EIO; } @@ -884,56 +884,56 @@ static void dw_spi_hw_init(struct device *dev, struct dw_spi *dws) int dw_spi_add_host(struct device *dev, struct dw_spi *dws) { - struct spi_controller *master; + struct spi_controller *host; int ret; if (!dws) return -EINVAL; - master = spi_alloc_master(dev, 0); - if (!master) + host = spi_alloc_host(dev, 0); + if (!host) return -ENOMEM; - device_set_node(&master->dev, dev_fwnode(dev)); + device_set_node(&host->dev, dev_fwnode(dev)); - dws->master = master; + dws->host = host; dws->dma_addr = (dma_addr_t)(dws->paddr + DW_SPI_DR); - spi_controller_set_devdata(master, dws); + spi_controller_set_devdata(host, dws); /* Basic HW init */ dw_spi_hw_init(dev, dws); ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, dev_name(dev), - master); + host); if (ret < 0 && ret != -ENOTCONN) { dev_err(dev, "can not get IRQ\n"); - goto err_free_master; + goto err_free_host; } dw_spi_init_mem_ops(dws); - master->use_gpio_descriptors = true; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP; + host->use_gpio_descriptors = true; + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP; if (dws->caps & DW_SPI_CAP_DFS32) - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); + host->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); else - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); - master->bus_num = dws->bus_num; - master->num_chipselect = dws->num_cs; - master->setup = dw_spi_setup; - master->cleanup = dw_spi_cleanup; + host->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); + host->bus_num = dws->bus_num; + host->num_chipselect = dws->num_cs; + host->setup = dw_spi_setup; + host->cleanup = dw_spi_cleanup; if (dws->set_cs) - master->set_cs = dws->set_cs; + host->set_cs = dws->set_cs; else - master->set_cs = dw_spi_set_cs; - master->transfer_one = dw_spi_transfer_one; - master->handle_err = dw_spi_handle_err; + host->set_cs = dw_spi_set_cs; + host->transfer_one = dw_spi_transfer_one; + host->handle_err = dw_spi_handle_err; if (dws->mem_ops.exec_op) - master->mem_ops = &dws->mem_ops; - master->max_speed_hz = dws->max_freq; - master->flags = SPI_MASTER_GPIO_SS; - master->auto_runtime_pm = true; + host->mem_ops = &dws->mem_ops; + host->max_speed_hz = dws->max_freq; + host->flags = SPI_CONTROLLER_GPIO_SS; + host->auto_runtime_pm = true; /* Get default rx sample delay */ device_property_read_u32(dev, "rx-sample-delay-ns", @@ -946,14 +946,14 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws) } else if (ret) { dev_warn(dev, "DMA init failed\n"); } else { - master->can_dma = dws->dma_ops->can_dma; - master->flags |= SPI_CONTROLLER_MUST_TX; + host->can_dma = dws->dma_ops->can_dma; + host->flags |= SPI_CONTROLLER_MUST_TX; } } - ret = spi_register_controller(master); + ret = spi_register_controller(host); if (ret) { - dev_err_probe(dev, ret, "problem registering spi master\n"); + dev_err_probe(dev, ret, "problem registering spi host\n"); goto err_dma_exit; } @@ -965,9 +965,9 @@ err_dma_exit: dws->dma_ops->dma_exit(dws); dw_spi_enable_chip(dws, 0); err_free_irq: - free_irq(dws->irq, master); -err_free_master: - spi_controller_put(master); + free_irq(dws->irq, host); +err_free_host: + spi_controller_put(host); return ret; } EXPORT_SYMBOL_NS_GPL(dw_spi_add_host, SPI_DW_CORE); @@ -976,14 +976,14 @@ void dw_spi_remove_host(struct dw_spi *dws) { dw_spi_debugfs_remove(dws); - spi_unregister_controller(dws->master); + spi_unregister_controller(dws->host); if (dws->dma_ops && dws->dma_ops->dma_exit) dws->dma_ops->dma_exit(dws); dw_spi_shutdown_chip(dws); - free_irq(dws->irq, dws->master); + free_irq(dws->irq, dws->host); } EXPORT_SYMBOL_NS_GPL(dw_spi_remove_host, SPI_DW_CORE); @@ -991,7 +991,7 @@ int dw_spi_suspend_host(struct dw_spi *dws) { int ret; - ret = spi_controller_suspend(dws->master); + ret = spi_controller_suspend(dws->host); if (ret) return ret; @@ -1002,8 +1002,8 @@ EXPORT_SYMBOL_NS_GPL(dw_spi_suspend_host, SPI_DW_CORE); int dw_spi_resume_host(struct dw_spi *dws) { - dw_spi_hw_init(&dws->master->dev, dws); - return spi_controller_resume(dws->master); + dw_spi_hw_init(&dws->host->dev, dws); + return spi_controller_resume(dws->host); } EXPORT_SYMBOL_NS_GPL(dw_spi_resume_host, SPI_DW_CORE); diff --git a/drivers/spi/spi-dw-dma.c b/drivers/spi/spi-dw-dma.c index df819652901a..0ecbb6c36e23 100644 --- a/drivers/spi/spi-dw-dma.c +++ b/drivers/spi/spi-dw-dma.c @@ -139,8 +139,8 @@ static int dw_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws) if (!dws->txchan) goto free_rxchan; - dws->master->dma_rx = dws->rxchan; - dws->master->dma_tx = dws->txchan; + dws->host->dma_rx = dws->rxchan; + dws->host->dma_tx = dws->txchan; init_completion(&dws->dma_completion); @@ -183,8 +183,8 @@ static int dw_spi_dma_init_generic(struct device *dev, struct dw_spi *dws) goto free_rxchan; } - dws->master->dma_rx = dws->rxchan; - dws->master->dma_tx = dws->txchan; + dws->host->dma_rx = dws->rxchan; + dws->host->dma_tx = dws->txchan; init_completion(&dws->dma_completion); @@ -242,10 +242,10 @@ static enum dma_slave_buswidth dw_spi_dma_convert_width(u8 n_bytes) } } -static bool dw_spi_can_dma(struct spi_controller *master, +static bool dw_spi_can_dma(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { - struct dw_spi *dws = spi_controller_get_devdata(master); + struct dw_spi *dws = spi_controller_get_devdata(host); enum dma_slave_buswidth dma_bus_width; if (xfer->len <= dws->fifo_len) @@ -271,7 +271,7 @@ static int dw_spi_dma_wait(struct dw_spi *dws, unsigned int len, u32 speed) msecs_to_jiffies(ms)); if (ms == 0) { - dev_err(&dws->master->cur_msg->spi->dev, + dev_err(&dws->host->cur_msg->spi->dev, "DMA transaction timed out\n"); return -ETIMEDOUT; } @@ -299,7 +299,7 @@ static int dw_spi_dma_wait_tx_done(struct dw_spi *dws, spi_delay_exec(&delay, xfer); if (retry < 0) { - dev_err(&dws->master->dev, "Tx hanged up\n"); + dev_err(&dws->host->dev, "Tx hanged up\n"); return -EIO; } @@ -400,7 +400,7 @@ static int dw_spi_dma_wait_rx_done(struct dw_spi *dws) spi_delay_exec(&delay, NULL); if (retry < 0) { - dev_err(&dws->master->dev, "Rx hanged up\n"); + dev_err(&dws->host->dev, "Rx hanged up\n"); return -EIO; } @@ -656,13 +656,13 @@ static int dw_spi_dma_transfer(struct dw_spi *dws, struct spi_transfer *xfer) if (ret) return ret; - if (dws->master->cur_msg->status == -EINPROGRESS) { + if (dws->host->cur_msg->status == -EINPROGRESS) { ret = dw_spi_dma_wait_tx_done(dws, xfer); if (ret) return ret; } - if (xfer->rx_buf && dws->master->cur_msg->status == -EINPROGRESS) + if (xfer->rx_buf && dws->host->cur_msg->status == -EINPROGRESS) ret = dw_spi_dma_wait_rx_done(dws); return ret; diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index a963bc96c223..805264c9c65c 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -76,7 +76,7 @@ struct dw_spi_mscc { */ static void dw_spi_mscc_set_cs(struct spi_device *spi, bool enable) { - struct dw_spi *dws = spi_master_get_devdata(spi->master); + struct dw_spi *dws = spi_controller_get_devdata(spi->controller); struct dw_spi_mmio *dwsmmio = container_of(dws, struct dw_spi_mmio, dws); struct dw_spi_mscc *dwsmscc = dwsmmio->priv; u32 cs = spi_get_chipselect(spi, 0); @@ -149,7 +149,7 @@ static int dw_spi_mscc_jaguar2_init(struct platform_device *pdev, */ static void dw_spi_sparx5_set_cs(struct spi_device *spi, bool enable) { - struct dw_spi *dws = spi_master_get_devdata(spi->master); + struct dw_spi *dws = spi_controller_get_devdata(spi->controller); struct dw_spi_mmio *dwsmmio = container_of(dws, struct dw_spi_mmio, dws); struct dw_spi_mscc *dwsmscc = dwsmmio->priv; u8 cs = spi_get_chipselect(spi, 0); @@ -277,7 +277,7 @@ static void dw_spi_elba_override_cs(struct regmap *syscon, int cs, int enable) static void dw_spi_elba_set_cs(struct spi_device *spi, bool enable) { - struct dw_spi *dws = spi_master_get_devdata(spi->master); + struct dw_spi *dws = spi_controller_get_devdata(spi->controller); struct dw_spi_mmio *dwsmmio = container_of(dws, struct dw_spi_mmio, dws); struct regmap *syscon = dwsmmio->priv; u8 cs; @@ -369,7 +369,9 @@ static int dw_spi_mmio_probe(struct platform_device *pdev) dws->max_freq = clk_get_rate(dwsmmio->clk); - device_property_read_u32(&pdev->dev, "reg-io-width", &dws->reg_io_width); + if (device_property_read_u32(&pdev->dev, "reg-io-width", + &dws->reg_io_width)) + dws->reg_io_width = 4; num_cs = 4; diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h index 3962e6dcf880..6cafeee8ee2a 100644 --- a/drivers/spi/spi-dw.h +++ b/drivers/spi/spi-dw.h @@ -142,14 +142,14 @@ struct dw_spi_dma_ops { int (*dma_init)(struct device *dev, struct dw_spi *dws); void (*dma_exit)(struct dw_spi *dws); int (*dma_setup)(struct dw_spi *dws, struct spi_transfer *xfer); - bool (*can_dma)(struct spi_controller *master, struct spi_device *spi, + bool (*can_dma)(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer); int (*dma_transfer)(struct dw_spi *dws, struct spi_transfer *xfer); void (*dma_stop)(struct dw_spi *dws); }; struct dw_spi { - struct spi_controller *master; + struct spi_controller *host; u32 ip; /* Synopsys DW SSI IP-core ID */ u32 ver; /* Synopsys component version */ diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c index 1615fd22f9a2..a1d60e51c053 100644 --- a/drivers/spi/spi-ep93xx.c +++ b/drivers/spi/spi-ep93xx.c @@ -104,15 +104,15 @@ struct ep93xx_spi { /** * ep93xx_spi_calc_divisors() - calculates SPI clock divisors - * @master: SPI master + * @host: SPI host * @rate: desired SPI output clock rate * @div_cpsr: pointer to return the cpsr (pre-scaler) divider * @div_scr: pointer to return the scr divider */ -static int ep93xx_spi_calc_divisors(struct spi_master *master, +static int ep93xx_spi_calc_divisors(struct spi_controller *host, u32 rate, u8 *div_cpsr, u8 *div_scr) { - struct ep93xx_spi *espi = spi_master_get_devdata(master); + struct ep93xx_spi *espi = spi_controller_get_devdata(host); unsigned long spi_clk_rate = clk_get_rate(espi->clk); int cpsr, scr; @@ -120,7 +120,7 @@ static int ep93xx_spi_calc_divisors(struct spi_master *master, * Make sure that max value is between values supported by the * controller. */ - rate = clamp(rate, master->min_speed_hz, master->max_speed_hz); + rate = clamp(rate, host->min_speed_hz, host->max_speed_hz); /* * Calculate divisors so that we can get speed according the @@ -143,18 +143,18 @@ static int ep93xx_spi_calc_divisors(struct spi_master *master, return -EINVAL; } -static int ep93xx_spi_chip_setup(struct spi_master *master, +static int ep93xx_spi_chip_setup(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { - struct ep93xx_spi *espi = spi_master_get_devdata(master); + struct ep93xx_spi *espi = spi_controller_get_devdata(host); u8 dss = bits_per_word_to_dss(xfer->bits_per_word); u8 div_cpsr = 0; u8 div_scr = 0; u16 cr0; int err; - err = ep93xx_spi_calc_divisors(master, xfer->speed_hz, + err = ep93xx_spi_calc_divisors(host, xfer->speed_hz, &div_cpsr, &div_scr); if (err) return err; @@ -166,9 +166,9 @@ static int ep93xx_spi_chip_setup(struct spi_master *master, cr0 |= SSPCR0_SPH; cr0 |= dss; - dev_dbg(&master->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n", + dev_dbg(&host->dev, "setup: mode %d, cpsr %d, scr %d, dss %d\n", spi->mode, div_cpsr, div_scr, dss); - dev_dbg(&master->dev, "setup: cr0 %#x\n", cr0); + dev_dbg(&host->dev, "setup: cr0 %#x\n", cr0); writel(div_cpsr, espi->mmio + SSPCPSR); writel(cr0, espi->mmio + SSPCR0); @@ -176,10 +176,10 @@ static int ep93xx_spi_chip_setup(struct spi_master *master, return 0; } -static void ep93xx_do_write(struct spi_master *master) +static void ep93xx_do_write(struct spi_controller *host) { - struct ep93xx_spi *espi = spi_master_get_devdata(master); - struct spi_transfer *xfer = master->cur_msg->state; + struct ep93xx_spi *espi = spi_controller_get_devdata(host); + struct spi_transfer *xfer = host->cur_msg->state; u32 val = 0; if (xfer->bits_per_word > 8) { @@ -194,10 +194,10 @@ static void ep93xx_do_write(struct spi_master *master) writel(val, espi->mmio + SSPDR); } -static void ep93xx_do_read(struct spi_master *master) +static void ep93xx_do_read(struct spi_controller *host) { - struct ep93xx_spi *espi = spi_master_get_devdata(master); - struct spi_transfer *xfer = master->cur_msg->state; + struct ep93xx_spi *espi = spi_controller_get_devdata(host); + struct spi_transfer *xfer = host->cur_msg->state; u32 val; val = readl(espi->mmio + SSPDR); @@ -214,7 +214,7 @@ static void ep93xx_do_read(struct spi_master *master) /** * ep93xx_spi_read_write() - perform next RX/TX transfer - * @master: SPI master + * @host: SPI host * * This function transfers next bytes (or half-words) to/from RX/TX FIFOs. If * called several times, the whole transfer will be completed. Returns @@ -223,20 +223,20 @@ static void ep93xx_do_read(struct spi_master *master) * When this function is finished, RX FIFO should be empty and TX FIFO should be * full. */ -static int ep93xx_spi_read_write(struct spi_master *master) +static int ep93xx_spi_read_write(struct spi_controller *host) { - struct ep93xx_spi *espi = spi_master_get_devdata(master); - struct spi_transfer *xfer = master->cur_msg->state; + struct ep93xx_spi *espi = spi_controller_get_devdata(host); + struct spi_transfer *xfer = host->cur_msg->state; /* read as long as RX FIFO has frames in it */ while ((readl(espi->mmio + SSPSR) & SSPSR_RNE)) { - ep93xx_do_read(master); + ep93xx_do_read(host); espi->fifo_level--; } /* write as long as TX FIFO has room */ while (espi->fifo_level < SPI_FIFO_SIZE && espi->tx < xfer->len) { - ep93xx_do_write(master); + ep93xx_do_write(host); espi->fifo_level++; } @@ -261,7 +261,7 @@ ep93xx_dma_data_to_trans_dir(enum dma_data_direction dir) /** * ep93xx_spi_dma_prepare() - prepares a DMA transfer - * @master: SPI master + * @host: SPI host * @dir: DMA transfer direction * * Function configures the DMA, maps the buffer and prepares the DMA @@ -269,11 +269,11 @@ ep93xx_dma_data_to_trans_dir(enum dma_data_direction dir) * in case of failure. */ static struct dma_async_tx_descriptor * -ep93xx_spi_dma_prepare(struct spi_master *master, +ep93xx_spi_dma_prepare(struct spi_controller *host, enum dma_data_direction dir) { - struct ep93xx_spi *espi = spi_master_get_devdata(master); - struct spi_transfer *xfer = master->cur_msg->state; + struct ep93xx_spi *espi = spi_controller_get_devdata(host); + struct spi_transfer *xfer = host->cur_msg->state; struct dma_async_tx_descriptor *txd; enum dma_slave_buswidth buswidth; struct dma_slave_config conf; @@ -348,7 +348,7 @@ ep93xx_spi_dma_prepare(struct spi_master *master, } if (WARN_ON(len)) { - dev_warn(&master->dev, "len = %zu expected 0!\n", len); + dev_warn(&host->dev, "len = %zu expected 0!\n", len); return ERR_PTR(-EINVAL); } @@ -367,16 +367,16 @@ ep93xx_spi_dma_prepare(struct spi_master *master, /** * ep93xx_spi_dma_finish() - finishes with a DMA transfer - * @master: SPI master + * @host: SPI host * @dir: DMA transfer direction * * Function finishes with the DMA transfer. After this, the DMA buffer is * unmapped. */ -static void ep93xx_spi_dma_finish(struct spi_master *master, +static void ep93xx_spi_dma_finish(struct spi_controller *host, enum dma_data_direction dir) { - struct ep93xx_spi *espi = spi_master_get_devdata(master); + struct ep93xx_spi *espi = spi_controller_get_devdata(host); struct dma_chan *chan; struct sg_table *sgt; @@ -393,35 +393,35 @@ static void ep93xx_spi_dma_finish(struct spi_master *master, static void ep93xx_spi_dma_callback(void *callback_param) { - struct spi_master *master = callback_param; + struct spi_controller *host = callback_param; - ep93xx_spi_dma_finish(master, DMA_TO_DEVICE); - ep93xx_spi_dma_finish(master, DMA_FROM_DEVICE); + ep93xx_spi_dma_finish(host, DMA_TO_DEVICE); + ep93xx_spi_dma_finish(host, DMA_FROM_DEVICE); - spi_finalize_current_transfer(master); + spi_finalize_current_transfer(host); } -static int ep93xx_spi_dma_transfer(struct spi_master *master) +static int ep93xx_spi_dma_transfer(struct spi_controller *host) { - struct ep93xx_spi *espi = spi_master_get_devdata(master); + struct ep93xx_spi *espi = spi_controller_get_devdata(host); struct dma_async_tx_descriptor *rxd, *txd; - rxd = ep93xx_spi_dma_prepare(master, DMA_FROM_DEVICE); + rxd = ep93xx_spi_dma_prepare(host, DMA_FROM_DEVICE); if (IS_ERR(rxd)) { - dev_err(&master->dev, "DMA RX failed: %ld\n", PTR_ERR(rxd)); + dev_err(&host->dev, "DMA RX failed: %ld\n", PTR_ERR(rxd)); return PTR_ERR(rxd); } - txd = ep93xx_spi_dma_prepare(master, DMA_TO_DEVICE); + txd = ep93xx_spi_dma_prepare(host, DMA_TO_DEVICE); if (IS_ERR(txd)) { - ep93xx_spi_dma_finish(master, DMA_FROM_DEVICE); - dev_err(&master->dev, "DMA TX failed: %ld\n", PTR_ERR(txd)); + ep93xx_spi_dma_finish(host, DMA_FROM_DEVICE); + dev_err(&host->dev, "DMA TX failed: %ld\n", PTR_ERR(txd)); return PTR_ERR(txd); } /* We are ready when RX is done */ rxd->callback = ep93xx_spi_dma_callback; - rxd->callback_param = master; + rxd->callback_param = host; /* Now submit both descriptors and start DMA */ dmaengine_submit(rxd); @@ -436,8 +436,8 @@ static int ep93xx_spi_dma_transfer(struct spi_master *master) static irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id) { - struct spi_master *master = dev_id; - struct ep93xx_spi *espi = spi_master_get_devdata(master); + struct spi_controller *host = dev_id; + struct ep93xx_spi *espi = spi_controller_get_devdata(host); u32 val; /* @@ -447,15 +447,15 @@ static irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id) if (readl(espi->mmio + SSPIIR) & SSPIIR_RORIS) { /* clear the overrun interrupt */ writel(0, espi->mmio + SSPICR); - dev_warn(&master->dev, + dev_warn(&host->dev, "receive overrun, aborting the message\n"); - master->cur_msg->status = -EIO; + host->cur_msg->status = -EIO; } else { /* * Interrupt is either RX (RIS) or TX (TIS). For both cases we * simply execute next data transfer. */ - if (ep93xx_spi_read_write(master)) { + if (ep93xx_spi_read_write(host)) { /* * In normal case, there still is some processing left * for current transfer. Let's wait for the next @@ -474,26 +474,26 @@ static irqreturn_t ep93xx_spi_interrupt(int irq, void *dev_id) val &= ~(SSPCR1_RORIE | SSPCR1_TIE | SSPCR1_RIE); writel(val, espi->mmio + SSPCR1); - spi_finalize_current_transfer(master); + spi_finalize_current_transfer(host); return IRQ_HANDLED; } -static int ep93xx_spi_transfer_one(struct spi_master *master, +static int ep93xx_spi_transfer_one(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { - struct ep93xx_spi *espi = spi_master_get_devdata(master); + struct ep93xx_spi *espi = spi_controller_get_devdata(host); u32 val; int ret; - ret = ep93xx_spi_chip_setup(master, spi, xfer); + ret = ep93xx_spi_chip_setup(host, spi, xfer); if (ret) { - dev_err(&master->dev, "failed to setup chip for transfer\n"); + dev_err(&host->dev, "failed to setup chip for transfer\n"); return ret; } - master->cur_msg->state = xfer; + host->cur_msg->state = xfer; espi->rx = 0; espi->tx = 0; @@ -503,10 +503,10 @@ static int ep93xx_spi_transfer_one(struct spi_master *master, * So in these cases we will be using PIO and don't bother for DMA. */ if (espi->dma_rx && xfer->len > SPI_FIFO_SIZE) - return ep93xx_spi_dma_transfer(master); + return ep93xx_spi_dma_transfer(host); /* Using PIO so prime the TX FIFO and enable interrupts */ - ep93xx_spi_read_write(master); + ep93xx_spi_read_write(host); val = readl(espi->mmio + SSPCR1); val |= (SSPCR1_RORIE | SSPCR1_TIE | SSPCR1_RIE); @@ -516,10 +516,10 @@ static int ep93xx_spi_transfer_one(struct spi_master *master, return 1; } -static int ep93xx_spi_prepare_message(struct spi_master *master, +static int ep93xx_spi_prepare_message(struct spi_controller *host, struct spi_message *msg) { - struct ep93xx_spi *espi = spi_master_get_devdata(master); + struct ep93xx_spi *espi = spi_controller_get_devdata(host); unsigned long timeout; /* @@ -528,7 +528,7 @@ static int ep93xx_spi_prepare_message(struct spi_master *master, timeout = jiffies + msecs_to_jiffies(SPI_TIMEOUT); while (readl(espi->mmio + SSPSR) & SSPSR_RNE) { if (time_after(jiffies, timeout)) { - dev_warn(&master->dev, + dev_warn(&host->dev, "timeout while flushing RX FIFO\n"); return -ETIMEDOUT; } @@ -544,9 +544,9 @@ static int ep93xx_spi_prepare_message(struct spi_master *master, return 0; } -static int ep93xx_spi_prepare_hardware(struct spi_master *master) +static int ep93xx_spi_prepare_hardware(struct spi_controller *host) { - struct ep93xx_spi *espi = spi_master_get_devdata(master); + struct ep93xx_spi *espi = spi_controller_get_devdata(host); u32 val; int ret; @@ -561,9 +561,9 @@ static int ep93xx_spi_prepare_hardware(struct spi_master *master) return 0; } -static int ep93xx_spi_unprepare_hardware(struct spi_master *master) +static int ep93xx_spi_unprepare_hardware(struct spi_controller *host) { - struct ep93xx_spi *espi = spi_master_get_devdata(master); + struct ep93xx_spi *espi = spi_controller_get_devdata(host); u32 val; val = readl(espi->mmio + SSPCR1); @@ -646,7 +646,7 @@ static void ep93xx_spi_release_dma(struct ep93xx_spi *espi) static int ep93xx_spi_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *host; struct ep93xx_spi_info *info; struct ep93xx_spi *espi; struct resource *res; @@ -661,63 +661,56 @@ static int ep93xx_spi_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) - return -EBUSY; + return irq; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "unable to get iomem resource\n"); - return -ENODEV; - } - - master = spi_alloc_master(&pdev->dev, sizeof(*espi)); - if (!master) + host = spi_alloc_host(&pdev->dev, sizeof(*espi)); + if (!host) return -ENOMEM; - master->use_gpio_descriptors = true; - master->prepare_transfer_hardware = ep93xx_spi_prepare_hardware; - master->unprepare_transfer_hardware = ep93xx_spi_unprepare_hardware; - master->prepare_message = ep93xx_spi_prepare_message; - master->transfer_one = ep93xx_spi_transfer_one; - master->bus_num = pdev->id; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); + host->use_gpio_descriptors = true; + host->prepare_transfer_hardware = ep93xx_spi_prepare_hardware; + host->unprepare_transfer_hardware = ep93xx_spi_unprepare_hardware; + host->prepare_message = ep93xx_spi_prepare_message; + host->transfer_one = ep93xx_spi_transfer_one; + host->bus_num = pdev->id; + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + host->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); /* * The SPI core will count the number of GPIO descriptors to figure * out the number of chip selects available on the platform. */ - master->num_chipselect = 0; + host->num_chipselect = 0; - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); - espi = spi_master_get_devdata(master); + espi = spi_controller_get_devdata(host); espi->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(espi->clk)) { dev_err(&pdev->dev, "unable to get spi clock\n"); error = PTR_ERR(espi->clk); - goto fail_release_master; + goto fail_release_host; } /* * Calculate maximum and minimum supported clock rates * for the controller. */ - master->max_speed_hz = clk_get_rate(espi->clk) / 2; - master->min_speed_hz = clk_get_rate(espi->clk) / (254 * 256); + host->max_speed_hz = clk_get_rate(espi->clk) / 2; + host->min_speed_hz = clk_get_rate(espi->clk) / (254 * 256); - espi->sspdr_phys = res->start + SSPDR; - - espi->mmio = devm_ioremap_resource(&pdev->dev, res); + espi->mmio = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(espi->mmio)) { error = PTR_ERR(espi->mmio); - goto fail_release_master; + goto fail_release_host; } + espi->sspdr_phys = res->start + SSPDR; error = devm_request_irq(&pdev->dev, irq, ep93xx_spi_interrupt, - 0, "ep93xx-spi", master); + 0, "ep93xx-spi", host); if (error) { dev_err(&pdev->dev, "failed to request irq\n"); - goto fail_release_master; + goto fail_release_host; } if (info->use_dma && ep93xx_spi_setup_dma(espi)) @@ -726,9 +719,9 @@ static int ep93xx_spi_probe(struct platform_device *pdev) /* make sure that the hardware is disabled */ writel(0, espi->mmio + SSPCR1); - error = devm_spi_register_master(&pdev->dev, master); + error = devm_spi_register_controller(&pdev->dev, host); if (error) { - dev_err(&pdev->dev, "failed to register SPI master\n"); + dev_err(&pdev->dev, "failed to register SPI host\n"); goto fail_free_dma; } @@ -739,16 +732,16 @@ static int ep93xx_spi_probe(struct platform_device *pdev) fail_free_dma: ep93xx_spi_release_dma(espi); -fail_release_master: - spi_master_put(master); +fail_release_host: + spi_controller_put(host); return error; } static void ep93xx_spi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct ep93xx_spi *espi = spi_master_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(pdev); + struct ep93xx_spi *espi = spi_controller_get_devdata(host); ep93xx_spi_release_dma(espi); } diff --git a/drivers/spi/spi-falcon.c b/drivers/spi/spi-falcon.c index 4c103dff0d44..84279058f0f1 100644 --- a/drivers/spi/spi-falcon.c +++ b/drivers/spi/spi-falcon.c @@ -91,14 +91,14 @@ struct falcon_sflash { u32 sfcmd; /* for caching of opcode, direction, ... */ - struct spi_master *master; + struct spi_controller *host; }; int falcon_sflash_xfer(struct spi_device *spi, struct spi_transfer *t, unsigned long flags) { struct device *dev = &spi->dev; - struct falcon_sflash *priv = spi_master_get_devdata(spi->master); + struct falcon_sflash *priv = spi_controller_get_devdata(spi->controller); const u8 *txp = t->tx_buf; u8 *rxp = t->rx_buf; unsigned int bytelen = ((8 * t->len + 7) / 8); @@ -351,10 +351,10 @@ static int falcon_sflash_setup(struct spi_device *spi) return 0; } -static int falcon_sflash_xfer_one(struct spi_master *master, +static int falcon_sflash_xfer_one(struct spi_controller *host, struct spi_message *m) { - struct falcon_sflash *priv = spi_master_get_devdata(master); + struct falcon_sflash *priv = spi_controller_get_devdata(host); struct spi_transfer *t; unsigned long spi_flags; unsigned long flags; @@ -382,7 +382,7 @@ static int falcon_sflash_xfer_one(struct spi_master *master, } m->status = ret; - spi_finalize_current_message(master); + spi_finalize_current_message(host); return 0; } @@ -390,25 +390,25 @@ static int falcon_sflash_xfer_one(struct spi_master *master, static int falcon_sflash_probe(struct platform_device *pdev) { struct falcon_sflash *priv; - struct spi_master *master; + struct spi_controller *host; int ret; - master = spi_alloc_master(&pdev->dev, sizeof(*priv)); - if (!master) + host = spi_alloc_host(&pdev->dev, sizeof(*priv)); + if (!host) return -ENOMEM; - priv = spi_master_get_devdata(master); - priv->master = master; + priv = spi_controller_get_devdata(host); + priv->host = host; - master->mode_bits = SPI_MODE_3; - master->flags = SPI_MASTER_HALF_DUPLEX; - master->setup = falcon_sflash_setup; - master->transfer_one_message = falcon_sflash_xfer_one; - master->dev.of_node = pdev->dev.of_node; + host->mode_bits = SPI_MODE_3; + host->flags = SPI_CONTROLLER_HALF_DUPLEX; + host->setup = falcon_sflash_setup; + host->transfer_one_message = falcon_sflash_xfer_one; + host->dev.of_node = pdev->dev.of_node; - ret = devm_spi_register_master(&pdev->dev, master); + ret = devm_spi_register_controller(&pdev->dev, host); if (ret) - spi_master_put(master); + spi_controller_put(host); return ret; } diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c index ba3b17d7c9ec..fc9e33be1e0e 100644 --- a/drivers/spi/spi-fsi.c +++ b/drivers/spi/spi-fsi.c @@ -542,7 +542,7 @@ static int fsi_spi_probe(struct device *dev) if (of_property_read_u32(np, "reg", &base)) continue; - ctlr = spi_alloc_master(dev, sizeof(*ctx)); + ctlr = spi_alloc_host(dev, sizeof(*ctx)); if (!ctlr) { of_node_put(np); break; diff --git a/drivers/spi/spi-fsl-cpm.c b/drivers/spi/spi-fsl-cpm.c index 38452089e8f3..47c7a5c6257f 100644 --- a/drivers/spi/spi-fsl-cpm.c +++ b/drivers/spi/spi-fsl-cpm.c @@ -56,12 +56,12 @@ void fsl_spi_cpm_reinit_txrx(struct mpc8xxx_spi *mspi) QE_CR_PROTOCOL_UNSPECIFIED, 0); } else { if (mspi->flags & SPI_CPM1) { - out_be32(&mspi->pram->rstate, 0); - out_be16(&mspi->pram->rbptr, - in_be16(&mspi->pram->rbase)); - out_be32(&mspi->pram->tstate, 0); - out_be16(&mspi->pram->tbptr, - in_be16(&mspi->pram->tbase)); + iowrite32be(0, &mspi->pram->rstate); + iowrite16be(ioread16be(&mspi->pram->rbase), + &mspi->pram->rbptr); + iowrite32be(0, &mspi->pram->tstate); + iowrite16be(ioread16be(&mspi->pram->tbase), + &mspi->pram->tbptr); } else { cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX); } @@ -75,24 +75,24 @@ static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi) struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd; unsigned int xfer_len = min(mspi->count, SPI_MRBLR); unsigned int xfer_ofs; - struct fsl_spi_reg *reg_base = mspi->reg_base; + struct fsl_spi_reg __iomem *reg_base = mspi->reg_base; xfer_ofs = mspi->xfer_in_progress->len - mspi->count; if (mspi->rx_dma == mspi->dma_dummy_rx) - out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma); + iowrite32be(mspi->rx_dma, &rx_bd->cbd_bufaddr); else - out_be32(&rx_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs); - out_be16(&rx_bd->cbd_datlen, 0); - out_be16(&rx_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP); + iowrite32be(mspi->rx_dma + xfer_ofs, &rx_bd->cbd_bufaddr); + iowrite16be(0, &rx_bd->cbd_datlen); + iowrite16be(BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP, &rx_bd->cbd_sc); if (mspi->tx_dma == mspi->dma_dummy_tx) - out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma); + iowrite32be(mspi->tx_dma, &tx_bd->cbd_bufaddr); else - out_be32(&tx_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs); - out_be16(&tx_bd->cbd_datlen, xfer_len); - out_be16(&tx_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP | - BD_SC_LAST); + iowrite32be(mspi->tx_dma + xfer_ofs, &tx_bd->cbd_bufaddr); + iowrite16be(xfer_len, &tx_bd->cbd_datlen); + iowrite16be(BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP | BD_SC_LAST, + &tx_bd->cbd_sc); /* start transfer */ mpc8xxx_spi_write_reg(®_base->command, SPCOM_STR); @@ -102,7 +102,7 @@ int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi, struct spi_transfer *t, bool is_dma_mapped) { struct device *dev = mspi->dev; - struct fsl_spi_reg *reg_base = mspi->reg_base; + struct fsl_spi_reg __iomem *reg_base = mspi->reg_base; if (is_dma_mapped) { mspi->map_tx_dma = 0; @@ -123,7 +123,7 @@ int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi, } if (t->bits_per_word == 16 && t->tx_buf) { const u16 *src = t->tx_buf; - u16 *dst; + __le16 *dst; int i; dst = kmalloc(t->len, GFP_KERNEL); @@ -202,12 +202,12 @@ EXPORT_SYMBOL_GPL(fsl_spi_cpm_bufs_complete); void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events) { u16 len; - struct fsl_spi_reg *reg_base = mspi->reg_base; + struct fsl_spi_reg __iomem *reg_base = mspi->reg_base; dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__, - in_be16(&mspi->rx_bd->cbd_datlen), mspi->count); + ioread16be(&mspi->rx_bd->cbd_datlen), mspi->count); - len = in_be16(&mspi->rx_bd->cbd_datlen); + len = ioread16be(&mspi->rx_bd->cbd_datlen); if (len > mspi->count) { WARN_ON(1); len = mspi->count; @@ -328,7 +328,7 @@ int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi) } if (mspi->flags & SPI_CPM1) { - void *pram; + void __iomem *pram; pram = devm_platform_ioremap_resource(to_platform_device(dev), 1); @@ -374,21 +374,21 @@ int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi) mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd)); /* Initialize parameter ram. */ - out_be16(&mspi->pram->tbase, cpm_muram_offset(mspi->tx_bd)); - out_be16(&mspi->pram->rbase, cpm_muram_offset(mspi->rx_bd)); - out_8(&mspi->pram->tfcr, CPMFCR_EB | CPMFCR_GBL); - out_8(&mspi->pram->rfcr, CPMFCR_EB | CPMFCR_GBL); - out_be16(&mspi->pram->mrblr, SPI_MRBLR); - out_be32(&mspi->pram->rstate, 0); - out_be32(&mspi->pram->rdp, 0); - out_be16(&mspi->pram->rbptr, 0); - out_be16(&mspi->pram->rbc, 0); - out_be32(&mspi->pram->rxtmp, 0); - out_be32(&mspi->pram->tstate, 0); - out_be32(&mspi->pram->tdp, 0); - out_be16(&mspi->pram->tbptr, 0); - out_be16(&mspi->pram->tbc, 0); - out_be32(&mspi->pram->txtmp, 0); + iowrite16be(cpm_muram_offset(mspi->tx_bd), &mspi->pram->tbase); + iowrite16be(cpm_muram_offset(mspi->rx_bd), &mspi->pram->rbase); + iowrite8(CPMFCR_EB | CPMFCR_GBL, &mspi->pram->tfcr); + iowrite8(CPMFCR_EB | CPMFCR_GBL, &mspi->pram->rfcr); + iowrite16be(SPI_MRBLR, &mspi->pram->mrblr); + iowrite32be(0, &mspi->pram->rstate); + iowrite32be(0, &mspi->pram->rdp); + iowrite16be(0, &mspi->pram->rbptr); + iowrite16be(0, &mspi->pram->rbc); + iowrite32be(0, &mspi->pram->rxtmp); + iowrite32be(0, &mspi->pram->tstate); + iowrite32be(0, &mspi->pram->tdp); + iowrite16be(0, &mspi->pram->tbptr); + iowrite16be(0, &mspi->pram->tbc); + iowrite32be(0, &mspi->pram->txtmp); return 0; diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c index 674cfe05f411..8318249f8a1f 100644 --- a/drivers/spi/spi-fsl-dspi.c +++ b/drivers/spi/spi-fsl-dspi.c @@ -13,7 +13,8 @@ #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/pinctrl/consumer.h> #include <linux/regmap.h> #include <linux/spi/spi.h> @@ -22,7 +23,7 @@ #define DRIVER_NAME "fsl-dspi" #define SPI_MCR 0x00 -#define SPI_MCR_MASTER BIT(31) +#define SPI_MCR_HOST BIT(31) #define SPI_MCR_PCSIS(x) ((x) << 16) #define SPI_MCR_CLR_TXF BIT(11) #define SPI_MCR_CLR_RXF BIT(10) @@ -339,7 +340,7 @@ static u32 dspi_pop_tx_pushr(struct fsl_dspi *dspi) { u16 cmd = dspi->tx_cmd, data = dspi_pop_tx(dspi); - if (spi_controller_is_slave(dspi->ctlr)) + if (spi_controller_is_target(dspi->ctlr)) return data; if (dspi->len > 0) @@ -429,7 +430,7 @@ static int dspi_next_xfer_dma_submit(struct fsl_dspi *dspi) dma_async_issue_pending(dma->chan_rx); dma_async_issue_pending(dma->chan_tx); - if (spi_controller_is_slave(dspi->ctlr)) { + if (spi_controller_is_target(dspi->ctlr)) { wait_for_completion_interruptible(&dspi->dma->cmd_rx_complete); return 0; } @@ -502,15 +503,14 @@ static int dspi_request_dma(struct fsl_dspi *dspi, phys_addr_t phy_addr) dma->chan_rx = dma_request_chan(dev, "rx"); if (IS_ERR(dma->chan_rx)) { - dev_err(dev, "rx dma channel not available\n"); - ret = PTR_ERR(dma->chan_rx); - return ret; + return dev_err_probe(dev, PTR_ERR(dma->chan_rx), + "rx dma channel not available\n"); } dma->chan_tx = dma_request_chan(dev, "tx"); if (IS_ERR(dma->chan_tx)) { - dev_err(dev, "tx dma channel not available\n"); ret = PTR_ERR(dma->chan_tx); + dev_err_probe(dev, ret, "tx dma channel not available\n"); goto err_tx_channel; } @@ -1061,7 +1061,7 @@ static int dspi_setup(struct spi_device *spi) if (spi->mode & SPI_CPHA) chip->ctar_val |= SPI_CTAR_CPHA; - if (!spi_controller_is_slave(dspi->ctlr)) { + if (!spi_controller_is_target(dspi->ctlr)) { chip->ctar_val |= SPI_CTAR_PCSSCK(pcssck) | SPI_CTAR_CSSCK(cssck) | SPI_CTAR_PASC(pasc) | @@ -1216,8 +1216,8 @@ static int dspi_init(struct fsl_dspi *dspi) if (dspi->devtype_data->trans_mode == DSPI_XSPI_MODE) mcr |= SPI_MCR_XSPI; - if (!spi_controller_is_slave(dspi->ctlr)) - mcr |= SPI_MCR_MASTER; + if (!spi_controller_is_target(dspi->ctlr)) + mcr |= SPI_MCR_HOST; regmap_write(dspi->regmap, SPI_MCR, mcr); regmap_write(dspi->regmap, SPI_SR, SPI_SR_CLEAR); @@ -1240,13 +1240,13 @@ static int dspi_init(struct fsl_dspi *dspi) return 0; } -static int dspi_slave_abort(struct spi_master *master) +static int dspi_target_abort(struct spi_controller *host) { - struct fsl_dspi *dspi = spi_master_get_devdata(master); + struct fsl_dspi *dspi = spi_controller_get_devdata(host); /* * Terminate all pending DMA transactions for the SPI working - * in SLAVE mode. + * in TARGET mode. */ if (dspi->devtype_data->trans_mode == DSPI_DMA_MODE) { dmaengine_terminate_sync(dspi->dma->chan_rx); @@ -1277,7 +1277,7 @@ static int dspi_probe(struct platform_device *pdev) if (!dspi) return -ENOMEM; - ctlr = spi_alloc_master(&pdev->dev, 0); + ctlr = spi_alloc_host(&pdev->dev, 0); if (!ctlr) return -ENOMEM; @@ -1292,7 +1292,7 @@ static int dspi_probe(struct platform_device *pdev) ctlr->dev.of_node = pdev->dev.of_node; ctlr->cleanup = dspi_cleanup; - ctlr->slave_abort = dspi_slave_abort; + ctlr->target_abort = dspi_target_abort; ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; ctlr->use_gpio_descriptors = true; @@ -1317,7 +1317,7 @@ static int dspi_probe(struct platform_device *pdev) ctlr->bus_num = bus_num; if (of_property_read_bool(np, "spi-slave")) - ctlr->slave = true; + ctlr->target = true; dspi->devtype_data = of_device_get_match_data(&pdev->dev); if (!dspi->devtype_data) { diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index b3d2d3db5850..ea647ee94da8 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -148,7 +148,7 @@ static inline void fsl_espi_write_reg8(struct fsl_espi *espi, int offset, static int fsl_espi_check_message(struct spi_message *m) { - struct fsl_espi *espi = spi_master_get_devdata(m->spi->master); + struct fsl_espi *espi = spi_controller_get_devdata(m->spi->controller); struct spi_transfer *t, *first; if (m->frame_length > SPCOM_TRANLEN_MAX) { @@ -323,7 +323,7 @@ start: static void fsl_espi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) { - struct fsl_espi *espi = spi_master_get_devdata(spi->master); + struct fsl_espi *espi = spi_controller_get_devdata(spi->controller); int bits_per_word = t ? t->bits_per_word : spi->bits_per_word; u32 pm, hz = t ? t->speed_hz : spi->max_speed_hz; struct fsl_espi_cs *cs = spi_get_ctldata(spi); @@ -351,7 +351,7 @@ static void fsl_espi_setup_transfer(struct spi_device *spi, static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) { - struct fsl_espi *espi = spi_master_get_devdata(spi->master); + struct fsl_espi *espi = spi_controller_get_devdata(spi->controller); unsigned int rx_len = t->len; u32 mask, spcom; int ret; @@ -396,7 +396,7 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t) static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans) { - struct fsl_espi *espi = spi_master_get_devdata(m->spi->master); + struct fsl_espi *espi = spi_controller_get_devdata(m->spi->controller); struct spi_device *spi = m->spi; int ret; @@ -432,7 +432,7 @@ static int fsl_espi_trans(struct spi_message *m, struct spi_transfer *trans) return ret; } -static int fsl_espi_do_one_msg(struct spi_master *master, +static int fsl_espi_do_one_msg(struct spi_controller *host, struct spi_message *m) { unsigned int rx_nbits = 0, delay_nsecs = 0; @@ -470,7 +470,7 @@ out: if (m->status == -EINPROGRESS) m->status = ret; - spi_finalize_current_message(master); + spi_finalize_current_message(host); return ret; } @@ -488,7 +488,7 @@ static int fsl_espi_setup(struct spi_device *spi) spi_set_ctldata(spi, cs); } - espi = spi_master_get_devdata(spi->master); + espi = spi_controller_get_devdata(spi->controller); pm_runtime_get_sync(espi->dev); @@ -584,8 +584,8 @@ static irqreturn_t fsl_espi_irq(s32 irq, void *context_data) #ifdef CONFIG_PM static int fsl_espi_runtime_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct fsl_espi *espi = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct fsl_espi *espi = spi_controller_get_devdata(host); u32 regval; regval = fsl_espi_read_reg(espi, ESPI_SPMODE); @@ -597,8 +597,8 @@ static int fsl_espi_runtime_suspend(struct device *dev) static int fsl_espi_runtime_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct fsl_espi *espi = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct fsl_espi *espi = spi_controller_get_devdata(host); u32 regval; regval = fsl_espi_read_reg(espi, ESPI_SPMODE); @@ -616,8 +616,8 @@ static size_t fsl_espi_max_message_size(struct spi_device *spi) static void fsl_espi_init_regs(struct device *dev, bool initial) { - struct spi_master *master = dev_get_drvdata(dev); - struct fsl_espi *espi = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct fsl_espi *espi = spi_controller_get_devdata(host); struct device_node *nc; u32 csmode, cs, prop; int ret; @@ -629,10 +629,10 @@ static void fsl_espi_init_regs(struct device *dev, bool initial) fsl_espi_write_reg(espi, ESPI_SPIE, 0xffffffff); /* Init eSPI CS mode register */ - for_each_available_child_of_node(master->dev.of_node, nc) { + for_each_available_child_of_node(host->dev.of_node, nc) { /* get chip select */ ret = of_property_read_u32(nc, "reg", &cs); - if (ret || cs >= master->num_chipselect) + if (ret || cs >= host->num_chipselect) continue; csmode = CSMODE_INIT_VAL; @@ -664,28 +664,28 @@ static void fsl_espi_init_regs(struct device *dev, bool initial) static int fsl_espi_probe(struct device *dev, struct resource *mem, unsigned int irq, unsigned int num_cs) { - struct spi_master *master; + struct spi_controller *host; struct fsl_espi *espi; int ret; - master = spi_alloc_master(dev, sizeof(struct fsl_espi)); - if (!master) + host = spi_alloc_host(dev, sizeof(struct fsl_espi)); + if (!host) return -ENOMEM; - dev_set_drvdata(dev, master); + dev_set_drvdata(dev, host); - master->mode_bits = SPI_RX_DUAL | SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | - SPI_LSB_FIRST | SPI_LOOP; - master->dev.of_node = dev->of_node; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); - master->setup = fsl_espi_setup; - master->cleanup = fsl_espi_cleanup; - master->transfer_one_message = fsl_espi_do_one_msg; - master->auto_runtime_pm = true; - master->max_message_size = fsl_espi_max_message_size; - master->num_chipselect = num_cs; + host->mode_bits = SPI_RX_DUAL | SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | + SPI_LSB_FIRST | SPI_LOOP; + host->dev.of_node = dev->of_node; + host->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16); + host->setup = fsl_espi_setup; + host->cleanup = fsl_espi_cleanup; + host->transfer_one_message = fsl_espi_do_one_msg; + host->auto_runtime_pm = true; + host->max_message_size = fsl_espi_max_message_size; + host->num_chipselect = num_cs; - espi = spi_master_get_devdata(master); + espi = spi_controller_get_devdata(host); spin_lock_init(&espi->lock); espi->dev = dev; @@ -696,8 +696,8 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem, goto err_probe; } /* determined by clock divider fields DIV16/PM in register SPMODEx */ - master->min_speed_hz = DIV_ROUND_UP(espi->spibrg, 4 * 16 * 16); - master->max_speed_hz = DIV_ROUND_UP(espi->spibrg, 4); + host->min_speed_hz = DIV_ROUND_UP(espi->spibrg, 4 * 16 * 16); + host->max_speed_hz = DIV_ROUND_UP(espi->spibrg, 4); init_completion(&espi->done); @@ -720,7 +720,7 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem, pm_runtime_enable(dev); pm_runtime_get_sync(dev); - ret = devm_spi_register_master(dev, master); + ret = devm_spi_register_controller(dev, host); if (ret < 0) goto err_pm; @@ -736,7 +736,7 @@ err_pm: pm_runtime_disable(dev); pm_runtime_set_suspended(dev); err_probe: - spi_master_put(master); + spi_controller_put(host); return ret; } @@ -791,10 +791,10 @@ static void of_fsl_espi_remove(struct platform_device *dev) #ifdef CONFIG_PM_SLEEP static int of_fsl_espi_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); + struct spi_controller *host = dev_get_drvdata(dev); int ret; - ret = spi_master_suspend(master); + ret = spi_controller_suspend(host); if (ret) return ret; @@ -803,7 +803,7 @@ static int of_fsl_espi_suspend(struct device *dev) static int of_fsl_espi_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); + struct spi_controller *host = dev_get_drvdata(dev); int ret; fsl_espi_init_regs(dev, false); @@ -812,7 +812,7 @@ static int of_fsl_espi_resume(struct device *dev) if (ret < 0) return ret; - return spi_master_resume(master); + return spi_controller_resume(host); } #endif /* CONFIG_PM_SLEEP */ diff --git a/drivers/spi/spi-fsl-lib.c b/drivers/spi/spi-fsl-lib.c index 76e1192eb025..885757c29fbb 100644 --- a/drivers/spi/spi-fsl-lib.c +++ b/drivers/spi/spi-fsl-lib.c @@ -18,7 +18,8 @@ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/module.h> -#include <linux/of_platform.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/spi/spi.h> #ifdef CONFIG_FSL_SOC #include <sysdev/fsl_soc.h> diff --git a/drivers/spi/spi-fsl-lib.h b/drivers/spi/spi-fsl-lib.h index 015a1abb6a84..50a07f984b23 100644 --- a/drivers/spi/spi-fsl-lib.h +++ b/drivers/spi/spi-fsl-lib.h @@ -103,12 +103,9 @@ extern void mpc8xxx_spi_rx_buf_u32(u32 data, struct mpc8xxx_spi *mpc8xxx_spi); extern struct mpc8xxx_spi_probe_info *to_of_pinfo( struct fsl_spi_platform_data *pdata); -extern int mpc8xxx_spi_bufs(struct mpc8xxx_spi *mspi, - struct spi_transfer *t, unsigned int len); extern const char *mpc8xxx_spi_strmode(unsigned int flags); extern void mpc8xxx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq); -extern int mpc8xxx_spi_remove(struct device *dev); extern int of_mpc8xxx_spi_probe(struct platform_device *ofdev); #endif /* __SPI_FSL_LIB_H__ */ diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index fb68c72df171..11991eb12636 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -17,7 +17,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> #include <linux/dma/imx-dma.h> @@ -73,7 +72,7 @@ #define CFGR1_PINCFG (BIT(24)|BIT(25)) #define CFGR1_PCSPOL BIT(8) #define CFGR1_NOSTALL BIT(3) -#define CFGR1_MASTER BIT(0) +#define CFGR1_HOST BIT(0) #define FSR_TXCOUNT (0xFF) #define RSR_RXEMPTY BIT(1) #define TCR_CPOL BIT(31) @@ -97,8 +96,7 @@ struct fsl_lpspi_data { unsigned long base_phys; struct clk *clk_ipg; struct clk *clk_per; - bool is_slave; - u32 num_cs; + bool is_target; bool is_only_cs1; bool is_first_byte; @@ -115,7 +113,7 @@ struct fsl_lpspi_data { struct lpspi_config config; struct completion xfer_done; - bool slave_aborted; + bool target_aborted; /* DMA */ bool usedma; @@ -236,7 +234,7 @@ static void fsl_lpspi_write_tx_fifo(struct fsl_lpspi_data *fsl_lpspi) } if (txfifo_cnt < fsl_lpspi->txfifosize) { - if (!fsl_lpspi->is_slave) { + if (!fsl_lpspi->is_target) { temp = readl(fsl_lpspi->base + IMX7ULP_TCR); temp &= ~TCR_CONTC; writel(temp, fsl_lpspi->base + IMX7ULP_TCR); @@ -260,7 +258,7 @@ static void fsl_lpspi_set_cmd(struct fsl_lpspi_data *fsl_lpspi) temp |= fsl_lpspi->config.bpw - 1; temp |= (fsl_lpspi->config.mode & 0x3) << 30; temp |= (fsl_lpspi->config.chip_select & 0x3) << 24; - if (!fsl_lpspi->is_slave) { + if (!fsl_lpspi->is_target) { temp |= fsl_lpspi->config.prescale << 27; /* * Set TCR_CONT will keep SS asserted after current transfer. @@ -387,7 +385,7 @@ static int fsl_lpspi_config(struct fsl_lpspi_data *fsl_lpspi) u32 temp; int ret; - if (!fsl_lpspi->is_slave) { + if (!fsl_lpspi->is_target) { ret = fsl_lpspi_set_bitrate(fsl_lpspi); if (ret) return ret; @@ -395,8 +393,8 @@ static int fsl_lpspi_config(struct fsl_lpspi_data *fsl_lpspi) fsl_lpspi_set_watermark(fsl_lpspi); - if (!fsl_lpspi->is_slave) - temp = CFGR1_MASTER; + if (!fsl_lpspi->is_target) + temp = CFGR1_HOST; else temp = CFGR1_PINCFG; if (fsl_lpspi->config.mode & SPI_CS_HIGH) @@ -463,12 +461,12 @@ static int fsl_lpspi_setup_transfer(struct spi_controller *controller, return fsl_lpspi_config(fsl_lpspi); } -static int fsl_lpspi_slave_abort(struct spi_controller *controller) +static int fsl_lpspi_target_abort(struct spi_controller *controller) { struct fsl_lpspi_data *fsl_lpspi = spi_controller_get_devdata(controller); - fsl_lpspi->slave_aborted = true; + fsl_lpspi->target_aborted = true; if (!fsl_lpspi->usedma) complete(&fsl_lpspi->xfer_done); else { @@ -484,9 +482,9 @@ static int fsl_lpspi_wait_for_completion(struct spi_controller *controller) struct fsl_lpspi_data *fsl_lpspi = spi_controller_get_devdata(controller); - if (fsl_lpspi->is_slave) { + if (fsl_lpspi->is_target) { if (wait_for_completion_interruptible(&fsl_lpspi->xfer_done) || - fsl_lpspi->slave_aborted) { + fsl_lpspi->target_aborted) { dev_dbg(fsl_lpspi->dev, "interrupted\n"); return -EINTR; } @@ -589,9 +587,9 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller, reinit_completion(&fsl_lpspi->dma_tx_completion); dma_async_issue_pending(controller->dma_tx); - fsl_lpspi->slave_aborted = false; + fsl_lpspi->target_aborted = false; - if (!fsl_lpspi->is_slave) { + if (!fsl_lpspi->is_target) { transfer_timeout = fsl_lpspi_calculate_timeout(fsl_lpspi, transfer->len); @@ -617,7 +615,7 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller, } } else { if (wait_for_completion_interruptible(&fsl_lpspi->dma_tx_completion) || - fsl_lpspi->slave_aborted) { + fsl_lpspi->target_aborted) { dev_dbg(fsl_lpspi->dev, "I/O Error in DMA TX interrupted\n"); dmaengine_terminate_all(controller->dma_tx); @@ -627,7 +625,7 @@ static int fsl_lpspi_dma_transfer(struct spi_controller *controller, } if (wait_for_completion_interruptible(&fsl_lpspi->dma_rx_completion) || - fsl_lpspi->slave_aborted) { + fsl_lpspi->target_aborted) { dev_dbg(fsl_lpspi->dev, "I/O Error in DMA RX interrupted\n"); dmaengine_terminate_all(controller->dma_tx); @@ -702,7 +700,7 @@ static int fsl_lpspi_pio_transfer(struct spi_controller *controller, fsl_lpspi->remain = t->len; reinit_completion(&fsl_lpspi->xfer_done); - fsl_lpspi->slave_aborted = false; + fsl_lpspi->target_aborted = false; fsl_lpspi_write_tx_fifo(fsl_lpspi); @@ -826,16 +824,17 @@ static int fsl_lpspi_probe(struct platform_device *pdev) struct spi_controller *controller; struct resource *res; int ret, irq; + u32 num_cs; u32 temp; - bool is_slave; + bool is_target; - is_slave = of_property_read_bool((&pdev->dev)->of_node, "spi-slave"); - if (is_slave) - controller = spi_alloc_slave(&pdev->dev, - sizeof(struct fsl_lpspi_data)); + is_target = of_property_read_bool((&pdev->dev)->of_node, "spi-slave"); + if (is_target) + controller = spi_alloc_target(&pdev->dev, + sizeof(struct fsl_lpspi_data)); else - controller = spi_alloc_master(&pdev->dev, - sizeof(struct fsl_lpspi_data)); + controller = spi_alloc_host(&pdev->dev, + sizeof(struct fsl_lpspi_data)); if (!controller) return -ENOMEM; @@ -844,25 +843,9 @@ static int fsl_lpspi_probe(struct platform_device *pdev) fsl_lpspi = spi_controller_get_devdata(controller); fsl_lpspi->dev = &pdev->dev; - fsl_lpspi->is_slave = is_slave; + fsl_lpspi->is_target = is_target; fsl_lpspi->is_only_cs1 = of_property_read_bool((&pdev->dev)->of_node, "fsl,spi-only-use-cs1-sel"); - if (of_property_read_u32((&pdev->dev)->of_node, "num-cs", - &fsl_lpspi->num_cs)) - fsl_lpspi->num_cs = 1; - - controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32); - controller->transfer_one = fsl_lpspi_transfer_one; - controller->prepare_transfer_hardware = lpspi_prepare_xfer_hardware; - controller->unprepare_transfer_hardware = lpspi_unprepare_xfer_hardware; - controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; - controller->flags = SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX; - controller->dev.of_node = pdev->dev.of_node; - controller->bus_num = pdev->id; - controller->num_chipselect = fsl_lpspi->num_cs; - controller->slave_abort = fsl_lpspi_slave_abort; - if (!fsl_lpspi->is_slave) - controller->use_gpio_descriptors = true; init_completion(&fsl_lpspi->xfer_done); @@ -912,6 +895,26 @@ static int fsl_lpspi_probe(struct platform_device *pdev) temp = readl(fsl_lpspi->base + IMX7ULP_PARAM); fsl_lpspi->txfifosize = 1 << (temp & 0x0f); fsl_lpspi->rxfifosize = 1 << ((temp >> 8) & 0x0f); + if (of_property_read_u32((&pdev->dev)->of_node, "num-cs", + &num_cs)) { + if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx93-spi")) + num_cs = ((temp >> 16) & 0xf); + else + num_cs = 1; + } + + controller->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32); + controller->transfer_one = fsl_lpspi_transfer_one; + controller->prepare_transfer_hardware = lpspi_prepare_xfer_hardware; + controller->unprepare_transfer_hardware = lpspi_unprepare_xfer_hardware; + controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + controller->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX; + controller->dev.of_node = pdev->dev.of_node; + controller->bus_num = pdev->id; + controller->num_chipselect = num_cs; + controller->target_abort = fsl_lpspi_target_abort; + if (!fsl_lpspi->is_target) + controller->use_gpio_descriptors = true; ret = fsl_lpspi_dma_init(&pdev->dev, fsl_lpspi, controller); if (ret == -EPROBE_DEFER) diff --git a/drivers/spi/spi-fsl-qspi.c b/drivers/spi/spi-fsl-qspi.c index 8ade61e5ebc0..79bac30e79af 100644 --- a/drivers/spi/spi-fsl-qspi.c +++ b/drivers/spi/spi-fsl-qspi.c @@ -34,7 +34,6 @@ #include <linux/module.h> #include <linux/mutex.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_qos.h> #include <linux/sizes.h> @@ -368,7 +367,7 @@ static int fsl_qspi_check_buswidth(struct fsl_qspi *q, u8 width) static bool fsl_qspi_supports_op(struct spi_mem *mem, const struct spi_mem_op *op) { - struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->master); + struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->controller); int ret; ret = fsl_qspi_check_buswidth(q, op->cmd.buswidth); @@ -641,7 +640,7 @@ static int fsl_qspi_readl_poll_tout(struct fsl_qspi *q, void __iomem *base, static int fsl_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) { - struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->master); + struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->controller); void __iomem *base = q->iobase; u32 addr_offset = 0; int err = 0; @@ -703,7 +702,7 @@ static int fsl_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) static int fsl_qspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) { - struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->master); + struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->controller); if (op->data.dir == SPI_MEM_DATA_OUT) { if (op->data.nbytes > q->devtype_data->txfifo) @@ -809,7 +808,7 @@ static int fsl_qspi_default_setup(struct fsl_qspi *q) static const char *fsl_qspi_get_name(struct spi_mem *mem) { - struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->master); + struct fsl_qspi *q = spi_controller_get_devdata(mem->spi->controller); struct device *dev = &mem->spi->dev; const char *name; @@ -849,7 +848,7 @@ static int fsl_qspi_probe(struct platform_device *pdev) struct fsl_qspi *q; int ret; - ctlr = spi_alloc_master(&pdev->dev, sizeof(*q)); + ctlr = spi_alloc_host(&pdev->dev, sizeof(*q)); if (!ctlr) return -ENOMEM; diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 106fe60a0a50..97faf984801f 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -88,7 +88,7 @@ static int fsl_spi_get_type(struct device *dev) static void fsl_spi_change_mode(struct spi_device *spi) { - struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master); + struct mpc8xxx_spi *mspi = spi_controller_get_devdata(spi->controller); struct spi_mpc8xxx_cs *cs = spi->controller_state; struct fsl_spi_reg __iomem *reg_base = mspi->reg_base; __be32 __iomem *mode = ®_base->mode; @@ -183,7 +183,7 @@ static int fsl_spi_setup_transfer(struct spi_device *spi, u32 hz = 0; struct spi_mpc8xxx_cs *cs = spi->controller_state; - mpc8xxx_spi = spi_master_get_devdata(spi->master); + mpc8xxx_spi = spi_controller_get_devdata(spi->controller); if (t) { bits_per_word = t->bits_per_word; @@ -252,7 +252,7 @@ static int fsl_spi_cpu_bufs(struct mpc8xxx_spi *mspi, static int fsl_spi_bufs(struct spi_device *spi, struct spi_transfer *t, bool is_dma_mapped) { - struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); + struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(spi->controller); struct fsl_spi_reg __iomem *reg_base; unsigned int len = t->len; u8 bits_per_word; @@ -385,7 +385,7 @@ static int fsl_spi_setup(struct spi_device *spi) spi_set_ctldata(spi, cs); initial_setup = true; } - mpc8xxx_spi = spi_master_get_devdata(spi->master); + mpc8xxx_spi = spi_controller_get_devdata(spi->controller); reg_base = mpc8xxx_spi->reg_base; @@ -479,7 +479,7 @@ static irqreturn_t fsl_spi_irq(s32 irq, void *context_data) static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on) { - struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master); + struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(spi->controller); struct fsl_spi_reg __iomem *reg_base = mpc8xxx_spi->reg_base; u32 slvsel; u16 cs = spi_get_chipselect(spi, 0); @@ -493,8 +493,8 @@ static void fsl_spi_grlib_cs_control(struct spi_device *spi, bool on) static void fsl_spi_grlib_probe(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(host); struct fsl_spi_reg __iomem *reg_base = mpc8xxx_spi->reg_base; int mbits; u32 capabilities; @@ -511,8 +511,8 @@ static void fsl_spi_grlib_probe(struct device *dev) mpc8xxx_spi->native_chipselects = SPCAP_SSSZ(capabilities); mpc8xxx_spi_write_reg(®_base->slvsel, 0xffffffff); } - master->num_chipselect = mpc8xxx_spi->native_chipselects; - master->set_cs = fsl_spi_grlib_cs_control; + host->num_chipselect = mpc8xxx_spi->native_chipselects; + host->set_cs = fsl_spi_grlib_cs_control; } static void fsl_spi_cs_control(struct spi_device *spi, bool on) @@ -526,35 +526,35 @@ static void fsl_spi_cs_control(struct spi_device *spi, bool on) iowrite32be(on ? 0 : SPI_BOOT_SEL_BIT, pinfo->immr_spi_cs); } -static struct spi_master *fsl_spi_probe(struct device *dev, +static struct spi_controller *fsl_spi_probe(struct device *dev, struct resource *mem, unsigned int irq) { struct fsl_spi_platform_data *pdata = dev_get_platdata(dev); - struct spi_master *master; + struct spi_controller *host; struct mpc8xxx_spi *mpc8xxx_spi; struct fsl_spi_reg __iomem *reg_base; u32 regval; int ret = 0; - master = spi_alloc_master(dev, sizeof(struct mpc8xxx_spi)); - if (master == NULL) { + host = spi_alloc_host(dev, sizeof(struct mpc8xxx_spi)); + if (host == NULL) { ret = -ENOMEM; goto err; } - dev_set_drvdata(dev, master); + dev_set_drvdata(dev, host); mpc8xxx_spi_probe(dev, mem, irq); - master->setup = fsl_spi_setup; - master->cleanup = fsl_spi_cleanup; - master->prepare_message = fsl_spi_prepare_message; - master->transfer_one = fsl_spi_transfer_one; - master->unprepare_message = fsl_spi_unprepare_message; - master->use_gpio_descriptors = true; - master->set_cs = fsl_spi_cs_control; + host->setup = fsl_spi_setup; + host->cleanup = fsl_spi_cleanup; + host->prepare_message = fsl_spi_prepare_message; + host->transfer_one = fsl_spi_transfer_one; + host->unprepare_message = fsl_spi_unprepare_message; + host->use_gpio_descriptors = true; + host->set_cs = fsl_spi_cs_control; - mpc8xxx_spi = spi_master_get_devdata(master); + mpc8xxx_spi = spi_controller_get_devdata(host); mpc8xxx_spi->max_bits_per_word = 32; mpc8xxx_spi->type = fsl_spi_get_type(dev); @@ -572,13 +572,13 @@ static struct spi_master *fsl_spi_probe(struct device *dev, fsl_spi_grlib_probe(dev); if (mpc8xxx_spi->flags & SPI_CPM_MODE) - master->bits_per_word_mask = + host->bits_per_word_mask = (SPI_BPW_RANGE_MASK(4, 8) | SPI_BPW_MASK(16) | SPI_BPW_MASK(32)); else - master->bits_per_word_mask = + host->bits_per_word_mask = (SPI_BPW_RANGE_MASK(4, 16) | SPI_BPW_MASK(32)); - master->bits_per_word_mask &= + host->bits_per_word_mask &= SPI_BPW_RANGE_MASK(1, mpc8xxx_spi->max_bits_per_word); if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) @@ -615,19 +615,19 @@ static struct spi_master *fsl_spi_probe(struct device *dev, mpc8xxx_spi_write_reg(®_base->mode, regval); - ret = devm_spi_register_master(dev, master); + ret = devm_spi_register_controller(dev, host); if (ret < 0) goto err_probe; dev_info(dev, "at 0x%p (irq = %d), %s mode\n", reg_base, mpc8xxx_spi->irq, mpc8xxx_spi_strmode(mpc8xxx_spi->flags)); - return master; + return host; err_probe: fsl_spi_cpm_free(mpc8xxx_spi); err_cpm_init: - spi_master_put(master); + spi_controller_put(host); err: return ERR_PTR(ret); } @@ -636,7 +636,7 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) { struct device *dev = &ofdev->dev; struct device_node *np = ofdev->dev.of_node; - struct spi_master *master; + struct spi_controller *host; struct resource mem; int irq, type; int ret; @@ -689,9 +689,9 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) goto unmap_out; } - master = fsl_spi_probe(dev, &mem, irq); + host = fsl_spi_probe(dev, &mem, irq); - return PTR_ERR_OR_ZERO(master); + return PTR_ERR_OR_ZERO(host); unmap_out: #if IS_ENABLED(CONFIG_FSL_SOC) @@ -703,8 +703,8 @@ unmap_out: static void of_fsl_spi_remove(struct platform_device *ofdev) { - struct spi_master *master = platform_get_drvdata(ofdev); - struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(ofdev); + struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(host); fsl_spi_cpm_free(mpc8xxx_spi); } @@ -730,7 +730,7 @@ static int plat_mpc8xxx_spi_probe(struct platform_device *pdev) { struct resource *mem; int irq; - struct spi_master *master; + struct spi_controller *host; if (!dev_get_platdata(&pdev->dev)) return -EINVAL; @@ -740,17 +740,17 @@ static int plat_mpc8xxx_spi_probe(struct platform_device *pdev) return -EINVAL; irq = platform_get_irq(pdev, 0); - if (irq <= 0) - return -EINVAL; + if (irq < 0) + return irq; - master = fsl_spi_probe(&pdev->dev, mem, irq); - return PTR_ERR_OR_ZERO(master); + host = fsl_spi_probe(&pdev->dev, mem, irq); + return PTR_ERR_OR_ZERO(host); } static void plat_mpc8xxx_spi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(pdev); + struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(host); fsl_spi_cpm_free(mpc8xxx_spi); } diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index 1df9d4844a68..f4f376a8351b 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -12,6 +12,7 @@ #include <linux/platform_device.h> #include <linux/pm_opp.h> #include <linux/pm_runtime.h> +#include <linux/property.h> #include <linux/soc/qcom/geni-se.h> #include <linux/spi/spi.h> #include <linux/spinlock.h> @@ -52,6 +53,9 @@ #define SPI_CS_CLK_DELAY_MSK GENMASK(19, 10) #define SPI_CS_CLK_DELAY_SHFT 10 +#define SE_SPI_SLAVE_EN (0x2BC) +#define SPI_SLAVE_EN BIT(0) + /* M_CMD OP codes for SPI */ #define SPI_TX_ONLY 1 #define SPI_RX_ONLY 2 @@ -99,6 +103,16 @@ struct spi_geni_master { int cur_xfer_mode; }; +static void spi_slv_setup(struct spi_geni_master *mas) +{ + struct geni_se *se = &mas->se; + + writel(SPI_SLAVE_EN, se->base + SE_SPI_SLAVE_EN); + writel(GENI_IO_MUX_0_EN, se->base + GENI_OUTPUT_CTRL); + writel(START_TRIGGER, se->base + SE_GENI_CFG_SEQ_START); + dev_dbg(mas->dev, "spi slave setup done\n"); +} + static int get_spi_clk_cfg(unsigned int speed_hz, struct spi_geni_master *mas, unsigned int *clk_idx, @@ -140,12 +154,22 @@ static void handle_se_timeout(struct spi_master *spi, const struct spi_transfer *xfer; spin_lock_irq(&mas->lock); - reinit_completion(&mas->cancel_done); if (mas->cur_xfer_mode == GENI_SE_FIFO) writel(0, se->base + SE_GENI_TX_WATERMARK_REG); xfer = mas->cur_xfer; mas->cur_xfer = NULL; + + if (spi->slave) { + /* + * skip CMD Cancel sequnece since spi slave + * doesn`t support CMD Cancel sequnece + */ + spin_unlock_irq(&mas->lock); + goto unmap_if_dma; + } + + reinit_completion(&mas->cancel_done); geni_se_cancel_m_cmd(se); spin_unlock_irq(&mas->lock); @@ -542,6 +566,10 @@ static bool geni_can_dma(struct spi_controller *ctlr, if (mas->cur_xfer_mode == GENI_GPI_DMA) return true; + /* Set SE DMA mode for SPI slave. */ + if (ctlr->slave) + return true; + len = get_xfer_len_in_words(xfer, mas); fifo_size = mas->tx_fifo_depth * mas->fifo_width_bits / mas->cur_bits_per_word; @@ -619,6 +647,7 @@ static void spi_geni_release_dma_chan(struct spi_geni_master *mas) static int spi_geni_init(struct spi_geni_master *mas) { + struct spi_master *spi = dev_get_drvdata(mas->dev); struct geni_se *se = &mas->se; unsigned int proto, major, minor, ver; u32 spi_tx_cfg, fifo_disable; @@ -627,7 +656,14 @@ static int spi_geni_init(struct spi_geni_master *mas) pm_runtime_get_sync(mas->dev); proto = geni_se_read_proto(se); - if (proto != GENI_SE_SPI) { + + if (spi->slave) { + if (proto != GENI_SE_SPI_SLAVE) { + dev_err(mas->dev, "Invalid proto %d\n", proto); + goto out_pm; + } + spi_slv_setup(mas); + } else if (proto != GENI_SE_SPI) { dev_err(mas->dev, "Invalid proto %d\n", proto); goto out_pm; } @@ -679,9 +715,11 @@ static int spi_geni_init(struct spi_geni_master *mas) } /* We always control CS manually */ - spi_tx_cfg = readl(se->base + SE_SPI_TRANS_CFG); - spi_tx_cfg &= ~CS_TOGGLE; - writel(spi_tx_cfg, se->base + SE_SPI_TRANS_CFG); + if (!spi->slave) { + spi_tx_cfg = readl(se->base + SE_SPI_TRANS_CFG); + spi_tx_cfg &= ~CS_TOGGLE; + writel(spi_tx_cfg, se->base + SE_SPI_TRANS_CFG); + } out_pm: pm_runtime_put(mas->dev); @@ -1074,6 +1112,9 @@ static int spi_geni_probe(struct platform_device *pdev) pm_runtime_set_autosuspend_delay(&pdev->dev, 250); pm_runtime_enable(dev); + if (device_property_read_bool(&pdev->dev, "spi-slave")) + spi->slave = true; + ret = geni_icc_get(&mas->se, NULL); if (ret) goto spi_geni_probe_runtime_disable; @@ -1094,7 +1135,7 @@ static int spi_geni_probe(struct platform_device *pdev) * for dma (gsi) mode, the gsi will set cs based on params passed in * TRE */ - if (mas->cur_xfer_mode == GENI_SE_FIFO) + if (!spi->slave && mas->cur_xfer_mode == GENI_SE_FIFO) spi->set_cs = spi_geni_set_cs; /* diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 092afc7679d4..d8db4564b406 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * SPI master driver using generic bitbanged GPIO + * SPI host driver using generic bitbanged GPIO * * Copyright (C) 2006,2008 David Brownell * Copyright (C) 2017 Linus Walleij @@ -10,7 +10,6 @@ #include <linux/platform_device.h> #include <linux/gpio/consumer.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/spi/spi.h> #include <linux/spi/spi_bitbang.h> @@ -18,7 +17,7 @@ /* - * This bitbanging SPI master driver should help make systems usable + * This bitbanging SPI host driver should help make systems usable * when a native hardware SPI engine is not available, perhaps because * its driver isn't yet working or because the I/O pins it requires * are used for other purposes. @@ -27,7 +26,7 @@ * * spi->controller_state ... reserved for bitbang framework code * - * spi->master->dev.driver_data ... points to spi_gpio->bitbang + * spi->controller->dev.driver_data ... points to spi_gpio->bitbang */ struct spi_gpio { @@ -78,7 +77,7 @@ spi_to_spi_gpio(const struct spi_device *spi) const struct spi_bitbang *bang; struct spi_gpio *spi_gpio; - bang = spi_master_get_devdata(spi->master); + bang = spi_controller_get_devdata(spi->controller); spi_gpio = container_of(bang, struct spi_gpio, bitbang); return spi_gpio; } @@ -170,7 +169,7 @@ static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi, /* * These functions do not call setmosi or getmiso if respective flag - * (SPI_MASTER_NO_RX or SPI_MASTER_NO_TX) is set, so they are safe to + * (SPI_CONTROLLER_NO_RX or SPI_CONTROLLER_NO_TX) is set, so they are safe to * call when such pin is not present or defined in the controller. * A separate set of callbacks is defined to get highest possible * speed in the generic case (when both MISO and MOSI lines are @@ -181,7 +180,7 @@ static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi, static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits, unsigned flags) { - flags = spi->master->flags; + flags = spi->controller->flags; if (unlikely(spi->mode & SPI_LSB_FIRST)) return bitbang_txrx_le_cpha0(spi, nsecs, 0, flags, word, bits); else @@ -191,7 +190,7 @@ static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi, static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits, unsigned flags) { - flags = spi->master->flags; + flags = spi->controller->flags; if (unlikely(spi->mode & SPI_LSB_FIRST)) return bitbang_txrx_le_cpha1(spi, nsecs, 0, flags, word, bits); else @@ -201,7 +200,7 @@ static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi, static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits, unsigned flags) { - flags = spi->master->flags; + flags = spi->controller->flags; if (unlikely(spi->mode & SPI_LSB_FIRST)) return bitbang_txrx_le_cpha0(spi, nsecs, 1, flags, word, bits); else @@ -211,7 +210,7 @@ static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi, static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi, unsigned nsecs, u32 word, u8 bits, unsigned flags) { - flags = spi->master->flags; + flags = spi->controller->flags; if (unlikely(spi->mode & SPI_LSB_FIRST)) return bitbang_txrx_le_cpha1(spi, nsecs, 1, flags, word, bits); else @@ -311,7 +310,7 @@ static void spi_gpio_cleanup(struct spi_device *spi) * On platforms which can do so, configure MISO with a weak pullup unless * there's an external pullup on that signal. That saves power by avoiding * floating signals. (A weak pulldown would save power too, but many - * drivers expect to see all-ones data as the no slave "response".) + * drivers expect to see all-ones data as the no target "response".) */ static int spi_gpio_request(struct device *dev, struct spi_gpio *spi_gpio) { @@ -335,27 +334,27 @@ static const struct of_device_id spi_gpio_dt_ids[] = { MODULE_DEVICE_TABLE(of, spi_gpio_dt_ids); static int spi_gpio_probe_dt(struct platform_device *pdev, - struct spi_master *master) + struct spi_controller *host) { - master->dev.of_node = pdev->dev.of_node; - master->use_gpio_descriptors = true; + host->dev.of_node = pdev->dev.of_node; + host->use_gpio_descriptors = true; return 0; } #else static inline int spi_gpio_probe_dt(struct platform_device *pdev, - struct spi_master *master) + struct spi_controller *host) { return 0; } #endif static int spi_gpio_probe_pdata(struct platform_device *pdev, - struct spi_master *master) + struct spi_controller *host) { struct device *dev = &pdev->dev; struct spi_gpio_platform_data *pdata = dev_get_platdata(dev); - struct spi_gpio *spi_gpio = spi_master_get_devdata(master); + struct spi_gpio *spi_gpio = spi_controller_get_devdata(host); int i; #ifdef GENERIC_BITBANG @@ -363,18 +362,18 @@ static int spi_gpio_probe_pdata(struct platform_device *pdev, return -ENODEV; #endif /* - * The master needs to think there is a chipselect even if not + * The host needs to think there is a chipselect even if not * connected */ - master->num_chipselect = pdata->num_chipselect ?: 1; + host->num_chipselect = pdata->num_chipselect ?: 1; - spi_gpio->cs_gpios = devm_kcalloc(dev, master->num_chipselect, + spi_gpio->cs_gpios = devm_kcalloc(dev, host->num_chipselect, sizeof(*spi_gpio->cs_gpios), GFP_KERNEL); if (!spi_gpio->cs_gpios) return -ENOMEM; - for (i = 0; i < master->num_chipselect; i++) { + for (i = 0; i < host->num_chipselect; i++) { spi_gpio->cs_gpios[i] = devm_gpiod_get_index(dev, "cs", i, GPIOD_OUT_HIGH); if (IS_ERR(spi_gpio->cs_gpios[i])) @@ -387,58 +386,58 @@ static int spi_gpio_probe_pdata(struct platform_device *pdev, static int spi_gpio_probe(struct platform_device *pdev) { int status; - struct spi_master *master; + struct spi_controller *host; struct spi_gpio *spi_gpio; struct device *dev = &pdev->dev; struct spi_bitbang *bb; - master = devm_spi_alloc_master(dev, sizeof(*spi_gpio)); - if (!master) + host = devm_spi_alloc_host(dev, sizeof(*spi_gpio)); + if (!host) return -ENOMEM; if (pdev->dev.of_node) - status = spi_gpio_probe_dt(pdev, master); + status = spi_gpio_probe_dt(pdev, host); else - status = spi_gpio_probe_pdata(pdev, master); + status = spi_gpio_probe_pdata(pdev, host); if (status) return status; - spi_gpio = spi_master_get_devdata(master); + spi_gpio = spi_controller_get_devdata(host); status = spi_gpio_request(dev, spi_gpio); if (status) return status; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); - master->mode_bits = SPI_3WIRE | SPI_3WIRE_HIZ | SPI_CPHA | SPI_CPOL | + host->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32); + host->mode_bits = SPI_3WIRE | SPI_3WIRE_HIZ | SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST; if (!spi_gpio->mosi) { /* HW configuration without MOSI pin * - * No setting SPI_MASTER_NO_RX here - if there is only + * No setting SPI_CONTROLLER_NO_RX here - if there is only * a MOSI pin connected the host can still do RX by * changing the direction of the line. */ - master->flags = SPI_MASTER_NO_TX; + host->flags = SPI_CONTROLLER_NO_TX; } - master->bus_num = pdev->id; - master->setup = spi_gpio_setup; - master->cleanup = spi_gpio_cleanup; + host->bus_num = pdev->id; + host->setup = spi_gpio_setup; + host->cleanup = spi_gpio_cleanup; bb = &spi_gpio->bitbang; - bb->master = master; + bb->master = host; /* * There is some additional business, apart from driving the CS GPIO * line, that we need to do on selection. This makes the local * callback for chipselect always get called. */ - master->flags |= SPI_MASTER_GPIO_SS; + host->flags |= SPI_CONTROLLER_GPIO_SS; bb->chipselect = spi_gpio_chipselect; bb->set_line_direction = spi_gpio_set_direction; - if (master->flags & SPI_MASTER_NO_TX) { + if (host->flags & SPI_CONTROLLER_NO_TX) { bb->txrx_word[SPI_MODE_0] = spi_gpio_spec_txrx_word_mode0; bb->txrx_word[SPI_MODE_1] = spi_gpio_spec_txrx_word_mode1; bb->txrx_word[SPI_MODE_2] = spi_gpio_spec_txrx_word_mode2; @@ -455,7 +454,7 @@ static int spi_gpio_probe(struct platform_device *pdev) if (status) return status; - return devm_spi_register_master(&pdev->dev, master); + return devm_spi_register_controller(&pdev->dev, host); } MODULE_ALIAS("platform:" DRIVER_NAME); @@ -469,6 +468,6 @@ static struct platform_driver spi_gpio_driver = { }; module_platform_driver(spi_gpio_driver); -MODULE_DESCRIPTION("SPI master driver using generic bitbanged GPIO "); +MODULE_DESCRIPTION("SPI host driver using generic bitbanged GPIO "); MODULE_AUTHOR("David Brownell"); MODULE_LICENSE("GPL"); diff --git a/drivers/spi/spi-gxp.c b/drivers/spi/spi-gxp.c index 684d63f402f3..fd2fac236bbd 100644 --- a/drivers/spi/spi-gxp.c +++ b/drivers/spi/spi-gxp.c @@ -3,7 +3,6 @@ #include <linux/iopoll.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> #include <linux/spi/spi-mem.h> @@ -200,7 +199,7 @@ static ssize_t gxp_spi_write(struct gxp_spi_chip *chip, const struct spi_mem_op static int do_gxp_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) { - struct gxp_spi *spifi = spi_controller_get_devdata(mem->spi->master); + struct gxp_spi *spifi = spi_controller_get_devdata(mem->spi->controller); struct gxp_spi_chip *chip = &spifi->chips[spi_get_chipselect(mem->spi, 0)]; int ret; @@ -236,7 +235,7 @@ static const struct spi_controller_mem_ops gxp_spi_mem_ops = { static int gxp_spi_setup(struct spi_device *spi) { - struct gxp_spi *spifi = spi_controller_get_devdata(spi->master); + struct gxp_spi *spifi = spi_controller_get_devdata(spi->controller); unsigned int cs = spi_get_chipselect(spi, 0); struct gxp_spi_chip *chip = &spifi->chips[cs]; @@ -258,7 +257,7 @@ static int gxp_spifi_probe(struct platform_device *pdev) data = of_device_get_match_data(&pdev->dev); - ctlr = devm_spi_alloc_master(dev, sizeof(*spifi)); + ctlr = devm_spi_alloc_host(dev, sizeof(*spifi)); if (!ctlr) return -ENOMEM; diff --git a/drivers/spi/spi-hisi-kunpeng.c b/drivers/spi/spi-hisi-kunpeng.c index 2b4b3d2a22b8..35ef5e8e2ffd 100644 --- a/drivers/spi/spi-hisi-kunpeng.c +++ b/drivers/spi/spi-hisi-kunpeng.c @@ -164,10 +164,10 @@ static int hisi_spi_debugfs_init(struct hisi_spi *hs) { char name[32]; - struct spi_controller *master; + struct spi_controller *host; - master = container_of(hs->dev, struct spi_controller, dev); - snprintf(name, 32, "hisi_spi%d", master->bus_num); + host = container_of(hs->dev, struct spi_controller, dev); + snprintf(name, 32, "hisi_spi%d", host->bus_num); hs->debugfs = debugfs_create_dir(name, NULL); if (IS_ERR(hs->debugfs)) return -ENOMEM; @@ -291,18 +291,18 @@ static void __hisi_calc_div_reg(struct hisi_chip_data *chip) chip->div_post = (chip->clk_div / chip->div_pre) - 1; } -static u32 hisi_calc_effective_speed(struct spi_controller *master, +static u32 hisi_calc_effective_speed(struct spi_controller *host, struct hisi_chip_data *chip, u32 speed_hz) { u32 effective_speed; /* Note clock divider doesn't support odd numbers */ - chip->clk_div = DIV_ROUND_UP(master->max_speed_hz, speed_hz) + 1; + chip->clk_div = DIV_ROUND_UP(host->max_speed_hz, speed_hz) + 1; chip->clk_div &= 0xfffe; if (chip->clk_div > CLK_DIV_MAX) chip->clk_div = CLK_DIV_MAX; - effective_speed = master->max_speed_hz / chip->clk_div; + effective_speed = host->max_speed_hz / chip->clk_div; if (chip->speed_hz != effective_speed) { __hisi_calc_div_reg(chip); chip->speed_hz = effective_speed; @@ -336,20 +336,20 @@ static void hisi_spi_hw_init(struct hisi_spi *hs) static irqreturn_t hisi_spi_irq(int irq, void *dev_id) { - struct spi_controller *master = dev_id; - struct hisi_spi *hs = spi_controller_get_devdata(master); + struct spi_controller *host = dev_id; + struct hisi_spi *hs = spi_controller_get_devdata(host); u32 irq_status = readl(hs->regs + HISI_SPI_ISR) & ISR_MASK; if (!irq_status) return IRQ_NONE; - if (!master->cur_msg) + if (!host->cur_msg) return IRQ_HANDLED; /* Error handling */ if (irq_status & ISR_RXOF) { dev_err(hs->dev, "interrupt_transfer: fifo overflow\n"); - master->cur_msg->status = -EIO; + host->cur_msg->status = -EIO; goto finalize_transfer; } @@ -369,20 +369,20 @@ static irqreturn_t hisi_spi_irq(int irq, void *dev_id) finalize_transfer: hisi_spi_disable(hs); - spi_finalize_current_transfer(master); + spi_finalize_current_transfer(host); return IRQ_HANDLED; } -static int hisi_spi_transfer_one(struct spi_controller *master, +static int hisi_spi_transfer_one(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *transfer) { - struct hisi_spi *hs = spi_controller_get_devdata(master); + struct hisi_spi *hs = spi_controller_get_devdata(host); struct hisi_chip_data *chip = spi_get_ctldata(spi); u32 cr = chip->cr; /* Update per transfer options for speed and bpw */ transfer->effective_speed_hz = - hisi_calc_effective_speed(master, chip, transfer->speed_hz); + hisi_calc_effective_speed(host, chip, transfer->speed_hz); cr |= FIELD_PREP(CR_DIV_PRE_MASK, chip->div_pre); cr |= FIELD_PREP(CR_DIV_POST_MASK, chip->div_post); cr |= FIELD_PREP(CR_BPW_MASK, transfer->bits_per_word - 1); @@ -409,10 +409,10 @@ static int hisi_spi_transfer_one(struct spi_controller *master, return 1; } -static void hisi_spi_handle_err(struct spi_controller *master, +static void hisi_spi_handle_err(struct spi_controller *host, struct spi_message *msg) { - struct hisi_spi *hs = spi_controller_get_devdata(master); + struct hisi_spi *hs = spi_controller_get_devdata(host); hisi_spi_disable(hs); @@ -452,7 +452,7 @@ static void hisi_spi_cleanup(struct spi_device *spi) static int hisi_spi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct spi_controller *master; + struct spi_controller *host; struct hisi_spi *hs; int ret, irq; @@ -460,13 +460,13 @@ static int hisi_spi_probe(struct platform_device *pdev) if (irq < 0) return irq; - master = devm_spi_alloc_master(dev, sizeof(*hs)); - if (!master) + host = devm_spi_alloc_host(dev, sizeof(*hs)); + if (!host) return -ENOMEM; - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); - hs = spi_controller_get_devdata(master); + hs = spi_controller_get_devdata(host); hs->dev = dev; hs->irq = irq; @@ -474,9 +474,9 @@ static int hisi_spi_probe(struct platform_device *pdev) if (IS_ERR(hs->regs)) return PTR_ERR(hs->regs); - /* Specify maximum SPI clocking speed (master only) by firmware */ + /* Specify maximum SPI clocking speed (host only) by firmware */ ret = device_property_read_u32(dev, "spi-max-frequency", - &master->max_speed_hz); + &host->max_speed_hz); if (ret) { dev_err(dev, "failed to get max SPI clocking speed, ret=%d\n", ret); @@ -484,32 +484,32 @@ static int hisi_spi_probe(struct platform_device *pdev) } ret = device_property_read_u16(dev, "num-cs", - &master->num_chipselect); + &host->num_chipselect); if (ret) - master->num_chipselect = DEFAULT_NUM_CS; - - master->use_gpio_descriptors = true; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); - master->bus_num = pdev->id; - master->setup = hisi_spi_setup; - master->cleanup = hisi_spi_cleanup; - master->transfer_one = hisi_spi_transfer_one; - master->handle_err = hisi_spi_handle_err; - master->dev.fwnode = dev->fwnode; + host->num_chipselect = DEFAULT_NUM_CS; + + host->use_gpio_descriptors = true; + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; + host->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); + host->bus_num = pdev->id; + host->setup = hisi_spi_setup; + host->cleanup = hisi_spi_cleanup; + host->transfer_one = hisi_spi_transfer_one; + host->handle_err = hisi_spi_handle_err; + host->dev.fwnode = dev->fwnode; hisi_spi_hw_init(hs); ret = devm_request_irq(dev, hs->irq, hisi_spi_irq, 0, dev_name(dev), - master); + host); if (ret < 0) { dev_err(dev, "failed to get IRQ=%d, ret=%d\n", hs->irq, ret); return ret; } - ret = spi_register_controller(master); + ret = spi_register_controller(host); if (ret) { - dev_err(dev, "failed to register spi master, ret=%d\n", ret); + dev_err(dev, "failed to register spi host, ret=%d\n", ret); return ret; } @@ -518,18 +518,18 @@ static int hisi_spi_probe(struct platform_device *pdev) dev_info(dev, "hw version:0x%x max-freq:%u kHz\n", readl(hs->regs + HISI_SPI_VERSION), - master->max_speed_hz / 1000); + host->max_speed_hz / 1000); return 0; } static void hisi_spi_remove(struct platform_device *pdev) { - struct spi_controller *master = platform_get_drvdata(pdev); - struct hisi_spi *hs = spi_controller_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(pdev); + struct hisi_spi *hs = spi_controller_get_devdata(host); debugfs_remove_recursive(hs->debugfs); - spi_unregister_controller(master); + spi_unregister_controller(host); } static const struct acpi_device_id hisi_spi_acpi_match[] = { diff --git a/drivers/spi/spi-hisi-sfc-v3xx.c b/drivers/spi/spi-hisi-sfc-v3xx.c index 7cbcb065bb44..9d22018f7985 100644 --- a/drivers/spi/spi-hisi-sfc-v3xx.c +++ b/drivers/spi/spi-hisi-sfc-v3xx.c @@ -152,7 +152,7 @@ static int hisi_sfc_v3xx_adjust_op_size(struct spi_mem *mem, uintptr_t addr = (uintptr_t)op->data.buf.in; int max_byte_count; - host = spi_controller_get_devdata(spi->master); + host = spi_controller_get_devdata(spi->controller); max_byte_count = host->max_cmd_dword * 4; @@ -174,7 +174,7 @@ static bool hisi_sfc_v3xx_supports_op(struct spi_mem *mem, struct spi_device *spi = mem->spi; struct hisi_sfc_v3xx_host *host; - host = spi_controller_get_devdata(spi->master); + host = spi_controller_get_devdata(spi->controller); if (op->data.buswidth > 4 || op->dummy.buswidth > 4 || op->addr.buswidth > 4 || op->cmd.buswidth > 4) @@ -363,7 +363,7 @@ static int hisi_sfc_v3xx_exec_op(struct spi_mem *mem, struct spi_device *spi = mem->spi; u8 chip_select = spi_get_chipselect(spi, 0); - host = spi_controller_get_devdata(spi->master); + host = spi_controller_get_devdata(spi->controller); return hisi_sfc_v3xx_generic_exec_op(host, op, chip_select); } @@ -431,7 +431,7 @@ static int hisi_sfc_v3xx_probe(struct platform_device *pdev) u32 version, glb_config; int ret; - ctlr = spi_alloc_master(&pdev->dev, sizeof(*host)); + ctlr = spi_alloc_host(&pdev->dev, sizeof(*host)); if (!ctlr) return -ENOMEM; @@ -448,13 +448,13 @@ static int hisi_sfc_v3xx_probe(struct platform_device *pdev) host->regbase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(host->regbase)) { ret = PTR_ERR(host->regbase); - goto err_put_master; + goto err_put_host; } host->irq = platform_get_irq_optional(pdev, 0); if (host->irq == -EPROBE_DEFER) { ret = -EPROBE_DEFER; - goto err_put_master; + goto err_put_host; } hisi_sfc_v3xx_disable_int(host); @@ -496,15 +496,15 @@ static int hisi_sfc_v3xx_probe(struct platform_device *pdev) ret = devm_spi_register_controller(dev, ctlr); if (ret) - goto err_put_master; + goto err_put_host; dev_info(&pdev->dev, "hw version 0x%x, %s mode.\n", version, host->irq ? "irq" : "polling"); return 0; -err_put_master: - spi_master_put(ctlr); +err_put_host: + spi_controller_put(ctlr); return ret; } diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index d775f87770e3..d8360f94d3b7 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -86,7 +86,7 @@ struct img_spfi { struct device *dev; - struct spi_master *master; + struct spi_controller *host; spinlock_t lock; void __iomem *regs; @@ -221,11 +221,11 @@ static unsigned int spfi_pio_read8(struct img_spfi *spfi, u8 *buf, return count; } -static int img_spfi_start_pio(struct spi_master *master, +static int img_spfi_start_pio(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { - struct img_spfi *spfi = spi_master_get_devdata(spi->master); + struct img_spfi *spfi = spi_controller_get_devdata(spi->controller); unsigned int tx_bytes = 0, rx_bytes = 0; const void *tx_buf = xfer->tx_buf; void *rx_buf = xfer->rx_buf; @@ -285,7 +285,7 @@ static void img_spfi_dma_rx_cb(void *data) spin_lock_irqsave(&spfi->lock, flags); spfi->rx_dma_busy = false; if (!spfi->tx_dma_busy) - spi_finalize_current_transfer(spfi->master); + spi_finalize_current_transfer(spfi->host); spin_unlock_irqrestore(&spfi->lock, flags); } @@ -299,15 +299,15 @@ static void img_spfi_dma_tx_cb(void *data) spin_lock_irqsave(&spfi->lock, flags); spfi->tx_dma_busy = false; if (!spfi->rx_dma_busy) - spi_finalize_current_transfer(spfi->master); + spi_finalize_current_transfer(spfi->host); spin_unlock_irqrestore(&spfi->lock, flags); } -static int img_spfi_start_dma(struct spi_master *master, +static int img_spfi_start_dma(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { - struct img_spfi *spfi = spi_master_get_devdata(spi->master); + struct img_spfi *spfi = spi_controller_get_devdata(spi->controller); struct dma_async_tx_descriptor *rxdesc = NULL, *txdesc = NULL; struct dma_slave_config rxconf, txconf; @@ -384,10 +384,10 @@ stop_dma: return -EIO; } -static void img_spfi_handle_err(struct spi_master *master, +static void img_spfi_handle_err(struct spi_controller *host, struct spi_message *msg) { - struct img_spfi *spfi = spi_master_get_devdata(master); + struct img_spfi *spfi = spi_controller_get_devdata(host); unsigned long flags; /* @@ -405,9 +405,9 @@ static void img_spfi_handle_err(struct spi_master *master, spin_unlock_irqrestore(&spfi->lock, flags); } -static int img_spfi_prepare(struct spi_master *master, struct spi_message *msg) +static int img_spfi_prepare(struct spi_controller *host, struct spi_message *msg) { - struct img_spfi *spfi = spi_master_get_devdata(master); + struct img_spfi *spfi = spi_controller_get_devdata(host); u32 val; val = spfi_readl(spfi, SPFI_PORT_STATE); @@ -427,20 +427,20 @@ static int img_spfi_prepare(struct spi_master *master, struct spi_message *msg) return 0; } -static int img_spfi_unprepare(struct spi_master *master, +static int img_spfi_unprepare(struct spi_controller *host, struct spi_message *msg) { - struct img_spfi *spfi = spi_master_get_devdata(master); + struct img_spfi *spfi = spi_controller_get_devdata(host); spfi_reset(spfi); return 0; } -static void img_spfi_config(struct spi_master *master, struct spi_device *spi, +static void img_spfi_config(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { - struct img_spfi *spfi = spi_master_get_devdata(spi->master); + struct img_spfi *spfi = spi_controller_get_devdata(spi->controller); u32 val, div; /* @@ -476,11 +476,11 @@ static void img_spfi_config(struct spi_master *master, struct spi_device *spi, spfi_writel(spfi, val, SPFI_CONTROL); } -static int img_spfi_transfer_one(struct spi_master *master, +static int img_spfi_transfer_one(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { - struct img_spfi *spfi = spi_master_get_devdata(spi->master); + struct img_spfi *spfi = spi_controller_get_devdata(spi->controller); int ret; if (xfer->len > SPFI_TRANSACTION_TSIZE_MASK) { @@ -490,16 +490,16 @@ static int img_spfi_transfer_one(struct spi_master *master, return -EINVAL; } - img_spfi_config(master, spi, xfer); - if (master->can_dma && master->can_dma(master, spi, xfer)) - ret = img_spfi_start_dma(master, spi, xfer); + img_spfi_config(host, spi, xfer); + if (host->can_dma && host->can_dma(host, spi, xfer)) + ret = img_spfi_start_dma(host, spi, xfer); else - ret = img_spfi_start_pio(master, spi, xfer); + ret = img_spfi_start_pio(host, spi, xfer); return ret; } -static bool img_spfi_can_dma(struct spi_master *master, struct spi_device *spi, +static bool img_spfi_can_dma(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { if (xfer->len > SPFI_32BIT_FIFO_SIZE) @@ -524,20 +524,20 @@ static irqreturn_t img_spfi_irq(int irq, void *dev_id) static int img_spfi_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *host; struct img_spfi *spfi; struct resource *res; int ret; u32 max_speed_hz; - master = spi_alloc_master(&pdev->dev, sizeof(*spfi)); - if (!master) + host = spi_alloc_host(&pdev->dev, sizeof(*spfi)); + if (!host) return -ENOMEM; - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); - spfi = spi_master_get_devdata(master); + spfi = spi_controller_get_devdata(host); spfi->dev = &pdev->dev; - spfi->master = master; + spfi->host = host; spin_lock_init(&spfi->lock); spfi->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); @@ -582,15 +582,15 @@ static int img_spfi_probe(struct platform_device *pdev) */ spfi_writel(spfi, SPFI_INTERRUPT_IACCESS, SPFI_INTERRUPT_ENABLE); - master->auto_runtime_pm = true; - master->bus_num = pdev->id; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_TX_DUAL | SPI_RX_DUAL; + host->auto_runtime_pm = true; + host->bus_num = pdev->id; + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_TX_DUAL | SPI_RX_DUAL; if (of_property_read_bool(spfi->dev->of_node, "img,supports-quad-mode")) - master->mode_bits |= SPI_TX_QUAD | SPI_RX_QUAD; - master->dev.of_node = pdev->dev.of_node; - master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(8); - master->max_speed_hz = clk_get_rate(spfi->spfi_clk) / 4; - master->min_speed_hz = clk_get_rate(spfi->spfi_clk) / 512; + host->mode_bits |= SPI_TX_QUAD | SPI_RX_QUAD; + host->dev.of_node = pdev->dev.of_node; + host->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(8); + host->max_speed_hz = clk_get_rate(spfi->spfi_clk) / 4; + host->min_speed_hz = clk_get_rate(spfi->spfi_clk) / 512; /* * Maximum speed supported by spfi is limited to the lower value @@ -601,15 +601,15 @@ static int img_spfi_probe(struct platform_device *pdev) */ if (!of_property_read_u32(spfi->dev->of_node, "spfi-max-frequency", &max_speed_hz)) { - if (master->max_speed_hz > max_speed_hz) - master->max_speed_hz = max_speed_hz; + if (host->max_speed_hz > max_speed_hz) + host->max_speed_hz = max_speed_hz; } - master->transfer_one = img_spfi_transfer_one; - master->prepare_message = img_spfi_prepare; - master->unprepare_message = img_spfi_unprepare; - master->handle_err = img_spfi_handle_err; - master->use_gpio_descriptors = true; + host->transfer_one = img_spfi_transfer_one; + host->prepare_message = img_spfi_prepare; + host->unprepare_message = img_spfi_unprepare; + host->handle_err = img_spfi_handle_err; + host->use_gpio_descriptors = true; spfi->tx_ch = dma_request_chan(spfi->dev, "tx"); if (IS_ERR(spfi->tx_ch)) { @@ -636,15 +636,15 @@ static int img_spfi_probe(struct platform_device *pdev) spfi->rx_ch = NULL; dev_warn(spfi->dev, "Failed to get DMA channels, falling back to PIO mode\n"); } else { - master->dma_tx = spfi->tx_ch; - master->dma_rx = spfi->rx_ch; - master->can_dma = img_spfi_can_dma; + host->dma_tx = spfi->tx_ch; + host->dma_rx = spfi->rx_ch; + host->can_dma = img_spfi_can_dma; } pm_runtime_set_active(spfi->dev); pm_runtime_enable(spfi->dev); - ret = devm_spi_register_master(spfi->dev, master); + ret = devm_spi_register_controller(spfi->dev, host); if (ret) goto disable_pm; @@ -660,15 +660,15 @@ disable_pm: disable_pclk: clk_disable_unprepare(spfi->sys_clk); put_spi: - spi_master_put(master); + spi_controller_put(host); return ret; } static void img_spfi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct img_spfi *spfi = spi_master_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(pdev); + struct img_spfi *spfi = spi_controller_get_devdata(host); if (spfi->tx_ch) dma_release_channel(spfi->tx_ch); @@ -685,8 +685,8 @@ static void img_spfi_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int img_spfi_runtime_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct img_spfi *spfi = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct img_spfi *spfi = spi_controller_get_devdata(host); clk_disable_unprepare(spfi->spfi_clk); clk_disable_unprepare(spfi->sys_clk); @@ -696,8 +696,8 @@ static int img_spfi_runtime_suspend(struct device *dev) static int img_spfi_runtime_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct img_spfi *spfi = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct img_spfi *spfi = spi_controller_get_devdata(host); int ret; ret = clk_prepare_enable(spfi->sys_clk); @@ -716,15 +716,15 @@ static int img_spfi_runtime_resume(struct device *dev) #ifdef CONFIG_PM_SLEEP static int img_spfi_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); + struct spi_controller *host = dev_get_drvdata(dev); - return spi_master_suspend(master); + return spi_controller_suspend(host); } static int img_spfi_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct img_spfi *spfi = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct img_spfi *spfi = spi_controller_get_devdata(host); int ret; ret = pm_runtime_resume_and_get(dev); @@ -733,7 +733,7 @@ static int img_spfi_resume(struct device *dev) spfi_reset(spfi); pm_runtime_put(dev); - return spi_master_resume(master); + return spi_controller_resume(host); } #endif /* CONFIG_PM_SLEEP */ diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 528ae46c087f..a8a74c7cb79f 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -20,7 +20,6 @@ #include <linux/spi/spi.h> #include <linux/types.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/property.h> #include <linux/dma/imx-dma.h> @@ -53,7 +52,7 @@ MODULE_PARM_DESC(polling_limit_us, /* The maximum bytes that a sdma BD can transfer. */ #define MAX_SDMA_BD_BYTES (1 << 15) #define MX51_ECSPI_CTRL_MAX_BURST 512 -/* The maximum bytes that IMX53_ECSPI can transfer in slave mode.*/ +/* The maximum bytes that IMX53_ECSPI can transfer in target mode.*/ #define MX53_MAX_TRANSFER_BYTES 512 enum spi_imx_devtype { @@ -78,7 +77,7 @@ struct spi_imx_devtype_data { void (*setup_wml)(struct spi_imx_data *spi_imx); void (*disable)(struct spi_imx_data *spi_imx); bool has_dmamode; - bool has_slavemode; + bool has_targetmode; unsigned int fifo_size; bool dynamic_burst; /* @@ -114,10 +113,10 @@ struct spi_imx_data { unsigned int dynamic_burst; bool rx_only; - /* Slave mode */ - bool slave_mode; - bool slave_aborted; - unsigned int slave_burst; + /* Target mode */ + bool target_mode; + bool target_aborted; + unsigned int target_burst; /* DMA */ bool usedma; @@ -241,7 +240,7 @@ static bool spi_imx_can_dma(struct spi_controller *controller, struct spi_device if (!controller->dma_rx) return false; - if (spi_imx->slave_mode) + if (spi_imx->target_mode) return false; if (transfer->len < spi_imx->devtype_data->fifo_size) @@ -405,12 +404,12 @@ static void spi_imx_buf_tx_swap(struct spi_imx_data *spi_imx) writel(val, spi_imx->base + MXC_CSPITXDATA); } -static void mx53_ecspi_rx_slave(struct spi_imx_data *spi_imx) +static void mx53_ecspi_rx_target(struct spi_imx_data *spi_imx) { u32 val = be32_to_cpu(readl(spi_imx->base + MXC_CSPIRXDATA)); if (spi_imx->rx_buf) { - int n_bytes = spi_imx->slave_burst % sizeof(val); + int n_bytes = spi_imx->target_burst % sizeof(val); if (!n_bytes) n_bytes = sizeof(val); @@ -419,13 +418,13 @@ static void mx53_ecspi_rx_slave(struct spi_imx_data *spi_imx) ((u8 *)&val) + sizeof(val) - n_bytes, n_bytes); spi_imx->rx_buf += n_bytes; - spi_imx->slave_burst -= n_bytes; + spi_imx->target_burst -= n_bytes; } spi_imx->remainder -= sizeof(u32); } -static void mx53_ecspi_tx_slave(struct spi_imx_data *spi_imx) +static void mx53_ecspi_tx_target(struct spi_imx_data *spi_imx) { u32 val = 0; int n_bytes = spi_imx->count % sizeof(val); @@ -536,8 +535,8 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, u32 current_cfg = cfg; int channel = mx51_ecspi_channel(spi); - /* set Master or Slave mode */ - if (spi_imx->slave_mode) + /* set Host or Target mode */ + if (spi_imx->target_mode) ctrl &= ~MX51_ECSPI_CTRL_MODE_MASK; else ctrl |= MX51_ECSPI_CTRL_MODE_MASK; @@ -565,11 +564,11 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, writel(testreg, spi_imx->base + MX51_ECSPI_TESTREG); /* - * eCSPI burst completion by Chip Select signal in Slave mode + * eCSPI burst completion by Chip Select signal in Target mode * is not functional for imx53 Soc, config SPI burst completed when * BURST_LENGTH + 1 bits are received */ - if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx)) + if (spi_imx->target_mode && is_imx53_ecspi(spi_imx)) cfg &= ~MX51_ECSPI_CONFIG_SBBCTRL(channel); else cfg |= MX51_ECSPI_CONFIG_SBBCTRL(channel); @@ -656,12 +655,16 @@ static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx, /* Clear BL field and set the right value */ ctrl &= ~MX51_ECSPI_CTRL_BL_MASK; - if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx)) - ctrl |= (spi_imx->slave_burst * 8 - 1) - << MX51_ECSPI_CTRL_BL_OFFSET; - else - ctrl |= (spi_imx->bits_per_word - 1) + if (spi_imx->target_mode && is_imx53_ecspi(spi_imx)) + ctrl |= (spi_imx->target_burst * 8 - 1) << MX51_ECSPI_CTRL_BL_OFFSET; + else { + if (spi_imx->count >= 512) + ctrl |= 0xFFF << MX51_ECSPI_CTRL_BL_OFFSET; + else + ctrl |= (spi_imx->count*8 - 1) + << MX51_ECSPI_CTRL_BL_OFFSET; + } /* set clock speed */ ctrl &= ~(0xf << MX51_ECSPI_CTRL_POSTDIV_OFFSET | @@ -718,7 +721,7 @@ static void mx51_ecspi_reset(struct spi_imx_data *spi_imx) #define MX31_INTREG_RREN (1 << 3) #define MX31_CSPICTRL_ENABLE (1 << 0) -#define MX31_CSPICTRL_MASTER (1 << 1) +#define MX31_CSPICTRL_HOST (1 << 1) #define MX31_CSPICTRL_XCH (1 << 2) #define MX31_CSPICTRL_SMC (1 << 3) #define MX31_CSPICTRL_POL (1 << 4) @@ -775,7 +778,7 @@ static int mx31_prepare_message(struct spi_imx_data *spi_imx, static int mx31_prepare_transfer(struct spi_imx_data *spi_imx, struct spi_device *spi) { - unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER; + unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_HOST; unsigned int clk; reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, spi_imx->spi_bus_clk, &clk) << @@ -845,7 +848,7 @@ static void mx31_reset(struct spi_imx_data *spi_imx) #define MX21_CSPICTRL_SSPOL (1 << 8) #define MX21_CSPICTRL_XCH (1 << 9) #define MX21_CSPICTRL_ENABLE (1 << 10) -#define MX21_CSPICTRL_MASTER (1 << 11) +#define MX21_CSPICTRL_HOST (1 << 11) #define MX21_CSPICTRL_DR_SHIFT 14 #define MX21_CSPICTRL_CS_SHIFT 19 @@ -879,7 +882,7 @@ static int mx21_prepare_message(struct spi_imx_data *spi_imx, static int mx21_prepare_transfer(struct spi_imx_data *spi_imx, struct spi_device *spi) { - unsigned int reg = MX21_CSPICTRL_ENABLE | MX21_CSPICTRL_MASTER; + unsigned int reg = MX21_CSPICTRL_ENABLE | MX21_CSPICTRL_HOST; unsigned int max = is_imx27_cspi(spi_imx) ? 16 : 18; unsigned int clk; @@ -921,7 +924,7 @@ static void mx21_reset(struct spi_imx_data *spi_imx) #define MX1_CSPICTRL_PHA (1 << 5) #define MX1_CSPICTRL_XCH (1 << 8) #define MX1_CSPICTRL_ENABLE (1 << 9) -#define MX1_CSPICTRL_MASTER (1 << 10) +#define MX1_CSPICTRL_HOST (1 << 10) #define MX1_CSPICTRL_DR_SHIFT 13 static void mx1_intctrl(struct spi_imx_data *spi_imx, int enable) @@ -954,7 +957,7 @@ static int mx1_prepare_message(struct spi_imx_data *spi_imx, static int mx1_prepare_transfer(struct spi_imx_data *spi_imx, struct spi_device *spi) { - unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_MASTER; + unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_HOST; unsigned int clk; reg |= spi_imx_clkdiv_2(spi_imx->spi_clk, spi_imx->spi_bus_clk, &clk) << @@ -993,7 +996,7 @@ static struct spi_imx_devtype_data imx1_cspi_devtype_data = { .fifo_size = 8, .has_dmamode = false, .dynamic_burst = false, - .has_slavemode = false, + .has_targetmode = false, .devtype = IMX1_CSPI, }; @@ -1007,7 +1010,7 @@ static struct spi_imx_devtype_data imx21_cspi_devtype_data = { .fifo_size = 8, .has_dmamode = false, .dynamic_burst = false, - .has_slavemode = false, + .has_targetmode = false, .devtype = IMX21_CSPI, }; @@ -1022,7 +1025,7 @@ static struct spi_imx_devtype_data imx27_cspi_devtype_data = { .fifo_size = 8, .has_dmamode = false, .dynamic_burst = false, - .has_slavemode = false, + .has_targetmode = false, .devtype = IMX27_CSPI, }; @@ -1036,7 +1039,7 @@ static struct spi_imx_devtype_data imx31_cspi_devtype_data = { .fifo_size = 8, .has_dmamode = false, .dynamic_burst = false, - .has_slavemode = false, + .has_targetmode = false, .devtype = IMX31_CSPI, }; @@ -1051,7 +1054,7 @@ static struct spi_imx_devtype_data imx35_cspi_devtype_data = { .fifo_size = 8, .has_dmamode = true, .dynamic_burst = false, - .has_slavemode = false, + .has_targetmode = false, .devtype = IMX35_CSPI, }; @@ -1066,7 +1069,7 @@ static struct spi_imx_devtype_data imx51_ecspi_devtype_data = { .fifo_size = 64, .has_dmamode = true, .dynamic_burst = true, - .has_slavemode = true, + .has_targetmode = true, .disable = mx51_ecspi_disable, .devtype = IMX51_ECSPI, }; @@ -1080,7 +1083,7 @@ static struct spi_imx_devtype_data imx53_ecspi_devtype_data = { .reset = mx51_ecspi_reset, .fifo_size = 64, .has_dmamode = true, - .has_slavemode = true, + .has_targetmode = true, .disable = mx51_ecspi_disable, .devtype = IMX53_ECSPI, }; @@ -1096,7 +1099,7 @@ static struct spi_imx_devtype_data imx6ul_ecspi_devtype_data = { .fifo_size = 64, .has_dmamode = true, .dynamic_burst = true, - .has_slavemode = true, + .has_targetmode = true, .tx_glitch_fixed = true, .disable = mx51_ecspi_disable, .devtype = IMX51_ECSPI, @@ -1161,7 +1164,7 @@ static void spi_imx_push(struct spi_imx_data *spi_imx) spi_imx->txfifo++; } - if (!spi_imx->slave_mode) + if (!spi_imx->target_mode) spi_imx->devtype_data->trigger(spi_imx); } @@ -1258,13 +1261,14 @@ static int spi_imx_setupxfer(struct spi_device *spi, spi_imx->spi_bus_clk = t->speed_hz; spi_imx->bits_per_word = t->bits_per_word; + spi_imx->count = t->len; /* * Initialize the functions for transfer. To transfer non byte-aligned * words, we have to use multiple word-size bursts, we can't use * dynamic_burst in that case. */ - if (spi_imx->devtype_data->dynamic_burst && !spi_imx->slave_mode && + if (spi_imx->devtype_data->dynamic_burst && !spi_imx->target_mode && !(spi->mode & SPI_CS_WORD) && (spi_imx->bits_per_word == 8 || spi_imx->bits_per_word == 16 || @@ -1296,10 +1300,10 @@ static int spi_imx_setupxfer(struct spi_device *spi, spi_imx->rx_only = ((t->tx_buf == NULL) || (t->tx_buf == spi->controller->dummy_tx)); - if (is_imx53_ecspi(spi_imx) && spi_imx->slave_mode) { - spi_imx->rx = mx53_ecspi_rx_slave; - spi_imx->tx = mx53_ecspi_tx_slave; - spi_imx->slave_burst = t->len; + if (is_imx53_ecspi(spi_imx) && spi_imx->target_mode) { + spi_imx->rx = mx53_ecspi_rx_target; + spi_imx->tx = mx53_ecspi_tx_target; + spi_imx->target_burst = t->len; } spi_imx->devtype_data->prepare_transfer(spi_imx, spi); @@ -1564,8 +1568,8 @@ static int spi_imx_poll_transfer(struct spi_device *spi, return 0; } -static int spi_imx_pio_transfer_slave(struct spi_device *spi, - struct spi_transfer *transfer) +static int spi_imx_pio_transfer_target(struct spi_device *spi, + struct spi_transfer *transfer) { struct spi_imx_data *spi_imx = spi_controller_get_devdata(spi->controller); int ret = 0; @@ -1584,22 +1588,22 @@ static int spi_imx_pio_transfer_slave(struct spi_device *spi, spi_imx->remainder = 0; reinit_completion(&spi_imx->xfer_done); - spi_imx->slave_aborted = false; + spi_imx->target_aborted = false; spi_imx_push(spi_imx); spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TE | MXC_INT_RDR); if (wait_for_completion_interruptible(&spi_imx->xfer_done) || - spi_imx->slave_aborted) { + spi_imx->target_aborted) { dev_dbg(&spi->dev, "interrupted\n"); ret = -EINTR; } - /* ecspi has a HW issue when works in Slave mode, + /* ecspi has a HW issue when works in Target mode, * after 64 words writtern to TXFIFO, even TXFIFO becomes empty, * ECSPI_TXDATA keeps shift out the last word data, - * so we have to disable ECSPI when in slave mode after the + * so we have to disable ECSPI when in target mode after the * transfer completes */ if (spi_imx->devtype_data->disable) @@ -1622,8 +1626,8 @@ static int spi_imx_transfer_one(struct spi_controller *controller, while (spi_imx->devtype_data->rx_available(spi_imx)) readl(spi_imx->base + MXC_CSPIRXDATA); - if (spi_imx->slave_mode) - return spi_imx_pio_transfer_slave(spi, transfer); + if (spi_imx->target_mode) + return spi_imx_pio_transfer_target(spi, transfer); /* * If we decided in spi_imx_can_dma() that we want to do a DMA @@ -1689,11 +1693,11 @@ spi_imx_unprepare_message(struct spi_controller *controller, struct spi_message return 0; } -static int spi_imx_slave_abort(struct spi_controller *controller) +static int spi_imx_target_abort(struct spi_controller *controller) { struct spi_imx_data *spi_imx = spi_controller_get_devdata(controller); - spi_imx->slave_aborted = true; + spi_imx->target_aborted = true; complete(&spi_imx->xfer_done); return 0; @@ -1708,17 +1712,17 @@ static int spi_imx_probe(struct platform_device *pdev) int ret, irq, spi_drctl; const struct spi_imx_devtype_data *devtype_data = of_device_get_match_data(&pdev->dev); - bool slave_mode; + bool target_mode; u32 val; - slave_mode = devtype_data->has_slavemode && - of_property_read_bool(np, "spi-slave"); - if (slave_mode) - controller = spi_alloc_slave(&pdev->dev, - sizeof(struct spi_imx_data)); - else - controller = spi_alloc_master(&pdev->dev, + target_mode = devtype_data->has_targetmode && + of_property_read_bool(np, "spi-slave"); + if (target_mode) + controller = spi_alloc_target(&pdev->dev, sizeof(struct spi_imx_data)); + else + controller = spi_alloc_host(&pdev->dev, + sizeof(struct spi_imx_data)); if (!controller) return -ENOMEM; @@ -1737,7 +1741,7 @@ static int spi_imx_probe(struct platform_device *pdev) spi_imx = spi_controller_get_devdata(controller); spi_imx->controller = controller; spi_imx->dev = &pdev->dev; - spi_imx->slave_mode = slave_mode; + spi_imx->target_mode = target_mode; spi_imx->devtype_data = devtype_data; @@ -1757,7 +1761,7 @@ static int spi_imx_probe(struct platform_device *pdev) controller->cleanup = spi_imx_cleanup; controller->prepare_message = spi_imx_prepare_message; controller->unprepare_message = spi_imx_unprepare_message; - controller->slave_abort = spi_imx_slave_abort; + controller->target_abort = spi_imx_target_abort; controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_NO_CS | SPI_MOSI_IDLE_LOW; @@ -1779,7 +1783,7 @@ static int spi_imx_probe(struct platform_device *pdev) if (is_imx51_ecspi(spi_imx) || is_imx53_ecspi(spi_imx)) { controller->max_native_cs = 4; - controller->flags |= SPI_MASTER_GPIO_SS; + controller->flags |= SPI_CONTROLLER_GPIO_SS; } spi_imx->spi_drctl = spi_drctl; diff --git a/drivers/spi/spi-ingenic.c b/drivers/spi/spi-ingenic.c index 7d4b515a160d..cc366936d72b 100644 --- a/drivers/spi/spi-ingenic.c +++ b/drivers/spi/spi-ingenic.c @@ -12,7 +12,7 @@ #include <linux/dma-mapping.h> #include <linux/iopoll.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/spi/spi.h> @@ -392,7 +392,7 @@ static int spi_ingenic_probe(struct platform_device *pdev) return -EINVAL; } - ctlr = devm_spi_alloc_master(dev, sizeof(*priv)); + ctlr = devm_spi_alloc_host(dev, sizeof(*priv)); if (!ctlr) { dev_err(dev, "Unable to allocate SPI controller.\n"); return -ENOMEM; diff --git a/drivers/spi/spi-intel.c b/drivers/spi/spi-intel.c index bc6d22149e7e..98ec4dc22b81 100644 --- a/drivers/spi/spi-intel.c +++ b/drivers/spi/spi-intel.c @@ -143,7 +143,7 @@ * @base: Beginning of MMIO space * @pregs: Start of protection registers * @sregs: Start of software sequencer registers - * @master: Pointer to the SPI controller structure + * @host: Pointer to the SPI controller structure * @nregions: Maximum number of regions * @pr_num: Maximum number of protected range registers * @chip0_size: Size of the first flash chip in bytes @@ -161,7 +161,7 @@ struct intel_spi { void __iomem *base; void __iomem *pregs; void __iomem *sregs; - struct spi_controller *master; + struct spi_controller *host; size_t nregions; size_t pr_num; size_t chip0_size; @@ -747,7 +747,7 @@ intel_spi_match_mem_op(struct intel_spi *ispi, const struct spi_mem_op *op) static bool intel_spi_supports_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) { - struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master); + struct intel_spi *ispi = spi_controller_get_devdata(mem->spi->controller); const struct intel_spi_mem_op *iop; iop = intel_spi_match_mem_op(ispi, op); @@ -778,7 +778,7 @@ static bool intel_spi_supports_mem_op(struct spi_mem *mem, static int intel_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) { - struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master); + struct intel_spi *ispi = spi_controller_get_devdata(mem->spi->controller); const struct intel_spi_mem_op *iop; iop = intel_spi_match_mem_op(ispi, op); @@ -790,7 +790,7 @@ static int intel_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *o static const char *intel_spi_get_name(struct spi_mem *mem) { - const struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master); + const struct intel_spi *ispi = spi_controller_get_devdata(mem->spi->controller); /* * Return name of the flash controller device to be compatible @@ -801,7 +801,7 @@ static const char *intel_spi_get_name(struct spi_mem *mem) static int intel_spi_dirmap_create(struct spi_mem_dirmap_desc *desc) { - struct intel_spi *ispi = spi_master_get_devdata(desc->mem->spi->master); + struct intel_spi *ispi = spi_controller_get_devdata(desc->mem->spi->controller); const struct intel_spi_mem_op *iop; iop = intel_spi_match_mem_op(ispi, &desc->info.op_tmpl); @@ -815,7 +815,7 @@ static int intel_spi_dirmap_create(struct spi_mem_dirmap_desc *desc) static ssize_t intel_spi_dirmap_read(struct spi_mem_dirmap_desc *desc, u64 offs, size_t len, void *buf) { - struct intel_spi *ispi = spi_master_get_devdata(desc->mem->spi->master); + struct intel_spi *ispi = spi_controller_get_devdata(desc->mem->spi->controller); const struct intel_spi_mem_op *iop = desc->priv; struct spi_mem_op op = desc->info.op_tmpl; int ret; @@ -832,7 +832,7 @@ static ssize_t intel_spi_dirmap_read(struct spi_mem_dirmap_desc *desc, u64 offs, static ssize_t intel_spi_dirmap_write(struct spi_mem_dirmap_desc *desc, u64 offs, size_t len, const void *buf) { - struct intel_spi *ispi = spi_master_get_devdata(desc->mem->spi->master); + struct intel_spi *ispi = spi_controller_get_devdata(desc->mem->spi->controller); const struct intel_spi_mem_op *iop = desc->priv; struct spi_mem_op op = desc->info.op_tmpl; int ret; @@ -1332,14 +1332,14 @@ static int intel_spi_read_desc(struct intel_spi *ispi) nc = (buf[1] & FLMAP0_NC_MASK) >> FLMAP0_NC_SHIFT; if (!nc) - ispi->master->num_chipselect = 1; + ispi->host->num_chipselect = 1; else if (nc == 1) - ispi->master->num_chipselect = 2; + ispi->host->num_chipselect = 2; else return -EINVAL; dev_dbg(ispi->dev, "%u flash components found\n", - ispi->master->num_chipselect); + ispi->host->num_chipselect); return 0; } @@ -1365,7 +1365,7 @@ static int intel_spi_populate_chip(struct intel_spi *ispi) snprintf(chip.modalias, 8, "spi-nor"); chip.platform_data = pdata; - if (!spi_new_device(ispi->master, &chip)) + if (!spi_new_device(ispi->host, &chip)) return -ENODEV; ret = intel_spi_read_desc(ispi); @@ -1373,13 +1373,13 @@ static int intel_spi_populate_chip(struct intel_spi *ispi) return ret; /* Add the second chip if present */ - if (ispi->master->num_chipselect < 2) + if (ispi->host->num_chipselect < 2) return 0; chip.platform_data = NULL; chip.chip_select = 1; - if (!spi_new_device(ispi->master, &chip)) + if (!spi_new_device(ispi->host, &chip)) return -ENODEV; return 0; } @@ -1396,31 +1396,31 @@ static int intel_spi_populate_chip(struct intel_spi *ispi) int intel_spi_probe(struct device *dev, struct resource *mem, const struct intel_spi_boardinfo *info) { - struct spi_controller *master; + struct spi_controller *host; struct intel_spi *ispi; int ret; - master = devm_spi_alloc_master(dev, sizeof(*ispi)); - if (!master) + host = devm_spi_alloc_host(dev, sizeof(*ispi)); + if (!host) return -ENOMEM; - master->mem_ops = &intel_spi_mem_ops; + host->mem_ops = &intel_spi_mem_ops; - ispi = spi_master_get_devdata(master); + ispi = spi_controller_get_devdata(host); ispi->base = devm_ioremap_resource(dev, mem); if (IS_ERR(ispi->base)) return PTR_ERR(ispi->base); ispi->dev = dev; - ispi->master = master; + ispi->host = host; ispi->info = info; ret = intel_spi_init(ispi); if (ret) return ret; - ret = devm_spi_register_master(dev, master); + ret = devm_spi_register_controller(dev, host); if (ret) return ret; diff --git a/drivers/spi/spi-iproc-qspi.c b/drivers/spi/spi-iproc-qspi.c index 5980a0dbbccb..39ee2b43a516 100644 --- a/drivers/spi/spi-iproc-qspi.c +++ b/drivers/spi/spi-iproc-qspi.c @@ -94,7 +94,6 @@ static int bcm_iproc_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct bcm_iproc_intc *priv; struct bcm_qspi_soc_intc *soc_intc; - struct resource *res; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -104,14 +103,12 @@ static int bcm_iproc_probe(struct platform_device *pdev) spin_lock_init(&priv->soclock); - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr_regs"); - priv->int_reg = devm_ioremap_resource(dev, res); + priv->int_reg = devm_platform_ioremap_resource_byname(pdev, "intr_regs"); if (IS_ERR(priv->int_reg)) return PTR_ERR(priv->int_reg); - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "intr_status_reg"); - priv->int_status_reg = devm_ioremap_resource(dev, res); + priv->int_status_reg = devm_platform_ioremap_resource_byname(pdev, + "intr_status_reg"); if (IS_ERR(priv->int_status_reg)) return PTR_ERR(priv->int_status_reg); diff --git a/drivers/spi/spi-jcore.c b/drivers/spi/spi-jcore.c index c42a3358e8c9..e37ca22e04ba 100644 --- a/drivers/spi/spi-jcore.c +++ b/drivers/spi/spi-jcore.c @@ -33,7 +33,7 @@ #define JCORE_SPI_WAIT_RDY_MAX_LOOP 2000000 struct jcore_spi { - struct spi_master *master; + struct spi_controller *host; void __iomem *base; unsigned int cs_reg; unsigned int speed_reg; @@ -59,7 +59,7 @@ static void jcore_spi_program(struct jcore_spi *hw) void __iomem *ctrl_reg = hw->base + CTRL_REG; if (jcore_spi_wait(ctrl_reg)) - dev_err(hw->master->dev.parent, + dev_err(hw->host->dev.parent, "timeout waiting to program ctrl reg.\n"); writel(hw->cs_reg | hw->speed_reg, ctrl_reg); @@ -67,10 +67,10 @@ static void jcore_spi_program(struct jcore_spi *hw) static void jcore_spi_chipsel(struct spi_device *spi, bool value) { - struct jcore_spi *hw = spi_master_get_devdata(spi->master); + struct jcore_spi *hw = spi_controller_get_devdata(spi->controller); u32 csbit = 1U << (2 * spi_get_chipselect(spi, 0)); - dev_dbg(hw->master->dev.parent, "chipselect %d\n", spi_get_chipselect(spi, 0)); + dev_dbg(hw->host->dev.parent, "chipselect %d\n", spi_get_chipselect(spi, 0)); if (value) hw->cs_reg |= csbit; @@ -90,14 +90,14 @@ static void jcore_spi_baudrate(struct jcore_spi *hw, int speed) else hw->speed_reg = ((hw->clock_freq / 2 / speed) - 1) << 27; jcore_spi_program(hw); - dev_dbg(hw->master->dev.parent, "speed=%d reg=0x%x\n", + dev_dbg(hw->host->dev.parent, "speed=%d reg=0x%x\n", speed, hw->speed_reg); } -static int jcore_spi_txrx(struct spi_master *master, struct spi_device *spi, +static int jcore_spi_txrx(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *t) { - struct jcore_spi *hw = spi_master_get_devdata(master); + struct jcore_spi *hw = spi_controller_get_devdata(host); void __iomem *ctrl_reg = hw->base + CTRL_REG; void __iomem *data_reg = hw->base + DATA_REG; @@ -130,7 +130,7 @@ static int jcore_spi_txrx(struct spi_master *master, struct spi_device *spi, *rx++ = readl(data_reg); } - spi_finalize_current_transfer(master); + spi_finalize_current_transfer(host); if (count < len) return -EREMOTEIO; @@ -142,26 +142,26 @@ static int jcore_spi_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct jcore_spi *hw; - struct spi_master *master; + struct spi_controller *host; struct resource *res; u32 clock_freq; struct clk *clk; int err = -ENODEV; - master = spi_alloc_master(&pdev->dev, sizeof(struct jcore_spi)); - if (!master) + host = spi_alloc_host(&pdev->dev, sizeof(struct jcore_spi)); + if (!host) return err; - /* Setup the master state. */ - master->num_chipselect = 3; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; - master->transfer_one = jcore_spi_txrx; - master->set_cs = jcore_spi_chipsel; - master->dev.of_node = node; - master->bus_num = pdev->id; + /* Setup the host state. */ + host->num_chipselect = 3; + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + host->transfer_one = jcore_spi_txrx; + host->set_cs = jcore_spi_chipsel; + host->dev.of_node = node; + host->bus_num = pdev->id; - hw = spi_master_get_devdata(master); - hw->master = master; + hw = spi_controller_get_devdata(host); + hw->host = host; platform_set_drvdata(pdev, hw); /* Find and map our resources */ @@ -200,7 +200,7 @@ static int jcore_spi_probe(struct platform_device *pdev) jcore_spi_baudrate(hw, 400000); /* Register our spi controller */ - err = devm_spi_register_master(&pdev->dev, master); + err = devm_spi_register_controller(&pdev->dev, host); if (err) goto exit; @@ -209,7 +209,7 @@ static int jcore_spi_probe(struct platform_device *pdev) exit_busy: err = -EBUSY; exit: - spi_master_put(master); + spi_controller_put(host); return err; } diff --git a/drivers/spi/spi-lantiq-ssc.c b/drivers/spi/spi-lantiq-ssc.c index 8d6ecc5d6f70..938e9e577e4f 100644 --- a/drivers/spi/spi-lantiq-ssc.c +++ b/drivers/spi/spi-lantiq-ssc.c @@ -6,7 +6,8 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/clk.h> #include <linux/io.h> #include <linux/delay.h> @@ -91,7 +92,7 @@ #define LTQ_SPI_STAT_RE BIT(9) /* Receive error flag */ #define LTQ_SPI_STAT_TE BIT(8) /* Transmit error flag */ #define LTQ_SPI_STAT_ME BIT(7) /* Mode error flag */ -#define LTQ_SPI_STAT_MS BIT(1) /* Master/slave select bit */ +#define LTQ_SPI_STAT_MS BIT(1) /* Host/target select bit */ #define LTQ_SPI_STAT_EN BIT(0) /* Enable bit */ #define LTQ_SPI_STAT_ERRORS (LTQ_SPI_STAT_ME | LTQ_SPI_STAT_TE | \ LTQ_SPI_STAT_RE | LTQ_SPI_STAT_AE | \ @@ -109,8 +110,8 @@ #define LTQ_SPI_WHBSTATE_CLRME BIT(6) /* Clear mode error flag */ #define LTQ_SPI_WHBSTATE_SETRUE BIT(5) /* Set receive underflow error flag */ #define LTQ_SPI_WHBSTATE_CLRRUE BIT(4) /* Clear receive underflow error flag */ -#define LTQ_SPI_WHBSTATE_SETMS BIT(3) /* Set master select bit */ -#define LTQ_SPI_WHBSTATE_CLRMS BIT(2) /* Clear master select bit */ +#define LTQ_SPI_WHBSTATE_SETMS BIT(3) /* Set host select bit */ +#define LTQ_SPI_WHBSTATE_CLRMS BIT(2) /* Clear host select bit */ #define LTQ_SPI_WHBSTATE_SETEN BIT(1) /* Set enable bit (operational mode) */ #define LTQ_SPI_WHBSTATE_CLREN BIT(0) /* Clear enable bit (config mode */ #define LTQ_SPI_WHBSTATE_CLR_ERRORS (LTQ_SPI_WHBSTATE_CLRRUE | \ @@ -162,7 +163,7 @@ struct lantiq_ssc_hwcfg { }; struct lantiq_ssc_spi { - struct spi_master *master; + struct spi_controller *host; struct device *dev; void __iomem *regbase; struct clk *spi_clk; @@ -366,7 +367,7 @@ static void lantiq_ssc_hw_init(const struct lantiq_ssc_spi *spi) hw_setup_bits_per_word(spi, spi->bits_per_word); hw_setup_clock_mode(spi, SPI_MODE_0); - /* Enable master mode and clear error flags */ + /* Enable host mode and clear error flags */ lantiq_ssc_writel(spi, LTQ_SPI_WHBSTATE_SETMS | LTQ_SPI_WHBSTATE_CLR_ERRORS, LTQ_SPI_WHBSTATE); @@ -386,8 +387,8 @@ static void lantiq_ssc_hw_init(const struct lantiq_ssc_spi *spi) static int lantiq_ssc_setup(struct spi_device *spidev) { - struct spi_master *master = spidev->master; - struct lantiq_ssc_spi *spi = spi_master_get_devdata(master); + struct spi_controller *host = spidev->controller; + struct lantiq_ssc_spi *spi = spi_controller_get_devdata(host); unsigned int cs = spi_get_chipselect(spidev, 0); u32 gpocon; @@ -415,10 +416,10 @@ static int lantiq_ssc_setup(struct spi_device *spidev) return 0; } -static int lantiq_ssc_prepare_message(struct spi_master *master, +static int lantiq_ssc_prepare_message(struct spi_controller *host, struct spi_message *message) { - struct lantiq_ssc_spi *spi = spi_master_get_devdata(master); + struct lantiq_ssc_spi *spi = spi_controller_get_devdata(host); hw_enter_config_mode(spi); hw_setup_clock_mode(spi, message->spi->mode); @@ -460,10 +461,10 @@ static void hw_setup_transfer(struct lantiq_ssc_spi *spi, lantiq_ssc_writel(spi, con, LTQ_SPI_CON); } -static int lantiq_ssc_unprepare_message(struct spi_master *master, +static int lantiq_ssc_unprepare_message(struct spi_controller *host, struct spi_message *message) { - struct lantiq_ssc_spi *spi = spi_master_get_devdata(master); + struct lantiq_ssc_spi *spi = spi_controller_get_devdata(host); flush_workqueue(spi->wq); @@ -692,8 +693,8 @@ static irqreturn_t lantiq_ssc_err_interrupt(int irq, void *data) lantiq_ssc_maskl(spi, 0, LTQ_SPI_WHBSTATE_CLR_ERRORS, LTQ_SPI_WHBSTATE); /* set bad status so it can be retried */ - if (spi->master->cur_msg) - spi->master->cur_msg->status = -EIO; + if (spi->host->cur_msg) + spi->host->cur_msg->status = -EIO; queue_work(spi->wq, &spi->work); spin_unlock(&spi->lock); @@ -771,22 +772,22 @@ static void lantiq_ssc_bussy_work(struct work_struct *work) u32 stat = lantiq_ssc_readl(spi, LTQ_SPI_STAT); if (!(stat & LTQ_SPI_STAT_BSY)) { - spi_finalize_current_transfer(spi->master); + spi_finalize_current_transfer(spi->host); return; } cond_resched(); } while (!time_after_eq(jiffies, end)); - if (spi->master->cur_msg) - spi->master->cur_msg->status = -EIO; - spi_finalize_current_transfer(spi->master); + if (spi->host->cur_msg) + spi->host->cur_msg->status = -EIO; + spi_finalize_current_transfer(spi->host); } -static void lantiq_ssc_handle_err(struct spi_master *master, +static void lantiq_ssc_handle_err(struct spi_controller *host, struct spi_message *message) { - struct lantiq_ssc_spi *spi = spi_master_get_devdata(master); + struct lantiq_ssc_spi *spi = spi_controller_get_devdata(host); /* flush FIFOs on timeout */ rx_fifo_flush(spi); @@ -795,7 +796,7 @@ static void lantiq_ssc_handle_err(struct spi_master *master, static void lantiq_ssc_set_cs(struct spi_device *spidev, bool enable) { - struct lantiq_ssc_spi *spi = spi_master_get_devdata(spidev->master); + struct lantiq_ssc_spi *spi = spi_controller_get_devdata(spidev->controller); unsigned int cs = spi_get_chipselect(spidev, 0); u32 fgpo; @@ -807,11 +808,11 @@ static void lantiq_ssc_set_cs(struct spi_device *spidev, bool enable) lantiq_ssc_writel(spi, fgpo, LTQ_SPI_FPGO); } -static int lantiq_ssc_transfer_one(struct spi_master *master, +static int lantiq_ssc_transfer_one(struct spi_controller *host, struct spi_device *spidev, struct spi_transfer *t) { - struct lantiq_ssc_spi *spi = spi_master_get_devdata(master); + struct lantiq_ssc_spi *spi = spi_controller_get_devdata(host); hw_setup_transfer(spi, spidev, t); @@ -903,7 +904,7 @@ MODULE_DEVICE_TABLE(of, lantiq_ssc_match); static int lantiq_ssc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct spi_master *master; + struct spi_controller *host; struct lantiq_ssc_spi *spi; const struct lantiq_ssc_hwcfg *hwcfg; u32 id, supports_dma, revision; @@ -912,33 +913,33 @@ static int lantiq_ssc_probe(struct platform_device *pdev) hwcfg = of_device_get_match_data(dev); - master = spi_alloc_master(dev, sizeof(struct lantiq_ssc_spi)); - if (!master) + host = spi_alloc_host(dev, sizeof(struct lantiq_ssc_spi)); + if (!host) return -ENOMEM; - spi = spi_master_get_devdata(master); - spi->master = master; + spi = spi_controller_get_devdata(host); + spi->host = host; spi->dev = dev; spi->hwcfg = hwcfg; platform_set_drvdata(pdev, spi); spi->regbase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(spi->regbase)) { err = PTR_ERR(spi->regbase); - goto err_master_put; + goto err_host_put; } err = hwcfg->cfg_irq(pdev, spi); if (err) - goto err_master_put; + goto err_host_put; spi->spi_clk = devm_clk_get(dev, "gate"); if (IS_ERR(spi->spi_clk)) { err = PTR_ERR(spi->spi_clk); - goto err_master_put; + goto err_host_put; } err = clk_prepare_enable(spi->spi_clk); if (err) - goto err_master_put; + goto err_host_put; /* * Use the old clk_get_fpi() function on Lantiq platform, till it @@ -964,19 +965,19 @@ static int lantiq_ssc_probe(struct platform_device *pdev) spi->bits_per_word = 8; spi->speed_hz = 0; - master->dev.of_node = pdev->dev.of_node; - master->num_chipselect = num_cs; - master->use_gpio_descriptors = true; - master->setup = lantiq_ssc_setup; - master->set_cs = lantiq_ssc_set_cs; - master->handle_err = lantiq_ssc_handle_err; - master->prepare_message = lantiq_ssc_prepare_message; - master->unprepare_message = lantiq_ssc_unprepare_message; - master->transfer_one = lantiq_ssc_transfer_one; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH | - SPI_LOOP; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 8) | - SPI_BPW_MASK(16) | SPI_BPW_MASK(32); + host->dev.of_node = pdev->dev.of_node; + host->num_chipselect = num_cs; + host->use_gpio_descriptors = true; + host->setup = lantiq_ssc_setup; + host->set_cs = lantiq_ssc_set_cs; + host->handle_err = lantiq_ssc_handle_err; + host->prepare_message = lantiq_ssc_prepare_message; + host->unprepare_message = lantiq_ssc_unprepare_message; + host->transfer_one = lantiq_ssc_transfer_one; + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH | + SPI_LOOP; + host->bits_per_word_mask = SPI_BPW_RANGE_MASK(2, 8) | + SPI_BPW_MASK(16) | SPI_BPW_MASK(32); spi->wq = alloc_ordered_workqueue(dev_name(dev), WQ_MEM_RECLAIM); if (!spi->wq) { @@ -997,9 +998,9 @@ static int lantiq_ssc_probe(struct platform_device *pdev) "Lantiq SSC SPI controller (Rev %i, TXFS %u, RXFS %u, DMA %u)\n", revision, spi->tx_fifo_size, spi->rx_fifo_size, supports_dma); - err = devm_spi_register_master(dev, master); + err = devm_spi_register_controller(dev, host); if (err) { - dev_err(dev, "failed to register spi_master\n"); + dev_err(dev, "failed to register spi host\n"); goto err_wq_destroy; } @@ -1011,8 +1012,8 @@ err_clk_put: clk_put(spi->fpi_clk); err_clk_disable: clk_disable_unprepare(spi->spi_clk); -err_master_put: - spi_master_put(master); +err_host_put: + spi_controller_put(host); return err; } diff --git a/drivers/spi/spi-loongson-core.c b/drivers/spi/spi-loongson-core.c new file mode 100644 index 000000000000..f97800b6fd65 --- /dev/null +++ b/drivers/spi/spi-loongson-core.c @@ -0,0 +1,279 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Loongson SPI Support +// Copyright (C) 2023 Loongson Technology Corporation Limited + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/spi/spi.h> + +#include "spi-loongson.h" + +static inline void loongson_spi_write_reg(struct loongson_spi *spi, unsigned char reg, + unsigned char data) +{ + writeb(data, spi->base + reg); +} + +static inline char loongson_spi_read_reg(struct loongson_spi *spi, unsigned char reg) +{ + return readb(spi->base + reg); +} + +static void loongson_spi_set_cs(struct spi_device *spi, bool en) +{ + int cs; + unsigned char mask = (BIT(4) | BIT(0)) << spi_get_chipselect(spi, 0); + unsigned char val = en ? mask : (BIT(0) << spi_get_chipselect(spi, 0)); + struct loongson_spi *loongson_spi = spi_controller_get_devdata(spi->controller); + + cs = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SFCS_REG) & ~mask; + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SFCS_REG, val | cs); +} + +static void loongson_spi_set_clk(struct loongson_spi *loongson_spi, unsigned int hz) +{ + unsigned char val; + unsigned int div, div_tmp; + static const char rdiv[12] = {0, 1, 4, 2, 3, 5, 6, 7, 8, 9, 10, 11}; + + div = clamp_val(DIV_ROUND_UP_ULL(loongson_spi->clk_rate, hz), 2, 4096); + div_tmp = rdiv[fls(div - 1)]; + loongson_spi->spcr = (div_tmp & GENMASK(1, 0)) >> 0; + loongson_spi->sper = (div_tmp & GENMASK(3, 2)) >> 2; + val = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPCR_REG); + val &= ~GENMASK(1, 0); + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPCR_REG, val | + loongson_spi->spcr); + val = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPER_REG); + val &= ~GENMASK(1, 0); + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPER_REG, val | + loongson_spi->sper); + loongson_spi->hz = hz; +} + +static void loongson_spi_set_mode(struct loongson_spi *loongson_spi, + struct spi_device *spi) +{ + unsigned char val; + + val = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPCR_REG); + val &= ~(LOONGSON_SPI_SPCR_CPOL | LOONGSON_SPI_SPCR_CPHA); + if (spi->mode & SPI_CPOL) + val |= LOONGSON_SPI_SPCR_CPOL; + if (spi->mode & SPI_CPHA) + val |= LOONGSON_SPI_SPCR_CPHA; + + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPCR_REG, val); + loongson_spi->mode |= spi->mode; +} + +static int loongson_spi_update_state(struct loongson_spi *loongson_spi, + struct spi_device *spi, struct spi_transfer *t) +{ + if (t && loongson_spi->hz != t->speed_hz) + loongson_spi_set_clk(loongson_spi, t->speed_hz); + + if ((spi->mode ^ loongson_spi->mode) & SPI_MODE_X_MASK) + loongson_spi_set_mode(loongson_spi, spi); + + return 0; +} + +static int loongson_spi_setup(struct spi_device *spi) +{ + struct loongson_spi *loongson_spi; + + loongson_spi = spi_controller_get_devdata(spi->controller); + if (spi->bits_per_word % 8) + return -EINVAL; + + if (spi_get_chipselect(spi, 0) >= spi->controller->num_chipselect) + return -EINVAL; + + loongson_spi->hz = 0; + loongson_spi_set_cs(spi, true); + + return 0; +} + +static int loongson_spi_write_read_8bit(struct spi_device *spi, const u8 **tx_buf, + u8 **rx_buf, unsigned int num) +{ + int ret; + struct loongson_spi *loongson_spi = spi_controller_get_devdata(spi->controller); + + if (tx_buf && *tx_buf) + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_FIFO_REG, *((*tx_buf)++)); + else + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_FIFO_REG, 0); + + ret = readb_poll_timeout(loongson_spi->base + LOONGSON_SPI_SPSR_REG, + loongson_spi->spsr, (loongson_spi->spsr & + LOONGSON_SPI_SPSR_RFEMPTY) != LOONGSON_SPI_SPSR_RFEMPTY, + 1, USEC_PER_MSEC); + + if (rx_buf && *rx_buf) + *(*rx_buf)++ = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_FIFO_REG); + else + loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_FIFO_REG); + + return ret; +} + +static int loongson_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) +{ + int ret; + unsigned int count; + const u8 *tx = xfer->tx_buf; + u8 *rx = xfer->rx_buf; + + count = xfer->len; + do { + ret = loongson_spi_write_read_8bit(spi, &tx, &rx, count); + if (ret) + break; + } while (--count); + + return ret; +} + +static int loongson_spi_prepare_message(struct spi_controller *ctlr, struct spi_message *m) +{ + struct loongson_spi *loongson_spi = spi_controller_get_devdata(ctlr); + + loongson_spi->para = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_PARA_REG); + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_PARA_REG, loongson_spi->para & + ~LOONGSON_SPI_PARA_MEM_EN); + + return 0; +} + +static int loongson_spi_transfer_one(struct spi_controller *ctrl, struct spi_device *spi, + struct spi_transfer *xfer) +{ + struct loongson_spi *loongson_spi = spi_controller_get_devdata(spi->controller); + + loongson_spi_update_state(loongson_spi, spi, xfer); + if (xfer->len) + return loongson_spi_write_read(spi, xfer); + + return 0; +} + +static int loongson_spi_unprepare_message(struct spi_controller *ctrl, struct spi_message *m) +{ + struct loongson_spi *loongson_spi = spi_controller_get_devdata(ctrl); + + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_PARA_REG, loongson_spi->para); + + return 0; +} + +static void loongson_spi_reginit(struct loongson_spi *loongson_spi_dev) +{ + unsigned char val; + + val = loongson_spi_read_reg(loongson_spi_dev, LOONGSON_SPI_SPCR_REG); + val &= ~LOONGSON_SPI_SPCR_SPE; + loongson_spi_write_reg(loongson_spi_dev, LOONGSON_SPI_SPCR_REG, val); + + loongson_spi_write_reg(loongson_spi_dev, LOONGSON_SPI_SPSR_REG, + (LOONGSON_SPI_SPSR_SPIF | LOONGSON_SPI_SPSR_WCOL)); + + val = loongson_spi_read_reg(loongson_spi_dev, LOONGSON_SPI_SPCR_REG); + val |= LOONGSON_SPI_SPCR_SPE; + loongson_spi_write_reg(loongson_spi_dev, LOONGSON_SPI_SPCR_REG, val); +} + +int loongson_spi_init_controller(struct device *dev, void __iomem *regs) +{ + struct spi_controller *controller; + struct loongson_spi *spi; + struct clk *clk; + + controller = devm_spi_alloc_host(dev, sizeof(struct loongson_spi)); + if (controller == NULL) + return -ENOMEM; + + controller->mode_bits = SPI_MODE_X_MASK | SPI_CS_HIGH; + controller->setup = loongson_spi_setup; + controller->prepare_message = loongson_spi_prepare_message; + controller->transfer_one = loongson_spi_transfer_one; + controller->unprepare_message = loongson_spi_unprepare_message; + controller->set_cs = loongson_spi_set_cs; + controller->num_chipselect = 4; + device_set_node(&controller->dev, dev_fwnode(dev)); + dev_set_drvdata(dev, controller); + + spi = spi_controller_get_devdata(controller); + spi->base = regs; + spi->controller = controller; + + clk = devm_clk_get_optional(dev, NULL); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), "unable to get clock\n"); + + spi->clk_rate = clk_get_rate(clk); + loongson_spi_reginit(spi); + + spi->mode = 0; + + return devm_spi_register_controller(dev, controller); +} +EXPORT_SYMBOL_NS_GPL(loongson_spi_init_controller, SPI_LOONGSON_CORE); + +static int __maybe_unused loongson_spi_suspend(struct device *dev) +{ + struct loongson_spi *loongson_spi; + struct spi_controller *controller; + + controller = dev_get_drvdata(dev); + spi_controller_suspend(controller); + + loongson_spi = spi_controller_get_devdata(controller); + + loongson_spi->spcr = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPCR_REG); + loongson_spi->sper = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPER_REG); + loongson_spi->spsr = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SPSR_REG); + loongson_spi->para = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_PARA_REG); + loongson_spi->sfcs = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_SFCS_REG); + loongson_spi->timi = loongson_spi_read_reg(loongson_spi, LOONGSON_SPI_TIMI_REG); + + return 0; +} + +static int __maybe_unused loongson_spi_resume(struct device *dev) +{ + struct loongson_spi *loongson_spi; + struct spi_controller *controller; + + controller = dev_get_drvdata(dev); + loongson_spi = spi_controller_get_devdata(controller); + + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPCR_REG, loongson_spi->spcr); + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPER_REG, loongson_spi->sper); + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SPSR_REG, loongson_spi->spsr); + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_PARA_REG, loongson_spi->para); + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_SFCS_REG, loongson_spi->sfcs); + loongson_spi_write_reg(loongson_spi, LOONGSON_SPI_TIMI_REG, loongson_spi->timi); + + spi_controller_resume(controller); + + return 0; +} + +const struct dev_pm_ops loongson_spi_dev_pm_ops = { + .suspend = loongson_spi_suspend, + .resume = loongson_spi_resume, +}; +EXPORT_SYMBOL_NS_GPL(loongson_spi_dev_pm_ops, SPI_LOONGSON_CORE); + +MODULE_DESCRIPTION("Loongson SPI core driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/spi/spi-loongson-pci.c b/drivers/spi/spi-loongson-pci.c new file mode 100644 index 000000000000..134cda0c13a5 --- /dev/null +++ b/drivers/spi/spi-loongson-pci.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0+ +// PCI interface driver for Loongson SPI Support +// Copyright (C) 2023 Loongson Technology Corporation Limited + +#include <linux/mod_devicetable.h> +#include <linux/pci.h> + +#include "spi-loongson.h" + +static int loongson_spi_pci_register(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + int ret; + void __iomem *reg_base; + struct device *dev = &pdev->dev; + int pci_bar = 0; + + ret = pcim_enable_device(pdev); + if (ret < 0) + return dev_err_probe(dev, ret, "cannot enable pci device\n"); + + ret = pcim_iomap_regions(pdev, BIT(pci_bar), pci_name(pdev)); + if (ret) + return dev_err_probe(dev, ret, "failed to request and remap memory\n"); + + reg_base = pcim_iomap_table(pdev)[pci_bar]; + + ret = loongson_spi_init_controller(dev, reg_base); + if (ret) + return dev_err_probe(dev, ret, "failed to initialize controller\n"); + + return 0; +} + +static struct pci_device_id loongson_spi_devices[] = { + { PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, 0x7a0b) }, + { PCI_DEVICE(PCI_VENDOR_ID_LOONGSON, 0x7a1b) }, + { } +}; +MODULE_DEVICE_TABLE(pci, loongson_spi_devices); + +static struct pci_driver loongson_spi_pci_driver = { + .name = "loongson-spi-pci", + .id_table = loongson_spi_devices, + .probe = loongson_spi_pci_register, + .driver = { + .bus = &pci_bus_type, + .pm = &loongson_spi_dev_pm_ops, + }, +}; +module_pci_driver(loongson_spi_pci_driver); + +MODULE_DESCRIPTION("Loongson spi pci driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(SPI_LOONGSON_CORE); diff --git a/drivers/spi/spi-loongson-plat.c b/drivers/spi/spi-loongson-plat.c new file mode 100644 index 000000000000..c066e5f5891e --- /dev/null +++ b/drivers/spi/spi-loongson-plat.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Platform driver for Loongson SPI Support +// Copyright (C) 2023 Loongson Technology Corporation Limited + +#include <linux/err.h> +#include <linux/mod_devicetable.h> +#include <linux/platform_device.h> + +#include "spi-loongson.h" + +static int loongson_spi_platform_probe(struct platform_device *pdev) +{ + int ret; + void __iomem *reg_base; + struct device *dev = &pdev->dev; + + reg_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(reg_base)) + return PTR_ERR(reg_base); + + ret = loongson_spi_init_controller(dev, reg_base); + if (ret) + return dev_err_probe(dev, ret, "failed to initialize controller\n"); + + return 0; +} + +static const struct of_device_id loongson_spi_id_table[] = { + { .compatible = "loongson,ls2k1000-spi" }, + { } +}; +MODULE_DEVICE_TABLE(of, loongson_spi_id_table); + +static struct platform_driver loongson_spi_plat_driver = { + .probe = loongson_spi_platform_probe, + .driver = { + .name = "loongson-spi", + .bus = &platform_bus_type, + .pm = &loongson_spi_dev_pm_ops, + .of_match_table = loongson_spi_id_table, + }, +}; +module_platform_driver(loongson_spi_plat_driver); + +MODULE_DESCRIPTION("Loongson spi platform driver"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(SPI_LOONGSON_CORE); diff --git a/drivers/spi/spi-loongson.h b/drivers/spi/spi-loongson.h new file mode 100644 index 000000000000..35f95b161842 --- /dev/null +++ b/drivers/spi/spi-loongson.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Header File for Loongson SPI Driver. */ +/* Copyright (C) 2023 Loongson Technology Corporation Limited */ + +#ifndef __LINUX_SPI_LOONGSON_H +#define __LINUX_SPI_LOONGSON_H + +#include <linux/bits.h> +#include <linux/pm.h> +#include <linux/types.h> + +#define LOONGSON_SPI_SPCR_REG 0x00 +#define LOONGSON_SPI_SPSR_REG 0x01 +#define LOONGSON_SPI_FIFO_REG 0x02 +#define LOONGSON_SPI_SPER_REG 0x03 +#define LOONGSON_SPI_PARA_REG 0x04 +#define LOONGSON_SPI_SFCS_REG 0x05 +#define LOONGSON_SPI_TIMI_REG 0x06 + +/* Bits definition for Loongson SPI register */ +#define LOONGSON_SPI_PARA_MEM_EN BIT(0) +#define LOONGSON_SPI_SPCR_CPHA BIT(2) +#define LOONGSON_SPI_SPCR_CPOL BIT(3) +#define LOONGSON_SPI_SPCR_SPE BIT(6) +#define LOONGSON_SPI_SPSR_RFEMPTY BIT(0) +#define LOONGSON_SPI_SPSR_WCOL BIT(6) +#define LOONGSON_SPI_SPSR_SPIF BIT(7) + +struct device; +struct spi_controller; + +struct loongson_spi { + struct spi_controller *controller; + void __iomem *base; + int cs_active; + unsigned int hz; + unsigned char spcr; + unsigned char sper; + unsigned char spsr; + unsigned char para; + unsigned char sfcs; + unsigned char timi; + unsigned int mode; + u64 clk_rate; +}; + +int loongson_spi_init_controller(struct device *dev, void __iomem *reg); +extern const struct dev_pm_ops loongson_spi_dev_pm_ops; +#endif /* __LINUX_SPI_LOONGSON_H */ diff --git a/drivers/spi/spi-loopback-test.c b/drivers/spi/spi-loopback-test.c index 675a73cf1579..bbf2015d8e5c 100644 --- a/drivers/spi/spi-loopback-test.c +++ b/drivers/spi/spi-loopback-test.c @@ -14,8 +14,8 @@ #include <linux/ktime.h> #include <linux/list.h> #include <linux/list_sort.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/printk.h> #include <linux/vmalloc.h> #include <linux/spi/spi.h> diff --git a/drivers/spi/spi-lp8841-rtc.c b/drivers/spi/spi-lp8841-rtc.c index 2d436541d6c2..b357461f1b8b 100644 --- a/drivers/spi/spi-lp8841-rtc.c +++ b/drivers/spi/spi-lp8841-rtc.c @@ -15,7 +15,6 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/spi/spi.h> #define DRIVER_NAME "spi_lp8841_rtc" @@ -75,14 +74,14 @@ bitbang_txrx_be_cpha0_lsb(struct spi_lp8841_rtc *data, for (; likely(bits); bits--) { /* setup LSB (to slave) on leading edge */ - if ((flags & SPI_MASTER_NO_TX) == 0) + if ((flags & SPI_CONTROLLER_NO_TX) == 0) setmosi(data, (word & 1)); usleep_range(usecs, usecs + 1); /* T(setup) */ /* sample LSB (from slave) on trailing edge */ word >>= 1; - if ((flags & SPI_MASTER_NO_RX) == 0) + if ((flags & SPI_CONTROLLER_NO_RX) == 0) word |= (getmiso(data) << 31); setsck(data, !cpol); @@ -113,7 +112,7 @@ spi_lp8841_rtc_transfer_one(struct spi_master *master, while (likely(count > 0)) { word = *tx++; bitbang_txrx_be_cpha0_lsb(data, 1, 0, - SPI_MASTER_NO_RX, word, 8); + SPI_CONTROLLER_NO_RX, word, 8); count--; } } else if (rx) { @@ -121,7 +120,7 @@ spi_lp8841_rtc_transfer_one(struct spi_master *master, writeb(data->state, data->iomem); while (likely(count > 0)) { word = bitbang_txrx_be_cpha0_lsb(data, 1, 0, - SPI_MASTER_NO_TX, word, 8); + SPI_CONTROLLER_NO_TX, word, 8); *rx++ = word; count--; } @@ -191,7 +190,7 @@ spi_lp8841_rtc_probe(struct platform_device *pdev) return -ENOMEM; platform_set_drvdata(pdev, master); - master->flags = SPI_MASTER_HALF_DUPLEX; + master->flags = SPI_CONTROLLER_HALF_DUPLEX; master->mode_bits = SPI_CS_HIGH | SPI_3WIRE | SPI_LSB_FIRST; master->bus_num = pdev->id; diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c index 141562c882f1..43d134f4b42b 100644 --- a/drivers/spi/spi-meson-spicc.c +++ b/drivers/spi/spi-meson-spicc.c @@ -15,7 +15,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> #include <linux/types.h> @@ -864,7 +863,7 @@ static int meson_spicc_probe(struct platform_device *pdev) SPI_BPW_MASK(24) | SPI_BPW_MASK(16) | SPI_BPW_MASK(8); - master->flags = (SPI_MASTER_MUST_RX | SPI_MASTER_MUST_TX); + master->flags = (SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX); master->min_speed_hz = spicc->data->min_speed_hz; master->max_speed_hz = spicc->data->max_speed_hz; master->setup = meson_spicc_setup; diff --git a/drivers/spi/spi-microchip-core.c b/drivers/spi/spi-microchip-core.c index b59e8a0c5b97..b451cd4860ec 100644 --- a/drivers/spi/spi-microchip-core.c +++ b/drivers/spi/spi-microchip-core.c @@ -530,10 +530,8 @@ static int mchp_corespi_probe(struct platform_device *pdev) return PTR_ERR(spi->regs); spi->irq = platform_get_irq(pdev, 0); - if (spi->irq <= 0) - return dev_err_probe(&pdev->dev, -ENXIO, - "invalid IRQ %d for SPI controller\n", - spi->irq); + if (spi->irq < 0) + return spi->irq; ret = devm_request_irq(&pdev->dev, spi->irq, mchp_corespi_interrupt, IRQF_SHARED, dev_name(&pdev->dev), master); diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index 99aeef28a477..5cecca1bef02 100644 --- a/drivers/spi/spi-mpc512x-psc.c +++ b/drivers/spi/spi-mpc512x-psc.c @@ -53,7 +53,7 @@ struct mpc512x_psc_spi { int type; void __iomem *psc; struct mpc512x_psc_fifo __iomem *fifo; - unsigned int irq; + int irq; u8 bits_per_word; u32 mclk_rate; diff --git a/drivers/spi/spi-mpc52xx-psc.c b/drivers/spi/spi-mpc52xx-psc.c index 9a1a080fb688..795c08594a4d 100644 --- a/drivers/spi/spi-mpc52xx-psc.c +++ b/drivers/spi/spi-mpc52xx-psc.c @@ -29,7 +29,7 @@ struct mpc52xx_psc_spi { /* driver internal data */ struct mpc52xx_psc __iomem *psc; struct mpc52xx_psc_fifo __iomem *fifo; - unsigned int irq; + int irq; u8 bits_per_word; struct completion done; diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 39272ad6641b..0757985947dd 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -1142,7 +1142,7 @@ static int mtk_spi_probe(struct platform_device *pdev) master->mode_bits |= SPI_CS_HIGH; if (mdata->dev_comp->must_tx) - master->flags = SPI_MASTER_MUST_TX; + master->flags = SPI_CONTROLLER_MUST_TX; if (mdata->dev_comp->ipm_design) master->mode_bits |= SPI_LOOP | SPI_RX_DUAL | SPI_TX_DUAL | SPI_RX_QUAD | SPI_TX_QUAD; diff --git a/drivers/spi/spi-mt7621.c b/drivers/spi/spi-mt7621.c index 3e9d396b33bd..91600e5c22e4 100644 --- a/drivers/spi/spi-mt7621.c +++ b/drivers/spi/spi-mt7621.c @@ -14,7 +14,9 @@ #include <linux/delay.h> #include <linux/io.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/of_device.h> +#include <linux/platform_device.h> #include <linux/reset.h> #include <linux/spi/spi.h> diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c index baa7a5353987..cf4ee8b19e42 100644 --- a/drivers/spi/spi-mtk-nor.c +++ b/drivers/spi/spi-mtk-nor.c @@ -13,7 +13,8 @@ #include <linux/iopoll.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/spi/spi.h> #include <linux/spi/spi-mem.h> diff --git a/drivers/spi/spi-mtk-snfi.c b/drivers/spi/spi-mtk-snfi.c index bed8317cd205..4433a8a9299f 100644 --- a/drivers/spi/spi-mtk-snfi.c +++ b/drivers/spi/spi-mtk-snfi.c @@ -76,7 +76,8 @@ #include <linux/interrupt.h> #include <linux/dma-mapping.h> #include <linux/iopoll.h> -#include <linux/of_platform.h> +#include <linux/of.h> +#include <linux/platform_device.h> #include <linux/mtd/nand-ecc-mtk.h> #include <linux/spi/spi.h> #include <linux/spi/spi-mem.h> diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index 963a53dd680b..cd0e7ae07162 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -572,7 +572,7 @@ static int mxs_spi_probe(struct platform_device *pdev) master->mode_bits = SPI_CPOL | SPI_CPHA; master->num_chipselect = 3; master->dev.of_node = np; - master->flags = SPI_MASTER_HALF_DUPLEX; + master->flags = SPI_CONTROLLER_HALF_DUPLEX; master->auto_runtime_pm = true; spi = spi_master_get_devdata(master); diff --git a/drivers/spi/spi-npcm-fiu.c b/drivers/spi/spi-npcm-fiu.c index eb353561509a..0ca21ff0e9cc 100644 --- a/drivers/spi/spi-npcm-fiu.c +++ b/drivers/spi/spi-npcm-fiu.c @@ -12,7 +12,7 @@ #include <linux/io.h> #include <linux/vmalloc.h> #include <linux/regmap.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/spi/spi-mem.h> #include <linux/mfd/syscon.h> @@ -287,7 +287,7 @@ static ssize_t npcm_fiu_direct_read(struct spi_mem_dirmap_desc *desc, u64 offs, size_t len, void *buf) { struct npcm_fiu_spi *fiu = - spi_controller_get_devdata(desc->mem->spi->master); + spi_controller_get_devdata(desc->mem->spi->controller); struct npcm_fiu_chip *chip = &fiu->chip[spi_get_chipselect(desc->mem->spi, 0)]; void __iomem *src = (void __iomem *)(chip->flash_region_mapped_ptr + offs); @@ -314,7 +314,7 @@ static ssize_t npcm_fiu_direct_write(struct spi_mem_dirmap_desc *desc, u64 offs, size_t len, const void *buf) { struct npcm_fiu_spi *fiu = - spi_controller_get_devdata(desc->mem->spi->master); + spi_controller_get_devdata(desc->mem->spi->controller); struct npcm_fiu_chip *chip = &fiu->chip[spi_get_chipselect(desc->mem->spi, 0)]; void __iomem *dst = (void __iomem *)(chip->flash_region_mapped_ptr + offs); @@ -335,7 +335,7 @@ static int npcm_fiu_uma_read(struct spi_mem *mem, bool is_address_size, u8 *data, u32 data_size) { struct npcm_fiu_spi *fiu = - spi_controller_get_devdata(mem->spi->master); + spi_controller_get_devdata(mem->spi->controller); u32 uma_cfg = BIT(10); u32 data_reg[4]; int ret; @@ -390,7 +390,7 @@ static int npcm_fiu_uma_write(struct spi_mem *mem, bool is_address_size, u8 *data, u32 data_size) { struct npcm_fiu_spi *fiu = - spi_controller_get_devdata(mem->spi->master); + spi_controller_get_devdata(mem->spi->controller); u32 uma_cfg = BIT(10); u32 data_reg[4] = {0}; u32 val; @@ -439,7 +439,7 @@ static int npcm_fiu_manualwrite(struct spi_mem *mem, const struct spi_mem_op *op) { struct npcm_fiu_spi *fiu = - spi_controller_get_devdata(mem->spi->master); + spi_controller_get_devdata(mem->spi->controller); u8 *data = (u8 *)op->data.buf.out; u32 num_data_chunks; u32 remain_data; @@ -544,7 +544,7 @@ static void npcm_fiux_set_direct_rd(struct npcm_fiu_spi *fiu) static int npcm_fiu_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) { struct npcm_fiu_spi *fiu = - spi_controller_get_devdata(mem->spi->master); + spi_controller_get_devdata(mem->spi->controller); struct npcm_fiu_chip *chip = &fiu->chip[spi_get_chipselect(mem->spi, 0)]; int ret = 0; u8 *buf; @@ -604,7 +604,7 @@ static int npcm_fiu_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) static int npcm_fiu_dirmap_create(struct spi_mem_dirmap_desc *desc) { struct npcm_fiu_spi *fiu = - spi_controller_get_devdata(desc->mem->spi->master); + spi_controller_get_devdata(desc->mem->spi->controller); struct npcm_fiu_chip *chip = &fiu->chip[spi_get_chipselect(desc->mem->spi, 0)]; struct regmap *gcr_regmap; @@ -665,7 +665,7 @@ static int npcm_fiu_dirmap_create(struct spi_mem_dirmap_desc *desc) static int npcm_fiu_setup(struct spi_device *spi) { - struct spi_controller *ctrl = spi->master; + struct spi_controller *ctrl = spi->controller; struct npcm_fiu_spi *fiu = spi_controller_get_devdata(ctrl); struct npcm_fiu_chip *chip; @@ -701,7 +701,7 @@ static int npcm_fiu_probe(struct platform_device *pdev) void __iomem *regbase; int id, ret; - ctrl = devm_spi_alloc_master(dev, sizeof(*fiu)); + ctrl = devm_spi_alloc_host(dev, sizeof(*fiu)); if (!ctrl) return -ENOMEM; @@ -755,7 +755,7 @@ static int npcm_fiu_probe(struct platform_device *pdev) ctrl->num_chipselect = fiu->info->max_cs; ctrl->dev.of_node = dev->of_node; - ret = devm_spi_register_master(dev, ctrl); + ret = devm_spi_register_controller(dev, ctrl); if (ret) clk_disable_unprepare(fiu->clk); diff --git a/drivers/spi/spi-nxp-fspi.c b/drivers/spi/spi-nxp-fspi.c index 544017655787..45a4acc95661 100644 --- a/drivers/spi/spi-nxp-fspi.c +++ b/drivers/spi/spi-nxp-fspi.c @@ -47,7 +47,6 @@ #include <linux/module.h> #include <linux/mutex.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_qos.h> #include <linux/regmap.h> @@ -1157,12 +1156,10 @@ static int nxp_fspi_probe(struct platform_device *pdev) /* find the resources - configuration register address space */ if (is_acpi_node(dev_fwnode(f->dev))) - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + f->iobase = devm_platform_ioremap_resource(pdev, 0); else - res = platform_get_resource_byname(pdev, - IORESOURCE_MEM, "fspi_base"); + f->iobase = devm_platform_ioremap_resource_byname(pdev, "fspi_base"); - f->iobase = devm_ioremap_resource(dev, res); if (IS_ERR(f->iobase)) { ret = PTR_ERR(f->iobase); goto err_put_ctrl; diff --git a/drivers/spi/spi-omap-uwire.c b/drivers/spi/spi-omap-uwire.c index 902d2e0c1f2f..f89aa9e52c23 100644 --- a/drivers/spi/spi-omap-uwire.c +++ b/drivers/spi/spi-omap-uwire.c @@ -486,7 +486,7 @@ static int uwire_probe(struct platform_device *pdev) /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16); - master->flags = SPI_MASTER_HALF_DUPLEX; + master->flags = SPI_CONTROLLER_HALF_DUPLEX; master->bus_num = 2; /* "official" */ master->num_chipselect = 4; diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 8331e247bf5c..e5cd82eb9e54 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1508,10 +1508,8 @@ static int omap2_mcspi_probe(struct platform_device *pdev) } status = platform_get_irq(pdev, 0); - if (status < 0) { - dev_err_probe(&pdev->dev, status, "no irq resource found\n"); + if (status < 0) goto free_master; - } init_completion(&mcspi->txdone); status = devm_request_irq(&pdev->dev, status, omap2_mcspi_irq_handler, 0, pdev->name, diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index ad9e83e34297..1f10f5c8e34d 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -16,7 +16,6 @@ #include <linux/pm_runtime.h> #include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_device.h> #include <linux/clk.h> #include <linux/sizes.h> #include <asm/unaligned.h> @@ -91,7 +90,7 @@ struct orion_child_options { }; struct orion_spi { - struct spi_master *master; + struct spi_controller *host; void __iomem *base; struct clk *clk; struct clk *axi_clk; @@ -142,7 +141,7 @@ static int orion_spi_baudrate_set(struct spi_device *spi, unsigned int speed) struct orion_spi *orion_spi; const struct orion_spi_dev *devdata; - orion_spi = spi_master_get_devdata(spi->master); + orion_spi = spi_controller_get_devdata(spi->controller); devdata = orion_spi->devdata; tclk_hz = clk_get_rate(orion_spi->clk); @@ -236,7 +235,7 @@ orion_spi_mode_set(struct spi_device *spi) u32 reg; struct orion_spi *orion_spi; - orion_spi = spi_master_get_devdata(spi->master); + orion_spi = spi_controller_get_devdata(spi->controller); reg = readl(spi_reg(orion_spi, ORION_SPI_IF_CONFIG_REG)); reg &= ~ORION_SPI_MODE_MASK; @@ -258,7 +257,7 @@ orion_spi_50mhz_ac_timing_erratum(struct spi_device *spi, unsigned int speed) u32 reg; struct orion_spi *orion_spi; - orion_spi = spi_master_get_devdata(spi->master); + orion_spi = spi_controller_get_devdata(spi->controller); /* * Erratum description: (Erratum NO. FE-9144572) The device @@ -298,7 +297,7 @@ orion_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) unsigned int bits_per_word = spi->bits_per_word; int rc; - orion_spi = spi_master_get_devdata(spi->master); + orion_spi = spi_controller_get_devdata(spi->controller); if ((t != NULL) && t->speed_hz) speed = t->speed_hz; @@ -331,7 +330,7 @@ static void orion_spi_set_cs(struct spi_device *spi, bool enable) void __iomem *ctrl_reg; u32 val; - orion_spi = spi_master_get_devdata(spi->master); + orion_spi = spi_controller_get_devdata(spi->controller); ctrl_reg = spi_reg(orion_spi, ORION_SPI_IF_CTRL_REG); val = readl(ctrl_reg); @@ -389,7 +388,7 @@ orion_spi_write_read_8bit(struct spi_device *spi, cs_single_byte = spi->mode & SPI_CS_WORD; - orion_spi = spi_master_get_devdata(spi->master); + orion_spi = spi_controller_get_devdata(spi->controller); if (cs_single_byte) orion_spi_set_cs(spi, 0); @@ -440,7 +439,7 @@ orion_spi_write_read_16bit(struct spi_device *spi, return -1; } - orion_spi = spi_master_get_devdata(spi->master); + orion_spi = spi_controller_get_devdata(spi->controller); tx_reg = spi_reg(orion_spi, ORION_SPI_DATA_OUT_REG); rx_reg = spi_reg(orion_spi, ORION_SPI_DATA_IN_REG); int_reg = spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG); @@ -476,7 +475,7 @@ orion_spi_write_read(struct spi_device *spi, struct spi_transfer *xfer) word_len = spi->bits_per_word; count = xfer->len; - orion_spi = spi_master_get_devdata(spi->master); + orion_spi = spi_controller_get_devdata(spi->controller); /* * Use SPI direct write mode if base address is available @@ -529,7 +528,7 @@ out: return xfer->len - count; } -static int orion_spi_transfer_one(struct spi_master *master, +static int orion_spi_transfer_one(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *t) { @@ -549,7 +548,7 @@ static int orion_spi_setup(struct spi_device *spi) { int ret; #ifdef CONFIG_PM - struct orion_spi *orion_spi = spi_master_get_devdata(spi->master); + struct orion_spi *orion_spi = spi_controller_get_devdata(spi->controller); struct device *dev = orion_spi->dev; orion_spi_runtime_resume(dev); @@ -645,44 +644,44 @@ MODULE_DEVICE_TABLE(of, orion_spi_of_match_table); static int orion_spi_probe(struct platform_device *pdev) { const struct orion_spi_dev *devdata; - struct spi_master *master; + struct spi_controller *host; struct orion_spi *spi; struct resource *r; unsigned long tclk_hz; int status = 0; struct device_node *np; - master = spi_alloc_master(&pdev->dev, sizeof(*spi)); - if (master == NULL) { - dev_dbg(&pdev->dev, "master allocation failed\n"); + host = spi_alloc_host(&pdev->dev, sizeof(*spi)); + if (host == NULL) { + dev_dbg(&pdev->dev, "host allocation failed\n"); return -ENOMEM; } if (pdev->id != -1) - master->bus_num = pdev->id; + host->bus_num = pdev->id; if (pdev->dev.of_node) { u32 cell_index; if (!of_property_read_u32(pdev->dev.of_node, "cell-index", &cell_index)) - master->bus_num = cell_index; + host->bus_num = cell_index; } /* we support all 4 SPI modes and LSB first option */ - master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST | SPI_CS_WORD; - master->set_cs = orion_spi_set_cs; - master->transfer_one = orion_spi_transfer_one; - master->num_chipselect = ORION_NUM_CHIPSELECTS; - master->setup = orion_spi_setup; - master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); - master->auto_runtime_pm = true; - master->use_gpio_descriptors = true; - master->flags = SPI_MASTER_GPIO_SS; - - platform_set_drvdata(pdev, master); - - spi = spi_master_get_devdata(master); - spi->master = master; + host->mode_bits = SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST | SPI_CS_WORD; + host->set_cs = orion_spi_set_cs; + host->transfer_one = orion_spi_transfer_one; + host->num_chipselect = ORION_NUM_CHIPSELECTS; + host->setup = orion_spi_setup; + host->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16); + host->auto_runtime_pm = true; + host->use_gpio_descriptors = true; + host->flags = SPI_CONTROLLER_GPIO_SS; + + platform_set_drvdata(pdev, host); + + spi = spi_controller_get_devdata(host); + spi->host = host; spi->dev = &pdev->dev; devdata = device_get_match_data(&pdev->dev); @@ -719,14 +718,14 @@ static int orion_spi_probe(struct platform_device *pdev) */ if (of_device_is_compatible(pdev->dev.of_node, "marvell,armada-370-spi")) - master->max_speed_hz = min(devdata->max_hz, + host->max_speed_hz = min(devdata->max_hz, DIV_ROUND_UP(tclk_hz, devdata->min_divisor)); else if (devdata->min_divisor) - master->max_speed_hz = + host->max_speed_hz = DIV_ROUND_UP(tclk_hz, devdata->min_divisor); else - master->max_speed_hz = devdata->max_hz; - master->min_speed_hz = DIV_ROUND_UP(tclk_hz, devdata->max_divisor); + host->max_speed_hz = devdata->max_hz; + host->min_speed_hz = DIV_ROUND_UP(tclk_hz, devdata->max_divisor); spi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r); if (IS_ERR(spi->base)) { @@ -785,8 +784,8 @@ static int orion_spi_probe(struct platform_device *pdev) if (status < 0) goto out_rel_pm; - master->dev.of_node = pdev->dev.of_node; - status = spi_register_master(master); + host->dev.of_node = pdev->dev.of_node; + status = spi_register_controller(host); if (status < 0) goto out_rel_pm; @@ -799,21 +798,21 @@ out_rel_axi_clk: out_rel_clk: clk_disable_unprepare(spi->clk); out: - spi_master_put(master); + spi_controller_put(host); return status; } static void orion_spi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct orion_spi *spi = spi_master_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(pdev); + struct orion_spi *spi = spi_controller_get_devdata(host); pm_runtime_get_sync(&pdev->dev); clk_disable_unprepare(spi->axi_clk); clk_disable_unprepare(spi->clk); - spi_unregister_master(master); + spi_unregister_controller(host); pm_runtime_disable(&pdev->dev); } @@ -822,8 +821,8 @@ MODULE_ALIAS("platform:" DRIVER_NAME); #ifdef CONFIG_PM static int orion_spi_runtime_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct orion_spi *spi = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct orion_spi *spi = spi_controller_get_devdata(host); clk_disable_unprepare(spi->axi_clk); clk_disable_unprepare(spi->clk); @@ -832,8 +831,8 @@ static int orion_spi_runtime_suspend(struct device *dev) static int orion_spi_runtime_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct orion_spi *spi = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct orion_spi *spi = spi_controller_get_devdata(host); if (!IS_ERR(spi->axi_clk)) clk_prepare_enable(spi->axi_clk); diff --git a/drivers/spi/spi-pci1xxxx.c b/drivers/spi/spi-pci1xxxx.c index 4445d82409d6..3638e974f5d4 100644 --- a/drivers/spi/spi-pci1xxxx.c +++ b/drivers/spi/spi-pci1xxxx.c @@ -65,7 +65,7 @@ struct pci1xxxx_spi_internal { bool spi_xfer_in_progress; int irq; struct completion spi_xfer_done; - struct spi_master *spi_host; + struct spi_controller *spi_host; struct pci1xxxx_spi *parent; struct { unsigned int dev_sel : 3; @@ -250,7 +250,7 @@ static int pci1xxxx_spi_probe(struct pci_dev *pdev, const struct pci_device_id * struct pci1xxxx_spi_internal *spi_sub_ptr; struct device *dev = &pdev->dev; struct pci1xxxx_spi *spi_bus; - struct spi_master *spi_host; + struct spi_controller *spi_host; u32 regval; int ret; @@ -276,7 +276,7 @@ static int pci1xxxx_spi_probe(struct pci_dev *pdev, const struct pci_device_id * sizeof(struct pci1xxxx_spi_internal), GFP_KERNEL); spi_sub_ptr = spi_bus->spi_int[iter]; - spi_sub_ptr->spi_host = devm_spi_alloc_master(dev, sizeof(struct spi_master)); + spi_sub_ptr->spi_host = devm_spi_alloc_host(dev, sizeof(struct spi_controller)); if (!spi_sub_ptr->spi_host) return -ENOMEM; @@ -365,9 +365,9 @@ static int pci1xxxx_spi_probe(struct pci_dev *pdev, const struct pci_device_id * spi_host->bits_per_word_mask = SPI_BPW_MASK(8); spi_host->max_speed_hz = PCI1XXXX_SPI_MAX_CLOCK_HZ; spi_host->min_speed_hz = PCI1XXXX_SPI_MIN_CLOCK_HZ; - spi_host->flags = SPI_MASTER_MUST_TX; - spi_master_set_devdata(spi_host, spi_sub_ptr); - ret = devm_spi_register_master(dev, spi_host); + spi_host->flags = SPI_CONTROLLER_MUST_TX; + spi_controller_set_devdata(spi_host, spi_sub_ptr); + ret = devm_spi_register_controller(dev, spi_host); if (ret) goto error; } @@ -415,7 +415,7 @@ static int pci1xxxx_spi_resume(struct device *dev) for (iter = 0; iter < spi_ptr->total_hw_instances; iter++) { spi_sub_ptr = spi_ptr->spi_int[iter]; - spi_master_resume(spi_sub_ptr->spi_host); + spi_controller_resume(spi_sub_ptr->spi_host); writel(regval, spi_ptr->reg_base + SPI_MST_EVENT_MASK_REG_OFFSET(iter)); @@ -441,7 +441,7 @@ static int pci1xxxx_spi_suspend(struct device *dev) /* Store existing config before suspend */ store_restore_config(spi_ptr, spi_sub_ptr, iter, 1); - spi_master_suspend(spi_sub_ptr->spi_host); + spi_controller_suspend(spi_sub_ptr->spi_host); writel(reg1, spi_ptr->reg_base + SPI_MST_EVENT_MASK_REG_OFFSET(iter)); } diff --git a/drivers/spi/spi-pic32-sqi.c b/drivers/spi/spi-pic32-sqi.c index 51dfb49523f3..883354d0ff52 100644 --- a/drivers/spi/spi-pic32-sqi.c +++ b/drivers/spi/spi-pic32-sqi.c @@ -139,7 +139,7 @@ struct pic32_sqi { void __iomem *regs; struct clk *sys_clk; struct clk *base_clk; /* drives spi clock */ - struct spi_master *master; + struct spi_controller *host; int irq; struct completion xfer_done; struct ring_desc *ring; @@ -316,9 +316,9 @@ static int pic32_sqi_one_transfer(struct pic32_sqi *sqi, return 0; } -static int pic32_sqi_prepare_hardware(struct spi_master *master) +static int pic32_sqi_prepare_hardware(struct spi_controller *host) { - struct pic32_sqi *sqi = spi_master_get_devdata(master); + struct pic32_sqi *sqi = spi_controller_get_devdata(host); /* enable spi interface */ pic32_setbits(sqi->regs + PESQI_CONF_REG, PESQI_EN); @@ -328,7 +328,7 @@ static int pic32_sqi_prepare_hardware(struct spi_master *master) return 0; } -static bool pic32_sqi_can_dma(struct spi_master *master, +static bool pic32_sqi_can_dma(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *x) { @@ -336,7 +336,7 @@ static bool pic32_sqi_can_dma(struct spi_master *master, return true; } -static int pic32_sqi_one_message(struct spi_master *master, +static int pic32_sqi_one_message(struct spi_controller *host, struct spi_message *msg) { struct spi_device *spi = msg->spi; @@ -347,7 +347,7 @@ static int pic32_sqi_one_message(struct spi_master *master, unsigned long timeout; u32 val; - sqi = spi_master_get_devdata(master); + sqi = spi_controller_get_devdata(host); reinit_completion(&sqi->xfer_done); msg->actual_length = 0; @@ -412,7 +412,7 @@ static int pic32_sqi_one_message(struct spi_master *master, /* wait for xfer completion */ timeout = wait_for_completion_timeout(&sqi->xfer_done, 5 * HZ); if (timeout == 0) { - dev_err(&sqi->master->dev, "wait timedout/interrupted\n"); + dev_err(&sqi->host->dev, "wait timedout/interrupted\n"); ret = -ETIMEDOUT; msg->status = ret; } else { @@ -434,14 +434,14 @@ xfer_out: /* release ring descr */ ring_desc_put(sqi, rdesc); } - spi_finalize_current_message(spi->master); + spi_finalize_current_message(spi->controller); return ret; } -static int pic32_sqi_unprepare_hardware(struct spi_master *master) +static int pic32_sqi_unprepare_hardware(struct spi_controller *host) { - struct pic32_sqi *sqi = spi_master_get_devdata(master); + struct pic32_sqi *sqi = spi_controller_get_devdata(host); /* disable clk */ pic32_clrbits(sqi->regs + PESQI_CLK_CTRL_REG, PESQI_CLK_EN); @@ -458,18 +458,18 @@ static int ring_desc_ring_alloc(struct pic32_sqi *sqi) int i; /* allocate coherent DMAable memory for hardware buffer descriptors. */ - sqi->bd = dma_alloc_coherent(&sqi->master->dev, + sqi->bd = dma_alloc_coherent(&sqi->host->dev, sizeof(*bd) * PESQI_BD_COUNT, &sqi->bd_dma, GFP_KERNEL); if (!sqi->bd) { - dev_err(&sqi->master->dev, "failed allocating dma buffer\n"); + dev_err(&sqi->host->dev, "failed allocating dma buffer\n"); return -ENOMEM; } /* allocate software ring descriptors */ sqi->ring = kcalloc(PESQI_BD_COUNT, sizeof(*rdesc), GFP_KERNEL); if (!sqi->ring) { - dma_free_coherent(&sqi->master->dev, + dma_free_coherent(&sqi->host->dev, sizeof(*bd) * PESQI_BD_COUNT, sqi->bd, sqi->bd_dma); return -ENOMEM; @@ -498,7 +498,7 @@ static int ring_desc_ring_alloc(struct pic32_sqi *sqi) static void ring_desc_ring_free(struct pic32_sqi *sqi) { - dma_free_coherent(&sqi->master->dev, + dma_free_coherent(&sqi->host->dev, sizeof(struct buf_desc) * PESQI_BD_COUNT, sqi->bd, sqi->bd_dma); kfree(sqi->ring); @@ -568,28 +568,28 @@ static void pic32_sqi_hw_init(struct pic32_sqi *sqi) static int pic32_sqi_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *host; struct pic32_sqi *sqi; int ret; - master = spi_alloc_master(&pdev->dev, sizeof(*sqi)); - if (!master) + host = spi_alloc_host(&pdev->dev, sizeof(*sqi)); + if (!host) return -ENOMEM; - sqi = spi_master_get_devdata(master); - sqi->master = master; + sqi = spi_controller_get_devdata(host); + sqi->host = host; sqi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sqi->regs)) { ret = PTR_ERR(sqi->regs); - goto err_free_master; + goto err_free_host; } /* irq */ sqi->irq = platform_get_irq(pdev, 0); if (sqi->irq < 0) { ret = sqi->irq; - goto err_free_master; + goto err_free_host; } /* clocks */ @@ -597,27 +597,27 @@ static int pic32_sqi_probe(struct platform_device *pdev) if (IS_ERR(sqi->sys_clk)) { ret = PTR_ERR(sqi->sys_clk); dev_err(&pdev->dev, "no sys_clk ?\n"); - goto err_free_master; + goto err_free_host; } sqi->base_clk = devm_clk_get(&pdev->dev, "spi_ck"); if (IS_ERR(sqi->base_clk)) { ret = PTR_ERR(sqi->base_clk); dev_err(&pdev->dev, "no base clk ?\n"); - goto err_free_master; + goto err_free_host; } ret = clk_prepare_enable(sqi->sys_clk); if (ret) { dev_err(&pdev->dev, "sys clk enable failed\n"); - goto err_free_master; + goto err_free_host; } ret = clk_prepare_enable(sqi->base_clk); if (ret) { dev_err(&pdev->dev, "base clk enable failed\n"); clk_disable_unprepare(sqi->sys_clk); - goto err_free_master; + goto err_free_host; } init_completion(&sqi->xfer_done); @@ -640,24 +640,24 @@ static int pic32_sqi_probe(struct platform_device *pdev) goto err_free_ring; } - /* register master */ - master->num_chipselect = 2; - master->max_speed_hz = clk_get_rate(sqi->base_clk); - master->dma_alignment = 32; - master->max_dma_len = PESQI_BD_BUF_LEN_MAX; - master->dev.of_node = pdev->dev.of_node; - master->mode_bits = SPI_MODE_3 | SPI_MODE_0 | SPI_TX_DUAL | + /* register host */ + host->num_chipselect = 2; + host->max_speed_hz = clk_get_rate(sqi->base_clk); + host->dma_alignment = 32; + host->max_dma_len = PESQI_BD_BUF_LEN_MAX; + host->dev.of_node = pdev->dev.of_node; + host->mode_bits = SPI_MODE_3 | SPI_MODE_0 | SPI_TX_DUAL | SPI_RX_DUAL | SPI_TX_QUAD | SPI_RX_QUAD; - master->flags = SPI_MASTER_HALF_DUPLEX; - master->can_dma = pic32_sqi_can_dma; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32); - master->transfer_one_message = pic32_sqi_one_message; - master->prepare_transfer_hardware = pic32_sqi_prepare_hardware; - master->unprepare_transfer_hardware = pic32_sqi_unprepare_hardware; - - ret = devm_spi_register_master(&pdev->dev, master); + host->flags = SPI_CONTROLLER_HALF_DUPLEX; + host->can_dma = pic32_sqi_can_dma; + host->bits_per_word_mask = SPI_BPW_RANGE_MASK(8, 32); + host->transfer_one_message = pic32_sqi_one_message; + host->prepare_transfer_hardware = pic32_sqi_prepare_hardware; + host->unprepare_transfer_hardware = pic32_sqi_unprepare_hardware; + + ret = devm_spi_register_controller(&pdev->dev, host); if (ret) { - dev_err(&master->dev, "failed registering spi master\n"); + dev_err(&host->dev, "failed registering spi host\n"); free_irq(sqi->irq, sqi); goto err_free_ring; } @@ -673,8 +673,8 @@ err_disable_clk: clk_disable_unprepare(sqi->base_clk); clk_disable_unprepare(sqi->sys_clk); -err_free_master: - spi_master_put(master); +err_free_host: + spi_controller_put(host); return ret; } diff --git a/drivers/spi/spi-pic32.c b/drivers/spi/spi-pic32.c index f2af5e653f3d..52b788dac10a 100644 --- a/drivers/spi/spi-pic32.c +++ b/drivers/spi/spi-pic32.c @@ -100,7 +100,7 @@ struct pic32_spi { int tx_irq; u32 fifo_n_byte; /* FIFO depth in bytes */ struct clk *clk; - struct spi_master *master; + struct spi_controller *host; /* Current controller setting */ u32 speed_hz; /* spi-clk rate */ u32 mode; @@ -224,9 +224,9 @@ static void pic32_err_stop(struct pic32_spi *pic32s, const char *msg) disable_irq_nosync(pic32s->tx_irq); /* Show err message and abort xfer with err */ - dev_err(&pic32s->master->dev, "%s\n", msg); - if (pic32s->master->cur_msg) - pic32s->master->cur_msg->status = -EIO; + dev_err(&pic32s->host->dev, "%s\n", msg); + if (pic32s->host->cur_msg) + pic32s->host->cur_msg->status = -EIO; complete(&pic32s->xfer_done); } @@ -250,7 +250,7 @@ static irqreturn_t pic32_spi_fault_irq(int irq, void *dev_id) return IRQ_HANDLED; } - if (!pic32s->master->cur_msg) { + if (!pic32s->host->cur_msg) { pic32_err_stop(pic32s, "err_irq: no mesg"); return IRQ_NONE; } @@ -300,16 +300,16 @@ static void pic32_spi_dma_rx_notify(void *data) static int pic32_spi_dma_transfer(struct pic32_spi *pic32s, struct spi_transfer *xfer) { - struct spi_master *master = pic32s->master; + struct spi_controller *host = pic32s->host; struct dma_async_tx_descriptor *desc_rx; struct dma_async_tx_descriptor *desc_tx; dma_cookie_t cookie; int ret; - if (!master->dma_rx || !master->dma_tx) + if (!host->dma_rx || !host->dma_tx) return -ENODEV; - desc_rx = dmaengine_prep_slave_sg(master->dma_rx, + desc_rx = dmaengine_prep_slave_sg(host->dma_rx, xfer->rx_sg.sgl, xfer->rx_sg.nents, DMA_DEV_TO_MEM, @@ -319,7 +319,7 @@ static int pic32_spi_dma_transfer(struct pic32_spi *pic32s, goto err_dma; } - desc_tx = dmaengine_prep_slave_sg(master->dma_tx, + desc_tx = dmaengine_prep_slave_sg(host->dma_tx, xfer->tx_sg.sgl, xfer->tx_sg.nents, DMA_MEM_TO_DEV, @@ -343,13 +343,13 @@ static int pic32_spi_dma_transfer(struct pic32_spi *pic32s, if (ret) goto err_dma_tx; - dma_async_issue_pending(master->dma_rx); - dma_async_issue_pending(master->dma_tx); + dma_async_issue_pending(host->dma_rx); + dma_async_issue_pending(host->dma_tx); return 0; err_dma_tx: - dmaengine_terminate_all(master->dma_rx); + dmaengine_terminate_all(host->dma_rx); err_dma: return ret; } @@ -357,7 +357,7 @@ err_dma: static int pic32_spi_dma_config(struct pic32_spi *pic32s, u32 dma_width) { int buf_offset = offsetof(struct pic32_spi_regs, buf); - struct spi_master *master = pic32s->master; + struct spi_controller *host = pic32s->host; struct dma_slave_config cfg; int ret; @@ -371,16 +371,16 @@ static int pic32_spi_dma_config(struct pic32_spi *pic32s, u32 dma_width) cfg.dst_addr_width = dma_width; /* tx channel */ cfg.direction = DMA_MEM_TO_DEV; - ret = dmaengine_slave_config(master->dma_tx, &cfg); + ret = dmaengine_slave_config(host->dma_tx, &cfg); if (ret) { - dev_err(&master->dev, "tx channel setup failed\n"); + dev_err(&host->dev, "tx channel setup failed\n"); return ret; } /* rx channel */ cfg.direction = DMA_DEV_TO_MEM; - ret = dmaengine_slave_config(master->dma_rx, &cfg); + ret = dmaengine_slave_config(host->dma_rx, &cfg); if (ret) - dev_err(&master->dev, "rx channel setup failed\n"); + dev_err(&host->dev, "rx channel setup failed\n"); return ret; } @@ -430,19 +430,19 @@ static int pic32_spi_set_word_size(struct pic32_spi *pic32s, u8 bits_per_word) return 0; } -static int pic32_spi_prepare_hardware(struct spi_master *master) +static int pic32_spi_prepare_hardware(struct spi_controller *host) { - struct pic32_spi *pic32s = spi_master_get_devdata(master); + struct pic32_spi *pic32s = spi_controller_get_devdata(host); pic32_spi_enable(pic32s); return 0; } -static int pic32_spi_prepare_message(struct spi_master *master, +static int pic32_spi_prepare_message(struct spi_controller *host, struct spi_message *msg) { - struct pic32_spi *pic32s = spi_master_get_devdata(master); + struct pic32_spi *pic32s = spi_controller_get_devdata(host); struct spi_device *spi = msg->spi; u32 val; @@ -481,18 +481,18 @@ static int pic32_spi_prepare_message(struct spi_master *master, return 0; } -static bool pic32_spi_can_dma(struct spi_master *master, +static bool pic32_spi_can_dma(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { - struct pic32_spi *pic32s = spi_master_get_devdata(master); + struct pic32_spi *pic32s = spi_controller_get_devdata(host); /* skip using DMA on small size transfer to avoid overhead.*/ return (xfer->len >= PIC32_DMA_LEN_MIN) && test_bit(PIC32F_DMA_PREP, &pic32s->flags); } -static int pic32_spi_one_transfer(struct spi_master *master, +static int pic32_spi_one_transfer(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *transfer) { @@ -501,7 +501,7 @@ static int pic32_spi_one_transfer(struct spi_master *master, unsigned long timeout; int ret; - pic32s = spi_master_get_devdata(master); + pic32s = spi_controller_get_devdata(host); /* handle transfer specific word size change */ if (transfer->bits_per_word && @@ -549,8 +549,8 @@ static int pic32_spi_one_transfer(struct spi_master *master, if (timeout == 0) { dev_err(&spi->dev, "wait error/timedout\n"); if (dma_issued) { - dmaengine_terminate_all(master->dma_rx); - dmaengine_terminate_all(master->dma_tx); + dmaengine_terminate_all(host->dma_rx); + dmaengine_terminate_all(host->dma_tx); } ret = -ETIMEDOUT; } else { @@ -560,16 +560,16 @@ static int pic32_spi_one_transfer(struct spi_master *master, return ret; } -static int pic32_spi_unprepare_message(struct spi_master *master, +static int pic32_spi_unprepare_message(struct spi_controller *host, struct spi_message *msg) { /* nothing to do */ return 0; } -static int pic32_spi_unprepare_hardware(struct spi_master *master) +static int pic32_spi_unprepare_hardware(struct spi_controller *host) { - struct pic32_spi *pic32s = spi_master_get_devdata(master); + struct pic32_spi *pic32s = spi_controller_get_devdata(host); pic32_spi_disable(pic32s); @@ -605,28 +605,28 @@ static void pic32_spi_cleanup(struct spi_device *spi) static int pic32_spi_dma_prep(struct pic32_spi *pic32s, struct device *dev) { - struct spi_master *master = pic32s->master; + struct spi_controller *host = pic32s->host; int ret = 0; - master->dma_rx = dma_request_chan(dev, "spi-rx"); - if (IS_ERR(master->dma_rx)) { - if (PTR_ERR(master->dma_rx) == -EPROBE_DEFER) + host->dma_rx = dma_request_chan(dev, "spi-rx"); + if (IS_ERR(host->dma_rx)) { + if (PTR_ERR(host->dma_rx) == -EPROBE_DEFER) ret = -EPROBE_DEFER; else dev_warn(dev, "RX channel not found.\n"); - master->dma_rx = NULL; + host->dma_rx = NULL; goto out_err; } - master->dma_tx = dma_request_chan(dev, "spi-tx"); - if (IS_ERR(master->dma_tx)) { - if (PTR_ERR(master->dma_tx) == -EPROBE_DEFER) + host->dma_tx = dma_request_chan(dev, "spi-tx"); + if (IS_ERR(host->dma_tx)) { + if (PTR_ERR(host->dma_tx) == -EPROBE_DEFER) ret = -EPROBE_DEFER; else dev_warn(dev, "TX channel not found.\n"); - master->dma_tx = NULL; + host->dma_tx = NULL; goto out_err; } @@ -639,14 +639,14 @@ static int pic32_spi_dma_prep(struct pic32_spi *pic32s, struct device *dev) return 0; out_err: - if (master->dma_rx) { - dma_release_channel(master->dma_rx); - master->dma_rx = NULL; + if (host->dma_rx) { + dma_release_channel(host->dma_rx); + host->dma_rx = NULL; } - if (master->dma_tx) { - dma_release_channel(master->dma_tx); - master->dma_tx = NULL; + if (host->dma_tx) { + dma_release_channel(host->dma_tx); + host->dma_tx = NULL; } return ret; @@ -658,11 +658,11 @@ static void pic32_spi_dma_unprep(struct pic32_spi *pic32s) return; clear_bit(PIC32F_DMA_PREP, &pic32s->flags); - if (pic32s->master->dma_rx) - dma_release_channel(pic32s->master->dma_rx); + if (pic32s->host->dma_rx) + dma_release_channel(pic32s->host->dma_rx); - if (pic32s->master->dma_tx) - dma_release_channel(pic32s->master->dma_tx); + if (pic32s->host->dma_tx) + dma_release_channel(pic32s->host->dma_tx); } static void pic32_spi_hw_init(struct pic32_spi *pic32s) @@ -680,7 +680,7 @@ static void pic32_spi_hw_init(struct pic32_spi *pic32s) /* disable framing mode */ ctrl &= ~CTRL_FRMEN; - /* enable master mode while disabled */ + /* enable host mode while disabled */ ctrl |= CTRL_MSTEN; /* set tx fifo threshold interrupt */ @@ -752,36 +752,36 @@ err_unmap_mem: static int pic32_spi_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *host; struct pic32_spi *pic32s; int ret; - master = spi_alloc_master(&pdev->dev, sizeof(*pic32s)); - if (!master) + host = spi_alloc_host(&pdev->dev, sizeof(*pic32s)); + if (!host) return -ENOMEM; - pic32s = spi_master_get_devdata(master); - pic32s->master = master; + pic32s = spi_controller_get_devdata(host); + pic32s->host = host; ret = pic32_spi_hw_probe(pdev, pic32s); if (ret) - goto err_master; - - master->dev.of_node = pdev->dev.of_node; - master->mode_bits = SPI_MODE_3 | SPI_MODE_0 | SPI_CS_HIGH; - master->num_chipselect = 1; /* single chip-select */ - master->max_speed_hz = clk_get_rate(pic32s->clk); - master->setup = pic32_spi_setup; - master->cleanup = pic32_spi_cleanup; - master->flags = SPI_MASTER_MUST_TX | SPI_MASTER_MUST_RX; - master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16) | + goto err_host; + + host->dev.of_node = pdev->dev.of_node; + host->mode_bits = SPI_MODE_3 | SPI_MODE_0 | SPI_CS_HIGH; + host->num_chipselect = 1; /* single chip-select */ + host->max_speed_hz = clk_get_rate(pic32s->clk); + host->setup = pic32_spi_setup; + host->cleanup = pic32_spi_cleanup; + host->flags = SPI_CONTROLLER_MUST_TX | SPI_CONTROLLER_MUST_RX; + host->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16) | SPI_BPW_MASK(32); - master->transfer_one = pic32_spi_one_transfer; - master->prepare_message = pic32_spi_prepare_message; - master->unprepare_message = pic32_spi_unprepare_message; - master->prepare_transfer_hardware = pic32_spi_prepare_hardware; - master->unprepare_transfer_hardware = pic32_spi_unprepare_hardware; - master->use_gpio_descriptors = true; + host->transfer_one = pic32_spi_one_transfer; + host->prepare_message = pic32_spi_prepare_message; + host->unprepare_message = pic32_spi_unprepare_message; + host->prepare_transfer_hardware = pic32_spi_prepare_hardware; + host->unprepare_transfer_hardware = pic32_spi_unprepare_hardware; + host->use_gpio_descriptors = true; /* optional DMA support */ ret = pic32_spi_dma_prep(pic32s, &pdev->dev); @@ -789,7 +789,7 @@ static int pic32_spi_probe(struct platform_device *pdev) goto err_bailout; if (test_bit(PIC32F_DMA_PREP, &pic32s->flags)) - master->can_dma = pic32_spi_can_dma; + host->can_dma = pic32_spi_can_dma; init_completion(&pic32s->xfer_done); pic32s->mode = -1; @@ -824,10 +824,10 @@ static int pic32_spi_probe(struct platform_device *pdev) goto err_bailout; } - /* register master */ - ret = devm_spi_register_master(&pdev->dev, master); + /* register host */ + ret = devm_spi_register_controller(&pdev->dev, host); if (ret) { - dev_err(&master->dev, "failed registering spi master\n"); + dev_err(&host->dev, "failed registering spi host\n"); goto err_bailout; } @@ -838,8 +838,8 @@ static int pic32_spi_probe(struct platform_device *pdev) err_bailout: pic32_spi_dma_unprep(pic32s); clk_disable_unprepare(pic32s->clk); -err_master: - spi_master_put(master); +err_host: + spi_controller_put(host); return ret; } diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 1af75eff26b6..bb347b6bb6f3 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -336,8 +336,8 @@ struct vendor_data { * @phybase: the physical memory where the SSP device resides * @virtbase: the virtual memory where the SSP is mapped * @clk: outgoing clock "SPICLK" for the SPI bus - * @master: SPI framework hookup - * @master_info: controller-specific data from machine setup + * @host: SPI framework hookup + * @host_info: controller-specific data from machine setup * @pump_transfers: Tasklet used in Interrupt Transfer mode * @cur_msg: Pointer to current spi_message being processed * @cur_transfer: Pointer to current spi_transfer @@ -370,8 +370,8 @@ struct pl022 { resource_size_t phybase; void __iomem *virtbase; struct clk *clk; - struct spi_master *master; - struct pl022_ssp_controller *master_info; + struct spi_controller *host; + struct pl022_ssp_controller *host_info; /* Message per-transfer pump */ struct tasklet_struct pump_transfers; struct spi_message *cur_msg; @@ -500,7 +500,7 @@ static void giveback(struct pl022 *pl022) * could invalidate the cs_control() callback... */ /* get a pointer to the next message, if any */ - next_msg = spi_get_next_queued_message(pl022->master); + next_msg = spi_get_next_queued_message(pl022->host); /* * see if the next and current messages point @@ -523,7 +523,7 @@ static void giveback(struct pl022 *pl022) writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); - spi_finalize_current_message(pl022->master); + spi_finalize_current_message(pl022->host); } /** @@ -1110,16 +1110,16 @@ static int pl022_dma_probe(struct pl022 *pl022) * of them. */ pl022->dma_rx_channel = dma_request_channel(mask, - pl022->master_info->dma_filter, - pl022->master_info->dma_rx_param); + pl022->host_info->dma_filter, + pl022->host_info->dma_rx_param); if (!pl022->dma_rx_channel) { dev_dbg(&pl022->adev->dev, "no RX DMA channel!\n"); goto err_no_rxchan; } pl022->dma_tx_channel = dma_request_channel(mask, - pl022->master_info->dma_filter, - pl022->master_info->dma_tx_param); + pl022->host_info->dma_filter, + pl022->host_info->dma_tx_param); if (!pl022->dma_tx_channel) { dev_dbg(&pl022->adev->dev, "no TX DMA channel!\n"); goto err_no_txchan; @@ -1573,10 +1573,10 @@ out: return; } -static int pl022_transfer_one_message(struct spi_master *master, +static int pl022_transfer_one_message(struct spi_controller *host, struct spi_message *msg) { - struct pl022 *pl022 = spi_master_get_devdata(master); + struct pl022 *pl022 = spi_controller_get_devdata(host); /* Initial message state */ pl022->cur_msg = msg; @@ -1602,9 +1602,9 @@ static int pl022_transfer_one_message(struct spi_master *master, return 0; } -static int pl022_unprepare_transfer_hardware(struct spi_master *master) +static int pl022_unprepare_transfer_hardware(struct spi_controller *host) { - struct pl022 *pl022 = spi_master_get_devdata(master); + struct pl022 *pl022 = spi_controller_get_devdata(host); /* nothing more to do - disable spi/ssp and power off */ writew((readw(SSP_CR1(pl022->virtbase)) & @@ -1826,10 +1826,10 @@ static const struct pl022_config_chip pl022_default_chip_info = { }; /** - * pl022_setup - setup function registered to SPI master framework + * pl022_setup - setup function registered to SPI host framework * @spi: spi device which is requesting setup * - * This function is registered to the SPI framework for this SPI master + * This function is registered to the SPI framework for this SPI host * controller. If it is the first time when setup is called by this device, * this function will initialize the runtime state for this chip and save * the same in the device structure. Else it will update the runtime info @@ -1844,7 +1844,7 @@ static int pl022_setup(struct spi_device *spi) struct chip_data *chip; struct ssp_clock_params clk_freq = { .cpsdvsr = 0, .scr = 0}; int status = 0; - struct pl022 *pl022 = spi_master_get_devdata(spi->master); + struct pl022 *pl022 = spi_controller_get_devdata(spi->controller); unsigned int bits = spi->bits_per_word; u32 tmp; struct device_node *np = spi->dev.of_node; @@ -1964,7 +1964,7 @@ static int pl022_setup(struct spi_device *spi) chip->dmacr = 0; chip->cpsr = 0; if ((chip_info->com_mode == DMA_TRANSFER) - && ((pl022->master_info)->enable_dma)) { + && ((pl022->host_info)->enable_dma)) { chip->enable_dma = true; dev_dbg(&spi->dev, "DMA mode set in controller state\n"); SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED, @@ -2061,10 +2061,10 @@ static int pl022_setup(struct spi_device *spi) } /** - * pl022_cleanup - cleanup function registered to SPI master framework + * pl022_cleanup - cleanup function registered to SPI host framework * @spi: spi device which is requesting cleanup * - * This function is registered to the SPI framework for this SPI master + * This function is registered to the SPI framework for this SPI host * controller. It will free the runtime state of chip. */ static void pl022_cleanup(struct spi_device *spi) @@ -2103,7 +2103,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) struct device *dev = &adev->dev; struct pl022_ssp_controller *platform_info = dev_get_platdata(&adev->dev); - struct spi_master *master; + struct spi_controller *host; struct pl022 *pl022 = NULL; /*Data for this driver */ int status = 0; @@ -2117,16 +2117,16 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) return -ENODEV; } - /* Allocate master with space for data */ - master = spi_alloc_master(dev, sizeof(struct pl022)); - if (master == NULL) { - dev_err(&adev->dev, "probe - cannot alloc SPI master\n"); + /* Allocate host with space for data */ + host = spi_alloc_host(dev, sizeof(struct pl022)); + if (host == NULL) { + dev_err(&adev->dev, "probe - cannot alloc SPI host\n"); return -ENOMEM; } - pl022 = spi_master_get_devdata(master); - pl022->master = master; - pl022->master_info = platform_info; + pl022 = spi_controller_get_devdata(host); + pl022->host = host; + pl022->host_info = platform_info; pl022->adev = adev; pl022->vendor = id->data; @@ -2134,25 +2134,25 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) * Bus Number Which has been Assigned to this SSP controller * on this board */ - master->bus_num = platform_info->bus_id; - master->cleanup = pl022_cleanup; - master->setup = pl022_setup; - master->auto_runtime_pm = true; - master->transfer_one_message = pl022_transfer_one_message; - master->unprepare_transfer_hardware = pl022_unprepare_transfer_hardware; - master->rt = platform_info->rt; - master->dev.of_node = dev->of_node; - master->use_gpio_descriptors = true; + host->bus_num = platform_info->bus_id; + host->cleanup = pl022_cleanup; + host->setup = pl022_setup; + host->auto_runtime_pm = true; + host->transfer_one_message = pl022_transfer_one_message; + host->unprepare_transfer_hardware = pl022_unprepare_transfer_hardware; + host->rt = platform_info->rt; + host->dev.of_node = dev->of_node; + host->use_gpio_descriptors = true; /* * Supports mode 0-3, loopback, and active low CS. Transfers are * always MS bit first on the original pl022. */ - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; if (pl022->vendor->extended_cr) - master->mode_bits |= SPI_LSB_FIRST; + host->mode_bits |= SPI_LSB_FIRST; - dev_dbg(&adev->dev, "BUSNO: %d\n", master->bus_num); + dev_dbg(&adev->dev, "BUSNO: %d\n", host->bus_num); status = amba_request_regions(adev, NULL); if (status) @@ -2215,10 +2215,10 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) /* Register with the SPI framework */ amba_set_drvdata(adev, pl022); - status = devm_spi_register_master(&adev->dev, master); + status = devm_spi_register_controller(&adev->dev, host); if (status != 0) { dev_err_probe(&adev->dev, status, - "problem registering spi master\n"); + "problem registering spi host\n"); goto err_spi_register; } dev_dbg(dev, "probe succeeded\n"); @@ -2246,7 +2246,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) err_no_ioremap: amba_release_regions(adev); err_no_ioregion: - spi_master_put(master); + spi_controller_put(host); return status; } @@ -2265,7 +2265,7 @@ pl022_remove(struct amba_device *adev) pm_runtime_get_noresume(&adev->dev); load_ssp_default_config(pl022); - if (pl022->master_info->enable_dma) + if (pl022->host_info->enable_dma) pl022_dma_remove(pl022); clk_disable_unprepare(pl022->clk); @@ -2279,13 +2279,13 @@ static int pl022_suspend(struct device *dev) struct pl022 *pl022 = dev_get_drvdata(dev); int ret; - ret = spi_master_suspend(pl022->master); + ret = spi_controller_suspend(pl022->host); if (ret) return ret; ret = pm_runtime_force_suspend(dev); if (ret) { - spi_master_resume(pl022->master); + spi_controller_resume(pl022->host); return ret; } @@ -2305,7 +2305,7 @@ static int pl022_resume(struct device *dev) dev_err(dev, "problem resuming\n"); /* Start the queue running */ - ret = spi_master_resume(pl022->master); + ret = spi_controller_resume(pl022->host); if (!ret) dev_dbg(dev, "resumed\n"); diff --git a/drivers/spi/spi-ppc4xx.c b/drivers/spi/spi-ppc4xx.c index d725e915025d..03aab661be9d 100644 --- a/drivers/spi/spi-ppc4xx.c +++ b/drivers/spi/spi-ppc4xx.c @@ -126,7 +126,7 @@ struct ppc4xx_spi { unsigned char *rx; struct spi_ppc4xx_regs __iomem *regs; /* pointer to the registers */ - struct spi_master *master; + struct spi_controller *host; struct device *dev; }; @@ -143,7 +143,7 @@ static int spi_ppc4xx_txrx(struct spi_device *spi, struct spi_transfer *t) dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n", t->tx_buf, t->rx_buf, t->len); - hw = spi_master_get_devdata(spi->master); + hw = spi_controller_get_devdata(spi->controller); hw->tx = t->tx_buf; hw->rx = t->rx_buf; @@ -161,7 +161,7 @@ static int spi_ppc4xx_txrx(struct spi_device *spi, struct spi_transfer *t) static int spi_ppc4xx_setupxfer(struct spi_device *spi, struct spi_transfer *t) { - struct ppc4xx_spi *hw = spi_master_get_devdata(spi->master); + struct ppc4xx_spi *hw = spi_controller_get_devdata(spi->controller); struct spi_ppc4xx_cs *cs = spi->controller_state; int scr; u8 cdm = 0; @@ -340,7 +340,7 @@ static void spi_ppc4xx_enable(struct ppc4xx_spi *hw) static int spi_ppc4xx_of_probe(struct platform_device *op) { struct ppc4xx_spi *hw; - struct spi_master *master; + struct spi_controller *host; struct spi_bitbang *bbp; struct resource resource; struct device_node *np = op->dev.of_node; @@ -349,20 +349,20 @@ static int spi_ppc4xx_of_probe(struct platform_device *op) int ret; const unsigned int *clk; - master = spi_alloc_master(dev, sizeof(*hw)); - if (master == NULL) + host = spi_alloc_host(dev, sizeof(*hw)); + if (host == NULL) return -ENOMEM; - master->dev.of_node = np; - platform_set_drvdata(op, master); - hw = spi_master_get_devdata(master); - hw->master = master; + host->dev.of_node = np; + platform_set_drvdata(op, host); + hw = spi_controller_get_devdata(host); + hw->host = host; hw->dev = dev; init_completion(&hw->done); /* Setup the state for the bitbang driver */ bbp = &hw->bitbang; - bbp->master = hw->master; + bbp->master = hw->host; bbp->setup_transfer = spi_ppc4xx_setupxfer; bbp->txrx_bufs = spi_ppc4xx_txrx; bbp->use_dma = 0; @@ -385,7 +385,7 @@ static int spi_ppc4xx_of_probe(struct platform_device *op) if (opbnp == NULL) { dev_err(dev, "OPB: cannot find node\n"); ret = -ENODEV; - goto free_master; + goto free_host; } /* Get the clock (Hz) for the OPB */ clk = of_get_property(opbnp, "clock-frequency", NULL); @@ -393,7 +393,7 @@ static int spi_ppc4xx_of_probe(struct platform_device *op) dev_err(dev, "OPB: no clock-frequency property set\n"); of_node_put(opbnp); ret = -ENODEV; - goto free_master; + goto free_host; } hw->opb_freq = *clk; hw->opb_freq >>= 2; @@ -402,7 +402,7 @@ static int spi_ppc4xx_of_probe(struct platform_device *op) ret = of_address_to_resource(np, 0, &resource); if (ret) { dev_err(dev, "error while parsing device node resource\n"); - goto free_master; + goto free_host; } hw->mapbase = resource.start; hw->mapsize = resource_size(&resource); @@ -411,7 +411,7 @@ static int spi_ppc4xx_of_probe(struct platform_device *op) if (hw->mapsize < sizeof(struct spi_ppc4xx_regs)) { dev_err(dev, "too small to map registers\n"); ret = -EINVAL; - goto free_master; + goto free_host; } /* Request IRQ */ @@ -420,7 +420,7 @@ static int spi_ppc4xx_of_probe(struct platform_device *op) 0, "spi_ppc4xx_of", (void *)hw); if (ret) { dev_err(dev, "unable to allocate interrupt\n"); - goto free_master; + goto free_host; } if (!request_mem_region(hw->mapbase, hw->mapsize, DRIVER_NAME)) { @@ -443,7 +443,7 @@ static int spi_ppc4xx_of_probe(struct platform_device *op) dev->dma_mask = 0; ret = spi_bitbang_start(bbp); if (ret) { - dev_err(dev, "failed to register SPI master\n"); + dev_err(dev, "failed to register SPI host\n"); goto unmap_regs; } @@ -457,8 +457,8 @@ map_io_error: release_mem_region(hw->mapbase, hw->mapsize); request_mem_error: free_irq(hw->irqnum, hw); -free_master: - spi_master_put(master); +free_host: + spi_controller_put(host); dev_err(dev, "initialization failed\n"); return ret; @@ -466,14 +466,14 @@ free_master: static void spi_ppc4xx_of_remove(struct platform_device *op) { - struct spi_master *master = platform_get_drvdata(op); - struct ppc4xx_spi *hw = spi_master_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(op); + struct ppc4xx_spi *hw = spi_controller_get_devdata(host); spi_bitbang_stop(&hw->bitbang); release_mem_region(hw->mapbase, hw->mapsize); free_irq(hw->irqnum, hw); iounmap(hw->regs); - spi_master_put(master); + spi_controller_put(host); } static const struct of_device_id spi_ppc4xx_of_match[] = { diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index 1bab18a0f262..f2a856f6a99e 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1102,7 +1102,7 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *controller, } } - if (spi_controller_is_slave(controller)) { + if (spi_controller_is_target(controller)) { while (drv_data->write(drv_data)) ; if (drv_data->gpiod_ready) { @@ -1121,7 +1121,7 @@ static int pxa2xx_spi_transfer_one(struct spi_controller *controller, return 1; } -static int pxa2xx_spi_slave_abort(struct spi_controller *controller) +static int pxa2xx_spi_target_abort(struct spi_controller *controller) { struct driver_data *drv_data = spi_controller_get_devdata(controller); @@ -1199,7 +1199,7 @@ static int setup(struct spi_device *spi) break; default: tx_hi_thres = 0; - if (spi_controller_is_slave(drv_data->controller)) { + if (spi_controller_is_target(drv_data->controller)) { tx_thres = 1; rx_thres = 2; } else { @@ -1248,7 +1248,7 @@ static int setup(struct spi_device *spi) } chip->cr1 = 0; - if (spi_controller_is_slave(drv_data->controller)) { + if (spi_controller_is_target(drv_data->controller)) { chip->cr1 |= SSCR1_SCFR; chip->cr1 |= SSCR1_SCLKDIR; chip->cr1 |= SSCR1_SFRMDIR; @@ -1344,7 +1344,7 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev) match = device_get_match_data(dev); if (match) - type = (enum pxa_ssp_type)match; + type = (uintptr_t)match; else if (is_lpss_priv) { u32 value; @@ -1395,7 +1395,7 @@ pxa2xx_spi_init_pdata(struct platform_device *pdev) else ssp->port_id = uid; - pdata->is_slave = device_property_read_bool(dev, "spi-slave"); + pdata->is_target = device_property_read_bool(dev, "spi-slave"); pdata->num_chipselect = 1; pdata->enable_dma = true; pdata->dma_burst_size = 1; @@ -1461,10 +1461,10 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) return -ENODEV; } - if (platform_info->is_slave) - controller = devm_spi_alloc_slave(dev, sizeof(*drv_data)); + if (platform_info->is_target) + controller = devm_spi_alloc_target(dev, sizeof(*drv_data)); else - controller = devm_spi_alloc_master(dev, sizeof(*drv_data)); + controller = devm_spi_alloc_host(dev, sizeof(*drv_data)); if (!controller) { dev_err(&pdev->dev, "cannot alloc spi_controller\n"); @@ -1487,7 +1487,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) controller->setup = setup; controller->set_cs = pxa2xx_spi_set_cs; controller->transfer_one = pxa2xx_spi_transfer_one; - controller->slave_abort = pxa2xx_spi_slave_abort; + controller->target_abort = pxa2xx_spi_target_abort; controller->handle_err = pxa2xx_spi_handle_err; controller->unprepare_transfer_hardware = pxa2xx_spi_unprepare_transfer; controller->fw_translate_cs = pxa2xx_spi_fw_translate_cs; @@ -1579,7 +1579,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) break; default: - if (spi_controller_is_slave(controller)) { + if (spi_controller_is_target(controller)) { tmp = SSCR1_SCFR | SSCR1_SCLKDIR | SSCR1_SFRMDIR | @@ -1592,7 +1592,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) } pxa2xx_spi_write(drv_data, SSCR1, tmp); tmp = SSCR0_Motorola | SSCR0_DataSize(8); - if (!spi_controller_is_slave(controller)) + if (!spi_controller_is_target(controller)) tmp |= SSCR0_SCR(2); pxa2xx_spi_write(drv_data, SSCR0, tmp); break; @@ -1620,7 +1620,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) controller->num_chipselect = platform_info->num_chipselect; controller->use_gpio_descriptors = true; - if (platform_info->is_slave) { + if (platform_info->is_target) { drv_data->gpiod_ready = devm_gpiod_get_optional(dev, "ready", GPIOD_OUT_LOW); if (IS_ERR(drv_data->gpiod_ready)) { diff --git a/drivers/spi/spi-qcom-qspi.c b/drivers/spi/spi-qcom-qspi.c index 1954c39b3d08..49b775134485 100644 --- a/drivers/spi/spi-qcom-qspi.c +++ b/drivers/spi/spi-qcom-qspi.c @@ -9,7 +9,7 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/pinctrl/consumer.h> #include <linux/pm_runtime.h> #include <linux/pm_opp.h> @@ -247,11 +247,11 @@ static void qcom_qspi_pio_xfer(struct qcom_qspi *ctrl) qcom_qspi_pio_xfer_ctrl(ctrl); } -static void qcom_qspi_handle_err(struct spi_master *master, +static void qcom_qspi_handle_err(struct spi_controller *host, struct spi_message *msg) { u32 int_status; - struct qcom_qspi *ctrl = spi_master_get_devdata(master); + struct qcom_qspi *ctrl = spi_controller_get_devdata(host); unsigned long flags; int i; @@ -411,11 +411,11 @@ static bool qcom_qspi_can_dma(struct spi_controller *ctlr, return xfer->len > QSPI_MAX_BYTES_FIFO; } -static int qcom_qspi_transfer_one(struct spi_master *master, +static int qcom_qspi_transfer_one(struct spi_controller *host, struct spi_device *slv, struct spi_transfer *xfer) { - struct qcom_qspi *ctrl = spi_master_get_devdata(master); + struct qcom_qspi *ctrl = spi_controller_get_devdata(host); int ret; unsigned long speed_hz; unsigned long flags; @@ -443,7 +443,7 @@ static int qcom_qspi_transfer_one(struct spi_master *master, ctrl->xfer.tx_buf = xfer->tx_buf; } ctrl->xfer.is_last = list_is_last(&xfer->transfer_list, - &master->cur_msg->transfers); + &host->cur_msg->transfers); ctrl->xfer.rem_bytes = xfer->len; if (xfer->rx_sg.nents || xfer->tx_sg.nents) { @@ -481,7 +481,7 @@ exit: return 1; } -static int qcom_qspi_prepare_message(struct spi_master *master, +static int qcom_qspi_prepare_message(struct spi_controller *host, struct spi_message *message) { u32 mstr_cfg; @@ -490,7 +490,7 @@ static int qcom_qspi_prepare_message(struct spi_master *master, int tx_data_delay = 1; unsigned long flags; - ctrl = spi_master_get_devdata(master); + ctrl = spi_controller_get_devdata(host); spin_lock_irqsave(&ctrl->lock, flags); mstr_cfg = readl(ctrl->base + MSTR_CONFIG); @@ -694,18 +694,18 @@ static int qcom_qspi_probe(struct platform_device *pdev) { int ret; struct device *dev; - struct spi_master *master; + struct spi_controller *host; struct qcom_qspi *ctrl; dev = &pdev->dev; - master = devm_spi_alloc_master(dev, sizeof(*ctrl)); - if (!master) + host = devm_spi_alloc_host(dev, sizeof(*ctrl)); + if (!host) return -ENOMEM; - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); - ctrl = spi_master_get_devdata(master); + ctrl = spi_controller_get_devdata(host); spin_lock_init(&ctrl->lock); ctrl->dev = dev; @@ -758,23 +758,23 @@ static int qcom_qspi_probe(struct platform_device *pdev) if (ret) return dev_err_probe(dev, ret, "could not set DMA mask\n"); - master->max_speed_hz = 300000000; - master->max_dma_len = 65536; /* as per HPG */ - master->dma_alignment = QSPI_ALIGN_REQ; - master->num_chipselect = QSPI_NUM_CS; - master->bus_num = -1; - master->dev.of_node = pdev->dev.of_node; - master->mode_bits = SPI_MODE_0 | - SPI_TX_DUAL | SPI_RX_DUAL | - SPI_TX_QUAD | SPI_RX_QUAD; - master->flags = SPI_MASTER_HALF_DUPLEX; - master->prepare_message = qcom_qspi_prepare_message; - master->transfer_one = qcom_qspi_transfer_one; - master->handle_err = qcom_qspi_handle_err; + host->max_speed_hz = 300000000; + host->max_dma_len = 65536; /* as per HPG */ + host->dma_alignment = QSPI_ALIGN_REQ; + host->num_chipselect = QSPI_NUM_CS; + host->bus_num = -1; + host->dev.of_node = pdev->dev.of_node; + host->mode_bits = SPI_MODE_0 | + SPI_TX_DUAL | SPI_RX_DUAL | + SPI_TX_QUAD | SPI_RX_QUAD; + host->flags = SPI_CONTROLLER_HALF_DUPLEX; + host->prepare_message = qcom_qspi_prepare_message; + host->transfer_one = qcom_qspi_transfer_one; + host->handle_err = qcom_qspi_handle_err; if (of_property_read_bool(pdev->dev.of_node, "iommus")) - master->can_dma = qcom_qspi_can_dma; - master->auto_runtime_pm = true; - master->mem_ops = &qcom_qspi_mem_ops; + host->can_dma = qcom_qspi_can_dma; + host->auto_runtime_pm = true; + host->mem_ops = &qcom_qspi_mem_ops; ret = devm_pm_opp_set_clkname(&pdev->dev, "core"); if (ret) @@ -794,7 +794,7 @@ static int qcom_qspi_probe(struct platform_device *pdev) pm_runtime_set_autosuspend_delay(dev, 250); pm_runtime_enable(dev); - ret = spi_register_master(master); + ret = spi_register_controller(host); if (!ret) return 0; @@ -805,18 +805,18 @@ static int qcom_qspi_probe(struct platform_device *pdev) static void qcom_qspi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); + struct spi_controller *host = platform_get_drvdata(pdev); /* Unregister _before_ disabling pm_runtime() so we stop transfers */ - spi_unregister_master(master); + spi_unregister_controller(host); pm_runtime_disable(&pdev->dev); } static int __maybe_unused qcom_qspi_runtime_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct qcom_qspi *ctrl = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct qcom_qspi *ctrl = spi_controller_get_devdata(host); int ret; /* Drop the performance state vote */ @@ -837,8 +837,8 @@ static int __maybe_unused qcom_qspi_runtime_suspend(struct device *dev) static int __maybe_unused qcom_qspi_runtime_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct qcom_qspi *ctrl = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct qcom_qspi *ctrl = spi_controller_get_devdata(host); int ret; pinctrl_pm_select_default_state(dev); @@ -859,30 +859,30 @@ static int __maybe_unused qcom_qspi_runtime_resume(struct device *dev) static int __maybe_unused qcom_qspi_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); + struct spi_controller *host = dev_get_drvdata(dev); int ret; - ret = spi_master_suspend(master); + ret = spi_controller_suspend(host); if (ret) return ret; ret = pm_runtime_force_suspend(dev); if (ret) - spi_master_resume(master); + spi_controller_resume(host); return ret; } static int __maybe_unused qcom_qspi_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); + struct spi_controller *host = dev_get_drvdata(dev); int ret; ret = pm_runtime_force_resume(dev); if (ret) return ret; - ret = spi_master_resume(master); + ret = spi_controller_resume(host); if (ret) pm_runtime_force_suspend(dev); diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index 00e5e88e72c4..4b6f6b25219b 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -11,7 +11,6 @@ #include <linux/list.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/spi/spi.h> @@ -386,20 +385,20 @@ static void spi_qup_write(struct spi_qup *controller) } while (remainder); } -static int spi_qup_prep_sg(struct spi_master *master, struct scatterlist *sgl, +static int spi_qup_prep_sg(struct spi_controller *host, struct scatterlist *sgl, unsigned int nents, enum dma_transfer_direction dir, dma_async_tx_callback callback) { - struct spi_qup *qup = spi_master_get_devdata(master); + struct spi_qup *qup = spi_controller_get_devdata(host); unsigned long flags = DMA_PREP_INTERRUPT | DMA_PREP_FENCE; struct dma_async_tx_descriptor *desc; struct dma_chan *chan; dma_cookie_t cookie; if (dir == DMA_MEM_TO_DEV) - chan = master->dma_tx; + chan = host->dma_tx; else - chan = master->dma_rx; + chan = host->dma_rx; desc = dmaengine_prep_slave_sg(chan, sgl, nents, dir, flags); if (IS_ERR_OR_NULL(desc)) @@ -413,13 +412,13 @@ static int spi_qup_prep_sg(struct spi_master *master, struct scatterlist *sgl, return dma_submit_error(cookie); } -static void spi_qup_dma_terminate(struct spi_master *master, +static void spi_qup_dma_terminate(struct spi_controller *host, struct spi_transfer *xfer) { if (xfer->tx_buf) - dmaengine_terminate_all(master->dma_tx); + dmaengine_terminate_all(host->dma_tx); if (xfer->rx_buf) - dmaengine_terminate_all(master->dma_rx); + dmaengine_terminate_all(host->dma_rx); } static u32 spi_qup_sgl_get_nents_len(struct scatterlist *sgl, u32 max, @@ -446,8 +445,8 @@ static int spi_qup_do_dma(struct spi_device *spi, struct spi_transfer *xfer, unsigned long timeout) { dma_async_tx_callback rx_done = NULL, tx_done = NULL; - struct spi_master *master = spi->master; - struct spi_qup *qup = spi_master_get_devdata(master); + struct spi_controller *host = spi->controller; + struct spi_qup *qup = spi_controller_get_devdata(host); struct scatterlist *tx_sgl, *rx_sgl; int ret; @@ -482,20 +481,20 @@ static int spi_qup_do_dma(struct spi_device *spi, struct spi_transfer *xfer, return ret; } if (rx_sgl) { - ret = spi_qup_prep_sg(master, rx_sgl, rx_nents, + ret = spi_qup_prep_sg(host, rx_sgl, rx_nents, DMA_DEV_TO_MEM, rx_done); if (ret) return ret; - dma_async_issue_pending(master->dma_rx); + dma_async_issue_pending(host->dma_rx); } if (tx_sgl) { - ret = spi_qup_prep_sg(master, tx_sgl, tx_nents, + ret = spi_qup_prep_sg(host, tx_sgl, tx_nents, DMA_MEM_TO_DEV, tx_done); if (ret) return ret; - dma_async_issue_pending(master->dma_tx); + dma_async_issue_pending(host->dma_tx); } if (!wait_for_completion_timeout(&qup->done, timeout)) @@ -514,8 +513,8 @@ static int spi_qup_do_dma(struct spi_device *spi, struct spi_transfer *xfer, static int spi_qup_do_pio(struct spi_device *spi, struct spi_transfer *xfer, unsigned long timeout) { - struct spi_master *master = spi->master; - struct spi_qup *qup = spi_master_get_devdata(master); + struct spi_controller *host = spi->controller; + struct spi_qup *qup = spi_controller_get_devdata(host); int ret, n_words, iterations, offset = 0; n_words = qup->n_words; @@ -659,7 +658,7 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id) /* set clock freq ... bits per word, determine mode */ static int spi_qup_io_prep(struct spi_device *spi, struct spi_transfer *xfer) { - struct spi_qup *controller = spi_master_get_devdata(spi->master); + struct spi_qup *controller = spi_controller_get_devdata(spi->controller); int ret; if (spi->mode & SPI_LOOP && xfer->len > controller->in_fifo_sz) { @@ -680,9 +679,9 @@ static int spi_qup_io_prep(struct spi_device *spi, struct spi_transfer *xfer) if (controller->n_words <= (controller->in_fifo_sz / sizeof(u32))) controller->mode = QUP_IO_M_MODE_FIFO; - else if (spi->master->can_dma && - spi->master->can_dma(spi->master, spi, xfer) && - spi->master->cur_msg_mapped) + else if (spi->controller->can_dma && + spi->controller->can_dma(spi->controller, spi, xfer) && + spi->controller->cur_msg_mapped) controller->mode = QUP_IO_M_MODE_BAM; else controller->mode = QUP_IO_M_MODE_BLOCK; @@ -693,7 +692,7 @@ static int spi_qup_io_prep(struct spi_device *spi, struct spi_transfer *xfer) /* prep qup for another spi transaction of specific type */ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer) { - struct spi_qup *controller = spi_master_get_devdata(spi->master); + struct spi_qup *controller = spi_controller_get_devdata(spi->controller); u32 config, iomode, control; unsigned long flags; @@ -841,11 +840,11 @@ static int spi_qup_io_config(struct spi_device *spi, struct spi_transfer *xfer) return 0; } -static int spi_qup_transfer_one(struct spi_master *master, +static int spi_qup_transfer_one(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { - struct spi_qup *controller = spi_master_get_devdata(master); + struct spi_qup *controller = spi_controller_get_devdata(host); unsigned long timeout, flags; int ret; @@ -879,21 +878,21 @@ static int spi_qup_transfer_one(struct spi_master *master, spin_unlock_irqrestore(&controller->lock, flags); if (ret && spi_qup_is_dma_xfer(controller->mode)) - spi_qup_dma_terminate(master, xfer); + spi_qup_dma_terminate(host, xfer); return ret; } -static bool spi_qup_can_dma(struct spi_master *master, struct spi_device *spi, +static bool spi_qup_can_dma(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { - struct spi_qup *qup = spi_master_get_devdata(master); + struct spi_qup *qup = spi_controller_get_devdata(host); size_t dma_align = dma_get_cache_alignment(); int n_words; if (xfer->rx_buf) { if (!IS_ALIGNED((size_t)xfer->rx_buf, dma_align) || - IS_ERR_OR_NULL(master->dma_rx)) + IS_ERR_OR_NULL(host->dma_rx)) return false; if (qup->qup_v1 && (xfer->len % qup->in_blk_sz)) return false; @@ -901,7 +900,7 @@ static bool spi_qup_can_dma(struct spi_master *master, struct spi_device *spi, if (xfer->tx_buf) { if (!IS_ALIGNED((size_t)xfer->tx_buf, dma_align) || - IS_ERR_OR_NULL(master->dma_tx)) + IS_ERR_OR_NULL(host->dma_tx)) return false; if (qup->qup_v1 && (xfer->len % qup->out_blk_sz)) return false; @@ -914,30 +913,30 @@ static bool spi_qup_can_dma(struct spi_master *master, struct spi_device *spi, return true; } -static void spi_qup_release_dma(struct spi_master *master) +static void spi_qup_release_dma(struct spi_controller *host) { - if (!IS_ERR_OR_NULL(master->dma_rx)) - dma_release_channel(master->dma_rx); - if (!IS_ERR_OR_NULL(master->dma_tx)) - dma_release_channel(master->dma_tx); + if (!IS_ERR_OR_NULL(host->dma_rx)) + dma_release_channel(host->dma_rx); + if (!IS_ERR_OR_NULL(host->dma_tx)) + dma_release_channel(host->dma_tx); } -static int spi_qup_init_dma(struct spi_master *master, resource_size_t base) +static int spi_qup_init_dma(struct spi_controller *host, resource_size_t base) { - struct spi_qup *spi = spi_master_get_devdata(master); + struct spi_qup *spi = spi_controller_get_devdata(host); struct dma_slave_config *rx_conf = &spi->rx_conf, *tx_conf = &spi->tx_conf; struct device *dev = spi->dev; int ret; /* allocate dma resources, if available */ - master->dma_rx = dma_request_chan(dev, "rx"); - if (IS_ERR(master->dma_rx)) - return PTR_ERR(master->dma_rx); + host->dma_rx = dma_request_chan(dev, "rx"); + if (IS_ERR(host->dma_rx)) + return PTR_ERR(host->dma_rx); - master->dma_tx = dma_request_chan(dev, "tx"); - if (IS_ERR(master->dma_tx)) { - ret = PTR_ERR(master->dma_tx); + host->dma_tx = dma_request_chan(dev, "tx"); + if (IS_ERR(host->dma_tx)) { + ret = PTR_ERR(host->dma_tx); goto err_tx; } @@ -952,13 +951,13 @@ static int spi_qup_init_dma(struct spi_master *master, resource_size_t base) tx_conf->dst_addr = base + QUP_OUTPUT_FIFO; tx_conf->dst_maxburst = spi->out_blk_sz; - ret = dmaengine_slave_config(master->dma_rx, rx_conf); + ret = dmaengine_slave_config(host->dma_rx, rx_conf); if (ret) { dev_err(dev, "failed to configure RX channel\n"); goto err; } - ret = dmaengine_slave_config(master->dma_tx, tx_conf); + ret = dmaengine_slave_config(host->dma_tx, tx_conf); if (ret) { dev_err(dev, "failed to configure TX channel\n"); goto err; @@ -967,9 +966,9 @@ static int spi_qup_init_dma(struct spi_master *master, resource_size_t base) return 0; err: - dma_release_channel(master->dma_tx); + dma_release_channel(host->dma_tx); err_tx: - dma_release_channel(master->dma_rx); + dma_release_channel(host->dma_rx); return ret; } @@ -979,7 +978,7 @@ static void spi_qup_set_cs(struct spi_device *spi, bool val) u32 spi_ioc; u32 spi_ioc_orig; - controller = spi_master_get_devdata(spi->master); + controller = spi_controller_get_devdata(spi->controller); spi_ioc = readl_relaxed(controller->base + SPI_IO_CONTROL); spi_ioc_orig = spi_ioc; if (!val) @@ -993,7 +992,7 @@ static void spi_qup_set_cs(struct spi_device *spi, bool val) static int spi_qup_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *host; struct clk *iclk, *cclk; struct spi_qup *controller; struct resource *res; @@ -1028,34 +1027,34 @@ static int spi_qup_probe(struct platform_device *pdev) return -ENXIO; } - master = spi_alloc_master(dev, sizeof(struct spi_qup)); - if (!master) { - dev_err(dev, "cannot allocate master\n"); + host = spi_alloc_host(dev, sizeof(struct spi_qup)); + if (!host) { + dev_err(dev, "cannot allocate host\n"); return -ENOMEM; } /* use num-cs unless not present or out of range */ if (of_property_read_u32(dev->of_node, "num-cs", &num_cs) || num_cs > SPI_NUM_CHIPSELECTS) - master->num_chipselect = SPI_NUM_CHIPSELECTS; + host->num_chipselect = SPI_NUM_CHIPSELECTS; else - master->num_chipselect = num_cs; + host->num_chipselect = num_cs; - master->use_gpio_descriptors = true; - master->max_native_cs = SPI_NUM_CHIPSELECTS; - master->bus_num = pdev->id; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; - master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); - master->max_speed_hz = max_freq; - master->transfer_one = spi_qup_transfer_one; - master->dev.of_node = pdev->dev.of_node; - master->auto_runtime_pm = true; - master->dma_alignment = dma_get_cache_alignment(); - master->max_dma_len = SPI_MAX_XFER; + host->use_gpio_descriptors = true; + host->max_native_cs = SPI_NUM_CHIPSELECTS; + host->bus_num = pdev->id; + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; + host->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); + host->max_speed_hz = max_freq; + host->transfer_one = spi_qup_transfer_one; + host->dev.of_node = pdev->dev.of_node; + host->auto_runtime_pm = true; + host->dma_alignment = dma_get_cache_alignment(); + host->max_dma_len = SPI_MAX_XFER; - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); - controller = spi_master_get_devdata(master); + controller = spi_controller_get_devdata(host); controller->dev = dev; controller->base = base; @@ -1063,16 +1062,16 @@ static int spi_qup_probe(struct platform_device *pdev) controller->cclk = cclk; controller->irq = irq; - ret = spi_qup_init_dma(master, res->start); + ret = spi_qup_init_dma(host, res->start); if (ret == -EPROBE_DEFER) goto error; else if (!ret) - master->can_dma = spi_qup_can_dma; + host->can_dma = spi_qup_can_dma; controller->qup_v1 = (uintptr_t)of_device_get_match_data(dev); if (!controller->qup_v1) - master->set_cs = spi_qup_set_cs; + host->set_cs = spi_qup_set_cs; spin_lock_init(&controller->lock); init_completion(&controller->done); @@ -1150,7 +1149,7 @@ static int spi_qup_probe(struct platform_device *pdev) pm_runtime_set_active(dev); pm_runtime_enable(dev); - ret = devm_spi_register_master(dev, master); + ret = devm_spi_register_controller(dev, host); if (ret) goto disable_pm; @@ -1162,17 +1161,17 @@ error_clk: clk_disable_unprepare(cclk); clk_disable_unprepare(iclk); error_dma: - spi_qup_release_dma(master); + spi_qup_release_dma(host); error: - spi_master_put(master); + spi_controller_put(host); return ret; } #ifdef CONFIG_PM static int spi_qup_pm_suspend_runtime(struct device *device) { - struct spi_master *master = dev_get_drvdata(device); - struct spi_qup *controller = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(device); + struct spi_qup *controller = spi_controller_get_devdata(host); u32 config; /* Enable clocks auto gaiting */ @@ -1188,8 +1187,8 @@ static int spi_qup_pm_suspend_runtime(struct device *device) static int spi_qup_pm_resume_runtime(struct device *device) { - struct spi_master *master = dev_get_drvdata(device); - struct spi_qup *controller = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(device); + struct spi_qup *controller = spi_controller_get_devdata(host); u32 config; int ret; @@ -1214,8 +1213,8 @@ static int spi_qup_pm_resume_runtime(struct device *device) #ifdef CONFIG_PM_SLEEP static int spi_qup_suspend(struct device *device) { - struct spi_master *master = dev_get_drvdata(device); - struct spi_qup *controller = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(device); + struct spi_qup *controller = spi_controller_get_devdata(host); int ret; if (pm_runtime_suspended(device)) { @@ -1223,7 +1222,7 @@ static int spi_qup_suspend(struct device *device) if (ret) return ret; } - ret = spi_master_suspend(master); + ret = spi_controller_suspend(host); if (ret) return ret; @@ -1238,8 +1237,8 @@ static int spi_qup_suspend(struct device *device) static int spi_qup_resume(struct device *device) { - struct spi_master *master = dev_get_drvdata(device); - struct spi_qup *controller = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(device); + struct spi_qup *controller = spi_controller_get_devdata(host); int ret; ret = clk_prepare_enable(controller->iclk); @@ -1256,7 +1255,7 @@ static int spi_qup_resume(struct device *device) if (ret) goto disable_clk; - ret = spi_master_resume(master); + ret = spi_controller_resume(host); if (ret) goto disable_clk; @@ -1271,8 +1270,8 @@ disable_clk: static void spi_qup_remove(struct platform_device *pdev) { - struct spi_master *master = dev_get_drvdata(&pdev->dev); - struct spi_qup *controller = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(&pdev->dev); + struct spi_qup *controller = spi_controller_get_devdata(host); int ret; ret = pm_runtime_get_sync(&pdev->dev); @@ -1290,7 +1289,7 @@ static void spi_qup_remove(struct platform_device *pdev) ERR_PTR(ret)); } - spi_qup_release_dma(master); + spi_qup_release_dma(host); pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); diff --git a/drivers/spi/spi-rb4xx.c b/drivers/spi/spi-rb4xx.c index 5073736d3d1f..225f75550780 100644 --- a/drivers/spi/spi-rb4xx.c +++ b/drivers/spi/spi-rb4xx.c @@ -80,7 +80,7 @@ static void do_spi_byte_two(struct rb4xx_spi *rbspi, u32 spi_ioc, u8 byte) static void rb4xx_set_cs(struct spi_device *spi, bool enable) { - struct rb4xx_spi *rbspi = spi_master_get_devdata(spi->master); + struct rb4xx_spi *rbspi = spi_controller_get_devdata(spi->controller); /* * Setting CS is done along with bitbanging the actual values, @@ -92,10 +92,10 @@ static void rb4xx_set_cs(struct spi_device *spi, bool enable) AR71XX_SPI_IOC_CS0 | AR71XX_SPI_IOC_CS1); } -static int rb4xx_transfer_one(struct spi_master *master, +static int rb4xx_transfer_one(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *t) { - struct rb4xx_spi *rbspi = spi_master_get_devdata(master); + struct rb4xx_spi *rbspi = spi_controller_get_devdata(host); int i; u32 spi_ioc; u8 *rx_buf; @@ -126,14 +126,14 @@ static int rb4xx_transfer_one(struct spi_master *master, continue; rx_buf[i] = rb4xx_read(rbspi, AR71XX_SPI_REG_RDS); } - spi_finalize_current_transfer(master); + spi_finalize_current_transfer(host); return 0; } static int rb4xx_spi_probe(struct platform_device *pdev) { - struct spi_master *master; + struct spi_controller *host; struct clk *ahb_clk; struct rb4xx_spi *rbspi; int err; @@ -143,31 +143,31 @@ static int rb4xx_spi_probe(struct platform_device *pdev) if (IS_ERR(spi_base)) return PTR_ERR(spi_base); - master = devm_spi_alloc_master(&pdev->dev, sizeof(*rbspi)); - if (!master) + host = devm_spi_alloc_host(&pdev->dev, sizeof(*rbspi)); + if (!host) return -ENOMEM; ahb_clk = devm_clk_get(&pdev->dev, "ahb"); if (IS_ERR(ahb_clk)) return PTR_ERR(ahb_clk); - master->dev.of_node = pdev->dev.of_node; - master->bus_num = 0; - master->num_chipselect = 3; - master->mode_bits = SPI_TX_DUAL; - master->bits_per_word_mask = SPI_BPW_MASK(8); - master->flags = SPI_MASTER_MUST_TX; - master->transfer_one = rb4xx_transfer_one; - master->set_cs = rb4xx_set_cs; + host->dev.of_node = pdev->dev.of_node; + host->bus_num = 0; + host->num_chipselect = 3; + host->mode_bits = SPI_TX_DUAL; + host->bits_per_word_mask = SPI_BPW_MASK(8); + host->flags = SPI_CONTROLLER_MUST_TX; + host->transfer_one = rb4xx_transfer_one; + host->set_cs = rb4xx_set_cs; - rbspi = spi_master_get_devdata(master); + rbspi = spi_controller_get_devdata(host); rbspi->base = spi_base; rbspi->clk = ahb_clk; platform_set_drvdata(pdev, rbspi); - err = devm_spi_register_master(&pdev->dev, master); + err = devm_spi_register_controller(&pdev->dev, host); if (err) { - dev_err(&pdev->dev, "failed to register SPI master\n"); + dev_err(&pdev->dev, "failed to register SPI host\n"); return err; } diff --git a/drivers/spi/spi-realtek-rtl.c b/drivers/spi/spi-realtek-rtl.c index 866b0477dbd7..0b0123e20b54 100644 --- a/drivers/spi/spi-realtek-rtl.c +++ b/drivers/spi/spi-realtek-rtl.c @@ -153,7 +153,7 @@ static int realtek_rtl_spi_probe(struct platform_device *pdev) struct rtspi *rtspi; int err; - ctrl = devm_spi_alloc_master(&pdev->dev, sizeof(*rtspi)); + ctrl = devm_spi_alloc_host(&pdev->dev, sizeof(*rtspi)); if (!ctrl) { dev_err(&pdev->dev, "Error allocating SPI controller\n"); return -ENOMEM; diff --git a/drivers/spi/spi-rockchip-sfc.c b/drivers/spi/spi-rockchip-sfc.c index 583f4187f030..0d7fadcd4ed3 100644 --- a/drivers/spi/spi-rockchip-sfc.c +++ b/drivers/spi/spi-rockchip-sfc.c @@ -487,7 +487,7 @@ static int rockchip_sfc_xfer_done(struct rockchip_sfc *sfc, u32 timeout_us) static int rockchip_sfc_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) { - struct rockchip_sfc *sfc = spi_master_get_devdata(mem->spi->master); + struct rockchip_sfc *sfc = spi_controller_get_devdata(mem->spi->controller); u32 len = op->data.nbytes; int ret; @@ -523,7 +523,7 @@ static int rockchip_sfc_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op static int rockchip_sfc_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) { - struct rockchip_sfc *sfc = spi_master_get_devdata(mem->spi->master); + struct rockchip_sfc *sfc = spi_controller_get_devdata(mem->spi->controller); op->data.nbytes = min(op->data.nbytes, sfc->max_iosize); @@ -557,22 +557,22 @@ static irqreturn_t rockchip_sfc_irq_handler(int irq, void *dev_id) static int rockchip_sfc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct spi_master *master; + struct spi_controller *host; struct rockchip_sfc *sfc; int ret; - master = devm_spi_alloc_master(&pdev->dev, sizeof(*sfc)); - if (!master) + host = devm_spi_alloc_host(&pdev->dev, sizeof(*sfc)); + if (!host) return -ENOMEM; - master->flags = SPI_MASTER_HALF_DUPLEX; - master->mem_ops = &rockchip_sfc_mem_ops; - master->dev.of_node = pdev->dev.of_node; - master->mode_bits = SPI_TX_QUAD | SPI_TX_DUAL | SPI_RX_QUAD | SPI_RX_DUAL; - master->max_speed_hz = SFC_MAX_SPEED; - master->num_chipselect = SFC_MAX_CHIPSELECT_NUM; + host->flags = SPI_CONTROLLER_HALF_DUPLEX; + host->mem_ops = &rockchip_sfc_mem_ops; + host->dev.of_node = pdev->dev.of_node; + host->mode_bits = SPI_TX_QUAD | SPI_TX_DUAL | SPI_RX_QUAD | SPI_RX_DUAL; + host->max_speed_hz = SFC_MAX_SPEED; + host->num_chipselect = SFC_MAX_CHIPSELECT_NUM; - sfc = spi_master_get_devdata(master); + sfc = spi_controller_get_devdata(host); sfc->dev = dev; sfc->regbase = devm_platform_ioremap_resource(pdev, 0); @@ -640,7 +640,7 @@ static int rockchip_sfc_probe(struct platform_device *pdev) sfc->max_iosize = rockchip_sfc_get_max_iosize(sfc); sfc->version = rockchip_sfc_get_version(sfc); - ret = spi_register_master(master); + ret = spi_register_controller(host); if (ret) goto err_irq; @@ -656,10 +656,10 @@ err_hclk: static void rockchip_sfc_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); + struct spi_controller *host = platform_get_drvdata(pdev); struct rockchip_sfc *sfc = platform_get_drvdata(pdev); - spi_unregister_master(master); + spi_unregister_controller(host); clk_disable_unprepare(sfc->clk); clk_disable_unprepare(sfc->hclk); diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index 143ede958ac1..5b010094dace 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -104,8 +104,8 @@ #define CR0_XFM_RO 0x2 #define CR0_OPM_OFFSET 20 -#define CR0_OPM_MASTER 0x0 -#define CR0_OPM_SLAVE 0x1 +#define CR0_OPM_HOST 0x0 +#define CR0_OPM_TARGET 0x1 #define CR0_SOI_OFFSET 23 @@ -125,7 +125,7 @@ #define SR_TF_EMPTY (1 << 2) #define SR_RF_EMPTY (1 << 3) #define SR_RF_FULL (1 << 4) -#define SR_SLAVE_TX_BUSY (1 << 5) +#define SR_TARGET_TX_BUSY (1 << 5) /* Bit fields in ISR, IMR, ISR, RISR, 5bit */ #define INT_MASK 0x1f @@ -151,7 +151,7 @@ #define RXDMA (1 << 0) #define TXDMA (1 << 1) -/* sclk_out: spi master internal logic in rk3x can support 50Mhz */ +/* sclk_out: spi host internal logic in rk3x can support 50Mhz */ #define MAX_SCLK_OUT 50000000U /* @@ -194,8 +194,8 @@ struct rockchip_spi { bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM]; - bool slave_abort; - bool cs_inactive; /* spi slave tansmition stop when cs inactive */ + bool target_abort; + bool cs_inactive; /* spi target tansmition stop when cs inactive */ bool cs_high_supported; /* native CS supports active-high polarity */ struct spi_transfer *xfer; /* Store xfer temporarily */ @@ -206,13 +206,13 @@ static inline void spi_enable_chip(struct rockchip_spi *rs, bool enable) writel_relaxed((enable ? 1U : 0U), rs->regs + ROCKCHIP_SPI_SSIENR); } -static inline void wait_for_tx_idle(struct rockchip_spi *rs, bool slave_mode) +static inline void wait_for_tx_idle(struct rockchip_spi *rs, bool target_mode) { unsigned long timeout = jiffies + msecs_to_jiffies(5); do { - if (slave_mode) { - if (!(readl_relaxed(rs->regs + ROCKCHIP_SPI_SR) & SR_SLAVE_TX_BUSY) && + if (target_mode) { + if (!(readl_relaxed(rs->regs + ROCKCHIP_SPI_SR) & SR_TARGET_TX_BUSY) && !((readl_relaxed(rs->regs + ROCKCHIP_SPI_SR) & SR_BUSY))) return; } else { @@ -351,9 +351,9 @@ static irqreturn_t rockchip_spi_isr(int irq, void *dev_id) struct spi_controller *ctlr = dev_id; struct rockchip_spi *rs = spi_controller_get_devdata(ctlr); - /* When int_cs_inactive comes, spi slave abort */ + /* When int_cs_inactive comes, spi target abort */ if (rs->cs_inactive && readl_relaxed(rs->regs + ROCKCHIP_SPI_IMR) & INT_CS_INACTIVE) { - ctlr->slave_abort(ctlr); + ctlr->target_abort(ctlr); writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR); writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR); @@ -405,7 +405,7 @@ static void rockchip_spi_dma_rxcb(void *data) struct rockchip_spi *rs = spi_controller_get_devdata(ctlr); int state = atomic_fetch_andnot(RXDMA, &rs->state); - if (state & TXDMA && !rs->slave_abort) + if (state & TXDMA && !rs->target_abort) return; if (rs->cs_inactive) @@ -421,11 +421,11 @@ static void rockchip_spi_dma_txcb(void *data) struct rockchip_spi *rs = spi_controller_get_devdata(ctlr); int state = atomic_fetch_andnot(TXDMA, &rs->state); - if (state & RXDMA && !rs->slave_abort) + if (state & RXDMA && !rs->target_abort) return; /* Wait until the FIFO data completely. */ - wait_for_tx_idle(rs, ctlr->slave); + wait_for_tx_idle(rs, ctlr->target); spi_enable_chip(rs, false); spi_finalize_current_transfer(ctlr); @@ -525,7 +525,7 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs, static int rockchip_spi_config(struct rockchip_spi *rs, struct spi_device *spi, struct spi_transfer *xfer, - bool use_dma, bool slave_mode) + bool use_dma, bool target_mode) { u32 cr0 = CR0_FRF_SPI << CR0_FRF_OFFSET | CR0_BHT_8BIT << CR0_BHT_OFFSET @@ -534,9 +534,9 @@ static int rockchip_spi_config(struct rockchip_spi *rs, u32 cr1; u32 dmacr = 0; - if (slave_mode) - cr0 |= CR0_OPM_SLAVE << CR0_OPM_OFFSET; - rs->slave_abort = false; + if (target_mode) + cr0 |= CR0_OPM_TARGET << CR0_OPM_OFFSET; + rs->target_abort = false; cr0 |= rs->rsd << CR0_RSD_OFFSET; cr0 |= (spi->mode & 0x3U) << CR0_SCPH_OFFSET; @@ -614,7 +614,7 @@ static size_t rockchip_spi_max_transfer_size(struct spi_device *spi) return ROCKCHIP_SPI_MAX_TRANLEN; } -static int rockchip_spi_slave_abort(struct spi_controller *ctlr) +static int rockchip_spi_target_abort(struct spi_controller *ctlr) { struct rockchip_spi *rs = spi_controller_get_devdata(ctlr); u32 rx_fifo_left; @@ -659,7 +659,7 @@ out: dmaengine_terminate_sync(ctlr->dma_tx); atomic_set(&rs->state, 0); spi_enable_chip(rs, false); - rs->slave_abort = true; + rs->target_abort = true; spi_finalize_current_transfer(ctlr); return 0; @@ -697,7 +697,7 @@ static int rockchip_spi_transfer_one( rs->xfer = xfer; use_dma = ctlr->can_dma ? ctlr->can_dma(ctlr, spi, xfer) : false; - ret = rockchip_spi_config(rs, spi, xfer, use_dma, ctlr->slave); + ret = rockchip_spi_config(rs, spi, xfer, use_dma, ctlr->target); if (ret) return ret; @@ -757,15 +757,15 @@ static int rockchip_spi_probe(struct platform_device *pdev) struct resource *mem; struct device_node *np = pdev->dev.of_node; u32 rsd_nsecs, num_cs; - bool slave_mode; + bool target_mode; - slave_mode = of_property_read_bool(np, "spi-slave"); + target_mode = of_property_read_bool(np, "spi-slave"); - if (slave_mode) - ctlr = spi_alloc_slave(&pdev->dev, + if (target_mode) + ctlr = spi_alloc_target(&pdev->dev, sizeof(struct rockchip_spi)); else - ctlr = spi_alloc_master(&pdev->dev, + ctlr = spi_alloc_host(&pdev->dev, sizeof(struct rockchip_spi)); if (!ctlr) @@ -854,11 +854,11 @@ static int rockchip_spi_probe(struct platform_device *pdev) ctlr->auto_runtime_pm = true; ctlr->bus_num = pdev->id; ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP | SPI_LSB_FIRST; - if (slave_mode) { + if (target_mode) { ctlr->mode_bits |= SPI_NO_CS; - ctlr->slave_abort = rockchip_spi_slave_abort; + ctlr->target_abort = rockchip_spi_target_abort; } else { - ctlr->flags = SPI_MASTER_GPIO_SS; + ctlr->flags = SPI_CONTROLLER_GPIO_SS; ctlr->max_native_cs = ROCKCHIP_SPI_MAX_CS_NUM; /* * rk spi0 has two native cs, spi1..5 one cs only @@ -911,7 +911,7 @@ static int rockchip_spi_probe(struct platform_device *pdev) case ROCKCHIP_SPI_VER2_TYPE2: rs->cs_high_supported = true; ctlr->mode_bits |= SPI_CS_HIGH; - if (ctlr->can_dma && slave_mode) + if (ctlr->can_dma && target_mode) rs->cs_inactive = true; else rs->cs_inactive = false; diff --git a/drivers/spi/spi-rpc-if.c b/drivers/spi/spi-rpc-if.c index 2f78124a1b59..e11146932828 100644 --- a/drivers/spi/spi-rpc-if.c +++ b/drivers/spi/spi-rpc-if.c @@ -134,7 +134,7 @@ static int rpcif_spi_probe(struct platform_device *pdev) struct rpcif *rpc; int error; - ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*rpc)); + ctlr = devm_spi_alloc_host(&pdev->dev, sizeof(*rpc)); if (!ctlr) return -ENOMEM; diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 08ceebbaf69b..8e81f1a8623f 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -19,7 +19,7 @@ #include <linux/clk.h> #include <linux/dmaengine.h> #include <linux/dma-mapping.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/pm_runtime.h> #include <linux/reset.h> #include <linux/sh_dma.h> @@ -1294,7 +1294,7 @@ static int rspi_probe(struct platform_device *pdev) const struct spi_ops *ops; unsigned long clksrc; - ctlr = spi_alloc_master(&pdev->dev, sizeof(struct rspi_data)); + ctlr = spi_alloc_host(&pdev->dev, sizeof(struct rspi_data)); if (ctlr == NULL) return -ENOMEM; @@ -1317,8 +1317,7 @@ static int rspi_probe(struct platform_device *pdev) rspi->ops = ops; rspi->ctlr = ctlr; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - rspi->addr = devm_ioremap_resource(&pdev->dev, res); + rspi->addr = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(rspi->addr)) { ret = PTR_ERR(rspi->addr); goto error1; diff --git a/drivers/spi/spi-rzv2m-csi.c b/drivers/spi/spi-rzv2m-csi.c index 14ad65da930d..d0f51b17aa7c 100644 --- a/drivers/spi/spi-rzv2m-csi.c +++ b/drivers/spi/spi-rzv2m-csi.c @@ -5,13 +5,17 @@ * Copyright (C) 2023 Renesas Electronics Corporation */ +#include <linux/bits.h> #include <linux/clk.h> #include <linux/count_zeros.h> #include <linux/interrupt.h> #include <linux/iopoll.h> +#include <linux/log2.h> #include <linux/platform_device.h> +#include <linux/property.h> #include <linux/reset.h> #include <linux/spi/spi.h> +#include <linux/units.h> /* Registers */ #define CSI_MODE 0x00 /* CSI mode control */ @@ -36,6 +40,7 @@ /* CSI_CLKSEL */ #define CSI_CLKSEL_CKP BIT(17) #define CSI_CLKSEL_DAP BIT(16) +#define CSI_CLKSEL_MODE (CSI_CLKSEL_CKP|CSI_CLKSEL_DAP) #define CSI_CLKSEL_SLAVE BIT(15) #define CSI_CLKSEL_CKS GENMASK(14, 1) @@ -60,17 +65,22 @@ /* CSI_FIFOTRG */ #define CSI_FIFOTRG_R_TRG GENMASK(2, 0) -#define CSI_FIFO_SIZE_BYTES 32 -#define CSI_FIFO_HALF_SIZE 16 +#define CSI_FIFO_SIZE_BYTES 32U +#define CSI_FIFO_HALF_SIZE 16U #define CSI_EN_DIS_TIMEOUT_US 100 -#define CSI_CKS_MAX 0x3FFF +/* + * Clock "csiclk" gets divided by 2 * CSI_CLKSEL_CKS in order to generate the + * serial clock (output from master), with CSI_CLKSEL_CKS ranging from 0x1 (that + * means "csiclk" is divided by 2) to 0x3FFF ("csiclk" is divided by 32766). + */ +#define CSI_CKS_MAX GENMASK(13, 0) #define UNDERRUN_ERROR BIT(0) #define OVERFLOW_ERROR BIT(1) #define TX_TIMEOUT_ERROR BIT(2) #define RX_TIMEOUT_ERROR BIT(3) -#define CSI_MAX_SPI_SCKO 8000000 +#define CSI_MAX_SPI_SCKO (8 * HZ_PER_MHZ) struct rzv2m_csi_priv { void __iomem *base; @@ -78,33 +88,19 @@ struct rzv2m_csi_priv { struct clk *pclk; struct device *dev; struct spi_controller *controller; - const u8 *txbuf; - u8 *rxbuf; - int buffer_len; - int bytes_sent; - int bytes_received; - int bytes_to_transfer; - int words_to_transfer; - unsigned char bytes_per_word; + const void *txbuf; + void *rxbuf; + unsigned int buffer_len; + unsigned int bytes_sent; + unsigned int bytes_received; + unsigned int bytes_to_transfer; + unsigned int words_to_transfer; + unsigned int bytes_per_word; wait_queue_head_t wait; - u8 errors; + u32 errors; u32 status; }; -static const unsigned char x_trg[] = { - 0, 1, 1, 2, 2, 2, 2, 3, - 3, 3, 3, 3, 3, 3, 3, 4, - 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 5 -}; - -static const unsigned char x_trg_words[] = { - 1, 2, 2, 4, 4, 4, 4, 8, - 8, 8, 8, 8, 8, 8, 8, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 32 -}; - static void rzv2m_csi_reg_write_bit(const struct rzv2m_csi_priv *csi, int reg_offs, int bit_mask, u32 value) { @@ -124,13 +120,12 @@ static int rzv2m_csi_sw_reset(struct rzv2m_csi_priv *csi, int assert) rzv2m_csi_reg_write_bit(csi, CSI_CNT, CSI_CNT_CSIRST, assert); - if (assert) { - return readl_poll_timeout(csi->base + CSI_MODE, reg, - !(reg & CSI_MODE_CSOT), 0, - CSI_EN_DIS_TIMEOUT_US); - } + if (!assert) + return 0; - return 0; + return readl_poll_timeout(csi->base + CSI_MODE, reg, + !(reg & CSI_MODE_CSOT), 0, + CSI_EN_DIS_TIMEOUT_US); } static int rzv2m_csi_start_stop_operation(const struct rzv2m_csi_priv *csi, @@ -140,28 +135,28 @@ static int rzv2m_csi_start_stop_operation(const struct rzv2m_csi_priv *csi, rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_CSIE, enable); - if (!enable && wait) - return readl_poll_timeout(csi->base + CSI_MODE, reg, - !(reg & CSI_MODE_CSOT), 0, - CSI_EN_DIS_TIMEOUT_US); + if (enable || !wait) + return 0; - return 0; + return readl_poll_timeout(csi->base + CSI_MODE, reg, + !(reg & CSI_MODE_CSOT), 0, + CSI_EN_DIS_TIMEOUT_US); } static int rzv2m_csi_fill_txfifo(struct rzv2m_csi_priv *csi) { - int i; + unsigned int i; if (readl(csi->base + CSI_OFIFOL)) return -EIO; if (csi->bytes_per_word == 2) { - u16 *buf = (u16 *)csi->txbuf; + const u16 *buf = csi->txbuf; for (i = 0; i < csi->words_to_transfer; i++) writel(buf[i], csi->base + CSI_OFIFO); } else { - u8 *buf = (u8 *)csi->txbuf; + const u8 *buf = csi->txbuf; for (i = 0; i < csi->words_to_transfer; i++) writel(buf[i], csi->base + CSI_OFIFO); @@ -175,18 +170,18 @@ static int rzv2m_csi_fill_txfifo(struct rzv2m_csi_priv *csi) static int rzv2m_csi_read_rxfifo(struct rzv2m_csi_priv *csi) { - int i; + unsigned int i; if (readl(csi->base + CSI_IFIFOL) != csi->bytes_to_transfer) return -EIO; if (csi->bytes_per_word == 2) { - u16 *buf = (u16 *)csi->rxbuf; + u16 *buf = csi->rxbuf; for (i = 0; i < csi->words_to_transfer; i++) buf[i] = (u16)readl(csi->base + CSI_IFIFO); } else { - u8 *buf = (u8 *)csi->rxbuf; + u8 *buf = csi->rxbuf; for (i = 0; i < csi->words_to_transfer; i++) buf[i] = (u8)readl(csi->base + CSI_IFIFO); @@ -200,9 +195,9 @@ static int rzv2m_csi_read_rxfifo(struct rzv2m_csi_priv *csi) static inline void rzv2m_csi_calc_current_transfer(struct rzv2m_csi_priv *csi) { - int bytes_transferred = max_t(int, csi->bytes_received, csi->bytes_sent); - int bytes_remaining = csi->buffer_len - bytes_transferred; - int to_transfer; + unsigned int bytes_transferred = max(csi->bytes_received, csi->bytes_sent); + unsigned int bytes_remaining = csi->buffer_len - bytes_transferred; + unsigned int to_transfer; if (csi->txbuf) /* @@ -210,9 +205,9 @@ static inline void rzv2m_csi_calc_current_transfer(struct rzv2m_csi_priv *csi) * hard to raise an overflow error (which is only possible * when IP transmits and receives at the same time). */ - to_transfer = min_t(int, CSI_FIFO_HALF_SIZE, bytes_remaining); + to_transfer = min(CSI_FIFO_HALF_SIZE, bytes_remaining); else - to_transfer = min_t(int, CSI_FIFO_SIZE_BYTES, bytes_remaining); + to_transfer = min(CSI_FIFO_SIZE_BYTES, bytes_remaining); if (csi->bytes_per_word == 2) to_transfer >>= 1; @@ -223,7 +218,7 @@ static inline void rzv2m_csi_calc_current_transfer(struct rzv2m_csi_priv *csi) * less than or equal to the number of bytes we need to transfer. * This may result in multiple smaller transfers. */ - csi->words_to_transfer = x_trg_words[to_transfer - 1]; + csi->words_to_transfer = rounddown_pow_of_two(to_transfer); if (csi->bytes_per_word == 2) csi->bytes_to_transfer = csi->words_to_transfer << 1; @@ -234,7 +229,7 @@ static inline void rzv2m_csi_calc_current_transfer(struct rzv2m_csi_priv *csi) static inline void rzv2m_csi_set_rx_fifo_trigger_level(struct rzv2m_csi_priv *csi) { rzv2m_csi_reg_write_bit(csi, CSI_FIFOTRG, CSI_FIFOTRG_R_TRG, - x_trg[csi->words_to_transfer - 1]); + ilog2(csi->words_to_transfer)); } static inline void rzv2m_csi_enable_rx_trigger(struct rzv2m_csi_priv *csi, @@ -307,7 +302,6 @@ static int rzv2m_csi_wait_for_tx_empty(struct rzv2m_csi_priv *csi) return 0; ret = rzv2m_csi_wait_for_interrupt(csi, CSI_INT_TREND, CSI_CNT_TREND_E); - if (ret == -ETIMEDOUT) csi->errors |= TX_TIMEOUT_ERROR; @@ -323,7 +317,6 @@ static inline int rzv2m_csi_wait_for_rx_ready(struct rzv2m_csi_priv *csi) ret = rzv2m_csi_wait_for_interrupt(csi, CSI_INT_R_TRGR, CSI_CNT_R_TRGR_E); - if (ret == -ETIMEDOUT) csi->errors |= RX_TIMEOUT_ERROR; @@ -332,7 +325,7 @@ static inline int rzv2m_csi_wait_for_rx_ready(struct rzv2m_csi_priv *csi) static irqreturn_t rzv2m_csi_irq_handler(int irq, void *data) { - struct rzv2m_csi_priv *csi = (struct rzv2m_csi_priv *)data; + struct rzv2m_csi_priv *csi = data; csi->status = readl(csi->base + CSI_INT); rzv2m_csi_disable_irqs(csi, csi->status); @@ -402,10 +395,8 @@ static int rzv2m_csi_setup(struct spi_device *spi) writel(CSI_MODE_SETUP, csi->base + CSI_MODE); /* Setup clock polarity and phase timing */ - rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_CKP, - !(spi->mode & SPI_CPOL)); - rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_DAP, - !(spi->mode & SPI_CPHA)); + rzv2m_csi_reg_write_bit(csi, CSI_CLKSEL, CSI_CLKSEL_MODE, + ~spi->mode & SPI_MODE_X_MASK); /* Setup serial data order */ rzv2m_csi_reg_write_bit(csi, CSI_MODE, CSI_MODE_DIR, @@ -433,8 +424,8 @@ static int rzv2m_csi_setup(struct spi_device *spi) static int rzv2m_csi_pio_transfer(struct rzv2m_csi_priv *csi) { - bool tx_completed = csi->txbuf ? false : true; - bool rx_completed = csi->rxbuf ? false : true; + bool tx_completed = !csi->txbuf; + bool rx_completed = !csi->rxbuf; int ret = 0; /* Make sure the TX FIFO is empty */ @@ -564,7 +555,7 @@ static int rzv2m_csi_probe(struct platform_device *pdev) int irq; int ret; - controller = devm_spi_alloc_master(dev, sizeof(*csi)); + controller = devm_spi_alloc_host(dev, sizeof(*csi)); if (!controller) return -ENOMEM; @@ -599,12 +590,13 @@ static int rzv2m_csi_probe(struct platform_device *pdev) init_waitqueue_head(&csi->wait); controller->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST; - controller->dev.of_node = pdev->dev.of_node; controller->bits_per_word_mask = SPI_BPW_MASK(16) | SPI_BPW_MASK(8); controller->setup = rzv2m_csi_setup; controller->transfer_one = rzv2m_csi_transfer_one; controller->use_gpio_descriptors = true; + device_set_node(&controller->dev, dev_fwnode(dev)); + ret = devm_request_irq(dev, irq, rzv2m_csi_irq_handler, 0, dev_name(dev), csi); if (ret) @@ -635,15 +627,13 @@ static int rzv2m_csi_probe(struct platform_device *pdev) return 0; } -static int rzv2m_csi_remove(struct platform_device *pdev) +static void rzv2m_csi_remove(struct platform_device *pdev) { struct rzv2m_csi_priv *csi = platform_get_drvdata(pdev); spi_unregister_controller(csi->controller); rzv2m_csi_sw_reset(csi, 1); clk_disable_unprepare(csi->csiclk); - - return 0; } static const struct of_device_id rzv2m_csi_match[] = { @@ -654,7 +644,7 @@ MODULE_DEVICE_TABLE(of, rzv2m_csi_match); static struct platform_driver rzv2m_csi_drv = { .probe = rzv2m_csi_probe, - .remove = rzv2m_csi_remove, + .remove_new = rzv2m_csi_remove, .driver = { .name = "rzv2m_csi", .of_match_table = rzv2m_csi_match, diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index b6c2659a66ca..0e48ffd499b9 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -14,7 +14,6 @@ #include <linux/pm_runtime.h> #include <linux/spi/spi.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_data/spi-s3c64xx.h> @@ -164,9 +163,9 @@ struct s3c64xx_spi_port_config { * struct s3c64xx_spi_driver_data - Runtime info holder for SPI driver. * @clk: Pointer to the spi clock. * @src_clk: Pointer to the clock used to generate SPI signals. - * @ioclk: Pointer to the i/o clock between master and slave + * @ioclk: Pointer to the i/o clock between host and target * @pdev: Pointer to device's platform device data - * @master: Pointer to the SPI Protocol master. + * @host: Pointer to the SPI Protocol host. * @cntrlr_info: Platform specific data for the controller this driver manages. * @lock: Controller specific lock. * @state: Set of FLAGS to indicate status. @@ -187,7 +186,7 @@ struct s3c64xx_spi_driver_data { struct clk *src_clk; struct clk *ioclk; struct platform_device *pdev; - struct spi_master *master; + struct spi_controller *host; struct s3c64xx_spi_info *cntrlr_info; spinlock_t lock; unsigned long sfr_start; @@ -330,7 +329,7 @@ static int prepare_dma(struct s3c64xx_spi_dma_data *dma, static void s3c64xx_spi_set_cs(struct spi_device *spi, bool enable) { struct s3c64xx_spi_driver_data *sdd = - spi_master_get_devdata(spi->master); + spi_controller_get_devdata(spi->controller); if (sdd->cntrlr_info->no_cs) return; @@ -352,9 +351,9 @@ static void s3c64xx_spi_set_cs(struct spi_device *spi, bool enable) } } -static int s3c64xx_spi_prepare_transfer(struct spi_master *spi) +static int s3c64xx_spi_prepare_transfer(struct spi_controller *spi) { - struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi); + struct s3c64xx_spi_driver_data *sdd = spi_controller_get_devdata(spi); if (is_polling(sdd)) return 0; @@ -382,9 +381,9 @@ static int s3c64xx_spi_prepare_transfer(struct spi_master *spi) return 0; } -static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi) +static int s3c64xx_spi_unprepare_transfer(struct spi_controller *spi) { - struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(spi); + struct s3c64xx_spi_driver_data *sdd = spi_controller_get_devdata(spi); if (is_polling(sdd)) return 0; @@ -400,11 +399,11 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi) return 0; } -static bool s3c64xx_spi_can_dma(struct spi_master *master, +static bool s3c64xx_spi_can_dma(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { - struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); + struct s3c64xx_spi_driver_data *sdd = spi_controller_get_devdata(host); if (sdd->rx_dma.ch && sdd->tx_dma.ch) { return xfer->len > (FIFO_LVL_MASK(sdd) >> 1) + 1; @@ -713,10 +712,10 @@ static int s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) #define XFER_DMAADDR_INVALID DMA_BIT_MASK(32) -static int s3c64xx_spi_prepare_message(struct spi_master *master, +static int s3c64xx_spi_prepare_message(struct spi_controller *host, struct spi_message *msg) { - struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); + struct s3c64xx_spi_driver_data *sdd = spi_controller_get_devdata(host); struct spi_device *spi = msg->spi; struct s3c64xx_spi_csinfo *cs = spi->controller_data; @@ -737,11 +736,11 @@ static size_t s3c64xx_spi_max_transfer_size(struct spi_device *spi) return ctlr->can_dma ? S3C64XX_SPI_PACKET_CNT_MASK : SIZE_MAX; } -static int s3c64xx_spi_transfer_one(struct spi_master *master, +static int s3c64xx_spi_transfer_one(struct spi_controller *host, struct spi_device *spi, struct spi_transfer *xfer) { - struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); + struct s3c64xx_spi_driver_data *sdd = spi_controller_get_devdata(host); const unsigned int fifo_len = (FIFO_LVL_MASK(sdd) >> 1) + 1; const void *tx_buf = NULL; void *rx_buf = NULL; @@ -891,15 +890,15 @@ static int s3c64xx_spi_transfer_one(struct spi_master *master, return status; } -static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata( +static struct s3c64xx_spi_csinfo *s3c64xx_get_target_ctrldata( struct spi_device *spi) { struct s3c64xx_spi_csinfo *cs; - struct device_node *slave_np, *data_np = NULL; + struct device_node *target_np, *data_np = NULL; u32 fb_delay = 0; - slave_np = spi->dev.of_node; - if (!slave_np) { + target_np = spi->dev.of_node; + if (!target_np) { dev_err(&spi->dev, "device node not found\n"); return ERR_PTR(-EINVAL); } @@ -908,7 +907,7 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata( if (!cs) return ERR_PTR(-ENOMEM); - data_np = of_get_child_by_name(slave_np, "controller-data"); + data_np = of_get_child_by_name(target_np, "controller-data"); if (!data_np) { dev_info(&spi->dev, "feedback delay set to default (0)\n"); return cs; @@ -933,9 +932,9 @@ static int s3c64xx_spi_setup(struct spi_device *spi) int err; int div; - sdd = spi_master_get_devdata(spi->master); + sdd = spi_controller_get_devdata(spi->controller); if (spi->dev.of_node) { - cs = s3c64xx_get_slave_ctrldata(spi); + cs = s3c64xx_get_target_ctrldata(spi); spi->controller_data = cs; } @@ -1023,7 +1022,7 @@ static void s3c64xx_spi_cleanup(struct spi_device *spi) static irqreturn_t s3c64xx_spi_irq(int irq, void *data) { struct s3c64xx_spi_driver_data *sdd = data; - struct spi_master *spi = sdd->master; + struct spi_controller *spi = sdd->host; unsigned int val, clr = 0; val = readl(sdd->regs + S3C64XX_SPI_STATUS); @@ -1152,7 +1151,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) struct resource *mem_res; struct s3c64xx_spi_driver_data *sdd; struct s3c64xx_spi_info *sci = dev_get_platdata(&pdev->dev); - struct spi_master *master; + struct spi_controller *host; int ret, irq; char clk_name[16]; @@ -1166,28 +1165,22 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, -ENODEV, "Platform_data missing!\n"); - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem_res) - return dev_err_probe(&pdev->dev, -ENXIO, - "Unable to get SPI MEM resource\n"); - irq = platform_get_irq(pdev, 0); if (irq < 0) - return dev_err_probe(&pdev->dev, irq, "Failed to get IRQ\n"); + return irq; - master = devm_spi_alloc_master(&pdev->dev, sizeof(*sdd)); - if (!master) + host = devm_spi_alloc_host(&pdev->dev, sizeof(*sdd)); + if (!host) return dev_err_probe(&pdev->dev, -ENOMEM, - "Unable to allocate SPI Master\n"); + "Unable to allocate SPI Host\n"); - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); - sdd = spi_master_get_devdata(master); + sdd = spi_controller_get_devdata(host); sdd->port_conf = s3c64xx_spi_get_port_config(pdev); - sdd->master = master; + sdd->host = host; sdd->cntrlr_info = sci; sdd->pdev = pdev; - sdd->sfr_start = mem_res->start; if (pdev->dev.of_node) { ret = of_alias_get_id(pdev->dev.of_node, "spi"); if (ret < 0) @@ -1203,31 +1196,32 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) sdd->tx_dma.direction = DMA_MEM_TO_DEV; sdd->rx_dma.direction = DMA_DEV_TO_MEM; - master->dev.of_node = pdev->dev.of_node; - master->bus_num = sdd->port_id; - master->setup = s3c64xx_spi_setup; - master->cleanup = s3c64xx_spi_cleanup; - master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; - master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer; - master->prepare_message = s3c64xx_spi_prepare_message; - master->transfer_one = s3c64xx_spi_transfer_one; - master->max_transfer_size = s3c64xx_spi_max_transfer_size; - master->num_chipselect = sci->num_cs; - master->use_gpio_descriptors = true; - master->dma_alignment = 8; - master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) | - SPI_BPW_MASK(8); + host->dev.of_node = pdev->dev.of_node; + host->bus_num = sdd->port_id; + host->setup = s3c64xx_spi_setup; + host->cleanup = s3c64xx_spi_cleanup; + host->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; + host->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer; + host->prepare_message = s3c64xx_spi_prepare_message; + host->transfer_one = s3c64xx_spi_transfer_one; + host->max_transfer_size = s3c64xx_spi_max_transfer_size; + host->num_chipselect = sci->num_cs; + host->use_gpio_descriptors = true; + host->dma_alignment = 8; + host->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) | + SPI_BPW_MASK(8); /* the spi->mode bits understood by this driver: */ - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; if (sdd->port_conf->has_loopback) - master->mode_bits |= SPI_LOOP; - master->auto_runtime_pm = true; + host->mode_bits |= SPI_LOOP; + host->auto_runtime_pm = true; if (!is_polling(sdd)) - master->can_dma = s3c64xx_spi_can_dma; + host->can_dma = s3c64xx_spi_can_dma; - sdd->regs = devm_ioremap_resource(&pdev->dev, mem_res); + sdd->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &mem_res); if (IS_ERR(sdd->regs)) return PTR_ERR(sdd->regs); + sdd->sfr_start = mem_res->start; if (sci->cfg_gpio && sci->cfg_gpio()) return dev_err_probe(&pdev->dev, -EBUSY, @@ -1277,14 +1271,14 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) S3C64XX_SPI_INT_TX_OVERRUN_EN | S3C64XX_SPI_INT_TX_UNDERRUN_EN, sdd->regs + S3C64XX_SPI_INT_EN); - ret = devm_spi_register_master(&pdev->dev, master); + ret = devm_spi_register_controller(&pdev->dev, host); if (ret != 0) { - dev_err(&pdev->dev, "cannot register SPI master: %d\n", ret); + dev_err(&pdev->dev, "cannot register SPI host: %d\n", ret); goto err_pm_put; } - dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d with %d Slaves attached\n", - sdd->port_id, master->num_chipselect); + dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d with %d Targets attached\n", + sdd->port_id, host->num_chipselect); dev_dbg(&pdev->dev, "\tIOmem=[%pR]\tFIFO %dbytes\n", mem_res, (FIFO_LVL_MASK(sdd) >> 1) + 1); @@ -1303,8 +1297,8 @@ err_pm_put: static void s3c64xx_spi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(pdev); + struct s3c64xx_spi_driver_data *sdd = spi_controller_get_devdata(host); pm_runtime_get_sync(&pdev->dev); @@ -1323,10 +1317,10 @@ static void s3c64xx_spi_remove(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP static int s3c64xx_spi_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct s3c64xx_spi_driver_data *sdd = spi_controller_get_devdata(host); - int ret = spi_master_suspend(master); + int ret = spi_controller_suspend(host); if (ret) return ret; @@ -1341,8 +1335,8 @@ static int s3c64xx_spi_suspend(struct device *dev) static int s3c64xx_spi_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct s3c64xx_spi_driver_data *sdd = spi_controller_get_devdata(host); struct s3c64xx_spi_info *sci = sdd->cntrlr_info; int ret; @@ -1353,15 +1347,15 @@ static int s3c64xx_spi_resume(struct device *dev) if (ret < 0) return ret; - return spi_master_resume(master); + return spi_controller_resume(host); } #endif /* CONFIG_PM_SLEEP */ #ifdef CONFIG_PM static int s3c64xx_spi_runtime_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct s3c64xx_spi_driver_data *sdd = spi_controller_get_devdata(host); clk_disable_unprepare(sdd->clk); clk_disable_unprepare(sdd->src_clk); @@ -1372,8 +1366,8 @@ static int s3c64xx_spi_runtime_suspend(struct device *dev) static int s3c64xx_spi_runtime_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct s3c64xx_spi_driver_data *sdd = spi_controller_get_devdata(host); int ret; if (sdd->port_conf->clk_ioclk) { diff --git a/drivers/spi/spi-sc18is602.c b/drivers/spi/spi-sc18is602.c index d52ed67243f7..eecf9ea95ae3 100644 --- a/drivers/spi/spi-sc18is602.c +++ b/drivers/spi/spi-sc18is602.c @@ -12,7 +12,6 @@ #include <linux/i2c.h> #include <linux/delay.h> #include <linux/pm_runtime.h> -#include <linux/of_device.h> #include <linux/of.h> #include <linux/platform_data/sc18is602.h> #include <linux/gpio/consumer.h> @@ -31,7 +30,7 @@ enum chips { sc18is602, sc18is602b, sc18is603 }; #define SC18IS602_MODE_CLOCK_DIV_128 0x3 struct sc18is602 { - struct spi_master *master; + struct spi_controller *host; struct device *dev; u8 ctrl; u32 freq; @@ -180,10 +179,10 @@ static int sc18is602_check_transfer(struct spi_device *spi, return 0; } -static int sc18is602_transfer_one(struct spi_master *master, +static int sc18is602_transfer_one(struct spi_controller *host, struct spi_message *m) { - struct sc18is602 *hw = spi_master_get_devdata(master); + struct sc18is602 *hw = spi_controller_get_devdata(host); struct spi_device *spi = m->spi; struct spi_transfer *t; int status = 0; @@ -214,7 +213,7 @@ static int sc18is602_transfer_one(struct spi_master *master, spi_transfer_delay_exec(t); } m->status = status; - spi_finalize_current_message(master); + spi_finalize_current_message(host); return status; } @@ -226,7 +225,7 @@ static size_t sc18is602_max_transfer_size(struct spi_device *spi) static int sc18is602_setup(struct spi_device *spi) { - struct sc18is602 *hw = spi_master_get_devdata(spi->master); + struct sc18is602 *hw = spi_controller_get_devdata(spi->controller); /* SC18IS602 does not support CS2 */ if (hw->id == sc18is602 && (spi_get_chipselect(spi, 0) == 2)) @@ -242,17 +241,17 @@ static int sc18is602_probe(struct i2c_client *client) struct device_node *np = dev->of_node; struct sc18is602_platform_data *pdata = dev_get_platdata(dev); struct sc18is602 *hw; - struct spi_master *master; + struct spi_controller *host; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) return -EINVAL; - master = devm_spi_alloc_master(dev, sizeof(struct sc18is602)); - if (!master) + host = devm_spi_alloc_host(dev, sizeof(struct sc18is602)); + if (!host) return -ENOMEM; - hw = spi_master_get_devdata(master); + hw = spi_controller_get_devdata(host); i2c_set_clientdata(client, hw); /* assert reset and then release */ @@ -261,24 +260,24 @@ static int sc18is602_probe(struct i2c_client *client) return PTR_ERR(hw->reset); gpiod_set_value_cansleep(hw->reset, 0); - hw->master = master; + hw->host = host; hw->client = client; hw->dev = dev; hw->ctrl = 0xff; if (client->dev.of_node) - hw->id = (enum chips)of_device_get_match_data(&client->dev); + hw->id = (uintptr_t)of_device_get_match_data(&client->dev); else hw->id = id->driver_data; switch (hw->id) { case sc18is602: case sc18is602b: - master->num_chipselect = 4; + host->num_chipselect = 4; hw->freq = SC18IS602_CLOCK; break; case sc18is603: - master->num_chipselect = 2; + host->num_chipselect = 2; if (pdata) { hw->freq = pdata->clock_frequency; } else { @@ -293,18 +292,18 @@ static int sc18is602_probe(struct i2c_client *client) hw->freq = SC18IS602_CLOCK; break; } - master->bus_num = np ? -1 : client->adapter->nr; - master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST; - master->bits_per_word_mask = SPI_BPW_MASK(8); - master->setup = sc18is602_setup; - master->transfer_one_message = sc18is602_transfer_one; - master->max_transfer_size = sc18is602_max_transfer_size; - master->max_message_size = sc18is602_max_transfer_size; - master->dev.of_node = np; - master->min_speed_hz = hw->freq / 128; - master->max_speed_hz = hw->freq / 4; - - return devm_spi_register_master(dev, master); + host->bus_num = np ? -1 : client->adapter->nr; + host->mode_bits = SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST; + host->bits_per_word_mask = SPI_BPW_MASK(8); + host->setup = sc18is602_setup; + host->transfer_one_message = sc18is602_transfer_one; + host->max_transfer_size = sc18is602_max_transfer_size; + host->max_message_size = sc18is602_max_transfer_size; + host->dev.of_node = np; + host->min_speed_hz = hw->freq / 128; + host->max_speed_hz = hw->freq / 4; + + return devm_spi_register_controller(dev, host); } static const struct i2c_device_id sc18is602_id[] = { @@ -343,6 +342,6 @@ static struct i2c_driver sc18is602_driver = { module_i2c_driver(sc18is602_driver); -MODULE_DESCRIPTION("SC18IS602/603 SPI Master Driver"); +MODULE_DESCRIPTION("SC18IS602/603 SPI Host Driver"); MODULE_AUTHOR("Guenter Roeck"); MODULE_LICENSE("GPL"); diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c index d6ffeae66ed3..5d63aa1d28e2 100644 --- a/drivers/spi/spi-sh-hspi.c +++ b/drivers/spi/spi-sh-hspi.c @@ -82,7 +82,7 @@ static int hspi_status_check_timeout(struct hspi_priv *hspi, u32 mask, u32 val) } /* - * spi master function + * spi host function */ #define hspi_hw_cs_enable(hspi) hspi_hw_cs_ctrl(hspi, 0) @@ -224,7 +224,7 @@ static int hspi_probe(struct platform_device *pdev) return -EINVAL; } - ctlr = spi_alloc_master(&pdev->dev, sizeof(*hspi)); + ctlr = spi_alloc_host(&pdev->dev, sizeof(*hspi)); if (!ctlr) return -ENOMEM; diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index 9e90b4f8b357..fb452bc78372 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -20,7 +20,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/sh_dma.h> @@ -55,7 +54,7 @@ struct sh_msiof_spi_priv { dma_addr_t rx_dma_addr; bool native_cs_inited; bool native_cs_high; - bool slave_aborted; + bool target_aborted; }; #define MAX_SS 3 /* Maximum number of native chip selects */ @@ -362,7 +361,7 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p, u32 ss, tmp |= !cs_high << SIMDR1_SYNCAC_SHIFT; tmp |= lsb_first << SIMDR1_BITLSB_SHIFT; tmp |= sh_msiof_spi_get_dtdl_and_syncdl(p); - if (spi_controller_is_slave(p->ctlr)) { + if (spi_controller_is_target(p->ctlr)) { sh_msiof_write(p, SITMDR1, tmp | SITMDR1_PCON); } else { sh_msiof_write(p, SITMDR1, @@ -554,7 +553,7 @@ static int sh_msiof_spi_setup(struct spi_device *spi) spi_controller_get_devdata(spi->controller); u32 clr, set, tmp; - if (spi_get_csgpiod(spi, 0) || spi_controller_is_slave(p->ctlr)) + if (spi_get_csgpiod(spi, 0) || spi_controller_is_target(p->ctlr)) return 0; if (p->native_cs_inited && @@ -603,11 +602,11 @@ static int sh_msiof_prepare_message(struct spi_controller *ctlr, static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf) { - bool slave = spi_controller_is_slave(p->ctlr); + bool target = spi_controller_is_target(p->ctlr); int ret = 0; /* setup clock and rx/tx signals */ - if (!slave) + if (!target) ret = sh_msiof_modify_ctr_wait(p, 0, SICTR_TSCKE); if (rx_buf && !ret) ret = sh_msiof_modify_ctr_wait(p, 0, SICTR_RXE); @@ -615,7 +614,7 @@ static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf) ret = sh_msiof_modify_ctr_wait(p, 0, SICTR_TXE); /* start by setting frame bit */ - if (!ret && !slave) + if (!ret && !target) ret = sh_msiof_modify_ctr_wait(p, 0, SICTR_TFSE); return ret; @@ -623,27 +622,27 @@ static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf) static int sh_msiof_spi_stop(struct sh_msiof_spi_priv *p, void *rx_buf) { - bool slave = spi_controller_is_slave(p->ctlr); + bool target = spi_controller_is_target(p->ctlr); int ret = 0; /* shut down frame, rx/tx and clock signals */ - if (!slave) + if (!target) ret = sh_msiof_modify_ctr_wait(p, SICTR_TFSE, 0); if (!ret) ret = sh_msiof_modify_ctr_wait(p, SICTR_TXE, 0); if (rx_buf && !ret) ret = sh_msiof_modify_ctr_wait(p, SICTR_RXE, 0); - if (!ret && !slave) + if (!ret && !target) ret = sh_msiof_modify_ctr_wait(p, SICTR_TSCKE, 0); return ret; } -static int sh_msiof_slave_abort(struct spi_controller *ctlr) +static int sh_msiof_target_abort(struct spi_controller *ctlr) { struct sh_msiof_spi_priv *p = spi_controller_get_devdata(ctlr); - p->slave_aborted = true; + p->target_aborted = true; complete(&p->done); complete(&p->done_txdma); return 0; @@ -652,9 +651,9 @@ static int sh_msiof_slave_abort(struct spi_controller *ctlr) static int sh_msiof_wait_for_completion(struct sh_msiof_spi_priv *p, struct completion *x) { - if (spi_controller_is_slave(p->ctlr)) { + if (spi_controller_is_target(p->ctlr)) { if (wait_for_completion_interruptible(x) || - p->slave_aborted) { + p->target_aborted) { dev_dbg(&p->pdev->dev, "interrupted\n"); return -EINTR; } @@ -700,7 +699,7 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p, tx_fifo(p, tx_buf, words, fifo_shift); reinit_completion(&p->done); - p->slave_aborted = false; + p->target_aborted = false; ret = sh_msiof_spi_start(p, rx_buf); if (ret) { @@ -797,7 +796,7 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx, reinit_completion(&p->done); if (tx) reinit_completion(&p->done_txdma); - p->slave_aborted = false; + p->target_aborted = false; /* Now start DMA */ if (rx) @@ -926,7 +925,7 @@ static int sh_msiof_transfer_one(struct spi_controller *ctlr, sh_msiof_spi_reset_regs(p); /* setup clocks (clock already enabled in chipselect()) */ - if (!spi_controller_is_slave(p->ctlr)) + if (!spi_controller_is_target(p->ctlr)) sh_msiof_spi_set_clk_regs(p, t); while (ctlr->dma_tx && len > 15) { @@ -1102,11 +1101,11 @@ static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev) if (!info) return NULL; - info->mode = of_property_read_bool(np, "spi-slave") ? MSIOF_SPI_SLAVE - : MSIOF_SPI_MASTER; + info->mode = of_property_read_bool(np, "spi-slave") ? MSIOF_SPI_TARGET + : MSIOF_SPI_HOST; /* Parse the MSIOF properties */ - if (info->mode == MSIOF_SPI_MASTER) + if (info->mode == MSIOF_SPI_HOST) of_property_read_u32(np, "num-cs", &num_cs); of_property_read_u32(np, "renesas,tx-fifo-size", &info->tx_fifo_override); @@ -1280,12 +1279,12 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) return -ENXIO; } - if (info->mode == MSIOF_SPI_SLAVE) - ctlr = spi_alloc_slave(&pdev->dev, - sizeof(struct sh_msiof_spi_priv)); + if (info->mode == MSIOF_SPI_TARGET) + ctlr = spi_alloc_target(&pdev->dev, + sizeof(struct sh_msiof_spi_priv)); else - ctlr = spi_alloc_master(&pdev->dev, - sizeof(struct sh_msiof_spi_priv)); + ctlr = spi_alloc_host(&pdev->dev, + sizeof(struct sh_msiof_spi_priv)); if (ctlr == NULL) return -ENOMEM; @@ -1348,7 +1347,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) ctlr->dev.of_node = pdev->dev.of_node; ctlr->setup = sh_msiof_spi_setup; ctlr->prepare_message = sh_msiof_prepare_message; - ctlr->slave_abort = sh_msiof_slave_abort; + ctlr->target_abort = sh_msiof_target_abort; ctlr->bits_per_word_mask = chipdata->bits_per_word_mask; ctlr->auto_runtime_pm = true; ctlr->transfer_one = sh_msiof_transfer_one; diff --git a/drivers/spi/spi-sh-sci.c b/drivers/spi/spi-sh-sci.c index 92ca3f2d61ba..148d615d2f38 100644 --- a/drivers/spi/spi-sh-sci.c +++ b/drivers/spi/spi-sh-sci.c @@ -56,17 +56,17 @@ static inline void setbits(struct sh_sci_spi *sp, int bits, int on) static inline void setsck(struct spi_device *dev, int on) { - setbits(spi_master_get_devdata(dev->master), PIN_SCK, on); + setbits(spi_controller_get_devdata(dev->controller), PIN_SCK, on); } static inline void setmosi(struct spi_device *dev, int on) { - setbits(spi_master_get_devdata(dev->master), PIN_TXD, on); + setbits(spi_controller_get_devdata(dev->controller), PIN_TXD, on); } static inline u32 getmiso(struct spi_device *dev) { - struct sh_sci_spi *sp = spi_master_get_devdata(dev->master); + struct sh_sci_spi *sp = spi_controller_get_devdata(dev->controller); return (ioread8(SCSPTR(sp)) & PIN_RXD) ? 1 : 0; } @@ -105,7 +105,7 @@ static u32 sh_sci_spi_txrx_mode3(struct spi_device *spi, static void sh_sci_spi_chipselect(struct spi_device *dev, int value) { - struct sh_sci_spi *sp = spi_master_get_devdata(dev->master); + struct sh_sci_spi *sp = spi_controller_get_devdata(dev->controller); if (sp->info->chip_select) (sp->info->chip_select)(sp->info, spi_get_chipselect(dev, 0), value); @@ -114,18 +114,18 @@ static void sh_sci_spi_chipselect(struct spi_device *dev, int value) static int sh_sci_spi_probe(struct platform_device *dev) { struct resource *r; - struct spi_master *master; + struct spi_controller *host; struct sh_sci_spi *sp; int ret; - master = spi_alloc_master(&dev->dev, sizeof(struct sh_sci_spi)); - if (master == NULL) { - dev_err(&dev->dev, "failed to allocate spi master\n"); + host = spi_alloc_host(&dev->dev, sizeof(struct sh_sci_spi)); + if (host == NULL) { + dev_err(&dev->dev, "failed to allocate spi host\n"); ret = -ENOMEM; goto err0; } - sp = spi_master_get_devdata(master); + sp = spi_controller_get_devdata(host); platform_set_drvdata(dev, sp); sp->info = dev_get_platdata(&dev->dev); @@ -136,7 +136,7 @@ static int sh_sci_spi_probe(struct platform_device *dev) } /* setup spi bitbang adaptor */ - sp->bitbang.master = master; + sp->bitbang.master = host; sp->bitbang.master->bus_num = sp->info->bus_num; sp->bitbang.master->num_chipselect = sp->info->num_chipselect; sp->bitbang.chipselect = sh_sci_spi_chipselect; @@ -166,7 +166,7 @@ static int sh_sci_spi_probe(struct platform_device *dev) setbits(sp, PIN_INIT, 0); iounmap(sp->membase); err1: - spi_master_put(sp->bitbang.master); + spi_controller_put(sp->bitbang.master); err0: return ret; } @@ -178,7 +178,7 @@ static void sh_sci_spi_remove(struct platform_device *dev) spi_bitbang_stop(&sp->bitbang); setbits(sp, PIN_INIT, 0); iounmap(sp->membase); - spi_master_put(sp->bitbang.master); + spi_controller_put(sp->bitbang.master); } static struct platform_driver sh_sci_spi_drv = { diff --git a/drivers/spi/spi-sh.c b/drivers/spi/spi-sh.c index d358a2a9c3f5..4b873d9a7602 100644 --- a/drivers/spi/spi-sh.c +++ b/drivers/spi/spi-sh.c @@ -72,7 +72,7 @@ struct spi_sh_data { void __iomem *addr; int irq; - struct spi_master *master; + struct spi_controller *host; unsigned long cr1; wait_queue_head_t wait; int width; @@ -327,7 +327,7 @@ static int spi_sh_transfer_one_message(struct spi_controller *ctlr, static int spi_sh_setup(struct spi_device *spi) { - struct spi_sh_data *ss = spi_master_get_devdata(spi->master); + struct spi_sh_data *ss = spi_controller_get_devdata(spi->controller); pr_debug("%s: enter\n", __func__); @@ -346,7 +346,7 @@ static int spi_sh_setup(struct spi_device *spi) static void spi_sh_cleanup(struct spi_device *spi) { - struct spi_sh_data *ss = spi_master_get_devdata(spi->master); + struct spi_sh_data *ss = spi_controller_get_devdata(spi->controller); pr_debug("%s: enter\n", __func__); @@ -381,14 +381,14 @@ static void spi_sh_remove(struct platform_device *pdev) { struct spi_sh_data *ss = platform_get_drvdata(pdev); - spi_unregister_master(ss->master); + spi_unregister_controller(ss->host); free_irq(ss->irq, ss); } static int spi_sh_probe(struct platform_device *pdev) { struct resource *res; - struct spi_master *master; + struct spi_controller *host; struct spi_sh_data *ss; int ret, irq; @@ -403,13 +403,13 @@ static int spi_sh_probe(struct platform_device *pdev) if (irq < 0) return irq; - master = devm_spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data)); - if (master == NULL) { - dev_err(&pdev->dev, "spi_alloc_master error.\n"); + host = devm_spi_alloc_host(&pdev->dev, sizeof(struct spi_sh_data)); + if (host == NULL) { + dev_err(&pdev->dev, "devm_spi_alloc_host error.\n"); return -ENOMEM; } - ss = spi_master_get_devdata(master); + ss = spi_controller_get_devdata(host); platform_set_drvdata(pdev, ss); switch (res->flags & IORESOURCE_MEM_TYPE_MASK) { @@ -424,7 +424,7 @@ static int spi_sh_probe(struct platform_device *pdev) return -ENODEV; } ss->irq = irq; - ss->master = master; + ss->host = host; ss->addr = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (ss->addr == NULL) { dev_err(&pdev->dev, "ioremap error.\n"); @@ -438,15 +438,15 @@ static int spi_sh_probe(struct platform_device *pdev) return ret; } - master->num_chipselect = 2; - master->bus_num = pdev->id; - master->setup = spi_sh_setup; - master->transfer_one_message = spi_sh_transfer_one_message; - master->cleanup = spi_sh_cleanup; + host->num_chipselect = 2; + host->bus_num = pdev->id; + host->setup = spi_sh_setup; + host->transfer_one_message = spi_sh_transfer_one_message; + host->cleanup = spi_sh_cleanup; - ret = spi_register_master(master); + ret = spi_register_controller(host); if (ret < 0) { - printk(KERN_ERR "spi_register_master error.\n"); + printk(KERN_ERR "spi_register_controller error.\n"); goto error3; } diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/spi-sifive.c index dae9e097c333..cfd17bbb2202 100644 --- a/drivers/spi/spi-sifive.c +++ b/drivers/spi/spi-sifive.c @@ -128,9 +128,9 @@ static void sifive_spi_init(struct sifive_spi *spi) } static int -sifive_spi_prepare_message(struct spi_master *master, struct spi_message *msg) +sifive_spi_prepare_message(struct spi_controller *host, struct spi_message *msg) { - struct sifive_spi *spi = spi_master_get_devdata(master); + struct sifive_spi *spi = spi_controller_get_devdata(host); struct spi_device *device = msg->spi; /* Update the chip select polarity */ @@ -152,7 +152,7 @@ sifive_spi_prepare_message(struct spi_master *master, struct spi_message *msg) static void sifive_spi_set_cs(struct spi_device *device, bool is_high) { - struct sifive_spi *spi = spi_master_get_devdata(device->master); + struct sifive_spi *spi = spi_controller_get_devdata(device->controller); /* Reverse polarity is handled by SCMR/CPOL. Not inverted CS. */ if (device->mode & SPI_CS_HIGH) @@ -252,10 +252,10 @@ static void sifive_spi_rx(struct sifive_spi *spi, u8 *rx_ptr) } static int -sifive_spi_transfer_one(struct spi_master *master, struct spi_device *device, +sifive_spi_transfer_one(struct spi_controller *host, struct spi_device *device, struct spi_transfer *t) { - struct sifive_spi *spi = spi_master_get_devdata(master); + struct sifive_spi *spi = spi_controller_get_devdata(host); int poll = sifive_spi_prep_transfer(spi, device, t); const u8 *tx_ptr = t->tx_buf; u8 *rx_ptr = t->rx_buf; @@ -294,35 +294,35 @@ static int sifive_spi_probe(struct platform_device *pdev) struct sifive_spi *spi; int ret, irq, num_cs; u32 cs_bits, max_bits_per_word; - struct spi_master *master; + struct spi_controller *host; - master = spi_alloc_master(&pdev->dev, sizeof(struct sifive_spi)); - if (!master) { + host = spi_alloc_host(&pdev->dev, sizeof(struct sifive_spi)); + if (!host) { dev_err(&pdev->dev, "out of memory\n"); return -ENOMEM; } - spi = spi_master_get_devdata(master); + spi = spi_controller_get_devdata(host); init_completion(&spi->done); - platform_set_drvdata(pdev, master); + platform_set_drvdata(pdev, host); spi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(spi->regs)) { ret = PTR_ERR(spi->regs); - goto put_master; + goto put_host; } spi->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(spi->clk)) { dev_err(&pdev->dev, "Unable to find bus clock\n"); ret = PTR_ERR(spi->clk); - goto put_master; + goto put_host; } irq = platform_get_irq(pdev, 0); if (irq < 0) { ret = irq; - goto put_master; + goto put_host; } /* Optional parameters */ @@ -339,14 +339,14 @@ static int sifive_spi_probe(struct platform_device *pdev) if (!ret && max_bits_per_word < 8) { dev_err(&pdev->dev, "Only 8bit SPI words supported by the driver\n"); ret = -EINVAL; - goto put_master; + goto put_host; } /* Spin up the bus clock before hitting registers */ ret = clk_prepare_enable(spi->clk); if (ret) { dev_err(&pdev->dev, "Unable to enable bus clock\n"); - goto put_master; + goto put_host; } /* probe the number of CS lines */ @@ -362,30 +362,30 @@ static int sifive_spi_probe(struct platform_device *pdev) num_cs = ilog2(cs_bits) + 1; if (num_cs > SIFIVE_SPI_MAX_CS) { - dev_err(&pdev->dev, "Invalid number of spi slaves\n"); + dev_err(&pdev->dev, "Invalid number of spi targets\n"); ret = -EINVAL; goto disable_clk; } - /* Define our master */ - master->dev.of_node = pdev->dev.of_node; - master->bus_num = pdev->id; - master->num_chipselect = num_cs; - master->mode_bits = SPI_CPHA | SPI_CPOL + /* Define our host */ + host->dev.of_node = pdev->dev.of_node; + host->bus_num = pdev->id; + host->num_chipselect = num_cs; + host->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST | SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD; /* TODO: add driver support for bits_per_word < 8 * we need to "left-align" the bits (unless SPI_LSB_FIRST) */ - master->bits_per_word_mask = SPI_BPW_MASK(8); - master->flags = SPI_CONTROLLER_MUST_TX | SPI_MASTER_GPIO_SS; - master->prepare_message = sifive_spi_prepare_message; - master->set_cs = sifive_spi_set_cs; - master->transfer_one = sifive_spi_transfer_one; + host->bits_per_word_mask = SPI_BPW_MASK(8); + host->flags = SPI_CONTROLLER_MUST_TX | SPI_CONTROLLER_GPIO_SS; + host->prepare_message = sifive_spi_prepare_message; + host->set_cs = sifive_spi_set_cs; + host->transfer_one = sifive_spi_transfer_one; pdev->dev.dma_mask = NULL; - /* Configure the SPI master hardware */ + /* Configure the SPI host hardware */ sifive_spi_init(spi); /* Register for SPI Interrupt */ @@ -397,11 +397,11 @@ static int sifive_spi_probe(struct platform_device *pdev) } dev_info(&pdev->dev, "mapped; irq=%d, cs=%d\n", - irq, master->num_chipselect); + irq, host->num_chipselect); - ret = devm_spi_register_master(&pdev->dev, master); + ret = devm_spi_register_controller(&pdev->dev, host); if (ret < 0) { - dev_err(&pdev->dev, "spi_register_master failed\n"); + dev_err(&pdev->dev, "spi_register_host failed\n"); goto disable_clk; } @@ -409,16 +409,16 @@ static int sifive_spi_probe(struct platform_device *pdev) disable_clk: clk_disable_unprepare(spi->clk); -put_master: - spi_master_put(master); +put_host: + spi_controller_put(host); return ret; } static void sifive_spi_remove(struct platform_device *pdev) { - struct spi_master *master = platform_get_drvdata(pdev); - struct sifive_spi *spi = spi_master_get_devdata(master); + struct spi_controller *host = platform_get_drvdata(pdev); + struct sifive_spi *spi = spi_controller_get_devdata(host); /* Disable all the interrupts just in case */ sifive_spi_write(spi, SIFIVE_SPI_REG_IE, 0); @@ -427,11 +427,11 @@ static void sifive_spi_remove(struct platform_device *pdev) static int sifive_spi_suspend(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct sifive_spi *spi = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct sifive_spi *spi = spi_controller_get_devdata(host); int ret; - ret = spi_master_suspend(master); + ret = spi_controller_suspend(host); if (ret) return ret; @@ -445,14 +445,14 @@ static int sifive_spi_suspend(struct device *dev) static int sifive_spi_resume(struct device *dev) { - struct spi_master *master = dev_get_drvdata(dev); - struct sifive_spi *spi = spi_master_get_devdata(master); + struct spi_controller *host = dev_get_drvdata(dev); + struct sifive_spi *spi = spi_controller_get_devdata(host); int ret; ret = clk_prepare_enable(spi->clk); if (ret) return ret; - ret = spi_master_resume(master); + ret = spi_controller_resume(host); if (ret) clk_disable_unprepare(spi->clk); diff --git a/drivers/spi/spi-slave-mt27xx.c b/drivers/spi/spi-slave-mt27xx.c index 4e4d426bfb43..6d6772974783 100644 --- a/drivers/spi/spi-slave-mt27xx.c +++ b/drivers/spi/spi-slave-mt27xx.c @@ -414,7 +414,7 @@ static int mtk_spi_slave_probe(struct platform_device *pdev) mdata->dev_comp = of_id->data; if (mdata->dev_comp->must_rx) - ctlr->flags = SPI_MASTER_MUST_RX; + ctlr->flags = SPI_CONTROLLER_MUST_RX; platform_set_drvdata(pdev, ctlr); diff --git a/drivers/spi/spi-sn-f-ospi.c b/drivers/spi/spi-sn-f-ospi.c index d64d3f75c726..a7c3b3923b4a 100644 --- a/drivers/spi/spi-sn-f-ospi.c +++ b/drivers/spi/spi-sn-f-ospi.c @@ -10,7 +10,7 @@ #include <linux/iopoll.h> #include <linux/module.h> #include <linux/mutex.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> #include <linux/spi/spi-mem.h> @@ -501,7 +501,7 @@ out: static int f_ospi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op) { - struct f_ospi *ospi = spi_controller_get_devdata(mem->spi->master); + struct f_ospi *ospi = spi_controller_get_devdata(mem->spi->controller); int err = 0; switch (op->data.dir) { @@ -606,7 +606,7 @@ static int f_ospi_probe(struct platform_device *pdev) u32 num_cs = OSPI_NUM_CS; int ret; - ctlr = spi_alloc_master(dev, sizeof(*ospi)); + ctlr = spi_alloc_host(dev, sizeof(*ospi)); if (!ctlr) return -ENOMEM; diff --git a/drivers/spi/spi-sprd-adi.c b/drivers/spi/spi-sprd-adi.c index 22e39c4c12c4..bf01feedbf93 100644 --- a/drivers/spi/spi-sprd-adi.c +++ b/drivers/spi/spi-sprd-adi.c @@ -11,7 +11,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/reboot.h> #include <linux/spi/spi.h> @@ -580,7 +579,7 @@ static int sprd_adi_probe(struct platform_device *pdev) ctlr->dev.of_node = pdev->dev.of_node; ctlr->bus_num = pdev->id; ctlr->num_chipselect = num_chipselect; - ctlr->flags = SPI_MASTER_HALF_DUPLEX; + ctlr->flags = SPI_CONTROLLER_HALF_DUPLEX; ctlr->bits_per_word_mask = 0; ctlr->transfer_one = sprd_adi_transfer_one; diff --git a/drivers/spi/spi-sprd.c b/drivers/spi/spi-sprd.c index 518c7eaca84e..95377cf748c0 100644 --- a/drivers/spi/spi-sprd.c +++ b/drivers/spi/spi-sprd.c @@ -11,7 +11,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_dma.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> diff --git a/drivers/spi/spi-stm32-qspi.c b/drivers/spi/spi-stm32-qspi.c index 2b6804aa6901..def74ae9b5f6 100644 --- a/drivers/spi/spi-stm32-qspi.c +++ b/drivers/spi/spi-stm32-qspi.c @@ -14,7 +14,6 @@ #include <linux/module.h> #include <linux/mutex.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/of_gpio.h> #include <linux/pinctrl/consumer.h> #include <linux/pm_runtime.h> diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index 6d10fa4ab783..b6d66caba4c0 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -238,6 +238,7 @@ struct stm32_spi; * @baud_rate_div_min: minimum baud rate divisor * @baud_rate_div_max: maximum baud rate divisor * @has_fifo: boolean to know if fifo is used for driver + * @has_device_mode: is this compatible capable to switch on device mode * @flags: compatible specific SPI controller flags used at registration time */ struct stm32_spi_cfg { @@ -259,6 +260,7 @@ struct stm32_spi_cfg { unsigned int baud_rate_div_min; unsigned int baud_rate_div_max; bool has_fifo; + bool has_device_mode; u16 flags; }; @@ -1001,9 +1003,9 @@ static int stm32_spi_prepare_msg(struct spi_controller *ctrl, if (spi->cfg->set_number_of_data) { int ret; - ret = spi_split_transfers_maxsize(ctrl, msg, - STM32H7_SPI_TSIZE_MAX, - GFP_KERNEL | GFP_DMA); + ret = spi_split_transfers_maxwords(ctrl, msg, + STM32H7_SPI_TSIZE_MAX, + GFP_KERNEL | GFP_DMA); if (ret) return ret; } @@ -1750,7 +1752,8 @@ static const struct stm32_spi_cfg stm32f4_spi_cfg = { .baud_rate_div_min = STM32F4_SPI_BR_DIV_MIN, .baud_rate_div_max = STM32F4_SPI_BR_DIV_MAX, .has_fifo = false, - .flags = SPI_MASTER_MUST_TX, + .has_device_mode = false, + .flags = SPI_CONTROLLER_MUST_TX, }; static const struct stm32_spi_cfg stm32h7_spi_cfg = { @@ -1774,6 +1777,7 @@ static const struct stm32_spi_cfg stm32h7_spi_cfg = { .baud_rate_div_min = STM32H7_SPI_MBR_DIV_MIN, .baud_rate_div_max = STM32H7_SPI_MBR_DIV_MAX, .has_fifo = true, + .has_device_mode = true, }; static const struct of_device_id stm32_spi_of_match[] = { @@ -1798,8 +1802,13 @@ static int stm32_spi_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; bool device_mode; int ret; + const struct stm32_spi_cfg *cfg = of_device_get_match_data(&pdev->dev); device_mode = of_property_read_bool(np, "spi-slave"); + if (!cfg->has_device_mode && device_mode) { + dev_err(&pdev->dev, "spi-slave not supported\n"); + return -EPERM; + } if (device_mode) ctrl = devm_spi_alloc_slave(&pdev->dev, sizeof(struct stm32_spi)); @@ -1817,9 +1826,7 @@ static int stm32_spi_probe(struct platform_device *pdev) spi->device_mode = device_mode; spin_lock_init(&spi->lock); - spi->cfg = (const struct stm32_spi_cfg *) - of_match_device(pdev->dev.driver->of_match_table, - &pdev->dev)->data; + spi->cfg = cfg; spi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(spi->base)) @@ -1829,8 +1836,7 @@ static int stm32_spi_probe(struct platform_device *pdev) spi->irq = platform_get_irq(pdev, 0); if (spi->irq <= 0) - return dev_err_probe(&pdev->dev, spi->irq, - "failed to get irq\n"); + return spi->irq; ret = devm_request_threaded_irq(&pdev->dev, spi->irq, spi->cfg->irq_handler_event, diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c index 30d541612253..3f5b1556ece0 100644 --- a/drivers/spi/spi-sun6i.c +++ b/drivers/spi/spi-sun6i.c @@ -14,7 +14,7 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/reset.h> @@ -83,6 +83,9 @@ #define SUN6I_XMIT_CNT_REG 0x34 #define SUN6I_BURST_CTL_CNT_REG 0x38 +#define SUN6I_BURST_CTL_CNT_STC_MASK GENMASK(23, 0) +#define SUN6I_BURST_CTL_CNT_DRM BIT(28) +#define SUN6I_BURST_CTL_CNT_QUAD_EN BIT(29) #define SUN6I_TXDATA_REG 0x200 #define SUN6I_RXDATA_REG 0x300 @@ -90,6 +93,7 @@ struct sun6i_spi_cfg { unsigned long fifo_depth; bool has_clk_ctl; + u32 mode_bits; }; struct sun6i_spi { @@ -266,7 +270,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master, unsigned int div, div_cdr1, div_cdr2, timeout; unsigned int start, end, tx_time; unsigned int trig_level; - unsigned int tx_len = 0, rx_len = 0; + unsigned int tx_len = 0, rx_len = 0, nbits = 0; bool use_dma; int ret = 0; u32 reg; @@ -418,13 +422,29 @@ static int sun6i_spi_transfer_one(struct spi_master *master, sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG, reg); /* Setup the transfer now... */ - if (sspi->tx_buf) + if (sspi->tx_buf) { tx_len = tfr->len; + nbits = tfr->tx_nbits; + } else if (tfr->rx_buf) { + nbits = tfr->rx_nbits; + } + + switch (nbits) { + case SPI_NBITS_DUAL: + reg = SUN6I_BURST_CTL_CNT_DRM; + break; + case SPI_NBITS_QUAD: + reg = SUN6I_BURST_CTL_CNT_QUAD_EN; + break; + case SPI_NBITS_SINGLE: + default: + reg = FIELD_PREP(SUN6I_BURST_CTL_CNT_STC_MASK, tx_len); + } /* Setup the counters */ + sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG, reg); sun6i_spi_write(sspi, SUN6I_BURST_CNT_REG, tfr->len); sun6i_spi_write(sspi, SUN6I_XMIT_CNT_REG, tx_len); - sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG, tx_len); if (!use_dma) { /* Fill the TX FIFO */ @@ -623,7 +643,8 @@ static int sun6i_spi_probe(struct platform_device *pdev) master->set_cs = sun6i_spi_set_cs; master->transfer_one = sun6i_spi_transfer_one; master->num_chipselect = 4; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST | + sspi->cfg->mode_bits; master->bits_per_word_mask = SPI_BPW_MASK(8); master->dev.of_node = pdev->dev.of_node; master->auto_runtime_pm = true; @@ -740,6 +761,7 @@ static const struct sun6i_spi_cfg sun8i_h3_spi_cfg = { static const struct sun6i_spi_cfg sun50i_r329_spi_cfg = { .fifo_depth = SUN8I_FIFO_DEPTH, + .mode_bits = SPI_RX_DUAL | SPI_TX_DUAL | SPI_RX_QUAD | SPI_TX_QUAD, }; static const struct of_device_id sun6i_spi_match[] = { diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 488df681eaef..460f232dad50 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -20,7 +20,6 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/reset.h> #include <linux/spi/spi.h> @@ -723,27 +722,23 @@ static int tegra_spi_set_hw_cs_timing(struct spi_device *spi) struct spi_delay *setup = &spi->cs_setup; struct spi_delay *hold = &spi->cs_hold; struct spi_delay *inactive = &spi->cs_inactive; - u8 setup_dly, hold_dly, inactive_dly; + u8 setup_dly, hold_dly; u32 setup_hold; u32 spi_cs_timing; u32 inactive_cycles; u8 cs_state; - if ((setup && setup->unit != SPI_DELAY_UNIT_SCK) || - (hold && hold->unit != SPI_DELAY_UNIT_SCK) || - (inactive && inactive->unit != SPI_DELAY_UNIT_SCK)) { + if (setup->unit != SPI_DELAY_UNIT_SCK || + hold->unit != SPI_DELAY_UNIT_SCK || + inactive->unit != SPI_DELAY_UNIT_SCK) { dev_err(&spi->dev, "Invalid delay unit %d, should be SPI_DELAY_UNIT_SCK\n", SPI_DELAY_UNIT_SCK); return -EINVAL; } - setup_dly = setup ? setup->value : 0; - hold_dly = hold ? hold->value : 0; - inactive_dly = inactive ? inactive->value : 0; - - setup_dly = min_t(u8, setup_dly, MAX_SETUP_HOLD_CYCLES); - hold_dly = min_t(u8, hold_dly, MAX_SETUP_HOLD_CYCLES); + setup_dly = min_t(u8, setup->value, MAX_SETUP_HOLD_CYCLES); + hold_dly = min_t(u8, hold->value, MAX_SETUP_HOLD_CYCLES); if (setup_dly && hold_dly) { setup_hold = SPI_SETUP_HOLD(setup_dly - 1, hold_dly - 1); spi_cs_timing = SPI_CS_SETUP_HOLD(tspi->spi_cs_timing1, @@ -755,7 +750,7 @@ static int tegra_spi_set_hw_cs_timing(struct spi_device *spi) } } - inactive_cycles = min_t(u8, inactive_dly, MAX_INACTIVE_CYCLES); + inactive_cycles = min_t(u8, inactive->value, MAX_INACTIVE_CYCLES); if (inactive_cycles) inactive_cycles--; cs_state = inactive_cycles ? 0 : 1; diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index 4286310628a2..0c5507473f97 100644 --- a/drivers/spi/spi-tegra20-sflash.c +++ b/drivers/spi/spi-tegra20-sflash.c @@ -455,7 +455,11 @@ static int tegra_sflash_probe(struct platform_device *pdev) goto exit_free_master; } - tsd->irq = platform_get_irq(pdev, 0); + ret = platform_get_irq(pdev, 0); + if (ret < 0) + goto exit_free_master; + tsd->irq = ret; + ret = request_irq(tsd->irq, tegra_sflash_isr, 0, dev_name(&pdev->dev), tsd); if (ret < 0) { diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index c2915f7672cc..4d6db6182c5e 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -21,7 +21,6 @@ #include <linux/pm_opp.h> #include <linux/pm_runtime.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/reset.h> #include <linux/spi/spi.h> @@ -1034,18 +1033,12 @@ static int tegra_slink_probe(struct platform_device *pdev) &master->max_speed_hz)) master->max_speed_hz = 25000000; /* 25MHz */ - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) { - dev_err(&pdev->dev, "No IO memory resource\n"); - ret = -ENODEV; - goto exit_free_master; - } - tspi->phys = r->start; - tspi->base = devm_ioremap_resource(&pdev->dev, r); + tspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r); if (IS_ERR(tspi->base)) { ret = PTR_ERR(tspi->base); goto exit_free_master; } + tspi->phys = r->start; /* disabled clock may cause interrupt storm upon request */ tspi->clk = devm_clk_get(&pdev->dev, NULL); diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c index fbd14dd7be44..e9ad9b0b598b 100644 --- a/drivers/spi/spi-tegra210-quad.c +++ b/drivers/spi/spi-tegra210-quad.c @@ -18,7 +18,6 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/reset.h> #include <linux/spi/spi.h> #include <linux/acpi.h> diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 5914335ff63d..4c81516b67db 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -22,7 +22,6 @@ #include <linux/slab.h> #include <linux/pm_runtime.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/pinctrl/consumer.h> #include <linux/mfd/syscon.h> #include <linux/regmap.h> @@ -770,7 +769,7 @@ static int ti_qspi_probe(struct platform_device *pdev) master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_RX_DUAL | SPI_RX_QUAD; - master->flags = SPI_MASTER_HALF_DUPLEX; + master->flags = SPI_CONTROLLER_HALF_DUPLEX; master->setup = ti_qspi_setup; master->auto_runtime_pm = true; master->transfer_one_message = ti_qspi_start_transfer_one; diff --git a/drivers/spi/spi-wpcm-fiu.c b/drivers/spi/spi-wpcm-fiu.c index f15312fdcdaf..852ffe013d32 100644 --- a/drivers/spi/spi-wpcm-fiu.c +++ b/drivers/spi/spi-wpcm-fiu.c @@ -3,9 +3,8 @@ #include <linux/clk.h> #include <linux/mfd/syscon.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_address.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/spi/spi-mem.h> diff --git a/drivers/spi/spi-xcomm.c b/drivers/spi/spi-xcomm.c index ae6218bcd02a..a3d57554f5ba 100644 --- a/drivers/spi/spi-xcomm.c +++ b/drivers/spi/spi-xcomm.c @@ -218,7 +218,7 @@ static int spi_xcomm_probe(struct i2c_client *i2c) master->num_chipselect = 16; master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_3WIRE; master->bits_per_word_mask = SPI_BPW_MASK(8); - master->flags = SPI_MASTER_HALF_DUPLEX; + master->flags = SPI_CONTROLLER_HALF_DUPLEX; master->transfer_one_message = spi_xcomm_transfer_one; master->dev.of_node = i2c->dev.of_node; i2c_set_clientdata(i2c, master); diff --git a/drivers/spi/spi-xtensa-xtfpga.c b/drivers/spi/spi-xtensa-xtfpga.c index 24dc845b940e..dbd85d7a1526 100644 --- a/drivers/spi/spi-xtensa-xtfpga.c +++ b/drivers/spi/spi-xtensa-xtfpga.c @@ -87,7 +87,7 @@ static int xtfpga_spi_probe(struct platform_device *pdev) if (!master) return -ENOMEM; - master->flags = SPI_MASTER_NO_RX; + master->flags = SPI_CONTROLLER_NO_RX; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16); master->bus_num = pdev->dev.id; master->dev.of_node = pdev->dev.of_node; diff --git a/drivers/spi/spi-zynq-qspi.c b/drivers/spi/spi-zynq-qspi.c index ee1995b91287..0db69a2a72ff 100644 --- a/drivers/spi/spi-zynq-qspi.c +++ b/drivers/spi/spi-zynq-qspi.c @@ -679,8 +679,8 @@ static int zynq_qspi_probe(struct platform_device *pdev) } xqspi->irq = platform_get_irq(pdev, 0); - if (xqspi->irq <= 0) { - ret = -ENXIO; + if (xqspi->irq < 0) { + ret = xqspi->irq; goto clk_dis_all; } ret = devm_request_irq(&pdev->dev, xqspi->irq, zynq_qspi_irq, diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index fb2ca9b90eab..94d9a33d9af5 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -14,9 +14,7 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> -#include <linux/of_irq.h> -#include <linux/of_address.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/spi/spi.h> @@ -1295,8 +1293,8 @@ static int zynqmp_qspi_probe(struct platform_device *pdev) zynqmp_qspi_init_hw(xqspi); xqspi->irq = platform_get_irq(pdev, 0); - if (xqspi->irq <= 0) { - ret = -ENXIO; + if (xqspi->irq < 0) { + ret = xqspi->irq; goto clk_dis_all; } ret = devm_request_irq(&pdev->dev, xqspi->irq, zynqmp_qspi_irq, diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 9291b2a0e887..8d6304cb061e 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -4,36 +4,36 @@ // Copyright (C) 2005 David Brownell // Copyright (C) 2008 Secret Lab Technologies Ltd. -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/init.h> +#include <linux/acpi.h> #include <linux/cache.h> -#include <linux/dma-mapping.h> +#include <linux/clk/clk-conf.h> +#include <linux/delay.h> +#include <linux/device.h> #include <linux/dmaengine.h> +#include <linux/dma-mapping.h> +#include <linux/export.h> +#include <linux/gpio/consumer.h> +#include <linux/highmem.h> +#include <linux/idr.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/kernel.h> +#include <linux/kthread.h> +#include <linux/mod_devicetable.h> #include <linux/mutex.h> #include <linux/of_device.h> #include <linux/of_irq.h> -#include <linux/clk/clk-conf.h> -#include <linux/slab.h> -#include <linux/mod_devicetable.h> -#include <linux/spi/spi.h> -#include <linux/spi/spi-mem.h> -#include <linux/gpio/consumer.h> -#include <linux/pm_runtime.h> +#include <linux/percpu.h> +#include <linux/platform_data/x86/apple.h> #include <linux/pm_domain.h> +#include <linux/pm_runtime.h> #include <linux/property.h> -#include <linux/export.h> +#include <linux/ptp_clock_kernel.h> #include <linux/sched/rt.h> +#include <linux/slab.h> +#include <linux/spi/spi.h> +#include <linux/spi/spi-mem.h> #include <uapi/linux/sched/types.h> -#include <linux/delay.h> -#include <linux/kthread.h> -#include <linux/ioport.h> -#include <linux/acpi.h> -#include <linux/highmem.h> -#include <linux/idr.h> -#include <linux/platform_data/x86/apple.h> -#include <linux/ptp_clock_kernel.h> -#include <linux/percpu.h> #define CREATE_TRACE_POINTS #include <trace/events/spi.h> @@ -64,7 +64,7 @@ modalias_show(struct device *dev, struct device_attribute *a, char *buf) if (len != -ENODEV) return len; - return sprintf(buf, "%s%s\n", SPI_MODULE_PREFIX, spi->modalias); + return sysfs_emit(buf, "%s%s\n", SPI_MODULE_PREFIX, spi->modalias); } static DEVICE_ATTR_RO(modalias); @@ -89,7 +89,7 @@ static ssize_t driver_override_show(struct device *dev, ssize_t len; device_lock(dev); - len = snprintf(buf, PAGE_SIZE, "%s\n", spi->driver_override ? : ""); + len = sysfs_emit(buf, "%s\n", spi->driver_override ? : ""); device_unlock(dev); return len; } @@ -631,6 +631,16 @@ static int __spi_add_device(struct spi_device *spi) struct device *dev = ctlr->dev.parent; int status; + /* Chipselects are numbered 0..max; validate. */ + if (spi_get_chipselect(spi, 0) >= ctlr->num_chipselect) { + dev_err(dev, "cs%d >= max %d\n", spi_get_chipselect(spi, 0), + ctlr->num_chipselect); + return -EINVAL; + } + + /* Set the bus ID string */ + spi_dev_set_name(spi); + /* * We need to make sure there's no other device with this * chipselect **BEFORE** we call setup(), else we'll trash @@ -682,26 +692,15 @@ static int __spi_add_device(struct spi_device *spi) * @spi: spi_device to register * * Companion function to spi_alloc_device. Devices allocated with - * spi_alloc_device can be added onto the spi bus with this function. + * spi_alloc_device can be added onto the SPI bus with this function. * * Return: 0 on success; negative errno on failure */ int spi_add_device(struct spi_device *spi) { struct spi_controller *ctlr = spi->controller; - struct device *dev = ctlr->dev.parent; int status; - /* Chipselects are numbered 0..max; validate. */ - if (spi_get_chipselect(spi, 0) >= ctlr->num_chipselect) { - dev_err(dev, "cs%d >= max %d\n", spi_get_chipselect(spi, 0), - ctlr->num_chipselect); - return -EINVAL; - } - - /* Set the bus ID string */ - spi_dev_set_name(spi); - mutex_lock(&ctlr->add_lock); status = __spi_add_device(spi); mutex_unlock(&ctlr->add_lock); @@ -709,25 +708,6 @@ int spi_add_device(struct spi_device *spi) } EXPORT_SYMBOL_GPL(spi_add_device); -static int spi_add_device_locked(struct spi_device *spi) -{ - struct spi_controller *ctlr = spi->controller; - struct device *dev = ctlr->dev.parent; - - /* Chipselects are numbered 0..max; validate. */ - if (spi_get_chipselect(spi, 0) >= ctlr->num_chipselect) { - dev_err(dev, "cs%d >= max %d\n", spi_get_chipselect(spi, 0), - ctlr->num_chipselect); - return -EINVAL; - } - - /* Set the bus ID string */ - spi_dev_set_name(spi); - - WARN_ON(!mutex_is_locked(&ctlr->add_lock)); - return __spi_add_device(spi); -} - /** * spi_new_device - instantiate one new SPI device * @ctlr: Controller to which device is connected @@ -889,7 +869,7 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n) * spi_res_alloc - allocate a spi resource that is life-cycle managed * during the processing of a spi_message while using * spi_transfer_one - * @spi: the spi device for which we allocate memory + * @spi: the SPI device for which we allocate memory * @release: the release code to execute for this resource * @size: size to alloc and return * @gfp: GFP allocation flags @@ -915,7 +895,7 @@ static void *spi_res_alloc(struct spi_device *spi, spi_res_release_t release, } /** - * spi_res_free - free an spi resource + * spi_res_free - free an SPI resource * @res: pointer to the custom data of a resource */ static void spi_res_free(void *res) @@ -931,7 +911,7 @@ static void spi_res_free(void *res) /** * spi_res_add - add a spi_res to the spi_message - * @message: the spi message + * @message: the SPI message * @res: the spi_resource */ static void spi_res_add(struct spi_message *message, void *res) @@ -943,7 +923,7 @@ static void spi_res_add(struct spi_message *message, void *res) } /** - * spi_res_release - release all spi resources for this message + * spi_res_release - release all SPI resources for this message * @ctlr: the @spi_controller * @message: the @spi_message */ @@ -1006,7 +986,7 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force) gpiod_set_value_cansleep(spi_get_csgpiod(spi, 0), activate); } /* Some SPI masters need both GPIO CS & slave_select */ - if ((spi->controller->flags & SPI_MASTER_GPIO_SS) && + if ((spi->controller->flags & SPI_CONTROLLER_GPIO_SS) && spi->controller->set_cs) spi->controller->set_cs(spi, !enable); } else if (spi->controller->set_cs) { @@ -1424,7 +1404,7 @@ int spi_delay_to_ns(struct spi_delay *_delay, struct spi_transfer *xfer) return -EINVAL; /* * If there is unknown effective speed, approximate it - * by underestimating with half of the requested hz. + * by underestimating with half of the requested Hz. */ hz = xfer->effective_speed_hz ?: xfer->speed_hz / 2; if (!hz) @@ -1739,11 +1719,11 @@ static int __spi_pump_transfer_message(struct spi_controller *ctlr, } /** - * __spi_pump_messages - function which processes spi message queue + * __spi_pump_messages - function which processes SPI message queue * @ctlr: controller to process queue for * @in_kthread: true if we are in the context of the message pump thread * - * This function checks if there is any spi message in the queue that + * This function checks if there is any SPI message in the queue that * needs processing and if so call out to the driver to initialize hardware * and transfer each message. * @@ -1758,7 +1738,7 @@ static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread) unsigned long flags; int ret; - /* Take the IO mutex */ + /* Take the I/O mutex */ mutex_lock(&ctlr->io_mutex); /* Lock queue */ @@ -2169,8 +2149,8 @@ static int __spi_queued_transfer(struct spi_device *spi, /** * spi_queued_transfer - transfer function for queued transfers - * @spi: spi device which is requesting transfer - * @msg: spi message which is to handled is queued to driver queue + * @spi: SPI device which is requesting transfer + * @msg: SPI message which is to handled is queued to driver queue * * Return: zero on success, else a negative error code. */ @@ -2399,9 +2379,6 @@ static void of_register_spi_devices(struct spi_controller *ctlr) struct spi_device *spi; struct device_node *nc; - if (!ctlr->dev.of_node) - return; - for_each_available_child_of_node(ctlr->dev.of_node, nc) { if (of_node_test_and_set_flag(nc, OF_POPULATED)) continue; @@ -2432,11 +2409,12 @@ static void of_register_spi_devices(struct spi_controller *ctlr) { } struct spi_device *spi_new_ancillary_device(struct spi_device *spi, u8 chip_select) { + struct spi_controller *ctlr = spi->controller; struct spi_device *ancillary; int rc = 0; /* Alloc an spi_device */ - ancillary = spi_alloc_device(spi->controller); + ancillary = spi_alloc_device(ctlr); if (!ancillary) { rc = -ENOMEM; goto err_out; @@ -2451,8 +2429,10 @@ struct spi_device *spi_new_ancillary_device(struct spi_device *spi, ancillary->max_speed_hz = spi->max_speed_hz; ancillary->mode = spi->mode; + WARN_ON(!mutex_is_locked(&ctlr->add_lock)); + /* Register the new device */ - rc = spi_add_device_locked(ancillary); + rc = __spi_add_device(ancillary); if (rc) { dev_err(&spi->dev, "failed to register ancillary device\n"); goto err_out; @@ -2499,7 +2479,7 @@ static int acpi_spi_count(struct acpi_resource *ares, void *data) * acpi_spi_count_resources - Count the number of SpiSerialBus resources * @adev: ACPI device * - * Returns the number of SpiSerialBus resources in the ACPI-device's + * Return: the number of SpiSerialBus resources in the ACPI-device's * resource-list; or a negative error code. */ int acpi_spi_count_resources(struct acpi_device *adev) @@ -2633,10 +2613,10 @@ static int acpi_spi_add_resource(struct acpi_resource *ares, void *data) * @adev: ACPI Device for the spi device * @index: Index of the spi resource inside the ACPI Node * - * This should be used to allocate a new spi device from and ACPI Node. - * The caller is responsible for calling spi_add_device to register the spi device. + * This should be used to allocate a new SPI device from and ACPI Device node. + * The caller is responsible for calling spi_add_device to register the SPI device. * - * If ctlr is set to NULL, the Controller for the spi device will be looked up + * If ctlr is set to NULL, the Controller for the SPI device will be looked up * using the resource. * If index is set to -1, index is not used. * Note: If index is -1, ctlr must be set. @@ -2817,8 +2797,7 @@ static ssize_t slave_show(struct device *dev, struct device_attribute *attr, struct device *child; child = device_find_any_child(&ctlr->dev); - return sprintf(buf, "%s\n", - child ? to_spi_device(child)->modalias : NULL); + return sysfs_emit(buf, "%s\n", child ? to_spi_device(child)->modalias : NULL); } static ssize_t slave_store(struct device *dev, struct device_attribute *attr, @@ -3056,7 +3035,7 @@ static int spi_get_gpio_descs(struct spi_controller *ctlr) ctlr->unused_native_cs = ffs(~native_cs_mask) - 1; - if ((ctlr->flags & SPI_MASTER_GPIO_SS) && num_cs_gpios && + if ((ctlr->flags & SPI_CONTROLLER_GPIO_SS) && num_cs_gpios && ctlr->max_native_cs && ctlr->unused_native_cs >= ctlr->max_native_cs) { dev_err(dev, "No unused native chip select available\n"); return -EINVAL; @@ -3084,6 +3063,20 @@ static int spi_controller_check_ops(struct spi_controller *ctlr) return 0; } +/* Allocate dynamic bus number using Linux idr */ +static int spi_controller_id_alloc(struct spi_controller *ctlr, int start, int end) +{ + int id; + + mutex_lock(&board_lock); + id = idr_alloc(&spi_master_idr, ctlr, start, end, GFP_KERNEL); + mutex_unlock(&board_lock); + if (WARN(id < 0, "couldn't get idr")) + return id == -ENOSPC ? -EBUSY : id; + ctlr->bus_num = id; + return 0; +} + /** * spi_register_controller - register SPI master or slave controller * @ctlr: initialized master, originally from spi_alloc_master() or @@ -3111,8 +3104,8 @@ int spi_register_controller(struct spi_controller *ctlr) { struct device *dev = ctlr->dev.parent; struct boardinfo *bi; + int first_dynamic; int status; - int id, first_dynamic; if (!dev) return -ENODEV; @@ -3125,27 +3118,13 @@ int spi_register_controller(struct spi_controller *ctlr) if (status) return status; + if (ctlr->bus_num < 0) + ctlr->bus_num = of_alias_get_id(ctlr->dev.of_node, "spi"); if (ctlr->bus_num >= 0) { /* Devices with a fixed bus num must check-in with the num */ - mutex_lock(&board_lock); - id = idr_alloc(&spi_master_idr, ctlr, ctlr->bus_num, - ctlr->bus_num + 1, GFP_KERNEL); - mutex_unlock(&board_lock); - if (WARN(id < 0, "couldn't get idr")) - return id == -ENOSPC ? -EBUSY : id; - ctlr->bus_num = id; - } else if (ctlr->dev.of_node) { - /* Allocate dynamic bus number using Linux idr */ - id = of_alias_get_id(ctlr->dev.of_node, "spi"); - if (id >= 0) { - ctlr->bus_num = id; - mutex_lock(&board_lock); - id = idr_alloc(&spi_master_idr, ctlr, ctlr->bus_num, - ctlr->bus_num + 1, GFP_KERNEL); - mutex_unlock(&board_lock); - if (WARN(id < 0, "couldn't get idr")) - return id == -ENOSPC ? -EBUSY : id; - } + status = spi_controller_id_alloc(ctlr, ctlr->bus_num, ctlr->bus_num + 1); + if (status) + return status; } if (ctlr->bus_num < 0) { first_dynamic = of_alias_get_highest_id("spi"); @@ -3154,13 +3133,9 @@ int spi_register_controller(struct spi_controller *ctlr) else first_dynamic++; - mutex_lock(&board_lock); - id = idr_alloc(&spi_master_idr, ctlr, first_dynamic, - 0, GFP_KERNEL); - mutex_unlock(&board_lock); - if (WARN(id < 0, "couldn't get idr")) - return id; - ctlr->bus_num = id; + status = spi_controller_id_alloc(ctlr, first_dynamic, 0); + if (status) + return status; } ctlr->bus_lock_flag = 0; init_completion(&ctlr->xfer_completion); @@ -3339,7 +3314,8 @@ void spi_unregister_controller(struct spi_controller *ctlr) if (IS_ENABLED(CONFIG_SPI_DYNAMIC)) mutex_unlock(&ctlr->add_lock); - /* Release the last reference on the controller if its driver + /* + * Release the last reference on the controller if its driver * has not yet been converted to devm_spi_alloc_master/slave(). */ if (!ctlr->devm_allocated) @@ -3552,7 +3528,7 @@ static int __spi_split_transfer_maxsize(struct spi_controller *ctlr, /* All the others need rx_buf/tx_buf also set */ for (i = 1, offset = maxsize; i < count; offset += maxsize, i++) { - /* Update rx_buf, tx_buf and dma */ + /* Update rx_buf, tx_buf and DMA */ if (xfers[i].rx_buf) xfers[i].rx_buf += offset; if (xfers[i].rx_dma) @@ -3622,7 +3598,7 @@ EXPORT_SYMBOL_GPL(spi_split_transfers_maxsize); /** - * spi_split_transfers_maxwords - split spi transfers into multiple transfers + * spi_split_transfers_maxwords - split SPI transfers into multiple transfers * when an individual transfer exceeds a * certain number of SPI words * @ctlr: the @spi_controller for this transfer @@ -3650,13 +3626,7 @@ int spi_split_transfers_maxwords(struct spi_controller *ctlr, size_t maxsize; int ret; - if (xfer->bits_per_word <= 8) - maxsize = maxwords; - else if (xfer->bits_per_word <= 16) - maxsize = 2 * maxwords; - else - maxsize = 4 * maxwords; - + maxsize = maxwords * roundup_pow_of_two(BITS_TO_BYTES(xfer->bits_per_word)); if (xfer->len > maxsize) { ret = __spi_split_transfer_maxsize(ctlr, msg, &xfer, maxsize, gfp); @@ -3671,7 +3641,8 @@ EXPORT_SYMBOL_GPL(spi_split_transfers_maxwords); /*-------------------------------------------------------------------------*/ -/* Core methods for SPI controller protocol drivers. Some of the +/* + * Core methods for SPI controller protocol drivers. Some of the * other core methods are currently defined as inline functions. */ @@ -3731,7 +3702,7 @@ static int spi_set_cs_timing(struct spi_device *spi) * changes those settings, and must be called from a context that can sleep. * Except for SPI_CS_HIGH, which takes effect immediately, the changes take * effect the next time the device is selected and data is transferred to - * or from it. When this function returns, the spi device is deselected. + * or from it. When this function returns, the SPI device is deselected. * * Note that this call will fail if the protocol driver specifies an option * that the underlying controller or its driver does not support. For @@ -3906,11 +3877,9 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message) */ if ((spi->mode & SPI_CS_WORD) && (!(ctlr->mode_bits & SPI_CS_WORD) || spi_get_csgpiod(spi, 0))) { - size_t maxsize; + size_t maxsize = BITS_TO_BYTES(spi->bits_per_word); int ret; - maxsize = (spi->bits_per_word + 7) / 8; - /* spi_split_transfers_maxsize() requires message->spi */ message->spi = spi; @@ -4071,7 +4040,7 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) * spi_async - asynchronous SPI transfer * @spi: device with which data will be exchanged * @message: describes the data transfers, including completion callback - * Context: any (irqs may be blocked, etc) + * Context: any (IRQs may be blocked, etc) * * This call may be used in_irq and other contexts which can't sleep, * as well as from task contexts which can sleep. @@ -4125,7 +4094,7 @@ EXPORT_SYMBOL_GPL(spi_async); * spi_async_locked - version of spi_async with exclusive bus usage * @spi: device with which data will be exchanged * @message: describes the data transfers, including completion callback - * Context: any (irqs may be blocked, etc) + * Context: any (IRQs may be blocked, etc) * * This call may be used in_irq and other contexts which can't sleep, * as well as from task contexts which can sleep. @@ -4388,9 +4357,9 @@ static u8 *buf; /** * spi_write_then_read - SPI synchronous write followed by read * @spi: device with which data will be exchanged - * @txbuf: data to be written (need not be dma-safe) + * @txbuf: data to be written (need not be DMA-safe) * @n_tx: size of txbuf, in bytes - * @rxbuf: buffer into which data will be read (need not be dma-safe) + * @rxbuf: buffer into which data will be read (need not be DMA-safe) * @n_rx: size of rxbuf, in bytes * Context: can sleep * @@ -4401,7 +4370,7 @@ static u8 *buf; * * Parameters to this routine are always copied using a small buffer. * Performance-sensitive or bulk transfer code should instead use - * spi_{async,sync}() calls with dma-safe buffers. + * spi_{async,sync}() calls with DMA-safe buffers. * * Return: zero on success, else a negative error code. */ @@ -4446,7 +4415,7 @@ int spi_write_then_read(struct spi_device *spi, x[0].tx_buf = local_buf; x[1].rx_buf = local_buf + n_tx; - /* Do the i/o */ + /* Do the I/O */ status = spi_sync(spi, &message); if (status == 0) memcpy(rxbuf, x[1].rx_buf, n_rx); diff --git a/drivers/thermal/amlogic_thermal.c b/drivers/thermal/amlogic_thermal.c index 756b218880a7..81ebbf6de0de 100644 --- a/drivers/thermal/amlogic_thermal.c +++ b/drivers/thermal/amlogic_thermal.c @@ -22,8 +22,6 @@ #include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/thermal.h> diff --git a/drivers/thermal/broadcom/bcm2711_thermal.c b/drivers/thermal/broadcom/bcm2711_thermal.c index c243a76a3471..03ac2d02e9d4 100644 --- a/drivers/thermal/broadcom/bcm2711_thermal.c +++ b/drivers/thermal/broadcom/bcm2711_thermal.c @@ -15,8 +15,8 @@ #include <linux/kernel.h> #include <linux/mfd/syscon.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/platform_device.h> -#include <linux/of_device.h> #include <linux/regmap.h> #include <linux/thermal.h> diff --git a/drivers/thermal/broadcom/brcmstb_thermal.c b/drivers/thermal/broadcom/brcmstb_thermal.c index 72d1dbe60b8f..0b73abdaa792 100644 --- a/drivers/thermal/broadcom/brcmstb_thermal.c +++ b/drivers/thermal/broadcom/brcmstb_thermal.c @@ -17,8 +17,8 @@ #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/platform_device.h> -#include <linux/of_device.h> #include <linux/thermal.h> #define AVS_TMON_STATUS 0x00 diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 3f09ef8be41a..fb54ed4bf6f0 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -13,9 +13,9 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/module.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/io.h> -#include <linux/of_device.h> #include <linux/thermal.h> #define HI6220_TEMP0_LAG (0x0) diff --git a/drivers/thermal/imx8mm_thermal.c b/drivers/thermal/imx8mm_thermal.c index d4b40869c7d7..e89b11b3f2b9 100644 --- a/drivers/thermal/imx8mm_thermal.c +++ b/drivers/thermal/imx8mm_thermal.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <linux/nvmem-consumer.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/thermal.h> diff --git a/drivers/thermal/imx_sc_thermal.c b/drivers/thermal/imx_sc_thermal.c index 8d6b4ef23746..7224f8d21db9 100644 --- a/drivers/thermal/imx_sc_thermal.c +++ b/drivers/thermal/imx_sc_thermal.c @@ -8,7 +8,6 @@ #include <linux/firmware/imx/sci.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/thermal.h> diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index a94ec0a0c9dd..826358cbe810 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -11,7 +11,7 @@ #include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> +#include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/thermal.h> #include <linux/nvmem-consumer.h> diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c index 5e1164226ada..ddd600820f68 100644 --- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c @@ -15,6 +15,7 @@ #define INT3400_THERMAL_TABLE_CHANGED 0x83 #define INT3400_ODVP_CHANGED 0x88 #define INT3400_KEEP_ALIVE 0xA0 +#define INT3400_FAKE_TEMP (20 * 1000) /* faked temp sensor with 20C */ enum int3400_thermal_uuid { INT3400_THERMAL_ACTIVE = 0, @@ -453,6 +454,7 @@ static void int3400_notify(acpi_handle handle, void *data) { struct int3400_thermal_priv *priv = data; + struct device *dev; char *thermal_prop[5]; int therm_event; @@ -475,12 +477,14 @@ static void int3400_notify(acpi_handle handle, return; } - thermal_prop[0] = kasprintf(GFP_KERNEL, "NAME=%s", priv->thermal->type); - thermal_prop[1] = kasprintf(GFP_KERNEL, "TEMP=%d", priv->thermal->temperature); + dev = thermal_zone_device(priv->thermal); + + thermal_prop[0] = kasprintf(GFP_KERNEL, "NAME=%s", thermal_zone_device_type(priv->thermal)); + thermal_prop[1] = kasprintf(GFP_KERNEL, "TEMP=%d", INT3400_FAKE_TEMP); thermal_prop[2] = kasprintf(GFP_KERNEL, "TRIP="); thermal_prop[3] = kasprintf(GFP_KERNEL, "EVENT=%d", therm_event); thermal_prop[4] = NULL; - kobject_uevent_env(&priv->thermal->device.kobj, KOBJ_CHANGE, thermal_prop); + kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, thermal_prop); kfree(thermal_prop[0]); kfree(thermal_prop[1]); kfree(thermal_prop[2]); @@ -490,7 +494,7 @@ static void int3400_notify(acpi_handle handle, static int int3400_thermal_get_temp(struct thermal_zone_device *thermal, int *temp) { - *temp = 20 * 1000; /* faked temp sensor with 20C */ + *temp = INT3400_FAKE_TEMP; return 0; } @@ -499,32 +503,28 @@ static int int3400_thermal_change_mode(struct thermal_zone_device *thermal, { struct int3400_thermal_priv *priv = thermal_zone_device_priv(thermal); int result = 0; + int enabled; if (!priv) return -EINVAL; - if (mode != thermal->mode) { - int enabled; - - enabled = mode == THERMAL_DEVICE_ENABLED; + enabled = mode == THERMAL_DEVICE_ENABLED; - if (priv->os_uuid_mask) { - if (!enabled) { - priv->os_uuid_mask = 0; - result = set_os_uuid_mask(priv, priv->os_uuid_mask); - } - goto eval_odvp; + if (priv->os_uuid_mask) { + if (!enabled) { + priv->os_uuid_mask = 0; + result = set_os_uuid_mask(priv, priv->os_uuid_mask); } - - if (priv->current_uuid_index < 0 || - priv->current_uuid_index >= INT3400_THERMAL_MAXIMUM_UUID) - return -EINVAL; - - result = int3400_thermal_run_osc(priv->adev->handle, - int3400_thermal_uuids[priv->current_uuid_index], - &enabled); + goto eval_odvp; } + if (priv->current_uuid_index < 0 || + priv->current_uuid_index >= INT3400_THERMAL_MAXIMUM_UUID) + return -EINVAL; + + result = int3400_thermal_run_osc(priv->adev->handle, + int3400_thermal_uuids[priv->current_uuid_index], + &enabled); eval_odvp: evaluate_odvp(priv); diff --git a/drivers/thermal/intel/int340x_thermal/int3401_thermal.c b/drivers/thermal/intel/int340x_thermal/int3401_thermal.c index 217786fba185..c93a28eec4db 100644 --- a/drivers/thermal/intel/int340x_thermal/int3401_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3401_thermal.c @@ -70,18 +70,7 @@ static struct platform_driver int3401_driver = { }, }; -static int __init proc_thermal_init(void) -{ - return platform_driver_register(&int3401_driver); -} - -static void __exit proc_thermal_exit(void) -{ - platform_driver_unregister(&int3401_driver); -} - -module_init(proc_thermal_init); -module_exit(proc_thermal_exit); +module_platform_driver(int3401_driver); MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c index 09e032f822f3..16fd9df5f36d 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci_legacy.c @@ -59,7 +59,7 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev, * ACPI/MSR. So we don't want to fail for auxiliary DTSs. */ proc_priv->soc_dts = intel_soc_dts_iosf_init( - INTEL_SOC_DTS_INTERRUPT_MSI, 2, 0); + INTEL_SOC_DTS_INTERRUPT_MSI, false, 0); if (!IS_ERR(proc_priv->soc_dts) && pdev->irq) { ret = pci_enable_msi(pdev); diff --git a/drivers/thermal/intel/intel_soc_dts_iosf.c b/drivers/thermal/intel/intel_soc_dts_iosf.c index db97499f4f0a..d00def3c4703 100644 --- a/drivers/thermal/intel/intel_soc_dts_iosf.c +++ b/drivers/thermal/intel/intel_soc_dts_iosf.c @@ -37,44 +37,11 @@ /* DTS encoding for TJ MAX temperature */ #define SOC_DTS_TJMAX_ENCODING 0x7F -/* Only 2 out of 4 is allowed for OSPM */ -#define SOC_MAX_DTS_TRIPS 2 - /* Mask for two trips in status bits */ #define SOC_DTS_TRIP_MASK 0x03 -/* DTS0 and DTS 1 */ -#define SOC_MAX_DTS_SENSORS 2 - -static int sys_get_trip_temp(struct thermal_zone_device *tzd, int trip, - int *temp) -{ - int status; - u32 out; - struct intel_soc_dts_sensor_entry *dts; - struct intel_soc_dts_sensors *sensors; - - dts = thermal_zone_device_priv(tzd); - sensors = dts->sensors; - mutex_lock(&sensors->dts_update_lock); - status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, - SOC_DTS_OFFSET_PTPS, &out); - mutex_unlock(&sensors->dts_update_lock); - if (status) - return status; - - out = (out >> (trip * 8)) & SOC_DTS_TJMAX_ENCODING; - if (!out) - *temp = 0; - else - *temp = sensors->tj_max - out * 1000; - - return 0; -} - -static int update_trip_temp(struct intel_soc_dts_sensor_entry *dts, - int thres_index, int temp, - enum thermal_trip_type trip_type) +static int update_trip_temp(struct intel_soc_dts_sensors *sensors, + int thres_index, int temp) { int status; u32 temp_out; @@ -85,7 +52,6 @@ static int update_trip_temp(struct intel_soc_dts_sensor_entry *dts, u32 store_te_out; u32 te_out; u32 int_enable_bit = SOC_DTS_TE_APICA_ENABLE; - struct intel_soc_dts_sensors *sensors = dts->sensors; if (sensors->intr_type == INTEL_SOC_DTS_INTERRUPT_MSI) int_enable_bit |= SOC_DTS_TE_MSI_ENABLE; @@ -148,8 +114,6 @@ static int update_trip_temp(struct intel_soc_dts_sensor_entry *dts, if (status) goto err_restore_te_out; - dts->trip_types[thres_index] = trip_type; - return 0; err_restore_te_out: iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, @@ -165,6 +129,22 @@ err_restore_ptps: return status; } +static int configure_trip(struct intel_soc_dts_sensor_entry *dts, + int thres_index, enum thermal_trip_type trip_type, + int temp) +{ + int ret; + + ret = update_trip_temp(dts->sensors, thres_index, temp); + if (ret) + return ret; + + dts->trips[thres_index].temperature = temp; + dts->trips[thres_index].type = trip_type; + + return 0; +} + static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp) { @@ -176,23 +156,12 @@ static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, return -EINVAL; mutex_lock(&sensors->dts_update_lock); - status = update_trip_temp(dts, trip, temp, - dts->trip_types[trip]); + status = update_trip_temp(sensors, trip, temp); mutex_unlock(&sensors->dts_update_lock); return status; } -static int sys_get_trip_type(struct thermal_zone_device *tzd, - int trip, enum thermal_trip_type *type) -{ - struct intel_soc_dts_sensor_entry *dts = thermal_zone_device_priv(tzd); - - *type = dts->trip_types[trip]; - - return 0; -} - static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp) { @@ -217,8 +186,6 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, static struct thermal_zone_device_ops tzone_ops = { .get_temp = sys_get_curr_temp, - .get_trip_temp = sys_get_trip_temp, - .get_trip_type = sys_get_trip_type, .set_trip_temp = sys_set_trip_temp, }; @@ -245,22 +212,18 @@ static int soc_dts_enable(int id) static void remove_dts_thermal_zone(struct intel_soc_dts_sensor_entry *dts) { - if (dts) { - iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, - SOC_DTS_OFFSET_ENABLE, dts->store_status); - thermal_zone_device_unregister(dts->tzone); - } + iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, + SOC_DTS_OFFSET_ENABLE, dts->store_status); + thermal_zone_device_unregister(dts->tzone); } static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts, - bool notification_support, int trip_cnt, - int read_only_trip_cnt) + bool critical_trip) { + int writable_trip_cnt = SOC_MAX_DTS_TRIPS; char name[10]; unsigned long trip; - int trip_count = 0; - int trip_mask = 0; - int writable_trip_cnt = 0; + int trip_mask; unsigned long ptps; u32 store_ptps; unsigned long i; @@ -273,11 +236,11 @@ static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts, goto err_ret; dts->id = id; - if (notification_support) { - trip_count = min(SOC_MAX_DTS_TRIPS, trip_cnt); - writable_trip_cnt = trip_count - read_only_trip_cnt; - trip_mask = GENMASK(writable_trip_cnt - 1, 0); - } + + if (critical_trip) + writable_trip_cnt--; + + trip_mask = GENMASK(writable_trip_cnt - 1, 0); /* Check if the writable trip we provide is not used by BIOS */ ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, @@ -290,13 +253,12 @@ static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts, trip_mask &= ~BIT(i / 8); } dts->trip_mask = trip_mask; - dts->trip_count = trip_count; snprintf(name, sizeof(name), "soc_dts%d", id); - dts->tzone = thermal_zone_device_register(name, - trip_count, - trip_mask, - dts, &tzone_ops, - NULL, 0, 0); + dts->tzone = thermal_zone_device_register_with_trips(name, dts->trips, + SOC_MAX_DTS_TRIPS, + trip_mask, + dts, &tzone_ops, + NULL, 0, 0); if (IS_ERR(dts->tzone)) { ret = PTR_ERR(dts->tzone); goto err_ret; @@ -316,26 +278,6 @@ err_ret: return ret; } -int intel_soc_dts_iosf_add_read_only_critical_trip( - struct intel_soc_dts_sensors *sensors, int critical_offset) -{ - int i, j; - - for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) { - struct intel_soc_dts_sensor_entry *entry = &sensors->soc_dts[i]; - int temp = sensors->tj_max - critical_offset; - unsigned long count = entry->trip_count; - unsigned long mask = entry->trip_mask; - - j = find_first_zero_bit(&mask, count); - if (j < count) - return update_trip_temp(entry, j, temp, THERMAL_TRIP_CRITICAL); - } - - return -EINVAL; -} -EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_add_read_only_critical_trip); - void intel_soc_dts_iosf_interrupt_handler(struct intel_soc_dts_sensors *sensors) { u32 sticky_out; @@ -371,12 +313,17 @@ void intel_soc_dts_iosf_interrupt_handler(struct intel_soc_dts_sensors *sensors) } EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_interrupt_handler); -struct intel_soc_dts_sensors *intel_soc_dts_iosf_init( - enum intel_soc_dts_interrupt_type intr_type, int trip_count, - int read_only_trip_count) +static void dts_trips_reset(struct intel_soc_dts_sensors *sensors, int dts_index) +{ + configure_trip(&sensors->soc_dts[dts_index], 0, 0, 0); + configure_trip(&sensors->soc_dts[dts_index], 1, 0, 0); +} + +struct intel_soc_dts_sensors * +intel_soc_dts_iosf_init(enum intel_soc_dts_interrupt_type intr_type, + bool critical_trip, int crit_offset) { struct intel_soc_dts_sensors *sensors; - bool notification; int tj_max; int ret; int i; @@ -384,9 +331,6 @@ struct intel_soc_dts_sensors *intel_soc_dts_iosf_init( if (!iosf_mbi_available()) return ERR_PTR(-ENODEV); - if (!trip_count || read_only_trip_count > trip_count) - return ERR_PTR(-EINVAL); - tj_max = intel_tcc_get_tjmax(-1); if (tj_max < 0) return ERR_PTR(tj_max); @@ -399,37 +343,46 @@ struct intel_soc_dts_sensors *intel_soc_dts_iosf_init( mutex_init(&sensors->dts_update_lock); sensors->intr_type = intr_type; sensors->tj_max = tj_max * 1000; - if (intr_type == INTEL_SOC_DTS_INTERRUPT_NONE) - notification = false; - else - notification = true; + for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) { + enum thermal_trip_type trip_type; + int temp; + sensors->soc_dts[i].sensors = sensors; - ret = add_dts_thermal_zone(i, &sensors->soc_dts[i], - notification, trip_count, - read_only_trip_count); + + ret = configure_trip(&sensors->soc_dts[i], 0, + THERMAL_TRIP_PASSIVE, 0); + if (ret) + goto err_reset_trips; + + if (critical_trip) { + trip_type = THERMAL_TRIP_CRITICAL; + temp = sensors->tj_max - crit_offset; + } else { + trip_type = THERMAL_TRIP_PASSIVE; + temp = 0; + } + ret = configure_trip(&sensors->soc_dts[i], 1, trip_type, temp); if (ret) - goto err_free; + goto err_reset_trips; } for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) { - ret = update_trip_temp(&sensors->soc_dts[i], 0, 0, - THERMAL_TRIP_PASSIVE); - if (ret) - goto err_remove_zone; - - ret = update_trip_temp(&sensors->soc_dts[i], 1, 0, - THERMAL_TRIP_PASSIVE); + ret = add_dts_thermal_zone(i, &sensors->soc_dts[i], critical_trip); if (ret) goto err_remove_zone; } return sensors; + err_remove_zone: for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) remove_dts_thermal_zone(&sensors->soc_dts[i]); -err_free: +err_reset_trips: + for (i = 0; i < SOC_MAX_DTS_SENSORS; i++) + dts_trips_reset(sensors, i); + kfree(sensors); return ERR_PTR(ret); } @@ -440,9 +393,8 @@ void intel_soc_dts_iosf_exit(struct intel_soc_dts_sensors *sensors) int i; for (i = 0; i < SOC_MAX_DTS_SENSORS; ++i) { - update_trip_temp(&sensors->soc_dts[i], 0, 0, 0); - update_trip_temp(&sensors->soc_dts[i], 1, 0, 0); remove_dts_thermal_zone(&sensors->soc_dts[i]); + dts_trips_reset(sensors, i); } kfree(sensors); } diff --git a/drivers/thermal/intel/intel_soc_dts_iosf.h b/drivers/thermal/intel/intel_soc_dts_iosf.h index c54945748200..162841df0ebe 100644 --- a/drivers/thermal/intel/intel_soc_dts_iosf.h +++ b/drivers/thermal/intel/intel_soc_dts_iosf.h @@ -12,6 +12,9 @@ /* DTS0 and DTS 1 */ #define SOC_MAX_DTS_SENSORS 2 +/* Only 2 out of 4 is allowed for OSPM */ +#define SOC_MAX_DTS_TRIPS 2 + enum intel_soc_dts_interrupt_type { INTEL_SOC_DTS_INTERRUPT_NONE, INTEL_SOC_DTS_INTERRUPT_APIC, @@ -26,8 +29,7 @@ struct intel_soc_dts_sensor_entry { int id; u32 store_status; u32 trip_mask; - u32 trip_count; - enum thermal_trip_type trip_types[2]; + struct thermal_trip trips[SOC_MAX_DTS_TRIPS]; struct thermal_zone_device *tzone; struct intel_soc_dts_sensors *sensors; }; @@ -40,12 +42,11 @@ struct intel_soc_dts_sensors { struct intel_soc_dts_sensor_entry soc_dts[SOC_MAX_DTS_SENSORS]; }; -struct intel_soc_dts_sensors *intel_soc_dts_iosf_init( - enum intel_soc_dts_interrupt_type intr_type, int trip_count, - int read_only_trip_count); + +struct intel_soc_dts_sensors * +intel_soc_dts_iosf_init(enum intel_soc_dts_interrupt_type intr_type, + bool critical_trip, int crit_offset); void intel_soc_dts_iosf_exit(struct intel_soc_dts_sensors *sensors); void intel_soc_dts_iosf_interrupt_handler( struct intel_soc_dts_sensors *sensors); -int intel_soc_dts_iosf_add_read_only_critical_trip( - struct intel_soc_dts_sensors *sensors, int critical_offset); #endif diff --git a/drivers/thermal/intel/intel_soc_dts_thermal.c b/drivers/thermal/intel/intel_soc_dts_thermal.c index 92e5c19d03f6..9c825c6e1f38 100644 --- a/drivers/thermal/intel/intel_soc_dts_thermal.c +++ b/drivers/thermal/intel/intel_soc_dts_thermal.c @@ -51,7 +51,8 @@ static int __init intel_soc_thermal_init(void) return -ENODEV; /* Create a zone with 2 trips with marked as read only */ - soc_dts = intel_soc_dts_iosf_init(INTEL_SOC_DTS_INTERRUPT_APIC, 2, 1); + soc_dts = intel_soc_dts_iosf_init(INTEL_SOC_DTS_INTERRUPT_APIC, true, + crit_offset); if (IS_ERR(soc_dts)) { err = PTR_ERR(soc_dts); return err; @@ -88,21 +89,7 @@ static int __init intel_soc_thermal_init(void) } } - err = intel_soc_dts_iosf_add_read_only_critical_trip(soc_dts, - crit_offset); - if (err) - goto error_trips; - return 0; - -error_trips: - if (soc_dts_thres_irq) { - free_irq(soc_dts_thres_irq, soc_dts); - acpi_unregister_gsi(soc_dts_thres_gsi); - } - intel_soc_dts_iosf_exit(soc_dts); - - return err; } static void __exit intel_soc_thermal_exit(void) diff --git a/drivers/thermal/intel/intel_tcc_cooling.c b/drivers/thermal/intel/intel_tcc_cooling.c index e95f799454fe..6c392147e6d1 100644 --- a/drivers/thermal/intel/intel_tcc_cooling.c +++ b/drivers/thermal/intel/intel_tcc_cooling.c @@ -60,7 +60,7 @@ static const struct x86_cpu_id tcc_ids[] __initconst = { X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE, NULL), X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, NULL), X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, NULL), - X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, NULL), + X86_MATCH_INTEL_FAM6_MODEL(ATOM_GRACEMONT, NULL), X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE, NULL), X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P, NULL), X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_S, NULL), diff --git a/drivers/thermal/k3_bandgap.c b/drivers/thermal/k3_bandgap.c index 1c3e590157ec..68f59b3735d3 100644 --- a/drivers/thermal/k3_bandgap.c +++ b/drivers/thermal/k3_bandgap.c @@ -11,7 +11,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_platform.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/thermal.h> #include <linux/types.h> diff --git a/drivers/thermal/k3_j72xx_bandgap.c b/drivers/thermal/k3_j72xx_bandgap.c index 5be1f09eeb2c..a5a0fc9b9356 100644 --- a/drivers/thermal/k3_j72xx_bandgap.c +++ b/drivers/thermal/k3_j72xx_bandgap.c @@ -10,10 +10,10 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/err.h> #include <linux/types.h> -#include <linux/of_platform.h> #include <linux/io.h> #include <linux/thermal.h> #include <linux/of.h> diff --git a/drivers/thermal/mediatek/auxadc_thermal.c b/drivers/thermal/mediatek/auxadc_thermal.c index f59d36de20a0..c537aed71017 100644 --- a/drivers/thermal/mediatek/auxadc_thermal.c +++ b/drivers/thermal/mediatek/auxadc_thermal.c @@ -15,7 +15,6 @@ #include <linux/nvmem-consumer.h> #include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/io.h> diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c index b693fac2d677..054c965ae5e1 100644 --- a/drivers/thermal/mediatek/lvts_thermal.c +++ b/drivers/thermal/mediatek/lvts_thermal.c @@ -13,7 +13,7 @@ #include <linux/iopoll.h> #include <linux/kernel.h> #include <linux/nvmem-consumer.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/reset.h> #include <linux/thermal.h> diff --git a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c index 5ddc39b2be32..756ac6842ff9 100644 --- a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c +++ b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c @@ -14,7 +14,6 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/thermal.h> diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c index 0e8ebfcd84c5..78c5cfe6a0c0 100644 --- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c +++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c @@ -10,7 +10,6 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/thermal.h> diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index 9029d01e029b..bd2fb8c2e968 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c @@ -11,7 +11,7 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/thermal.h> diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index b8571f7090aa..293f8dd9fe0a 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -11,7 +11,7 @@ #include <linux/interrupt.h> #include <linux/io.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/reboot.h> diff --git a/drivers/thermal/rzg2l_thermal.c b/drivers/thermal/rzg2l_thermal.c index b56981f85306..6b2bf3426f52 100644 --- a/drivers/thermal/rzg2l_thermal.c +++ b/drivers/thermal/rzg2l_thermal.c @@ -9,8 +9,8 @@ #include <linux/io.h> #include <linux/iopoll.h> #include <linux/math.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/reset.h> diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index 45e5c840d130..58f4d8f7a3fd 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -15,7 +15,7 @@ #include <linux/io.h> #include <linux/interrupt.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/platform_device.h> diff --git a/drivers/thermal/sprd_thermal.c b/drivers/thermal/sprd_thermal.c index 2fb90fdad76e..e27c4bdc8912 100644 --- a/drivers/thermal/sprd_thermal.c +++ b/drivers/thermal/sprd_thermal.c @@ -6,7 +6,7 @@ #include <linux/iopoll.h> #include <linux/module.h> #include <linux/nvmem-consumer.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/thermal.h> diff --git a/drivers/thermal/st/stm_thermal.c b/drivers/thermal/st/stm_thermal.c index 903fcf1763f1..142a7e5d12f4 100644 --- a/drivers/thermal/st/stm_thermal.c +++ b/drivers/thermal/st/stm_thermal.c @@ -14,8 +14,6 @@ #include <linux/iopoll.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_address.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/thermal.h> diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c index 195f3c5d0b38..cca16d632d9f 100644 --- a/drivers/thermal/sun8i_thermal.c +++ b/drivers/thermal/sun8i_thermal.c @@ -14,7 +14,7 @@ #include <linux/interrupt.h> #include <linux/module.h> #include <linux/nvmem-consumer.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/reset.h> diff --git a/drivers/thermal/tegra/tegra30-tsensor.c b/drivers/thermal/tegra/tegra30-tsensor.c index c243e9d76d3c..d911fa60f100 100644 --- a/drivers/thermal/tegra/tegra30-tsensor.c +++ b/drivers/thermal/tegra/tegra30-tsensor.c @@ -18,7 +18,7 @@ #include <linux/iopoll.h> #include <linux/math.h> #include <linux/module.h> -#include <linux/of_device.h> +#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm.h> #include <linux/reset.h> diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index cc2b5e81c620..a59700593d32 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -348,7 +348,8 @@ static void handle_thermal_trip(struct thermal_zone_device *tz, int trip_id) struct thermal_trip trip; /* Ignore disabled trip points */ - if (test_bit(trip_id, &tz->trips_disabled)) + if (test_bit(trip_id, &tz->trips_disabled) || + trip.temperature == THERMAL_TEMP_INVALID) return; __thermal_zone_get_trip(tz, trip_id, &trip); @@ -496,6 +497,25 @@ void thermal_zone_device_update(struct thermal_zone_device *tz, } EXPORT_SYMBOL_GPL(thermal_zone_device_update); +/** + * thermal_zone_device_exec - Run a callback under the zone lock. + * @tz: Thermal zone. + * @cb: Callback to run. + * @data: Data to pass to the callback. + */ +void thermal_zone_device_exec(struct thermal_zone_device *tz, + void (*cb)(struct thermal_zone_device *, + unsigned long), + unsigned long data) +{ + mutex_lock(&tz->lock); + + cb(tz, data); + + mutex_unlock(&tz->lock); +} +EXPORT_SYMBOL_GPL(thermal_zone_device_exec); + static void thermal_zone_device_check(struct work_struct *work) { struct thermal_zone_device *tz = container_of(work, struct diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h index 17c1bbed734d..04513f9fbfa1 100644 --- a/drivers/thermal/thermal_core.h +++ b/drivers/thermal/thermal_core.h @@ -54,10 +54,6 @@ int for_each_thermal_cooling_device(int (*cb)(struct thermal_cooling_device *, int for_each_thermal_governor(int (*cb)(struct thermal_governor *, void *), void *thermal_governor); -int __for_each_thermal_trip(struct thermal_zone_device *, - int (*cb)(struct thermal_trip *, void *), - void *); - struct thermal_zone_device *thermal_zone_get_by_id(int id); struct thermal_attr { diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index bc07ae1c284c..4ca905723429 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -10,8 +10,7 @@ #include <linux/err.h> #include <linux/export.h> -#include <linux/of_device.h> -#include <linux/of_platform.h> +#include <linux/of.h> #include <linux/slab.h> #include <linux/thermal.h> #include <linux/types.h> @@ -292,13 +291,13 @@ static int __thermal_of_unbind(struct device_node *map_np, int index, int trip_i ret = of_parse_phandle_with_args(map_np, "cooling-device", "#cooling-cells", index, &cooling_spec); - of_node_put(cooling_spec.np); - if (ret < 0) { pr_err("Invalid cooling-device entry\n"); return ret; } + of_node_put(cooling_spec.np); + if (cooling_spec.args_count < 2) { pr_err("wrong reference to cooling device, missing limits\n"); return -EINVAL; @@ -325,13 +324,13 @@ static int __thermal_of_bind(struct device_node *map_np, int index, int trip_id, ret = of_parse_phandle_with_args(map_np, "cooling-device", "#cooling-cells", index, &cooling_spec); - of_node_put(cooling_spec.np); - if (ret < 0) { pr_err("Invalid cooling-device entry\n"); return ret; } + of_node_put(cooling_spec.np); + if (cooling_spec.args_count < 2) { pr_err("wrong reference to cooling device, missing limits\n"); return -EINVAL; diff --git a/drivers/thermal/thermal_trip.c b/drivers/thermal/thermal_trip.c index 907f3a4d7bc8..53115cfdfd42 100644 --- a/drivers/thermal/thermal_trip.c +++ b/drivers/thermal/thermal_trip.c @@ -9,28 +9,26 @@ */ #include "thermal_core.h" -int __for_each_thermal_trip(struct thermal_zone_device *tz, - int (*cb)(struct thermal_trip *, void *), - void *data) +int for_each_thermal_trip(struct thermal_zone_device *tz, + int (*cb)(struct thermal_trip *, void *), + void *data) { int i, ret; - struct thermal_trip trip; lockdep_assert_held(&tz->lock); - for (i = 0; i < tz->num_trips; i++) { - - ret = __thermal_zone_get_trip(tz, i, &trip); - if (ret) - return ret; + if (!tz->trips) + return -ENODATA; - ret = cb(&trip, data); + for (i = 0; i < tz->num_trips; i++) { + ret = cb(&tz->trips[i], data); if (ret) return ret; } return 0; } +EXPORT_SYMBOL_GPL(for_each_thermal_trip); int thermal_zone_get_num_trips(struct thermal_zone_device *tz) { diff --git a/drivers/thermal/uniphier_thermal.c b/drivers/thermal/uniphier_thermal.c index aef6119cc004..6f32ab61d174 100644 --- a/drivers/thermal/uniphier_thermal.c +++ b/drivers/thermal/uniphier_thermal.c @@ -12,7 +12,6 @@ #include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/thermal.h> diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c index 6fb0e007af63..386674ead7f0 100644 --- a/drivers/ufs/core/ufs-mcq.c +++ b/drivers/ufs/core/ufs-mcq.c @@ -580,7 +580,6 @@ static bool ufshcd_mcq_sqe_search(struct ufs_hba *hba, { struct ufshcd_lrb *lrbp = &hba->lrb[task_tag]; struct utp_transfer_req_desc *utrd; - u32 mask = hwq->max_entries - 1; __le64 cmd_desc_base_addr; bool ret = false; u64 addr, match; @@ -608,7 +607,10 @@ static bool ufshcd_mcq_sqe_search(struct ufs_hba *hba, ret = true; goto out; } - sq_head_slot = (sq_head_slot + 1) & mask; + + sq_head_slot++; + if (sq_head_slot == hwq->max_entries) + sq_head_slot = 0; } out: diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 8d6fd4c3324f..c1557d21b027 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -321,7 +321,7 @@ static void ufs_qcom_select_unipro_mode(struct ufs_qcom_host *host) ufs_qcom_cap_qunipro(host) ? QUNIPRO_SEL : 0, REG_UFS_CFG1); - if (host->hw_ver.major == 0x05) + if (host->hw_ver.major >= 0x05) ufshcd_rmwl(host->hba, QUNIPRO_G4_SEL, 0, REG_UFS_CFG0); /* make sure above configuration is applied before we return */ diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 1a16a8bdea60..4f68f6ef3cc1 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -2642,21 +2642,21 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, snoop(&dev->dev, "%s: CONTROL\n", __func__); ret = proc_control(ps, p); if (ret >= 0) - inode->i_mtime = inode->i_ctime = current_time(inode); + inode->i_mtime = inode_set_ctime_current(inode); break; case USBDEVFS_BULK: snoop(&dev->dev, "%s: BULK\n", __func__); ret = proc_bulk(ps, p); if (ret >= 0) - inode->i_mtime = inode->i_ctime = current_time(inode); + inode->i_mtime = inode_set_ctime_current(inode); break; case USBDEVFS_RESETEP: snoop(&dev->dev, "%s: RESETEP\n", __func__); ret = proc_resetep(ps, p); if (ret >= 0) - inode->i_mtime = inode->i_ctime = current_time(inode); + inode->i_mtime = inode_set_ctime_current(inode); break; case USBDEVFS_RESET: @@ -2668,7 +2668,7 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, snoop(&dev->dev, "%s: CLEAR_HALT\n", __func__); ret = proc_clearhalt(ps, p); if (ret >= 0) - inode->i_mtime = inode->i_ctime = current_time(inode); + inode->i_mtime = inode_set_ctime_current(inode); break; case USBDEVFS_GETDRIVER: @@ -2695,7 +2695,7 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, snoop(&dev->dev, "%s: SUBMITURB\n", __func__); ret = proc_submiturb(ps, p); if (ret >= 0) - inode->i_mtime = inode->i_ctime = current_time(inode); + inode->i_mtime = inode_set_ctime_current(inode); break; #ifdef CONFIG_COMPAT @@ -2703,14 +2703,14 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, snoop(&dev->dev, "%s: CONTROL32\n", __func__); ret = proc_control_compat(ps, p); if (ret >= 0) - inode->i_mtime = inode->i_ctime = current_time(inode); + inode->i_mtime = inode_set_ctime_current(inode); break; case USBDEVFS_BULK32: snoop(&dev->dev, "%s: BULK32\n", __func__); ret = proc_bulk_compat(ps, p); if (ret >= 0) - inode->i_mtime = inode->i_ctime = current_time(inode); + inode->i_mtime = inode_set_ctime_current(inode); break; case USBDEVFS_DISCSIGNAL32: @@ -2722,7 +2722,7 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, snoop(&dev->dev, "%s: SUBMITURB32\n", __func__); ret = proc_submiturb_compat(ps, p); if (ret >= 0) - inode->i_mtime = inode->i_ctime = current_time(inode); + inode->i_mtime = inode_set_ctime_current(inode); break; case USBDEVFS_IOCTL32: diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index f41a385a5c42..6e9ef35a43a7 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1377,7 +1377,7 @@ ffs_sb_make_inode(struct super_block *sb, void *data, inode = new_inode(sb); if (inode) { - struct timespec64 ts = current_time(inode); + struct timespec64 ts = inode_set_ctime_current(inode); inode->i_ino = get_next_ino(); inode->i_mode = perms->mode; @@ -1385,7 +1385,6 @@ ffs_sb_make_inode(struct super_block *sb, void *data, inode->i_gid = perms->gid; inode->i_atime = ts; inode->i_mtime = ts; - inode->i_ctime = ts; inode->i_private = data; if (fops) inode->i_fop = fops; diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 28249d0bf062..ce9e31f3d26b 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -1969,8 +1969,7 @@ gadgetfs_make_inode (struct super_block *sb, inode->i_mode = mode; inode->i_uid = make_kuid(&init_user_ns, default_uid); inode->i_gid = make_kgid(&init_user_ns, default_gid); - inode->i_atime = inode->i_mtime = inode->i_ctime - = current_time(inode); + inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode); inode->i_private = data; inode->i_fop = fops; } diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index d5d7c402b651..d43153fec18e 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -269,6 +269,13 @@ config XEN_PRIVCMD disaggregated Xen setups this driver might be needed for other domains, too. +config XEN_PRIVCMD_IRQFD + bool "Xen irqfd support" + depends on XEN_PRIVCMD && XEN_VIRTIO && EVENTFD + help + Using the irqfd mechanism a virtio backend running in a daemon can + speed up interrupt injection into a guest. + config XEN_ACPI_PROCESSOR tristate "Xen ACPI processor" depends on XEN && XEN_PV_DOM0 && X86 && ACPI_PROCESSOR && CPU_FREQ diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index f13c3b76ad1e..35659bf70746 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -1044,7 +1044,7 @@ EXPORT_SYMBOL_GPL(gnttab_pages_clear_private); /** * gnttab_free_pages - free pages allocated by gnttab_alloc_pages() - * @nr_pages; number of pages to free + * @nr_pages: number of pages to free * @pages: the pages */ void gnttab_free_pages(int nr_pages, struct page **pages) diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index f447cd37cc4c..f00ad5f5f1d4 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c @@ -9,11 +9,16 @@ #define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt +#include <linux/eventfd.h> +#include <linux/file.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/mutex.h> +#include <linux/poll.h> #include <linux/sched.h> #include <linux/slab.h> #include <linux/string.h> +#include <linux/workqueue.h> #include <linux/errno.h> #include <linux/mm.h> #include <linux/mman.h> @@ -833,6 +838,263 @@ out: return rc; } +#ifdef CONFIG_XEN_PRIVCMD_IRQFD +/* Irqfd support */ +static struct workqueue_struct *irqfd_cleanup_wq; +static DEFINE_MUTEX(irqfds_lock); +static LIST_HEAD(irqfds_list); + +struct privcmd_kernel_irqfd { + struct xen_dm_op_buf xbufs; + domid_t dom; + bool error; + struct eventfd_ctx *eventfd; + struct work_struct shutdown; + wait_queue_entry_t wait; + struct list_head list; + poll_table pt; +}; + +static void irqfd_deactivate(struct privcmd_kernel_irqfd *kirqfd) +{ + lockdep_assert_held(&irqfds_lock); + + list_del_init(&kirqfd->list); + queue_work(irqfd_cleanup_wq, &kirqfd->shutdown); +} + +static void irqfd_shutdown(struct work_struct *work) +{ + struct privcmd_kernel_irqfd *kirqfd = + container_of(work, struct privcmd_kernel_irqfd, shutdown); + u64 cnt; + + eventfd_ctx_remove_wait_queue(kirqfd->eventfd, &kirqfd->wait, &cnt); + eventfd_ctx_put(kirqfd->eventfd); + kfree(kirqfd); +} + +static void irqfd_inject(struct privcmd_kernel_irqfd *kirqfd) +{ + u64 cnt; + long rc; + + eventfd_ctx_do_read(kirqfd->eventfd, &cnt); + + xen_preemptible_hcall_begin(); + rc = HYPERVISOR_dm_op(kirqfd->dom, 1, &kirqfd->xbufs); + xen_preemptible_hcall_end(); + + /* Don't repeat the error message for consecutive failures */ + if (rc && !kirqfd->error) { + pr_err("Failed to configure irq for guest domain: %d\n", + kirqfd->dom); + } + + kirqfd->error = rc; +} + +static int +irqfd_wakeup(wait_queue_entry_t *wait, unsigned int mode, int sync, void *key) +{ + struct privcmd_kernel_irqfd *kirqfd = + container_of(wait, struct privcmd_kernel_irqfd, wait); + __poll_t flags = key_to_poll(key); + + if (flags & EPOLLIN) + irqfd_inject(kirqfd); + + if (flags & EPOLLHUP) { + mutex_lock(&irqfds_lock); + irqfd_deactivate(kirqfd); + mutex_unlock(&irqfds_lock); + } + + return 0; +} + +static void +irqfd_poll_func(struct file *file, wait_queue_head_t *wqh, poll_table *pt) +{ + struct privcmd_kernel_irqfd *kirqfd = + container_of(pt, struct privcmd_kernel_irqfd, pt); + + add_wait_queue_priority(wqh, &kirqfd->wait); +} + +static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd) +{ + struct privcmd_kernel_irqfd *kirqfd, *tmp; + __poll_t events; + struct fd f; + void *dm_op; + int ret; + + kirqfd = kzalloc(sizeof(*kirqfd) + irqfd->size, GFP_KERNEL); + if (!kirqfd) + return -ENOMEM; + dm_op = kirqfd + 1; + + if (copy_from_user(dm_op, irqfd->dm_op, irqfd->size)) { + ret = -EFAULT; + goto error_kfree; + } + + kirqfd->xbufs.size = irqfd->size; + set_xen_guest_handle(kirqfd->xbufs.h, dm_op); + kirqfd->dom = irqfd->dom; + INIT_WORK(&kirqfd->shutdown, irqfd_shutdown); + + f = fdget(irqfd->fd); + if (!f.file) { + ret = -EBADF; + goto error_kfree; + } + + kirqfd->eventfd = eventfd_ctx_fileget(f.file); + if (IS_ERR(kirqfd->eventfd)) { + ret = PTR_ERR(kirqfd->eventfd); + goto error_fd_put; + } + + /* + * Install our own custom wake-up handling so we are notified via a + * callback whenever someone signals the underlying eventfd. + */ + init_waitqueue_func_entry(&kirqfd->wait, irqfd_wakeup); + init_poll_funcptr(&kirqfd->pt, irqfd_poll_func); + + mutex_lock(&irqfds_lock); + + list_for_each_entry(tmp, &irqfds_list, list) { + if (kirqfd->eventfd == tmp->eventfd) { + ret = -EBUSY; + mutex_unlock(&irqfds_lock); + goto error_eventfd; + } + } + + list_add_tail(&kirqfd->list, &irqfds_list); + mutex_unlock(&irqfds_lock); + + /* + * Check if there was an event already pending on the eventfd before we + * registered, and trigger it as if we didn't miss it. + */ + events = vfs_poll(f.file, &kirqfd->pt); + if (events & EPOLLIN) + irqfd_inject(kirqfd); + + /* + * Do not drop the file until the kirqfd is fully initialized, otherwise + * we might race against the EPOLLHUP. + */ + fdput(f); + return 0; + +error_eventfd: + eventfd_ctx_put(kirqfd->eventfd); + +error_fd_put: + fdput(f); + +error_kfree: + kfree(kirqfd); + return ret; +} + +static int privcmd_irqfd_deassign(struct privcmd_irqfd *irqfd) +{ + struct privcmd_kernel_irqfd *kirqfd; + struct eventfd_ctx *eventfd; + + eventfd = eventfd_ctx_fdget(irqfd->fd); + if (IS_ERR(eventfd)) + return PTR_ERR(eventfd); + + mutex_lock(&irqfds_lock); + + list_for_each_entry(kirqfd, &irqfds_list, list) { + if (kirqfd->eventfd == eventfd) { + irqfd_deactivate(kirqfd); + break; + } + } + + mutex_unlock(&irqfds_lock); + + eventfd_ctx_put(eventfd); + + /* + * Block until we know all outstanding shutdown jobs have completed so + * that we guarantee there will not be any more interrupts once this + * deassign function returns. + */ + flush_workqueue(irqfd_cleanup_wq); + + return 0; +} + +static long privcmd_ioctl_irqfd(struct file *file, void __user *udata) +{ + struct privcmd_data *data = file->private_data; + struct privcmd_irqfd irqfd; + + if (copy_from_user(&irqfd, udata, sizeof(irqfd))) + return -EFAULT; + + /* No other flags should be set */ + if (irqfd.flags & ~PRIVCMD_IRQFD_FLAG_DEASSIGN) + return -EINVAL; + + /* If restriction is in place, check the domid matches */ + if (data->domid != DOMID_INVALID && data->domid != irqfd.dom) + return -EPERM; + + if (irqfd.flags & PRIVCMD_IRQFD_FLAG_DEASSIGN) + return privcmd_irqfd_deassign(&irqfd); + + return privcmd_irqfd_assign(&irqfd); +} + +static int privcmd_irqfd_init(void) +{ + irqfd_cleanup_wq = alloc_workqueue("privcmd-irqfd-cleanup", 0, 0); + if (!irqfd_cleanup_wq) + return -ENOMEM; + + return 0; +} + +static void privcmd_irqfd_exit(void) +{ + struct privcmd_kernel_irqfd *kirqfd, *tmp; + + mutex_lock(&irqfds_lock); + + list_for_each_entry_safe(kirqfd, tmp, &irqfds_list, list) + irqfd_deactivate(kirqfd); + + mutex_unlock(&irqfds_lock); + + destroy_workqueue(irqfd_cleanup_wq); +} +#else +static inline long privcmd_ioctl_irqfd(struct file *file, void __user *udata) +{ + return -EOPNOTSUPP; +} + +static inline int privcmd_irqfd_init(void) +{ + return 0; +} + +static inline void privcmd_irqfd_exit(void) +{ +} +#endif /* CONFIG_XEN_PRIVCMD_IRQFD */ + static long privcmd_ioctl(struct file *file, unsigned int cmd, unsigned long data) { @@ -868,6 +1130,10 @@ static long privcmd_ioctl(struct file *file, ret = privcmd_ioctl_mmap_resource(file, udata); break; + case IOCTL_PRIVCMD_IRQFD: + ret = privcmd_ioctl_irqfd(file, udata); + break; + default: break; } @@ -992,15 +1258,27 @@ static int __init privcmd_init(void) err = misc_register(&xen_privcmdbuf_dev); if (err != 0) { pr_err("Could not register Xen hypercall-buf device\n"); - misc_deregister(&privcmd_dev); - return err; + goto err_privcmdbuf; + } + + err = privcmd_irqfd_init(); + if (err != 0) { + pr_err("irqfd init failed\n"); + goto err_irqfd; } return 0; + +err_irqfd: + misc_deregister(&xen_privcmdbuf_dev); +err_privcmdbuf: + misc_deregister(&privcmd_dev); + return err; } static void __exit privcmd_exit(void) { + privcmd_irqfd_exit(); misc_deregister(&privcmd_dev); misc_deregister(&xen_privcmdbuf_dev); } diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c index 9cb61db67efd..296703939846 100644 --- a/drivers/xen/xen-acpi-processor.c +++ b/drivers/xen/xen-acpi-processor.c @@ -473,11 +473,8 @@ static int xen_upload_processor_pm_data(void) if (!_pr) continue; - if (!pr_backup) { - pr_backup = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL); - if (pr_backup) - memcpy(pr_backup, _pr, sizeof(struct acpi_processor)); - } + if (!pr_backup) + pr_backup = kmemdup(_pr, sizeof(*_pr), GFP_KERNEL); (void)upload_pm_data(_pr); } diff --git a/drivers/xen/xen-pciback/conf_space_quirks.h b/drivers/xen/xen-pciback/conf_space_quirks.h index d873abe35bf6..fc1557dfef49 100644 --- a/drivers/xen/xen-pciback/conf_space_quirks.h +++ b/drivers/xen/xen-pciback/conf_space_quirks.h @@ -21,8 +21,6 @@ struct xen_pcibk_config_quirk { int xen_pcibk_config_quirks_add_field(struct pci_dev *dev, struct config_field *field); -int xen_pcibk_config_quirks_remove_field(struct pci_dev *dev, int reg); - int xen_pcibk_config_quirks_init(struct pci_dev *dev); void xen_pcibk_config_field_free(struct config_field *field); diff --git a/drivers/xen/xen-pciback/pciback.h b/drivers/xen/xen-pciback/pciback.h index 9a64196e831d..f9599ed2f2e2 100644 --- a/drivers/xen/xen-pciback/pciback.h +++ b/drivers/xen/xen-pciback/pciback.h @@ -201,6 +201,3 @@ static inline void xen_pcibk_lateeoi(struct xen_pcibk_device *pdev, int xen_pcibk_xenbus_register(void); void xen_pcibk_xenbus_unregister(void); #endif - -/* Handles shared IRQs that can to device domain and control domain. */ -void xen_pcibk_irq_handler(struct pci_dev *dev, int reset); diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c index 3f3836cb7279..fcb335bb7b18 100644 --- a/drivers/xen/xenbus/xenbus_probe_frontend.c +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c @@ -429,7 +429,7 @@ static void xenbus_check_frontend(char *class, char *dev) printk(KERN_DEBUG "XENBUS: frontend %s %s\n", frontend, xenbus_strstate(fe_state)); backend = xenbus_read(XBT_NIL, frontend, "backend", NULL); - if (!backend || IS_ERR(backend)) + if (IS_ERR_OR_NULL(backend)) goto out; err = xenbus_scanf(XBT_NIL, backend, "state", "%i", &be_state); if (err == 1) diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index 12e02eb01f59..028a182bcc9e 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c @@ -840,8 +840,8 @@ void xs_suspend(void) { xs_suspend_enter(); - down_write(&xs_watch_rwsem); mutex_lock(&xs_response_mutex); + down_write(&xs_watch_rwsem); } void xs_resume(void) @@ -866,8 +866,8 @@ void xs_resume(void) void xs_suspend_cancel(void) { - mutex_unlock(&xs_response_mutex); up_write(&xs_watch_rwsem); + mutex_unlock(&xs_response_mutex); xs_suspend_exit(); } diff --git a/drivers/zorro/names.c b/drivers/zorro/names.c index fa3c83dbe843..077114ccc840 100644 --- a/drivers/zorro/names.c +++ b/drivers/zorro/names.c @@ -15,6 +15,7 @@ #include <linux/types.h> #include <linux/zorro.h> +#include "zorro.h" struct zorro_prod_info { __u16 prod; |