Add 1-wire master driver for i.MX27 / i.MX31
Subsystems (5)
PATCH 1/1 Add 1-wire master driver for i.MX27 / i.MX31
From: Sascha Hauer <[email protected]>
This patch adds support for the 1-wire master interface for i.MX27 and i.MX31.
--- 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
drivers/w1/masters/Kconfig +6 -0
@@ -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
drivers/w1/masters/Makefile +2 -0
@@ -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
drivers/w1/masters/mxc_w1.c new file +215 -0
215 lines not on this page · raw message
Signature · 1 line
1.5.2.5
PATCH 1/1 MX2: Add W1 device/resources
From: Sascha Hauer <[email protected]>
--- arch/arm/mach-mx2/devices.c | 15 +++++++++++++++ arch/arm/mach-mx2/devices.h | 2 +- 2 files changed, 16 insertions(+), 1 deletions(-)
arch/arm/mach-mx2/devices.c +15 -0
@@ -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 ] = {
arch/arm/mach-mx2/devices.h +1 -1
@@ -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;
Signature · 1 line
1.5.2.5
PATCH 1/1 MX31: add w1 platform_device and resources
From: Sascha Hauer <[email protected]>
--- arch/arm/mach-mx3/devices.c | 15 +++++++++++++++ arch/arm/mach-mx3/devices.h | 1 + 2 files changed, 16 insertions(+), 0 deletions(-)
arch/arm/mach-mx3/devices.c +15 -0
@@ -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, +};
arch/arm/mach-mx3/devices.h +1 -0
@@ -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;
Signature · 1 line
1.5.2.5
PATCH 1/1 MX2 pcm038: add 1-wire master support
From: Sascha Hauer <[email protected]>
--- arch/arm/mach-mx2/pcm038.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
arch/arm/mach-mx2/pcm038.c +2 -0
@@ -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));
Signature · 1 line
1.5.2.5
PATCH 1/1 pcm037: add 1wire support
From: Sascha Hauer <[email protected]>
--- arch/arm/mach-mx3/pcm037.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-)
arch/arm/mach-mx3/pcm037.c +3 -0
@@ -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 ); }/*
Signature · 1 line
1.5.2.5
Sascha Hauer
maintainerHi,
Quoted 4 lines · Evgeniy Polyakov
From: Sascha Hauer <[email protected]>
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
Quoted 266 lines
Signed-off-by Luotao Fu <[email protected]>Signed-off-by Sascha Hauer <[email protected]>Signed-off-by Evgeniy Polyakov <[email protected]>--- 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.cdrivers/w1/masters/Kconfig +6
-0@@ -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 && ARMdrivers/w1/masters/Makefile +2
-0@@ -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.odrivers/w1/masters/mxc_w1.c new file +215
-0@@ -0,0 +1,215 @@ +/* +* Copyright 2005-2008 Freescale Semiconductor, Inc. All Rights Reserved. +* Copyright 2008 Luotao Fu, [email protected] +* +* 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" );Signature · 1 line
1.5.2.5
Signature · 4 lines
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-9Quoted 4 lines · On Wed, 19 Nov 2008 01:16:13 +0300 Evgeniy Polyakov <[email protected]> wrote:
From: Sascha Hauer <[email protected]>
This patch adds support for the 1-wire master interface for i.MX27 and i.MX31.
Looks sane.
Quoted 3 lines
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?
Quoted 5 lines
...
(quoted diff) +2
-0+static int __devinit mxc_w1_probe(struct platform_device *pdev) +{
Review
Quoted 10 lines
(quoted diff) +10
-0+ 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?
Review
Quoted 11 lines
(quoted diff) +11
-0+ 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.
Quoted 28 lines
(quoted diff) +28
-0+ 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; +
Review
Quoted 10 lines
(quoted diff) +10
-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 <[email protected]>
- coding-style fixes
- remove unneeded casts of void*
---
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
drivers/w1/masters/mxc_w1.c renamed from drivers/w1/masters/mxc_w1.c~add-1-wire-master-driver-for-imx27-imx31-fix +4 -6
@@ -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 *datstatic 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; }
_
Sascha Hauer
maintainerHi Andrew,
Sorry for the delay, we are moving to a new office at the moment.
Quoted 7 lines · Andrew Morton
Quoted 4 lines · On Wed, 19 Nov 2008 01:16:13 +0300 Evgeniy Polyakov <[email protected]> wrote:
From: Sascha Hauer <[email protected]>
This patch adds support for the 1-wire master interface for i.MX27 and i.MX31.
Quoted 7 lines
Looks sane.
Quoted 3 lines
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.
Quoted 19 lines
Quoted 6 lines
...
(quoted diff) +2
-0+static int __devinit mxc_w1_probe(struct platform_device *pdev) +{Review
Quoted 10 lines
(quoted diff) +10
-0+ 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
Quoted 6 lines
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;
};Quoted 15 lines
Review
Quoted 12 lines
(quoted diff) +11
-0+ 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_SECwould 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 <[email protected]> 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.
Documentation/w1/masters/00-INDEX +2 -0
@@ -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.
Documentation/w1/masters/mxc-w1 new file +11 -0
@@ -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 <[email protected]>
drivers/w1/masters/Kconfig +6 -0
@@ -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
drivers/w1/masters/Makefile +2 -0
@@ -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
drivers/w1/masters/mxc_w1.c new file +211 -0
211 lines not on this page · raw message
Signature · 4 lines
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