From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751412AbcGLT0r (ORCPT ); Tue, 12 Jul 2016 15:26:47 -0400 Received: from mail-by2nam03on0063.outbound.protection.outlook.com ([104.47.42.63]:12788 "EHLO NAM03-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1750885AbcGLT0n (ORCPT ); Tue, 12 Jul 2016 15:26:43 -0400 X-Greylist: delayed 896 seconds by postgrey-1.27 at vger.kernel.org; Tue, 12 Jul 2016 15:26:42 EDT Authentication-Results: spf=fail (sender IP is 66.35.236.227) smtp.mailfrom=opensource.altera.com; lists.infradead.org; dkim=pass (signature was verified) header.d=altera.onmicrosoft.com;lists.infradead.org; dmarc=none action=none header.from=opensource.altera.com; Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=atull@opensource.altera.com; From: Alan Tull To: Rob Herring CC: Mark Rutland , Moritz Fischer , Ian Campbell , Dinh Nguyen , , , , , Alan Tull Subject: [PATCH 2/2] fpga-manager: Add Socfpga Arria10 support Date: Tue, 12 Jul 2016 14:07:09 -0500 Message-ID: <20160712190709.5964-3-atull@opensource.altera.com> X-Mailer: git-send-email 2.9.1 In-Reply-To: <20160712190709.5964-1-atull@opensource.altera.com> References: <20160712190709.5964-1-atull@opensource.altera.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [64.129.157.38] X-ClientProxiedBy: SN1PR17CA0084.namprd17.prod.outlook.com (10.163.3.180) To BLUPR03MB1508.namprd03.prod.outlook.com (10.163.81.26) X-MS-Office365-Filtering-Correlation-Id: 98b5dd8a-e75d-480f-ae80-08d3aa885edc X-Microsoft-Exchange-Diagnostics-untrusted: 1;BLUPR03MB1508;2:vT5SvNpjSKXrFdMZiG+bYQ7BN1QsMSPV6gIuZ0lNAOhODZmmTi6SNlyYwpbp4SqV9UZIfPVXQvMmwDeGRBqb7YNHQvJ6WksYSUukoyVOSZ9VWmjGUE3u1XOBIJK29NRLG5uD8GGQRmsNbqf+f9HHs7woqOUa6Abo3ft0ojXS0HExkFHXFYEllCn+DUqEPd/2;3:KmbOmuiNbIjz0Rmm97UJmpFijUpE9/dZsQx98Wcg7WddaYXMB8I33awBT9UALnUTdURHeXMeBNxMrOcGb/xNwL4ZgP3Qx6xd/Ic+wzNc6Q2bHjMoVMINLNRRGtG5IsVY X-Microsoft-Antispam-Untrusted: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BLUPR03MB1508; X-Microsoft-Exchange-Diagnostics-untrusted: 1;BLUPR03MB1508;25:hu/ZWBt980pFr7b+nbKGJjnExBEz0Wvp8xTB1tLb9ExxCdeqMhv5Vj7z/k6HBBoPpxewJ4Q8KOD/3ux4GMQbAip6iVgjitlzdWAGiruQK25V6NJUhC9t3EbYb8Zdp7qlU6R6wK+stK4iV1fVui65laXhW7eaAFbG1MSArzBV7y8rS09jMo/FolrnuirQKcqCzTW7/NxYpru+wxPpHFytm+5+WTJXkeCC1ZzlSH2rwYyQjuKfFPSu+gCBwSF21GUbd84lXpLJOdywQlhKg+Lqhqussp34WIG2YjrYtjcUpZYLGwsigYT2GZOKKuSkkwM2kl/AfDv+U7Mikb+usDbSfYpUBg4l9JA4LjKvzurGMg9gJUwWsVB0Ofwd/KT6c3JzZ7W9GneL8nA0UUnwYc8dwQXxnaIDYcG+1aNWEcrumtMMOSqzusw4vrvDPfegl9vnu55/N6oUcXEir7NkSyMmP4sQf/z3wP4j7iXvSrsNqriJMUd5Iv05iBRYpIgjgsKXAjjYWq8PhqswdtGZnbUtx4L0X1qQFz4dZggzGFLSoCu7DG/mhP97lpbAi8tl5aYNfzpt84LmwxasMjKy+4KwbmMxb+mRjN+DBZzL2P6Zi5N2rMe1b2wqcfEslhkLjhiGX6h/lvtR4aaRrbhNAOi9jvEZD8nyaYqy2Oa9+Z91X7t66Zlj3sQdEun6SYZh++GXYHi3rdfwZxabi6ppctanXq8DRr7vRCREJE3YxlSmRyjRwjjwz/l72OJMvsJDOm5JU5bVFb0NlWpi69aB5bS0Iqh0hAQznyePec9MLeHw4LA= X-Microsoft-Exchange-Diagnostics-untrusted: 1;BLUPR03MB1508;31:YY1DECIK13JIWu+L6Hu3zPw/aRtomZrQueAk1qkU+ueT03O+Quv3BkAzNuYZulY+0KxNO2qIAQ2CwQYTAS6Mq/0QxQveshZLPSEa6pcqFTVJ6eRTGJiWK7DMkVIdcrfm1I6XaGEfJ8L4HuxNn8NQQeptPmGtBhmVPMeq8ftzMoDzBT6/2+TAaX2d0GIfSuDGmO+F+OVXnyLhi1iS7sTiAw==;20:kY0nh5S9j8kSxFM9b0ILRCRtwnK9j46T9g4cu37ac/d4pKZ/Kcj5JAwWQV4qPSoO4lYGRxH13e/4WqFxOA5yr4fFlGkbdcnLBzYlFoKlQWNoc1sUMsSj9+fJeP60TmuP1SNhvsx8rhstdvYezsSWkBtN8GtIZCNZmsXLmee/s6U=;4:Qrm3gapXKv4qqW0RCeCZZanRxybCYQuVg+LkdoMN3J1OuAckUiIWQL1uwc+qno18JbYfIrmN39D6jJrPzZFa5UPwNfTUQ3nbdTT7dtzn22YQtvdRQcmjeCR3aEXhBlDR1s2Q5skrbwO4DXqxnEPLJvkU9Dn7jMTL8VsiZ1BDmCuIhDJIysaWxOb9oT/KT5UkkQPBULswIDLu9auvBotDhLAotW1zXqek5KTap3s32Wcm9lVYYk02i96v2yyxtOohPm6G7fneHMfeW8BgDPTSDE5BYed2hZ9G0KctaeNA1fNtx52t9wxZT8LQMVmqpvHyqiiDIwj6uAvmLMpzq3Rmn3rGgaEGYCnjgdGTEpVkuJQqNg4iMq9mnCSUlGL5VfWAbC3xd8EnA/9RrHY/9/58U6Dd3qUZ7oM6wm21CT9v8kPngYQptEqkpXJtycs7jA+Z9E8CsqH7E9yXJ8BEDctY9fcwYcHk6i+PZM7Xxfe95PtbGhYvtt98GwRhBMu9+6+5 X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(250305191791016)(22074186197030)(80048183373757);UriScan:(250305191791016)(22074186197030)(80048183373757); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(2401047)(5005006)(8121501046)(10201501046)(3002001)(6055026);SRVR:BLUPR03MB1508;BCL:0;PCL:0;RULEID:;SRVR:BLUPR03MB1508;BCL:0;PCL:0;RULEID:(601004)(2401047)(13023025)(13024025)(13018025)(13015025)(13017025)(5005006)(8121501046)(10201501046)(3002001)(6055026);SRVR:BY1PR0301MB0901;BCL:0;PCL:0;RULEID:;SRVR:BY1PR0301MB0901; X-Forefront-PRVS: 0001227049 X-Forefront-Antispam-Report-Untrusted: SFV:NSPM;SFS:(10009020)(4630300001)(6009001)(7916002)(189002)(199003)(101416001)(19580395003)(42186005)(7736002)(48376002)(92566002)(7846002)(189998001)(305945005)(107886002)(81166006)(586003)(3846002)(50466002)(15975445007)(19580405001)(81156014)(575784001)(4001430100002)(2950100001)(86362001)(105586002)(110136002)(50986999)(229853001)(76176999)(77096005)(5003940100001)(47776003)(33646002)(106356001)(69596002)(66066001)(8676002)(4326007)(2906002)(53416004)(6116002)(1076002)(68736007)(50226002)(97736004)(2004002);DIR:OUT;SFP:1101;SCL:1;SRVR:BLUPR03MB1508;H:linuxheads99.altera.com;FPR:;SPF:None;PTR:InfoNoRecords;MX:1;A:0;LANG:en; X-Microsoft-Exchange-Diagnostics-untrusted: =?us-ascii?Q?1;BLUPR03MB1508;23:hGDe2ls+CxDVl6CqB+Xz2XZY8S4ygy/A6BGpIZ7uY?= =?us-ascii?Q?Vn1jU5r9xD46IqKnw02nldUYYQJx9fOIXwI/R0Vuomccmr2NjhHnn0vq0MAt?= =?us-ascii?Q?/NkrnlLBSYHthJfYbJwCjYepiTXeV1gZmVQFV/62eEObAO5by/USP0bFg56x?= =?us-ascii?Q?AuJ3qafwnN1Nkg/xKz0nFp4c2cppn4YdSz+NlOgI2YfQAUtvVLXeZlK8IoaG?= =?us-ascii?Q?tnarOBmEhNTg2v9ruoiTJ+Hdca6e1u0cHF9U2o/5Frfbefst8zOGWZLpXxE1?= =?us-ascii?Q?H79/L+dPEBvIj796rKwYtVWtlfFIr8WMYivE5vZ50meKM4IGVaz5Z8eIJsd2?= =?us-ascii?Q?XuNJNuRqPGEaFRce0k2M4heVksFqtKr5qKrwgLSWayQ0qQnYiice511DInl0?= =?us-ascii?Q?w/Xm4mMnmXOkPRYs0FrGxupkex/C1K/CKkFFeddsVCN+HcFBV4msV4KcRx+h?= =?us-ascii?Q?B/HjHx6RW3ZoxDEKkGrVJS9Xn/ki8W3BaYxYsPpEocqlvIBQQtxDxFQWsQxO?= =?us-ascii?Q?he2Q/vdiv4RMVfYE3nXCDSBy1RfBjCkGQY8vKvoPZba5iqHh4o8o7fv6eWAV?= =?us-ascii?Q?tEGm5HfToJ/KiQy5L0DDCPx6ceuw52HB6trgqyGEhFZs0M/kFI36agOMekD4?= =?us-ascii?Q?3kaBTgK5noo0E+oM9pOn+OtTcPFSvUmqSX9nRhTrpsfFfUA+khf9Q98YWyxb?= =?us-ascii?Q?wgm5ay+BOFvN27XHQXUuqfoZ9ylbkrJhU26JaKS1IEJLY+WMWxuhmN0TI1Ti?= =?us-ascii?Q?6FZfXXI4tnlky+jpFvosxpeqyKwlsEvmh98bWzPXjngKiNh1g82LedFy0nle?= =?us-ascii?Q?t9+HxpHQVHIDw1Zc3xtqINbPKMZ7VoMb1ZIuLILU73YbNtly2vfCYheZieMQ?= =?us-ascii?Q?2GlaLk0DqMuTbzmUNWqcmbP1zT0/oLKkAbdqhhzkN/e71rjq6vq1z3qCCUkl?= =?us-ascii?Q?t5HXHdGWvCPSIBv7QhC/+TxDI34hDxaqRRAJhadhkFhhTMPxqtfh3TFCLfRy?= =?us-ascii?Q?DC6B+OY2+dSHBD8NCpl1c1KT/ImnDsv/zZMMH0DJpUlD2KQmEjGJqNrUZP8p?= =?us-ascii?Q?kjsJkkbWXKOSVKesiYazGEeKuLRdVaNfjHxvU+j7/TrwZ/SiZGukmiZkS4lW?= =?us-ascii?Q?d512R66vk3pox5G1xllStX7TY0fVUEgwpdnIbobDsZd9fdGW4eFgxm8c8weO?= =?us-ascii?Q?rzzuwY8+NtsTJw=3D?= X-Microsoft-Exchange-Diagnostics-untrusted: 1;BLUPR03MB1508;6:t7nY3cGTG32FL/eYymPSkpKQe25LgDpR5ZDc8gKTp6e8/CmMjfuHruQr6KLzn/HQevT9IdBa8UdiSHJis9piHJFBd8qNRDZ5WMt32MtFBYhcE0vMrvzBMKa+BlWlyQsjuKGbQbdnnhuxp9ZLKrjt6v07q9o9nqqTlzsvDvLRmjBRsto/6Cg9ItnRp9AafN1yWKJE3xlXw72WYkoy/8NBWOGMA66dvQDPrsXq4qhKB5W4/qWjVm0Dn0WQvwNqU/K+tfNhMdZfJ9D6/E3b46wgMYU2QxMYc5hsm1i+GtdorSwAU5wecWsvg3cUgby8dJcseuZsgbmnYy7EuHl48bpKHw==;5:4unCQfMSKCRRwhI9IlsSLkrDB3gfLN25YlHzuUdb9og+WzG/3/yODhxaWTZLxT+BCXkax+a1PsL2tddiRMnCYHHlGClF+QaPI3gBIyyAFN5u2JstFz7GOaUs9PKSFPmQRmWFObVLJpnwVmWfNYHp5A==;24:8OqqoLo4qPmsVnm3Wn4saYDinFwQUrK8D8ZG6yvxBld473WuFDxvlqFY6to9zQw3B/vci9bQrtuPIOkmgP6fzShX+0dxTazVkX8zTNRlMtw=;7:WENX1ALAiUvBetj9YOjsPF/pSZC0AlykzRUd+gdqBr0G+d6IqAnN3Hg2faqvVsNQmrkNJS+ZxmGoNnt8kPg3vyglVdokUfsMozhTjf+ZJzD/tHay0rDoWcG+iFTOm4heu/nvvHCLdjM1ns6tG+6eq6Bp4lcvv7DNGe0oFPbnKqyl5dBTNKFd/v89JJOin4T/i3aGfDy3QO+SfPwHyh9lQg5m1cwKjnuLLA/SIUYq7z/c50GHOPpC4PJi6+q7zL4V SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics-untrusted: 1;BLUPR03MB1508;20:TjWJRpC46kozYi8yUA8ujFqAjNFPZ+BA7oie1AtyIi9CgHmv/3H7tQZX331hTmk0MmavswX0v6tD8lUwnSqwBz2JrLGqDaU/XV8GSL7ejlAqU71hXWwT95M/sbn/AjooR7KCbfRWhjjsah649hM71d69rtkYQvV/6OBO3/qfkCg= X-MS-Exchange-Transport-CrossTenantHeadersStamped: BLUPR03MB1508 X-EOPAttributedMessage: 0 X-MS-Exchange-Transport-CrossTenantHeadersStripped: BL2FFO11OLC012.protection.gbl X-MS-Office365-Filtering-HT: Tenant X-Forefront-Antispam-Report: CIP:66.35.236.227;IPV:NLI;CTRY:US;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(7916002)(2980300002)(1110001)(1109001)(339900001)(189002)(199003)(4001430100002)(11100500001)(66066001)(48376002)(50466002)(6806005)(956001)(47776003)(16796002)(81156014)(5003940100001)(305945005)(4326007)(8676002)(2906002)(7846002)(1076002)(7736002)(50226002)(110136002)(586003)(107886002)(189998001)(356003)(92566002)(68736007)(6116002)(81166006)(3846002)(33646002)(85426001)(77096005)(15975445007)(97736004)(87936001)(8936002)(229853001)(6070500001)(3720700001)(575784001)(86362001)(76176999)(106466001)(53416004)(19580405001)(19580395003)(2950100001)(105606002)(50986999)(7099028)(2004002);DIR:OUT;SFP:1101;SCL:1;SRVR:BY1PR0301MB0901;H:sj-itexedge03.altera.priv.altera.com;FPR:;SPF:Fail;PTR:InfoDomainNonexistent;MX:1;A:0;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;BL2FFO11OLC012;1:M0gID4qoVb+H4aiGjNGNVwpryEPGmkefCJAfGsflz2Qe/2kpb/WKx5vusb9BScNgYRU8HGkab1hnIeZ64he9TbhnVD5cfJ+o8O6HSZPQGHK5/CnMdiODYclL455zq8Jtq77+z0yRhdNORkKpd0BszZviW4CZeKV20N/3r9uYznHsxhehbRupt2Qi6QYysXFQC1XqXTsJxh/2rM6DpMbha6/AC6UdIw+rBxicmEfb5K8gQvkPOeY+vJ1twAu5To9AOwo8WTGK8bO2opoUH2QZftEU8LabJat+xBG35KpDo/6IAPObv2GatftfiKcQxmwKcLyQ0X6YlZBkAOjyiwNUIf+ZbGRMfCldzLfAyDP2gVC6lv+ToEUtJBhEpNmfE3+j3SDCLsbZ7DVgEujL3wODWDjBc98K2SEui5S7mzmwFVOvVRS3+AU/HIt88IEqHSolmNcCtQ0m82tkpSqoSL6MzUPvKh+mtaiHpeygcQfX6u/dpMBWA3YVR4VM+PhprbkaStnnufwFT6NvKS43WNjaJaAuCd0gSoskW0x3MbWCZgptB1VoEGldexpDkNM8wdvETMOF5lXLw3+S6SBLZ8H++g== X-Microsoft-Exchange-Diagnostics: 1;BY1PR0301MB0901;2:oV0iv7msNIj9uqfJg7lc4seGjmqQL/H+DJaK34ATDpa2chsYhk9IfsGxDub4/Qp726Ae0sbCOAZHtFdsmofuGwQg8c08DCOM+bSEDcBWTQiFqdljD+VFjCL8GWn/rVKZcdV2IqJ/fu8RfnrDXgOhjQz5a1NyfB7aSW8GKWwQWD1PMVLAnl29rtEDolsUvVJ6;3:qgoSG3oyvgcfYPcFZDi2bkRiytOzyEkmoncOjtpcHgtkl7WLmwbFyevqGwnhY5cG6M/vg12dOE+86cOwnYlv6oFyBSmRjU0nd17SaU/sw0LObNu9DQPzEdqt4ssjKm8g7k9GyLux6DtWYuQYhHJb1HoZWhe1qkMfsLiKGk1oveu/d2GhE0KAi7kWW4BXtkZM3SI7FclQ0C8VfuNMZX1XkUpURgMYpKntHGokwmdrzEVN4jENRmQf6Dkdpo5hSN4y X-DkimResult-Test: Passed X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(3001016);SRVR:BY1PR0301MB0901; X-Microsoft-Exchange-Diagnostics: 1;BY1PR0301MB0901;25:p4jL/KXYPoKIxwLT8qAKkLLsp0Ngc47zyFWCL9UT240Y93AOmWIFj80I7Ct0tLCVq6WMqjbl9vMOA37IZgzuusiI1vMzsu550NtgrsAVB3tV4mNYp0oiP3Wkbbkg9oZlrWW3s+YHn95P1K6Zs+ZF3TB+B+iNBWcX9Y1u8tzXA6pU0R4M1cyGB0tLA9dvEnCg0tAEaFL8VZyqyy0WTvLqFg/YzitSalc2DI+ZC1JAbnKZqaAgOuF1ryQVfQLeH3lWdX+KiP+2mcZ19DbRiczVNrrJFO9X9VOTiXeXnGMNOmUtXw3RGdiGy8pqGH6mxcTNt/cT8CohEuSd3cNNrpIuWTQMDYOTnMDHPo6LB+NT2dVShwKCFFRFEqoXKR/aKsJWnrGplqZ+43qfLErQpevQAqQGkX/z15EiOVDhhbyCzKeP+IYLZwusEXVOlGWi1sIypI+guID+a9HUPBNaGQ62yJQEct/vcRcrOmc8cMiq1AZC5z+YfA1AiY2MD6nx+pLUMr+MkzdXMBvipP/GRqDXaDu3aOnesWe/Q2d3df7cCzSPOIC1gKi0sTxH/CT1Ej7XaKcEuyhJGOjPckNSpc+/gx8Xr+KuSMbuWMW+ukvVKGQezYTzBbYEGz+AtcQEwFYvkbSJUZq7yNfSpCbnmuxMxLIaTAH5Gd+prgfI/wyrX1yPAwU2S04u0443d4FgbS6PqR4FttKzpthj5okxt0rqrUn22WGdIBpX3p/JevrYQTx5irTSrdvS3nE1vuNr8bOhPxvAdDiNM1dgVO3Wb4MunDydZAqOE44wf1q6ptoCv3ojkN4Qcb9RFGIvm3DTUcxW X-Microsoft-Exchange-Diagnostics: 1;BY1PR0301MB0901;31:/tjaGDM/ikH1+ua+ZR+k55Lk1yd7NhdagaIPNOssLckmA4tXgwSew8MwYiHO2Mc1uasBRdv8EXACKBR9+djKnUqW12r2g30jutg3a24GPRNMQYltPgbzv82oazF9p5LKFiJJRfihiJWyrPLdeCrjWsftq9pFtfKmu+yhB0luf/UK//6Yk2rQC8rmFUlA/xMtTN/Dm05p2KuOvW2SGpCXuw==;20:DItZzEpqdqHICQXkGhl0ZPZYav+0jMPJg4T2rmsublb9R7gqE74BE2B+21rUw+Op32G1lZUBFaHLQGFiP+KWdi5THCPnP43YOofokZEJcNpCVQ98IX9USpcTz3Oym7YmS4lahttSnbWYy4V30CWdr2kTNnNRDVPeB0ATEl9HYBM= X-Microsoft-Exchange-Diagnostics: 1;BY1PR0301MB0901;4:5vOP35+TXR3IWdaBc/tFng3k5K5+uQ2zRcVRfV1lOvrnLLV1SjcI5SXp0cOYAZ8XcxSOZRcIEck3nbUpmXQlhzcIQhUHmymjF7MDzz/z8/f5K2lAg0XtOizcZUw9O3qCsz3OFMdAtD5W6G8DfEYqGPRjekbz78SZxJlkUt4C1e7Rblsu+AGpdpAQV/pmUGSG/gpns2SO7Wf8oNoED7t99OE3k4AqgnpCXgENVCm6yPDEZCk5QRq7K6TBf4nr9oGP929qiTG8MpbSbxDPmlgsB9AUAF8vloIHWXHG9FFG+4S2pmKTaXK/k5GpE82zUwCpBDjBAOcN4L9v3dyuP7x0uStf2SDoKRKWwXo2IpFJJMggEHqSWba+GtaHXCtxs2m096YDWvOvCw29GUFeaaQrgM872s6BE4Q2mY7njSjCFRT7xahey6Vo5PrXoG+ftgRRlgAYtn51FnyuXR78MD5KjqsVR3w8ejaj28C1cRX0ezsAj3tfb6G4AtCaSr99RyQs8P5c7PvFI1DXzUQIalYDKqUe8JerNj6fJFCCcKRhDjwPDhpDrKURyS0P1g5pmv9F7qsUBHUnrnh4POFp28qyEw== X-Forefront-PRVS: 0001227049 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BY1PR0301MB0901;23:AWFrpf4Rmuy0jier5aa7NjmrnEIMU3/5GHZ5szK?= =?us-ascii?Q?yRh3OyETMcirGCtqQMjOZ6fjnhhCtTSuMKvEqlqIdJn1qAQY5hHtaHjPP2mY?= =?us-ascii?Q?CYa9KJvLAtk4BDnFd+9/QJDoc3s2BqRuEjkz5EmvXOEEUHTAdSzD7g/ZxsRa?= =?us-ascii?Q?pChpqTp0nfUEYFELG8VDAJTub/rynKS8WrS9zF//QYf7G9PF1UtLCtdMIIsM?= =?us-ascii?Q?wR5KpVPDKOioxQPU/P3g2pcgqoiYJj7aXXLDRjaZ5zFCt34aBrgxc55WpB3f?= =?us-ascii?Q?atOBcv79Ycfh2D6EhlVHeUjoaphFJmhfNA4izGnR1yQUxTuo2cm5oJTpD0+8?= =?us-ascii?Q?L+5uSmVr7W36GxJolAFTy7iaYIP858lZtjmPvdgI4uA13Bbk27WW8TNxbtSb?= =?us-ascii?Q?IVDtb1ovUZJMI1OMXoLgj4JnPcmjNCbjNLsKZYv8j78UISh8sKLFrZk79UNV?= =?us-ascii?Q?oXPbs6mAPvs9vIb3ATKCwTmpwzoVtgAFXeG+V2YpOdYtroyvzpQRUHdMkjGL?= =?us-ascii?Q?WBP3zcMx9QXmt6EeRPyh1NVJGWxuLzhumQkZhsst1Hi+RD0blXoUnm/e9JjI?= =?us-ascii?Q?UalU9sZ64YlXapvtkmhHpxq2FkoeHhhAl0zQJasnNgddNfknX1e0a3FBL8uS?= =?us-ascii?Q?EgGvDD2Qdz53TXovmf1ur78+TB5FTT0kZ5hRMSx9phwcTF1V+CZvfp4cj8zg?= =?us-ascii?Q?JXDCalY8oc3HVF2vJKJjUnv9Zy//cDvNkX2//6lyIh/WKQWnfE413ht8+shc?= =?us-ascii?Q?gdZe/3P8YEMuiOhy6GRW441HilC8ri/j8vg1sNgeCVrRNqgT6Q3jEpkwlxxA?= =?us-ascii?Q?pS3gh/6J0vnQdEkbtg0EfjqBaJyJkRWZn8lxCKczQs6gja0nv9BUtcLt7wTw?= =?us-ascii?Q?fSuZJOXI//22jsdfq0QWdbS0CANlhXu6QDle35XbD8ILWk4t9HPMQf4zWeLk?= =?us-ascii?Q?oNVyHXW+DZdAFZ3pyANdG11SUYpd/qbQwWqrKW5b39f9E4xp0s6FYAMPY5u9?= =?us-ascii?Q?uZXB3QrEgfisiT6UIWYEP4gduDX1umlXdT3VsLXKaoGcbXGPO4UGNg3srEbY?= =?us-ascii?Q?O3rcNPui0ohQ3F+ryudqB7uXoZSXYlV6/DuUKVr1rEOAKbAEdKl3Vt47VYsj?= =?us-ascii?Q?Y9o/Ok2tWXCr2gxBKvk4uK1VAN4/aO52sxZHmjPAFjL50BZpSA+/A1/URkqq?= =?us-ascii?Q?ecMICFeG56YzMDohf0iq1hI/h6RNJNyAJrcV/XNdLJEYJwvKsLu/aQ8bSYy2?= =?us-ascii?Q?3LivX0wXt+QWOeBQijGkEh0o7pq29AwPRR3ckUzSmSa8gWbALYhSNj5ObISv?= =?us-ascii?Q?hMBii6VOnQ7mc8NWwEtXIQjeZFoBUpUVTohd0KH0uJ5SSQUtHD517i+fWc76?= =?us-ascii?Q?B3WQ0DxKYnDRbBmZ/qWaYN1OHRywnOFFgs6Wgo+8UxpHaT6Kt?= X-Microsoft-Exchange-Diagnostics: 1;BY1PR0301MB0901;6:SSk9It1nVQHDNAhIDdCX0NXnpafpsKHWGMP+LHmy4IBf0uDmYeAPjo4XJzAUsIWl7qAGscrwfhG3URUTu9bmH13iANAOLSnM5ie3QwHuzybNRFAmc6WlCYgVcVjBeikfsfgs85JbWqOl3dlfDaKlFjjHWMR+Sf1WDt9xFscA+ftk6uEN3M69IsNdlpGPn1FdEfcctG5SieJnsKeIj1d/qfyXCLVrfg+lbVntSnvCKSL9XEKJKkJL/dQt3L5ee3wx8UbV2u9LmR/QJe78b/IjfhzJA96UYUScs/4WEyhrAEPJ6zwwHCIDp7AJz+V+uj++i5QNXYv5rbf6O4N03H882w==;5:gLevhgvAUIkhtooXkWk6jVmI2qo8J76QoXO8945w3bY8fBzyUwd3PRVIQkCrSWsK/FIhppc9gJFDV1ohTdqwjBJ5okx42c9vd7nhKn6sOFV81+pd07X7ujYnLW9VcwHBrYqHONc23IjTbRug3h1+IQ==;24:fQIx5qLRaO5UmxGHpKR6hf0qHV2UEOq6kslb8968zjVr0w7FaegMq2SlYIIeqf/Gy4ibsdG5YG+/AlIpTiKyM1+BkBMVp9yJiqHi2GBvs0M=;7:N6IQXOR0jfwt0yoanrUKwvsDhcOD8gP1iWCYcnhlVxw6bH5yBR9AN/EQQtqHXzkAFYMsyoRzj2oPqjfrwUJT8GQuufFscbQQXkGsrxGk+TRvW2k7GYZF2iMjhgSCUgGX204KIyU3j5+iDB8H6vvoB68y2gibQqpSUH/7t1dPQdDq++UK6ECc8745jAlRb8C9RWfn83R0E6KK7c0FypegBQ== X-Microsoft-Exchange-Diagnostics: 1;BY1PR0301MB0901;20:AinaBrNvMU0LQ5f3aF8b0Ap1efPY83GQi78qE/TY4jFI8g0Pp9wz0Z+ef1TP22R9khJWvftj5b8CLKdaLZoYbPPOkVPU8+XRJVDHAJBcqIuXsxe7BkR1Bp2l71DotdcOWWn5L9n4df42r7AoScP9AffIWqqZUM9RtM+nQ9FtKD0= X-OriginatorOrg: opensource.altera.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Jul 2016 19:11:46.4119 (UTC) X-MS-Exchange-CrossTenant-Id: fbd72e03-d4a5-4110-adce-614d51f2077a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=fbd72e03-d4a5-4110-adce-614d51f2077a;Ip=[66.35.236.227];Helo=[sj-itexedge03.altera.priv.altera.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY1PR0301MB0901 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add low level driver to support reprogramming FPGAs for Altera SoCFPGA Arria10. Signed-off-by: Alan Tull --- drivers/fpga/Kconfig | 6 + drivers/fpga/Makefile | 1 + drivers/fpga/socfpga-a10.c | 573 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 580 insertions(+) create mode 100644 drivers/fpga/socfpga-a10.c diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index b346166..1a18623 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -26,6 +26,12 @@ config FPGA_MGR_SOCFPGA help FPGA manager driver support for Altera SOCFPGA. +config FPGA_MGR_SOCFPGA_A10 + tristate "Altera SoCFPGA Arria10" + depends on ARCH_SOCFPGA + help + FPGA manager driver support for Altera Arria10 SoCFPGA. + config FPGA_MGR_ZYNQ_FPGA tristate "Xilinx Zynq FPGA" depends on HAS_DMA diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index e658436..0375cbd 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_FPGA) += fpga-mgr.o # FPGA Manager Drivers obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o +obj-$(CONFIG_FPGA_MGR_SOCFPGA_A10) += socfpga-a10.o obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o # FPGA Bridge Drivers diff --git a/drivers/fpga/socfpga-a10.c b/drivers/fpga/socfpga-a10.c new file mode 100644 index 0000000..63e0c5b --- /dev/null +++ b/drivers/fpga/socfpga-a10.c @@ -0,0 +1,573 @@ +/* + * FPGA Manager Driver for Altera Arria10 SoCFPGA + * + * Copyright (C) 2015-2016 Altera Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define A10_FPGAMGR_DCLKCNT_OFST 0x08 +#define A10_FPGAMGR_DCLKSTAT_OFST 0x0c +#define A10_FPGAMGR_IMGCFG_CTL_00_OFST 0x70 +#define A10_FPGAMGR_IMGCFG_CTL_01_OFST 0x74 +#define A10_FPGAMGR_IMGCFG_CTL_02_OFST 0x78 +#define A10_FPGAMGR_IMGCFG_STAT_OFST 0x80 + +#define A10_FPGAMGR_DCLKSTAT_DCLKDONE BIT(0) + +#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NCONFIG BIT(0) +#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NSTATUS BIT(1) +#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_CONDONE BIT(2) +#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG BIT(8) +#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_NSTATUS_OE BIT(16) +#define A10_FPGAMGR_IMGCFG_CTL_00_S2F_CONDONE_OE BIT(24) + +#define A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG BIT(0) +#define A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST BIT(16) +#define A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE BIT(24) + +#define A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL BIT(0) +#define A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_MASK (BIT(16) | BIT(17)) +#define A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SHIFT 16 +#define A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH BIT(24) +#define A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SHIFT 24 + +#define A10_FPGAMGR_IMGCFG_STAT_F2S_CRC_ERROR BIT(0) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_EARLY_USERMODE BIT(1) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_USERMODE BIT(2) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN BIT(4) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN BIT(6) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_PR_READY BIT(9) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_PR_DONE BIT(10) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_PR_ERROR BIT(11) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_NCONFIG_PIN BIT(12) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_MASK (BIT(16) | BIT(17) | BIT(18)) +#define A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_SHIFT 16 + +/* FPGA CD Ratio Value */ +#define CDRATIO_x1 0x0 +#define CDRATIO_x2 0x1 +#define CDRATIO_x4 0x2 +#define CDRATIO_x8 0x3 + +/* Configuration width 16/32 bit */ +#define CFGWDTH_32 1 +#define CFGWDTH_16 0 + +/* + * struct a10_fpga_priv - private data for fpga manager + * @regmap: regmap for register access + * @fpga_data_addr: iomap for single address data register to FPGA + * @clk: clock + */ +struct a10_fpga_priv { + struct regmap *regmap; + void __iomem *fpga_data_addr; + struct clk *clk; +}; + +static bool socfpga_a10_fpga_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case A10_FPGAMGR_DCLKCNT_OFST: + case A10_FPGAMGR_DCLKSTAT_OFST: + case A10_FPGAMGR_IMGCFG_CTL_00_OFST: + case A10_FPGAMGR_IMGCFG_CTL_01_OFST: + case A10_FPGAMGR_IMGCFG_CTL_02_OFST: + return true; + } + return false; +} + +static bool socfpga_a10_fpga_readable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case A10_FPGAMGR_DCLKCNT_OFST: + case A10_FPGAMGR_DCLKSTAT_OFST: + case A10_FPGAMGR_IMGCFG_CTL_00_OFST: + case A10_FPGAMGR_IMGCFG_CTL_01_OFST: + case A10_FPGAMGR_IMGCFG_CTL_02_OFST: + case A10_FPGAMGR_IMGCFG_STAT_OFST: + return true; + } + return false; +} + +static const struct regmap_config socfpga_a10_fpga_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .writeable_reg = socfpga_a10_fpga_writeable_reg, + .readable_reg = socfpga_a10_fpga_readable_reg, + .max_register = A10_FPGAMGR_IMGCFG_STAT_OFST, + .cache_type = REGCACHE_NONE, +}; + +/* + * from the register map description of cdratio in imgcfg_ctrl_02: + * Normal Configuration : 32bit Passive Parallel + * Partial Reconfiguration : 16bit Passive Parallel + */ +static void socfpga_a10_fpga_set_cfg_width(struct a10_fpga_priv *priv, + int width) +{ + width <<= A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH_SHIFT; + + regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST, + A10_FPGAMGR_IMGCFG_CTL_02_CFGWIDTH, width); +} + +static void socfpga_a10_fpga_generate_dclks(struct a10_fpga_priv *priv, + u32 count) +{ + u32 val; + unsigned int i; + + /* Clear any existing DONE status. */ + regmap_write(priv->regmap, A10_FPGAMGR_DCLKSTAT_OFST, + A10_FPGAMGR_DCLKSTAT_DCLKDONE); + + /* Issue the DCLK regmap. */ + regmap_write(priv->regmap, A10_FPGAMGR_DCLKCNT_OFST, count); + + /* wait till the dclkcnt done */ + for (i = 0; i < 100; i++) { + regmap_read(priv->regmap, A10_FPGAMGR_DCLKSTAT_OFST, &val); + if (val) + break; + udelay(1); + } + + /* Clear DONE status. */ + regmap_write(priv->regmap, A10_FPGAMGR_DCLKSTAT_OFST, + A10_FPGAMGR_DCLKSTAT_DCLKDONE); +} + +static int socfpga_a10_fpga_encrypted(struct fpga_manager *mgr, + u32 *buf32, size_t buf32_size) +{ + int encrypt; + + if (buf32_size < 70) + return -EINVAL; + + encrypt = ((buf32[69] >> 2) & 3) != 0; + + dev_dbg(&mgr->dev, "header word %d = %08x encrypt=%d\n", + 69, buf32[69], encrypt); + + return encrypt; +} + +static int socfpga_a10_fpga_compressed(struct fpga_manager *mgr, + u32 *buf32, size_t buf32_size) +{ + int compress; + + if (buf32_size < 230) + return -EINVAL; + + compress = !((buf32[229] >> 1) & 1); + + dev_dbg(&mgr->dev, "header word %d = %08x compress=%d\n", + 229, buf32[229], compress); + + return compress; +} + +static unsigned int socfpga_a10_fpga_get_cd_ratio(unsigned int cfg_width, + bool encrypt, bool compress) +{ + unsigned int cd_ratio; + + /* + * cd ratio is dependent on cfg width and whether the bitstream + * is encrypted and/or compressed. + * + * | width | encr. | compr. | cd ratio | + * | 16 | 0 | 0 | 1 | + * | 16 | 0 | 1 | 4 | + * | 16 | 1 | 0 | 2 | + * | 16 | 1 | 1 | 4 | + * | 32 | 0 | 0 | 1 | + * | 32 | 0 | 1 | 8 | + * | 32 | 1 | 0 | 4 | + * | 32 | 1 | 1 | 8 | + */ + if (!compress && !encrypt) + return CDRATIO_x1; + + if (compress) + cd_ratio = CDRATIO_x4; + else + cd_ratio = CDRATIO_x2; + + /* if 32 bit, double the cd ratio (so register + field setting is incremented) */ + if (cfg_width == CFGWDTH_32) + cd_ratio += 1; + + return cd_ratio; +} + +static int socfpga_a10_fpga_set_cdratio(struct fpga_manager *mgr, + unsigned int cfg_width, + const char *buf, size_t count) +{ + struct a10_fpga_priv *priv = mgr->priv; + unsigned int cd_ratio; + int encrypt, compress; + + encrypt = socfpga_a10_fpga_encrypted(mgr, (u32 *)buf, count / 4); + if (encrypt < 0) + return -EINVAL; + + compress = socfpga_a10_fpga_compressed(mgr, (u32 *)buf, count / 4); + if (compress < 0) + return -EINVAL; + + cd_ratio = socfpga_a10_fpga_get_cd_ratio(cfg_width, encrypt, compress); + + regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST, + A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_MASK, + cd_ratio << A10_FPGAMGR_IMGCFG_CTL_02_CDRATIO_SHIFT); + + return 0; +} + +static u32 socfpga_a10_fpga_read_stat(struct a10_fpga_priv *priv) +{ + u32 val; + + regmap_read(priv->regmap, A10_FPGAMGR_IMGCFG_STAT_OFST, &val); + + return val; +} + +static int socfpga_a10_fpga_wait_for_pr_ready(struct a10_fpga_priv *priv) +{ + u32 reg, i; + + for (i = 0; i < 10 ; i++) { + reg = socfpga_a10_fpga_read_stat(priv); + + if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_ERROR) + return -EINVAL; + + if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_READY) + return 0; + } + + return -ETIMEDOUT; +} + +static int socfpga_a10_fpga_wait_for_pr_done(struct a10_fpga_priv *priv) +{ + u32 reg, i; + + for (i = 0; i < 10 ; i++) { + reg = socfpga_a10_fpga_read_stat(priv); + + if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_ERROR) + return -EINVAL; + + if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_DONE) + return 0; + } + + return -ETIMEDOUT; +} + +/* Start the FPGA programming by initialize the FPGA Manager */ +static int socfpga_a10_fpga_write_init(struct fpga_manager *mgr, u32 flags, + const char *buf, size_t count) +{ + struct a10_fpga_priv *priv = mgr->priv; + unsigned int cfg_width; + u32 msel, stat, mask; + int ret; + + if (flags & FPGA_MGR_PARTIAL_RECONFIG) + cfg_width = CFGWDTH_16; + else + return -EINVAL; + + /* Check for passive parallel (msel == 000 or 001) */ + msel = socfpga_a10_fpga_read_stat(priv); + msel &= A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_MASK; + msel >>= A10_FPGAMGR_IMGCFG_STAT_F2S_MSEL_SHIFT; + if ((msel != 0) && (msel != 1)) { + dev_dbg(&mgr->dev, "Fail: invalid msel=%d\n", msel); + return -EINVAL; + } + + /* Make sure no external devices are interfering */ + stat = socfpga_a10_fpga_read_stat(priv); + mask = A10_FPGAMGR_IMGCFG_STAT_F2S_NCONFIG_PIN | + A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN; + if ((stat & mask) != mask) + return -EINVAL; + + /* Set cfg width */ + socfpga_a10_fpga_set_cfg_width(priv, cfg_width); + + /* Determine cd ratio from bitstream header and set cd ratio */ + ret = socfpga_a10_fpga_set_cdratio(mgr, cfg_width, buf, count); + if (ret) + return ret; + + /* + * Clear s2f_nce to enable chip select. Leave pr_request + * unasserted and override disabled. + */ + regmap_write(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST, + A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG); + + /* Set cfg_ctrl to enable s2f dclk and data */ + regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST, + A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL, + A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL); + + /* + * Disable overrides not needed for pr. + * s2f_config==1 leaves reset deasseted. + */ + regmap_write(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_00_OFST, + A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NCONFIG | + A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_NSTATUS | + A10_FPGAMGR_IMGCFG_CTL_00_S2F_NENABLE_CONDONE | + A10_FPGAMGR_IMGCFG_CTL_00_S2F_NCONFIG); + + /* Enable override for data, dclk, nce, and pr_request to CSS */ + regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST, + A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG, 0); + + /* Send some clocks to clear out any errors */ + socfpga_a10_fpga_generate_dclks(priv, 256); + + /* Assert pr_request */ + regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST, + A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST, + A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST); + + /* Do some dclks, wait for pr_ready */ + socfpga_a10_fpga_generate_dclks(priv, 0x7ff); + + /* Wait for pr_ready */ + return socfpga_a10_fpga_wait_for_pr_ready(priv); +} + +/* + * write data to the FPGA data register + */ +static int socfpga_a10_fpga_write(struct fpga_manager *mgr, const char *buf, + size_t count) +{ + struct a10_fpga_priv *priv = mgr->priv; + u32 *buffer_32 = (u32 *)buf; + size_t i = 0; + + if (count <= 0) + return -EINVAL; + + /* Write out the complete 32-bit chunks */ + while (count >= sizeof(u32)) { + writel(buffer_32[i++], priv->fpga_data_addr); + count -= sizeof(u32); + } + + /* Write out remaining non 32-bit chunks */ + switch (count) { + case 3: + writel(buffer_32[i++] & 0x00ffffff, priv->fpga_data_addr); + break; + case 2: + writel(buffer_32[i++] & 0x0000ffff, priv->fpga_data_addr); + break; + case 1: + writel(buffer_32[i++] & 0x000000ff, priv->fpga_data_addr); + break; + case 0: + break; + default: + /* This will never happen */ + return -EFAULT; + } + + return 0; +} + +static int socfpga_a10_fpga_write_complete(struct fpga_manager *mgr, u32 flags) +{ + struct a10_fpga_priv *priv = mgr->priv; + u32 reg; + int ret; + + /* Wait for pr_done */ + ret = socfpga_a10_fpga_wait_for_pr_done(priv); + + /* Clear pr_request */ + regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST, + A10_FPGAMGR_IMGCFG_CTL_01_S2F_PR_REQUEST, 0); + + /* Send some clocks to clear out any errors */ + socfpga_a10_fpga_generate_dclks(priv, 256); + + /* Disable s2f dclk and data */ + regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_02_OFST, + A10_FPGAMGR_IMGCFG_CTL_02_EN_CFG_CTRL, 0); + + /* Deassert chip select */ + regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST, + A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE, + A10_FPGAMGR_IMGCFG_CTL_01_S2F_NCE); + + /* Disable data, dclk, nce, and pr_request override to CSS */ + regmap_update_bits(priv->regmap, A10_FPGAMGR_IMGCFG_CTL_01_OFST, + A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG, + A10_FPGAMGR_IMGCFG_CTL_01_S2F_NENABLE_CONFIG); + + /* Return any errors regarding pr_done or pr_error */ + if (ret) + return ret; + + /* Final check */ + reg = socfpga_a10_fpga_read_stat(priv); + + if (((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_USERMODE) == 0) || + ((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_CONDONE_PIN) == 0) || + ((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN) == 0)) { + dev_dbg(&mgr->dev, + "Timeout in final check. Status=%08xf\n", reg); + return -ETIMEDOUT; + } + + return 0; +} + +static enum fpga_mgr_states socfpga_a10_fpga_state(struct fpga_manager *mgr) +{ + struct a10_fpga_priv *priv = mgr->priv; + u32 reg = socfpga_a10_fpga_read_stat(priv); + + if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_USERMODE) + return FPGA_MGR_STATE_OPERATING; + + if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_PR_READY) + return FPGA_MGR_STATE_WRITE; + + if (reg & A10_FPGAMGR_IMGCFG_STAT_F2S_CRC_ERROR) + return FPGA_MGR_STATE_WRITE_COMPLETE_ERR; + + if ((reg & A10_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN) == 0) + return FPGA_MGR_STATE_RESET; + + return FPGA_MGR_STATE_UNKNOWN; +} + +static const struct fpga_manager_ops socfpga_a10_fpga_mgr_ops = { + .state = socfpga_a10_fpga_state, + .write_init = socfpga_a10_fpga_write_init, + .write = socfpga_a10_fpga_write, + .write_complete = socfpga_a10_fpga_write_complete, +}; + +static int socfpga_a10_fpga_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct a10_fpga_priv *priv; + void __iomem *reg_base; + struct resource *res; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + /* First mmio base is for register access */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + reg_base = devm_ioremap_resource(dev, res); + if (IS_ERR(reg_base)) + return PTR_ERR(reg_base); + + /* Second mmio base is for writing FPGA image data */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + priv->fpga_data_addr = devm_ioremap_resource(dev, res); + if (IS_ERR(priv->fpga_data_addr)) + return PTR_ERR(priv->fpga_data_addr); + + /* regmap for register access */ + priv->regmap = devm_regmap_init_mmio(dev, reg_base, + &socfpga_a10_fpga_regmap_config); + if (IS_ERR(priv->regmap)) + return -ENODEV; + + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) { + dev_err(dev, "no clock specified\n"); + return PTR_ERR(priv->clk); + } + + ret = clk_prepare_enable(priv->clk); + if (ret) { + dev_err(dev, "could not enable clock\n"); + clk_put(priv->clk); + return -EBUSY; + } + + return fpga_mgr_register(dev, "SoCFPGA Arria10 FPGA Manager", + &socfpga_a10_fpga_mgr_ops, priv); +} + +static int socfpga_a10_fpga_remove(struct platform_device *pdev) +{ + struct fpga_manager *mgr = platform_get_drvdata(pdev); + struct a10_fpga_priv *priv = mgr->priv; + + fpga_mgr_unregister(&pdev->dev); + clk_disable_unprepare(priv->clk); + clk_put(priv->clk); + + return 0; +} + +static const struct of_device_id socfpga_a10_fpga_of_match[] = { + { .compatible = "altr,socfpga-a10-fpga-mgr", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, socfpga_a10_fpga_of_match); + +static struct platform_driver socfpga_a10_fpga_driver = { + .probe = socfpga_a10_fpga_probe, + .remove = socfpga_a10_fpga_remove, + .driver = { + .name = "socfpga_a10_fpga_manager", + .of_match_table = socfpga_a10_fpga_of_match, + }, +}; + +module_platform_driver(socfpga_a10_fpga_driver); + +MODULE_AUTHOR("Alan Tull "); +MODULE_DESCRIPTION("SoCFPGA Arria10 FPGA Manager"); +MODULE_LICENSE("GPL v2"); -- 2.9.1