* [PATCH] Add 1-wire master driver for i.MX27 / i.MX31
@ 2008-11-18 22:16 Evgeniy Polyakov
2008-11-18 22:16 ` [PATCH] MX2: Add W1 device/resources Evgeniy Polyakov
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Evgeniy Polyakov @ 2008-11-18 22:16 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, Sascha Hauer, Luotao Fu, Evgeniy Polyakov
From: Sascha Hauer <s.hauer@pengutronix.de>
This patch adds support for the 1-wire master interface for i.MX27 and
i.MX31.
Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Evgeniy Polyakov <zbr@ioremap.net>
---
drivers/w1/masters/Kconfig | 6 +
drivers/w1/masters/Makefile | 2 +
drivers/w1/masters/mxc_w1.c | 215 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 223 insertions(+), 0 deletions(-)
create mode 100644 drivers/w1/masters/mxc_w1.c
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig
index a14d5b6..f2da1a8 100644
--- a/drivers/w1/masters/Kconfig
+++ b/drivers/w1/masters/Kconfig
@@ -34,6 +34,12 @@ config W1_MASTER_DS2482
This driver can also be built as a module. If so, the module
will be called ds2482.
+config W1_MASTER_MXC
+ tristate "Freescale MXC 1-wire busmaster"
+ depends on W1 && ARCH_MXC
+ help
+ Say Y here to enable MXC 1-wire host
+
config W1_MASTER_DS1WM
tristate "Maxim DS1WM 1-wire busmaster"
depends on W1 && ARM
diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile
index bc4714a..c5a3e96 100644
--- a/drivers/w1/masters/Makefile
+++ b/drivers/w1/masters/Makefile
@@ -5,6 +5,8 @@
obj-$(CONFIG_W1_MASTER_MATROX) += matrox_w1.o
obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o
obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o
+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
diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c
new file mode 100644
index 0000000..92323be
--- /dev/null
+++ b/drivers/w1/masters/mxc_w1.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2005-2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Luotao Fu, kernel@pengutronix.de
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include "../w1.h"
+#include "../w1_int.h"
+#include "../w1_log.h"
+
+/* According to the mx27 Datasheet the reset procedure should take up to about
+ * 1350us. We set the timeout to 500*100us = 50ms for sure */
+#define MXC_W1_RESET_TIMEOUT 500
+
+/*
+ * MXC W1 Register offsets
+ */
+#define MXC_W1_CONTROL 0x00
+#define MXC_W1_TIME_DIVIDER 0x02
+#define MXC_W1_RESET 0x04
+#define MXC_W1_COMMAND 0x06
+#define MXC_W1_TXRX 0x08
+#define MXC_W1_INTERRUPT 0x0A
+#define MXC_W1_INTERRUPT_EN 0x0C
+
+struct mxc_w1_device {
+ void __iomem *regs;
+ unsigned int clkdiv;
+ struct clk *clk;
+ struct w1_bus_master *bus_master;
+};
+
+/*
+ * this is the low level routine to
+ * reset the device on the One Wire interface
+ * on the hardware
+ */
+static u8 mxc_w1_ds2_reset_bus(void *data)
+{
+ u8 reg_val, rc = 1;
+ unsigned int timeout_cnt = 0;
+
+ struct mxc_w1_device *dev = (struct mxc_w1_device *)data;
+
+ __raw_writeb(0x80, (dev->regs + MXC_W1_CONTROL));
+
+ while (1) {
+ reg_val = __raw_readb(dev->regs + MXC_W1_CONTROL);
+
+ if (((reg_val >> 7) & 0x1) == 0 ||
+ timeout_cnt > MXC_W1_RESET_TIMEOUT) {
+ rc = 0;
+ break;
+ } else
+ timeout_cnt++;
+
+ udelay(100);
+ }
+ return (reg_val >> 7) & 0x1;
+}
+
+/*
+ * 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 mxc_w1_ds2_touch_bit(void *data, u8 bit)
+{
+ unsigned int timeout_cnt = 400;
+
+ struct mxc_w1_device *mdev = (struct mxc_w1_device *)data;
+ void __iomem *ctrl_addr = mdev->regs + MXC_W1_CONTROL;
+
+ __raw_writeb((1 << (5 - bit)), ctrl_addr);
+
+ while (timeout_cnt--) {
+ if (!((__raw_readb(ctrl_addr) >> (5 - bit)) & 0x1))
+ break;
+
+ udelay(1);
+ }
+
+ return ((__raw_readb(ctrl_addr)) >> 3) & 0x1;
+}
+
+static int __devinit mxc_w1_probe(struct platform_device *pdev)
+{
+ struct mxc_w1_device *mdev;
+ struct resource *res;
+ int err = 0;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ mdev = kzalloc(sizeof(struct mxc_w1_device) +
+ sizeof(struct w1_bus_master), GFP_KERNEL);
+
+ if (!mdev)
+ return -ENOMEM;
+
+ mdev->clk = clk_get(&pdev->dev, "owire_clk");
+ if (!mdev->clk) {
+ err = -ENODEV;
+ goto failed_clk;
+ }
+
+ mdev->bus_master = (struct w1_bus_master *)(mdev + 1);
+ mdev->clkdiv = (clk_get_rate(mdev->clk) / 1000000) - 1;
+
+ res = request_mem_region(res->start, resource_size(res),
+ "mxc_w1");
+ if (!res) {
+ err = -EBUSY;
+ goto failed_req;
+ }
+
+ mdev->regs = ioremap(res->start, resource_size(res));
+ if (!mdev->regs) {
+ printk(KERN_ERR"Cannot map frame buffer registers\n");
+ goto failed_ioremap;
+ }
+
+ clk_enable(mdev->clk);
+ __raw_writeb(mdev->clkdiv, mdev->regs + MXC_W1_TIME_DIVIDER);
+
+ mdev->bus_master->data = mdev;
+ mdev->bus_master->reset_bus = &mxc_w1_ds2_reset_bus;
+ mdev->bus_master->touch_bit = &mxc_w1_ds2_touch_bit;
+
+ err = w1_add_master_device(mdev->bus_master);
+
+ if (err)
+ goto failed_add;
+
+ platform_set_drvdata(pdev, mdev);
+ return 0;
+
+failed_add:
+ iounmap(mdev->regs);
+failed_ioremap:
+ release_mem_region(res->start, resource_size(res));
+failed_req:
+ clk_put(mdev->clk);
+failed_clk:
+ kfree(mdev);
+ return err;
+}
+
+/*
+ * disassociate the w1 device from the driver
+ */
+static int mxc_w1_remove(struct platform_device *pdev)
+{
+ struct mxc_w1_device *mdev = platform_get_drvdata(pdev);
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ w1_remove_master_device(mdev->bus_master);
+
+ iounmap(mdev->regs);
+ release_mem_region(res->start, resource_size(res));
+ clk_disable(mdev->clk);
+ clk_put(mdev->clk);
+
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver mxc_w1_driver = {
+ .driver = {
+ .name = "mxc_w1",
+ },
+ .probe = mxc_w1_probe,
+ .remove = mxc_w1_remove,
+};
+
+static int __init mxc_w1_init(void)
+{
+ return platform_driver_register(&mxc_w1_driver);
+}
+
+static void mxc_w1_exit(void)
+{
+ platform_driver_unregister(&mxc_w1_driver);
+}
+
+module_init(mxc_w1_init);
+module_exit(mxc_w1_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Freescale Semiconductors Inc");
+MODULE_DESCRIPTION("Driver for One-Wire on MXC");
--
1.5.2.5
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH] MX2: Add W1 device/resources 2008-11-18 22:16 [PATCH] Add 1-wire master driver for i.MX27 / i.MX31 Evgeniy Polyakov @ 2008-11-18 22:16 ` Evgeniy Polyakov 2008-11-18 22:16 ` [PATCH] MX31: add w1 platform_device and resources Evgeniy Polyakov 2008-11-18 22:25 ` [PATCH] Add 1-wire master driver for i.MX27 / i.MX31 Sascha Hauer 2008-11-19 8:19 ` Andrew Morton 2 siblings, 1 reply; 8+ messages in thread From: Evgeniy Polyakov @ 2008-11-18 22:16 UTC (permalink / raw) To: Andrew Morton; +Cc: linux-kernel, Sascha Hauer, Evgeniy Polyakov From: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Evgeniy Polyakov <zbr@ioremap.net> --- arch/arm/mach-mx2/devices.c | 15 +++++++++++++++ arch/arm/mach-mx2/devices.h | 2 +- 2 files changed, 16 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-mx2/devices.c b/arch/arm/mach-mx2/devices.c index bd0559d..092e09b 100644 --- a/arch/arm/mach-mx2/devices.c +++ b/arch/arm/mach-mx2/devices.c @@ -190,6 +190,21 @@ struct platform_device mxc_wdt = { .resource = mxc_wdt_resources, }; +static struct resource mxc_w1_master_resources[] = { + { + .start = OWIRE_BASE_ADDR, + .end = OWIRE_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device mxc_w1_master_device = { + .name = "mxc_w1", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_w1_master_resources), + .resource = mxc_w1_master_resources, +}; + /* GPIO port description */ static struct mxc_gpio_port imx_gpio_ports[] = { [0] = { diff --git a/arch/arm/mach-mx2/devices.h b/arch/arm/mach-mx2/devices.h index c77a4b8..5683c45 100644 --- a/arch/arm/mach-mx2/devices.h +++ b/arch/arm/mach-mx2/devices.h @@ -12,4 +12,4 @@ extern struct platform_device mxc_uart_device2; extern struct platform_device mxc_uart_device3; extern struct platform_device mxc_uart_device4; extern struct platform_device mxc_uart_device5; - +extern struct platform_device mxc_w1_master_device; -- 1.5.2.5 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH] MX31: add w1 platform_device and resources 2008-11-18 22:16 ` [PATCH] MX2: Add W1 device/resources Evgeniy Polyakov @ 2008-11-18 22:16 ` Evgeniy Polyakov 2008-11-18 22:16 ` [PATCH] MX2 pcm038: add 1-wire master support Evgeniy Polyakov 0 siblings, 1 reply; 8+ messages in thread From: Evgeniy Polyakov @ 2008-11-18 22:16 UTC (permalink / raw) To: Andrew Morton; +Cc: linux-kernel, Sascha Hauer, Evgeniy Polyakov From: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Evgeniy Polyakov <zbr@ioremap.net> --- arch/arm/mach-mx3/devices.c | 15 +++++++++++++++ arch/arm/mach-mx3/devices.h | 1 + 2 files changed, 16 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-mx3/devices.c b/arch/arm/mach-mx3/devices.c index a6bdcc0..12b3e3c 100644 --- a/arch/arm/mach-mx3/devices.c +++ b/arch/arm/mach-mx3/devices.c @@ -145,3 +145,18 @@ int __init mxc_register_gpios(void) { return mxc_gpio_init(imx_gpio_ports, ARRAY_SIZE(imx_gpio_ports)); } + +static struct resource mxc_w1_master_resources[] = { + { + .start = OWIRE_BASE_ADDR, + .end = OWIRE_BASE_ADDR + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +struct platform_device mxc_w1_master_device = { + .name = "mxc_w1", + .id = 0, + .num_resources = ARRAY_SIZE(mxc_w1_master_resources), + .resource = mxc_w1_master_resources, +}; diff --git a/arch/arm/mach-mx3/devices.h b/arch/arm/mach-mx3/devices.h index 4dc03f9..cb1459c 100644 --- a/arch/arm/mach-mx3/devices.h +++ b/arch/arm/mach-mx3/devices.h @@ -4,3 +4,4 @@ extern struct platform_device mxc_uart_device1; extern struct platform_device mxc_uart_device2; extern struct platform_device mxc_uart_device3; extern struct platform_device mxc_uart_device4; +extern struct platform_device mxc_w1_master_device; -- 1.5.2.5 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH] MX2 pcm038: add 1-wire master support 2008-11-18 22:16 ` [PATCH] MX31: add w1 platform_device and resources Evgeniy Polyakov @ 2008-11-18 22:16 ` Evgeniy Polyakov 2008-11-18 22:16 ` [PATCH] pcm037: add 1wire support Evgeniy Polyakov 0 siblings, 1 reply; 8+ messages in thread From: Evgeniy Polyakov @ 2008-11-18 22:16 UTC (permalink / raw) To: Andrew Morton; +Cc: linux-kernel, Sascha Hauer, Evgeniy Polyakov From: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Evgeniy Polyakov <zbr@ioremap.net> --- arch/arm/mach-mx2/pcm038.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-mx2/pcm038.c b/arch/arm/mach-mx2/pcm038.c index 7f55746..ac516b1 100644 --- a/arch/arm/mach-mx2/pcm038.c +++ b/arch/arm/mach-mx2/pcm038.c @@ -168,6 +168,7 @@ static void gpio_fec_inactive(void) static struct platform_device *platform_devices[] __initdata = { &pcm038_nor_mtd_device, + &mxc_w1_master_device, }; static void __init pcm038_init(void) @@ -177,6 +178,7 @@ static void __init pcm038_init(void) mxc_register_device(&mxc_uart_device0, &uart_pdata[0]); mxc_register_device(&mxc_uart_device1, &uart_pdata[1]); mxc_register_device(&mxc_uart_device2, &uart_pdata[2]); + mxc_gpio_mode(PE16_AF_RTCK); /* OWIRE */ platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); -- 1.5.2.5 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH] pcm037: add 1wire support 2008-11-18 22:16 ` [PATCH] MX2 pcm038: add 1-wire master support Evgeniy Polyakov @ 2008-11-18 22:16 ` Evgeniy Polyakov 0 siblings, 0 replies; 8+ messages in thread From: Evgeniy Polyakov @ 2008-11-18 22:16 UTC (permalink / raw) To: Andrew Morton; +Cc: linux-kernel, Sascha Hauer, Evgeniy Polyakov From: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Evgeniy Polyakov <zbr@ioremap.net> --- arch/arm/mach-mx3/pcm037.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c index 843f68c..8cd1fdf 100644 --- a/arch/arm/mach-mx3/pcm037.c +++ b/arch/arm/mach-mx3/pcm037.c @@ -81,6 +81,9 @@ static void __init mxc_board_init(void) mxc_iomux_mode(MX31_PIN_CSPI3_MISO__TXD3); mxc_register_device(&mxc_uart_device2, &uart_pdata); + + mxc_iomux_mode(MX31_PIN_BATT_LINE__OWIRE); + mxc_register_device(&mxc_w1_master_device, NULL); } /* -- 1.5.2.5 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] Add 1-wire master driver for i.MX27 / i.MX31 2008-11-18 22:16 [PATCH] Add 1-wire master driver for i.MX27 / i.MX31 Evgeniy Polyakov 2008-11-18 22:16 ` [PATCH] MX2: Add W1 device/resources Evgeniy Polyakov @ 2008-11-18 22:25 ` Sascha Hauer 2008-11-19 8:19 ` Andrew Morton 2 siblings, 0 replies; 8+ messages in thread From: Sascha Hauer @ 2008-11-18 22:25 UTC (permalink / raw) To: Evgeniy Polyakov; +Cc: Andrew Morton, linux-kernel, Luotao Fu Hi, On Wed, Nov 19, 2008 at 01:16:13AM +0300, Evgeniy Polyakov wrote: > From: Sascha Hauer <s.hauer@pengutronix.de> > > This patch adds support for the 1-wire master interface for i.MX27 and > i.MX31. Ack for this one, the other patches from this series need to go via Russell King to prevent merge conflicts with other MX2 patches. Sorry, I should have made that clear. Sascha > > Signed-off-by: Luotao Fu <l.fu@pengutronix.de> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > Signed-off-by: Evgeniy Polyakov <zbr@ioremap.net> > --- > drivers/w1/masters/Kconfig | 6 + > drivers/w1/masters/Makefile | 2 + > drivers/w1/masters/mxc_w1.c | 215 +++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 223 insertions(+), 0 deletions(-) > create mode 100644 drivers/w1/masters/mxc_w1.c > > diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig > index a14d5b6..f2da1a8 100644 > --- a/drivers/w1/masters/Kconfig > +++ b/drivers/w1/masters/Kconfig > @@ -34,6 +34,12 @@ config W1_MASTER_DS2482 > This driver can also be built as a module. If so, the module > will be called ds2482. > > +config W1_MASTER_MXC > + tristate "Freescale MXC 1-wire busmaster" > + depends on W1 && ARCH_MXC > + help > + Say Y here to enable MXC 1-wire host > + > config W1_MASTER_DS1WM > tristate "Maxim DS1WM 1-wire busmaster" > depends on W1 && ARM > diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile > index bc4714a..c5a3e96 100644 > --- a/drivers/w1/masters/Makefile > +++ b/drivers/w1/masters/Makefile > @@ -5,6 +5,8 @@ > obj-$(CONFIG_W1_MASTER_MATROX) += matrox_w1.o > obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o > obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o > +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 > diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c > new file mode 100644 > index 0000000..92323be > --- /dev/null > +++ b/drivers/w1/masters/mxc_w1.c > @@ -0,0 +1,215 @@ > +/* > + * Copyright 2005-2008 Freescale Semiconductor, Inc. All Rights Reserved. > + * Copyright 2008 Luotao Fu, kernel@pengutronix.de > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version 2 > + * of the License, or (at your option) any later version. > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. > + * > + */ > + > +#include <linux/module.h> > +#include <linux/interrupt.h> > +#include <linux/platform_device.h> > +#include <linux/clk.h> > +#include <linux/delay.h> > +#include <linux/io.h> > + > +#include "../w1.h" > +#include "../w1_int.h" > +#include "../w1_log.h" > + > +/* According to the mx27 Datasheet the reset procedure should take up to about > + * 1350us. We set the timeout to 500*100us = 50ms for sure */ > +#define MXC_W1_RESET_TIMEOUT 500 > + > +/* > + * MXC W1 Register offsets > + */ > +#define MXC_W1_CONTROL 0x00 > +#define MXC_W1_TIME_DIVIDER 0x02 > +#define MXC_W1_RESET 0x04 > +#define MXC_W1_COMMAND 0x06 > +#define MXC_W1_TXRX 0x08 > +#define MXC_W1_INTERRUPT 0x0A > +#define MXC_W1_INTERRUPT_EN 0x0C > + > +struct mxc_w1_device { > + void __iomem *regs; > + unsigned int clkdiv; > + struct clk *clk; > + struct w1_bus_master *bus_master; > +}; > + > +/* > + * this is the low level routine to > + * reset the device on the One Wire interface > + * on the hardware > + */ > +static u8 mxc_w1_ds2_reset_bus(void *data) > +{ > + u8 reg_val, rc = 1; > + unsigned int timeout_cnt = 0; > + > + struct mxc_w1_device *dev = (struct mxc_w1_device *)data; > + > + __raw_writeb(0x80, (dev->regs + MXC_W1_CONTROL)); > + > + while (1) { > + reg_val = __raw_readb(dev->regs + MXC_W1_CONTROL); > + > + if (((reg_val >> 7) & 0x1) == 0 || > + timeout_cnt > MXC_W1_RESET_TIMEOUT) { > + rc = 0; > + break; > + } else > + timeout_cnt++; > + > + udelay(100); > + } > + return (reg_val >> 7) & 0x1; > +} > + > +/* > + * 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 mxc_w1_ds2_touch_bit(void *data, u8 bit) > +{ > + unsigned int timeout_cnt = 400; > + > + struct mxc_w1_device *mdev = (struct mxc_w1_device *)data; > + void __iomem *ctrl_addr = mdev->regs + MXC_W1_CONTROL; > + > + __raw_writeb((1 << (5 - bit)), ctrl_addr); > + > + while (timeout_cnt--) { > + if (!((__raw_readb(ctrl_addr) >> (5 - bit)) & 0x1)) > + break; > + > + udelay(1); > + } > + > + return ((__raw_readb(ctrl_addr)) >> 3) & 0x1; > +} > + > +static int __devinit mxc_w1_probe(struct platform_device *pdev) > +{ > + struct mxc_w1_device *mdev; > + struct resource *res; > + int err = 0; > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (!res) > + return -ENODEV; > + > + mdev = kzalloc(sizeof(struct mxc_w1_device) + > + sizeof(struct w1_bus_master), GFP_KERNEL); > + > + if (!mdev) > + return -ENOMEM; > + > + mdev->clk = clk_get(&pdev->dev, "owire_clk"); > + if (!mdev->clk) { > + err = -ENODEV; > + goto failed_clk; > + } > + > + mdev->bus_master = (struct w1_bus_master *)(mdev + 1); > + mdev->clkdiv = (clk_get_rate(mdev->clk) / 1000000) - 1; > + > + res = request_mem_region(res->start, resource_size(res), > + "mxc_w1"); > + if (!res) { > + err = -EBUSY; > + goto failed_req; > + } > + > + mdev->regs = ioremap(res->start, resource_size(res)); > + if (!mdev->regs) { > + printk(KERN_ERR"Cannot map frame buffer registers\n"); > + goto failed_ioremap; > + } > + > + clk_enable(mdev->clk); > + __raw_writeb(mdev->clkdiv, mdev->regs + MXC_W1_TIME_DIVIDER); > + > + mdev->bus_master->data = mdev; > + mdev->bus_master->reset_bus = &mxc_w1_ds2_reset_bus; > + mdev->bus_master->touch_bit = &mxc_w1_ds2_touch_bit; > + > + err = w1_add_master_device(mdev->bus_master); > + > + if (err) > + goto failed_add; > + > + platform_set_drvdata(pdev, mdev); > + return 0; > + > +failed_add: > + iounmap(mdev->regs); > +failed_ioremap: > + release_mem_region(res->start, resource_size(res)); > +failed_req: > + clk_put(mdev->clk); > +failed_clk: > + kfree(mdev); > + return err; > +} > + > +/* > + * disassociate the w1 device from the driver > + */ > +static int mxc_w1_remove(struct platform_device *pdev) > +{ > + struct mxc_w1_device *mdev = platform_get_drvdata(pdev); > + struct resource *res; > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + > + w1_remove_master_device(mdev->bus_master); > + > + iounmap(mdev->regs); > + release_mem_region(res->start, resource_size(res)); > + clk_disable(mdev->clk); > + clk_put(mdev->clk); > + > + platform_set_drvdata(pdev, NULL); > + > + return 0; > +} > + > +static struct platform_driver mxc_w1_driver = { > + .driver = { > + .name = "mxc_w1", > + }, > + .probe = mxc_w1_probe, > + .remove = mxc_w1_remove, > +}; > + > +static int __init mxc_w1_init(void) > +{ > + return platform_driver_register(&mxc_w1_driver); > +} > + > +static void mxc_w1_exit(void) > +{ > + platform_driver_unregister(&mxc_w1_driver); > +} > + > +module_init(mxc_w1_init); > +module_exit(mxc_w1_exit); > + > +MODULE_LICENSE("GPL"); > +MODULE_AUTHOR("Freescale Semiconductors Inc"); > +MODULE_DESCRIPTION("Driver for One-Wire on MXC"); > -- > 1.5.2.5 > > -- Pengutronix - Linux Solutions for Science and Industry Handelsregister: Amtsgericht Hildesheim, HRA 2686 Hannoversche Str. 2, 31134 Hildesheim, Germany Phone: +49-5121-206917-0 | Fax: +49-5121-206917-9 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Add 1-wire master driver for i.MX27 / i.MX31 2008-11-18 22:16 [PATCH] Add 1-wire master driver for i.MX27 / i.MX31 Evgeniy Polyakov 2008-11-18 22:16 ` [PATCH] MX2: Add W1 device/resources Evgeniy Polyakov 2008-11-18 22:25 ` [PATCH] Add 1-wire master driver for i.MX27 / i.MX31 Sascha Hauer @ 2008-11-19 8:19 ` Andrew Morton 2008-11-21 10:12 ` Sascha Hauer 2 siblings, 1 reply; 8+ messages in thread From: Andrew Morton @ 2008-11-19 8:19 UTC (permalink / raw) To: Evgeniy Polyakov; +Cc: linux-kernel, Sascha Hauer, Luotao Fu On Wed, 19 Nov 2008 01:16:13 +0300 Evgeniy Polyakov <zbr@ioremap.net> wrote: > From: Sascha Hauer <s.hauer@pengutronix.de> > > This patch adds support for the 1-wire master interface for i.MX27 and > i.MX31. Looks sane. > Ack for this one, the other patches from this series need to go via > Russell King to prevent merge conflicts with other MX2 patches. Sorry, I > should have made that clear. Is this patch fully independent of the others? > > ... > > +static int __devinit mxc_w1_probe(struct platform_device *pdev) > +{ > + struct mxc_w1_device *mdev; > + struct resource *res; > + int err = 0; > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (!res) > + return -ENODEV; > + > + mdev = kzalloc(sizeof(struct mxc_w1_device) + > + sizeof(struct w1_bus_master), GFP_KERNEL); whee, that's a bit of a hack. It would be better to do struct foo { struct mxc_w1_device mxc_w1_device; struct w1_bus_master w1_bus_master; }; no? > + if (!mdev) > + return -ENOMEM; > + > + mdev->clk = clk_get(&pdev->dev, "owire_clk"); > + if (!mdev->clk) { > + err = -ENODEV; > + goto failed_clk; > + } > + > + mdev->bus_master = (struct w1_bus_master *)(mdev + 1); > + mdev->clkdiv = (clk_get_rate(mdev->clk) / 1000000) - 1; If that 1000000 refers to microseconds then the use of USEC_PER_SEC would be clearer. > + res = request_mem_region(res->start, resource_size(res), > + "mxc_w1"); > + if (!res) { > + err = -EBUSY; > + goto failed_req; > + } > + > + mdev->regs = ioremap(res->start, resource_size(res)); > + if (!mdev->regs) { > + printk(KERN_ERR"Cannot map frame buffer registers\n"); > + goto failed_ioremap; > + } > + > + clk_enable(mdev->clk); > + __raw_writeb(mdev->clkdiv, mdev->regs + MXC_W1_TIME_DIVIDER); > + > + mdev->bus_master->data = mdev; > + mdev->bus_master->reset_bus = &mxc_w1_ds2_reset_bus; > + mdev->bus_master->touch_bit = &mxc_w1_ds2_touch_bit; > + > + err = w1_add_master_device(mdev->bus_master); > + > + if (err) > + goto failed_add; > + > + platform_set_drvdata(pdev, mdev); > + return 0; > + > +failed_add: > + iounmap(mdev->regs); > +failed_ioremap: > + release_mem_region(res->start, resource_size(res)); > +failed_req: > + clk_put(mdev->clk); > +failed_clk: > + kfree(mdev); > + return err; > +} Trivial fixes: From: Andrew Morton <akpm@linux-foundation.org> - coding-style fixes - remove unneeded casts of void* Cc: Evgeniy Polyakov <zbr@ioremap.net> Cc: Luotao Fu <l.fu@pengutronix.de> Cc: Russell King <rmk@arm.linux.org.uk> Cc: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> --- drivers/w1/masters/mxc_w1.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff -puN drivers/w1/masters/Kconfig~add-1-wire-master-driver-for-imx27-imx31-fix drivers/w1/masters/Kconfig diff -puN drivers/w1/masters/Makefile~add-1-wire-master-driver-for-imx27-imx31-fix drivers/w1/masters/Makefile diff -puN drivers/w1/masters/mxc_w1.c~add-1-wire-master-driver-for-imx27-imx31-fix drivers/w1/masters/mxc_w1.c --- a/drivers/w1/masters/mxc_w1.c~add-1-wire-master-driver-for-imx27-imx31-fix +++ a/drivers/w1/masters/mxc_w1.c @@ -59,8 +59,7 @@ static u8 mxc_w1_ds2_reset_bus(void *dat { u8 reg_val, rc = 1; unsigned int timeout_cnt = 0; - - struct mxc_w1_device *dev = (struct mxc_w1_device *)data; + struct mxc_w1_device *dev = data; __raw_writeb(0x80, (dev->regs + MXC_W1_CONTROL)); @@ -87,8 +86,7 @@ static u8 mxc_w1_ds2_reset_bus(void *dat static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit) { unsigned int timeout_cnt = 400; - - struct mxc_w1_device *mdev = (struct mxc_w1_device *)data; + struct mxc_w1_device *mdev = data; void __iomem *ctrl_addr = mdev->regs + MXC_W1_CONTROL; __raw_writeb((1 << (5 - bit)), ctrl_addr); @@ -135,9 +133,9 @@ static int __devinit mxc_w1_probe(struct goto failed_req; } - mdev->regs = ioremap(res->start, resource_size(res)); + mdev->regs = ioremap(res->start, resource_size(res)); if (!mdev->regs) { - printk(KERN_ERR"Cannot map frame buffer registers\n"); + printk(KERN_ERR "Cannot map frame buffer registers\n"); goto failed_ioremap; } _ ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] Add 1-wire master driver for i.MX27 / i.MX31 2008-11-19 8:19 ` Andrew Morton @ 2008-11-21 10:12 ` Sascha Hauer 0 siblings, 0 replies; 8+ messages in thread From: Sascha Hauer @ 2008-11-21 10:12 UTC (permalink / raw) To: Andrew Morton; +Cc: Evgeniy Polyakov, linux-kernel, Luotao Fu Hi Andrew, Sorry for the delay, we are moving to a new office at the moment. On Wed, Nov 19, 2008 at 12:19:32AM -0800, Andrew Morton wrote: > On Wed, 19 Nov 2008 01:16:13 +0300 Evgeniy Polyakov <zbr@ioremap.net> wrote: > > > From: Sascha Hauer <s.hauer@pengutronix.de> > > > > This patch adds support for the 1-wire master interface for i.MX27 and > > i.MX31. > > Looks sane. > > > Ack for this one, the other patches from this series need to go via > > Russell King to prevent merge conflicts with other MX2 patches. Sorry, I > > should have made that clear. > > Is this patch fully independent of the others? The first patch adds a platform driver and the other patches add users for this driver. Otherwise they are independent. > > > > > ... > > > > +static int __devinit mxc_w1_probe(struct platform_device *pdev) > > +{ > > + struct mxc_w1_device *mdev; > > + struct resource *res; > > + int err = 0; > > + > > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > > + if (!res) > > + return -ENODEV; > > + > > + mdev = kzalloc(sizeof(struct mxc_w1_device) + > > + sizeof(struct w1_bus_master), GFP_KERNEL); > > whee, that's a bit of a hack. It would be better to do > > struct foo { > struct mxc_w1_device mxc_w1_device; > struct w1_bus_master w1_bus_master; > }; > > no? Uh, yes that's indeed a hack. I changed it to: struct mxc_w1_device { [...] struct w1_bus_master bus_master; }; > > > + if (!mdev) > > + return -ENOMEM; > > + > > + mdev->clk = clk_get(&pdev->dev, "owire_clk"); > > + if (!mdev->clk) { > > + err = -ENODEV; > > + goto failed_clk; > > + } > > + > > + mdev->bus_master = (struct w1_bus_master *)(mdev + 1); > > + mdev->clkdiv = (clk_get_rate(mdev->clk) / 1000000) - 1; > > If that 1000000 refers to microseconds then the use of USEC_PER_SEC > would be clearer. No, it's clk_get_rate() in Hz divided by 1000000 Hz to get a plain divider without unit. Here's an updated version of the patch. Let me know if you want a patch against your tree instead. Sascha commit 8259cf2a77b1f2aa215940576f5a55ce72e58a64 Author: Sascha Hauer <s.hauer@pengutronix.de> Date: Wed Nov 12 16:19:22 2008 +0100 Add 1-wire master driver for i.MX27 / i.MX31 This patch adds support for the 1-wire master interface for i.MX27 and i.MX31. Signed-off-by: Luotao Fu <l.fu@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> diff --git a/Documentation/w1/masters/00-INDEX b/Documentation/w1/masters/00-INDEX index 7b0ceaa..d63fa02 100644 --- a/Documentation/w1/masters/00-INDEX +++ b/Documentation/w1/masters/00-INDEX @@ -4,5 +4,7 @@ ds2482 - The Maxim/Dallas Semiconductor DS2482 provides 1-wire busses. ds2490 - The Maxim/Dallas Semiconductor DS2490 builds USB <-> W1 bridges. +mxc_w1 + - W1 master controller driver found on Freescale MX2/MX3 SoCs w1-gpio - GPIO 1-wire bus master driver. diff --git a/Documentation/w1/masters/mxc-w1 b/Documentation/w1/masters/mxc-w1 new file mode 100644 index 0000000..97f6199 --- /dev/null +++ b/Documentation/w1/masters/mxc-w1 @@ -0,0 +1,11 @@ +Kernel driver mxc_w1 +==================== + +Supported chips: + * Freescale MX27, MX31 and probably other i.MX SoCs + Datasheets: + http://www.freescale.com/files/32bit/doc/data_sheet/MCIMX31.pdf?fpsp=1 + http://www.freescale.com/files/dsp/MCIMX27.pdf?fpsp=1 + +Author: Originally based on Freescale code, prepared for mainline by + Sascha Hauer <s.hauer@pengutronix.de> diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index c449309..d4f8050 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig @@ -34,6 +34,12 @@ config W1_MASTER_DS2482 This driver can also be built as a module. If so, the module will be called ds2482. +config W1_MASTER_MXC + tristate "Freescale MXC 1-wire busmaster" + depends on W1 && ARCH_MXC + help + Say Y here to enable MXC 1-wire host + config W1_MASTER_DS1WM tristate "Maxim DS1WM 1-wire busmaster" depends on W1 && ARM diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile index 1420b5b..6c61e22 100644 --- a/drivers/w1/masters/Makefile +++ b/drivers/w1/masters/Makefile @@ -5,5 +5,7 @@ obj-$(CONFIG_W1_MASTER_MATROX) += matrox_w1.o obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o +obj-$(CONFIG_W1_MASTER_MXC) += mxc_w1.o + obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c new file mode 100644 index 0000000..b9d74d0 --- /dev/null +++ b/drivers/w1/masters/mxc_w1.c @@ -0,0 +1,211 @@ +/* + * Copyright 2005-2008 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008 Luotao Fu, kernel@pengutronix.de + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/io.h> + +#include "../w1.h" +#include "../w1_int.h" +#include "../w1_log.h" + +/* According to the mx27 Datasheet the reset procedure should take up to about + * 1350us. We set the timeout to 500*100us = 50ms for sure */ +#define MXC_W1_RESET_TIMEOUT 500 + +/* + * MXC W1 Register offsets + */ +#define MXC_W1_CONTROL 0x00 +#define MXC_W1_TIME_DIVIDER 0x02 +#define MXC_W1_RESET 0x04 +#define MXC_W1_COMMAND 0x06 +#define MXC_W1_TXRX 0x08 +#define MXC_W1_INTERRUPT 0x0A +#define MXC_W1_INTERRUPT_EN 0x0C + +struct mxc_w1_device { + void __iomem *regs; + unsigned int clkdiv; + struct clk *clk; + struct w1_bus_master bus_master; +}; + +/* + * this is the low level routine to + * reset the device on the One Wire interface + * on the hardware + */ +static u8 mxc_w1_ds2_reset_bus(void *data) +{ + u8 reg_val; + unsigned int timeout_cnt = 0; + struct mxc_w1_device *dev = data; + + __raw_writeb(0x80, (dev->regs + MXC_W1_CONTROL)); + + while (1) { + reg_val = __raw_readb(dev->regs + MXC_W1_CONTROL); + + if (((reg_val >> 7) & 0x1) == 0 || + timeout_cnt > MXC_W1_RESET_TIMEOUT) + break; + else + timeout_cnt++; + + udelay(100); + } + return (reg_val >> 7) & 0x1; +} + +/* + * 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 mxc_w1_ds2_touch_bit(void *data, u8 bit) +{ + struct mxc_w1_device *mdev = data; + void __iomem *ctrl_addr = mdev->regs + MXC_W1_CONTROL; + unsigned int timeout_cnt = 400; /* Takes max. 120us according to + * datasheet. + */ + + __raw_writeb((1 << (5 - bit)), ctrl_addr); + + while (timeout_cnt--) { + if (!((__raw_readb(ctrl_addr) >> (5 - bit)) & 0x1)) + break; + + udelay(1); + } + + return ((__raw_readb(ctrl_addr)) >> 3) & 0x1; +} + +static int __init mxc_w1_probe(struct platform_device *pdev) +{ + struct mxc_w1_device *mdev; + struct resource *res; + int err = 0; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + mdev = kzalloc(sizeof(struct mxc_w1_device), GFP_KERNEL); + if (!mdev) + return -ENOMEM; + + mdev->clk = clk_get(&pdev->dev, "owire_clk"); + if (!mdev->clk) { + err = -ENODEV; + goto failed_clk; + } + + mdev->clkdiv = (clk_get_rate(mdev->clk) / 1000000) - 1; + + res = request_mem_region(res->start, resource_size(res), + "mxc_w1"); + if (!res) { + err = -EBUSY; + goto failed_req; + } + + mdev->regs = ioremap(res->start, resource_size(res)); + if (!mdev->regs) { + printk(KERN_ERR "Cannot map frame buffer registers\n"); + goto failed_ioremap; + } + + clk_enable(mdev->clk); + __raw_writeb(mdev->clkdiv, mdev->regs + MXC_W1_TIME_DIVIDER); + + mdev->bus_master.data = mdev; + mdev->bus_master.reset_bus = mxc_w1_ds2_reset_bus; + mdev->bus_master.touch_bit = mxc_w1_ds2_touch_bit; + + err = w1_add_master_device(&mdev->bus_master); + + if (err) + goto failed_add; + + platform_set_drvdata(pdev, mdev); + return 0; + +failed_add: + iounmap(mdev->regs); +failed_ioremap: + release_mem_region(res->start, resource_size(res)); +failed_req: + clk_put(mdev->clk); +failed_clk: + kfree(mdev); + return err; +} + +/* + * disassociate the w1 device from the driver + */ +static int mxc_w1_remove(struct platform_device *pdev) +{ + struct mxc_w1_device *mdev = platform_get_drvdata(pdev); + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + w1_remove_master_device(&mdev->bus_master); + + iounmap(mdev->regs); + release_mem_region(res->start, resource_size(res)); + clk_disable(mdev->clk); + clk_put(mdev->clk); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver mxc_w1_driver = { + .driver = { + .name = "mxc_w1", + }, + .probe = mxc_w1_probe, + .remove = mxc_w1_remove, +}; + +static int __init mxc_w1_init(void) +{ + return platform_driver_register(&mxc_w1_driver); +} + +static void mxc_w1_exit(void) +{ + platform_driver_unregister(&mxc_w1_driver); +} + +module_init(mxc_w1_init); +module_exit(mxc_w1_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Freescale Semiconductors Inc"); +MODULE_DESCRIPTION("Driver for One-Wire on MXC"); -- Pengutronix - Linux Solutions for Science and Industry Handelsregister: Amtsgericht Hildesheim, HRA 2686 Hannoversche Str. 2, 31134 Hildesheim, Germany Phone: +49-5121-206917-0 | Fax: +49-5121-206917-9 ^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2008-11-21 10:12 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-11-18 22:16 [PATCH] Add 1-wire master driver for i.MX27 / i.MX31 Evgeniy Polyakov 2008-11-18 22:16 ` [PATCH] MX2: Add W1 device/resources Evgeniy Polyakov 2008-11-18 22:16 ` [PATCH] MX31: add w1 platform_device and resources Evgeniy Polyakov 2008-11-18 22:16 ` [PATCH] MX2 pcm038: add 1-wire master support Evgeniy Polyakov 2008-11-18 22:16 ` [PATCH] pcm037: add 1wire support Evgeniy Polyakov 2008-11-18 22:25 ` [PATCH] Add 1-wire master driver for i.MX27 / i.MX31 Sascha Hauer 2008-11-19 8:19 ` Andrew Morton 2008-11-21 10:12 ` Sascha Hauer
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox