From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751553AbdF1Pab (ORCPT ); Wed, 28 Jun 2017 11:30:31 -0400 Received: from mail-he1eur01on0074.outbound.protection.outlook.com ([104.47.0.74]:8800 "EHLO EUR01-HE1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751492AbdF1PaY (ORCPT ); Wed, 28 Jun 2017 11:30:24 -0400 Authentication-Results: spf=pass (sender IP is 188.184.36.48) smtp.mailfrom=cern.ch; topic.nl; dkim=none (message not signed) header.d=none;topic.nl; dmarc=bestguesspass action=none header.from=cern.ch; Date: Wed, 28 Jun 2017 17:29:38 +0200 From: Tom Levens X-X-Sender: tlevens@lxplus022.cern.ch To: Guenter Roeck CC: Mike Looijmans , Tom Levens , , , , , , Subject: Re: [PATCH v2 3/3] hwmon: ltc2990: support all measurement modes In-Reply-To: <20170628150130.GC30968@roeck-us.net> Message-ID: References: <1479384616-12479-1-git-send-email-tom.levens@cern.ch> <1479384616-12479-3-git-send-email-tom.levens@cern.ch> <410de6c9-a13e-51f7-4d66-6f4e2537c574@roeck-us.net> <97eb089f-e0e2-1146-6e17-8f9f790433d8@topic.nl> <20170628150130.GC30968@roeck-us.net> User-Agent: Alpine 2.20 (LRH 67 2015-01-07) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="-1195621031-153106770-1498663783=:31209" X-Originating-IP: [188.184.89.69] X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:188.184.36.48;IPV:NLI;CTRY:CH;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(39450400003)(39850400002)(39840400002)(39400400002)(39410400002)(39860400002)(2980300002)(438002)(199003)(377424004)(24454002)(377454003)(252514010)(189002)(41446006)(5005980100005)(53416004)(356003)(189998001)(54356999)(76176999)(50986999)(5660300001)(106466001)(1720100001)(478600001)(66066001)(8676002)(93886004)(6116002)(74482002)(3846002)(6246003)(38730400002)(110136004)(7736002)(7636002)(2906002)(54906002)(5009310100001)(55016002)(6306002)(7696004)(8936002)(2476003)(83506001)(4001350100001)(84326002)(53546010)(6666003)(86362001)(229853002)(966005)(2950100002)(305945005)(6916009)(512874002)(15974865002)(4610100001)(4326008);DIR:OUT;SFP:1101;SCL:1;SRVR:AM3PR06MB516;H:cernmxgwlb4.cern.ch;FPR:;SPF:Pass;MLV:sfv;A:1;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;AM5EUR02FT014;1:3hdq9CjWupeEr7gK0+j248wwxAYOPscs0dQJla48F95gzDMO3q5xMLpr+PT8eVoHyzH8qziD2O1bWpzexDp3tTItoTdb6Lqt2tbvBylFvaZHigD0HM/lGKps0b0eAM2UmTJA4BVxkMJO6/0YOys+mA/u55ODobZmmeZebAlnvkFXvQA15n2l0mXmc4zT7sfHDwKRONeKGa4g7voMPx3yo240yUcmPDW5k7pciAbKA65zOs31UfzCUtW+wHlGKDdSjOJhot9c2QNjj0QvVT4g12apsMjHTxeJsc17516tzA7a0AoeaY+tj82H6Axy4ITnLP9PrSqnx9eXTcq9TF1nBtEvR0yNxInsYjyTvSobuEZjXmw9VjGyFXCYBZ2wuBLOkJXK2IpNpmTzZJhONiEopDJMvIGa1JUlHMkaYfWUewHuSJnXNxEjGBmpnp0m4mKLgndDJRQ3IaUfWqkjg8Ud8ZqTn+kjtcBYsf4QLNOiDPiwrf8by2Bm7VpnTqR5Up6/4UP0kH6MPo5dPxh07p34Dd4f/8ddydW6RErvru4LnkVv9JvXhSYK9bfVGH9HyewC9CzOuUIPmiHy4+qLVlueI80N17TVKU4cLctVqqeOLDm7MU56lk6ByYLa7qTFKYTKzXh4CmIQH2xVsy7d+VM4wt2YVLBQTMOQOmk63Jv37Sp2OozfDxoQsu34WW3x4udfU1v0F+SieCdiCzp/RiTSRDYVb4Zp6bKapafe0b/fbeyyR71PGGdQiLYilZCNIIL/mCLwo9zBoptk1LG+YMW54VBAi98jnm4pa9q7UPOBwUiFg6IayNes+MDZKGAPwaZmLgQiZNq5xq20JG8hlLlU3mDQ0WA+PFuvP90GzYu24oI3WLwsy8wt25/NQUFZyy0q0dRiUJBuclexNEnYHrhjueQQ2x6gL87mAGlJrmTD6F8Mu/3ylKgWt6Z1/uKJLUDZ X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: cef5300e-0535-46e9-dc2a-08d4be3a9685 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(300000500095)(300135000095)(300000501095)(300135300095)(22001)(300000502095)(300135100095)(8251501002)(2017030254075)(300000503095)(300135400095)(201703131423075)(201703031133081)(300000504095)(300135200095)(300000505095)(300135600095)(300000506095)(300135500095);SRVR:AM3PR06MB516; X-Microsoft-Exchange-Diagnostics: 1;AM3PR06MB516;3:FZ1O3MEolAtcpJZ3WM4Te3XKHN6KzUdLSE7vlYwjs3ep4z0iTQm6FzqR1xGD1NAiTqEVXBn/9byJRBaNP2LJV2Iv8VM+mrTkRtrHCxOO6IaqQ428IvqG3sylqCjDzVZY3se+XMXGYvlImJCZ3lGGiNlHf92rqvjhiABsFcLCq5RkM4Yvg1p+WYMe5+qdEJMOsYRYw8TANetNpLqbacrMCWTTzI+56T6EpiUF2lajcap/DAliifKF63kN/CP5z2qxwBIOCGVN9CJOE4QF8h8mDiQuG0ax4EHQGi2KllMpxwPxTvagWGlkEIpUqC+a59pcjDH3gu8U2tQXbBNcKlBtEKGLf2YVd+xer56UVwaZXUqJuTCneGYhY8GFyscvHh6vXh69LxLtII7vvaUvtm8cV00UAEpW7venNd6V+zPsyHPDrmXTsx5M/aK10H7TuMSKHltcG/iTFrx6GieC2OaNsUhYoTElk9mCoB8zFd40jIOcc0h8TjxOmj/UkXmKXV7TweG9jnI2L31IeWSRNav+Kcqrw6b1k5XLYFXB9j3holXUc/QTUmAu1HTvp8z7Xg/d7OnFnOVnIBNtkqNm65bNnlzGd7AM3y4SaVWl6dJtRy/Y0xRGwF1T+OVb/dxCvvpEBZQL49JMfFehDX299DyD3xdZNCuIVGe7CzlAXc9tDHJ8v1At45A5MyDJJamGeDvdWoV8s7EXYHTKxt8MwSjgLcDEbf1/s5g2TqO1BcD3A48Ub3I22RFHbkoRbF1JXvuSFvXo5z5KjfP68o50Rj669raBn/ud02hV0Kfhy7CCCCfU8YZl9/ygKwuVZ8qbDNXtKHBIh1lJsvsHAx1500A3KDm1QfOgTXRKRl4zIMBLAYa80v44BCBLuWuhVM9ULicny95QVdftoINEzdd/KFGXrQ== X-MS-TrafficTypeDiagnostic: AM3PR06MB516: X-Microsoft-Exchange-Diagnostics: 1;AM3PR06MB516;25:s6Q2sJXOMhIZoL1YULOoWtw+fkvnrBiYdBvDBoWPfmlVrjqMdDPQy0d20SJ1oENKHs6AKN0BNeoINCF9Gxs84hVnKRSfBjmzs3rec92ffiy/JSEQaVbyyx+SKbcFiEKfyjQmXWPUC/gQFw9PqeBF6SsqtYDhB7AK1lWqen5d8fEFeP484HtsOaCJEUFoA1vXd431o5aKGeqYg8s4rsl60m/756X5XcBaY3R5m6o/DVFwIO143ve1tOppQgDIbw6uLJTiofP0lEF9O5WdUnYhZ+poy/xfQVI6Iy5WXBnXFRfcXs8YMrHozcVJLUB0fZOjJ7oCKJyETmbNzxJZL6J0MdCbilRaRPP0ghe9FixHm4W9aWTKsaqc2kStOxq8ioTgmdh0F0oLP8zJeae2cVch320SC2IjpKg9GMkFL78h6DYoh+p+xAiJMumi854s6mRkVgQTWwZ/Fm6FVWD0Y+1Rv55YotfT+2ubXRK9gWGtRVCLSBxAoNg1KnLY6qvl+vAF7j1Eo/0bEZlU/wqd8KF7L0qdiPVw1hW8VXKmXDpC6juUTP8oH3WbsyhknQjq+itvbnW9LsjYiQcCwKenKi8eIa1BFwgYz21FJRVJKf4hSdmbcGn15gK/DFOEJXGxNubEBAkcgqBjIUUSeC23Ww4ZGLxbd19W8S/5npKzLZkdWz7eRe4szi+awhDN+6tYGVVZRSPKH1qlJD2dN4y4wPstDsRrOfSfmP2dFgt0u+wFuuEBiNTNY1xzN4O30Nu/bDEuT4++I3XIN8GCRkrmMvNirsPaDw2QQSDyKNk4wouCiyV7RmXZfIccdhrcLDwIBMrsFWAiwykyp1upogyzvky1InVdg0NWYafmjyN4yrIIARMh66D5h4uevM3dlfGY2TYvJs0SJM/2N5O22nnJCX5APQk+XKs+scIAZIZB6Lbm/f8= X-Microsoft-Exchange-Diagnostics: 1;AM3PR06MB516;31:i+ADuWD6+uzvNUnk+eO0WBCOERxnMNATF5+IWnj/Ys6cKjlnKCbMgZvyjLULiRojW6YWFhT2/CHeDY3mlUvEza12tip0I4jbZsKEAf33XDTMEK2piEGH4kh0rkrbaWoRAhPArTSy8ZSAFxjTXM/vg7ZmwLX/jmq2EL1vt5NuPzrR6s3qC0eVJaib721mXPWVUSoSUqIClzLl8IGJKrrw8840287XHLoHQLjhglw4yTSsZsaQbY+mvOJ0UrOwiQWwB+suley+rwIkF3GZ8U0cD71V+FGAcUPmsTInvcM9HTvXV+75MI5Ix7ZdB2rRZkphHXqjjPUwUb4XbOGof7bNhr9MZTGdw8LbmuPXGtyiBqJgxCaxEs03C9DJDbnK5WTfEULAQlbx/+AR7EvbwIpCo3Isdjowr8pvINEhvAdg5wotc1GnUhumoyZrC6sgYDcOUec4/EKH9ixmvp0voWoEVW6tmJhWCtrf0DvqRk2p4Z7vswh9eH9hG0Q3sn2TEq1GhrlS4S1VoBBv/2f7wss+sPktm10JWbzGAPctQabPNkD+YyE6/3oUn+zRd5dw2idk8nJ1+lt/tP2tC9egnR28t69PFF1v9WobscNb8z1cPHnD00is+0+TiGSgH3LFtiMweSqtxPFFq7wl6HeKOco07AlBupBeAcYJsbW7XmkRk5+N1MpCGhlm+lj+2o+cVAek X-Microsoft-Exchange-Diagnostics: 1;AM3PR06MB516;20:a0GQX8jX+CvxuzxusJV3tsoKa+KVfmY7GDaKwnDZbaYEQAYld4b6q0y9a+O9i/6yfjaZuikS3KJWSfaFhWPocXIVbz04ph1YtZd7mLUP3pRgIUMiaDOf638M7iprU/U/gC/1opRQxahSiFL1RIsPF8puzOai+a5Aj/k95buhAU/8fOevwfyMPDYNYy4B41BOPl7M6Lls+3auQfrW11VgX9fvpQURlRVjOjxQVR/FZ4nxpBSMBHrYcgAjaHjnVyzTbxCkPJf17miBk8eFpelx4ZEpGFNobRmjNA1IrH3F2G7GmOeuEr3aV1Knlah5z7/wNCKvx0qckxvA+Vv8nW0y4U3MDPnO5W4aaGC6FGri+FiIbIGdrivM2WpaB7Kj4jdYcVB0TXXKRYuAfApeXC9b7FHfGxp5ldLZDvRoG/7pfRMBgiRROjycytkl/NiPPhQQHtHhDhMZpk/tBDV+o2f31vBeOQLuJBUNThb+VUJpnpUUh7w4UCuXdoFOA/vAtYQ+ X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(20558992708506)(133145235818549)(72170088055959)(236129657087228)(48057245064654)(112613623882745)(5213294742642)(247924648384137); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(601004)(2401047)(5005006)(13016025)(8121501046)(13018025)(93006095)(93004095)(10201501046)(3002001)(100000703101)(100105400095)(6041248)(20161123564025)(20161123558100)(20161123562025)(201703131423075)(201702281529075)(201702281528075)(201703061421075)(201703061406153)(20161123555025)(20161123560025)(6072148)(100000704101)(100105200095)(100000705101)(100105500095);SRVR:AM3PR06MB516;BCL:0;PCL:0;RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095);SRVR:AM3PR06MB516; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;AM3PR06MB516;4:6bdGWD2T0OzZWkP7PcfKcAE4FD1VRwGkaMHRwUsnbPY?= =?us-ascii?Q?Vhza3xnI6awnOdgC4alfO40m9BlZmqJULpxC0Vt9rMjHB8n+uYZSGc9iyg4O?= =?us-ascii?Q?R2oIA66p5xoe4eqH4NfhiRJNlAR6pEj0MOt6XIbA2cyM6aUnNjs+APZkp3Mm?= =?us-ascii?Q?eu1RshKeEOTqU+HUW86CiIq1U6RBC6blz4F4lBzQKShbT5t2U7IAeo9uNERq?= =?us-ascii?Q?3APa32jqjiCNTirvuS2rzI7fTrGfWwiH08IWKKg6rtgTLiT3fjBzX+ElK1hi?= =?us-ascii?Q?RuPEnZwqc88l98zz6xVkk8YFDyUC7sZMfHE6TzNWsVgALqd/bZzN3EPGnyjh?= =?us-ascii?Q?1fX7jZ9Dw+QXSwjzfN4dlvaK5oFhLuCjn705xDHEq4IC90V3JfoFG1a5Fl3A?= =?us-ascii?Q?tBOLGSlzoB0nA4SmnHRLTXSyLYAIlNGcYoZeOiY6ZgCQSAWMP3S/Co1BPR2e?= =?us-ascii?Q?EDv4hFH/niVNkABogHMBjCs1x057t4CVqcS/Edlc5/EhprCT8TFMrea1YHid?= =?us-ascii?Q?mxVW5q7vSlcuU6eMJ6strS57kiNDWrRRcO3eHKQ8/6LXxNEMdwF+SkD1ErJR?= =?us-ascii?Q?aKO8o7B+GhxLCtbsljT1l2t6SILWYLhxCZKMGXUl9ZROqnP2p8EGneSMKjwM?= =?us-ascii?Q?WzmaW/syOfXC0KUfGOo3AC+77XpRZ1doiWhNDsjeRpwhrxmpjKySe8u7n1fh?= =?us-ascii?Q?jGBNGEhI7Fd+7k24xfEASxfxFtYg8opArM9auZhcupaArJtsANIH+j4g9jKN?= =?us-ascii?Q?0uz+rcZghSTLMLLezqORFKKC0KApkv2zKbR2SqNcfOCyzE6f5Q5qguxbbvW4?= =?us-ascii?Q?AQZC7orI9xAHp0BBfephHanYfzUaLMQuGYWITnhWoVmmalW4QUuW2Y2+yKPT?= =?us-ascii?Q?OD8nDYbuvBR5wMQxMVSptoVQj8G6LlCkQI/P0PrWJcIcGQsGL5YRfenZMQ5O?= =?us-ascii?Q?4FX/aR0dy/AsPE/MVsEdAxa30XdI1UOXALVRbuHTuqRSKhlP9pGwTuBtSa5n?= =?us-ascii?Q?ODGO6DCqDLLE+cVDx7v3LI6fv4qUmQSZXqXnMKKJjwvSUvpe/feZxGEy10lF?= =?us-ascii?Q?E6PWklo9mz2CUKRohOkzDHsGkYvH6C7E1MsUliAu2NSX4H5z75u5J8ZesuaA?= =?us-ascii?Q?5VEmQ9xTb6UATmXC0XPmWfUnh1MsuNB5cjuNOXWG6ANsV3o5PQNopukht/yC?= =?us-ascii?Q?Mz3B/wxAaKqvYLFbKUoDgh/b5WX+veIcne8BkgXLuqoP+TBEto6PeDGEv/br?= =?us-ascii?Q?MqLHPpp6M2Ws/s61E7YqxH3QkppRuua3yE8Bb4y8GxWwQLjBu7hPpL7/jNN9?= =?us-ascii?Q?0eJzL/TbZLfVsk78jNbQwDjiFX1lufzpyuaKeFrTc5qhRKdB4lntUDJ3gjOL?= =?us-ascii?Q?s5nElykLqifw0stC0hpGDrPguyf+DIVeKt1D+O8Rb6E8Ay+qIOPRMyek3z/n?= =?us-ascii?Q?taM2T9qxwNaNLDRLM0RDQ1fUJQxGx0v5MDfBfostXkxhYBBPFO3UssnZGAhE?= =?us-ascii?Q?NLeGtc+UVNxh9QT9Pwq2m4HXo0fha2cQ=3D?= X-Forefront-PRVS: 03524FBD26 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;AM3PR06MB516;23:+4AlrzmylG2mnfmV/ZXfc7OjWlRsbN+3kAB0ts4S8p?= =?us-ascii?Q?FX9eRCKUY+HuhcoibDFB0LlDwqQrpNIQDSOfa9bGZOgQaGCZ14nAGRmoaKkm?= =?us-ascii?Q?+dsKhKtcAI2OapGSyt4B7+8bgBnnmnmsRC2TgejSJc9UcnJu8jepbIuclALr?= =?us-ascii?Q?dTZ7kChbultZtaNy1FUKllpY2MWj8f7/fHNIPF3/OhghOLyxPgSSTYOhNugK?= =?us-ascii?Q?pXj+QXI1ehaBbqqS+WnXlqqzHy/2FbwMcRxFsL4/DjXOylVBtgy6KFl8ujVE?= =?us-ascii?Q?150tNaMlVkWs1UcAkZWI5apY5357zgETQpUlUu8mL8JC75uFMqDQQUKAWvQL?= =?us-ascii?Q?dmYLzjBKMdHeoOuLlWlaE6hZa1U+7GPmjTlzwbtxaDP/AMbfFmS9DYgEdmyr?= =?us-ascii?Q?tQb/MER8XePBg56+1MQnxeGGrQIzEy2Tjh5OCa/P6LpwDF4XxkVj3B05p+mo?= =?us-ascii?Q?KlTUh2NgsIpQ/0XMEnUCYw4t4yfBzBdSeKBi23ganisQMtmaBnxUzt3SUYib?= =?us-ascii?Q?p1fYORXz971HnVXBky1DRcw5vaaR4BIKdtU0+/LT27ehgutgvK7mT/HdS/pq?= =?us-ascii?Q?8uZeOITzkTYYWkIxfKERo3TSSP8nEsiVmUpv7+gI9jGjpODwxOm7kahLBd/a?= =?us-ascii?Q?ZF7FXioPnGR8zc8NJU1R8dzSZ7zRzb2Xy7Y6IRS8H0MFLdW05yudYT6q/wiO?= =?us-ascii?Q?xcojMcuXWJxf18CUt+bmC8mD1y/3YlOzTlvrnhk6VL/lNps3b2L+O54Pi9UW?= =?us-ascii?Q?9dq7ZW7t645S2NhWDfFf9jC4T8BiaofW17t3D4o8E8qHxPzoQPOmk2ZwyVva?= =?us-ascii?Q?ucPuFKdZIupt0H9CLbHHh4Qs49qtdLqDR/21+OCizJz14ldIhjkxu4aitEBH?= =?us-ascii?Q?+OEmUk94wX830Vpg5rz4ptVQyWMflOHfrM16UkgHGIfyhfQ5E9djx6t6PvPv?= =?us-ascii?Q?Lt+P7WBtE6wsBT5l4sG0kr+7BPJuudOYwMWwLgqcJOj0KrskGfD4E3Fs/aPD?= =?us-ascii?Q?iD0TPyrr+4PP6hK/MzyeOX/4c1UPqIJNhaAGzEAH7sKMb8MxzdFjEI0kmqnK?= =?us-ascii?Q?B9PQVryC59eflWAlQksHISVxx8dTJhbwqv2FjAoH9QG/nzEv/qG/m2ULIOzM?= =?us-ascii?Q?M4W+Us2UFX8Ue6vUoUwzl7R13sI/DtTweq0ogO2NEzhwG5iX1t6EIZYMgrRb?= =?us-ascii?Q?W9VhiqG3k0CT0Mk9PGD9FNqDOPTQsUvj27Dk116or126wINtI1GIXmv2r/9i?= =?us-ascii?Q?qWYhlMXAN+vIhS8eWXyovpQuLY9He0u1TAXGulR/ZhgIlrCYUA2cnR346FeV?= =?us-ascii?Q?VzrPH8UPU5C1M1TNQVEKekDUTkDrIkXG3PcXZ9O6ObY4H2v1qf0gF85vYCEE?= =?us-ascii?Q?Z1vb6Lr7lj8Ze2Ba6e7rXA3Y6ZikpYjGpekgN3CbzSxfbrezG5T1jnuPtlnY?= =?us-ascii?Q?h5WrOHvCASO3r1SRIslzPZmaGbR7gbH0oaN7Ozky7bTrgQyaMsFMoCn3e0lt?= =?us-ascii?Q?1Ix39VbgAmaA=3D=3D?= X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;AM3PR06MB516;6:3lyLy40UU91g6iHdKCX7rR+txc+oFrJaCb4yJnx/DIb?= =?us-ascii?Q?63c1yraBcjXesqHiqXZ8MOcGcrRwlQ8FXOR4nPAJvJJCrvR2cVm0W5o3TECH?= =?us-ascii?Q?VNw/puvAWnu11hfEub4dELlW+EUZyVZBdfDWHdn6Vzi34CBvqCIelVUJubFf?= =?us-ascii?Q?vdBlmD742ivJERviUBBHK/Utwfm0bn2HeA7cZK8/dKj1OUXj5D3kc/OeYgas?= =?us-ascii?Q?M7mPfUToLO6RsN1Rp1vzPLtBOdb8q5Xs1BJTRcHHTU6JO19Hq2uDOZsvb5u+?= =?us-ascii?Q?7HQ5i2yOJiTCg4Ya13pACC7K0i8pmDgVj6I0ckKu90wEwE4ZAXrYwZECkZeE?= =?us-ascii?Q?llEwieshHMlF6+nphyYoRzsNWRq1xq1oIoufBXM3h9sixfNSyTfiI/+1LoV9?= =?us-ascii?Q?m7CHmVJrLCLqAX5hYEIaewxH+T67UQyhFJioRzYys+hohWmWSWBjAoSgB8lm?= =?us-ascii?Q?QlepYtFOamWavwmI1iWD0w7e3f6oP1xsTfjC54CsjzcQPYCaQK7KPcLe+1MC?= =?us-ascii?Q?8nXGDCsWfyQOI/f8cjHt4VlSLGDAj5t+GUB5+KGrrwW/jeSe8RA3Idq9qaVE?= =?us-ascii?Q?anfTn0Mom6rfXYR0KKZCH+XQAP8TXyYnS3syCiOpFVklV0zVTXXUJ72oPjAS?= =?us-ascii?Q?GlC384VgHJY3y4nAW1NbyrF+A8a9cd66X0x6RsiloXvJn6QN21mC0gg1xZzx?= =?us-ascii?Q?+IYaUNo9UefJYUrAGMceVi6xcbe3FY+2SDWjNlOzREWAXcWEhQjBNBDxgnYd?= =?us-ascii?Q?NLAVG0O4Pp+8Ii2ijItrOqdgo+aiD8gsmQ+h7Wigo7fnhpkmV/NZws/96wWK?= =?us-ascii?Q?64bTw03WDPZcfZR3PzOqHNNOvf2AIaRHqHHUEFsMWg51G61QjALsmlFXDijO?= =?us-ascii?Q?mPYG0qzcE+GdeERg3NVB2f4zqrUqu+BFxPfIgib3JD1EvWV0OZnDe3MDVnM9?= =?us-ascii?Q?VZ70wq8Ak670/8wfusPn99sZ7TmQdPePwYV1b9GMhnmh9TsqLH+DqI5zMTOA?= =?us-ascii?Q?=3D?= X-Microsoft-Exchange-Diagnostics: 1;AM3PR06MB516;5:TuDxImo+DqN6Gc+WyHIKRWZ5NKbGh/6iJEN6cQ6gcXcNm5ZKazRxOdDKI19vYAxRELW59I0ZiNeuv4pI0gliBTKm2a+YMg9T7zigccpbe8CAIwIbQeuwTqakYdntQXLU/zdw98G+tnIMzQaqIt5WJJqcgn7155qN8bV4nxcjpzjn5Jy8aXuvhQDUc3L4QLqLtgJ6NsXIhMYBaxDLzOV8aPOyhC2dA9Y3T7UbjNU1p58fE1Oj1kf6izWlpwml2goPgc+tUjZDH4OQhsnPQk9eJtgHd6A7A33sUwuMf09HReS2BGCyol+dN012GRqelxLQ3MHUevzyY4JIUA9HHe4zbRvSXA6DzCn2xBgNhm71o8DlPErtuj2LErPGxRLjvCShyM5btMskQLdCaXO+2ypzt3XP6M4YM3zsgGTSMb9NJP1Ng0PATZqlr7S3tYUJ8o1RLleVyNwIWACBXbTyUAL5K3EAg9qrK1+0eOrEOYcHyONtxKnalyFZ6+qzr7DaBtBY;24:DhgGD8V5zHJexhXaY6GqZ080IzDPa58X/JmufkfZZksVtBkMog2ux9PcYBp/mil9V3KspiA+faBD3xANaD9wEFyid2sEyyzCuOEJ5WiR1oY= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;AM3PR06MB516;7:PQ5CxmpCBDFUj8qIFRcKcw/RgIjRnbo2FuXmK0aiC65pOXdK7HDIsbefzah4XAisPutvaBP1UyXfXQlHnZLIsS66ZmMVl3sw9nPkF+pKOMyKIVtrEit7YLuH+GGCGe87Sef8gxhVqO/KpuJCJuApTicGN42VXQ1lMWKzlSRYgBgv5cL+w0Bj5rLvN84etFKN5U8oFJqNavDCRiYRHv+wav8Vr2dqNGKzgj++QiqmdLN3zy6YR/Dl98R7sNz/OXKP9ggPp4WdhBkacAqSXfnELUR5q7JcFc+hHnOm/o90jyt5a4DEIiG+uM7KBhszPzgwhOGo3XC8GqHb7J7uSt9XkWvkeINBB6ke6BH3f62sVPY32FgsnGtJm/kNsk1lJ1NiQdAfo+Y8Gj4+CLvuIiml4dXzRWf18PHQzhB58aFeIvw39k2GRttT+3OWeaTwzG3AdLFgJtpGxLFarK8GMvKecXLQnl1BUpQibf6w9pjOhpyV3jul2vBq2RXkNo3PDf9TXAvBMO/OC1z3rJ0PWqykZsmNtWklj/6C80la31Sl4QILOfAqR1aE94aNerDlmBU/UramiM6kmqBiL7H6hlMuaPVYDQ/Myqgwa0CGUDCsl2mrmS8AVuVXo7XCsNftu1h1Eyf0B7jqqu5sRUZjuMlP5L342Xn7RzU+AeyisDqIXICW5RDJMSrpCg6mp8G12s+u98ZaMEuNzvsnmIb/CcTR5oDOnU8UZbVoIk1K6zxz21q4Bewut6+E//UUuGf1/ouoYxP1OJdgPen5l3ZPtHXHXNujfqsqbdscksT5KMOrJR0= X-OriginatorOrg: cern.ch X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 Jun 2017 15:30:20.6318 (UTC) X-MS-Exchange-CrossTenant-Id: c80d3499-4a40-4a8c-986e-abce017d6b19 X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=c80d3499-4a40-4a8c-986e-abce017d6b19;Ip=[188.184.36.48];Helo=[cernmxgwlb4.cern.ch] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM3PR06MB516 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org ---1195621031-153106770-1498663783=:31209 Content-Type: text/plain; charset="UTF-8"; format=flowed Content-Transfer-Encoding: 8BIT On Wed, 28 Jun 2017, Guenter Roeck wrote: > On Wed, Jun 28, 2017 at 04:24:03PM +0200, Mike Looijmans wrote: >> On 17-11-16 17:56, Guenter Roeck wrote: >>> On 11/17/2016 04:10 AM, Tom Levens wrote: >>>> Updated version of the ltc2990 driver which supports all measurement >>>> modes available in the chip. The mode can be set through a devicetree >>>> attribute. >>> >>> property >>> >>>> >>>> Signed-off-by: Tom Levens >>>> --- >>>> >>>> Changes since v1: >>>> * Refactored value conversion (patch 1/3) >>>> * Split the devicetree binding into separate patch (patch 2/3) >>>> * Specifying an invalid mode now returns -EINVAL, previously this >>>> only issued a warning and used the default value >>>> * Removed the "mode" sysfs attribute, as the mode of the chip is >>>> hardware specific and should not be user configurable. This allows much >>>> simpler code as a result. >>>> >>>> Documentation/hwmon/ltc2990 | 24 ++++--- >>>> drivers/hwmon/Kconfig | 7 +-- >>>> drivers/hwmon/ltc2990.c | 167 ++++++++++++++++++++++++++++++++++++------- >>>> 3 files changed, 159 insertions(+), 39 deletions(-) >>>> >>>> diff --git a/Documentation/hwmon/ltc2990 b/Documentation/hwmon/ltc2990 >>>> index c25211e..3ed68f6 100644 >>>> --- a/Documentation/hwmon/ltc2990 >>>> +++ b/Documentation/hwmon/ltc2990 >>>> @@ -8,6 +8,7 @@ Supported chips: >>>> Datasheet: http://www.linear.com/product/ltc2990 >>>> >>>> Author: Mike Looijmans >>>> + Tom Levens >>>> >>>> >>>> Description >>>> @@ -16,10 +17,8 @@ Description >>>> LTC2990 is a Quad I2C Voltage, Current and Temperature Monitor. >>>> The chip's inputs can measure 4 voltages, or two inputs together (1+2 and 3+4) >>>> can be combined to measure a differential voltage, which is typically used to >>>> -measure current through a series resistor, or a temperature. >>>> - >>>> -This driver currently uses the 2x differential mode only. In order to support >>>> -other modes, the driver will need to be expanded. >>>> +measure current through a series resistor, or a temperature with an external >>>> +diode. >>>> >>>> >>>> Usage Notes >>>> @@ -32,12 +31,19 @@ devices explicitly. >>>> Sysfs attributes >>>> ---------------- >>>> >>>> +in0_input Voltage at Vcc pin in millivolt (range 2.5V to 5V) >>>> +temp1_input Internal chip temperature in millidegrees Celcius >>>> + >>>> +A subset of the following attributes are visible, depending on the measurement >>>> +mode of the chip. >>>> + >>>> +in[1-4]_input Voltage at V[1-4] pin in millivolt >>>> +temp2_input External temperature sensor TR1 in millidegrees Celcius >>>> +temp3_input External temperature sensor TR2 in millidegrees Celcius >>>> +curr1_input Current in mA across V1-V2 assuming a 1mOhm sense resistor >>>> +curr2_input Current in mA across V3-V4 assuming a 1mOhm sense resistor >>>> + >>>> The "curr*_input" measurements actually report the voltage drop across the >>>> input pins in microvolts. This is equivalent to the current through a 1mOhm >>>> sense resistor. Divide the reported value by the actual sense resistor value >>>> in mOhm to get the actual value. >>>> - >>>> -in0_input Voltage at Vcc pin in millivolt (range 2.5V to 5V) >>>> -temp1_input Internal chip temperature in millidegrees Celcius >>>> -curr1_input Current in mA across v1-v2 assuming a 1mOhm sense resistor. >>>> -curr2_input Current in mA across v3-v4 assuming a 1mOhm sense resistor. >>>> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig >>>> index 45cef3d..f7096ca 100644 >>>> --- a/drivers/hwmon/Kconfig >>>> +++ b/drivers/hwmon/Kconfig >>>> @@ -699,15 +699,12 @@ config SENSORS_LTC2945 >>>> be called ltc2945. >>>> >>>> config SENSORS_LTC2990 >>>> - tristate "Linear Technology LTC2990 (current monitoring mode only)" >>>> + tristate "Linear Technology LTC2990" >>>> depends on I2C >>>> help >>>> If you say yes here you get support for Linear Technology LTC2990 >>>> I2C System Monitor. The LTC2990 supports a combination of voltage, >>>> - current and temperature monitoring, but in addition to the Vcc supply >>>> - voltage and chip temperature, this driver currently only supports >>>> - reading two currents by measuring two differential voltages across >>>> - series resistors. >>>> + current and temperature monitoring. >>>> >>>> This driver can also be built as a module. If so, the module will >>>> be called ltc2990. >>>> diff --git a/drivers/hwmon/ltc2990.c b/drivers/hwmon/ltc2990.c >>>> index 0ec4102..e8d36f5 100644 >>>> --- a/drivers/hwmon/ltc2990.c >>>> +++ b/drivers/hwmon/ltc2990.c >>>> @@ -6,11 +6,7 @@ >>>> * >>>> * License: GPLv2 >>>> * >>>> - * This driver assumes the chip is wired as a dual current monitor, and >>>> - * reports the voltage drop across two series resistors. It also reports >>>> - * the chip's internal temperature and Vcc power supply voltage. >>>> - * >>>> - * Value conversion refactored >>>> + * Value conversion refactored and support for all measurement modes added >>>> * by Tom Levens >>>> */ >>>> >>>> @@ -21,6 +17,7 @@ >>>> #include >>>> #include >>>> #include >>>> +#include >>>> >>>> #define LTC2990_STATUS 0x00 >>>> #define LTC2990_CONTROL 0x01 >>>> @@ -35,32 +32,96 @@ >>>> #define LTC2990_CONTROL_KELVIN BIT(7) >>>> #define LTC2990_CONTROL_SINGLE BIT(6) >>>> #define LTC2990_CONTROL_MEASURE_ALL (0x3 << 3) >>>> -#define LTC2990_CONTROL_MODE_CURRENT 0x06 >>>> -#define LTC2990_CONTROL_MODE_VOLTAGE 0x07 >>>> +#define LTC2990_CONTROL_MODE_DEFAULT 0x06 >>> >>> I think LTC2990_CONTROL_MODE_CURRENT was better - it describes the actual mode. >>> Changing the define to _DEFAULT does not really improve code readability. >>> >>>> +#define LTC2990_CONTROL_MODE_MAX 0x07 >>>> + >>>> +#define LTC2990_IN0 BIT(0) >>>> +#define LTC2990_IN1 BIT(1) >>>> +#define LTC2990_IN2 BIT(2) >>>> +#define LTC2990_IN3 BIT(3) >>>> +#define LTC2990_IN4 BIT(4) >>>> +#define LTC2990_CURR1 BIT(5) >>>> +#define LTC2990_CURR2 BIT(6) >>>> +#define LTC2990_TEMP1 BIT(7) >>>> +#define LTC2990_TEMP2 BIT(8) >>>> +#define LTC2990_TEMP3 BIT(9) >>>> + >>>> +static const int ltc2990_attrs_ena[] = { >>>> + LTC2990_IN1 | LTC2990_IN2 | LTC2990_TEMP3, >>>> + LTC2990_CURR1 | LTC2990_TEMP3, >>>> + LTC2990_CURR1 | LTC2990_IN3 | LTC2990_IN4, >>>> + LTC2990_TEMP2 | LTC2990_IN3 | LTC2990_IN4, >>>> + LTC2990_TEMP2 | LTC2990_CURR2, >>>> + LTC2990_TEMP2 | LTC2990_TEMP3, >>>> + LTC2990_CURR1 | LTC2990_CURR2, >>>> + LTC2990_IN1 | LTC2990_IN2 | LTC2990_IN3 | LTC2990_IN4 >>>> +}; >>>> + >>>> +struct ltc2990_data { >>>> + struct i2c_client *i2c; >>>> + u32 mode; >>>> +}; >>>> >>>> /* Return the converted value from the given register in uV or mC */ >>>> -static int ltc2990_get_value(struct i2c_client *i2c, u8 reg, s32 *result) >>>> +static int ltc2990_get_value(struct i2c_client *i2c, int index, s32 *result) >>>> { >>>> s32 val; >>>> + u8 reg; >>>> + >>>> + switch (index) { >>>> + case LTC2990_IN0: >>>> + reg = LTC2990_VCC_MSB; >>>> + break; >>>> + case LTC2990_IN1: >>>> + case LTC2990_CURR1: >>>> + case LTC2990_TEMP2: >>>> + reg = LTC2990_V1_MSB; >>>> + break; >>>> + case LTC2990_IN2: >>>> + reg = LTC2990_V2_MSB; >>>> + break; >>>> + case LTC2990_IN3: >>>> + case LTC2990_CURR2: >>>> + case LTC2990_TEMP3: >>>> + reg = LTC2990_V3_MSB; >>>> + break; >>>> + case LTC2990_IN4: >>>> + reg = LTC2990_V4_MSB; >>>> + break; >>>> + case LTC2990_TEMP1: >>>> + reg = LTC2990_TINT_MSB; >>>> + break; >>>> + default: >>>> + return -EINVAL; >>>> + } >>>> >>>> val = i2c_smbus_read_word_swapped(i2c, reg); >>>> if (unlikely(val < 0)) >>>> return val; >>>> >>>> - switch (reg) { >>>> - case LTC2990_TINT_MSB: >>>> - /* internal temp, 0.0625 degrees/LSB, 13-bit */ >>>> + switch (index) { >>>> + case LTC2990_TEMP1: >>>> + case LTC2990_TEMP2: >>>> + case LTC2990_TEMP3: >>>> + /* temp, 0.0625 degrees/LSB, 13-bit */ >>>> *result = sign_extend32(val, 12) * 1000 / 16; >>>> break; >>>> - case LTC2990_V1_MSB: >>>> - case LTC2990_V3_MSB: >>>> - /* Vx-Vy, 19.42uV/LSB. Depends on mode. */ >>>> + case LTC2990_CURR1: >>>> + case LTC2990_CURR2: >>>> + /* Vx-Vy, 19.42uV/LSB */ >>>> *result = sign_extend32(val, 14) * 1942 / 100; >>>> break; >>>> - case LTC2990_VCC_MSB: >>>> - /* Vcc, 305.18μV/LSB, 2.5V offset */ >>>> + case LTC2990_IN0: >>>> + /* Vcc, 305.18uV/LSB, 2.5V offset */ >>>> *result = sign_extend32(val, 14) * 30518 / (100 * 1000) + 2500; >>>> break; >>>> + case LTC2990_IN1: >>>> + case LTC2990_IN2: >>>> + case LTC2990_IN3: >>>> + case LTC2990_IN4: >>>> + /* Vx: 305.18uV/LSB */ >>>> + *result = sign_extend32(val, 14) * 30518 / (100 * 1000); >>>> + break; >>>> default: >>>> return -EINVAL; /* won't happen, keep compiler happy */ >>>> } >>>> @@ -72,48 +133,104 @@ static ssize_t ltc2990_show_value(struct device *dev, >>>> struct device_attribute *da, char *buf) >>>> { >>>> struct sensor_device_attribute *attr = to_sensor_dev_attr(da); >>>> + struct ltc2990_data *data = dev_get_drvdata(dev); >>>> s32 value; >>>> int ret; >>>> >>>> - ret = ltc2990_get_value(dev_get_drvdata(dev), attr->index, &value); >>>> + ret = ltc2990_get_value(data->i2c, attr->index, &value); >>>> if (unlikely(ret < 0)) >>>> return ret; >>>> >>>> return snprintf(buf, PAGE_SIZE, "%d\n", value); >>>> } >>>> >>>> +static umode_t ltc2990_attrs_visible(struct kobject *kobj, >>>> + struct attribute *a, int n) >>>> +{ >>>> + struct device *dev = container_of(kobj, struct device, kobj); >>>> + struct ltc2990_data *data = dev_get_drvdata(dev); >>>> + struct device_attribute *da = >>>> + container_of(a, struct device_attribute, attr); >>>> + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); >>>> + >>>> + if (attr->index == LTC2990_TEMP1 || >>>> + attr->index == LTC2990_IN0 || >>>> + attr->index & ltc2990_attrs_ena[data->mode]) >>>> + return a->mode; >>>> + else >>> >>> Unnecessary else >>> >>>> + return 0; >>>> +} >>>> + >>>> static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ltc2990_show_value, NULL, >>>> - LTC2990_TINT_MSB); >>>> + LTC2990_TEMP1); >>>> +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, ltc2990_show_value, NULL, >>>> + LTC2990_TEMP2); >>>> +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, ltc2990_show_value, NULL, >>>> + LTC2990_TEMP3); >>>> static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, ltc2990_show_value, NULL, >>>> - LTC2990_V1_MSB); >>>> + LTC2990_CURR1); >>>> static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, ltc2990_show_value, NULL, >>>> - LTC2990_V3_MSB); >>>> + LTC2990_CURR2); >>>> static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, ltc2990_show_value, NULL, >>>> - LTC2990_VCC_MSB); >>>> + LTC2990_IN0); >>>> +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, ltc2990_show_value, NULL, >>>> + LTC2990_IN1); >>>> +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, ltc2990_show_value, NULL, >>>> + LTC2990_IN2); >>>> +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, ltc2990_show_value, NULL, >>>> + LTC2990_IN3); >>>> +static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, ltc2990_show_value, NULL, >>>> + LTC2990_IN4); >>>> >>>> static struct attribute *ltc2990_attrs[] = { >>>> &sensor_dev_attr_temp1_input.dev_attr.attr, >>>> + &sensor_dev_attr_temp2_input.dev_attr.attr, >>>> + &sensor_dev_attr_temp3_input.dev_attr.attr, >>>> &sensor_dev_attr_curr1_input.dev_attr.attr, >>>> &sensor_dev_attr_curr2_input.dev_attr.attr, >>>> &sensor_dev_attr_in0_input.dev_attr.attr, >>>> + &sensor_dev_attr_in1_input.dev_attr.attr, >>>> + &sensor_dev_attr_in2_input.dev_attr.attr, >>>> + &sensor_dev_attr_in3_input.dev_attr.attr, >>>> + &sensor_dev_attr_in4_input.dev_attr.attr, >>>> NULL, >>>> }; >>>> -ATTRIBUTE_GROUPS(ltc2990); >>>> + >>>> +static const struct attribute_group ltc2990_group = { >>>> + .attrs = ltc2990_attrs, >>>> + .is_visible = ltc2990_attrs_visible, >>>> +}; >>>> +__ATTRIBUTE_GROUPS(ltc2990); >>>> >>>> static int ltc2990_i2c_probe(struct i2c_client *i2c, >>>> const struct i2c_device_id *id) >>>> { >>>> int ret; >>>> struct device *hwmon_dev; >>>> + struct ltc2990_data *data; >>>> + struct device_node *of_node = i2c->dev.of_node; >>>> >>>> if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA | >>>> I2C_FUNC_SMBUS_WORD_DATA)) >>>> return -ENODEV; >>>> >>>> - /* Setup continuous mode, current monitor */ >>>> + data = devm_kzalloc(&i2c->dev, sizeof(struct ltc2990_data), GFP_KERNEL); >>>> + if (unlikely(!data)) >>>> + return -ENOMEM; >>>> + data->i2c = i2c; >>>> + >>>> + if (!of_node || of_property_read_u32(of_node, "lltc,mode", &data->mode)) >>>> + data->mode = LTC2990_CONTROL_MODE_DEFAULT; >>> >>> Iam arguing with myself if we should still do this or if we should read the mode >>> from the chip instead if it isn't provided (after all, it may have been >>> initialized >>> by the BIOS/ROMMON). >>> >>> Mike, would that break your application, or can you specify the mode in >>> devicetree ? >> >> OMFG, I just spent half the day implementing the exact same thing, and only >> after sumbmitting it, I stumbled upon this thread. I must be getting old. >> >> A well, seems I implemented things a bit differently, so you get to pick and >> choose which patch was better. >> > > As I just replied to your patch, there is no question here. The compatible > statement refers to chip compatibility; one can not use it to also provide > configuration information. > >> Whatever happened to this patch though? It didn't make it to mainline, >> otherwise I'd have found it sooner... >> > I'll have to look it up, but I guess I didn't get an updated version. As far as I remember I had a working V3 of this patch, but it is entirely possible that it was never submitted as I have been busy with other projects recently. I'll dig it out and check that it is complete. Cheers, > Guenter > >> >>> >>> Thanks, >>> Guenter >>> >>>> + >>>> + if (data->mode > LTC2990_CONTROL_MODE_MAX) { >>>> + dev_err(&i2c->dev, "Error: Invalid mode %d.\n", data->mode); >>>> + return -EINVAL; >>>> + } >>>> + >>>> + /* Setup continuous mode */ >>>> ret = i2c_smbus_write_byte_data(i2c, LTC2990_CONTROL, >>>> LTC2990_CONTROL_MEASURE_ALL | >>>> - LTC2990_CONTROL_MODE_CURRENT); >>>> + data->mode); >>>> if (ret < 0) { >>>> dev_err(&i2c->dev, "Error: Failed to set control mode.\n"); >>>> return ret; >>>> @@ -127,7 +244,7 @@ static int ltc2990_i2c_probe(struct i2c_client *i2c, >>>> >>>> hwmon_dev = devm_hwmon_device_register_with_groups(&i2c->dev, >>>> i2c->name, >>>> - i2c, >>>> + data, >>>> ltc2990_groups); >>>> >>>> return PTR_ERR_OR_ZERO(hwmon_dev); >>>> >>> >> >> >> >> Kind regards, >> >> Mike Looijmans >> System Expert >> >> TOPIC Products >> Materiaalweg 4, NL-5681 RJ Best >> Postbus 440, NL-5680 AK Best >> Telefoon: +31 (0) 499 33 69 79 >> E-mail: mike.looijmans@topicproducts.com >> Website: www.topicproducts.com >> >> Please consider the environment before printing this e-mail >> >> >> > ---1195621031-153106770-1498663783=:31209--