socfpga: Adding Scan Manager driver
PATCH v5 1/1 socfpga: Adding Scan Manager driver
Scan Manager driver will be called to configure the IOCSR scan chain. This configuration will setup the IO buffer settings
---
Changes for v5
- Removal of additional blank line
- Added comment for magic number
Changes for v4
- avoid code duplication by add goto error
- include underscore to variables name Changes for v3
- merge the handoff file and driver into single patch Changes for v2
- rebase with latest v2014.01-rc1
--- arch/arm/cpu/armv7/socfpga/Makefile | 2 +- arch/arm/cpu/armv7/socfpga/scan_manager.c | 214 +++++++ arch/arm/cpu/armv7/socfpga/spl.c | 4 + arch/arm/include/asm/arch-socfpga/scan_manager.h | 96 +++ .../include/asm/arch-socfpga/socfpga_base_addrs.h | 1 + board/altera/socfpga/iocsr_config.c | 657 ++++++++++++++++++++ board/altera/socfpga/iocsr_config.h | 17 + include/configs/socfpga_cyclone5.h | 1 + 8 files changed, 991 insertions(+), 1 deletion(-) create mode 100644 arch/arm/cpu/armv7/socfpga/scan_manager.c create mode 100644 arch/arm/include/asm/arch-socfpga/scan_manager.h create mode 100644 board/altera/socfpga/iocsr_config.c create mode 100644 board/altera/socfpga/iocsr_config.h
arch/arm/cpu/armv7/socfpga/Makefile +1 -1
@@ -9,4 +9,4 @@ obj-y := lowlevel_init.o obj-y += misc.o timer.o reset_manager.o system_manager.o -obj-$(CONFIG_SPL_BUILD) += spl.o freeze_controller.o +obj-$(CONFIG_SPL_BUILD) += spl.o freeze_controller.o scan_manager.o
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +214 -0
214 lines not on this page · raw message
arch/arm/cpu/armv7/socfpga/spl.c +4 -0
@@ -32,6 +32,10 @@ void spl_board_init(void)/* freeze all IO banks */ sys_mgr_frzctrl_freeze_req (); +/* configure the IOCSR / IO buffer settings */ +if (scan_mgr_configure_iocsr ()) +hang (); +/* configure the pin muxing through system manager */ sysmgr_pinmux_init ();#endif /* CONFIG_SOCFPGA_VIRTUAL_TARGET */
arch/arm/include/asm/arch-socfpga/scan_manager.h new file +96 -0
96 lines not on this page · raw message
arch/arm/include/asm/arch-socfpga/socfpga_base_addrs.h +1 -0
@@ -13,5 +13,6 @@#define SOCFPGA_OSC1TIMER0_ADDRESS 0xffd00000#define SOCFPGA_RSTMGR_ADDRESS 0xffd05000#define SOCFPGA_SYSMGR_ADDRESS 0xffd08000 +#define SOCFPGA_SCANMGR_ADDRESS 0xfff02000#endif /* _SOCFPGA_BASE_ADDRS_H_ */
board/altera/socfpga/iocsr_config.c new file +657 -0
657 lines not on this page · raw message
board/altera/socfpga/iocsr_config.h new file +17 -0
@@ -0,0 +1,17 @@ +/* +* Copyright Altera Corporation (C) 2012-2014. All rights reserved +* +* SPDX-License-Identifier: BSD-3-Clause +*/ + +/* This file is generated by Preloader Generator */ + +#ifndef _PRELOADER_IOCSR_CONFIG_H_ +#define _PRELOADER_IOCSR_CONFIG_H_ + +#define CONFIG_HPS_IOCSR_SCANCHAIN0_LENGTH (764) +#define CONFIG_HPS_IOCSR_SCANCHAIN1_LENGTH (1719) +#define CONFIG_HPS_IOCSR_SCANCHAIN2_LENGTH (955) +#define CONFIG_HPS_IOCSR_SCANCHAIN3_LENGTH (16766) + +#endif /*_PRELOADER_IOCSR_CONFIG_H_*/
include/configs/socfpga_cyclone5.h +1 -0
@@ -8,6 +8,7 @@#include <asm/arch/socfpga_base_addrs.h> #include "../../board/altera/socfpga/pinmux_config.h" +#include "../../board/altera/socfpga/iocsr_config.h" /* * High level configuration
Signature · 1 line
1.7.9.5
PATCH v5 1/1 socfpga: Adding Scan Manager driver
Dear Chin Liang See,
Quoted 73 lines · In message <[email protected]> you wrote:
Scan Manager driver will be called to configure the IOCSR scan chain. This configuration will setup the IO buffer settings
Signed-off-by Chin Liang See <[email protected]>Cc Dinh Nguyen <[email protected]>Cc Wolfgang Denk <[email protected]>CC Pavel Machek <[email protected]>Cc Tom Rini <[email protected]>Cc Albert Aribaud <[email protected]>---
Changes for v5
- Removal of additional blank line
- Added comment for magic number
Changes for v4
- avoid code duplication by add goto error
- include underscore to variables name Changes for v3
- merge the handoff file and driver into single patch Changes for v2
- rebase with latest v2014.01-rc1--- arch/arm/cpu/armv7/socfpga/Makefile | 2 +- arch/arm/cpu/armv7/socfpga/scan_manager.c | 214 +++++++ arch/arm/cpu/armv7/socfpga/spl.c | 4 + arch/arm/include/asm/arch-socfpga/scan_manager.h | 96 +++ .../include/asm/arch-socfpga/socfpga_base_addrs.h | 1 + board/altera/socfpga/iocsr_config.c | 657 ++++++++++++++++++++ board/altera/socfpga/iocsr_config.h | 17 + include/configs/socfpga_cyclone5.h | 1 + 8 files changed, 991 insertions(+), 1 deletion(-) create mode 100644 arch/arm/cpu/armv7/socfpga/scan_manager.c create mode 100644 arch/arm/include/asm/arch-socfpga/scan_manager.h create mode 100644 board/altera/socfpga/iocsr_config.c create mode 100644 board/altera/socfpga/iocsr_config.harch/arm/cpu/armv7/socfpga/Makefile +1
-1@@ -9,4 +9,4 @@ obj-y := lowlevel_init.o obj-y += misc.o timer.o reset_manager.o system_manager.o -obj-$(CONFIG_SPL_BUILD) += spl.o freeze_controller.o +obj-$(CONFIG_SPL_BUILD) += spl.o freeze_controller.o scan_manager.oarch/arm/cpu/armv7/socfpga/scan_manager.c new file +22
-0@@ -0,0 +1,214 @@ +/* +* Copyright (C) 2013 Altera Corporation <www.altera.com> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/freeze_controller.h> +#include <asm/arch/scan_manager.h> + +DECLARE_GLOBAL_DATA_PTR ; + +static const struct socfpga_scan_manager *scan_manager_base = + (void *)(SOCFPGA_SCANMGR_ADDRESS ); +static const struct socfpga_freeze_controller *freeze_controller_base = + (void *)(SOCFPGA_SYSMGR_ADDRESS +SYSMGR_FRZCTRL_ADDRESS ); + +/* +* Function to check IO scan chain engine status and wait if the engine is +* is active. Poll the IO scan chain engine till maximum iteration reached. +*/
arch/arm/cpu/armv7/socfpga/scan_manager.c line 32
Quoted 10 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +10
-0+static inline uint32_t scan_mgr_io_scan_chain_engine_is_idle (uint32_t max_iter) +{ +uint32_t scanmgr_status; + + scanmgr_status =readl (&scan_manager_base->stat); + +/* Poll the engine until the scan engine is inactive */ +while (SCANMGR_STAT_ACTIVE_GET (scanmgr_status) + || (SCANMGR_STAT_WFIFOCNT_GET (scanmgr_status) >0 )) { + max_iter--;
This is difficult to read due to unlucky indentation. I suggest to rewrite like this:
while (SCANMGR_STAT_ACTIVE_GET(scanmgr_status) ||
(SCANMGR_STAT_WFIFOCNT_GET(scanmgr_status) > 0)) {or even
while (SCANMGR_STAT_ACTIVE_GET(scanmgr_status) ||
(SCANMGR_STAT_WFIFOCNT_GET(scanmgr_status) > 0)
) {arch/arm/cpu/armv7/socfpga/scan_manager.c line 39
Quoted 6 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +6
-0+ scanmgr_status =readl (&scan_manager_base->stat); + else + return SCAN_MGR_IO_SCAN_ENGINE_STATUS_ACTIVE; + } +return SCAN_MGR_IO_SCAN_ENGINE_STATUS_IDLE ; +}
You decrement the parameter "max_iter" in the loop - I guess this was intended to make sure this is not an endless loop. But there is no test anywhere for it becoming 0 or so - which makes the parameter unused. I guess this needs fixing?
arch/arm/cpu/armv7/socfpga/scan_manager.c line 69
Quoted 4 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +4
-0+if (SCAN_MGR_IO_SCAN_ENGINE_STATUS_IDLE + !=scan_mgr_io_scan_chain_engine_is_idle ( +MAX_WAITING_DELAY_IO_SCAN_ENGINE )) +return 1 ;
See above. This is not readable.
Blame yourself that you have such problems - why do you cose so long identifiers as "SCAN_MGR_IO_SCAN_ENGINE_STATUS_IDLE" or "scan_mgr_io_scan_chain_engine_is_idle" - when you cannot put two names on a single line without breaking the 80 character limit, you are doing something wrong.
arch/arm/cpu/armv7/socfpga/scan_manager.c line 115
Quoted 4 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +4
-0+if (SCAN_MGR_IO_SCAN_ENGINE_STATUS_IDLE + !=scan_mgr_io_scan_chain_engine_is_idle ( +MAX_WAITING_DELAY_IO_SCAN_ENGINE )) + goto error;
Same here. Fix the indentation.
Even better, fix these unwieldy names.
arch/arm/cpu/armv7/socfpga/scan_manager.c line 122
Quoted 2 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +2
-0+/* Final TDI_TDO packet if any */ +if (0 != io_scan_chain_data_residual) {
Actually I would prefer if you wrote all this in the natural order, i. e. as
if (io_scan_chain_data_residual != 0)
With != it's just a nuisance, but with < or > it requires the reader to think backwards which makes the code hard to read and increases the error rate.
arch/arm/cpu/armv7/socfpga/scan_manager.c line 136
Quoted 3 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +3
-0+ tdi_tdo_header =TDI_TDO_HEADER_FIRST_BYTE | + ((io_scan_chain_data_residual -1 ) + <<TDI_TDO_HEADER_SECOND_BYTE_SHIFT );
Again, this is hard to read. Please fix globally. Do not start a new line with an operation - put this in the previous line where it serves as a mark that the line will need a continuation.
arch/arm/cpu/armv7/socfpga/scan_manager.c line 150
Quoted 7 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +7
-0+for (i =0 ; i < io_program_iter; i++) +/* +* write remaining scan chain data into scan +* manager WFIFO with 4 bytes write +*/ +writel (iocsr_scan_chain[index + i], + &scan_manager_base->fifo_quad_byte);
Incorrect multiline comment style, fix the last line.
Second, even if checkpatch lats this pass, we don't. This is a multi-line statement (even without the comment), and as such it requires braces.
arch/arm/cpu/armv7/socfpga/scan_manager.c line 163
Quoted 8 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +8
-0+if (IO_SCAN_CHAIN_PAYLOAD_24BIT < residual) +/* +* write the last 4B scan chain data +* into scan manager WFIFO +*/ +writel (iocsr_scan_chain[index], + &scan_manager_base->fifo_quad_byte); +else {
Braces needed - first because it is multiline, second because the esle branch has braces.
arch/arm/cpu/armv7/socfpga/scan_manager.c line 176
Quoted 4 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +4
-0+for (i =0 ; i < residual; i +=8 ) +writel (((iocsr_scan_chain[index] >> i) + &IO_SCAN_CHAIN_BYTE_MASK ), + &scan_manager_base->fifo_single_byte);
Braces needed.
arch/arm/cpu/armv7/socfpga/scan_manager.c line 115
Quoted 4 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +4
-0+if (SCAN_MGR_IO_SCAN_ENGINE_STATUS_IDLE + !=scan_mgr_io_scan_chain_engine_is_idle ( +MAX_WAITING_DELAY_IO_SCAN_ENGINE )) + goto error;
fix indentation.,
arch/arm/cpu/armv7/socfpga/scan_manager.c line 75
Quoted 1 line
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +1
-0+#define IO_SCAN_CHAIN_128BIT_SHIFT (7)
Remove parens around simple values - please fix globally.
arch/arm/cpu/armv7/socfpga/scan_manager.c line 4
Quoted 6 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +5
-0+++ b/board/altera/socfpga/iocsr_config.h@@ -0,0 +1,17 @@ +/* +* Copyright Altera Corporation (C) 2012-2014. All rights reserved +* +* SPDX-License-Identifier: BSD-3-Clause
Why is this not under GPL? New code that gets added to U-Boot shall be GPL-2.0+
Best regards,
Wolfgang Denk
Signature · 4 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de Every solution breeds new problems.
PATCH v5 1/1 socfpga: Adding Scan Manager driver
Dear Wolfgang,
Quoted 91 lines · ZY - wd
Dear Chin Liang See,
Quoted 73 lines · In message <[email protected]> you wrote:
Scan Manager driver will be called to configure the IOCSR scan chain. This configuration will setup the IO buffer settings
Signed-off-by Chin Liang See <[email protected]>Cc Dinh Nguyen <[email protected]>Cc Wolfgang Denk <[email protected]>CC Pavel Machek <[email protected]>Cc Tom Rini <[email protected]>Cc Albert Aribaud <[email protected]>---
Changes for v5
- Removal of additional blank line
- Added comment for magic number
Changes for v4
- avoid code duplication by add goto error
- include underscore to variables name Changes for v3
- merge the handoff file and driver into single patch Changes for v2
- rebase with latest v2014.01-rc1--- arch/arm/cpu/armv7/socfpga/Makefile | 2 +- arch/arm/cpu/armv7/socfpga/scan_manager.c | 214 +++++++ arch/arm/cpu/armv7/socfpga/spl.c | 4 + arch/arm/include/asm/arch-socfpga/scan_manager.h | 96 +++ .../include/asm/arch-socfpga/socfpga_base_addrs.h | 1 + board/altera/socfpga/iocsr_config.c | 657 ++++++++++++++++++++ board/altera/socfpga/iocsr_config.h | 17 + include/configs/socfpga_cyclone5.h | 1 + 8 files changed, 991 insertions(+), 1 deletion(-) create mode 100644 arch/arm/cpu/armv7/socfpga/scan_manager.c create mode 100644 arch/arm/include/asm/arch-socfpga/scan_manager.h create mode 100644 board/altera/socfpga/iocsr_config.c create mode 100644 board/altera/socfpga/iocsr_config.harch/arm/cpu/armv7/socfpga/Makefile +1
-1@@ -9,4 +9,4 @@ obj-y := lowlevel_init.o obj-y += misc.o timer.o reset_manager.o system_manager.o -obj-$(CONFIG_SPL_BUILD) += spl.o freeze_controller.o +obj-$(CONFIG_SPL_BUILD) += spl.o freeze_controller.o scan_manager.oarch/arm/cpu/armv7/socfpga/scan_manager.c new file +22
-0@@ -0,0 +1,214 @@ +/* +* Copyright (C) 2013 Altera Corporation <www.altera.com> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/freeze_controller.h> +#include <asm/arch/scan_manager.h> + +DECLARE_GLOBAL_DATA_PTR ; + +static const struct socfpga_scan_manager *scan_manager_base = + (void *)(SOCFPGA_SCANMGR_ADDRESS ); +static const struct socfpga_freeze_controller *freeze_controller_base = + (void *)(SOCFPGA_SYSMGR_ADDRESS +SYSMGR_FRZCTRL_ADDRESS ); + +/* +* Function to check IO scan chain engine status and wait if the engine is +* is active. Poll the IO scan chain engine till maximum iteration reached. +*/ arch/arm/cpu/armv7/socfpga/scan_manager.c line 32
Quoted 10 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +10
-0+static inline uint32_t scan_mgr_io_scan_chain_engine_is_idle (uint32_t max_iter) +{ +uint32_t scanmgr_status; + + scanmgr_status =readl (&scan_manager_base->stat); + +/* Poll the engine until the scan engine is inactive */ +while (SCANMGR_STAT_ACTIVE_GET (scanmgr_status) + || (SCANMGR_STAT_WFIFOCNT_GET (scanmgr_status) >0 )) { + max_iter--;This is difficult to read due to unlucky indentation. I suggest to rewrite like this:
Quoted 9 lines
while (SCANMGR_STAT_ACTIVE_GET(scanmgr_status) || (SCANMGR_STAT_WFIFOCNT_GET(scanmgr_status) > 0)) {or even
while (SCANMGR_STAT_ACTIVE_GET(scanmgr_status) || (SCANMGR_STAT_WFIFOCNT_GET(scanmgr_status) > 0) ) {
Fixed
Quoted 11 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c line 39
Quoted 6 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +6
-0+ scanmgr_status =readl (&scan_manager_base->stat); + else + return SCAN_MGR_IO_SCAN_ENGINE_STATUS_ACTIVE; + } +return SCAN_MGR_IO_SCAN_ENGINE_STATUS_IDLE ; +}You decrement the parameter "
max_iter" in the loop - I guess this was intended to make sure this is not an endless loop. But there is no test anywhere for it becoming 0 or so - which makes the parameter unused. I guess this needs fixing?
Actually this is checked at later line of code where the function will exit if max_iter equal to zero or less.
Quoted 8 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c line 69
Quoted 5 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +4
-0+if (SCAN_MGR_IO_SCAN_ENGINE_STATUS_IDLE + !=scan_mgr_io_scan_chain_engine_is_idle ( +MAX_WAITING_DELAY_IO_SCAN_ENGINE )) +return 1 ;See above. This is not readable.
Quoted 5 lines
Blame yourself that you have such problems - why do you cose so long identifiers as "
SCAN_MGR_IO_SCAN_ENGINE_STATUS_IDLE" or "scan_mgr_io_scan_chain_engine_is_idle" - when you cannot put two names on a single line without breaking the 80 character limit, you are doing something wrong.
Actually the variables are generated by tools. But I agree that it create unnecessary length which make the code hard to read. With that, I fixed all these variables.
Quoted 9 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c line 115
Quoted 5 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +4
-0+if (SCAN_MGR_IO_SCAN_ENGINE_STATUS_IDLE + !=scan_mgr_io_scan_chain_engine_is_idle ( +MAX_WAITING_DELAY_IO_SCAN_ENGINE )) + goto error;Same here. Fix the indentation.
Even better, fix these unwieldy names.
Fixed
Quoted 7 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c line 122
Quoted 3 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +2
-0+/* Final TDI_TDO packet if any */ +if (0 != io_scan_chain_data_residual) {Actually I would prefer if you wrote all this in the natural order, i. e. as
Quoted 5 lines
if (io_scan_chain_data_residual != 0)With != it's just a nuisance, but with < or > it requires the reader to think backwards which makes the code hard to read and increases the error rate.
Fixed by simplifying it to if (io_scan_chain_data_residual)
Quoted 8 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c line 136
Quoted 4 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +3
-0+ tdi_tdo_header =TDI_TDO_HEADER_FIRST_BYTE | + ((io_scan_chain_data_residual -1 ) + <<TDI_TDO_HEADER_SECOND_BYTE_SHIFT );Again, this is hard to read. Please fix globally. Do not start a new line with an operation - put this in the previous line where it serves as a mark that the line will need a continuation.
Fixed
Quoted 10 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c line 150
Quoted 8 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +7
-0+for (i =0 ; i < io_program_iter; i++) +/* +* write remaining scan chain data into scan +* manager WFIFO with 4 bytes write +*/ +writel (iocsr_scan_chain[index + i], + &scan_manager_base->fifo_quad_byte);Incorrect multiline comment style, fix the last line.
Fixed
Quoted 4 lines
Second, even if checkpatch lats this pass, we don't. This is a multi-line statement (even without the comment), and as such it requires braces.
Yup, good to note this. Fixed
Quoted 12 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c line 163
Quoted 9 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +8
-0+if (IO_SCAN_CHAIN_PAYLOAD_24BIT < residual) +/* +* write the last 4B scan chain data +* into scan manager WFIFO +*/ +writel (iocsr_scan_chain[index], + &scan_manager_base->fifo_quad_byte); +else {Braces needed - first because it is multiline, second because the esle branch has braces.
Fixed
Quoted 7 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c line 176
Quoted 5 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +4
-0+for (i =0 ; i < residual; i +=8 ) +writel (((iocsr_scan_chain[index] >> i) + &IO_SCAN_CHAIN_BYTE_MASK ), + &scan_manager_base->fifo_single_byte);Braces needed.
Fixed
Quoted 7 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c line 115
Quoted 5 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +4
-0+if (SCAN_MGR_IO_SCAN_ENGINE_STATUS_IDLE + !=scan_mgr_io_scan_chain_engine_is_idle ( +MAX_WAITING_DELAY_IO_SCAN_ENGINE )) + goto error;fix indentation.,
Fixed
Quoted 5 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c line 75
Quoted 3 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +1
-0+#define IO_SCAN_CHAIN_128BIT_SHIFT (7)Remove parens around simple values - please fix globally.
Good to know this. Fixed
Quoted 10 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c line 4
Quoted 7 lines
arch/arm/cpu/armv7/socfpga/scan_manager.c new file +5
-0+++ b/board/altera/socfpga/iocsr_config.h@@ -0,0 +1,17 @@ +/* +* Copyright Altera Corporation (C) 2012-2014. All rights reserved +* +* SPDX-License-Identifier: BSD-3-Clause Why is this not under GPL? New code that gets added to U-Boot shall be GPL-2.0+
Actually this is tools generated which will be consumed by non GPL software too. This file doesn't contain any source but just array with values. Hope this is ok.
Quoted 6 lines
Best regards,
Wolfgang Denk