Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754234AbcKATQD (ORCPT ); Tue, 1 Nov 2016 15:16:03 -0400 Received: from mail-sn1nam02on0064.outbound.protection.outlook.com ([104.47.36.64]:45312 "EHLO NAM02-SN1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753264AbcKATPa (ORCPT ); Tue, 1 Nov 2016 15:15:30 -0400 Authentication-Results: spf=fail (sender IP is 66.35.236.227) smtp.mailfrom=opensource.altera.com; ettus.com; dkim=pass (signature was verified) header.d=altera.onmicrosoft.com;ettus.com; 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: Greg Kroah-Hartman CC: Rob Herring , , "Moritz Fischer" , Dinh Nguyen , , Alan Tull Subject: [[PATCH repost v21] 11/11] fpga-manager: Add Socfpga Arria10 support Date: Tue, 1 Nov 2016 14:14:32 -0500 Message-ID: <1478027672-4857-12-git-send-email-atull@opensource.altera.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1478027672-4857-1-git-send-email-atull@opensource.altera.com> References: <1478027672-4857-1-git-send-email-atull@opensource.altera.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [67.164.136.211] X-ClientProxiedBy: CO2PR06CA030.namprd06.prod.outlook.com (10.141.242.30) To CY1PR03MB1519.namprd03.prod.outlook.com (10.163.17.25) X-MS-Office365-Filtering-Correlation-Id: fc367808-ff1e-4b34-6777-08d4028b6e51 X-Microsoft-Exchange-Diagnostics-untrusted: 1;CY1PR03MB1519;2:IIYKBJvMo+H2CRrxjdEcotJUXpqb8ajbxktGT46bXbXJLw57I9qOOc1iFZIp1rtJ43Ov/oBTosMa+sqZpZYU3pBXOVbvBiFlAVjZS8cQnUezAfuBmmqLE+y1c6OR5HJro714BKwIeM5ey8UZGtmcdbn5XvEEb8Ypk2BCTB6WIBgL/fBFy3pkZTSi63cxCrKApx2Gayl7nadwZz0iwte5Uw==;3:dVsZhfEqBElWW98Ia3186LYTT2gm+mIEuVqb5PvDr9XBnH8E4KFne1FZt4oAyS3jFqGNM7gysU5n0rId2Oagljm2TNDN6zrU/Lrk9aiS2eUznOmElZtvciRlSIUXkJmu8PyNs1Pd+Ld1yHxrCxCqzw== X-Microsoft-Antispam-Untrusted: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:CY1PR03MB1519; X-Microsoft-Exchange-Diagnostics-untrusted: 1;CY1PR03MB1519;25:lQ3YPIzGSnWw0L5YIgx9YswMQMwXsCy8CjQURuh2gaoNHKFFnLpb7PUOOzUOtKJ0d+N70UaZoevL3cboCl4P0VJXXqWztflNANgYQ+EAH+Mjr5Ko7ThZ9E/iBPWWLnBy42lp+HZ7N177cY6BmVXW5ySxtPj9fTJfSjUYfFg2OG6ylF5qnbKBeX4cD+c5K57DiEWWETlHR2iMWe7xP8p4YwHd2tyUrZisJA2R6hemcltCCXFFWeirJUL/exmPWt6p6unnb2EmFV3GHEbcZNOHSJEojB0yZrEYZtKZQMXz1at6PW7iLPOBDBr+Y9zw8X59pGu1PsBsjPrOVCU4OBEXsBnXu0xoiu93qGPAcJy3gfpcmBEtFfyU4sXS+M3HJp+cG2w25ugX8CcfBCxbwzrjMgBZsarEFjndQEM0pfu7gOFRKX1RqjxmvfHN95+RbOkDawoaUr6toDnFIcdWBqHaIP/ZZrdQ7c7Yo5DfY10vyvet+Owbj6EetRVQS65EqDTOdutYA7qV/56XgkABgRqflJMNibn3U0ZYaVy+PY1hfEC8N7+BCX2YIXQWSvjrGcSA1W+E6AbYZtko5MMznXgfyk6nMgI5gj0WRtl0UPJ2cINsf0R3sJP1NnyvEF3oWqnum1a4KFx4/Uy/lz8YQbFNTr0Y0imb9DS6x/fs30A4QzKfzL+E8AQRcj6682mESI8N1AvLkH5eJs4YN/VPUWVEwLNQ/UnSFBskNWTq5VZt/VkWqMpbIKiViNbimJFwkjKF+5owWX2T4b0VTI54mtpJYev4C1q9R5tp6dLp5p/6zc0vYPF1FHYM7exHLLj7KVv1Sr3p/DenqnzimTpJRYsgNi0fJ/NSRatIMDCzF8GsM0c= X-Microsoft-Exchange-Diagnostics-untrusted: 1;CY1PR03MB1519;31:A+xjcp608MIg8u2Rno8zyioLA8eZhZz4b+xcEOM7ujn3iaVcTT9fV9tazPuQue6CK2Ki4+u95d2Jmn3NwJr/mRnPaHQYQ+0JO5NN6Hc6PgBIB9FmLyZOuHivpgAPXuMGR6MjhaNNqlX6zOB1AKdPDvP3cXJu6dVxe7Lv0RERv7qtNQ7k7uMY9gqQgzYaatVmATXSLIZUk0h8J5jcrVCAFU5YcofxXBKcxD70HaUAtXi6TqrJnBAfMxmC7yGauarLbG19eEEkWEL3pDpDiLEH0MgV3fnYVb0RyzqKuTVpras=;20:Rtzm+JwZDsE8Qy3qndT3WVaTUPh7HiIPP+bcdsjGi7qeC6dt7Pa7r7MVfMBA1HRJxDSUlBppFreDEtXeKteX4Saa1tlwhoPTIOj5pDxth/pZaED4zHNPbiK8KU+9MYrY4vmaTbseWs8L4kjEsXb7PQCLQV9lVwWO2yspGSNVPN0= 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:(6040176)(6045074)(601004)(2401047)(5005006)(8121501046)(10201501046)(3002001)(6055026)(6046074)(6072074);SRVR:CY1PR03MB1519;BCL:0;PCL:0;RULEID:;SRVR:CY1PR03MB1519;BCL:0;PCL:0;RULEID:(6040176)(6045074)(601004)(2401047)(8121501046)(13024025)(13018025)(5005006)(13017025)(13023025)(13015025)(10201501046)(3002001)(6055026)(6046074)(6072074);SRVR:CO2PR03MB2294;BCL:0;PCL:0;RULEID:;SRVR:CO2PR03MB2294; X-Microsoft-Exchange-Diagnostics-untrusted: 1;CY1PR03MB1519;4:1MxQLEAO3e8jzmIcga3KNLYXtA1Qlf1kPQBPbLFRNOiFW09FrGwQSRmD2BBW9SGzW4IcuHffSPHhOmWABAMAk9NKcu6As/cvkMDIT1D26MHs5PPXAhSK1cOOJ3sCtBS+mmHgfcN4NfMfpAAVw9umnMoTMADddtvu1CiKSmdT6yJqF+boKe8U/gr4CeSkE5VlAdBb8n7AsWVjJa8XEln6zjZgGVCGqKKIfx+0+ChtujJnul8fR+I8zI7bVgbQDSsslUgIytlIQPpwG9g3k76pNYabu0hvJdoyrxpQZfq+y3q/vjub5L+tD6wjMZfVllvYU1DS5DtVsKLDHBvtzesf1mLx9fSqr6QId5CLmPjVVqSIjaBnAUxkPnPvmXGyyHaQmM8WvmJgdIEmXz6J9tseXCe+h4B37agHzhTJL4fZWNBPLf2TH+FhYgdGb6xWXtCv+JaVOirDsyVM+WsC/hQ2I22C+MFuJa2esdt4dV+/hGg4LzgfpsLCwo2QEkVGbU6bS0c64iFc9elc0I3zPWHuJ5UpTBretwH/OKKx46PybfCJ56dzkUDlFaWlKz011EEBdCoRpLXLlVFCGW0UJqb1bg== X-Forefront-PRVS: 01136D2D90 X-Forefront-Antispam-Report-Untrusted: SFV:NSPM;SFS:(10009020)(4630300001)(6009001)(7916002)(189002)(199003)(92566002)(3846002)(77096005)(7846002)(19580395003)(19580405001)(6666003)(68736007)(81156014)(81166006)(4001430100002)(101416001)(86362001)(8676002)(5660300001)(76176999)(6116002)(305945005)(50986999)(2906002)(7736002)(575784001)(33646002)(110136003)(66066001)(42882006)(42186005)(105586002)(47776003)(107886002)(5003940100001)(2950100002)(586003)(6916009)(229853001)(4326007)(15975445007)(48376002)(106356001)(50466002)(189998001)(50226002)(97736004)(2004002);DIR:OUT;SFP:1101;SCL:1;SRVR:CY1PR03MB1519;H:atull-VirtualBox.hsd1.nm.comcast.net;FPR:;SPF:None;PTR:InfoNoRecords;MX:1;A:0;LANG:en; X-Microsoft-Exchange-Diagnostics-untrusted: =?us-ascii?Q?1;CY1PR03MB1519;23:MQgi4anBZmO7vrcDrGvp7bG24v8mNWDdveSrcQxf4?= =?us-ascii?Q?yYuuRQ9b8FQxISf3Ank+wa8cUdkT11mAAw98s0iEPI/y5ROHjLVnHE1+tK+Y?= =?us-ascii?Q?3XwZkkEQnmUBaj+pn25/vQPjm7PnC2RGuFg0JeQ0p5VAi6cXjPK+Elf+QO2z?= =?us-ascii?Q?iIj/us8x0xkoVO8krj1uGTDMgo3/23GhirJpFFut7xGwX5hffBGfvYTrarqL?= =?us-ascii?Q?NehfYVo97FBiUwDCoPyV/DZM1WPO61PEeh2sRVP7a0xoq6LPR/Ln4Rwo+/Bf?= =?us-ascii?Q?y5+Ymq9KzwGte23jxieCGLFBs15zjrO8Exdpo4A39+FPPapvbLQbZVowk71M?= =?us-ascii?Q?Gk7EnHQbBEQq4J2uHKso53e9kJNYJLuQGPwGGCgYC5TjbderWvJiNIlCdPEc?= =?us-ascii?Q?X4JMln9/DfYXq8jXtId3lTzllwU8yGrfd+AvNNyiuQTJWWITh+cpapC7SJ91?= =?us-ascii?Q?KIB9nY1S6C2iC1pv6Vb5Hxec/5e5pcgATDGsGythwmns4EKGyeN81QbKvrX2?= =?us-ascii?Q?hlmx44iHV49tzg0r8KEP0c+D4NBkg2Gen6CHdJ425zCeoK1UTeapIkc2yiU+?= =?us-ascii?Q?ddFVqO5g0bmCG4WQ3CI0s0aUhqv2tMKL755QcD47FKt00tXTa276UypVi2rZ?= =?us-ascii?Q?txPENsIt9b0lxu4OVNxnr9fmJDPnHxGEnbt0m8nEsuWUHcMbhCdO6Kt1VrWo?= =?us-ascii?Q?2T/hjA4fpL/hddWtKFS67DB7hGSmpbJBSUUpzDGGmPnoKyKZLMghjkDwACgL?= =?us-ascii?Q?dp5MxTZ7+poKDYUonC/jk1D4A3hTV6U1KYuds7be1NIf0yFuJDtbk2zBkrVD?= =?us-ascii?Q?lpD+3X3F2Ns8bsCBoexUi5vcbqNhbsQKV6NRa4wPWLLskikm+chx5LbuE81o?= =?us-ascii?Q?naHjyucBZBPqgeK+9uca38PdIs9YvHuzFZfK9WyF3BmASA6SZl3xObYavWEK?= =?us-ascii?Q?M6/eAm6/5cKSazZd35ZjqBfNy62dxsBIF+mzcuRDoYrQeJL1wXQIVwPahbmw?= =?us-ascii?Q?a0C9WazF1uMVBBJ9JTR4z5js0HpvGXMQYnqF/2aC6GCSJerJ4Jyt0tGGRllz?= =?us-ascii?Q?KW7+ZH0sTcS0elKuJGchznjanGzHcqaFN95C3Cc/fJwRkPJjzNmGHXO2ShyX?= =?us-ascii?Q?GHJtQy4VWRVuqDWXesr8f6YtSK7Ah3h4A5cejtlwH9QbANh1Slujn99yKbJx?= =?us-ascii?Q?M50P25RKZQB1tXLnl46NpYbt9O1nBT16oPO?= X-Microsoft-Exchange-Diagnostics-untrusted: 1;CY1PR03MB1519;6:djn10wpwC73TlUeUoY0cGRpxPPDxtRt4uioqj51uCtDCX4pyDSu5PKFPFuPutsvElD8pj93g0XuUOVRv7Dkjabg2TH02caBSTJ5XCciypiJEya6+5/Poa5UqCafVBw9crafKUgWtS1AYMnByjEo8uFLRF8dw+rZ7rHiYGUhYCRGB3vUFWtUBEXrxUDs5wIAg8dAjNIJAKDBPUuwyeH8f0VI9IwEbEhLU9SE+wTKvwkdOKaFwtSyp/rVFfNbb33KgwOz1hMxCkAfOLtF51wMYEUoA0rWMCY50cBLsjTH+gl9zp8uZmOgfivfzqSp2yL8JwHc/AiGGerKfbLy5kA1q/wHv+znXIgSZ0zJirQ+ao9LncZaKSDHJy0vhQvazlCVE;5:NCo60uCSEPiE3QlgTH9VaLvOXLfFPnrt4uZ7W1bp4dKtXMf9QoWORbv2rT24Nwb/ZyY6F014jFyEWsfcOv+tbB8IrjIF5mZvb2r6PFK4aawyV8n3+lzGfogOmLCT/2PZe8FLGpBpgd6R5wHuPQ6RzA==;24:8/zSIxkvplYNX0Gora8dtLRXz9YJ4XbiTTV9GvtCJL4tQSk3cNnzHU6qKwHsB4u7WyKt4M27Qqnx5k//w+RTvRQ1K7KAdeyTI1xRyqkJsYI= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics-untrusted: 1;CY1PR03MB1519;7:3jxkWNdO9Hn0THeA69A1LYl0HifYOgCqz1D/OmJ7InqScyrluhrIDodBOvJp/FmK3KeJ786ORXCXWj7ed5zFDe5dy29Ww9LBxUbiSNDv5Io8H9xbV3d8UGMKyUiF4zJMXr+MtGegx2nVgFbDKQLDtM1pNoqR1QyxfvrCQIbuVoz3xfnHw7trAOihY4Xr7SF5VUyX+5bOc/26s+BjZADjD5Ot3/8BO+B6Gpl5+UeRnx8WmurjM1C29Y70fBCevo1e3s2ZPLokculu7pS3jBaoF4Z/Pfr5M1wIDhYFKwh8OQxWwr/AipdQZH1jGPha/nuzDjkhqZsi0hhQ659cx06wCUhZcF3cb8L11qOaWsEr0Zk= X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY1PR03MB1519 X-EOPAttributedMessage: 0 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)(1109001)(1110001)(339900001)(199003)(189002)(3720700001)(6116002)(4001430100002)(97736004)(8676002)(4326007)(48376002)(626004)(81156014)(81166006)(50466002)(2906002)(8936002)(47776003)(15975445007)(50226002)(6666003)(87936001)(77096005)(85426001)(575784001)(86362001)(66066001)(19580405001)(7736002)(7846002)(42882006)(76176999)(5003940100001)(6916009)(2950100002)(50986999)(305945005)(110136003)(19580395003)(68736007)(336002)(92566002)(189998001)(3846002)(956001)(586003)(107886002)(356003)(106466001)(229853001)(5660300001)(33646002)(105606002)(6070500001)(7099028)(2004002);DIR:OUT;SFP:1101;SCL:1;SRVR:CO2PR03MB2294;H:sj-itexedge03.altera.priv.altera.com;FPR:;SPF:Fail;PTR:InfoDomainNonexistent;A:0;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;BY2FFO11OLC008;1:P5xmw9fSibtEqCIX6ga7VhFNfYTve/8WHwgzoNBzgQx+X9bMEjuAXHRNsz5dUd/J7R5JbEmRY0Esk7A++kWKrJPVV1qKvSOLdY+3klGxc2SJoYsFvjasGEo0YtgRZZAYf6I0+PuDqQdj9bV+4oAU7meNRE4u3kWO2nJp1fAM9TWsJvDCjg+LAQDY4kKj0NN5KsAW1wsKT7rZWoKhC3MMo35wVJZMI9XgvYDacC9VYfQxE48APPlPhinVMMQVlCFV/RkJA3YLlQ2sRDNsDFLkn7txprr4+7i5HhraU1sOG/mVkdLRAm5gDOv0vMwfTbGDgUrE6JBL3u3LF4olThZzrZaX3JGMM/k7YgIk3/ikQhofkNL8NmhuZRSa1o55/jEZDh3bj7sfJorRZruvCaohNeQayLfYAq5T9AzihQeF3FkP0b96DSrlo380RO/zqYNjpCDCLwFV3C557XXPEmErRcJlBvuEAEEPB/kioJjMoHhNXEL1Gb3mVST3GtLgfnXyFxGOp1l8YYmHa0iajBwJJKCPJjxBATP1RkWXaukjOKDxxxJ3tuJbckc5p7DY+bksh+amjInC8wwYgrR+Ce5ElQ== X-MS-Exchange-Transport-CrossTenantHeadersStripped: BY2FFO11OLC008.protection.gbl X-Microsoft-Exchange-Diagnostics: 1;CO2PR03MB2294;2:Cnp/wz2+JYSE9KmlF1XW+5yb3H76/OiUMTMqa1RIpaHzLOpFMCKYv6fqUrCA8d0+GH0qvxnws7CoHurhaiK70qy0Tqc3mkQBQolZC0O08XburPuO1vj7LzWBY6lEwZhqd+T9/TFMVtWFXQY1jF3acZ7VHI0EQHrhS/AO6cInvEoyxAnz9Ll1r+KFqsY1BCUKlZBvH45oQfbQT573j/sjrw==;3:N0V68chSBap5z56VGjn/4smDcG9UaOG+V/4dnydvuGeOKinA4G8bQ2DSvr/B2nWwLuVrkEmfiK8tLIGup/iAfgs4E6QMcYRnUAxIGjglUGV1XEfE+hICn2HNfi4Vmih3R5TGROrcl2nzrkXde/DWn6wPzuGlnxca7XP4PZacGJAYNqcnBsHhLDpdgOo4BZsCV1aJx6mlzt4bITOx7/LGQL4/1JKq3WGUiMukhz+zEFGnaWUS7H0jlQmDc6Jn9hOgmTcysi5rIwejyXFvVFle3w== X-DkimResult-Test: Passed X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(3001016);SRVR:CO2PR03MB2294; X-Microsoft-Exchange-Diagnostics: 1;CO2PR03MB2294;25:cwmt5tnQoYL56od5AHDeJElAuXgodiyeuSwRQiX2puom2Ycg4aJBleKcmBk/p8Gkt7NlG4sSKRCveLM9TUyyCT4RJO0ZuhOpop2ngio7Ti7ccz1Klod2txiZ8qMtFcWXYZ7aYCv3qWHTxR4ddG6BwDYrT1ogjvxb6rciewhvyzc7B+kTwVo19w2rpCkhAMz3IHf4DnL5B2tVB2z2JSLm78/OIvT1M1NERwsXsXLY87x82HRLEJyadRARfF6u3eYKlFWb9ob8GG7IY8/WXvd34oYJo7q7qrwCGXrFGpkxhc9JCW6Mo25I/UtdF/yd1L8EBXhV/4yusKKRhQUvPyeCHHmd39gwOfvG6JY2cdUMxC0zRjMW4vAFDvk61zZGIz57/5XJ9G2CiOBkwdtxk1cskAVWckUIdKq59Y6ggIsTjpujAPnvIipzPmSiXGD4Bceyns+chxfcemT4Yo1a/RDLcSWyVakJfCHFDO0l4q5noLRtuyQeMLIt8cpNb55Z39JXNmmhBYXG1ph6ePkk8RgbVXPkNaR897N4HvOQfxMd/kll3E1cWiXQhEMJxbRFlIXH4Mb1oauU/fiPpIA1SLBH6yY8/TPMFMBVWm0FC56B41yryrTseXyI/YXsjRGF7eJ7p+UxNi8vNAAv3/GueaCMTck8CLsYbmU93doNnEh7nmWIaCMvPeD62PVi6RboWlBYyd+3cFgnYu70eMVN374zZxDClLkJEDbQ3B0OfOgot5ny1uuwNIc4v4x1vui+Hcr53Ha2S9kWD8dQs8Jz2vPuA2Qs+3ByftHSbD2N205OTVmvQds3ECve1XrGgvSWznKB4HfwqHZiy5QmbHNspLUz75w+whaFf1VyR/VjRJU+e+c= X-Microsoft-Exchange-Diagnostics: 1;CO2PR03MB2294;31:qB9S5I7NMcHduwhi/TxXKV1NFOwcMQq2XE5IIZtgMGbaox9c5to9RV2tl4MUK24Pb3TKlF6E2V+3I+5Tq3sETcvwDJsKdA67i001NrGxTR++ujn7Ea04I7UnXjrIL/cPMB83lrKM8aE3ePX98JrqA5gceV7CKITjnbcOAJ8ea77vt/j20fTnFTwK0wDDjlkbhIXnex7ru3zdg0UYRJB7rZCArmq7hdPLHApK+X9sMLAl+pWBqpt5sIQrTFz59GSY4Iv/dQc6nN+6BtbVoCALC3rYPBgZsH33QNuSy9+uTQs=;20:9cc3RVczTZW8xEUoWZdYwJ6bMiXSUmX9jJSf3UOKBPR119amBwCluNs7RWqdYVwJnyjeOAwFJeXO/FHmN8XCBI8/1US/wyQ6Y4SOfBBA2exe+jR6St8b8/9rF0ESwDCC2lQZkXH4Jvede8u0LJ/zzuRN5XFygTk07XGvKjsPhcY= X-Microsoft-Exchange-Diagnostics: 1;CO2PR03MB2294;4:gg9y6PeP1Sf82nKwEOV5N60ivxEdHulx2EqgCwH3Bciakz/NO2ybOLMN70PdVaA+uuYTZlbN8BtoaFtGujmE2tZuTFULMQK2cF78W1hyhB/PJuSd1Hxa+0DLC2pJZYTDxd9WL6cqY1YzzAWOOLdoKtqqhPudhDL+LpFkucOztE6rOsjUENYiueLcSkLv2M8gKXS69t93Qd8rDS7kxFEWHmtoHZY8gh9uHpvzFXV9Ruldqj+NTCIJc2Y/kEPMWy7JzXFjtTtc0boXHvZMQLne+ukDVtSHDAdcVmjh+isOV0xlXf9CxkYQqPUGtXxFmo4leRjj2gyp0a8+7UN+9kYkwUIUlOkwEArR40TypjE5sCuT6g3cd8z+mfWHWb3B75ypRVWRD79nLNMD9ixi3BQI2DhrtUMb+RORCMkggZIlpzZsqCrH6WWzlr8bQOTjTWRa6bJAo+En481eZfAUoshimlBqflTtZ139XOEnAWgGeLtgGr/AtCx5GO+fhrnGm052nBGpCtSjikox/SGKySmGTDAlJZ2yKwrsplUGa0SdSBaZPwdKqYRda+MJrhF5KEwKxYKHQ68TUs1BttdsPGov4tmY1+xU8zRqW+89Wjk7Y1sSg9IebAAzd5a8UFHkRMhNHr54gSn4iJ9BdwTpsZz2NLx+OTNX34Xg+Z1h+4KpNtMmT0155QnY2Ih2z8jJVFEK X-Forefront-PRVS: 01136D2D90 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;CO2PR03MB2294;23:HiO1DNx3M8ge12Rh3OpbFiDrueUmlFCdsh/itCbZQ?= =?us-ascii?Q?S59C1ALleJNvtlLuPt03FTl2oHNR9wstQ++LA4Sc756moM6TVzh8iG42umrC?= =?us-ascii?Q?V30PoH0TLcQbE48O9F6z+igd9CfZaEsk2nvn677/atV8dRDO/bimjeAqaLkq?= =?us-ascii?Q?IT9P8bE5cosCYB7PY0wuVQtPWaZv+3l6PKSf/ZU2rhWykg+vIW/46VITR1HX?= =?us-ascii?Q?HAK4Og1p3Qwkz2SE6/OdkEzVQMWGmKmyPKCTve/M5ZjZxWSFNcZKMwncEvhk?= =?us-ascii?Q?MSkLcHP+svgsXbCFQOTQhxTsKLYuCys4vtCPtWXC7i5DALeJz2XpPyrnElQl?= =?us-ascii?Q?5Qlo68sEgnofHkqnLXjHLTycIF+tFiDZkYAnVO09oakvtk/KhmORtNEE1+M+?= =?us-ascii?Q?ztjMiq73McLaP0oRjLOKTcglAUv8LHniuGyC8FFC0UjH4om0fnYnDweazJMh?= =?us-ascii?Q?z6TcTMhh/bTYSqRAI7smX2PbJfFsVc1+WnJmhGq7bFTZA+i/rYtv4GcyYus5?= =?us-ascii?Q?LAw/HIZslqRd9UjBjMkigVhInuntUKBI+rWv8VlcIkCICp0/f6CExn4/ml0y?= =?us-ascii?Q?opWGrq48YFRyBqQZc72zAfV6nD6FNGr1frR+U62/LUae8svDis3ZtHsx7J9A?= =?us-ascii?Q?v1v6ijaZByaLDgM4/GBIQaSgeOqYKQMpQgsmcju1NQojaNj3FMxb2YouegcK?= =?us-ascii?Q?zkBBSshzqKo2nefO6hOcyz6l5Peo73zbhTvF4CGelp55x+D2mNk3WL8NGGfD?= =?us-ascii?Q?Z3CZZOGk0Zkxw79zvuUoARnRG2HqEmVa0w5O8fOaUaSRvXzAWVBvQYLux/jB?= =?us-ascii?Q?4ZoEOJminGthiH8xPZMMzEfBoDM8bqj+ltb7vN6qEjxeoY9mzuDDHTOyWUqW?= =?us-ascii?Q?C/tklRiz0nQI9EuujFQ1wAObM7lJGGErOsREyA0qBSyhzP7LxHbr3BsCgmsH?= =?us-ascii?Q?7icooMvbVkojDpVMA2HdoAv0XJ2a2HgbLBtLcOf4sVG0IZjtz2MYVBYiio+t?= =?us-ascii?Q?IDhakXe1/1Qj8DVgEV4RaeaSVRMMf6GDuawJY+X6tfZOdftepwmCNHUpIzri?= =?us-ascii?Q?0LllKeXl7KmFRUIvipDBvHRWzXH3Vgipx69PODWgxO5QMRl0GM01VkkhmjKs?= =?us-ascii?Q?VIUfumCM+07bcF3cMi6F7rN4tQPYgiqC9hFUfD0NhGYbceIrOixY8OnWFRKT?= =?us-ascii?Q?/r/RopC+Ax2HyEy5NzLPqzyx6NXrB7maasexI8PQhVbetCfq/1KGFU+ulLqC?= =?us-ascii?Q?Bw3gGDGEZWBEVa69CxKFDg4ma9XIG6IhT9JHpDVBdVEWQNZGutOQPViQvSTM?= =?us-ascii?Q?EAfxOsvQDMUcJF89Vzzm3WD/Zpn4glXkzNayO2q+CAjsf7oI1YYnnv4hMIiB?= =?us-ascii?Q?WhWx8CGHMB6fk3/rVPm9JOC/JIqXdTIfIGYCZpzvAsEtO4TtlIYqTUBXXxEg?= =?us-ascii?Q?//Uaz4Mxg=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1;CO2PR03MB2294;6:zuqg0qWtxBiSGsg8sa8p8VMjKTiuD47kJF7sd+fOz3U2bFr7NhS9MCwgpuo2RJcAC6VhjMir9iMMCSf0G5pyOe5Nizh2s60oJygbCPi44SCSWsD8UTpW0ysGrrgZyAEaP3LiMtLL9a+9AAQPxiL1D3cKL5+aHu4yFJbbD9KpcyHTtx+LWQGZN6Ufv3frrnTecCxMRj0TofHLWFMgRVn7YSkVDLWE8AibjIHVGrJcWWAAZRj7i1Ygzq7Tofqm5mta9qA75aqBX1T1QggW87dGzn8+bSaEaKv89wB+fjch6lhNKdFvq8iMpXvv5yqoaL9+kODnkkjzKJ1bBnxDFxHKz6UxJxr1EFTy1RKEp+jJrXLK2DwisHq77AwoXyTK+Fu8;5:pTbD0gkvMg7/EwOH2SMqiIOy2JtgAjo4tzep/SLOuiEEQWomzybOzGRowUfg8LQPQq5FPEa8sGxD2hKIbQhJd449FdbUUHh4tV5yqAm9oXWNjnhX+HHCkJqgCXRqUoBt0he56lbVeICutqB7Zj3Gog==;24:7ufIGSooBBsRqPwoQ9Gkp2jLsrukvhKmrYyU0vxEKJhwniTepmC0GMVCK2x6KcuF42IXyfImlXZ5r2qwEQaMa5NdADMvFOZJZjzZhg3lV8s= X-Microsoft-Exchange-Diagnostics: 1;CO2PR03MB2294;7:8YVn38C8W4OjFgNwcJ1cOOShd+AnjcDFHTudBjWmRDQzmvdTIXjipM59ep+Pb8ob6sE+j94g9ng+9Ll7Usg70r71d0jc16VUE1igOC5aWrV6v8zmjFhL3yppk84T+uo7tgarTOQG5Sbvo0yk7lZ0az/O0P/AiJVV4b3WgWqp/RKY91PstzlpE8F+H+6UR4OdXLpToatv3nTcF5nI06xQRsm8CXeJ7PcorwK6UyUIrJW5COuS+AijZlTMEoijiodbYBt/5aGh7hag7Q6ALsDtpmKgHNIgvPjPtph3uK/Kkoh1IzXa/9D0RoPqOoELtpjtbYtmIqZMzpsJnUkJc0gCKQ== X-OriginatorOrg: opensource.altera.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 01 Nov 2016 19:15:23.6253 (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: CO2PR03MB2294 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 18058 Lines: 606 Add low level driver to support reprogramming FPGAs for Altera SoCFPGA Arria10. Signed-off-by: Alan Tull Reviewed-by: Moritz Fischer Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/Kconfig | 6 + drivers/fpga/Makefile | 1 + drivers/fpga/socfpga-a10.c | 556 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 563 insertions(+) create mode 100644 drivers/fpga/socfpga-a10.c diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 8fe6a84..889e4c3 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 ARCH_ZYNQ || COMPILE_TEST diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index a6f874d..8df07bc 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..ccd9fb2 --- /dev/null +++ b/drivers/fpga/socfpga-a10.c @@ -0,0 +1,556 @@ +/* + * 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; + + /* 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 */ + regmap_read_poll_timeout(priv->regmap, A10_FPGAMGR_DCLKSTAT_OFST, val, + val, 1, 100); + + /* Clear DONE status. */ + regmap_write(priv->regmap, A10_FPGAMGR_DCLKSTAT_OFST, + A10_FPGAMGR_DCLKSTAT_DCLKDONE); +} + +#define RBF_ENCRYPTION_MODE_OFFSET 69 +#define RBF_DECOMPRESS_OFFSET 229 + +static int socfpga_a10_fpga_encrypted(u32 *buf32, size_t buf32_size) +{ + if (buf32_size < RBF_ENCRYPTION_MODE_OFFSET + 1) + return -EINVAL; + + /* Is the bitstream encrypted? */ + return ((buf32[RBF_ENCRYPTION_MODE_OFFSET] >> 2) & 3) != 0; +} + +static int socfpga_a10_fpga_compressed(u32 *buf32, size_t buf32_size) +{ + if (buf32_size < RBF_DECOMPRESS_OFFSET + 1) + return -EINVAL; + + /* Is the bitstream compressed? */ + return !((buf32[RBF_DECOMPRESS_OFFSET] >> 1) & 1); +} + +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 by incrementing the field */ + 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((u32 *)buf, count / 4); + if (encrypt < 0) + return -EINVAL; + + compress = socfpga_a10_fpga_compressed((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, + struct fpga_image_info *info, + const char *buf, size_t count) +{ + struct a10_fpga_priv *priv = mgr->priv; + unsigned int cfg_width; + u32 msel, stat, mask; + int ret; + + if (info->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); + + /* Provide 2048 DCLKs before starting the config data streaming. */ + 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, + struct fpga_image_info *info) +{ + 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"); + 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); + + 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"); -- 1.9.1