linux-m68k.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] i2c/busses: Add i2c-icy for I2C on m68k/Amiga
@ 2019-08-11  4:32 Max Staudt
  2019-08-11  4:40 ` Max Staudt
  2019-08-12  9:37 ` Geert Uytterhoeven
  0 siblings, 2 replies; 11+ messages in thread
From: Max Staudt @ 2019-08-11  4:32 UTC (permalink / raw)
  To: linux-i2c, Wolfram Sang; +Cc: linux-m68k, linux-kernel, glaubitz, Max Staudt

This is the i2c-icy driver for the ICY board for Amiga computers.
It connects a PCF8584 I2C controller to the Zorro bus, providing I2C
connectivity. The original documentation can be found on Aminet:

https://aminet.net/package/docs/hard/icy

Since the 2019 a1k.org community re-print of these PCBs sports an
LTC2990 hwmon chip as an example use case, this driver autoprobes for
that as well. If it is present, modprobing ltc2990 is sufficient.

IRQ support is currently not implemented, as i2c-algo-pcf is built for
the ISA bus and a straight implementation of the same stack locks up a
Zorro machine.

Tested-by: Max Staudt <max@enpas.org>
Signed-off-by: Max Staudt <max@enpas.org>
---
 MAINTAINERS                  |   6 ++
 drivers/i2c/busses/Kconfig   |  11 +++
 drivers/i2c/busses/Makefile  |   1 +
 drivers/i2c/busses/i2c-icy.c | 224 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 242 insertions(+)
 create mode 100644 drivers/i2c/busses/i2c-icy.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 1be025959..70336c083 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7705,6 +7705,12 @@ S:	Maintained
 F:	drivers/mfd/lpc_ich.c
 F:	drivers/gpio/gpio-ich.c
 
+ICY I2C DRIVER
+M:	Max Staudt <max@enpas.org>
+L:	linux-i2c@vger.kernel.org
+S:	Maintained
+F:	drivers/i2c/busses/i2c-icy.c
+
 IDE SUBSYSTEM
 M:	"David S. Miller" <davem@davemloft.net>
 L:	linux-ide@vger.kernel.org
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index ee5dfb5ae..e798b8517 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -1300,6 +1300,17 @@ config I2C_ELEKTOR
 	  This support is also available as a module.  If so, the module
 	  will be called i2c-elektor.
 
+config I2C_ICY
+	tristate "ICY Zorro card"
+	depends on ZORRO && BROKEN_ON_SMP
+	select I2C_ALGOPCF
+	help
+	  This supports the PCF8584 Zorro bus I2C adapter, known as ICY.
+	  Say Y if you own such an adapter.
+
+	  This support is also available as a module.  If so, the module
+	  will be called i2c-icy.
+
 config I2C_MLXCPLD
 	tristate "Mellanox I2C driver"
 	depends on X86_64
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index a3245231b..d0e1c3d4e 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -139,6 +139,7 @@ obj-$(CONFIG_I2C_BCM_KONA)	+= i2c-bcm-kona.o
 obj-$(CONFIG_I2C_BRCMSTB)	+= i2c-brcmstb.o
 obj-$(CONFIG_I2C_CROS_EC_TUNNEL)	+= i2c-cros-ec-tunnel.o
 obj-$(CONFIG_I2C_ELEKTOR)	+= i2c-elektor.o
+obj-$(CONFIG_I2C_ICY)		+= i2c-icy.o
 obj-$(CONFIG_I2C_MLXCPLD)	+= i2c-mlxcpld.o
 obj-$(CONFIG_I2C_OPAL)		+= i2c-opal.o
 obj-$(CONFIG_I2C_PCA_ISA)	+= i2c-pca-isa.o
diff --git a/drivers/i2c/busses/i2c-icy.c b/drivers/i2c/busses/i2c-icy.c
new file mode 100644
index 000000000..037fdfe32
--- /dev/null
+++ b/drivers/i2c/busses/i2c-icy.c
@@ -0,0 +1,224 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * I2C driver for stand-alone PCF8584 style adapters on Zorro cards
+ *
+ * Original ICY documentation can be found on Aminet:
+ * https://aminet.net/package/docs/hard/icy
+ *
+ * There has been a modern community re-print of this design in 2019:
+ * https://www.a1k.org/forum/index.php?threads/70106/
+ *
+ * The card is basically a Philips PCF8584 connected straight to the
+ * beginning of the AutoConfig'd address space (register S1 on base+2),
+ * with /INT on /INT2 on the Zorro bus.
+ *
+ * Copyright (c) 2019 Max Staudt <max@enpas.org>
+ *
+ * This is heavily based on i2c-elektor.c and thanks go to:
+ *
+ * Simon G. Vogl
+ * Hans Berglund
+ * Kyosti Malkki <kmalkki@cc.hut.fi>
+ * Frodo Looijaard <frodol@dds.nl>
+ * Oleg I. Vdovikin
+ *
+ *
+ * IRQ support is currently not implemented.
+ *
+ * As it turns out, i2c-algo-pcf is really written with i2c-elektor's
+ * edge-triggered ISA interrupts in mind, while the Amiga's Zorro bus has
+ * level-triggered interrupts. This means that once an interrupt occurs, we
+ * have to tell the PCF8584 to shut up immediately, or it will keep the
+ * interrupt line busy and cause an IRQ storm.
+
+ * However, because of the PCF8584's host-side protocol, there is no good
+ * way to just quieten it without side effects. Rather, we have to perform
+ * the next read/write operation straight away, which will reset the /INT
+ * pin. This entails re-designing the core of i2c-algo-pcf in the future.
+ * For now, we never request an IRQ from the PCF8584, and poll it instead.
+ */
+
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-pcf.h>
+#include <linux/io.h>
+
+#include <asm/amigaints.h>
+#include <linux/zorro.h>
+
+#include "../algos/i2c-algo-pcf.h"
+
+
+static int clock = 0x1c;
+module_param(clock, int, 0444);
+
+
+
+struct icy_i2c {
+	struct i2c_adapter adapter;
+
+	void __iomem *reg_s0;
+	void __iomem *reg_s1;
+	struct i2c_client *client_ltc2990;
+};
+
+
+
+/*
+ * Functions called by i2c-algo-pcf
+ */
+static void icy_pcf_setbyte(void *data, int ctl, int val)
+{
+	struct icy_i2c *i2c = (struct icy_i2c *)data;
+
+	u8 __iomem *address = ctl ? i2c->reg_s1 : i2c->reg_s0;
+
+	iowrite8(val, address);
+}
+
+static int icy_pcf_getbyte(void *data, int ctl)
+{
+	struct icy_i2c *i2c = (struct icy_i2c *)data;
+
+	u8 __iomem *address = ctl ? i2c->reg_s1 : i2c->reg_s0;
+	int val = ioread8(address);
+
+	return val;
+}
+
+static int icy_pcf_getown(void *data)
+{
+	return 0x55;
+}
+
+static int icy_pcf_getclock(void *data)
+{
+	return clock;
+}
+
+static void icy_pcf_waitforpin(void *data)
+{
+	udelay(100);
+}
+
+
+
+/*
+ * Main i2c-icy part
+ */
+static struct i2c_board_info icy_ltc2990_info = {
+	I2C_BOARD_INFO("ltc2990", 0x4c),
+};
+
+static unsigned short const icy_ltc2990_addresses[] = {0x4c, I2C_CLIENT_END};
+
+
+static int icy_probe(struct zorro_dev *z,
+			 const struct zorro_device_id *ent)
+{
+	struct icy_i2c *i2c;
+	struct i2c_algo_pcf_data *algo_data;
+
+
+	i2c = devm_kzalloc(&z->dev, sizeof(*i2c), GFP_KERNEL);
+	if (!i2c)
+		return -ENOMEM;
+
+	algo_data = devm_kzalloc(&z->dev, sizeof(*algo_data), GFP_KERNEL);
+	if (!algo_data)
+		return -ENOMEM;
+
+	dev_set_drvdata(&z->dev, i2c);
+	i2c->adapter.dev.parent = &z->dev;
+	i2c->adapter.owner = THIS_MODULE;
+	i2c->adapter.class = I2C_CLASS_DEPRECATED;
+	/* i2c->adapter.algo assigned by i2c_pcf_add_bus() */
+	i2c->adapter.algo_data = algo_data;
+	strlcpy(i2c->adapter.name, "ICY I2C Zorro adapter",
+		sizeof(i2c->adapter.name));
+
+	if (!devm_request_mem_region(&z->dev,
+				     z->resource.start,
+				     4, i2c->adapter.name))
+		return -ENXIO;
+
+	/* Driver private data */
+	i2c->reg_s0 = ZTWO_VADDR(z->resource.start);
+	i2c->reg_s1 = ZTWO_VADDR(z->resource.start + 2);
+
+	algo_data->data = (void *)i2c;
+	algo_data->setpcf     = icy_pcf_setbyte;
+	algo_data->getpcf     = icy_pcf_getbyte;
+	algo_data->getown     = icy_pcf_getown;
+	algo_data->getclock   = icy_pcf_getclock;
+	algo_data->waitforpin = icy_pcf_waitforpin;
+
+	if (i2c_pcf_add_bus(&i2c->adapter)) {
+		dev_err(&z->dev, "i2c_pcf_add_bus() failed\n");
+		return -ENXIO;
+	}
+
+	dev_info(&z->dev, "ICY I2C controller at %#x, IRQ not implemented\n",
+		 z->resource.start);
+
+	/*
+	 * The 2019 a1k.org PCBs have an LTC2990 at 0x4c, so start
+	 * it automatically once ltc2990 is modprobed.
+	 *
+	 * in0 is the voltage of the internal 5V power supply.
+	 * temp1 is the temperature inside the chip.
+	 *
+	 * Configuration 0x18 enables all sensors on this PCB:
+	 *  # modprobe i2c-dev
+	 *  # i2cset 0 0x4c 1 0x18
+	 *  # modprobe ltc2990
+	 * in1 will be the voltage of the 5V rail, divided by 2.
+	 * in2 will be the voltage of the 12V rail, divided by 4.
+	 * temp3 will be measured using a PCB loop next the chip.
+	 */
+	i2c->client_ltc2990 = i2c_new_probed_device(&i2c->adapter,
+						    &icy_ltc2990_info,
+						    icy_ltc2990_addresses,
+						    NULL);
+
+	return 0;
+}
+
+static void icy_remove(struct zorro_dev *z)
+{
+	struct icy_i2c *i2c = dev_get_drvdata(&z->dev);
+
+	i2c_unregister_device(i2c->client_ltc2990);
+
+	i2c_del_adapter(&i2c->adapter);
+}
+
+
+
+static const struct zorro_device_id icy_zorro_tbl[] = {
+	{ ZORRO_ID(VMC, 15, 0), },
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(zorro, icy_zorro_tbl);
+
+static struct zorro_driver icy_driver = {
+	.name           = "i2c-icy",
+	.id_table       = icy_zorro_tbl,
+	.probe          = icy_probe,
+	.remove         = icy_remove,
+};
+
+module_driver(icy_driver,
+	      zorro_register_driver,
+	      zorro_unregister_driver);
+
+
+MODULE_AUTHOR("Max Staudt <max@enpas.org>");
+MODULE_DESCRIPTION("I2C bus via PCF8584 on ICY Zorro card");
+MODULE_LICENSE("GPL");
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread
* Re: [PATCH v5 1/3] i2c/busses: Add i2c-icy for I2C on m68k/Amiga
@ 2019-08-20  9:23 Max
  2019-08-20  9:27 ` [PATCH] " Max Staudt
  0 siblings, 1 reply; 11+ messages in thread
From: Max @ 2019-08-20  9:23 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Linux I2C, linux-hwmon, Wolfram Sang, Jean Delvare,
	Guenter Roeck, Linux/m68k, Linux Kernel Mailing List,
	John Paul Adrian Glaubitz



On August 20, 2019 11:08:00 AM GMT+02:00, Geert Uytterhoeven <geert@linux-m68k.org> wrote:
>> +       int val = z_readb(address);
>> +
>> +       return val;
>
>return z_readb(address);

Argh, that slipped through the cracks. I'll mend it later. Thank you.

Max

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

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

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-11  4:32 [PATCH] i2c/busses: Add i2c-icy for I2C on m68k/Amiga Max Staudt
2019-08-11  4:40 ` Max Staudt
2019-08-12  9:37 ` Geert Uytterhoeven
2019-08-12 10:43   ` Max Staudt
2019-08-12 11:07     ` Geert Uytterhoeven
2019-08-12 11:48       ` Max Staudt
2019-08-12 22:21   ` Max Staudt
2019-08-13  6:53     ` Geert Uytterhoeven
2019-08-20  9:23 [PATCH v5 1/3] " Max
2019-08-20  9:27 ` [PATCH] " Max Staudt
2019-08-29 19:00   ` Wolfram Sang
2019-08-29 19:17     ` Max Staudt

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).