linux-rtc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/9] Use MFD framework for SGI IOC3 drivers
@ 2019-08-09 10:32 Thomas Bogendoerfer
  2019-08-09 10:32 ` [PATCH v4 1/9] w1: add 1-wire master driver for IP block found in SGI ASICs Thomas Bogendoerfer
                   ` (8 more replies)
  0 siblings, 9 replies; 27+ messages in thread
From: Thomas Bogendoerfer @ 2019-08-09 10:32 UTC (permalink / raw)
  To: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Srinivas Kandagatla,
	Alessandro Zummo, Alexandre Belloni, Greg Kroah-Hartman,
	Jiri Slaby, Evgeniy Polyakov, linux-mips, linux-kernel,
	linux-input, netdev, linux-rtc, linux-serial

SGI IOC3 ASIC includes support for ethernet, PS2 keyboard/mouse,
NIC (number in a can), GPIO and a byte  bus. By attaching a
SuperIO chip to it, it also supports serial lines and a parallel
port. The chip is used on a variety of SGI systems with different
configurations. This patchset moves code out of the network driver,
which doesn't belong there, into its new place a MFD driver and
specific platform drivers for the different subfunctions.

Changes in v4:
 - added w1 drivers to the series after merge in 5.3 failed because
   of no response from maintainer and other parts of this series
   won't work without that drivers
 - moved ip30 systemboard support to the ip30 series, which will
   deal with rtc oddity Lee found
 - converted to use devm_platform_ioremap_resource
 - use PLATFORM_DEVID_AUTO for serial, ethernet and serio in mfd driver
 - fixed reverse christmas order in ioc3-eth.c
 - formating issue found by Lee
 - re-worked irq request/free in serio driver to avoid crashes during
   probe/remove

Changes in v3:
 - use 1-wire subsystem for handling proms
 - pci-xtalk driver uses prom information to create PCI subsystem
   ids for use in MFD driver
 - changed MFD driver to only use static declared mfd_cells
 - added IP30 system board setup to MFD driver
 - mac address is now read from ioc3-eth driver with nvmem framework

Changes in v2:
 - fixed issue in ioc3kbd.c reported by Dmitry Torokhov
 - merged IP27 RTC removal and 8250 serial driver addition into
   main MFD patch to keep patches bisectable

Thomas Bogendoerfer (9):
  w1: add 1-wire master driver for IP block found in SGI ASICs
  w1: add DS2501, DS2502, DS2505 EPROM device driver
  nvmem: core: add nvmem_device_find
  MIPS: PCI: refactor ioc3 special handling
  MIPS: PCI: use information from 1-wire PROM for IOC3 detection
  MIPS: SGI-IP27: remove ioc3 ethernet init
  mfd: ioc3: Add driver for SGI IOC3 chip
  MIPS: SGI-IP27: fix readb/writeb addressing
  Input: add IOC3 serio driver

 arch/mips/include/asm/mach-ip27/mangle-port.h |    4 +-
 arch/mips/include/asm/pci/bridge.h            |    1 +
 arch/mips/include/asm/sn/ioc3.h               |  356 ++---
 arch/mips/pci/pci-xtalk-bridge.c              |  296 ++--
 arch/mips/sgi-ip27/ip27-console.c             |    5 +-
 arch/mips/sgi-ip27/ip27-init.c                |   13 -
 arch/mips/sgi-ip27/ip27-timer.c               |   20 -
 arch/mips/sgi-ip27/ip27-xtalk.c               |   38 +-
 drivers/input/serio/Kconfig                   |   10 +
 drivers/input/serio/Makefile                  |    1 +
 drivers/input/serio/ioc3kbd.c                 |  163 +++
 drivers/mfd/Kconfig                           |   13 +
 drivers/mfd/Makefile                          |    1 +
 drivers/mfd/ioc3.c                            |  586 ++++++++
 drivers/net/ethernet/sgi/Kconfig              |    4 +-
 drivers/net/ethernet/sgi/ioc3-eth.c           | 1936 ++++++++++---------------
 drivers/nvmem/core.c                          |   62 +-
 drivers/rtc/rtc-m48t35.c                      |   11 +
 drivers/tty/serial/8250/8250_ioc3.c           |   98 ++
 drivers/tty/serial/8250/Kconfig               |   11 +
 drivers/tty/serial/8250/Makefile              |    1 +
 drivers/w1/masters/Kconfig                    |    9 +
 drivers/w1/masters/Makefile                   |    1 +
 drivers/w1/masters/sgi_w1.c                   |  130 ++
 drivers/w1/slaves/Kconfig                     |    6 +
 drivers/w1/slaves/Makefile                    |    1 +
 drivers/w1/slaves/w1_ds250x.c                 |  293 ++++
 include/linux/nvmem-consumer.h                |    9 +
 include/linux/platform_data/sgi-w1.h          |   15 +
 include/linux/w1.h                            |    2 +
 30 files changed, 2522 insertions(+), 1574 deletions(-)
 create mode 100644 drivers/input/serio/ioc3kbd.c
 create mode 100644 drivers/mfd/ioc3.c
 create mode 100644 drivers/tty/serial/8250/8250_ioc3.c
 create mode 100644 drivers/w1/masters/sgi_w1.c
 create mode 100644 drivers/w1/slaves/w1_ds250x.c
 create mode 100644 include/linux/platform_data/sgi-w1.h

-- 
2.13.7


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v4 1/9] w1: add 1-wire master driver for IP block found in SGI ASICs
  2019-08-09 10:32 [PATCH v4 0/9] Use MFD framework for SGI IOC3 drivers Thomas Bogendoerfer
@ 2019-08-09 10:32 ` Thomas Bogendoerfer
  2019-08-09 10:32 ` [PATCH v4 2/9] w1: add DS2501, DS2502, DS2505 EPROM device driver Thomas Bogendoerfer
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 27+ messages in thread
From: Thomas Bogendoerfer @ 2019-08-09 10:32 UTC (permalink / raw)
  To: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Srinivas Kandagatla,
	Alessandro Zummo, Alexandre Belloni, Greg Kroah-Hartman,
	Jiri Slaby, Evgeniy Polyakov, linux-mips, linux-kernel,
	linux-input, netdev, linux-rtc, linux-serial

Starting with SGI Origin machines nearly every new SGI ASIC contains
an 1-Wire master. They are used for attaching One-Wire prom devices,
which contain information about part numbers, revision numbers,
serial number etc. and MAC addresses for ethernet interfaces.
This patch adds a master driver to support this IP block.
It also adds an extra field dev_id to struct w1_bus_master, which
could be in used in slave drivers for creating unique device names.

Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
---
 drivers/w1/masters/Kconfig           |   9 +++
 drivers/w1/masters/Makefile          |   1 +
 drivers/w1/masters/sgi_w1.c          | 130 +++++++++++++++++++++++++++++++++++
 include/linux/platform_data/sgi-w1.h |  15 ++++
 include/linux/w1.h                   |   2 +
 5 files changed, 157 insertions(+)
 create mode 100644 drivers/w1/masters/sgi_w1.c
 create mode 100644 include/linux/platform_data/sgi-w1.h

diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig
index 7ae260577901..24b9a8e05f64 100644
--- a/drivers/w1/masters/Kconfig
+++ b/drivers/w1/masters/Kconfig
@@ -65,5 +65,14 @@ config HDQ_MASTER_OMAP
 	  Say Y here if you want support for the 1-wire or HDQ Interface
 	  on an OMAP processor.
 
+config W1_MASTER_SGI
+	tristate "SGI ASIC driver"
+	help
+	  Say Y here if you want support for your 1-wire devices using
+	  SGI ASIC 1-Wire interface
+
+	  This support is also available as a module.  If so, the module
+	  will be called sgi_w1.
+
 endmenu
 
diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile
index 18954cae4256..dae629b7ab49 100644
--- a/drivers/w1/masters/Makefile
+++ b/drivers/w1/masters/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_W1_MASTER_MXC)		+= mxc_w1.o
 obj-$(CONFIG_W1_MASTER_DS1WM)		+= ds1wm.o
 obj-$(CONFIG_W1_MASTER_GPIO)		+= w1-gpio.o
 obj-$(CONFIG_HDQ_MASTER_OMAP)		+= omap_hdq.o
+obj-$(CONFIG_W1_MASTER_SGI)		+= sgi_w1.o
diff --git a/drivers/w1/masters/sgi_w1.c b/drivers/w1/masters/sgi_w1.c
new file mode 100644
index 000000000000..1b2d96b945be
--- /dev/null
+++ b/drivers/w1/masters/sgi_w1.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * sgi_w1.c - w1 master driver for one wire support in SGI ASICs
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/sgi-w1.h>
+
+#include <linux/w1.h>
+
+#define MCR_RD_DATA	BIT(0)
+#define MCR_DONE	BIT(1)
+
+#define MCR_PACK(pulse, sample) (((pulse) << 10) | ((sample) << 2))
+
+struct sgi_w1_device {
+	u32 __iomem *mcr;
+	struct w1_bus_master bus_master;
+	char dev_id[64];
+};
+
+static u8 sgi_w1_wait(u32 __iomem *mcr)
+{
+	u32 mcr_val;
+
+	do {
+		mcr_val = readl(mcr);
+	} while (!(mcr_val & MCR_DONE));
+
+	return (mcr_val & MCR_RD_DATA) ? 1 : 0;
+}
+
+/*
+ * this is the low level routine to
+ * reset the device on the One Wire interface
+ * on the hardware
+ */
+static u8 sgi_w1_reset_bus(void *data)
+{
+	struct sgi_w1_device *dev = data;
+	u8 ret;
+
+	writel(MCR_PACK(520, 65), dev->mcr);
+	ret = sgi_w1_wait(dev->mcr);
+	udelay(500); /* recovery time */
+	return ret;
+}
+
+/*
+ * this is the low level routine to read/write a bit on the One Wire
+ * interface on the hardware. It does write 0 if parameter bit is set
+ * to 0, otherwise a write 1/read.
+ */
+static u8 sgi_w1_touch_bit(void *data, u8 bit)
+{
+	struct sgi_w1_device *dev = data;
+	u8 ret;
+
+	if (bit)
+		writel(MCR_PACK(6, 13), dev->mcr);
+	else
+		writel(MCR_PACK(80, 30), dev->mcr);
+
+	ret = sgi_w1_wait(dev->mcr);
+	if (bit)
+		udelay(100); /* recovery */
+	return ret;
+}
+
+static int sgi_w1_probe(struct platform_device *pdev)
+{
+	struct sgi_w1_device *sdev;
+	struct sgi_w1_platform_data *pdata;
+	struct resource *res;
+
+	sdev = devm_kzalloc(&pdev->dev, sizeof(struct sgi_w1_device),
+			    GFP_KERNEL);
+	if (!sdev)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	sdev->mcr = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(sdev->mcr))
+		return PTR_ERR(sdev->mcr);
+
+	sdev->bus_master.data = sdev;
+	sdev->bus_master.reset_bus = sgi_w1_reset_bus;
+	sdev->bus_master.touch_bit = sgi_w1_touch_bit;
+
+	pdata = dev_get_platdata(&pdev->dev);
+	if (pdata) {
+		strlcpy(sdev->dev_id, pdata->dev_id, sizeof(sdev->dev_id));
+		sdev->bus_master.dev_id = sdev->dev_id;
+	}
+
+	platform_set_drvdata(pdev, sdev);
+
+	return w1_add_master_device(&sdev->bus_master);
+}
+
+/*
+ * disassociate the w1 device from the driver
+ */
+static int sgi_w1_remove(struct platform_device *pdev)
+{
+	struct sgi_w1_device *sdev = platform_get_drvdata(pdev);
+
+	w1_remove_master_device(&sdev->bus_master);
+
+	return 0;
+}
+
+static struct platform_driver sgi_w1_driver = {
+	.driver = {
+		.name = "sgi_w1",
+	},
+	.probe = sgi_w1_probe,
+	.remove = sgi_w1_remove,
+};
+module_platform_driver(sgi_w1_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Thomas Bogendoerfer");
+MODULE_DESCRIPTION("Driver for One-Wire IP in SGI ASICs");
diff --git a/include/linux/platform_data/sgi-w1.h b/include/linux/platform_data/sgi-w1.h
new file mode 100644
index 000000000000..fc6b92e0b942
--- /dev/null
+++ b/include/linux/platform_data/sgi-w1.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * SGI One-Wire (W1) IP
+ */
+
+#ifndef PLATFORM_DATA_SGI_W1_H
+#define PLATFORM_DATA_SGI_W1_H
+
+#include <asm/sn/types.h>
+
+struct sgi_w1_platform_data {
+	char dev_id[64];
+};
+
+#endif /* PLATFORM_DATA_SGI_W1_H */
diff --git a/include/linux/w1.h b/include/linux/w1.h
index e0b5156f78fd..89843e9f634c 100644
--- a/include/linux/w1.h
+++ b/include/linux/w1.h
@@ -150,6 +150,8 @@ struct w1_bus_master {
 
 	void		(*search)(void *, struct w1_master *,
 		u8, w1_slave_found_callback);
+
+	char		*dev_id;
 };
 
 /**
-- 
2.13.7


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v4 2/9] w1: add DS2501, DS2502, DS2505 EPROM device driver
  2019-08-09 10:32 [PATCH v4 0/9] Use MFD framework for SGI IOC3 drivers Thomas Bogendoerfer
  2019-08-09 10:32 ` [PATCH v4 1/9] w1: add 1-wire master driver for IP block found in SGI ASICs Thomas Bogendoerfer
@ 2019-08-09 10:32 ` Thomas Bogendoerfer
  2019-08-09 10:32 ` [PATCH v4 3/9] nvmem: core: add nvmem_device_find Thomas Bogendoerfer
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 27+ messages in thread
From: Thomas Bogendoerfer @ 2019-08-09 10:32 UTC (permalink / raw)
  To: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Srinivas Kandagatla,
	Alessandro Zummo, Alexandre Belloni, Greg Kroah-Hartman,
	Jiri Slaby, Evgeniy Polyakov, linux-mips, linux-kernel,
	linux-input, netdev, linux-rtc, linux-serial

Add a 1-Wire slave driver to support DS250x EPROM deivces. This
slave driver attaches the devices to the NVMEM subsystem for
an easy in-kernel usage.

Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
---
 drivers/w1/slaves/Kconfig     |   6 +
 drivers/w1/slaves/Makefile    |   1 +
 drivers/w1/slaves/w1_ds250x.c | 293 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 300 insertions(+)
 create mode 100644 drivers/w1/slaves/w1_ds250x.c

diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index 37aaad26b373..ebed495b9e69 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -101,6 +101,12 @@ config W1_SLAVE_DS2438
 	  Say Y here if you want to use a 1-wire
 	  DS2438 Smart Battery Monitor device support
 
+config W1_SLAVE_DS250X
+	tristate "512b/1kb/16kb EPROM family support"
+	help
+	  Say Y here if you want to use a 1-wire
+	  512b/1kb/16kb EPROM family device (DS250x).
+
 config W1_SLAVE_DS2780
 	tristate "Dallas 2780 battery monitor chip"
 	help
diff --git a/drivers/w1/slaves/Makefile b/drivers/w1/slaves/Makefile
index eab29f151413..8e9655eaa478 100644
--- a/drivers/w1/slaves/Makefile
+++ b/drivers/w1/slaves/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_W1_SLAVE_DS2431)	+= w1_ds2431.o
 obj-$(CONFIG_W1_SLAVE_DS2805)	+= w1_ds2805.o
 obj-$(CONFIG_W1_SLAVE_DS2433)	+= w1_ds2433.o
 obj-$(CONFIG_W1_SLAVE_DS2438)	+= w1_ds2438.o
+obj-$(CONFIG_W1_SLAVE_DS250X)	+= w1_ds250x.o
 obj-$(CONFIG_W1_SLAVE_DS2780)	+= w1_ds2780.o
 obj-$(CONFIG_W1_SLAVE_DS2781)	+= w1_ds2781.o
 obj-$(CONFIG_W1_SLAVE_DS28E04)	+= w1_ds28e04.o
diff --git a/drivers/w1/slaves/w1_ds250x.c b/drivers/w1/slaves/w1_ds250x.c
new file mode 100644
index 000000000000..78da3774bbbe
--- /dev/null
+++ b/drivers/w1/slaves/w1_ds250x.c
@@ -0,0 +1,293 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * w1_ds250x.c - w1 family 09/0b/89/91 (DS250x) driver
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/crc16.h>
+
+#include <linux/w1.h>
+#include <linux/nvmem-provider.h>
+
+#define W1_DS2501_UNW_FAMILY    0x91
+#define W1_DS2501_SIZE          64
+
+#define W1_DS2502_FAMILY        0x09
+#define W1_DS2502_UNW_FAMILY    0x89
+#define W1_DS2502_SIZE          128
+
+#define W1_DS2505_FAMILY	0x0b
+#define W1_DS2505_SIZE		2048
+
+#define W1_PAGE_SIZE		32
+
+#define W1_EXT_READ_MEMORY	0xA5
+#define W1_READ_DATA_CRC        0xC3
+
+#define OFF2PG(off)	((off) / W1_PAGE_SIZE)
+
+#define CRC16_INIT		0
+#define CRC16_VALID		0xb001
+
+struct w1_eprom_data {
+	size_t size;
+	int (*read)(struct w1_slave *sl, int pageno);
+	u8 eprom[W1_DS2505_SIZE];
+	DECLARE_BITMAP(page_present, W1_DS2505_SIZE / W1_PAGE_SIZE);
+	char nvmem_name[64];
+};
+
+static int w1_ds2502_read_page(struct w1_slave *sl, int pageno)
+{
+	struct w1_eprom_data *data = sl->family_data;
+	int pgoff = pageno * W1_PAGE_SIZE;
+	int ret = -EIO;
+	u8 buf[3];
+	u8 crc8;
+
+	if (test_bit(pageno, data->page_present))
+		return 0; /* page already present */
+
+	mutex_lock(&sl->master->bus_mutex);
+
+	if (w1_reset_select_slave(sl))
+		goto err;
+
+	buf[0] = W1_READ_DATA_CRC;
+	buf[1] = pgoff & 0xff;
+	buf[2] = pgoff >> 8;
+	w1_write_block(sl->master, buf, 3);
+
+	crc8 = w1_read_8(sl->master);
+	if (w1_calc_crc8(buf, 3) != crc8)
+		goto err;
+
+	w1_read_block(sl->master, &data->eprom[pgoff], W1_PAGE_SIZE);
+
+	crc8 = w1_read_8(sl->master);
+	if (w1_calc_crc8(&data->eprom[pgoff], W1_PAGE_SIZE) != crc8)
+		goto err;
+
+	set_bit(pageno, data->page_present); /* mark page present */
+	ret = 0;
+err:
+	mutex_unlock(&sl->master->bus_mutex);
+	return ret;
+}
+
+static int w1_ds2505_read_page(struct w1_slave *sl, int pageno)
+{
+	struct w1_eprom_data *data = sl->family_data;
+	int redir_retries = 16;
+	int pgoff, epoff;
+	int ret = -EIO;
+	u8 buf[6];
+	u8 redir;
+	u16 crc;
+
+	if (test_bit(pageno, data->page_present))
+		return 0; /* page already present */
+
+	epoff = pgoff = pageno * W1_PAGE_SIZE;
+	mutex_lock(&sl->master->bus_mutex);
+
+retry:
+	if (w1_reset_select_slave(sl))
+		goto err;
+
+	buf[0] = W1_EXT_READ_MEMORY;
+	buf[1] = pgoff & 0xff;
+	buf[2] = pgoff >> 8;
+	w1_write_block(sl->master, buf, 3);
+	w1_read_block(sl->master, buf + 3, 3); /* redir, crc16 */
+	redir = buf[3];
+	crc = crc16(CRC16_INIT, buf, 6);
+
+	if (crc != CRC16_VALID)
+		goto err;
+
+
+	if (redir != 0xff) {
+		redir_retries--;
+		if (redir_retries < 0)
+			goto err;
+
+		pgoff = (redir ^ 0xff) * W1_PAGE_SIZE;
+		goto retry;
+	}
+
+	w1_read_block(sl->master, &data->eprom[epoff], W1_PAGE_SIZE);
+	w1_read_block(sl->master, buf, 2); /* crc16 */
+	crc = crc16(CRC16_INIT, &data->eprom[epoff], W1_PAGE_SIZE);
+	crc = crc16(crc, buf, 2);
+
+	if (crc != CRC16_VALID)
+		goto err;
+
+	set_bit(pageno, data->page_present);
+	ret = 0;
+err:
+	mutex_unlock(&sl->master->bus_mutex);
+	return ret;
+}
+
+static int w1_nvmem_read(void *priv, unsigned int off, void *buf, size_t count)
+{
+	struct w1_slave *sl = priv;
+	struct w1_eprom_data *data = sl->family_data;
+	size_t eprom_size = data->size;
+	int ret;
+	int i;
+
+	if (off > eprom_size)
+		return -EINVAL;
+
+	if ((off + count) > eprom_size)
+		count = eprom_size - off;
+
+	i = OFF2PG(off);
+	do {
+		ret = data->read(sl, i++);
+		if (ret < 0)
+			return ret;
+	} while (i < OFF2PG(off + count));
+
+	memcpy(buf, &data->eprom[off], count);
+	return 0;
+}
+
+static int w1_eprom_add_slave(struct w1_slave *sl)
+{
+	struct w1_eprom_data *data;
+	struct nvmem_device *nvmem;
+	struct nvmem_config nvmem_cfg = {
+		.dev = &sl->dev,
+		.reg_read = w1_nvmem_read,
+		.type = NVMEM_TYPE_OTP,
+		.read_only = true,
+		.word_size = 1,
+		.priv = sl,
+		.id = -1
+	};
+
+	data = devm_kzalloc(&sl->dev, sizeof(struct w1_eprom_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	sl->family_data = data;
+	switch (sl->family->fid) {
+	case W1_DS2501_UNW_FAMILY:
+		data->size = W1_DS2501_SIZE;
+		data->read = w1_ds2502_read_page;
+		break;
+	case W1_DS2502_FAMILY:
+	case W1_DS2502_UNW_FAMILY:
+		data->size = W1_DS2502_SIZE;
+		data->read = w1_ds2502_read_page;
+		break;
+	case W1_DS2505_FAMILY:
+		data->size = W1_DS2505_SIZE;
+		data->read = w1_ds2505_read_page;
+		break;
+	}
+
+	if (sl->master->bus_master->dev_id)
+		snprintf(data->nvmem_name, sizeof(data->nvmem_name),
+			 "%s-%02x-%012llx",
+			 sl->master->bus_master->dev_id, sl->reg_num.family,
+			 (unsigned long long)sl->reg_num.id);
+	else
+		snprintf(data->nvmem_name, sizeof(data->nvmem_name),
+			 "%02x-%012llx",
+			 sl->reg_num.family,
+			 (unsigned long long)sl->reg_num.id);
+
+	nvmem_cfg.name = data->nvmem_name;
+	nvmem_cfg.size = data->size;
+
+	nvmem = devm_nvmem_register(&sl->dev, &nvmem_cfg);
+	if (IS_ERR(nvmem))
+		return PTR_ERR(nvmem);
+
+	return 0;
+}
+
+static struct w1_family_ops w1_eprom_fops = {
+	.add_slave	= w1_eprom_add_slave,
+};
+
+static struct w1_family w1_family_09 = {
+	.fid = W1_DS2502_FAMILY,
+	.fops = &w1_eprom_fops,
+};
+
+static struct w1_family w1_family_0b = {
+	.fid = W1_DS2505_FAMILY,
+	.fops = &w1_eprom_fops,
+};
+
+static struct w1_family w1_family_89 = {
+	.fid = W1_DS2502_UNW_FAMILY,
+	.fops = &w1_eprom_fops,
+};
+
+static struct w1_family w1_family_91 = {
+	.fid = W1_DS2501_UNW_FAMILY,
+	.fops = &w1_eprom_fops,
+};
+
+static int __init w1_ds250x_init(void)
+{
+	int err;
+
+	err = w1_register_family(&w1_family_09);
+	if (err)
+		return err;
+
+	err = w1_register_family(&w1_family_0b);
+	if (err)
+		goto err_0b;
+
+	err = w1_register_family(&w1_family_89);
+	if (err)
+		goto err_89;
+
+	err = w1_register_family(&w1_family_91);
+	if (err)
+		goto err_91;
+
+	return 0;
+
+err_91:
+	w1_unregister_family(&w1_family_89);
+err_89:
+	w1_unregister_family(&w1_family_0b);
+err_0b:
+	w1_unregister_family(&w1_family_09);
+	return err;
+}
+
+static void __exit w1_ds250x_exit(void)
+{
+	w1_unregister_family(&w1_family_09);
+	w1_unregister_family(&w1_family_0b);
+	w1_unregister_family(&w1_family_89);
+	w1_unregister_family(&w1_family_91);
+}
+
+module_init(w1_ds250x_init);
+module_exit(w1_ds250x_exit);
+
+MODULE_AUTHOR("Thomas Bogendoerfer <tbogendoerfe@suse.de>");
+MODULE_DESCRIPTION("w1 family driver for DS250x Add Only Memory");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("w1-family-" __stringify(W1_DS2502_FAMILY));
+MODULE_ALIAS("w1-family-" __stringify(W1_DS2505_FAMILY));
+MODULE_ALIAS("w1-family-" __stringify(W1_DS2501_UNW_FAMILY));
+MODULE_ALIAS("w1-family-" __stringify(W1_DS2502_UNW_FAMILY));
-- 
2.13.7


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v4 3/9] nvmem: core: add nvmem_device_find
  2019-08-09 10:32 [PATCH v4 0/9] Use MFD framework for SGI IOC3 drivers Thomas Bogendoerfer
  2019-08-09 10:32 ` [PATCH v4 1/9] w1: add 1-wire master driver for IP block found in SGI ASICs Thomas Bogendoerfer
  2019-08-09 10:32 ` [PATCH v4 2/9] w1: add DS2501, DS2502, DS2505 EPROM device driver Thomas Bogendoerfer
@ 2019-08-09 10:32 ` Thomas Bogendoerfer
  2019-08-13  9:40   ` Srinivas Kandagatla
  2019-08-09 10:32 ` [PATCH v4 4/9] MIPS: PCI: refactor ioc3 special handling Thomas Bogendoerfer
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 27+ messages in thread
From: Thomas Bogendoerfer @ 2019-08-09 10:32 UTC (permalink / raw)
  To: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Srinivas Kandagatla,
	Alessandro Zummo, Alexandre Belloni, Greg Kroah-Hartman,
	Jiri Slaby, Evgeniy Polyakov, linux-mips, linux-kernel,
	linux-input, netdev, linux-rtc, linux-serial

nvmem_device_find provides a way to search for nvmem devices with
the help of a match function simlair to bus_find_device.

Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
---
 drivers/nvmem/core.c           | 62 ++++++++++++++++++++++--------------------
 include/linux/nvmem-consumer.h |  9 ++++++
 2 files changed, 41 insertions(+), 30 deletions(-)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index ac5d945be88a..e591ba54758f 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -76,36 +76,18 @@ static struct bus_type nvmem_bus_type = {
 	.name		= "nvmem",
 };
 
+#if IS_ENABLED(CONFIG_OF)
 static int of_nvmem_match(struct device *dev, const void *nvmem_np)
 {
 	return dev->of_node == nvmem_np;
 }
+#endif
 
-static struct nvmem_device *of_nvmem_find(struct device_node *nvmem_np)
+static int nvmem_match_name(struct device *dev, const void *data)
 {
-	struct device *d;
-
-	if (!nvmem_np)
-		return NULL;
-
-	d = bus_find_device(&nvmem_bus_type, NULL, nvmem_np, of_nvmem_match);
-
-	if (!d)
-		return NULL;
+	const char *name = data;
 
-	return to_nvmem_device(d);
-}
-
-static struct nvmem_device *nvmem_find(const char *name)
-{
-	struct device *d;
-
-	d = bus_find_device_by_name(&nvmem_bus_type, NULL, name);
-
-	if (!d)
-		return NULL;
-
-	return to_nvmem_device(d);
+	return sysfs_streq(name, dev_name(dev));
 }
 
 static void nvmem_cell_drop(struct nvmem_cell *cell)
@@ -537,13 +519,16 @@ int devm_nvmem_unregister(struct device *dev, struct nvmem_device *nvmem)
 }
 EXPORT_SYMBOL(devm_nvmem_unregister);
 
-static struct nvmem_device *__nvmem_device_get(struct device_node *np,
-					       const char *nvmem_name)
+static struct nvmem_device *__nvmem_device_get(void *data,
+			int (*match)(struct device *dev, const void *data))
 {
 	struct nvmem_device *nvmem = NULL;
+	struct device *dev;
 
 	mutex_lock(&nvmem_mutex);
-	nvmem = np ? of_nvmem_find(np) : nvmem_find(nvmem_name);
+	dev = bus_find_device(&nvmem_bus_type, NULL, data, match);
+	if (dev)
+		nvmem = to_nvmem_device(dev);
 	mutex_unlock(&nvmem_mutex);
 	if (!nvmem)
 		return ERR_PTR(-EPROBE_DEFER);
@@ -592,7 +577,7 @@ struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id)
 	if (!nvmem_np)
 		return ERR_PTR(-ENOENT);
 
-	return __nvmem_device_get(nvmem_np, NULL);
+	return __nvmem_device_get(nvmem_np, of_nvmem_match);
 }
 EXPORT_SYMBOL_GPL(of_nvmem_device_get);
 #endif
@@ -618,10 +603,26 @@ struct nvmem_device *nvmem_device_get(struct device *dev, const char *dev_name)
 
 	}
 
-	return __nvmem_device_get(NULL, dev_name);
+	return __nvmem_device_get((void *)dev_name, nvmem_match_name);
 }
 EXPORT_SYMBOL_GPL(nvmem_device_get);
 
+/**
+ * nvmem_device_find() - Find nvmem device with matching function
+ *
+ * @data: Data to pass to match function
+ * @match: Callback function to check device
+ *
+ * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
+ * on success.
+ */
+struct nvmem_device *nvmem_device_find(void *data,
+			int (*match)(struct device *dev, const void *data))
+{
+	return __nvmem_device_get(data, match);
+}
+EXPORT_SYMBOL_GPL(nvmem_device_find);
+
 static int devm_nvmem_device_match(struct device *dev, void *res, void *data)
 {
 	struct nvmem_device **nvmem = res;
@@ -715,7 +716,8 @@ nvmem_cell_get_from_lookup(struct device *dev, const char *con_id)
 		if ((strcmp(lookup->dev_id, dev_id) == 0) &&
 		    (strcmp(lookup->con_id, con_id) == 0)) {
 			/* This is the right entry. */
-			nvmem = __nvmem_device_get(NULL, lookup->nvmem_name);
+			nvmem = __nvmem_device_get((void *)lookup->nvmem_name,
+						   nvmem_match_name);
 			if (IS_ERR(nvmem)) {
 				/* Provider may not be registered yet. */
 				cell = ERR_CAST(nvmem);
@@ -785,7 +787,7 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id)
 	if (!nvmem_np)
 		return ERR_PTR(-EINVAL);
 
-	nvmem = __nvmem_device_get(nvmem_np, NULL);
+	nvmem = __nvmem_device_get(nvmem_np, of_nvmem_match);
 	of_node_put(nvmem_np);
 	if (IS_ERR(nvmem))
 		return ERR_CAST(nvmem);
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index 8f8be5b00060..02dc4aa992b2 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -89,6 +89,9 @@ void nvmem_del_cell_lookups(struct nvmem_cell_lookup *entries,
 int nvmem_register_notifier(struct notifier_block *nb);
 int nvmem_unregister_notifier(struct notifier_block *nb);
 
+struct nvmem_device *nvmem_device_find(void *data,
+			int (*match)(struct device *dev, const void *data));
+
 #else
 
 static inline struct nvmem_cell *nvmem_cell_get(struct device *dev,
@@ -204,6 +207,12 @@ static inline int nvmem_unregister_notifier(struct notifier_block *nb)
 	return -EOPNOTSUPP;
 }
 
+static inline struct nvmem_device *nvmem_device_find(void *data,
+			int (*match)(struct device *dev, const void *data))
+{
+	return NULL;
+}
+
 #endif /* CONFIG_NVMEM */
 
 #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
-- 
2.13.7


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v4 4/9] MIPS: PCI: refactor ioc3 special handling
  2019-08-09 10:32 [PATCH v4 0/9] Use MFD framework for SGI IOC3 drivers Thomas Bogendoerfer
                   ` (2 preceding siblings ...)
  2019-08-09 10:32 ` [PATCH v4 3/9] nvmem: core: add nvmem_device_find Thomas Bogendoerfer
@ 2019-08-09 10:32 ` Thomas Bogendoerfer
  2019-08-09 10:32 ` [PATCH v4 5/9] MIPS: PCI: use information from 1-wire PROM for IOC3 detection Thomas Bogendoerfer
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 27+ messages in thread
From: Thomas Bogendoerfer @ 2019-08-09 10:32 UTC (permalink / raw)
  To: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Srinivas Kandagatla,
	Alessandro Zummo, Alexandre Belloni, Greg Kroah-Hartman,
	Jiri Slaby, Evgeniy Polyakov, linux-mips, linux-kernel,
	linux-input, netdev, linux-rtc, linux-serial

Refactored code to only have one ioc3 special handling for read
access and one for write access.

Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
---
 arch/mips/pci/pci-xtalk-bridge.c | 167 +++++++++++++++------------------------
 1 file changed, 62 insertions(+), 105 deletions(-)

diff --git a/arch/mips/pci/pci-xtalk-bridge.c b/arch/mips/pci/pci-xtalk-bridge.c
index bcf7f559789a..7b4d40354ee7 100644
--- a/arch/mips/pci/pci-xtalk-bridge.c
+++ b/arch/mips/pci/pci-xtalk-bridge.c
@@ -20,16 +20,50 @@
  * Most of the IOC3 PCI config register aren't present
  * we emulate what is needed for a normal PCI enumeration
  */
-static u32 emulate_ioc3_cfg(int where, int size)
+static int ioc3_cfg_rd(void *addr, int where, int size, u32 *value)
 {
-	if (size == 1 && where == 0x3d)
-		return 0x01;
-	else if (size == 2 && where == 0x3c)
-		return 0x0100;
-	else if (size == 4 && where == 0x3c)
-		return 0x00000100;
+	u32 cf, shift, mask;
 
-	return 0;
+	switch (where & ~3) {
+	case 0x00 ... 0x10:
+	case 0x40 ... 0x44:
+		if (get_dbe(cf, (u32 *)addr))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+		break;
+	case 0x3c:
+		/* emulate sane interrupt pin value */
+		cf = 0x00000100;
+		break;
+	default:
+		cf = 0;
+		break;
+	}
+	shift = (where & 3) << 3;
+	mask = 0xffffffffU >> ((4 - size) << 3);
+	*value = (cf >> shift) & mask;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int ioc3_cfg_wr(void *addr, int where, int size, u32 value)
+{
+	u32 cf, shift, mask, smask;
+
+	if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
+		return PCIBIOS_SUCCESSFUL;
+
+	if (get_dbe(cf, (u32 *)addr))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	shift = ((where & 3) << 3);
+	mask = (0xffffffffU >> ((4 - size) << 3));
+	smask = mask << shift;
+
+	cf = (cf & ~smask) | ((value & mask) << shift);
+	if (put_dbe(cf, (u32 *)addr))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
 }
 
 static void bridge_disable_swapping(struct pci_dev *dev)
@@ -64,7 +98,7 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn,
 	int slot = PCI_SLOT(devfn);
 	int fn = PCI_FUNC(devfn);
 	void *addr;
-	u32 cf, shift, mask;
+	u32 cf;
 	int res;
 
 	addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
@@ -75,8 +109,10 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn,
 	 * IOC3 is broken beyond belief ...  Don't even give the
 	 * generic PCI code a chance to look at it for real ...
 	 */
-	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
-		goto is_ioc3;
+	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) {
+		addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
+		return ioc3_cfg_rd(addr, where, size, value);
+	}
 
 	addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
 
@@ -88,26 +124,6 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn,
 		res = get_dbe(*value, (u32 *)addr);
 
 	return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
-
-is_ioc3:
-
-	/*
-	 * IOC3 special handling
-	 */
-	if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) {
-		*value = emulate_ioc3_cfg(where, size);
-		return PCIBIOS_SUCCESSFUL;
-	}
-
-	addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
-	if (get_dbe(cf, (u32 *)addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	shift = ((where & 3) << 3);
-	mask = (0xffffffffU >> ((4 - size) << 3));
-	*value = (cf >> shift) & mask;
-
-	return PCIBIOS_SUCCESSFUL;
 }
 
 static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn,
@@ -119,7 +135,7 @@ static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn,
 	int slot = PCI_SLOT(devfn);
 	int fn = PCI_FUNC(devfn);
 	void *addr;
-	u32 cf, shift, mask;
+	u32 cf;
 	int res;
 
 	bridge_write(bc, b_pci_cfg, (busno << 16) | (slot << 11));
@@ -131,8 +147,10 @@ static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn,
 	 * IOC3 is broken beyond belief ...  Don't even give the
 	 * generic PCI code a chance to look at it for real ...
 	 */
-	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
-		goto is_ioc3;
+	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) {
+		addr = &bridge->b_type1_cfg.c[(fn << 8) | (where & ~3)];
+		return ioc3_cfg_rd(addr, where, size, value);
+	}
 
 	addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))];
 
@@ -144,26 +162,6 @@ static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn,
 		res = get_dbe(*value, (u32 *)addr);
 
 	return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
-
-is_ioc3:
-
-	/*
-	 * IOC3 special handling
-	 */
-	if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) {
-		*value = emulate_ioc3_cfg(where, size);
-		return PCIBIOS_SUCCESSFUL;
-	}
-
-	addr = &bridge->b_type1_cfg.c[(fn << 8) | where];
-	if (get_dbe(cf, (u32 *)addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	shift = ((where & 3) << 3);
-	mask = (0xffffffffU >> ((4 - size) << 3));
-	*value = (cf >> shift) & mask;
-
-	return PCIBIOS_SUCCESSFUL;
 }
 
 static int pci_read_config(struct pci_bus *bus, unsigned int devfn,
@@ -183,7 +181,7 @@ static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn,
 	int slot = PCI_SLOT(devfn);
 	int fn = PCI_FUNC(devfn);
 	void *addr;
-	u32 cf, shift, mask, smask;
+	u32 cf;
 	int res;
 
 	addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
@@ -194,8 +192,10 @@ static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn,
 	 * IOC3 is broken beyond belief ...  Don't even give the
 	 * generic PCI code a chance to look at it for real ...
 	 */
-	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
-		goto is_ioc3;
+	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) {
+		addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
+		return ioc3_cfg_wr(addr, where, size, value);
+	}
 
 	addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
 
@@ -210,29 +210,6 @@ static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn,
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	return PCIBIOS_SUCCESSFUL;
-
-is_ioc3:
-
-	/*
-	 * IOC3 special handling
-	 */
-	if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
-		return PCIBIOS_SUCCESSFUL;
-
-	addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
-
-	if (get_dbe(cf, (u32 *)addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	shift = ((where & 3) << 3);
-	mask = (0xffffffffU >> ((4 - size) << 3));
-	smask = mask << shift;
-
-	cf = (cf & ~smask) | ((value & mask) << shift);
-	if (put_dbe(cf, (u32 *)addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	return PCIBIOS_SUCCESSFUL;
 }
 
 static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn,
@@ -244,7 +221,7 @@ static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn,
 	int fn = PCI_FUNC(devfn);
 	int busno = bus->number;
 	void *addr;
-	u32 cf, shift, mask, smask;
+	u32 cf;
 	int res;
 
 	bridge_write(bc, b_pci_cfg, (busno << 16) | (slot << 11));
@@ -256,8 +233,10 @@ static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn,
 	 * IOC3 is broken beyond belief ...  Don't even give the
 	 * generic PCI code a chance to look at it for real ...
 	 */
-	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
-		goto is_ioc3;
+	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) {
+		addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
+		return ioc3_cfg_wr(addr, where, size, value);
+	}
 
 	addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))];
 
@@ -272,28 +251,6 @@ static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn,
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	return PCIBIOS_SUCCESSFUL;
-
-is_ioc3:
-
-	/*
-	 * IOC3 special handling
-	 */
-	if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
-		return PCIBIOS_SUCCESSFUL;
-
-	addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
-	if (get_dbe(cf, (u32 *)addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	shift = ((where & 3) << 3);
-	mask = (0xffffffffU >> ((4 - size) << 3));
-	smask = mask << shift;
-
-	cf = (cf & ~smask) | ((value & mask) << shift);
-	if (put_dbe(cf, (u32 *)addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	return PCIBIOS_SUCCESSFUL;
 }
 
 static int pci_write_config(struct pci_bus *bus, unsigned int devfn,
-- 
2.13.7


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v4 5/9] MIPS: PCI: use information from 1-wire PROM for IOC3 detection
  2019-08-09 10:32 [PATCH v4 0/9] Use MFD framework for SGI IOC3 drivers Thomas Bogendoerfer
                   ` (3 preceding siblings ...)
  2019-08-09 10:32 ` [PATCH v4 4/9] MIPS: PCI: refactor ioc3 special handling Thomas Bogendoerfer
@ 2019-08-09 10:32 ` Thomas Bogendoerfer
  2019-08-09 10:32 ` [PATCH v4 6/9] MIPS: SGI-IP27: remove ioc3 ethernet init Thomas Bogendoerfer
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 27+ messages in thread
From: Thomas Bogendoerfer @ 2019-08-09 10:32 UTC (permalink / raw)
  To: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Srinivas Kandagatla,
	Alessandro Zummo, Alexandre Belloni, Greg Kroah-Hartman,
	Jiri Slaby, Evgeniy Polyakov, linux-mips, linux-kernel,
	linux-input, netdev, linux-rtc, linux-serial

IOC3 chips in SGI system are conntected to a bridge ASIC, which has
a 1-wire prom attached with part number information. This changeset
uses this information to create PCI subsystem information, which
the MFD driver uses for further platform device setup.

Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
---
 arch/mips/include/asm/pci/bridge.h |   1 +
 arch/mips/include/asm/sn/ioc3.h    |   9 +++
 arch/mips/pci/pci-xtalk-bridge.c   | 135 ++++++++++++++++++++++++++++++++++++-
 arch/mips/sgi-ip27/ip27-xtalk.c    |  38 +++++++++--
 4 files changed, 175 insertions(+), 8 deletions(-)

diff --git a/arch/mips/include/asm/pci/bridge.h b/arch/mips/include/asm/pci/bridge.h
index a92cd30b48c9..3bc630ff9ad4 100644
--- a/arch/mips/include/asm/pci/bridge.h
+++ b/arch/mips/include/asm/pci/bridge.h
@@ -807,6 +807,7 @@ struct bridge_controller {
 	unsigned long		intr_addr;
 	struct irq_domain	*domain;
 	unsigned int		pci_int[8];
+	u32			ioc3_sid[8];
 	nasid_t			nasid;
 };
 
diff --git a/arch/mips/include/asm/sn/ioc3.h b/arch/mips/include/asm/sn/ioc3.h
index 25c8dccab51f..5022b0ab2074 100644
--- a/arch/mips/include/asm/sn/ioc3.h
+++ b/arch/mips/include/asm/sn/ioc3.h
@@ -661,4 +661,13 @@ typedef enum ioc3_subdevs_e {
 #define IOC3_INTA_SUBDEVS	IOC3_SDB_ETHER
 #define IOC3_INTB_SUBDEVS	(IOC3_SDB_GENERIC|IOC3_SDB_KBMS|IOC3_SDB_SERIAL|IOC3_SDB_ECPP|IOC3_SDB_RT)
 
+/* subsystem IDs supplied by card detection in pci-xtalk-bridge */
+#define	IOC3_SUBSYS_IP27_BASEIO6G	0xc300
+#define	IOC3_SUBSYS_IP27_MIO		0xc301
+#define	IOC3_SUBSYS_IP27_BASEIO		0xc302
+#define	IOC3_SUBSYS_IP29_SYSBOARD	0xc303
+#define	IOC3_SUBSYS_IP30_SYSBOARD	0xc304
+#define	IOC3_SUBSYS_MENET		0xc305
+#define	IOC3_SUBSYS_MENET4		0xc306
+
 #endif /* _IOC3_H */
diff --git a/arch/mips/pci/pci-xtalk-bridge.c b/arch/mips/pci/pci-xtalk-bridge.c
index 7b4d40354ee7..dcf6117a17c3 100644
--- a/arch/mips/pci/pci-xtalk-bridge.c
+++ b/arch/mips/pci/pci-xtalk-bridge.c
@@ -11,16 +11,22 @@
 #include <linux/dma-direct.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/xtalk-bridge.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/crc16.h>
 
 #include <asm/pci/bridge.h>
 #include <asm/paccess.h>
 #include <asm/sn/irq_alloc.h>
+#include <asm/sn/ioc3.h>
+
+#define CRC16_INIT	0
+#define CRC16_VALID	0xb001
 
 /*
  * Most of the IOC3 PCI config register aren't present
  * we emulate what is needed for a normal PCI enumeration
  */
-static int ioc3_cfg_rd(void *addr, int where, int size, u32 *value)
+static int ioc3_cfg_rd(void *addr, int where, int size, u32 *value, u32 sid)
 {
 	u32 cf, shift, mask;
 
@@ -30,6 +36,9 @@ static int ioc3_cfg_rd(void *addr, int where, int size, u32 *value)
 		if (get_dbe(cf, (u32 *)addr))
 			return PCIBIOS_DEVICE_NOT_FOUND;
 		break;
+	case 0x2c:
+		cf = sid;
+		break;
 	case 0x3c:
 		/* emulate sane interrupt pin value */
 		cf = 0x00000100;
@@ -111,7 +120,8 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn,
 	 */
 	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) {
 		addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
-		return ioc3_cfg_rd(addr, where, size, value);
+		return ioc3_cfg_rd(addr, where, size, value,
+				   bc->ioc3_sid[slot]);
 	}
 
 	addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
@@ -149,7 +159,8 @@ static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn,
 	 */
 	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) {
 		addr = &bridge->b_type1_cfg.c[(fn << 8) | (where & ~3)];
-		return ioc3_cfg_rd(addr, where, size, value);
+		return ioc3_cfg_rd(addr, where, size, value,
+				   bc->ioc3_sid[slot]);
 	}
 
 	addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))];
@@ -426,6 +437,117 @@ static int bridge_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 	return irq;
 }
 
+#define IOC3_SID(sid)	(PCI_VENDOR_ID_SGI << 16 | (sid))
+
+static void bridge_setup_ip27_baseio6g(struct bridge_controller *bc)
+{
+	bc->ioc3_sid[2] = IOC3_SID(IOC3_SUBSYS_IP27_BASEIO6G);
+	bc->ioc3_sid[6] = IOC3_SID(IOC3_SUBSYS_IP27_MIO);
+}
+
+static void bridge_setup_ip27_baseio(struct bridge_controller *bc)
+{
+	bc->ioc3_sid[2] = IOC3_SID(IOC3_SUBSYS_IP27_BASEIO);
+}
+
+static void bridge_setup_ip29_baseio(struct bridge_controller *bc)
+{
+	bc->ioc3_sid[2] = IOC3_SID(IOC3_SUBSYS_IP29_SYSBOARD);
+}
+
+static void bridge_setup_ip30_sysboard(struct bridge_controller *bc)
+{
+	bc->ioc3_sid[2] = IOC3_SID(IOC3_SUBSYS_IP30_SYSBOARD);
+}
+
+static void bridge_setup_menet(struct bridge_controller *bc)
+{
+	bc->ioc3_sid[0] = IOC3_SID(IOC3_SUBSYS_MENET);
+	bc->ioc3_sid[1] = IOC3_SID(IOC3_SUBSYS_MENET);
+	bc->ioc3_sid[2] = IOC3_SID(IOC3_SUBSYS_MENET);
+	bc->ioc3_sid[3] = IOC3_SID(IOC3_SUBSYS_MENET4);
+}
+
+#define BRIDGE_BOARD_SETUP(_partno, _setup)	\
+	{ .match = _partno, .setup = _setup }
+
+static const struct {
+	char *match;
+	void (*setup)(struct bridge_controller *bc);
+} bridge_ioc3_devid[] = {
+	BRIDGE_BOARD_SETUP("030-0734-", bridge_setup_ip27_baseio6g),
+	BRIDGE_BOARD_SETUP("030-0880-", bridge_setup_ip27_baseio6g),
+	BRIDGE_BOARD_SETUP("030-1023-", bridge_setup_ip27_baseio),
+	BRIDGE_BOARD_SETUP("030-1124-", bridge_setup_ip27_baseio),
+	BRIDGE_BOARD_SETUP("030-1025-", bridge_setup_ip29_baseio),
+	BRIDGE_BOARD_SETUP("030-1244-", bridge_setup_ip29_baseio),
+	BRIDGE_BOARD_SETUP("030-1389-", bridge_setup_ip29_baseio),
+	BRIDGE_BOARD_SETUP("030-0887-", bridge_setup_ip30_sysboard),
+	BRIDGE_BOARD_SETUP("030-1467-", bridge_setup_ip30_sysboard),
+	BRIDGE_BOARD_SETUP("030-0873-", bridge_setup_menet),
+};
+
+static void bridge_setup_board(struct bridge_controller *bc, char *partnum)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bridge_ioc3_devid); i++)
+		if (!strncmp(partnum, bridge_ioc3_devid[i].match,
+			     strlen(bridge_ioc3_devid[i].match))) {
+			bridge_ioc3_devid[i].setup(bc);
+		}
+}
+
+static int bridge_nvmem_match(struct device *dev, const void *data)
+{
+	const char *name = dev_name(dev);
+	const char *prefix = data;
+
+	if (strlen(name) < strlen(prefix))
+		return 0;
+
+	return memcmp(prefix, dev_name(dev), strlen(prefix)) == 0;
+}
+
+static int bridge_get_partnum(u64 baddr, char *partnum)
+{
+	struct nvmem_device *nvmem;
+	char prefix[24];
+	u8 prom[64];
+	int i, j;
+	int ret;
+
+	snprintf(prefix, sizeof(prefix), "bridge-%012llx-0b-", baddr);
+
+	nvmem = nvmem_device_find(prefix, bridge_nvmem_match);
+	if (IS_ERR(nvmem))
+		return PTR_ERR(nvmem);
+
+	ret = nvmem_device_read(nvmem, 0, 64, prom);
+	nvmem_device_put(nvmem);
+
+	if (ret != 64)
+		return ret;
+
+	if (crc16(CRC16_INIT, prom, 32) != CRC16_VALID ||
+	    crc16(CRC16_INIT, prom + 32, 32) != CRC16_VALID)
+		return -EINVAL;
+
+	/* Assemble part number */
+	j = 0;
+	for (i = 0; i < 19; i++)
+		if (prom[i + 11] != ' ')
+			partnum[j++] = prom[i + 11];
+
+	for (i = 0; i < 6; i++)
+		if (prom[i + 32] != ' ')
+			partnum[j++] = prom[i + 32];
+
+	partnum[j] = 0;
+
+	return 0;
+}
+
 static int bridge_probe(struct platform_device *pdev)
 {
 	struct xtalk_bridge_platform_data *bd = dev_get_platdata(&pdev->dev);
@@ -434,9 +556,14 @@ static int bridge_probe(struct platform_device *pdev)
 	struct pci_host_bridge *host;
 	struct irq_domain *domain, *parent;
 	struct fwnode_handle *fn;
+	char partnum[26];
 	int slot;
 	int err;
 
+	/* get part number from one wire prom */
+	if (bridge_get_partnum(virt_to_phys((void *)bd->bridge_addr), partnum))
+		return -EPROBE_DEFER; /* not available yet */
+
 	parent = irq_get_default_host();
 	if (!parent)
 		return -ENODEV;
@@ -517,6 +644,8 @@ static int bridge_probe(struct platform_device *pdev)
 	}
 	bridge_read(bc, b_wid_tflush);	  /* wait until Bridge PIO complete */
 
+	bridge_setup_board(bc, partnum);
+
 	host->dev.parent = dev;
 	host->sysdata = bc;
 	host->busnr = 0;
diff --git a/arch/mips/sgi-ip27/ip27-xtalk.c b/arch/mips/sgi-ip27/ip27-xtalk.c
index 4a1f0b0c29e2..9b7524362a11 100644
--- a/arch/mips/sgi-ip27/ip27-xtalk.c
+++ b/arch/mips/sgi-ip27/ip27-xtalk.c
@@ -10,6 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/smp.h>
 #include <linux/platform_device.h>
+#include <linux/platform_data/sgi-w1.h>
 #include <linux/platform_data/xtalk-bridge.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/types.h>
@@ -26,9 +27,35 @@
 static void bridge_platform_create(nasid_t nasid, int widget, int masterwid)
 {
 	struct xtalk_bridge_platform_data *bd;
+	struct sgi_w1_platform_data *wd;
 	struct platform_device *pdev;
+	struct resource w1_res;
 	unsigned long offset;
 
+	offset = NODE_OFFSET(nasid);
+
+	wd = kzalloc(sizeof(*wd), GFP_KERNEL);
+	if (!wd)
+		goto no_mem;
+
+	snprintf(wd->dev_id, sizeof(wd->dev_id), "bridge-%012lx",
+		 offset + (widget << SWIN_SIZE_BITS));
+
+	memset(&w1_res, 0, sizeof(w1_res));
+	w1_res.start = offset + (widget << SWIN_SIZE_BITS) +
+				offsetof(struct bridge_regs, b_nic);
+	w1_res.end = w1_res.start + 3;
+	w1_res.flags = IORESOURCE_MEM;
+
+	pdev = platform_device_alloc("sgi_w1", PLATFORM_DEVID_AUTO);
+	if (!pdev) {
+		kfree(wd);
+		goto no_mem;
+	}
+	platform_device_add_resources(pdev, &w1_res, 1);
+	platform_device_add_data(pdev, wd, sizeof(*wd));
+	platform_device_add(pdev);
+
 	bd = kzalloc(sizeof(*bd), GFP_KERNEL);
 	if (!bd)
 		goto no_mem;
@@ -38,7 +65,6 @@ static void bridge_platform_create(nasid_t nasid, int widget, int masterwid)
 		goto no_mem;
 	}
 
-	offset = NODE_OFFSET(nasid);
 
 	bd->bridge_addr = RAW_NODE_SWIN_BASE(nasid, widget);
 	bd->intr_addr	= BIT_ULL(47) + 0x01800000 + PI_INT_PEND_MOD;
@@ -46,14 +72,14 @@ static void bridge_platform_create(nasid_t nasid, int widget, int masterwid)
 	bd->masterwid	= masterwid;
 
 	bd->mem.name	= "Bridge PCI MEM";
-	bd->mem.start	= offset + (widget << SWIN_SIZE_BITS);
-	bd->mem.end	= bd->mem.start + SWIN_SIZE - 1;
+	bd->mem.start	= offset + (widget << SWIN_SIZE_BITS) + BRIDGE_DEVIO0;
+	bd->mem.end	= offset + (widget << SWIN_SIZE_BITS) + SWIN_SIZE - 1;
 	bd->mem.flags	= IORESOURCE_MEM;
 	bd->mem_offset	= offset;
 
 	bd->io.name	= "Bridge PCI IO";
-	bd->io.start	= offset + (widget << SWIN_SIZE_BITS);
-	bd->io.end	= bd->io.start + SWIN_SIZE - 1;
+	bd->io.start	= offset + (widget << SWIN_SIZE_BITS) + BRIDGE_DEVIO0;
+	bd->io.end	= offset + (widget << SWIN_SIZE_BITS) + SWIN_SIZE - 1;
 	bd->io.flags	= IORESOURCE_IO;
 	bd->io_offset	= offset;
 
@@ -81,6 +107,8 @@ static int probe_one_port(nasid_t nasid, int widget, int masterwid)
 		bridge_platform_create(nasid, widget, masterwid);
 		break;
 	default:
+		pr_info("xtalk:n%d/%d unknown widget (0x%x)\n",
+			nasid, widget, partnum);
 		break;
 	}
 
-- 
2.13.7


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v4 6/9] MIPS: SGI-IP27: remove ioc3 ethernet init
  2019-08-09 10:32 [PATCH v4 0/9] Use MFD framework for SGI IOC3 drivers Thomas Bogendoerfer
                   ` (4 preceding siblings ...)
  2019-08-09 10:32 ` [PATCH v4 5/9] MIPS: PCI: use information from 1-wire PROM for IOC3 detection Thomas Bogendoerfer
@ 2019-08-09 10:32 ` Thomas Bogendoerfer
  2019-08-09 10:32 ` [PATCH v4 8/9] MIPS: SGI-IP27: fix readb/writeb addressing Thomas Bogendoerfer
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 27+ messages in thread
From: Thomas Bogendoerfer @ 2019-08-09 10:32 UTC (permalink / raw)
  To: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Srinivas Kandagatla,
	Alessandro Zummo, Alexandre Belloni, Greg Kroah-Hartman,
	Jiri Slaby, Evgeniy Polyakov, linux-mips, linux-kernel,
	linux-input, netdev, linux-rtc, linux-serial

Removed not needed disabling of ethernet interrupts in IP27 platform code.

Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
---
 arch/mips/sgi-ip27/ip27-init.c | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c
index 066b33f50bcc..59d5375c9021 100644
--- a/arch/mips/sgi-ip27/ip27-init.c
+++ b/arch/mips/sgi-ip27/ip27-init.c
@@ -130,17 +130,6 @@ cnodeid_t get_compact_nodeid(void)
 	return NASID_TO_COMPACT_NODEID(get_nasid());
 }
 
-static inline void ioc3_eth_init(void)
-{
-	struct ioc3 *ioc3;
-	nasid_t nid;
-
-	nid = get_nasid();
-	ioc3 = (struct ioc3 *) KL_CONFIG_CH_CONS_INFO(nid)->memory_base;
-
-	ioc3->eier = 0;
-}
-
 extern void ip27_reboot_setup(void);
 
 void __init plat_mem_setup(void)
@@ -182,8 +171,6 @@ void __init plat_mem_setup(void)
 		panic("Kernel compiled for N mode.");
 #endif
 
-	ioc3_eth_init();
-
 	ioport_resource.start = 0;
 	ioport_resource.end = ~0UL;
 	set_io_port_base(IO_BASE);
-- 
2.13.7


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v4 8/9] MIPS: SGI-IP27: fix readb/writeb addressing
  2019-08-09 10:32 [PATCH v4 0/9] Use MFD framework for SGI IOC3 drivers Thomas Bogendoerfer
                   ` (5 preceding siblings ...)
  2019-08-09 10:32 ` [PATCH v4 6/9] MIPS: SGI-IP27: remove ioc3 ethernet init Thomas Bogendoerfer
@ 2019-08-09 10:32 ` Thomas Bogendoerfer
  2019-08-10 13:22   ` Andy Shevchenko
  2019-08-09 10:32 ` [PATCH v4 9/9] Input: add IOC3 serio driver Thomas Bogendoerfer
       [not found] ` <20190809103235.16338-8-tbogendoerfer@suse.de>
  8 siblings, 1 reply; 27+ messages in thread
From: Thomas Bogendoerfer @ 2019-08-09 10:32 UTC (permalink / raw)
  To: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Srinivas Kandagatla,
	Alessandro Zummo, Alexandre Belloni, Greg Kroah-Hartman,
	Jiri Slaby, Evgeniy Polyakov, linux-mips, linux-kernel,
	linux-input, netdev, linux-rtc, linux-serial

Our chosen byte swapping, which is what firmware already uses, is to
do readl/writel by normal lw/sw intructions (data invariance). This
also means we need to mangle addresses for u8 and u16 accesses. The
mangling for 16bit has been done aready, but 8bit one was missing.
Correcting this causes different addresses for accesses to the
SuperIO and local bus of the IOC3 chip. This is fixed by changing
byte order in ioc3 and m48rtc_rtc structs.

Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
---
 arch/mips/include/asm/mach-ip27/mangle-port.h |   4 +-
 arch/mips/include/asm/sn/ioc3.h               | 198 +++++++++++++-------------
 arch/mips/sgi-ip27/ip27-console.c             |   5 +-
 drivers/rtc/rtc-m48t35.c                      |  11 ++
 drivers/tty/serial/8250/8250_ioc3.c           |   4 +-
 5 files changed, 115 insertions(+), 107 deletions(-)

diff --git a/arch/mips/include/asm/mach-ip27/mangle-port.h b/arch/mips/include/asm/mach-ip27/mangle-port.h
index f6e4912ea062..27c56efa519f 100644
--- a/arch/mips/include/asm/mach-ip27/mangle-port.h
+++ b/arch/mips/include/asm/mach-ip27/mangle-port.h
@@ -8,7 +8,7 @@
 #ifndef __ASM_MACH_IP27_MANGLE_PORT_H
 #define __ASM_MACH_IP27_MANGLE_PORT_H
 
-#define __swizzle_addr_b(port)	(port)
+#define __swizzle_addr_b(port)	((port) ^ 3)
 #define __swizzle_addr_w(port)	((port) ^ 2)
 #define __swizzle_addr_l(port)	(port)
 #define __swizzle_addr_q(port)	(port)
@@ -20,6 +20,6 @@
 # define ioswabl(a, x)		(x)
 # define __mem_ioswabl(a, x)	cpu_to_le32(x)
 # define ioswabq(a, x)		(x)
-# define __mem_ioswabq(a, x)	cpu_to_le32(x)
+# define __mem_ioswabq(a, x)	cpu_to_le64(x)
 
 #endif /* __ASM_MACH_IP27_MANGLE_PORT_H */
diff --git a/arch/mips/include/asm/sn/ioc3.h b/arch/mips/include/asm/sn/ioc3.h
index 89938fdce8ef..ac6d7e6e31e0 100644
--- a/arch/mips/include/asm/sn/ioc3.h
+++ b/arch/mips/include/asm/sn/ioc3.h
@@ -10,35 +10,35 @@
 
 /* serial port register map */
 struct ioc3_serialregs {
-	uint32_t	sscr;
-	uint32_t	stpir;
-	uint32_t	stcir;
-	uint32_t	srpir;
-	uint32_t	srcir;
-	uint32_t	srtr;
-	uint32_t	shadow;
+	u32	sscr;
+	u32	stpir;
+	u32	stcir;
+	u32	srpir;
+	u32	srcir;
+	u32	srtr;
+	u32	shadow;
 };
 
 /* SUPERIO uart register map */
 struct ioc3_uartregs {
+	u8	iu_lcr;
 	union {
-		char	rbr;	/* read only, DLAB == 0 */
-		char	thr;	/* write only, DLAB == 0 */
-		char	dll;	/* DLAB == 1 */
-	} u1;
+		u8	iir;	/* read only */
+		u8	fcr;	/* write only */
+	};
 	union {
-		char	ier;	/* DLAB == 0 */
-		char	dlm;	/* DLAB == 1 */
-	} u2;
+		u8	ier;	/* DLAB == 0 */
+		u8	dlm;	/* DLAB == 1 */
+	};
 	union {
-		char	iir;	/* read only */
-		char	fcr;	/* write only */
-	} u3;
-	char	iu_lcr;
-	char	iu_mcr;
-	char	iu_lsr;
-	char	iu_msr;
-	char	iu_scr;
+		u8	rbr;	/* read only, DLAB == 0 */
+		u8	thr;	/* write only, DLAB == 0 */
+		u8	dll;	/* DLAB == 1 */
+	} u1;
+	u8	iu_scr;
+	u8	iu_msr;
+	u8	iu_lsr;
+	u8	iu_mcr;
 };
 
 #define iu_rbr u1.rbr
@@ -50,122 +50,122 @@ struct ioc3_uartregs {
 #define iu_fcr u3.fcr
 
 struct ioc3_sioregs {
-	char	fill[0x141];	/* starts at 0x141 */
+	u8	fill[0x141];	/* starts at 0x141 */
 
-	char	uartc;
-	char	kbdcg;
+	u8	kbdcg;
+	u8	uartc;
 
-	char	fill0[0x150 - 0x142 - 1];
+	u8	fill0[0x151 - 0x142 - 1];
 
-	char	pp_data;
-	char	pp_dsr;
-	char	pp_dcr;
+	u8	pp_dcr;
+	u8	pp_dsr;
+	u8	pp_data;
 
-	char	fill1[0x158 - 0x152 - 1];
+	u8	fill1[0x159 - 0x153 - 1];
 
-	char	pp_fifa;
-	char	pp_cfgb;
-	char	pp_ecr;
+	u8	pp_ecr;
+	u8	pp_cfgb;
+	u8	pp_fifa;
 
-	char	fill2[0x168 - 0x15a - 1];
+	u8	fill2[0x16a - 0x15b - 1];
 
-	char	rtcad;
-	char	rtcdat;
+	u8	rtcdat;
+	u8	rtcad;
 
-	char	fill3[0x170 - 0x169 - 1];
+	u8	fill3[0x170 - 0x16b - 1];
 
 	struct ioc3_uartregs	uartb;	/* 0x20170  */
 	struct ioc3_uartregs	uarta;	/* 0x20178  */
 };
 
 struct ioc3_ethregs {
-	uint32_t	emcr;		/* 0x000f0  */
-	uint32_t	eisr;		/* 0x000f4  */
-	uint32_t	eier;		/* 0x000f8  */
-	uint32_t	ercsr;		/* 0x000fc  */
-	uint32_t	erbr_h;		/* 0x00100  */
-	uint32_t	erbr_l;		/* 0x00104  */
-	uint32_t	erbar;		/* 0x00108  */
-	uint32_t	ercir;		/* 0x0010c  */
-	uint32_t	erpir;		/* 0x00110  */
-	uint32_t	ertr;		/* 0x00114  */
-	uint32_t	etcsr;		/* 0x00118  */
-	uint32_t	ersr;		/* 0x0011c  */
-	uint32_t	etcdc;		/* 0x00120  */
-	uint32_t	ebir;		/* 0x00124  */
-	uint32_t	etbr_h;		/* 0x00128  */
-	uint32_t	etbr_l;		/* 0x0012c  */
-	uint32_t	etcir;		/* 0x00130  */
-	uint32_t	etpir;		/* 0x00134  */
-	uint32_t	emar_h;		/* 0x00138  */
-	uint32_t	emar_l;		/* 0x0013c  */
-	uint32_t	ehar_h;		/* 0x00140  */
-	uint32_t	ehar_l;		/* 0x00144  */
-	uint32_t	micr;		/* 0x00148  */
-	uint32_t	midr_r;		/* 0x0014c  */
-	uint32_t	midr_w;		/* 0x00150  */
+	u32	emcr;		/* 0x000f0  */
+	u32	eisr;		/* 0x000f4  */
+	u32	eier;		/* 0x000f8  */
+	u32	ercsr;		/* 0x000fc  */
+	u32	erbr_h;		/* 0x00100  */
+	u32	erbr_l;		/* 0x00104  */
+	u32	erbar;		/* 0x00108  */
+	u32	ercir;		/* 0x0010c  */
+	u32	erpir;		/* 0x00110  */
+	u32	ertr;		/* 0x00114  */
+	u32	etcsr;		/* 0x00118  */
+	u32	ersr;		/* 0x0011c  */
+	u32	etcdc;		/* 0x00120  */
+	u32	ebir;		/* 0x00124  */
+	u32	etbr_h;		/* 0x00128  */
+	u32	etbr_l;		/* 0x0012c  */
+	u32	etcir;		/* 0x00130  */
+	u32	etpir;		/* 0x00134  */
+	u32	emar_h;		/* 0x00138  */
+	u32	emar_l;		/* 0x0013c  */
+	u32	ehar_h;		/* 0x00140  */
+	u32	ehar_l;		/* 0x00144  */
+	u32	micr;		/* 0x00148  */
+	u32	midr_r;		/* 0x0014c  */
+	u32	midr_w;		/* 0x00150  */
 };
 
 struct ioc3_serioregs {
-	uint32_t	km_csr;		/* 0x0009c  */
-	uint32_t	k_rd;		/* 0x000a0  */
-	uint32_t	m_rd;		/* 0x000a4  */
-	uint32_t	k_wd;		/* 0x000a8  */
-	uint32_t	m_wd;		/* 0x000ac  */
+	u32	km_csr;		/* 0x0009c  */
+	u32	k_rd;		/* 0x000a0  */
+	u32	m_rd;		/* 0x000a4  */
+	u32	k_wd;		/* 0x000a8  */
+	u32	m_wd;		/* 0x000ac  */
 };
 
 /* Register layout of IOC3 in configuration space.  */
 struct ioc3 {
 	/* PCI Config Space registers  */
-	uint32_t	pci_id;		/* 0x00000  */
-	uint32_t	pci_scr;	/* 0x00004  */
-	uint32_t	pci_rev;	/* 0x00008  */
-	uint32_t	pci_lat;	/* 0x0000c  */
-	uint32_t	pci_addr;	/* 0x00010  */
-	uint32_t	pci_err_addr_l;	/* 0x00014  */
-	uint32_t	pci_err_addr_h;	/* 0x00018  */
-
-	uint32_t	sio_ir;		/* 0x0001c  */
-	uint32_t	sio_ies;	/* 0x00020  */
-	uint32_t	sio_iec;	/* 0x00024  */
-	uint32_t	sio_cr;		/* 0x00028  */
-	uint32_t	int_out;	/* 0x0002c  */
-	uint32_t	mcr;		/* 0x00030  */
+	u32	pci_id;		/* 0x00000  */
+	u32	pci_scr;	/* 0x00004  */
+	u32	pci_rev;	/* 0x00008  */
+	u32	pci_lat;	/* 0x0000c  */
+	u32	pci_addr;	/* 0x00010  */
+	u32	pci_err_addr_l;	/* 0x00014  */
+	u32	pci_err_addr_h;	/* 0x00018  */
+
+	u32	sio_ir;		/* 0x0001c  */
+	u32	sio_ies;	/* 0x00020  */
+	u32	sio_iec;	/* 0x00024  */
+	u32	sio_cr;		/* 0x00028  */
+	u32	int_out;	/* 0x0002c  */
+	u32	mcr;		/* 0x00030  */
 
 	/* General Purpose I/O registers  */
-	uint32_t	gpcr_s;		/* 0x00034  */
-	uint32_t	gpcr_c;		/* 0x00038  */
-	uint32_t	gpdr;		/* 0x0003c  */
-	uint32_t	gppr[16];	/* 0x00040  */
+	u32	gpcr_s;		/* 0x00034  */
+	u32	gpcr_c;		/* 0x00038  */
+	u32	gpdr;		/* 0x0003c  */
+	u32	gppr[16];	/* 0x00040  */
 
 	/* Parallel Port Registers  */
-	uint32_t	ppbr_h_a;	/* 0x00080  */
-	uint32_t	ppbr_l_a;	/* 0x00084  */
-	uint32_t	ppcr_a;		/* 0x00088  */
-	uint32_t	ppcr;		/* 0x0008c  */
-	uint32_t	ppbr_h_b;	/* 0x00090  */
-	uint32_t	ppbr_l_b;	/* 0x00094  */
-	uint32_t	ppcr_b;		/* 0x00098  */
+	u32	ppbr_h_a;	/* 0x00080  */
+	u32	ppbr_l_a;	/* 0x00084  */
+	u32	ppcr_a;		/* 0x00088  */
+	u32	ppcr;		/* 0x0008c  */
+	u32	ppbr_h_b;	/* 0x00090  */
+	u32	ppbr_l_b;	/* 0x00094  */
+	u32	ppcr_b;		/* 0x00098  */
 
 	/* Keyboard and Mouse Registers	 */
 	struct ioc3_serioregs	serio;
 
 	/* Serial Port Registers  */
-	uint32_t	sbbr_h;		/* 0x000b0  */
-	uint32_t	sbbr_l;		/* 0x000b4  */
+	u32	sbbr_h;		/* 0x000b0  */
+	u32	sbbr_l;		/* 0x000b4  */
 	struct ioc3_serialregs	port_a;
 	struct ioc3_serialregs	port_b;
 
 	/* Ethernet Registers */
 	struct ioc3_ethregs	eth;
-	uint32_t	pad1[(0x20000 - 0x00154) / 4];
+	u32	pad1[(0x20000 - 0x00154) / 4];
 
 	/* SuperIO Registers  XXX */
 	struct ioc3_sioregs	sregs;	/* 0x20000 */
-	uint32_t	pad2[(0x40000 - 0x20180) / 4];
+	u32	pad2[(0x40000 - 0x20180) / 4];
 
 	/* SSRAM Diagnostic Access */
-	uint32_t	ssram[(0x80000 - 0x40000) / 4];
+	u32	ssram[(0x80000 - 0x40000) / 4];
 
 	/* Bytebus device offsets
 	   0x80000 -   Access to the generic devices selected with   DEV0
@@ -598,10 +598,6 @@ struct ioc3_etxd {
 
 #define MIDR_DATA_MASK		0x0000ffff
 
-#if defined(CONFIG_SGI_IP27) || defined(CONFIG_SGI_IP30)
-extern int bridge_alloc_irq(struct pci_dev *dev);
-#endif
-
 /* subsystem IDs supplied by card detection in pci-xtalk-bridge */
 #define	IOC3_SUBSYS_IP27_BASEIO6G	0xc300
 #define	IOC3_SUBSYS_IP27_MIO		0xc301
diff --git a/arch/mips/sgi-ip27/ip27-console.c b/arch/mips/sgi-ip27/ip27-console.c
index 6bdb48d41276..5886bee89d06 100644
--- a/arch/mips/sgi-ip27/ip27-console.c
+++ b/arch/mips/sgi-ip27/ip27-console.c
@@ -35,6 +35,7 @@ void prom_putchar(char c)
 {
 	struct ioc3_uartregs *uart = console_uart();
 
-	while ((uart->iu_lsr & 0x20) == 0);
-	uart->iu_thr = c;
+	while ((readb(&uart->iu_lsr) & 0x20) == 0)
+		;
+	writeb(c, &uart->iu_thr);
 }
diff --git a/drivers/rtc/rtc-m48t35.c b/drivers/rtc/rtc-m48t35.c
index d3a75d447fce..e8194f1f01a8 100644
--- a/drivers/rtc/rtc-m48t35.c
+++ b/drivers/rtc/rtc-m48t35.c
@@ -20,6 +20,16 @@
 
 struct m48t35_rtc {
 	u8	pad[0x7ff8];    /* starts at 0x7ff8 */
+#ifdef CONFIG_SGI_IP27
+	u8	hour;
+	u8	min;
+	u8	sec;
+	u8	control;
+	u8	year;
+	u8	month;
+	u8	date;
+	u8	day;
+#else
 	u8	control;
 	u8	sec;
 	u8	min;
@@ -28,6 +38,7 @@ struct m48t35_rtc {
 	u8	date;
 	u8	month;
 	u8	year;
+#endif
 };
 
 #define M48T35_RTC_SET		0x80
diff --git a/drivers/tty/serial/8250/8250_ioc3.c b/drivers/tty/serial/8250/8250_ioc3.c
index 2be6ed2967e0..4c405f1b9c67 100644
--- a/drivers/tty/serial/8250/8250_ioc3.c
+++ b/drivers/tty/serial/8250/8250_ioc3.c
@@ -23,12 +23,12 @@ struct ioc3_8250_data {
 
 static unsigned int ioc3_serial_in(struct uart_port *p, int offset)
 {
-	return readb(p->membase + offset);
+	return readb(p->membase + (offset ^ 3));
 }
 
 static void ioc3_serial_out(struct uart_port *p, int offset, int value)
 {
-	writeb(value, p->membase + offset);
+	writeb(value, p->membase + (offset ^ 3));
 }
 
 static int serial8250_ioc3_probe(struct platform_device *pdev)
-- 
2.13.7


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v4 9/9] Input: add IOC3 serio driver
  2019-08-09 10:32 [PATCH v4 0/9] Use MFD framework for SGI IOC3 drivers Thomas Bogendoerfer
                   ` (6 preceding siblings ...)
  2019-08-09 10:32 ` [PATCH v4 8/9] MIPS: SGI-IP27: fix readb/writeb addressing Thomas Bogendoerfer
@ 2019-08-09 10:32 ` Thomas Bogendoerfer
  2019-08-09 22:04   ` Dmitry Torokhov
  2019-08-14 13:20   ` Jonas Gorski
       [not found] ` <20190809103235.16338-8-tbogendoerfer@suse.de>
  8 siblings, 2 replies; 27+ messages in thread
From: Thomas Bogendoerfer @ 2019-08-09 10:32 UTC (permalink / raw)
  To: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Srinivas Kandagatla,
	Alessandro Zummo, Alexandre Belloni, Greg Kroah-Hartman,
	Jiri Slaby, Evgeniy Polyakov, linux-mips, linux-kernel,
	linux-input, netdev, linux-rtc, linux-serial

This patch adds a platform driver for supporting keyboard and mouse
interface of SGI IOC3 chips.

Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
---
 drivers/input/serio/Kconfig   |  10 +++
 drivers/input/serio/Makefile  |   1 +
 drivers/input/serio/ioc3kbd.c | 163 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 174 insertions(+)
 create mode 100644 drivers/input/serio/ioc3kbd.c

diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index f3e18f8ef9ca..373a1646019e 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -165,6 +165,16 @@ config SERIO_MACEPS2
 	  To compile this driver as a module, choose M here: the
 	  module will be called maceps2.
 
+config SERIO_SGI_IOC3
+	tristate "SGI IOC3 PS/2 controller"
+	depends on SGI_MFD_IOC3
+	help
+	  Say Y here if you have an SGI Onyx2, SGI Octane or IOC3 PCI card
+	  and you want to attach and use a keyboard, mouse, or both.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ioc3kbd.
+
 config SERIO_LIBPS2
 	tristate "PS/2 driver library"
 	depends on SERIO_I8042 || SERIO_I8042=n
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
index 67950a5ccb3f..6d97bad7b844 100644
--- a/drivers/input/serio/Makefile
+++ b/drivers/input/serio/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_HIL_MLC)		+= hp_sdc_mlc.o hil_mlc.o
 obj-$(CONFIG_SERIO_PCIPS2)	+= pcips2.o
 obj-$(CONFIG_SERIO_PS2MULT)	+= ps2mult.o
 obj-$(CONFIG_SERIO_MACEPS2)	+= maceps2.o
+obj-$(CONFIG_SERIO_SGI_IOC3)	+= ioc3kbd.o
 obj-$(CONFIG_SERIO_LIBPS2)	+= libps2.o
 obj-$(CONFIG_SERIO_RAW)		+= serio_raw.o
 obj-$(CONFIG_SERIO_AMS_DELTA)	+= ams_delta_serio.o
diff --git a/drivers/input/serio/ioc3kbd.c b/drivers/input/serio/ioc3kbd.c
new file mode 100644
index 000000000000..6840e3c23fed
--- /dev/null
+++ b/drivers/input/serio/ioc3kbd.c
@@ -0,0 +1,163 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SGI IOC3 PS/2 controller driver for linux
+ *
+ * Copyright (C) 2019 Thomas Bogendoerfer <tbogendoerfer@suse.de>
+ *
+ * Based on code Copyright (C) 2005 Stanislaw Skowronek <skylark@unaligned.org>
+ *               Copyright (C) 2009 Johannes Dickgreber <tanzy@gmx.de>
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/serio.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/sn/ioc3.h>
+
+struct ioc3kbd_data {
+	struct ioc3_serioregs __iomem *regs;
+	struct serio *kbd, *aux;
+	int irq;
+};
+
+static int ioc3kbd_write(struct serio *dev, u8 val)
+{
+	struct ioc3kbd_data *d = dev->port_data;
+	unsigned long timeout = 0;
+	u32 mask;
+
+	mask = (dev == d->aux) ? KM_CSR_M_WRT_PEND : KM_CSR_K_WRT_PEND;
+	while ((readl(&d->regs->km_csr) & mask) && (timeout < 1000)) {
+		udelay(100);
+		timeout++;
+	}
+
+	if (timeout >= 1000)
+		return -ETIMEDOUT;
+
+	writel(val, dev == d->aux ? &d->regs->m_wd : &d->regs->k_wd);
+
+	return 0;
+}
+
+static irqreturn_t ioc3kbd_intr(int itq, void *dev_id)
+{
+	struct ioc3kbd_data *d = dev_id;
+	u32 data_k, data_m;
+
+	data_k = readl(&d->regs->k_rd);
+	data_m = readl(&d->regs->m_rd);
+
+	if (data_k & KM_RD_VALID_0)
+		serio_interrupt(d->kbd, (data_k >> KM_RD_DATA_0_SHIFT) & 0xff,
+				0);
+	if (data_k & KM_RD_VALID_1)
+		serio_interrupt(d->kbd, (data_k >> KM_RD_DATA_1_SHIFT) & 0xff,
+				0);
+	if (data_k & KM_RD_VALID_2)
+		serio_interrupt(d->kbd, (data_k >> KM_RD_DATA_2_SHIFT) & 0xff,
+				0);
+	if (data_m & KM_RD_VALID_0)
+		serio_interrupt(d->aux, (data_m >> KM_RD_DATA_0_SHIFT) & 0xff,
+				0);
+	if (data_m & KM_RD_VALID_1)
+		serio_interrupt(d->aux, (data_m >> KM_RD_DATA_1_SHIFT) & 0xff,
+				0);
+	if (data_m & KM_RD_VALID_2)
+		serio_interrupt(d->aux, (data_m >> KM_RD_DATA_2_SHIFT) & 0xff,
+				0);
+
+	return 0;
+}
+
+static int ioc3kbd_probe(struct platform_device *pdev)
+{
+	struct ioc3_serioregs __iomem *regs;
+	struct device *dev = &pdev->dev;
+	struct ioc3kbd_data *d;
+	struct serio *sk, *sa;
+	int irq, ret;
+
+	regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return -ENXIO;
+
+	d = devm_kzalloc(&pdev->dev, sizeof(*d), GFP_KERNEL);
+	if (!d)
+		return -ENOMEM;
+
+	sk = kzalloc(sizeof(*sk), GFP_KERNEL);
+	if (!sk)
+		return -ENOMEM;
+
+	sa = kzalloc(sizeof(*sa), GFP_KERNEL);
+	if (!sa) {
+		kfree(sk);
+		return -ENOMEM;
+	}
+
+	sk->id.type = SERIO_8042;
+	sk->write = ioc3kbd_write;
+	snprintf(sk->name, sizeof(sk->name), "IOC3 keyboard %d", pdev->id);
+	snprintf(sk->phys, sizeof(sk->phys), "ioc3/serio%dkbd", pdev->id);
+	sk->port_data = d;
+	sk->dev.parent = &pdev->dev;
+
+	sa->id.type = SERIO_8042;
+	sa->write = ioc3kbd_write;
+	snprintf(sa->name, sizeof(sa->name), "IOC3 auxiliary %d", pdev->id);
+	snprintf(sa->phys, sizeof(sa->phys), "ioc3/serio%daux", pdev->id);
+	sa->port_data = d;
+	sa->dev.parent = dev;
+
+	d->regs = regs;
+	d->kbd = sk;
+	d->aux = sa;
+	d->irq = irq;
+
+	platform_set_drvdata(pdev, d);
+	serio_register_port(d->kbd);
+	serio_register_port(d->aux);
+
+	ret = devm_request_irq(&pdev->dev, irq, ioc3kbd_intr, IRQF_SHARED,
+			       "ioc3-kbd", d);
+	if (ret) {
+		dev_err(&pdev->dev, "could not request IRQ %d\n", irq);
+		serio_unregister_port(d->kbd);
+		serio_unregister_port(d->aux);
+		kfree(sk);
+		kfree(sa);
+		return ret;
+	}
+	return 0;
+}
+
+static int ioc3kbd_remove(struct platform_device *pdev)
+{
+	struct ioc3kbd_data *d = platform_get_drvdata(pdev);
+
+	devm_free_irq(&pdev->dev, d->irq, d);
+	serio_unregister_port(d->kbd);
+	serio_unregister_port(d->aux);
+	return 0;
+}
+
+static struct platform_driver ioc3kbd_driver = {
+	.probe          = ioc3kbd_probe,
+	.remove         = ioc3kbd_remove,
+	.driver = {
+		.name = "ioc3-kbd",
+	},
+};
+module_platform_driver(ioc3kbd_driver);
+
+MODULE_AUTHOR("Thomas Bogendoerfer <tbogendoerfer@suse.de>");
+MODULE_DESCRIPTION("SGI IOC3 serio driver");
+MODULE_LICENSE("GPL");
-- 
2.13.7


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 7/9] mfd: ioc3: Add driver for SGI IOC3 chip
       [not found] ` <20190809103235.16338-8-tbogendoerfer@suse.de>
@ 2019-08-09 21:22   ` Jakub Kicinski
  2019-08-11  7:32     ` Thomas Bogendoerfer
  0 siblings, 1 reply; 27+ messages in thread
From: Jakub Kicinski @ 2019-08-09 21:22 UTC (permalink / raw)
  To: Thomas Bogendoerfer
  Cc: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Srinivas Kandagatla,
	Alessandro Zummo, Alexandre Belloni, Greg Kroah-Hartman,
	Jiri Slaby, Evgeniy Polyakov, linux-mips, linux-kernel,
	linux-input, netdev, linux-rtc, linux-serial

On Fri,  9 Aug 2019 12:32:29 +0200, Thomas Bogendoerfer wrote:
> SGI IOC3 chip has integrated ethernet, keyboard and mouse interface.
> It also supports connecting a SuperIO chip for serial and parallel
> interfaces. IOC3 is used inside various SGI systemboards and add-on
> cards with different equipped external interfaces.
> 
> Support for ethernet and serial interfaces were implemented inside
> the network driver. This patchset moves out the not network related
> parts to a new MFD driver, which takes care of card detection,
> setup of platform devices and interrupt distribution for the subdevices.
> 
> Serial portion: Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> 
> Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>

There are a lot of changes in the ethernet part which are not easy to
explain by the introduction of the other MFD parts.. Could you possibly
break this change up into smaller chunks?

Also please don't use stdint types in the kernel, please try checkpatch
to catch coding style issues.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 9/9] Input: add IOC3 serio driver
  2019-08-09 10:32 ` [PATCH v4 9/9] Input: add IOC3 serio driver Thomas Bogendoerfer
@ 2019-08-09 22:04   ` Dmitry Torokhov
  2019-08-14 13:20   ` Jonas Gorski
  1 sibling, 0 replies; 27+ messages in thread
From: Dmitry Torokhov @ 2019-08-09 22:04 UTC (permalink / raw)
  To: Thomas Bogendoerfer
  Cc: Ralf Baechle, Paul Burton, James Hogan, Lee Jones,
	David S. Miller, Srinivas Kandagatla, Alessandro Zummo,
	Alexandre Belloni, Greg Kroah-Hartman, Jiri Slaby,
	Evgeniy Polyakov, linux-mips, linux-kernel, linux-input, netdev,
	linux-rtc, linux-serial

On Fri, Aug 09, 2019 at 12:32:31PM +0200, Thomas Bogendoerfer wrote:
> This patch adds a platform driver for supporting keyboard and mouse
> interface of SGI IOC3 chips.
> 
> Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
> ---
>  drivers/input/serio/Kconfig   |  10 +++
>  drivers/input/serio/Makefile  |   1 +
>  drivers/input/serio/ioc3kbd.c | 163 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 174 insertions(+)
>  create mode 100644 drivers/input/serio/ioc3kbd.c
> 
> diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
> index f3e18f8ef9ca..373a1646019e 100644
> --- a/drivers/input/serio/Kconfig
> +++ b/drivers/input/serio/Kconfig
> @@ -165,6 +165,16 @@ config SERIO_MACEPS2
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called maceps2.
>  
> +config SERIO_SGI_IOC3
> +	tristate "SGI IOC3 PS/2 controller"
> +	depends on SGI_MFD_IOC3
> +	help
> +	  Say Y here if you have an SGI Onyx2, SGI Octane or IOC3 PCI card
> +	  and you want to attach and use a keyboard, mouse, or both.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called ioc3kbd.
> +
>  config SERIO_LIBPS2
>  	tristate "PS/2 driver library"
>  	depends on SERIO_I8042 || SERIO_I8042=n
> diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
> index 67950a5ccb3f..6d97bad7b844 100644
> --- a/drivers/input/serio/Makefile
> +++ b/drivers/input/serio/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_HIL_MLC)		+= hp_sdc_mlc.o hil_mlc.o
>  obj-$(CONFIG_SERIO_PCIPS2)	+= pcips2.o
>  obj-$(CONFIG_SERIO_PS2MULT)	+= ps2mult.o
>  obj-$(CONFIG_SERIO_MACEPS2)	+= maceps2.o
> +obj-$(CONFIG_SERIO_SGI_IOC3)	+= ioc3kbd.o
>  obj-$(CONFIG_SERIO_LIBPS2)	+= libps2.o
>  obj-$(CONFIG_SERIO_RAW)		+= serio_raw.o
>  obj-$(CONFIG_SERIO_AMS_DELTA)	+= ams_delta_serio.o
> diff --git a/drivers/input/serio/ioc3kbd.c b/drivers/input/serio/ioc3kbd.c
> new file mode 100644
> index 000000000000..6840e3c23fed
> --- /dev/null
> +++ b/drivers/input/serio/ioc3kbd.c
> @@ -0,0 +1,163 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * SGI IOC3 PS/2 controller driver for linux
> + *
> + * Copyright (C) 2019 Thomas Bogendoerfer <tbogendoerfer@suse.de>
> + *
> + * Based on code Copyright (C) 2005 Stanislaw Skowronek <skylark@unaligned.org>
> + *               Copyright (C) 2009 Johannes Dickgreber <tanzy@gmx.de>
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/serio.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +#include <asm/sn/ioc3.h>
> +
> +struct ioc3kbd_data {
> +	struct ioc3_serioregs __iomem *regs;
> +	struct serio *kbd, *aux;
> +	int irq;
> +};
> +
> +static int ioc3kbd_write(struct serio *dev, u8 val)
> +{
> +	struct ioc3kbd_data *d = dev->port_data;
> +	unsigned long timeout = 0;
> +	u32 mask;
> +
> +	mask = (dev == d->aux) ? KM_CSR_M_WRT_PEND : KM_CSR_K_WRT_PEND;
> +	while ((readl(&d->regs->km_csr) & mask) && (timeout < 1000)) {
> +		udelay(100);
> +		timeout++;
> +	}
> +
> +	if (timeout >= 1000)
> +		return -ETIMEDOUT;
> +
> +	writel(val, dev == d->aux ? &d->regs->m_wd : &d->regs->k_wd);
> +
> +	return 0;
> +}
> +
> +static irqreturn_t ioc3kbd_intr(int itq, void *dev_id)
> +{
> +	struct ioc3kbd_data *d = dev_id;
> +	u32 data_k, data_m;
> +
> +	data_k = readl(&d->regs->k_rd);
> +	data_m = readl(&d->regs->m_rd);
> +
> +	if (data_k & KM_RD_VALID_0)
> +		serio_interrupt(d->kbd, (data_k >> KM_RD_DATA_0_SHIFT) & 0xff,
> +				0);
> +	if (data_k & KM_RD_VALID_1)
> +		serio_interrupt(d->kbd, (data_k >> KM_RD_DATA_1_SHIFT) & 0xff,
> +				0);
> +	if (data_k & KM_RD_VALID_2)
> +		serio_interrupt(d->kbd, (data_k >> KM_RD_DATA_2_SHIFT) & 0xff,
> +				0);
> +	if (data_m & KM_RD_VALID_0)
> +		serio_interrupt(d->aux, (data_m >> KM_RD_DATA_0_SHIFT) & 0xff,
> +				0);
> +	if (data_m & KM_RD_VALID_1)
> +		serio_interrupt(d->aux, (data_m >> KM_RD_DATA_1_SHIFT) & 0xff,
> +				0);
> +	if (data_m & KM_RD_VALID_2)
> +		serio_interrupt(d->aux, (data_m >> KM_RD_DATA_2_SHIFT) & 0xff,
> +				0);
> +
> +	return 0;

IRQ_NONE? Or IRQ_HANDLED?

> +}
> +
> +static int ioc3kbd_probe(struct platform_device *pdev)
> +{
> +	struct ioc3_serioregs __iomem *regs;
> +	struct device *dev = &pdev->dev;
> +	struct ioc3kbd_data *d;
> +	struct serio *sk, *sa;
> +	int irq, ret;
> +
> +	regs = devm_platform_ioremap_resource(pdev, 0);
> +	if (IS_ERR(regs))
> +		return PTR_ERR(regs);
> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq < 0)
> +		return -ENXIO;
> +
> +	d = devm_kzalloc(&pdev->dev, sizeof(*d), GFP_KERNEL);
> +	if (!d)
> +		return -ENOMEM;
> +
> +	sk = kzalloc(sizeof(*sk), GFP_KERNEL);
> +	if (!sk)
> +		return -ENOMEM;
> +
> +	sa = kzalloc(sizeof(*sa), GFP_KERNEL);
> +	if (!sa) {
> +		kfree(sk);
> +		return -ENOMEM;
> +	}
> +
> +	sk->id.type = SERIO_8042;
> +	sk->write = ioc3kbd_write;
> +	snprintf(sk->name, sizeof(sk->name), "IOC3 keyboard %d", pdev->id);
> +	snprintf(sk->phys, sizeof(sk->phys), "ioc3/serio%dkbd", pdev->id);
> +	sk->port_data = d;
> +	sk->dev.parent = &pdev->dev;
> +
> +	sa->id.type = SERIO_8042;
> +	sa->write = ioc3kbd_write;
> +	snprintf(sa->name, sizeof(sa->name), "IOC3 auxiliary %d", pdev->id);
> +	snprintf(sa->phys, sizeof(sa->phys), "ioc3/serio%daux", pdev->id);
> +	sa->port_data = d;
> +	sa->dev.parent = dev;
> +
> +	d->regs = regs;
> +	d->kbd = sk;
> +	d->aux = sa;
> +	d->irq = irq;
> +
> +	platform_set_drvdata(pdev, d);
> +	serio_register_port(d->kbd);
> +	serio_register_port(d->aux);
> +
> +	ret = devm_request_irq(&pdev->dev, irq, ioc3kbd_intr, IRQF_SHARED,
> +			       "ioc3-kbd", d);

Just request_irq(); there is not really any benefit from devm since you
free it manually.

What else is sharing this interrupt?

> +	if (ret) {
> +		dev_err(&pdev->dev, "could not request IRQ %d\n", irq);
> +		serio_unregister_port(d->kbd);
> +		serio_unregister_port(d->aux);
> +		kfree(sk);
> +		kfree(sa);
> +		return ret;
> +	}
> +	return 0;
> +}
> +
> +static int ioc3kbd_remove(struct platform_device *pdev)
> +{
> +	struct ioc3kbd_data *d = platform_get_drvdata(pdev);
> +
> +	devm_free_irq(&pdev->dev, d->irq, d);
> +	serio_unregister_port(d->kbd);
> +	serio_unregister_port(d->aux);
> +	return 0;
> +}
> +
> +static struct platform_driver ioc3kbd_driver = {
> +	.probe          = ioc3kbd_probe,
> +	.remove         = ioc3kbd_remove,
> +	.driver = {
> +		.name = "ioc3-kbd",
> +	},
> +};
> +module_platform_driver(ioc3kbd_driver);
> +
> +MODULE_AUTHOR("Thomas Bogendoerfer <tbogendoerfer@suse.de>");
> +MODULE_DESCRIPTION("SGI IOC3 serio driver");
> +MODULE_LICENSE("GPL");
> -- 
> 2.13.7
> 

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 8/9] MIPS: SGI-IP27: fix readb/writeb addressing
  2019-08-09 10:32 ` [PATCH v4 8/9] MIPS: SGI-IP27: fix readb/writeb addressing Thomas Bogendoerfer
@ 2019-08-10 13:22   ` Andy Shevchenko
  2019-08-11  7:29     ` Greg Kroah-Hartman
  0 siblings, 1 reply; 27+ messages in thread
From: Andy Shevchenko @ 2019-08-10 13:22 UTC (permalink / raw)
  To: Thomas Bogendoerfer
  Cc: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Srinivas Kandagatla,
	Alessandro Zummo, Alexandre Belloni, Greg Kroah-Hartman,
	Jiri Slaby, Evgeniy Polyakov, linux-mips,
	Linux Kernel Mailing List, linux-input, netdev,
	open list:REAL TIME CLOCK (RTC) SUBSYSTEM,
	open list:SERIAL DRIVERS

On Fri, Aug 9, 2019 at 1:34 PM Thomas Bogendoerfer
<tbogendoerfer@suse.de> wrote:
>
> Our chosen byte swapping, which is what firmware already uses, is to
> do readl/writel by normal lw/sw intructions (data invariance). This
> also means we need to mangle addresses for u8 and u16 accesses. The
> mangling for 16bit has been done aready, but 8bit one was missing.
> Correcting this causes different addresses for accesses to the
> SuperIO and local bus of the IOC3 chip. This is fixed by changing
> byte order in ioc3 and m48rtc_rtc structs.

>  /* serial port register map */
>  struct ioc3_serialregs {
> -       uint32_t        sscr;
> -       uint32_t        stpir;
> -       uint32_t        stcir;
> -       uint32_t        srpir;
> -       uint32_t        srcir;
> -       uint32_t        srtr;
> -       uint32_t        shadow;
> +       u32     sscr;
> +       u32     stpir;
> +       u32     stcir;
> +       u32     srpir;
> +       u32     srcir;
> +       u32     srtr;
> +       u32     shadow;
>  };

Isn't it a churn? AFAIU kernel documentation the uint32_t is okay to
use, just be consistent inside one module / driver.
Am I mistaken?


-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 8/9] MIPS: SGI-IP27: fix readb/writeb addressing
  2019-08-10 13:22   ` Andy Shevchenko
@ 2019-08-11  7:29     ` Greg Kroah-Hartman
  2019-08-13  8:47       ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 27+ messages in thread
From: Greg Kroah-Hartman @ 2019-08-11  7:29 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Thomas Bogendoerfer, Ralf Baechle, Paul Burton, James Hogan,
	Dmitry Torokhov, Lee Jones, David S. Miller, Srinivas Kandagatla,
	Alessandro Zummo, Alexandre Belloni, Jiri Slaby,
	Evgeniy Polyakov, linux-mips, Linux Kernel Mailing List,
	linux-input, netdev, open list:REAL TIME CLOCK (RTC) SUBSYSTEM,
	open list:SERIAL DRIVERS

On Sat, Aug 10, 2019 at 04:22:23PM +0300, Andy Shevchenko wrote:
> On Fri, Aug 9, 2019 at 1:34 PM Thomas Bogendoerfer
> <tbogendoerfer@suse.de> wrote:
> >
> > Our chosen byte swapping, which is what firmware already uses, is to
> > do readl/writel by normal lw/sw intructions (data invariance). This
> > also means we need to mangle addresses for u8 and u16 accesses. The
> > mangling for 16bit has been done aready, but 8bit one was missing.
> > Correcting this causes different addresses for accesses to the
> > SuperIO and local bus of the IOC3 chip. This is fixed by changing
> > byte order in ioc3 and m48rtc_rtc structs.
> 
> >  /* serial port register map */
> >  struct ioc3_serialregs {
> > -       uint32_t        sscr;
> > -       uint32_t        stpir;
> > -       uint32_t        stcir;
> > -       uint32_t        srpir;
> > -       uint32_t        srcir;
> > -       uint32_t        srtr;
> > -       uint32_t        shadow;
> > +       u32     sscr;
> > +       u32     stpir;
> > +       u32     stcir;
> > +       u32     srpir;
> > +       u32     srcir;
> > +       u32     srtr;
> > +       u32     shadow;
> >  };
> 
> Isn't it a churn? AFAIU kernel documentation the uint32_t is okay to
> use, just be consistent inside one module / driver.
> Am I mistaken?

No, but really it uint* shouldn't be used anywhere in the kernel source
as it does not make sense.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 7/9] mfd: ioc3: Add driver for SGI IOC3 chip
  2019-08-09 21:22   ` [PATCH v4 7/9] mfd: ioc3: Add driver for SGI IOC3 chip Jakub Kicinski
@ 2019-08-11  7:32     ` Thomas Bogendoerfer
  2019-08-12 19:52       ` Jakub Kicinski
  0 siblings, 1 reply; 27+ messages in thread
From: Thomas Bogendoerfer @ 2019-08-11  7:32 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Srinivas Kandagatla,
	Alessandro Zummo, Alexandre Belloni, Greg Kroah-Hartman,
	Jiri Slaby, Evgeniy Polyakov, linux-mips, linux-kernel,
	linux-input, netdev, linux-rtc, linux-serial

On Fri, 9 Aug 2019 14:22:22 -0700
Jakub Kicinski <jakub.kicinski@netronome.com> wrote:

> On Fri,  9 Aug 2019 12:32:29 +0200, Thomas Bogendoerfer wrote:
> > SGI IOC3 chip has integrated ethernet, keyboard and mouse interface.
> > It also supports connecting a SuperIO chip for serial and parallel
> > interfaces. IOC3 is used inside various SGI systemboards and add-on
> > cards with different equipped external interfaces.
> > 
> > Support for ethernet and serial interfaces were implemented inside
> > the network driver. This patchset moves out the not network related
> > parts to a new MFD driver, which takes care of card detection,
> > setup of platform devices and interrupt distribution for the subdevices.
> > 
> > Serial portion: Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > 
> > Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
> 
> There are a lot of changes in the ethernet part which are not easy to
> explain by the introduction of the other MFD parts.. Could you possibly
> break this change up into smaller chunks?

working on it

> Also please don't use stdint types in the kernel, please try checkpatch
> to catch coding style issues.

my patch already reduces them and checkpatch only warns about usage of printk
for the network part. Changing that to dev_warn/dev_err in the mfd patch didn't
seem the right thing to do. As I'm splitting the conversion patch into a few
steps I could also replace the printks.

Thomas.

-- 
SUSE Linux GmbH
GF: Felix Imendörffer, Mary Higgins, Sri Rasiah
HRB 21284 (AG Nürnberg)

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 7/9] mfd: ioc3: Add driver for SGI IOC3 chip
  2019-08-11  7:32     ` Thomas Bogendoerfer
@ 2019-08-12 19:52       ` Jakub Kicinski
  0 siblings, 0 replies; 27+ messages in thread
From: Jakub Kicinski @ 2019-08-12 19:52 UTC (permalink / raw)
  To: Thomas Bogendoerfer
  Cc: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Srinivas Kandagatla,
	Alessandro Zummo, Alexandre Belloni, Greg Kroah-Hartman,
	Jiri Slaby, Evgeniy Polyakov, linux-mips, linux-kernel,
	linux-input, netdev, linux-rtc, linux-serial

On Sun, 11 Aug 2019 09:32:12 +0200, Thomas Bogendoerfer wrote:
> > Also please don't use stdint types in the kernel, please try checkpatch
> > to catch coding style issues.  
> 
> my patch already reduces them and checkpatch only warns about usage of printk
> for the network part. Changing that to dev_warn/dev_err in the mfd patch didn't
> seem the right thing to do. As I'm splitting the conversion patch into a few
> steps I could also replace the printks.

Thanks for looking into it. I was referring to the use of uint32_t
instead of u32. Perhaps checkpatch has to be motivated with the --strict
option to point those out?

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 8/9] MIPS: SGI-IP27: fix readb/writeb addressing
  2019-08-11  7:29     ` Greg Kroah-Hartman
@ 2019-08-13  8:47       ` Philippe Mathieu-Daudé
  2019-08-14 11:40         ` Thomas Bogendoerfer
  0 siblings, 1 reply; 27+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-08-13  8:47 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Andy Shevchenko
  Cc: Thomas Bogendoerfer, Ralf Baechle, Paul Burton, James Hogan,
	Dmitry Torokhov, Lee Jones, David S. Miller, Srinivas Kandagatla,
	Alessandro Zummo, Alexandre Belloni, Jiri Slaby,
	Evgeniy Polyakov, linux-mips, Linux Kernel Mailing List,
	linux-input, netdev, open list:REAL TIME CLOCK (RTC) SUBSYSTEM,
	open list:SERIAL DRIVERS

Hi Thomas,

On 8/11/19 9:29 AM, Greg Kroah-Hartman wrote:
> On Sat, Aug 10, 2019 at 04:22:23PM +0300, Andy Shevchenko wrote:
>> On Fri, Aug 9, 2019 at 1:34 PM Thomas Bogendoerfer
>> <tbogendoerfer@suse.de> wrote:
>>>
>>> Our chosen byte swapping, which is what firmware already uses, is to
>>> do readl/writel by normal lw/sw intructions (data invariance). This
>>> also means we need to mangle addresses for u8 and u16 accesses. The
>>> mangling for 16bit has been done aready, but 8bit one was missing.
>>> Correcting this causes different addresses for accesses to the
>>> SuperIO and local bus of the IOC3 chip. This is fixed by changing
>>> byte order in ioc3 and m48rtc_rtc structs.
>>
>>>  /* serial port register map */
>>>  struct ioc3_serialregs {
>>> -       uint32_t        sscr;
>>> -       uint32_t        stpir;
>>> -       uint32_t        stcir;
>>> -       uint32_t        srpir;
>>> -       uint32_t        srcir;
>>> -       uint32_t        srtr;
>>> -       uint32_t        shadow;
>>> +       u32     sscr;
>>> +       u32     stpir;
>>> +       u32     stcir;
>>> +       u32     srpir;
>>> +       u32     srcir;
>>> +       u32     srtr;
>>> +       u32     shadow;
>>>  };
>>
>> Isn't it a churn? AFAIU kernel documentation the uint32_t is okay to
>> use, just be consistent inside one module / driver.
>> Am I mistaken?
> 
> No, but really it uint* shouldn't be used anywhere in the kernel source
> as it does not make sense.

If you respin your series, please send this cleanup as a separate patch.

Thanks,

Phil.

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 3/9] nvmem: core: add nvmem_device_find
  2019-08-09 10:32 ` [PATCH v4 3/9] nvmem: core: add nvmem_device_find Thomas Bogendoerfer
@ 2019-08-13  9:40   ` Srinivas Kandagatla
  2019-08-14 11:46     ` Thomas Bogendoerfer
  0 siblings, 1 reply; 27+ messages in thread
From: Srinivas Kandagatla @ 2019-08-13  9:40 UTC (permalink / raw)
  To: Thomas Bogendoerfer, Ralf Baechle, Paul Burton, James Hogan,
	Dmitry Torokhov, Lee Jones, David S. Miller, Alessandro Zummo,
	Alexandre Belloni, Greg Kroah-Hartman, Jiri Slaby,
	Evgeniy Polyakov, linux-mips, linux-kernel, linux-input, netdev,
	linux-rtc, linux-serial



On 09/08/2019 11:32, Thomas Bogendoerfer wrote:
> nvmem_device_find provides a way to search for nvmem devices with
> the help of a match function simlair to bus_find_device.
> 
> Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
> ---
>   drivers/nvmem/core.c           | 62 ++++++++++++++++++++++--------------------
>   include/linux/nvmem-consumer.h |  9 ++++++
>   2 files changed, 41 insertions(+), 30 deletions(-)

Have you considered using nvmem_register_notifier() ?


--srini

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 8/9] MIPS: SGI-IP27: fix readb/writeb addressing
  2019-08-13  8:47       ` Philippe Mathieu-Daudé
@ 2019-08-14 11:40         ` Thomas Bogendoerfer
  0 siblings, 0 replies; 27+ messages in thread
From: Thomas Bogendoerfer @ 2019-08-14 11:40 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Greg Kroah-Hartman, Andy Shevchenko, Ralf Baechle, Paul Burton,
	James Hogan, Dmitry Torokhov, Lee Jones, David S. Miller,
	Srinivas Kandagatla, Alessandro Zummo, Alexandre Belloni,
	Jiri Slaby, Evgeniy Polyakov, linux-mips,
	Linux Kernel Mailing List, linux-input, netdev,
	open list:REAL TIME CLOCK (RTC) SUBSYSTEM,
	open list:SERIAL DRIVERS

On Tue, 13 Aug 2019 10:47:13 +0200
Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:

> Hi Thomas,
> 
> On 8/11/19 9:29 AM, Greg Kroah-Hartman wrote:
> > On Sat, Aug 10, 2019 at 04:22:23PM +0300, Andy Shevchenko wrote:
> >> On Fri, Aug 9, 2019 at 1:34 PM Thomas Bogendoerfer
> >> <tbogendoerfer@suse.de> wrote:
> >>>
> >>> Our chosen byte swapping, which is what firmware already uses, is to
> >>> do readl/writel by normal lw/sw intructions (data invariance). This
> >>> also means we need to mangle addresses for u8 and u16 accesses. The
> >>> mangling for 16bit has been done aready, but 8bit one was missing.
> >>> Correcting this causes different addresses for accesses to the
> >>> SuperIO and local bus of the IOC3 chip. This is fixed by changing
> >>> byte order in ioc3 and m48rtc_rtc structs.
> >>
> >>>  /* serial port register map */
> >>>  struct ioc3_serialregs {
> >>> -       uint32_t        sscr;
> >>> -       uint32_t        stpir;
> >>> -       uint32_t        stcir;
> >>> -       uint32_t        srpir;
> >>> -       uint32_t        srcir;
> >>> -       uint32_t        srtr;
> >>> -       uint32_t        shadow;
> >>> +       u32     sscr;
> >>> +       u32     stpir;
> >>> +       u32     stcir;
> >>> +       u32     srpir;
> >>> +       u32     srcir;
> >>> +       u32     srtr;
> >>> +       u32     shadow;
> >>>  };
> >>
> >> Isn't it a churn? AFAIU kernel documentation the uint32_t is okay to
> >> use, just be consistent inside one module / driver.
> >> Am I mistaken?
> > 
> > No, but really it uint* shouldn't be used anywhere in the kernel source
> > as it does not make sense.
> 
> If you respin your series, please send this cleanup as a separate patch.

no need for an extra patch. I realized that patch 7 in this series introduces
all of these uint32_t. So i already fixed it there.

Thomas.

-- 
SUSE Linux GmbH
GF: Felix Imendörffer, Mary Higgins, Sri Rasiah
HRB 21284 (AG Nürnberg)

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 3/9] nvmem: core: add nvmem_device_find
  2019-08-13  9:40   ` Srinivas Kandagatla
@ 2019-08-14 11:46     ` Thomas Bogendoerfer
  2019-08-14 12:52       ` Srinivas Kandagatla
  0 siblings, 1 reply; 27+ messages in thread
From: Thomas Bogendoerfer @ 2019-08-14 11:46 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Alessandro Zummo, Alexandre Belloni,
	Greg Kroah-Hartman, Jiri Slaby, Evgeniy Polyakov, linux-mips,
	linux-kernel, linux-input, netdev, linux-rtc, linux-serial

On Tue, 13 Aug 2019 10:40:34 +0100
Srinivas Kandagatla <srinivas.kandagatla@linaro.org> wrote:

> 
> 
> On 09/08/2019 11:32, Thomas Bogendoerfer wrote:
> > nvmem_device_find provides a way to search for nvmem devices with
> > the help of a match function simlair to bus_find_device.
> > 
> > Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
> > ---
> >   drivers/nvmem/core.c           | 62 ++++++++++++++++++++++--------------------
> >   include/linux/nvmem-consumer.h |  9 ++++++
> >   2 files changed, 41 insertions(+), 30 deletions(-)
> 
> Have you considered using nvmem_register_notifier() ?

yes, that was the first idea. But then I realized I need to build up
a private database of information already present in nvmem bus. So I
looked for a way to retrieve it from there. Unfortunately I couldn't
use bus_find_device directly, because nvmem_bus_type and struct nvmem_device
is hidden. So I refactured the lookup code and added a more universal
lookup function, which fits my needs and should be usable for more.

Thomas.

-- 
SUSE Linux GmbH
GF: Felix Imendörffer, Mary Higgins, Sri Rasiah
HRB 21284 (AG Nürnberg)

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 3/9] nvmem: core: add nvmem_device_find
  2019-08-14 11:46     ` Thomas Bogendoerfer
@ 2019-08-14 12:52       ` Srinivas Kandagatla
  2019-08-16 14:09         ` Thomas Bogendoerfer
  0 siblings, 1 reply; 27+ messages in thread
From: Srinivas Kandagatla @ 2019-08-14 12:52 UTC (permalink / raw)
  To: Thomas Bogendoerfer
  Cc: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Alessandro Zummo, Alexandre Belloni,
	Greg Kroah-Hartman, Jiri Slaby, Evgeniy Polyakov, linux-mips,
	linux-kernel, linux-input, netdev, linux-rtc, linux-serial



On 14/08/2019 12:46, Thomas Bogendoerfer wrote:
> On Tue, 13 Aug 2019 10:40:34 +0100
> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> wrote:
> 
>>
>>
>> On 09/08/2019 11:32, Thomas Bogendoerfer wrote:
>>> nvmem_device_find provides a way to search for nvmem devices with
>>> the help of a match function simlair to bus_find_device.
>>>
>>> Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
>>> ---
>>>    drivers/nvmem/core.c           | 62 ++++++++++++++++++++++--------------------
>>>    include/linux/nvmem-consumer.h |  9 ++++++
>>>    2 files changed, 41 insertions(+), 30 deletions(-)
>>
>> Have you considered using nvmem_register_notifier() ?
> 
> yes, that was the first idea. But then I realized I need to build up
> a private database of information already present in nvmem bus. So I
> looked for a way to retrieve it from there. Unfortunately I couldn't
> use bus_find_device directly, because nvmem_bus_type and struct nvmem_device
> is hidden. So I refactured the lookup code and added a more universal
> lookup function, which fits my needs and should be usable for more.
I see your point.

overall the patch as it is look good, but recently we added more generic 
lookups for DT node, looks like part of your patch is un-doing generic 
device name lookup.

DT node match lookup is in 
https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git/log/?h=generic_lookup_helpers

of_nvmem_match and nvmem_match_name are duplicating the code here.
Looks like its possible to use generic lookups along with custom match 
by splitting __nvmem_device_get() to two functions, one for lookup and 
other for refcounting.

Other missing bit is adding this api to documentation in 
./Documentation/driver-api/nvmem.rst


thanks,
srini
> 
> Thomas.
> 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 9/9] Input: add IOC3 serio driver
  2019-08-09 10:32 ` [PATCH v4 9/9] Input: add IOC3 serio driver Thomas Bogendoerfer
  2019-08-09 22:04   ` Dmitry Torokhov
@ 2019-08-14 13:20   ` Jonas Gorski
  2019-08-14 14:37     ` Thomas Bogendoerfer
  1 sibling, 1 reply; 27+ messages in thread
From: Jonas Gorski @ 2019-08-14 13:20 UTC (permalink / raw)
  To: Thomas Bogendoerfer
  Cc: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Srinivas Kandagatla,
	Alessandro Zummo, Alexandre Belloni, Greg Kroah-Hartman,
	Jiri Slaby, Evgeniy Polyakov, linux-mips, linux-kernel,
	linux-input, Network Development, linux-rtc, linux-serial

Hi,

On Fri, 9 Aug 2019 at 12:33, Thomas Bogendoerfer <tbogendoerfer@suse.de> wrote:
>
> This patch adds a platform driver for supporting keyboard and mouse
> interface of SGI IOC3 chips.
>
> Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
> ---
>  drivers/input/serio/Kconfig   |  10 +++
>  drivers/input/serio/Makefile  |   1 +
>  drivers/input/serio/ioc3kbd.c | 163 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 174 insertions(+)
>  create mode 100644 drivers/input/serio/ioc3kbd.c
>
> diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
> index f3e18f8ef9ca..373a1646019e 100644
> --- a/drivers/input/serio/Kconfig
> +++ b/drivers/input/serio/Kconfig
> @@ -165,6 +165,16 @@ config SERIO_MACEPS2
>           To compile this driver as a module, choose M here: the
>           module will be called maceps2.
>
> +config SERIO_SGI_IOC3
> +       tristate "SGI IOC3 PS/2 controller"
> +       depends on SGI_MFD_IOC3
> +       help
> +         Say Y here if you have an SGI Onyx2, SGI Octane or IOC3 PCI card
> +         and you want to attach and use a keyboard, mouse, or both.
> +
> +         To compile this driver as a module, choose M here: the
> +         module will be called ioc3kbd.
> +
>  config SERIO_LIBPS2
>         tristate "PS/2 driver library"
>         depends on SERIO_I8042 || SERIO_I8042=n
> diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
> index 67950a5ccb3f..6d97bad7b844 100644
> --- a/drivers/input/serio/Makefile
> +++ b/drivers/input/serio/Makefile
> @@ -20,6 +20,7 @@ obj-$(CONFIG_HIL_MLC)         += hp_sdc_mlc.o hil_mlc.o
>  obj-$(CONFIG_SERIO_PCIPS2)     += pcips2.o
>  obj-$(CONFIG_SERIO_PS2MULT)    += ps2mult.o
>  obj-$(CONFIG_SERIO_MACEPS2)    += maceps2.o
> +obj-$(CONFIG_SERIO_SGI_IOC3)   += ioc3kbd.o
>  obj-$(CONFIG_SERIO_LIBPS2)     += libps2.o
>  obj-$(CONFIG_SERIO_RAW)                += serio_raw.o
>  obj-$(CONFIG_SERIO_AMS_DELTA)  += ams_delta_serio.o
> diff --git a/drivers/input/serio/ioc3kbd.c b/drivers/input/serio/ioc3kbd.c
> new file mode 100644
> index 000000000000..6840e3c23fed
> --- /dev/null
> +++ b/drivers/input/serio/ioc3kbd.c
> @@ -0,0 +1,163 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * SGI IOC3 PS/2 controller driver for linux
> + *
> + * Copyright (C) 2019 Thomas Bogendoerfer <tbogendoerfer@suse.de>
> + *
> + * Based on code Copyright (C) 2005 Stanislaw Skowronek <skylark@unaligned.org>
> + *               Copyright (C) 2009 Johannes Dickgreber <tanzy@gmx.de>
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/serio.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +#include <asm/sn/ioc3.h>
> +
> +struct ioc3kbd_data {
> +       struct ioc3_serioregs __iomem *regs;
> +       struct serio *kbd, *aux;
> +       int irq;
> +};
> +
> +static int ioc3kbd_write(struct serio *dev, u8 val)
> +{
> +       struct ioc3kbd_data *d = dev->port_data;
> +       unsigned long timeout = 0;
> +       u32 mask;
> +
> +       mask = (dev == d->aux) ? KM_CSR_M_WRT_PEND : KM_CSR_K_WRT_PEND;
> +       while ((readl(&d->regs->km_csr) & mask) && (timeout < 1000)) {
> +               udelay(100);
> +               timeout++;
> +       }
> +
> +       if (timeout >= 1000)
> +               return -ETIMEDOUT;
> +
> +       writel(val, dev == d->aux ? &d->regs->m_wd : &d->regs->k_wd);
> +
> +       return 0;
> +}
> +
> +static irqreturn_t ioc3kbd_intr(int itq, void *dev_id)
> +{
> +       struct ioc3kbd_data *d = dev_id;
> +       u32 data_k, data_m;
> +
> +       data_k = readl(&d->regs->k_rd);
> +       data_m = readl(&d->regs->m_rd);
> +
> +       if (data_k & KM_RD_VALID_0)
> +               serio_interrupt(d->kbd, (data_k >> KM_RD_DATA_0_SHIFT) & 0xff,
> +                               0);
> +       if (data_k & KM_RD_VALID_1)
> +               serio_interrupt(d->kbd, (data_k >> KM_RD_DATA_1_SHIFT) & 0xff,
> +                               0);
> +       if (data_k & KM_RD_VALID_2)
> +               serio_interrupt(d->kbd, (data_k >> KM_RD_DATA_2_SHIFT) & 0xff,
> +                               0);
> +       if (data_m & KM_RD_VALID_0)
> +               serio_interrupt(d->aux, (data_m >> KM_RD_DATA_0_SHIFT) & 0xff,
> +                               0);
> +       if (data_m & KM_RD_VALID_1)
> +               serio_interrupt(d->aux, (data_m >> KM_RD_DATA_1_SHIFT) & 0xff,
> +                               0);
> +       if (data_m & KM_RD_VALID_2)
> +               serio_interrupt(d->aux, (data_m >> KM_RD_DATA_2_SHIFT) & 0xff,
> +                               0);
> +
> +       return 0;
> +}
> +
> +static int ioc3kbd_probe(struct platform_device *pdev)
> +{
> +       struct ioc3_serioregs __iomem *regs;
> +       struct device *dev = &pdev->dev;
> +       struct ioc3kbd_data *d;
> +       struct serio *sk, *sa;
> +       int irq, ret;
> +
> +       regs = devm_platform_ioremap_resource(pdev, 0);
> +       if (IS_ERR(regs))
> +               return PTR_ERR(regs);
> +
> +       irq = platform_get_irq(pdev, 0);
> +       if (irq < 0)
> +               return -ENXIO;
> +
> +       d = devm_kzalloc(&pdev->dev, sizeof(*d), GFP_KERNEL);

&pdev->dev => dev

> +       if (!d)
> +               return -ENOMEM;
> +
> +       sk = kzalloc(sizeof(*sk), GFP_KERNEL);

any reason not to devm_kzalloc this as well? Then you won't need to
manually free it in the error cases.

> +       if (!sk)
> +               return -ENOMEM;
> +
> +       sa = kzalloc(sizeof(*sa), GFP_KERNEL);

same here.

> +       if (!sa) {
> +               kfree(sk);
> +               return -ENOMEM;
> +       }
> +
> +       sk->id.type = SERIO_8042;
> +       sk->write = ioc3kbd_write;
> +       snprintf(sk->name, sizeof(sk->name), "IOC3 keyboard %d", pdev->id);
> +       snprintf(sk->phys, sizeof(sk->phys), "ioc3/serio%dkbd", pdev->id);
> +       sk->port_data = d;
> +       sk->dev.parent = &pdev->dev;

&pdev->dev => dev

> +
> +       sa->id.type = SERIO_8042;
> +       sa->write = ioc3kbd_write;
> +       snprintf(sa->name, sizeof(sa->name), "IOC3 auxiliary %d", pdev->id);
> +       snprintf(sa->phys, sizeof(sa->phys), "ioc3/serio%daux", pdev->id);
> +       sa->port_data = d;
> +       sa->dev.parent = dev;
> +
> +       d->regs = regs;
> +       d->kbd = sk;
> +       d->aux = sa;
> +       d->irq = irq;
> +
> +       platform_set_drvdata(pdev, d);
> +       serio_register_port(d->kbd);
> +       serio_register_port(d->aux);
> +
> +       ret = devm_request_irq(&pdev->dev, irq, ioc3kbd_intr, IRQF_SHARED,
> +                              "ioc3-kbd", d);
> +       if (ret) {
> +               dev_err(&pdev->dev, "could not request IRQ %d\n", irq);
> +               serio_unregister_port(d->kbd);
> +               serio_unregister_port(d->aux);
> +               kfree(sk);
> +               kfree(sa);
> +               return ret;
> +       }
> +       return 0;
> +}
> +
> +static int ioc3kbd_remove(struct platform_device *pdev)
> +{
> +       struct ioc3kbd_data *d = platform_get_drvdata(pdev);
> +
> +       devm_free_irq(&pdev->dev, d->irq, d);
> +       serio_unregister_port(d->kbd);
> +       serio_unregister_port(d->aux);
> +       return 0;
> +}

and on that topic, won't you need to kfree d->kbd and d->aux here?
Unless you devm_kzalloc'd them.

Alternatively you could also just embed the two serio structs into
ioc3kbd_data, then you only need one allocation instead of three.


Regards

Jonas

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 9/9] Input: add IOC3 serio driver
  2019-08-14 13:20   ` Jonas Gorski
@ 2019-08-14 14:37     ` Thomas Bogendoerfer
  2019-08-14 16:57       ` Jonas Gorski
  0 siblings, 1 reply; 27+ messages in thread
From: Thomas Bogendoerfer @ 2019-08-14 14:37 UTC (permalink / raw)
  To: Jonas Gorski
  Cc: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Srinivas Kandagatla,
	Alessandro Zummo, Alexandre Belloni, Greg Kroah-Hartman,
	Jiri Slaby, Evgeniy Polyakov, linux-mips, linux-kernel,
	linux-input, Network Development, linux-rtc, linux-serial

On Wed, 14 Aug 2019 15:20:14 +0200
Jonas Gorski <jonas.gorski@gmail.com> wrote:

> > +       d = devm_kzalloc(&pdev->dev, sizeof(*d), GFP_KERNEL);
> 
> &pdev->dev => dev

will change.

> 
> > +       if (!d)
> > +               return -ENOMEM;
> > +
> > +       sk = kzalloc(sizeof(*sk), GFP_KERNEL);
> 
> any reason not to devm_kzalloc this as well? Then you won't need to
> manually free it in the error cases.

it has different life time than the device, so it may not allocated
via devm_kzalloc

> > +static int ioc3kbd_remove(struct platform_device *pdev)
> > +{
> > +       struct ioc3kbd_data *d = platform_get_drvdata(pdev);
> > +
> > +       devm_free_irq(&pdev->dev, d->irq, d);
> > +       serio_unregister_port(d->kbd);
> > +       serio_unregister_port(d->aux);
> > +       return 0;
> > +}
> 
> and on that topic, won't you need to kfree d->kbd and d->aux here?

that's done in serio_release_port() by the serio core.

Thomas.

-- 
SUSE Linux GmbH
GF: Felix Imendörffer, Mary Higgins, Sri Rasiah
HRB 21284 (AG Nürnberg)

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 9/9] Input: add IOC3 serio driver
  2019-08-14 14:37     ` Thomas Bogendoerfer
@ 2019-08-14 16:57       ` Jonas Gorski
  2019-08-14 18:04         ` Dmitry Torokhov
  0 siblings, 1 reply; 27+ messages in thread
From: Jonas Gorski @ 2019-08-14 16:57 UTC (permalink / raw)
  To: Thomas Bogendoerfer
  Cc: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Srinivas Kandagatla,
	Alessandro Zummo, Alexandre Belloni, Greg Kroah-Hartman,
	Jiri Slaby, Evgeniy Polyakov, linux-mips, linux-kernel,
	linux-input, Network Development, linux-rtc, linux-serial

On Wed, 14 Aug 2019 at 16:37, Thomas Bogendoerfer <tbogendoerfer@suse.de> wrote:
>
> On Wed, 14 Aug 2019 15:20:14 +0200
> Jonas Gorski <jonas.gorski@gmail.com> wrote:
>
> > > +       d = devm_kzalloc(&pdev->dev, sizeof(*d), GFP_KERNEL);
> >
> > &pdev->dev => dev
>
> will change.
>
> >
> > > +       if (!d)
> > > +               return -ENOMEM;
> > > +
> > > +       sk = kzalloc(sizeof(*sk), GFP_KERNEL);
> >
> > any reason not to devm_kzalloc this as well? Then you won't need to
> > manually free it in the error cases.
>
> it has different life time than the device, so it may not allocated
> via devm_kzalloc
>
> > > +static int ioc3kbd_remove(struct platform_device *pdev)
> > > +{
> > > +       struct ioc3kbd_data *d = platform_get_drvdata(pdev);
> > > +
> > > +       devm_free_irq(&pdev->dev, d->irq, d);
> > > +       serio_unregister_port(d->kbd);
> > > +       serio_unregister_port(d->aux);
> > > +       return 0;
> > > +}
> >
> > and on that topic, won't you need to kfree d->kbd and d->aux here?
>
> that's done in serio_release_port() by the serio core.

i see. But in that case, don't the kfree's after the
serio_unregister_port's in the error path of the .probe function cause
a double free?


Regards
Jonas

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 9/9] Input: add IOC3 serio driver
  2019-08-14 16:57       ` Jonas Gorski
@ 2019-08-14 18:04         ` Dmitry Torokhov
  0 siblings, 0 replies; 27+ messages in thread
From: Dmitry Torokhov @ 2019-08-14 18:04 UTC (permalink / raw)
  To: Jonas Gorski
  Cc: Thomas Bogendoerfer, Ralf Baechle, Paul Burton, James Hogan,
	Lee Jones, David S. Miller, Srinivas Kandagatla,
	Alessandro Zummo, Alexandre Belloni, Greg Kroah-Hartman,
	Jiri Slaby, Evgeniy Polyakov, linux-mips, linux-kernel,
	linux-input, Network Development, linux-rtc, linux-serial

On Wed, Aug 14, 2019 at 06:57:55PM +0200, Jonas Gorski wrote:
> On Wed, 14 Aug 2019 at 16:37, Thomas Bogendoerfer <tbogendoerfer@suse.de> wrote:
> >
> > On Wed, 14 Aug 2019 15:20:14 +0200
> > Jonas Gorski <jonas.gorski@gmail.com> wrote:
> >
> > > > +       d = devm_kzalloc(&pdev->dev, sizeof(*d), GFP_KERNEL);
> > >
> > > &pdev->dev => dev
> >
> > will change.
> >
> > >
> > > > +       if (!d)
> > > > +               return -ENOMEM;
> > > > +
> > > > +       sk = kzalloc(sizeof(*sk), GFP_KERNEL);
> > >
> > > any reason not to devm_kzalloc this as well? Then you won't need to
> > > manually free it in the error cases.
> >
> > it has different life time than the device, so it may not allocated
> > via devm_kzalloc
> >
> > > > +static int ioc3kbd_remove(struct platform_device *pdev)
> > > > +{
> > > > +       struct ioc3kbd_data *d = platform_get_drvdata(pdev);
> > > > +
> > > > +       devm_free_irq(&pdev->dev, d->irq, d);
> > > > +       serio_unregister_port(d->kbd);
> > > > +       serio_unregister_port(d->aux);
> > > > +       return 0;
> > > > +}
> > >
> > > and on that topic, won't you need to kfree d->kbd and d->aux here?
> >
> > that's done in serio_release_port() by the serio core.
> 
> i see. But in that case, don't the kfree's after the
> serio_unregister_port's in the error path of the .probe function cause
> a double free?

Yes they do, we need to drop kfree()s from there. Nicely spotted.

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 3/9] nvmem: core: add nvmem_device_find
  2019-08-14 12:52       ` Srinivas Kandagatla
@ 2019-08-16 14:09         ` Thomas Bogendoerfer
  2019-08-19 16:03           ` Srinivas Kandagatla
  0 siblings, 1 reply; 27+ messages in thread
From: Thomas Bogendoerfer @ 2019-08-16 14:09 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Alessandro Zummo, Alexandre Belloni,
	Greg Kroah-Hartman, Jiri Slaby, Evgeniy Polyakov, linux-mips,
	linux-kernel, linux-input, netdev, linux-rtc, linux-serial

On Wed, Aug 14, 2019 at 01:52:49PM +0100, Srinivas Kandagatla wrote:
> On 14/08/2019 12:46, Thomas Bogendoerfer wrote:
> >On Tue, 13 Aug 2019 10:40:34 +0100
> >Srinivas Kandagatla <srinivas.kandagatla@linaro.org> wrote:
> >>On 09/08/2019 11:32, Thomas Bogendoerfer wrote:
> >>>nvmem_device_find provides a way to search for nvmem devices with
> >>>the help of a match function simlair to bus_find_device.
> >>>
> >>>Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
> >>>---
> >>>   drivers/nvmem/core.c           | 62 ++++++++++++++++++++++--------------------
> >>>   include/linux/nvmem-consumer.h |  9 ++++++
> >>>   2 files changed, 41 insertions(+), 30 deletions(-)
> >>
> >>Have you considered using nvmem_register_notifier() ?
> >
> >yes, that was the first idea. But then I realized I need to build up
> >a private database of information already present in nvmem bus. So I
> >looked for a way to retrieve it from there. Unfortunately I couldn't
> >use bus_find_device directly, because nvmem_bus_type and struct nvmem_device
> >is hidden. So I refactured the lookup code and added a more universal
> >lookup function, which fits my needs and should be usable for more.
> I see your point.
> 
> overall the patch as it is look good, but recently we added more generic
> lookups for DT node, looks like part of your patch is un-doing generic
> device name lookup.
> 
> DT node match lookup is in https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git/log/?h=generic_lookup_helpers

these patches are not in Linus tree, yet. I guess they will show up
in 5.4. No idea how to deal with it right now, do you ?

> Other missing bit is adding this api to documentation in
> ./Documentation/driver-api/nvmem.rst

ok, will do.

Thomas.

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 3/9] nvmem: core: add nvmem_device_find
  2019-08-16 14:09         ` Thomas Bogendoerfer
@ 2019-08-19 16:03           ` Srinivas Kandagatla
  2019-08-21 12:48             ` Thomas Bogendoerfer
  0 siblings, 1 reply; 27+ messages in thread
From: Srinivas Kandagatla @ 2019-08-19 16:03 UTC (permalink / raw)
  To: Thomas Bogendoerfer
  Cc: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Alessandro Zummo, Alexandre Belloni,
	Greg Kroah-Hartman, Jiri Slaby, Evgeniy Polyakov, linux-mips,
	linux-kernel, linux-input, netdev, linux-rtc, linux-serial



On 16/08/2019 15:09, Thomas Bogendoerfer wrote:
> On Wed, Aug 14, 2019 at 01:52:49PM +0100, Srinivas Kandagatla wrote:
>> On 14/08/2019 12:46, Thomas Bogendoerfer wrote:
>>> On Tue, 13 Aug 2019 10:40:34 +0100
>>> Srinivas Kandagatla <srinivas.kandagatla@linaro.org> wrote:
>>>> On 09/08/2019 11:32, Thomas Bogendoerfer wrote:
>>>>> nvmem_device_find provides a way to search for nvmem devices with
>>>>> the help of a match function simlair to bus_find_device.
>>>>>
>>>>> Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
>>>>> ---
>>>>>    drivers/nvmem/core.c           | 62 ++++++++++++++++++++++--------------------
>>>>>    include/linux/nvmem-consumer.h |  9 ++++++
>>>>>    2 files changed, 41 insertions(+), 30 deletions(-)
>>>>
>>>> Have you considered using nvmem_register_notifier() ?
>>>
>>> yes, that was the first idea. But then I realized I need to build up
>>> a private database of information already present in nvmem bus. So I
>>> looked for a way to retrieve it from there. Unfortunately I couldn't
>>> use bus_find_device directly, because nvmem_bus_type and struct nvmem_device
>>> is hidden. So I refactured the lookup code and added a more universal
>>> lookup function, which fits my needs and should be usable for more.
>> I see your point.
>>
>> overall the patch as it is look good, but recently we added more generic
>> lookups for DT node, looks like part of your patch is un-doing generic
>> device name lookup.
>>
>> DT node match lookup is in https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git/log/?h=generic_lookup_helpers
> 
> these patches are not in Linus tree, yet. I guess they will show up
> in 5.4. No idea how to deal with it right now, do you ?
All these patches are due to go in next merge window,
You should base your patch on top of linux-next.

thanks,
srini
> 
>> Other missing bit is adding this api to documentation in
>> ./Documentation/driver-api/nvmem.rst
> 
> ok, will do.
> 
> Thomas.
> 

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 3/9] nvmem: core: add nvmem_device_find
  2019-08-19 16:03           ` Srinivas Kandagatla
@ 2019-08-21 12:48             ` Thomas Bogendoerfer
  0 siblings, 0 replies; 27+ messages in thread
From: Thomas Bogendoerfer @ 2019-08-21 12:48 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: Ralf Baechle, Paul Burton, James Hogan, Dmitry Torokhov,
	Lee Jones, David S. Miller, Alessandro Zummo, Alexandre Belloni,
	Greg Kroah-Hartman, Jiri Slaby, Evgeniy Polyakov, linux-mips,
	linux-kernel, linux-input, netdev, linux-rtc, linux-serial

On Mon, Aug 19, 2019 at 05:03:42PM +0100, Srinivas Kandagatla wrote:
> >>On 14/08/2019 12:46, Thomas Bogendoerfer wrote:
> >these patches are not in Linus tree, yet. I guess they will show up
> >in 5.4. No idea how to deal with it right now, do you ?
> All these patches are due to go in next merge window,
> You should base your patch on top of linux-next.

that depends, which maintainer will merge this series. Right now
it doesn't look like this series will make it into 5.4 as there
is still no sign form the W1 maintainer. My idea is to break out
the 5.4 parts and submit it. So I'll rebase the nvmem patch to
linux-next and send it. Hope it will be ok,  if the user of
the new function will show up in 5.5.

Thomas.

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2019-08-21 14:29 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-09 10:32 [PATCH v4 0/9] Use MFD framework for SGI IOC3 drivers Thomas Bogendoerfer
2019-08-09 10:32 ` [PATCH v4 1/9] w1: add 1-wire master driver for IP block found in SGI ASICs Thomas Bogendoerfer
2019-08-09 10:32 ` [PATCH v4 2/9] w1: add DS2501, DS2502, DS2505 EPROM device driver Thomas Bogendoerfer
2019-08-09 10:32 ` [PATCH v4 3/9] nvmem: core: add nvmem_device_find Thomas Bogendoerfer
2019-08-13  9:40   ` Srinivas Kandagatla
2019-08-14 11:46     ` Thomas Bogendoerfer
2019-08-14 12:52       ` Srinivas Kandagatla
2019-08-16 14:09         ` Thomas Bogendoerfer
2019-08-19 16:03           ` Srinivas Kandagatla
2019-08-21 12:48             ` Thomas Bogendoerfer
2019-08-09 10:32 ` [PATCH v4 4/9] MIPS: PCI: refactor ioc3 special handling Thomas Bogendoerfer
2019-08-09 10:32 ` [PATCH v4 5/9] MIPS: PCI: use information from 1-wire PROM for IOC3 detection Thomas Bogendoerfer
2019-08-09 10:32 ` [PATCH v4 6/9] MIPS: SGI-IP27: remove ioc3 ethernet init Thomas Bogendoerfer
2019-08-09 10:32 ` [PATCH v4 8/9] MIPS: SGI-IP27: fix readb/writeb addressing Thomas Bogendoerfer
2019-08-10 13:22   ` Andy Shevchenko
2019-08-11  7:29     ` Greg Kroah-Hartman
2019-08-13  8:47       ` Philippe Mathieu-Daudé
2019-08-14 11:40         ` Thomas Bogendoerfer
2019-08-09 10:32 ` [PATCH v4 9/9] Input: add IOC3 serio driver Thomas Bogendoerfer
2019-08-09 22:04   ` Dmitry Torokhov
2019-08-14 13:20   ` Jonas Gorski
2019-08-14 14:37     ` Thomas Bogendoerfer
2019-08-14 16:57       ` Jonas Gorski
2019-08-14 18:04         ` Dmitry Torokhov
     [not found] ` <20190809103235.16338-8-tbogendoerfer@suse.de>
2019-08-09 21:22   ` [PATCH v4 7/9] mfd: ioc3: Add driver for SGI IOC3 chip Jakub Kicinski
2019-08-11  7:32     ` Thomas Bogendoerfer
2019-08-12 19:52       ` Jakub Kicinski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).