From patchwork Tue Nov 21 04:04:56 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phil Reid X-Patchwork-Id: 839905 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-i2c-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3ygsSB27jjz9s7M for ; Tue, 21 Nov 2017 15:05:14 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752707AbdKUEFL (ORCPT ); Mon, 20 Nov 2017 23:05:11 -0500 Received: from anchovy3.45ru.net.au ([203.30.46.155]:47100 "EHLO anchovy.45ru.net.au" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752709AbdKUEFK (ORCPT ); Mon, 20 Nov 2017 23:05:10 -0500 Received: (qmail 23069 invoked by uid 5089); 21 Nov 2017 04:05:06 -0000 Received: by simscan 1.2.0 ppid: 22922, pid: 22925, t: 0.7522s scanners: regex: 1.2.0 attach: 1.2.0 clamav: 0.88.3/m:40/d:1950 X-RBL: $rbltext Received: from unknown (HELO preid-centos7.electromag.com.au) (preid@electromag.com.au@203.59.230.133) by anchovy2.45ru.net.au with ESMTPA; 21 Nov 2017 04:05:04 -0000 Received: by preid-centos7.electromag.com.au (Postfix, from userid 1000) id E27A7335C1A8D; Tue, 21 Nov 2017 12:05:00 +0800 (AWST) From: Phil Reid To: realmz6@gmail.com, wsa@the-dreams.de, sre@kernel.org, preid@electromag.com.au, benjamin.tissoires@redhat.com, adi-buildroot-devel@lists.sourceforge.net, linux-i2c@vger.kernel.org, linux-pm@vger.kernel.org, jdelvare@suse.de Subject: [RFC 1/3] i2c: smbus: move of_i2c_setup_smbus_alert declaration to i2c-core.h Date: Tue, 21 Nov 2017 12:04:56 +0800 Message-Id: <1511237098-33250-2-git-send-email-preid@electromag.com.au> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1511237098-33250-1-git-send-email-preid@electromag.com.au> References: <1511237098-33250-1-git-send-email-preid@electromag.com.au> Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org This declaration isn't used by anything outside of the i2c-core at present. In preparation for moving the smbus_alert code from it's own module into the i2c-core move to i2c-core.h Signed-off-by: Phil Reid --- drivers/i2c/i2c-core.h | 9 +++++++++ drivers/i2c/i2c-smbus.c | 3 ++- include/linux/i2c-smbus.h | 10 ---------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h index 3d3d9bf..8ef0402 100644 --- a/drivers/i2c/i2c-core.h +++ b/drivers/i2c/i2c-core.h @@ -60,3 +60,12 @@ static inline void i2c_acpi_remove_space_handler(struct i2c_adapter *adapter) { static inline void of_i2c_register_devices(struct i2c_adapter *adap) { } #endif extern struct notifier_block i2c_of_notifier; + +#if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_OF) +int of_i2c_setup_smbus_alert(struct i2c_adapter *adap); +#else +static inline int of_i2c_setup_smbus_alert(struct i2c_adapter *adap) +{ + return 0; +} +#endif diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c index 5a1dd7f..c11a50e 100644 --- a/drivers/i2c/i2c-smbus.c +++ b/drivers/i2c/i2c-smbus.c @@ -25,6 +25,8 @@ #include #include +#include "i2c-core.h" + struct i2c_smbus_alert { struct work_struct alert; struct i2c_client *ara; /* Alert response address */ @@ -123,7 +125,6 @@ static void smbalert_work(struct work_struct *work) alert = container_of(work, struct i2c_smbus_alert, alert); smbus_alert(0, alert); - } /* Setup SMBALERT# infrastructure */ diff --git a/include/linux/i2c-smbus.h b/include/linux/i2c-smbus.h index fb0e040..5f16a63 100644 --- a/include/linux/i2c-smbus.h +++ b/include/linux/i2c-smbus.h @@ -26,7 +26,6 @@ #include #include - /** * i2c_smbus_alert_setup - platform data for the smbus_alert i2c client * @alert_edge_triggered: whether the alert interrupt is edge (1) or level (0) @@ -49,13 +48,4 @@ struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter, struct i2c_smbus_alert_setup *setup); int i2c_handle_smbus_alert(struct i2c_client *ara); -#if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_OF) -int of_i2c_setup_smbus_alert(struct i2c_adapter *adap); -#else -static inline int of_i2c_setup_smbus_alert(struct i2c_adapter *adap) -{ - return 0; -} -#endif - #endif /* _LINUX_I2C_SMBUS_H */ From patchwork Tue Nov 21 04:04:57 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phil Reid X-Patchwork-Id: 839902 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-i2c-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3ygsS76p8jz9s71 for ; Tue, 21 Nov 2017 15:05:11 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752422AbdKUEFJ (ORCPT ); Mon, 20 Nov 2017 23:05:09 -0500 Received: from anchovy1.45ru.net.au ([203.30.46.145]:33178 "EHLO anchovy.45ru.net.au" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752358AbdKUEFI (ORCPT ); Mon, 20 Nov 2017 23:05:08 -0500 Received: (qmail 18124 invoked by uid 5089); 21 Nov 2017 04:05:05 -0000 Received: by simscan 1.2.0 ppid: 18040, pid: 18042, t: 0.1845s scanners: regex: 1.2.0 attach: 1.2.0 clamav: 0.88.3/m:40/d:1950 X-RBL: $rbltext Received: from unknown (HELO preid-centos7.electromag.com.au) (preid@electromag.com.au@203.59.230.133) by anchovy1.45ru.net.au with ESMTPA; 21 Nov 2017 04:05:04 -0000 Received: by preid-centos7.electromag.com.au (Postfix, from userid 1000) id E3C56335C1A9C; Tue, 21 Nov 2017 12:05:00 +0800 (AWST) From: Phil Reid To: realmz6@gmail.com, wsa@the-dreams.de, sre@kernel.org, preid@electromag.com.au, benjamin.tissoires@redhat.com, adi-buildroot-devel@lists.sourceforge.net, linux-i2c@vger.kernel.org, linux-pm@vger.kernel.org, jdelvare@suse.de Subject: [RFC 2/3] i2c: Kconfig: rename variable I2C_SMBUS to I2C_SMBUS_ALERT Date: Tue, 21 Nov 2017 12:04:57 +0800 Message-Id: <1511237098-33250-3-git-send-email-preid@electromag.com.au> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1511237098-33250-1-git-send-email-preid@electromag.com.au> References: <1511237098-33250-1-git-send-email-preid@electromag.com.au> Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org i2c-smbus now only contains code related to the smbus_alert driver. Other smbus protocols have been moved from this into the i2c-core-smbus. Change the Kconfig variable name to reflect this. Signed-off-by: Phil Reid --- arch/blackfin/configs/BF527-TLL6527M_defconfig | 2 +- drivers/i2c/Kconfig | 11 +++++------ drivers/i2c/Makefile | 2 +- drivers/i2c/busses/Kconfig | 8 ++++---- drivers/i2c/i2c-core-smbus.c | 2 +- drivers/i2c/i2c-core.h | 2 +- drivers/power/supply/Kconfig | 2 +- 7 files changed, 14 insertions(+), 15 deletions(-) diff --git a/arch/blackfin/configs/BF527-TLL6527M_defconfig b/arch/blackfin/configs/BF527-TLL6527M_defconfig index cdeb518..30f3b5c 100644 --- a/arch/blackfin/configs/BF527-TLL6527M_defconfig +++ b/arch/blackfin/configs/BF527-TLL6527M_defconfig @@ -109,7 +109,7 @@ CONFIG_SERIAL_BFIN_UART1=y # CONFIG_HW_RANDOM is not set CONFIG_I2C_CHARDEV=y # CONFIG_I2C_HELPER_AUTO is not set -CONFIG_I2C_SMBUS=y +CONFIG_I2C_SMBUS_ALERT=y CONFIG_I2C_BLACKFIN_TWI=y CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ=100 CONFIG_GPIOLIB=y diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index efc3354..fcd4bea 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -55,7 +55,7 @@ config I2C_CHARDEV programs use the I2C bus. Information on how to do this is contained in the file . - This support is also available as a module. If so, the module + This support is also available as a module. If so, the module will be called i2c-dev. config I2C_MUX @@ -84,12 +84,11 @@ config I2C_HELPER_AUTO In doubt, say Y. -config I2C_SMBUS - tristate "SMBus-specific protocols" if !I2C_HELPER_AUTO +config I2C_SMBUS_ALERT + tristate "SMBus-alert protocol" if !I2C_HELPER_AUTO help - Say Y here if you want support for SMBus extensions to the I2C - specification. At the moment, two extensions are supported: - the SMBus Alert protocol and the SMBus Host Notify protocol. + Say Y here if you want support for SMBus alert extensions to the I2C + specification. This support is also available as a module. If so, the module will be called i2c-smbus. diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 7bb65a4..b0116a1 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -9,7 +9,7 @@ i2c-core-$(CONFIG_ACPI) += i2c-core-acpi.o i2c-core-$(CONFIG_I2C_SLAVE) += i2c-core-slave.o i2c-core-$(CONFIG_OF) += i2c-core-of.o -obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o +obj-$(CONFIG_I2C_SMBUS_ALERT) += i2c-smbus.o obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o obj-$(CONFIG_I2C_MUX) += i2c-mux.o obj-y += algos/ busses/ muxes/ diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 009345d..310d5ec 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -91,7 +91,7 @@ config I2C_I801 tristate "Intel 82801 (ICH/PCH)" depends on PCI select CHECK_SIGNATURE if X86 && DMI - select I2C_SMBUS + select I2C_SMBUS_ALERT help If you say yes to this option, support will be included for the Intel 801 family of mainboard I2C interfaces. Specifically, the following @@ -1056,7 +1056,7 @@ config I2C_OCTEON config I2C_THUNDERX tristate "Cavium ThunderX I2C bus support" depends on 64BIT && PCI && (ARM64 || COMPILE_TEST) - select I2C_SMBUS + select I2C_SMBUS_ALERT help Say yes if you want to support the I2C serial bus on Cavium ThunderX SOC. @@ -1132,7 +1132,7 @@ config I2C_PARPORT tristate "Parallel port adapter" depends on PARPORT select I2C_ALGOBIT - select I2C_SMBUS + select I2C_SMBUS_ALERT help This supports parallel port I2C adapters such as the ones made by Philips or Velleman, Analog Devices evaluation boards, and more. @@ -1156,7 +1156,7 @@ config I2C_PARPORT config I2C_PARPORT_LIGHT tristate "Parallel port adapter (light)" select I2C_ALGOBIT - select I2C_SMBUS + select I2C_SMBUS_ALERT help This supports parallel port I2C adapters such as the ones made by Philips or Velleman, Analog Devices evaluation boards, and more. diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c index 4bb9927..f4c3b18 100644 --- a/drivers/i2c/i2c-core-smbus.c +++ b/drivers/i2c/i2c-core-smbus.c @@ -626,7 +626,7 @@ struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter, } EXPORT_SYMBOL_GPL(i2c_setup_smbus_alert); -#if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_OF) +#if IS_ENABLED(CONFIG_I2C_SMBUS_ALERT) && IS_ENABLED(CONFIG_OF) int of_i2c_setup_smbus_alert(struct i2c_adapter *adapter) { struct i2c_client *client; diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h index 8ef0402..2ee5396 100644 --- a/drivers/i2c/i2c-core.h +++ b/drivers/i2c/i2c-core.h @@ -61,7 +61,7 @@ static inline void of_i2c_register_devices(struct i2c_adapter *adap) { } #endif extern struct notifier_block i2c_of_notifier; -#if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_OF) +#if IS_ENABLED(CONFIG_I2C_SMBUS_ALERT) && IS_ENABLED(CONFIG_OF) int of_i2c_setup_smbus_alert(struct i2c_adapter *adap); #else static inline int of_i2c_setup_smbus_alert(struct i2c_adapter *adap) diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index fbca0ba..fac8252 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -187,7 +187,7 @@ config CHARGER_SBS config MANAGER_SBS tristate "Smart Battery System Manager" depends on I2C && I2C_MUX && GPIOLIB - select I2C_SMBUS + select I2C_SMBUS_ALERT help Say Y here to include support for Smart Battery System Manager ICs. The driver reports online and charging status via sysfs. From patchwork Tue Nov 21 04:04:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Phil Reid X-Patchwork-Id: 839903 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=linux-i2c-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3ygsS85zQYz9s7B for ; Tue, 21 Nov 2017 15:05:12 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752617AbdKUEFK (ORCPT ); Mon, 20 Nov 2017 23:05:10 -0500 Received: from anchovy1.45ru.net.au ([203.30.46.145]:33187 "EHLO anchovy.45ru.net.au" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752616AbdKUEFI (ORCPT ); Mon, 20 Nov 2017 23:05:08 -0500 Received: (qmail 18133 invoked by uid 5089); 21 Nov 2017 04:05:05 -0000 Received: by simscan 1.2.0 ppid: 18039, pid: 18041, t: 0.2293s scanners: regex: 1.2.0 attach: 1.2.0 clamav: 0.88.3/m:40/d:1950 X-RBL: $rbltext Received: from unknown (HELO preid-centos7.electromag.com.au) (preid@electromag.com.au@203.59.230.133) by anchovy1.45ru.net.au with ESMTPA; 21 Nov 2017 04:05:04 -0000 Received: by preid-centos7.electromag.com.au (Postfix, from userid 1000) id E832F335C1A9E; Tue, 21 Nov 2017 12:05:00 +0800 (AWST) From: Phil Reid To: realmz6@gmail.com, wsa@the-dreams.de, sre@kernel.org, preid@electromag.com.au, benjamin.tissoires@redhat.com, adi-buildroot-devel@lists.sourceforge.net, linux-i2c@vger.kernel.org, linux-pm@vger.kernel.org, jdelvare@suse.de Subject: [RFC 3/3] i2c: core: move smbus_alert module into i2c-core Date: Tue, 21 Nov 2017 12:04:58 +0800 Message-Id: <1511237098-33250-4-git-send-email-preid@electromag.com.au> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1511237098-33250-1-git-send-email-preid@electromag.com.au> References: <1511237098-33250-1-git-send-email-preid@electromag.com.au> Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org Remove the i2c-smbus module and move the smbus_alert driver into the i2c-core. This simplifies the build logic for when i2c-core is builtin and drivers selecting I2C_SMBUS_ALERT are modules. Also smbus_alert code is moved from i2c-core-smbus.c to i2c-core-smbus-alert.c Signed-off-by: Phil Reid --- drivers/i2c/Kconfig | 5 +- drivers/i2c/Makefile | 2 +- drivers/i2c/i2c-core-base.c | 7 ++ drivers/i2c/i2c-core-smbus-alert.c | 241 +++++++++++++++++++++++++++++++++++++ drivers/i2c/i2c-core-smbus.c | 22 ---- drivers/i2c/i2c-core.h | 13 ++ drivers/i2c/i2c-smbus.c | 218 --------------------------------- 7 files changed, 263 insertions(+), 245 deletions(-) create mode 100644 drivers/i2c/i2c-core-smbus-alert.c delete mode 100644 drivers/i2c/i2c-smbus.c diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index fcd4bea..486a1f4 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -85,14 +85,11 @@ config I2C_HELPER_AUTO In doubt, say Y. config I2C_SMBUS_ALERT - tristate "SMBus-alert protocol" if !I2C_HELPER_AUTO + bool "SMBus-alert protocol" if !I2C_HELPER_AUTO help Say Y here if you want support for SMBus alert extensions to the I2C specification. - This support is also available as a module. If so, the module - will be called i2c-smbus. - source drivers/i2c/algos/Kconfig source drivers/i2c/busses/Kconfig diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index b0116a1..efc3c54c 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -8,8 +8,8 @@ i2c-core-objs := i2c-core-base.o i2c-core-smbus.o i2c-core-$(CONFIG_ACPI) += i2c-core-acpi.o i2c-core-$(CONFIG_I2C_SLAVE) += i2c-core-slave.o i2c-core-$(CONFIG_OF) += i2c-core-of.o +i2c-core-$(CONFIG_I2C_SMBUS_ALERT) += i2c-core-smbus-alert.o -obj-$(CONFIG_I2C_SMBUS_ALERT) += i2c-smbus.o obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o obj-$(CONFIG_I2C_MUX) += i2c-mux.o obj-y += algos/ busses/ muxes/ diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 54ffc8d..5788c80 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -1690,6 +1690,10 @@ static int __init i2c_init(void) if (retval) goto class_err; + retval = i2c_smbus_alert_add_driver(); + if (retval) + goto dummy_err; + if (IS_ENABLED(CONFIG_OF_DYNAMIC)) WARN_ON(of_reconfig_notifier_register(&i2c_of_notifier)); if (IS_ENABLED(CONFIG_ACPI)) @@ -1697,6 +1701,8 @@ static int __init i2c_init(void) return 0; +dummy_err: + i2c_del_driver(&dummy_driver); class_err: #ifdef CONFIG_I2C_COMPAT class_compat_unregister(i2c_adapter_compat_class); @@ -1713,6 +1719,7 @@ static void __exit i2c_exit(void) WARN_ON(acpi_reconfig_notifier_unregister(&i2c_acpi_notifier)); if (IS_ENABLED(CONFIG_OF_DYNAMIC)) WARN_ON(of_reconfig_notifier_unregister(&i2c_of_notifier)); + i2c_smbus_alert_del_driver(); i2c_del_driver(&dummy_driver); #ifdef CONFIG_I2C_COMPAT class_compat_unregister(i2c_adapter_compat_class); diff --git a/drivers/i2c/i2c-core-smbus-alert.c b/drivers/i2c/i2c-core-smbus-alert.c new file mode 100644 index 0000000..fa0c333 --- /dev/null +++ b/drivers/i2c/i2c-core-smbus-alert.c @@ -0,0 +1,241 @@ +/* + * i2c-smbus.c - SMBus extensions to the I2C protocol + * + * Copyright (C) 2008 David Brownell + * Copyright (C) 2010 Jean Delvare + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "i2c-core.h" + +struct i2c_smbus_alert { + struct work_struct alert; + struct i2c_client *ara; /* Alert response address */ +}; + +struct alert_data { + unsigned short addr; + enum i2c_alert_protocol type; + unsigned int data; +}; + +/* If this is the alerting device, notify its driver */ +static int smbus_do_alert(struct device *dev, void *addrp) +{ + struct i2c_client *client = i2c_verify_client(dev); + struct alert_data *data = addrp; + struct i2c_driver *driver; + + if (!client || client->addr != data->addr) + return 0; + if (client->flags & I2C_CLIENT_TEN) + return 0; + + /* + * Drivers should either disable alerts, or provide at least + * a minimal handler. Lock so the driver won't change. + */ + device_lock(dev); + if (client->dev.driver) { + driver = to_i2c_driver(client->dev.driver); + if (driver->alert) + driver->alert(client, data->type, data->data); + else + dev_warn(&client->dev, "no driver alert()!\n"); + } else + dev_dbg(&client->dev, "alert with no driver\n"); + device_unlock(dev); + + /* Stop iterating after we find the device */ + return -EBUSY; +} + +/* + * The alert IRQ handler needs to hand work off to a task which can issue + * SMBus calls, because those sleeping calls can't be made in IRQ context. + */ +static irqreturn_t smbus_alert(int irq, void *d) +{ + struct i2c_smbus_alert *alert = d; + struct i2c_client *ara; + unsigned short prev_addr = 0; /* Not a valid address */ + + ara = alert->ara; + + for (;;) { + s32 status; + struct alert_data data; + + /* + * Devices with pending alerts reply in address order, low + * to high, because of slave transmit arbitration. After + * responding, an SMBus device stops asserting SMBALERT#. + * + * Note that SMBus 2.0 reserves 10-bit addresses for future + * use. We neither handle them, nor try to use PEC here. + */ + status = i2c_smbus_read_byte(ara); + if (status < 0) + break; + + data.data = status & 1; + data.addr = status >> 1; + data.type = I2C_PROTOCOL_SMBUS_ALERT; + + if (data.addr == prev_addr) { + dev_warn(&ara->dev, "Duplicate SMBALERT# from dev " + "0x%02x, skipping\n", data.addr); + break; + } + dev_dbg(&ara->dev, "SMBALERT# from dev 0x%02x, flag %d\n", + data.addr, data.data); + + /* Notify driver for the device which issued the alert */ + device_for_each_child(&ara->adapter->dev, &data, + smbus_do_alert); + prev_addr = data.addr; + } + + return IRQ_HANDLED; +} + +static void smbalert_work(struct work_struct *work) +{ + struct i2c_smbus_alert *alert; + + alert = container_of(work, struct i2c_smbus_alert, alert); + + smbus_alert(0, alert); +} + +/* Setup SMBALERT# infrastructure */ +static int smbalert_probe(struct i2c_client *ara, + const struct i2c_device_id *id) +{ + struct i2c_smbus_alert_setup *setup = dev_get_platdata(&ara->dev); + struct i2c_smbus_alert *alert; + struct i2c_adapter *adapter = ara->adapter; + int res, irq; + + alert = devm_kzalloc(&ara->dev, sizeof(struct i2c_smbus_alert), + GFP_KERNEL); + if (!alert) + return -ENOMEM; + + if (setup) { + irq = setup->irq; + } else { + irq = of_irq_get_byname(adapter->dev.of_node, "smbus_alert"); + if (irq <= 0) + return irq; + } + + INIT_WORK(&alert->alert, smbalert_work); + alert->ara = ara; + + if (irq > 0) { + res = devm_request_threaded_irq(&ara->dev, irq, + NULL, smbus_alert, + IRQF_SHARED | IRQF_ONESHOT, + "smbus_alert", alert); + if (res) + return res; + } + + i2c_set_clientdata(ara, alert); + dev_info(&adapter->dev, "supports SMBALERT#\n"); + + return 0; +} + +/* IRQ and memory resources are managed so they are freed automatically */ +static int smbalert_remove(struct i2c_client *ara) +{ + struct i2c_smbus_alert *alert = i2c_get_clientdata(ara); + + cancel_work_sync(&alert->alert); + return 0; +} + +static const struct i2c_device_id smbalert_ids[] = { + { "smbus_alert", 0 }, + { /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, smbalert_ids); + +static struct i2c_driver smbalert_driver = { + .driver = { + .name = "smbus_alert", + }, + .probe = smbalert_probe, + .remove = smbalert_remove, + .id_table = smbalert_ids, +}; + +int of_i2c_setup_smbus_alert(struct i2c_adapter *adapter) +{ + struct i2c_client *client; + int irq; + + irq = of_property_match_string(adapter->dev.of_node, "interrupt-names", + "smbus_alert"); + if (irq == -EINVAL || irq == -ENODATA) + return 0; + else if (irq < 0) + return irq; + + client = i2c_setup_smbus_alert(adapter, NULL); + if (!client) + return -ENODEV; + + return 0; +} + +/** + * i2c_handle_smbus_alert - Handle an SMBus alert + * @ara: the ARA client on the relevant adapter + * Context: can't sleep + * + * Helper function to be called from an I2C bus driver's interrupt + * handler. It will schedule the alert work, in turn calling the + * corresponding I2C device driver's alert function. + * + * It is assumed that ara is a valid i2c client previously returned by + * i2c_setup_smbus_alert(). + */ +int i2c_handle_smbus_alert(struct i2c_client *ara) +{ + struct i2c_smbus_alert *alert = i2c_get_clientdata(ara); + + return schedule_work(&alert->alert); +} +EXPORT_SYMBOL_GPL(i2c_handle_smbus_alert); + +int i2c_smbus_alert_add_driver(void) +{ + return i2c_add_driver(&smbalert_driver); +} + +void i2c_smbus_alert_del_driver(void) +{ + i2c_del_driver(&smbalert_driver); +} diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c index f4c3b18..7f3ec02 100644 --- a/drivers/i2c/i2c-core-smbus.c +++ b/drivers/i2c/i2c-core-smbus.c @@ -625,25 +625,3 @@ struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter, return i2c_new_device(adapter, &ara_board_info); } EXPORT_SYMBOL_GPL(i2c_setup_smbus_alert); - -#if IS_ENABLED(CONFIG_I2C_SMBUS_ALERT) && IS_ENABLED(CONFIG_OF) -int of_i2c_setup_smbus_alert(struct i2c_adapter *adapter) -{ - struct i2c_client *client; - int irq; - - irq = of_property_match_string(adapter->dev.of_node, "interrupt-names", - "smbus_alert"); - if (irq == -EINVAL || irq == -ENODATA) - return 0; - else if (irq < 0) - return irq; - - client = i2c_setup_smbus_alert(adapter, NULL); - if (!client) - return -ENODEV; - - return 0; -} -EXPORT_SYMBOL_GPL(of_i2c_setup_smbus_alert); -#endif diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h index 2ee5396..c6873f4 100644 --- a/drivers/i2c/i2c-core.h +++ b/drivers/i2c/i2c-core.h @@ -69,3 +69,16 @@ static inline int of_i2c_setup_smbus_alert(struct i2c_adapter *adap) return 0; } #endif + +#if IS_ENABLED(CONFIG_I2C_SMBUS_ALERT) +int i2c_smbus_alert_add_driver(void); +void i2c_smbus_alert_del_driver(void); +#else +static inline int i2c_smbus_alert_add_driver(void) +{ + return 0; +} +static inline void i2c_smbus_alert_del_driver(void) +{ +} +#endif diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c deleted file mode 100644 index c11a50e..0000000 --- a/drivers/i2c/i2c-smbus.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * i2c-smbus.c - SMBus extensions to the I2C protocol - * - * Copyright (C) 2008 David Brownell - * Copyright (C) 2010 Jean Delvare - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "i2c-core.h" - -struct i2c_smbus_alert { - struct work_struct alert; - struct i2c_client *ara; /* Alert response address */ -}; - -struct alert_data { - unsigned short addr; - enum i2c_alert_protocol type; - unsigned int data; -}; - -/* If this is the alerting device, notify its driver */ -static int smbus_do_alert(struct device *dev, void *addrp) -{ - struct i2c_client *client = i2c_verify_client(dev); - struct alert_data *data = addrp; - struct i2c_driver *driver; - - if (!client || client->addr != data->addr) - return 0; - if (client->flags & I2C_CLIENT_TEN) - return 0; - - /* - * Drivers should either disable alerts, or provide at least - * a minimal handler. Lock so the driver won't change. - */ - device_lock(dev); - if (client->dev.driver) { - driver = to_i2c_driver(client->dev.driver); - if (driver->alert) - driver->alert(client, data->type, data->data); - else - dev_warn(&client->dev, "no driver alert()!\n"); - } else - dev_dbg(&client->dev, "alert with no driver\n"); - device_unlock(dev); - - /* Stop iterating after we find the device */ - return -EBUSY; -} - -/* - * The alert IRQ handler needs to hand work off to a task which can issue - * SMBus calls, because those sleeping calls can't be made in IRQ context. - */ -static irqreturn_t smbus_alert(int irq, void *d) -{ - struct i2c_smbus_alert *alert = d; - struct i2c_client *ara; - unsigned short prev_addr = 0; /* Not a valid address */ - - ara = alert->ara; - - for (;;) { - s32 status; - struct alert_data data; - - /* - * Devices with pending alerts reply in address order, low - * to high, because of slave transmit arbitration. After - * responding, an SMBus device stops asserting SMBALERT#. - * - * Note that SMBus 2.0 reserves 10-bit addresses for future - * use. We neither handle them, nor try to use PEC here. - */ - status = i2c_smbus_read_byte(ara); - if (status < 0) - break; - - data.data = status & 1; - data.addr = status >> 1; - data.type = I2C_PROTOCOL_SMBUS_ALERT; - - if (data.addr == prev_addr) { - dev_warn(&ara->dev, "Duplicate SMBALERT# from dev " - "0x%02x, skipping\n", data.addr); - break; - } - dev_dbg(&ara->dev, "SMBALERT# from dev 0x%02x, flag %d\n", - data.addr, data.data); - - /* Notify driver for the device which issued the alert */ - device_for_each_child(&ara->adapter->dev, &data, - smbus_do_alert); - prev_addr = data.addr; - } - - return IRQ_HANDLED; -} - -static void smbalert_work(struct work_struct *work) -{ - struct i2c_smbus_alert *alert; - - alert = container_of(work, struct i2c_smbus_alert, alert); - - smbus_alert(0, alert); -} - -/* Setup SMBALERT# infrastructure */ -static int smbalert_probe(struct i2c_client *ara, - const struct i2c_device_id *id) -{ - struct i2c_smbus_alert_setup *setup = dev_get_platdata(&ara->dev); - struct i2c_smbus_alert *alert; - struct i2c_adapter *adapter = ara->adapter; - int res, irq; - - alert = devm_kzalloc(&ara->dev, sizeof(struct i2c_smbus_alert), - GFP_KERNEL); - if (!alert) - return -ENOMEM; - - if (setup) { - irq = setup->irq; - } else { - irq = of_irq_get_byname(adapter->dev.of_node, "smbus_alert"); - if (irq <= 0) - return irq; - } - - INIT_WORK(&alert->alert, smbalert_work); - alert->ara = ara; - - if (irq > 0) { - res = devm_request_threaded_irq(&ara->dev, irq, - NULL, smbus_alert, - IRQF_SHARED | IRQF_ONESHOT, - "smbus_alert", alert); - if (res) - return res; - } - - i2c_set_clientdata(ara, alert); - dev_info(&adapter->dev, "supports SMBALERT#\n"); - - return 0; -} - -/* IRQ and memory resources are managed so they are freed automatically */ -static int smbalert_remove(struct i2c_client *ara) -{ - struct i2c_smbus_alert *alert = i2c_get_clientdata(ara); - - cancel_work_sync(&alert->alert); - return 0; -} - -static const struct i2c_device_id smbalert_ids[] = { - { "smbus_alert", 0 }, - { /* LIST END */ } -}; -MODULE_DEVICE_TABLE(i2c, smbalert_ids); - -static struct i2c_driver smbalert_driver = { - .driver = { - .name = "smbus_alert", - }, - .probe = smbalert_probe, - .remove = smbalert_remove, - .id_table = smbalert_ids, -}; - -/** - * i2c_handle_smbus_alert - Handle an SMBus alert - * @ara: the ARA client on the relevant adapter - * Context: can't sleep - * - * Helper function to be called from an I2C bus driver's interrupt - * handler. It will schedule the alert work, in turn calling the - * corresponding I2C device driver's alert function. - * - * It is assumed that ara is a valid i2c client previously returned by - * i2c_setup_smbus_alert(). - */ -int i2c_handle_smbus_alert(struct i2c_client *ara) -{ - struct i2c_smbus_alert *alert = i2c_get_clientdata(ara); - - return schedule_work(&alert->alert); -} -EXPORT_SYMBOL_GPL(i2c_handle_smbus_alert); - -module_i2c_driver(smbalert_driver); - -MODULE_AUTHOR("Jean Delvare "); -MODULE_DESCRIPTION("SMBus protocol extensions support"); -MODULE_LICENSE("GPL");