All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andreas Kemnade <andreas@kemnade.info>
To: "Jonathan Neuschäfer" <j.neuschaefer@gmx.net>
Cc: linux-kernel@vger.kernel.org, "Lee Jones" <lee.jones@linaro.org>,
	"Rob Herring" <robh+dt@kernel.org>,
	"Thierry Reding" <thierry.reding@gmail.com>,
	"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
	"Alessandro Zummo" <a.zummo@towertech.it>,
	"Alexandre Belloni" <alexandre.belloni@bootlin.com>,
	"Shawn Guo" <shawnguo@kernel.org>,
	"Sascha Hauer" <s.hauer@pengutronix.de>,
	"Pengutronix Kernel Team" <kernel@pengutronix.de>,
	"Fabio Estevam" <festevam@gmail.com>,
	"NXP Linux Team" <linux-imx@nxp.com>,
	"Sam Ravnborg" <sam@ravnborg.org>,
	"Linus Walleij" <linus.walleij@linaro.org>,
	"Heiko Stuebner" <heiko.stuebner@theobroma-systems.com>,
	"Stephan Gerhold" <stephan@gerhold.net>,
	"Lubomir Rintel" <lkundrak@v3.sk>,
	"Mark Brown" <broonie@kernel.org>, allen <allen.chen@ite.com.t>
Subject: Re: [RFC PATCH 04/10] mfd: Add base driver for Netronix embedded controller
Date: Sat, 27 Jun 2020 10:17:38 +0200	[thread overview]
Message-ID: <20200627101738.2fe4abc3@aktux> (raw)
In-Reply-To: <20200620224222.1312520-3-j.neuschaefer@gmx.net>

On Sun, 21 Jun 2020 00:42:15 +0200
Jonathan Neuschäfer <j.neuschaefer@gmx.net> wrote:

> Third-party hardware documentation is available at
> https://github.com/neuschaefer/linux/wiki/Netronix-MSP430-embedded-controller
> 
> The EC supports interrupts, but the driver doesn't make use of them so
> far.
> 
> Known problems:
> - The reboot handler is installed in such a way that it directly calls
>   into the i2c subsystem to send the reboot command to the EC. This
>   means that the reboot handler may sleep, which is not allowed.
> 
see
https://patchwork.ozlabs.org/project/linux-i2c/patch/20190415213432.8972-3-contact@stefanchrist.eu/

for a fix of such problems. 

> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> ---
>  drivers/mfd/Kconfig       |   7 ++
>  drivers/mfd/Makefile      |   1 +
>  drivers/mfd/ntxec.c       | 188 ++++++++++++++++++++++++++++++++++++++
>  include/linux/mfd/ntxec.h |  30 ++++++
>  4 files changed, 226 insertions(+)
>  create mode 100644 drivers/mfd/ntxec.c
>  create mode 100644 include/linux/mfd/ntxec.h
> 
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index a37d7d1713820..78410b928648e 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -978,6 +978,13 @@ config MFD_VIPERBOARD
>  	  You need to select the mfd cell drivers separately.
>  	  The drivers do not support all features the board exposes.
> 
> +config MFD_NTXEC
> +	bool "Netronix Embedded Controller"
> +	depends on I2C && OF
> +	help
> +	  Say yes here if you want to support the embedded controller of
> +	  certain e-book readers designed by the ODM Netronix.
> +
>  config MFD_RETU
>  	tristate "Nokia Retu and Tahvo multi-function device"
>  	select MFD_CORE
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index 9367a92f795a6..19d9391ed6f32 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -218,6 +218,7 @@ obj-$(CONFIG_MFD_INTEL_MSIC)	+= intel_msic.o
>  obj-$(CONFIG_MFD_INTEL_PMC_BXT)	+= intel_pmc_bxt.o
>  obj-$(CONFIG_MFD_PALMAS)	+= palmas.o
>  obj-$(CONFIG_MFD_VIPERBOARD)    += viperboard.o
> +obj-$(CONFIG_MFD_NTXEC)		+= ntxec.o
>  obj-$(CONFIG_MFD_RC5T583)	+= rc5t583.o rc5t583-irq.o
>  obj-$(CONFIG_MFD_RK808)		+= rk808.o
>  obj-$(CONFIG_MFD_RN5T618)	+= rn5t618.o
> diff --git a/drivers/mfd/ntxec.c b/drivers/mfd/ntxec.c
> new file mode 100644
> index 0000000000000..82adea34ea746
> --- /dev/null
> +++ b/drivers/mfd/ntxec.c
> @@ -0,0 +1,188 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +// Copyright 2020 Jonathan Neuschäfer
> +//
> +// MFD driver for the usually MSP430-based embedded controller used in certain
> +// Netronix ebook reader board designs
> +
> +#include <asm/unaligned.h>
> +#include <linux/delay.h>
> +#include <linux/errno.h>
> +#include <linux/i2c.h>
> +#include <linux/mfd/ntxec.h>
> +#include <linux/of_platform.h>
> +#include <linux/pm.h>
> +#include <linux/reboot.h>
> +#include <linux/types.h>
> +
> +
> +#define NTXEC_VERSION		0x00
> +#define NTXEC_POWEROFF		0x50
> +#define NTXEC_POWERKEEP		0x70
> +#define NTXEC_RESET		0x90
> +
> +
> +/* Register access */
> +
> +int ntxec_read16(struct ntxec *ec, u8 addr)
> +{
> +	u8 request[1] = { addr };
> +	u8 response[2];
> +	int res;
> +
> +	struct i2c_msg msgs[] = {
> +		{
> +			.addr = ec->client->addr,
> +			.flags = ec->client->flags,
> +			.len = sizeof(request),
> +			.buf = request
> +		}, {
> +			.addr = ec->client->addr,
> +			.flags = ec->client->flags | I2C_M_RD,
> +			.len = sizeof(response),
> +			.buf = response
> +		}
> +	};
> +
> +	res = i2c_transfer(ec->client->adapter, msgs, ARRAY_SIZE(msgs));
> +	if (res < 0)
> +		return res;
> +	if (res != ARRAY_SIZE(msgs))
> +		return -EIO;
> +
> +	return get_unaligned_be16(response);
> +}
> +EXPORT_SYMBOL(ntxec_read16);
> +
> +int ntxec_write16(struct ntxec *ec, u8 addr, u16 value)
> +{
> +	u8 request[3] = { addr, };
> +	int res;
> +
> +	put_unaligned_be16(value, request + 1);
> +
> +	res = i2c_transfer_buffer_flags(ec->client, request, sizeof(request),
> +					ec->client->flags);
> +	if (res < 0)
> +		return res;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(ntxec_write16);
> +
> +int ntxec_read8(struct ntxec *ec, u8 addr)
> +{
> +	int res = ntxec_read16(ec, addr);
> +
> +	if (res < 0)
> +		return res;
> +
> +	return (res >> 8) & 0xff;
> +}
> +EXPORT_SYMBOL(ntxec_read8);
> +
> +int ntxec_write8(struct ntxec *ec, u8 addr, u8 value)
> +{
> +	return ntxec_write16(ec, addr, value << 8);
> +}
> +EXPORT_SYMBOL(ntxec_write8);
> +

do we really need both 16bit and 8bit accessors? If not,
then simply use regmap_i2c_init and set val_bits accordingly.
Maybe just doing the << 8 in the constants?

> +
> +/* Reboot/poweroff handling */
> +
> +static struct ntxec *poweroff_restart_instance;
> +
> +static void ntxec_poweroff(void)
> +{
> +	ntxec_write8(poweroff_restart_instance, NTXEC_POWEROFF, 0x01);
> +	msleep(5000);
> +}
> +
> +static int ntxec_restart(struct notifier_block *nb,
> +		unsigned long action, void *data)
> +{
> +	/* FIXME: The I2C driver sleeps, but restart handlers may not sleep */
> +	ntxec_write8(poweroff_restart_instance, NTXEC_RESET, 0xff);
> +	/* TODO: delay? */
> +	return NOTIFY_DONE;
> +}
> +
> +static struct notifier_block ntxec_restart_handler = {
> +	.notifier_call = ntxec_restart,
> +	.priority = 128
> +};
> +
> +
> +/* Driver setup */
> +
> +static int ntxec_probe(struct i2c_client *client,
> +			    const struct i2c_device_id *ids)
> +{
> +	struct ntxec *ec;
> +	int res;
> +
> +	ec = devm_kmalloc(&client->dev, sizeof(*ec), GFP_KERNEL);
> +	if (!ec)
> +		return -ENOMEM;
> +
> +	ec->dev = &client->dev;
> +	ec->client = client;
> +
> +	/* Determine the firmware version */
> +	res = ntxec_read16(ec, NTXEC_VERSION);
> +	if (res < 0) {
> +		dev_dbg(ec->dev, "Failed to read firmware version number\n");
> +		return res;
> +	}
> +	ec->version = res;
> +
> +	dev_info(ec->dev,
> +		 "Netronix embedded controller version %04x detected.\n",
> +		 ec->version);
> +
> +	/* For now, we don't support the new register layout. */
> +	if (ntxec_has_new_layout(ec))
> +		return -EOPNOTSUPP;
> +
> +	if (of_device_is_system_power_controller(ec->dev->of_node)) {
> +		/*
> +		 * Set the 'powerkeep' bit. This is necessary on some boards
> +		 * in order to keep the system running.
> +		 */
> +		res = ntxec_write8(ec, NTXEC_POWERKEEP, 0x08);
> +		if (res < 0)
> +			return res;
> +
> +		/* Install poweroff handler */
> +		WARN_ON(poweroff_restart_instance);
> +		poweroff_restart_instance = ec;
> +		if (pm_power_off != NULL)
> +			/* TODO: Refactor among all poweroff drivers */
> +			dev_err(ec->dev, "pm_power_off already assigned\n");
> +		else
> +			pm_power_off = ntxec_poweroff;
> +
common pattern, across drivers, so I think doing something else would
be a separate cleanup issue.

Regards,
Andreas

WARNING: multiple messages have this Message-ID (diff)
From: Andreas Kemnade <andreas@kemnade.info>
To: "Jonathan Neuschäfer" <j.neuschaefer@gmx.net>
Cc: linux-kernel@vger.kernel.org, "Lee Jones" <lee.jones@linaro.org>,
	"Rob Herring" <robh+dt@kernel.org>,
	"Thierry Reding" <thierry.reding@gmail.com>,
	"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
	"Alessandro Zummo" <a.zummo@towertech.it>,
	"Alexandre Belloni" <alexandre.belloni@bootlin.com>,
	"Shawn Guo" <shawnguo@kernel.org>,
	"Sascha Hauer" <s.hauer@pengutronix.de>,
	"Pengutronix Kernel Team" <kernel@pengutronix.de>,
	"Fabio Estevam" <festevam@gmail.com>,
	"NXP Linux Team" <linux-imx@nxp.com>,
	"Sam Ravnborg" <sam@ravnborg.org>,
	"Linus Walleij" <linus.walleij@linaro.org>,
	"Heiko Stuebner" <heiko.stuebner@theobroma-systems.com>,
	"Stephan Gerhold" <stephan@gerhold.net>,
	"Lubomir Rintel" <lkundrak@v3.sk>,
	"Mark Brown" <broonie@kernel.org>, allen <allen.chen@ite.com.tw>,
	"Mauro Carvalho Chehab" <mchehab+huawei@kernel.org>,
	"David S. Miller" <davem@davemloft.net>,
	devicetree@vger.kernel.org, linux-pwm@vger.kernel.org,
	linux-rtc@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	"Heiko Stuebner" <heiko@sntech.de>,
	"Josua Mayer" <josua.mayer@jm0.eu>
Subject: Re: [RFC PATCH 04/10] mfd: Add base driver for Netronix embedded controller
Date: Sat, 27 Jun 2020 10:17:38 +0200	[thread overview]
Message-ID: <20200627101738.2fe4abc3@aktux> (raw)
In-Reply-To: <20200620224222.1312520-3-j.neuschaefer@gmx.net>

On Sun, 21 Jun 2020 00:42:15 +0200
Jonathan Neuschäfer <j.neuschaefer@gmx.net> wrote:

> Third-party hardware documentation is available at
> https://github.com/neuschaefer/linux/wiki/Netronix-MSP430-embedded-controller
> 
> The EC supports interrupts, but the driver doesn't make use of them so
> far.
> 
> Known problems:
> - The reboot handler is installed in such a way that it directly calls
>   into the i2c subsystem to send the reboot command to the EC. This
>   means that the reboot handler may sleep, which is not allowed.
> 
see
https://patchwork.ozlabs.org/project/linux-i2c/patch/20190415213432.8972-3-contact@stefanchrist.eu/

for a fix of such problems. 

> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> ---
>  drivers/mfd/Kconfig       |   7 ++
>  drivers/mfd/Makefile      |   1 +
>  drivers/mfd/ntxec.c       | 188 ++++++++++++++++++++++++++++++++++++++
>  include/linux/mfd/ntxec.h |  30 ++++++
>  4 files changed, 226 insertions(+)
>  create mode 100644 drivers/mfd/ntxec.c
>  create mode 100644 include/linux/mfd/ntxec.h
> 
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index a37d7d1713820..78410b928648e 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -978,6 +978,13 @@ config MFD_VIPERBOARD
>  	  You need to select the mfd cell drivers separately.
>  	  The drivers do not support all features the board exposes.
> 
> +config MFD_NTXEC
> +	bool "Netronix Embedded Controller"
> +	depends on I2C && OF
> +	help
> +	  Say yes here if you want to support the embedded controller of
> +	  certain e-book readers designed by the ODM Netronix.
> +
>  config MFD_RETU
>  	tristate "Nokia Retu and Tahvo multi-function device"
>  	select MFD_CORE
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index 9367a92f795a6..19d9391ed6f32 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -218,6 +218,7 @@ obj-$(CONFIG_MFD_INTEL_MSIC)	+= intel_msic.o
>  obj-$(CONFIG_MFD_INTEL_PMC_BXT)	+= intel_pmc_bxt.o
>  obj-$(CONFIG_MFD_PALMAS)	+= palmas.o
>  obj-$(CONFIG_MFD_VIPERBOARD)    += viperboard.o
> +obj-$(CONFIG_MFD_NTXEC)		+= ntxec.o
>  obj-$(CONFIG_MFD_RC5T583)	+= rc5t583.o rc5t583-irq.o
>  obj-$(CONFIG_MFD_RK808)		+= rk808.o
>  obj-$(CONFIG_MFD_RN5T618)	+= rn5t618.o
> diff --git a/drivers/mfd/ntxec.c b/drivers/mfd/ntxec.c
> new file mode 100644
> index 0000000000000..82adea34ea746
> --- /dev/null
> +++ b/drivers/mfd/ntxec.c
> @@ -0,0 +1,188 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +// Copyright 2020 Jonathan Neuschäfer
> +//
> +// MFD driver for the usually MSP430-based embedded controller used in certain
> +// Netronix ebook reader board designs
> +
> +#include <asm/unaligned.h>
> +#include <linux/delay.h>
> +#include <linux/errno.h>
> +#include <linux/i2c.h>
> +#include <linux/mfd/ntxec.h>
> +#include <linux/of_platform.h>
> +#include <linux/pm.h>
> +#include <linux/reboot.h>
> +#include <linux/types.h>
> +
> +
> +#define NTXEC_VERSION		0x00
> +#define NTXEC_POWEROFF		0x50
> +#define NTXEC_POWERKEEP		0x70
> +#define NTXEC_RESET		0x90
> +
> +
> +/* Register access */
> +
> +int ntxec_read16(struct ntxec *ec, u8 addr)
> +{
> +	u8 request[1] = { addr };
> +	u8 response[2];
> +	int res;
> +
> +	struct i2c_msg msgs[] = {
> +		{
> +			.addr = ec->client->addr,
> +			.flags = ec->client->flags,
> +			.len = sizeof(request),
> +			.buf = request
> +		}, {
> +			.addr = ec->client->addr,
> +			.flags = ec->client->flags | I2C_M_RD,
> +			.len = sizeof(response),
> +			.buf = response
> +		}
> +	};
> +
> +	res = i2c_transfer(ec->client->adapter, msgs, ARRAY_SIZE(msgs));
> +	if (res < 0)
> +		return res;
> +	if (res != ARRAY_SIZE(msgs))
> +		return -EIO;
> +
> +	return get_unaligned_be16(response);
> +}
> +EXPORT_SYMBOL(ntxec_read16);
> +
> +int ntxec_write16(struct ntxec *ec, u8 addr, u16 value)
> +{
> +	u8 request[3] = { addr, };
> +	int res;
> +
> +	put_unaligned_be16(value, request + 1);
> +
> +	res = i2c_transfer_buffer_flags(ec->client, request, sizeof(request),
> +					ec->client->flags);
> +	if (res < 0)
> +		return res;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(ntxec_write16);
> +
> +int ntxec_read8(struct ntxec *ec, u8 addr)
> +{
> +	int res = ntxec_read16(ec, addr);
> +
> +	if (res < 0)
> +		return res;
> +
> +	return (res >> 8) & 0xff;
> +}
> +EXPORT_SYMBOL(ntxec_read8);
> +
> +int ntxec_write8(struct ntxec *ec, u8 addr, u8 value)
> +{
> +	return ntxec_write16(ec, addr, value << 8);
> +}
> +EXPORT_SYMBOL(ntxec_write8);
> +

do we really need both 16bit and 8bit accessors? If not,
then simply use regmap_i2c_init and set val_bits accordingly.
Maybe just doing the << 8 in the constants?

> +
> +/* Reboot/poweroff handling */
> +
> +static struct ntxec *poweroff_restart_instance;
> +
> +static void ntxec_poweroff(void)
> +{
> +	ntxec_write8(poweroff_restart_instance, NTXEC_POWEROFF, 0x01);
> +	msleep(5000);
> +}
> +
> +static int ntxec_restart(struct notifier_block *nb,
> +		unsigned long action, void *data)
> +{
> +	/* FIXME: The I2C driver sleeps, but restart handlers may not sleep */
> +	ntxec_write8(poweroff_restart_instance, NTXEC_RESET, 0xff);
> +	/* TODO: delay? */
> +	return NOTIFY_DONE;
> +}
> +
> +static struct notifier_block ntxec_restart_handler = {
> +	.notifier_call = ntxec_restart,
> +	.priority = 128
> +};
> +
> +
> +/* Driver setup */
> +
> +static int ntxec_probe(struct i2c_client *client,
> +			    const struct i2c_device_id *ids)
> +{
> +	struct ntxec *ec;
> +	int res;
> +
> +	ec = devm_kmalloc(&client->dev, sizeof(*ec), GFP_KERNEL);
> +	if (!ec)
> +		return -ENOMEM;
> +
> +	ec->dev = &client->dev;
> +	ec->client = client;
> +
> +	/* Determine the firmware version */
> +	res = ntxec_read16(ec, NTXEC_VERSION);
> +	if (res < 0) {
> +		dev_dbg(ec->dev, "Failed to read firmware version number\n");
> +		return res;
> +	}
> +	ec->version = res;
> +
> +	dev_info(ec->dev,
> +		 "Netronix embedded controller version %04x detected.\n",
> +		 ec->version);
> +
> +	/* For now, we don't support the new register layout. */
> +	if (ntxec_has_new_layout(ec))
> +		return -EOPNOTSUPP;
> +
> +	if (of_device_is_system_power_controller(ec->dev->of_node)) {
> +		/*
> +		 * Set the 'powerkeep' bit. This is necessary on some boards
> +		 * in order to keep the system running.
> +		 */
> +		res = ntxec_write8(ec, NTXEC_POWERKEEP, 0x08);
> +		if (res < 0)
> +			return res;
> +
> +		/* Install poweroff handler */
> +		WARN_ON(poweroff_restart_instance);
> +		poweroff_restart_instance = ec;
> +		if (pm_power_off != NULL)
> +			/* TODO: Refactor among all poweroff drivers */
> +			dev_err(ec->dev, "pm_power_off already assigned\n");
> +		else
> +			pm_power_off = ntxec_poweroff;
> +
common pattern, across drivers, so I think doing something else would
be a separate cleanup issue.

Regards,
Andreas

WARNING: multiple messages have this Message-ID (diff)
From: Andreas Kemnade <andreas@kemnade.info>
To: "Jonathan Neuschäfer" <j.neuschaefer@gmx.net>
Cc: "Alexandre Belloni" <alexandre.belloni@bootlin.com>,
	"Heiko Stuebner" <heiko@sntech.de>,
	linux-pwm@vger.kernel.org,
	"Linus Walleij" <linus.walleij@linaro.org>,
	"Thierry Reding" <thierry.reding@gmail.com>,
	"Fabio Estevam" <festevam@gmail.com>,
	linux-rtc@vger.kernel.org,
	"Mauro Carvalho Chehab" <mchehab+huawei@kernel.org>,
	"Sam Ravnborg" <sam@ravnborg.org>,
	"NXP Linux Team" <linux-imx@nxp.com>,
	"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
	devicetree@vger.kernel.org,
	"Stephan Gerhold" <stephan@gerhold.net>,
	allen <allen.chen@ite.com.tw>,
	"Sascha Hauer" <s.hauer@pengutronix.de>,
	"Lubomir Rintel" <lkundrak@v3.sk>,
	"Rob Herring" <robh+dt@kernel.org>,
	"Lee Jones" <lee.jones@linaro.org>,
	linux-arm-kernel@lists.infradead.org,
	"Alessandro Zummo" <a.zummo@towertech.it>,
	linux-kernel@vger.kernel.org, "Mark Brown" <broonie@kernel.org>,
	"Pengutronix Kernel Team" <kernel@pengutronix.de>,
	"Heiko Stuebner" <heiko.stuebner@theobroma-systems.com>,
	"Josua Mayer" <josua.mayer@jm0.eu>,
	"Shawn Guo" <shawnguo@kernel.org>,
	"David S. Miller" <davem@davemloft.net>
Subject: Re: [RFC PATCH 04/10] mfd: Add base driver for Netronix embedded controller
Date: Sat, 27 Jun 2020 10:17:38 +0200	[thread overview]
Message-ID: <20200627101738.2fe4abc3@aktux> (raw)
In-Reply-To: <20200620224222.1312520-3-j.neuschaefer@gmx.net>

On Sun, 21 Jun 2020 00:42:15 +0200
Jonathan Neuschäfer <j.neuschaefer@gmx.net> wrote:

> Third-party hardware documentation is available at
> https://github.com/neuschaefer/linux/wiki/Netronix-MSP430-embedded-controller
> 
> The EC supports interrupts, but the driver doesn't make use of them so
> far.
> 
> Known problems:
> - The reboot handler is installed in such a way that it directly calls
>   into the i2c subsystem to send the reboot command to the EC. This
>   means that the reboot handler may sleep, which is not allowed.
> 
see
https://patchwork.ozlabs.org/project/linux-i2c/patch/20190415213432.8972-3-contact@stefanchrist.eu/

for a fix of such problems. 

> Signed-off-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
> ---
>  drivers/mfd/Kconfig       |   7 ++
>  drivers/mfd/Makefile      |   1 +
>  drivers/mfd/ntxec.c       | 188 ++++++++++++++++++++++++++++++++++++++
>  include/linux/mfd/ntxec.h |  30 ++++++
>  4 files changed, 226 insertions(+)
>  create mode 100644 drivers/mfd/ntxec.c
>  create mode 100644 include/linux/mfd/ntxec.h
> 
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index a37d7d1713820..78410b928648e 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -978,6 +978,13 @@ config MFD_VIPERBOARD
>  	  You need to select the mfd cell drivers separately.
>  	  The drivers do not support all features the board exposes.
> 
> +config MFD_NTXEC
> +	bool "Netronix Embedded Controller"
> +	depends on I2C && OF
> +	help
> +	  Say yes here if you want to support the embedded controller of
> +	  certain e-book readers designed by the ODM Netronix.
> +
>  config MFD_RETU
>  	tristate "Nokia Retu and Tahvo multi-function device"
>  	select MFD_CORE
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index 9367a92f795a6..19d9391ed6f32 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -218,6 +218,7 @@ obj-$(CONFIG_MFD_INTEL_MSIC)	+= intel_msic.o
>  obj-$(CONFIG_MFD_INTEL_PMC_BXT)	+= intel_pmc_bxt.o
>  obj-$(CONFIG_MFD_PALMAS)	+= palmas.o
>  obj-$(CONFIG_MFD_VIPERBOARD)    += viperboard.o
> +obj-$(CONFIG_MFD_NTXEC)		+= ntxec.o
>  obj-$(CONFIG_MFD_RC5T583)	+= rc5t583.o rc5t583-irq.o
>  obj-$(CONFIG_MFD_RK808)		+= rk808.o
>  obj-$(CONFIG_MFD_RN5T618)	+= rn5t618.o
> diff --git a/drivers/mfd/ntxec.c b/drivers/mfd/ntxec.c
> new file mode 100644
> index 0000000000000..82adea34ea746
> --- /dev/null
> +++ b/drivers/mfd/ntxec.c
> @@ -0,0 +1,188 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +// Copyright 2020 Jonathan Neuschäfer
> +//
> +// MFD driver for the usually MSP430-based embedded controller used in certain
> +// Netronix ebook reader board designs
> +
> +#include <asm/unaligned.h>
> +#include <linux/delay.h>
> +#include <linux/errno.h>
> +#include <linux/i2c.h>
> +#include <linux/mfd/ntxec.h>
> +#include <linux/of_platform.h>
> +#include <linux/pm.h>
> +#include <linux/reboot.h>
> +#include <linux/types.h>
> +
> +
> +#define NTXEC_VERSION		0x00
> +#define NTXEC_POWEROFF		0x50
> +#define NTXEC_POWERKEEP		0x70
> +#define NTXEC_RESET		0x90
> +
> +
> +/* Register access */
> +
> +int ntxec_read16(struct ntxec *ec, u8 addr)
> +{
> +	u8 request[1] = { addr };
> +	u8 response[2];
> +	int res;
> +
> +	struct i2c_msg msgs[] = {
> +		{
> +			.addr = ec->client->addr,
> +			.flags = ec->client->flags,
> +			.len = sizeof(request),
> +			.buf = request
> +		}, {
> +			.addr = ec->client->addr,
> +			.flags = ec->client->flags | I2C_M_RD,
> +			.len = sizeof(response),
> +			.buf = response
> +		}
> +	};
> +
> +	res = i2c_transfer(ec->client->adapter, msgs, ARRAY_SIZE(msgs));
> +	if (res < 0)
> +		return res;
> +	if (res != ARRAY_SIZE(msgs))
> +		return -EIO;
> +
> +	return get_unaligned_be16(response);
> +}
> +EXPORT_SYMBOL(ntxec_read16);
> +
> +int ntxec_write16(struct ntxec *ec, u8 addr, u16 value)
> +{
> +	u8 request[3] = { addr, };
> +	int res;
> +
> +	put_unaligned_be16(value, request + 1);
> +
> +	res = i2c_transfer_buffer_flags(ec->client, request, sizeof(request),
> +					ec->client->flags);
> +	if (res < 0)
> +		return res;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(ntxec_write16);
> +
> +int ntxec_read8(struct ntxec *ec, u8 addr)
> +{
> +	int res = ntxec_read16(ec, addr);
> +
> +	if (res < 0)
> +		return res;
> +
> +	return (res >> 8) & 0xff;
> +}
> +EXPORT_SYMBOL(ntxec_read8);
> +
> +int ntxec_write8(struct ntxec *ec, u8 addr, u8 value)
> +{
> +	return ntxec_write16(ec, addr, value << 8);
> +}
> +EXPORT_SYMBOL(ntxec_write8);
> +

do we really need both 16bit and 8bit accessors? If not,
then simply use regmap_i2c_init and set val_bits accordingly.
Maybe just doing the << 8 in the constants?

> +
> +/* Reboot/poweroff handling */
> +
> +static struct ntxec *poweroff_restart_instance;
> +
> +static void ntxec_poweroff(void)
> +{
> +	ntxec_write8(poweroff_restart_instance, NTXEC_POWEROFF, 0x01);
> +	msleep(5000);
> +}
> +
> +static int ntxec_restart(struct notifier_block *nb,
> +		unsigned long action, void *data)
> +{
> +	/* FIXME: The I2C driver sleeps, but restart handlers may not sleep */
> +	ntxec_write8(poweroff_restart_instance, NTXEC_RESET, 0xff);
> +	/* TODO: delay? */
> +	return NOTIFY_DONE;
> +}
> +
> +static struct notifier_block ntxec_restart_handler = {
> +	.notifier_call = ntxec_restart,
> +	.priority = 128
> +};
> +
> +
> +/* Driver setup */
> +
> +static int ntxec_probe(struct i2c_client *client,
> +			    const struct i2c_device_id *ids)
> +{
> +	struct ntxec *ec;
> +	int res;
> +
> +	ec = devm_kmalloc(&client->dev, sizeof(*ec), GFP_KERNEL);
> +	if (!ec)
> +		return -ENOMEM;
> +
> +	ec->dev = &client->dev;
> +	ec->client = client;
> +
> +	/* Determine the firmware version */
> +	res = ntxec_read16(ec, NTXEC_VERSION);
> +	if (res < 0) {
> +		dev_dbg(ec->dev, "Failed to read firmware version number\n");
> +		return res;
> +	}
> +	ec->version = res;
> +
> +	dev_info(ec->dev,
> +		 "Netronix embedded controller version %04x detected.\n",
> +		 ec->version);
> +
> +	/* For now, we don't support the new register layout. */
> +	if (ntxec_has_new_layout(ec))
> +		return -EOPNOTSUPP;
> +
> +	if (of_device_is_system_power_controller(ec->dev->of_node)) {
> +		/*
> +		 * Set the 'powerkeep' bit. This is necessary on some boards
> +		 * in order to keep the system running.
> +		 */
> +		res = ntxec_write8(ec, NTXEC_POWERKEEP, 0x08);
> +		if (res < 0)
> +			return res;
> +
> +		/* Install poweroff handler */
> +		WARN_ON(poweroff_restart_instance);
> +		poweroff_restart_instance = ec;
> +		if (pm_power_off != NULL)
> +			/* TODO: Refactor among all poweroff drivers */
> +			dev_err(ec->dev, "pm_power_off already assigned\n");
> +		else
> +			pm_power_off = ntxec_poweroff;
> +
common pattern, across drivers, so I think doing something else would
be a separate cleanup issue.

Regards,
Andreas

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  parent reply	other threads:[~2020-06-27  8:18 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-06-20 22:42 [RFC PATCH 02/10] dt-bindings: Add vendor prefix for Netronix, Inc Jonathan Neuschäfer
2020-06-20 22:42 ` Jonathan Neuschäfer
     [not found] ` <20200620224222.1312520-1-j.neuschaefer-hi6Y0CQ0nG0@public.gmane.org>
2020-06-20 22:42   ` [RFC PATCH 03/10] dt-bindings: mfd: Add binding for Netronix's embedded controller Jonathan Neuschäfer
2020-06-20 22:42     ` Jonathan Neuschäfer
2020-06-20 22:42   ` [RFC PATCH 04/10] mfd: Add base driver for Netronix " Jonathan Neuschäfer
2020-06-20 22:42     ` Jonathan Neuschäfer
2020-06-22 10:55     ` Lee Jones
2020-06-22 10:55       ` Lee Jones
2020-06-28  8:11       ` Jonathan Neuschäfer
2020-06-28  8:11         ` Jonathan Neuschäfer
2020-06-28  8:11         ` Jonathan Neuschäfer
2020-06-27  8:17     ` Andreas Kemnade [this message]
2020-06-27  8:17       ` Andreas Kemnade
2020-06-27  8:17       ` Andreas Kemnade
2020-06-28  8:29       ` Jonathan Neuschäfer
2020-06-28  8:29         ` Jonathan Neuschäfer
2020-06-28  8:29         ` Jonathan Neuschäfer
2020-06-20 22:42   ` [RFC PATCH 05/10] dt-bindings: pwm: Add bindings for PWM function in Netronix EC Jonathan Neuschäfer
2020-06-20 22:42     ` Jonathan Neuschäfer
     [not found]     ` <20200620224222.1312520-4-j.neuschaefer-hi6Y0CQ0nG0@public.gmane.org>
2020-06-21 18:41       ` Andreas Kemnade
2020-06-21 18:41         ` Andreas Kemnade
2020-08-23 22:42         ` Jonathan Neuschäfer
2020-08-23 22:42           ` Jonathan Neuschäfer
2020-06-20 22:42   ` [RFC PATCH 09/10] MAINTAINERS: Add entry for Netronix embedded controller Jonathan Neuschäfer
2020-06-20 22:42     ` Jonathan Neuschäfer
2020-06-20 22:42 ` [RFC PATCH 06/10] pwm: ntxec: Add driver for PWM function in Netronix EC Jonathan Neuschäfer
2020-06-20 22:42   ` Jonathan Neuschäfer
2020-06-22  8:18   ` Uwe Kleine-König
2020-06-22  8:18     ` Uwe Kleine-König
     [not found]     ` <20200622081802.pv4xmb7vn4te5r5t-T6qyLwKrzP+Pq0V0m3QNwQq/OYV65a7L4Y2cMoPwMik@public.gmane.org>
2020-07-03 16:15       ` Jonathan Neuschäfer
2020-07-03 16:15         ` Jonathan Neuschäfer
2020-07-03 16:15         ` Jonathan Neuschäfer
2020-06-20 22:42 ` [RFC PATCH 07/10] dt-bindings: rtc: Add bindings for Netronix embedded controller RTC Jonathan Neuschäfer
2020-06-20 22:42   ` Jonathan Neuschäfer
     [not found]   ` <20200620224222.1312520-6-j.neuschaefer-hi6Y0CQ0nG0@public.gmane.org>
2020-06-21  0:02     ` Alexandre Belloni
2020-06-21  0:02       ` Alexandre Belloni
     [not found]       ` <20200621000220.GB131826-m++hUPXGwpdeoWH0uzbU5w@public.gmane.org>
2020-06-26 21:55         ` Andreas Kemnade
2020-06-26 21:55           ` Andreas Kemnade
2020-06-26 21:55           ` Andreas Kemnade
     [not found]           ` <20200626235552.7820a999-cLv4Z9ELZ06ZuzBka8ofvg@public.gmane.org>
2020-07-03 17:04             ` Jonathan Neuschäfer
2020-07-03 17:04               ` Jonathan Neuschäfer
2020-07-03 17:04               ` Jonathan Neuschäfer
2020-06-20 22:42 ` [RFC PATCH 08/10] rtc: New driver for RTC in Netronix embedded controller Jonathan Neuschäfer
2020-06-20 22:42   ` Jonathan Neuschäfer
     [not found]   ` <20200620224222.1312520-7-j.neuschaefer-hi6Y0CQ0nG0@public.gmane.org>
2020-06-21  0:11     ` Alexandre Belloni
2020-06-21  0:11       ` Alexandre Belloni
     [not found]       ` <20200621001106.GC131826-m++hUPXGwpdeoWH0uzbU5w@public.gmane.org>
2020-07-04 19:23         ` Jonathan Neuschäfer
2020-07-04 19:23           ` Jonathan Neuschäfer
2020-07-04 19:23           ` Jonathan Neuschäfer
2020-06-20 22:42 ` [RFC PATCH 10/10] ARM: dts: imx50-kobo-aura: Add " Jonathan Neuschäfer
2020-06-20 22:42   ` Jonathan Neuschäfer
2020-06-20 22:46 ` [RFC PATCH 02/10] dt-bindings: Add vendor prefix for Netronix, Inc Jonathan Neuschäfer
2020-06-20 22:46   ` Jonathan Neuschäfer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200627101738.2fe4abc3@aktux \
    --to=andreas@kemnade.info \
    --cc=a.zummo@towertech.it \
    --cc=alexandre.belloni@bootlin.com \
    --cc=allen.chen@ite.com.t \
    --cc=broonie@kernel.org \
    --cc=festevam@gmail.com \
    --cc=heiko.stuebner@theobroma-systems.com \
    --cc=j.neuschaefer@gmx.net \
    --cc=kernel@pengutronix.de \
    --cc=lee.jones@linaro.org \
    --cc=linus.walleij@linaro.org \
    --cc=linux-imx@nxp.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lkundrak@v3.sk \
    --cc=robh+dt@kernel.org \
    --cc=s.hauer@pengutronix.de \
    --cc=sam@ravnborg.org \
    --cc=shawnguo@kernel.org \
    --cc=stephan@gerhold.net \
    --cc=thierry.reding@gmail.com \
    --cc=u.kleine-koenig@pengutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.