From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758293AbbIVPm4 (ORCPT ); Tue, 22 Sep 2015 11:42:56 -0400 Received: from mail-by2on0084.outbound.protection.outlook.com ([207.46.100.84]:56784 "EHLO na01-by2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753909AbbIVPmt (ORCPT ); Tue, 22 Sep 2015 11:42:49 -0400 Authentication-Results: spf=fail (sender IP is 66.35.236.227) smtp.mailfrom=opensource.altera.com; ettus.com; dkim=none (message not signed) header.d=none;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: To: , , , , , CC: Moritz Fischer , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Petr Cvek , , , Alan Tull Subject: [PATCH v11 4/4] fpga manager: add driver for socfpga fpga manager Date: Tue, 22 Sep 2015 10:21:11 -0500 Message-ID: <1442935271-10375-5-git-send-email-atull@opensource.altera.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1442935271-10375-1-git-send-email-atull@opensource.altera.com> References: <1442935271-10375-1-git-send-email-atull@opensource.altera.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [64.129.157.38] X-ClientProxiedBy: BY2PR1001CA0082.namprd10.prod.outlook.com (25.164.163.50) To BY1PR03MB1516.namprd03.prod.outlook.com (25.162.210.15) X-Microsoft-Exchange-Diagnostics-untrusted: 1;BY1PR03MB1516;2:UpWe887mMIY/IyT2ttCPIRu+eXmiGeA0zc3RPahKzt3PZN+NQeoPrMT9uPCAlGkQN34pl27Ubrb2DmTtTTe+E8kMtXTaX/o1hhG5RYbDiJt1+k3CNOq+a9RZZwfM8O5DeGpBIw+uIjengRBTxN3NeKCI1+h6yDTe7KVm0KCArsQ=;3:56uiJOFCgnbB5NSSz30lB7metNGHTAK0Oy3Uj1Xk42pLiAtu3o340lU92LTxRmFM1GfzRdt2FilgLjOro2zlo+fkXIT2lzilK/OzVc3LCAG0KkDT3GHFb+y3gFCHTyvW06qTRyLAJaFjjEeBf5EVZg==;25:BJfY06B7kYC1HpX3rnixFGB+8Ghv1OeJea94OLyPLxoE+xuPfJo+C3JqGNzIRju+awUIS/jjRqbJjMybm7wQBkdDhXOJ3nXyitB/dxumWtMjKWATfTeXr03FIiC2R4JpVeAeUmbY4GTjLZenxP/DeGabN4xzKIftByCc5f6T0PMpNElkHGLs2e5SOg4Z9ieuxJLcuX88/pIELsgie+giJSmuqTjpK2fJS5Yv3DTno4JEGPl7b8NKPW/mvdQdyKyv;20:Ir6h/ngdc0aD9myg9i6Ha4H/2Xb9Qm3awik7mkBfTVPetf/A3h4715Nuz8I+6EDgPdfBHA16C0bWg5DcaKPD6eYBQl7wl3ZW1P+wHV3hMKi/CcgoIx8UMpRvSDQNsk2TfxeTQgZD3DkfdrY72o/oUFFORrLzR+KbhaT5aI0xSoI= X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BY1PR03MB1516;UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BLUPR03MB310; X-LD-Processed: fbd72e03-d4a5-4110-adce-614d51f2077a,ExtAddr,ExtAddr,ExtAddr X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:;UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(2401047)(5005006)(520078)(8121501046)(3002001);SRVR:BY1PR03MB1516;BCL:0;PCL:0;RULEID:;SRVR:BY1PR03MB1516;BCL:0;PCL:0;RULEID:(601004)(2401047)(520078)(5005006)(8121501046)(3002001);SRVR:BLUPR03MB310;BCL:0;PCL:0;RULEID:;SRVR:BLUPR03MB310; X-Microsoft-Exchange-Diagnostics-untrusted: 1;BY1PR03MB1516;4:7pGKVdYRc+nHfrqzrc4WLvfUj8XQwHekaIDElorzHaAnHgPu+7QH4CJGANeDnKWMSWDFUIenH9yxbf5kCZcQW5gkSinkZ/GTgdQVW2xYhW1REu+0sgXOa1peGrsGHnl4GCHqGq+iPQuPKg9LcdECmuajKFpxO9sI5yPrrWb/RmEvLf4tEX1R0mGCb/uoZ8IG1z8WDN05L3wVCPgOqxpz7fdflh0nvCS7Ic4zpv2at3YfI0T8xFbo86JbRnpll971YOtvn7X0iSfnK5J/PW6qghdkKtJEo//h+g/app1SHTXULnRALF7fs3lRWeddWv8YAs6bFXyuA63tE5fLOQNGJ46tzqEgetOYCB5CR/E/S54= X-Forefront-PRVS: 0707248B64 X-Forefront-Antispam-Report-Untrusted: SFV:NSPM;SFS:(10009020)(6009001)(199003)(189002)(50466002)(87976001)(107886002)(5001830100001)(5007970100001)(47776003)(5001860100001)(64706001)(81156007)(101416001)(66066001)(97736004)(5001770100001)(42186005)(5001960100002)(62966003)(4001540100001)(48376002)(77156002)(2950100001)(53416004)(189998001)(69596002)(5004730100002)(105586002)(76176999)(92566002)(40100003)(86152002)(19580405001)(106356001)(33646002)(229853001)(50986999)(86362001)(575784001)(122386002)(46102003)(5003940100001)(2201001)(77096005)(68736005)(15975445007)(50226001)(19580395003)(7059030)(2004002)(4001430100001)(2101003);DIR:OUT;SFP:1101;SCL:1;SRVR:BY1PR03MB1516;H:linuxheads99.altera.com;FPR:;SPF:None;PTR:InfoNoRecords;A:0;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics-untrusted: =?us-ascii?Q?1;BY1PR03MB1516;23:ADQdES9D/FeJArub79n2hnmfA2BF7D1EuUCYNphNB?= =?us-ascii?Q?URA2SQwc0iEYaAqRo5VAGzURzEieykxVO/RSnb2vshV2qiAt17FUMh9EdrAd?= =?us-ascii?Q?oxhGteppI5epn5nDe55iqg3EIUI+8yIELrOIHBubwZCgni8K8TXr/ORlbbw+?= =?us-ascii?Q?6lkqzbwV0Gw3rYKqe55UGBRNDQ56GBT0FMPhD849vs52wX26ivFKFkNU9h9n?= =?us-ascii?Q?TlTmjL8SCwIIFKbXicyIfDDYQesu7y9Q+EnC2OwZXQc5keXfgUQPOL3dvzNp?= =?us-ascii?Q?P2xPcIOa+cGNd7Tznc9PxD+NDiEulqBgL0RJ3VqSQaLFUGA1NmrwiG0JjnWy?= =?us-ascii?Q?MeFDbGWXA6t+oJkaCoXDC0kjmGqUQqkh2hnhLvDH4XB20jQIZFeaBrbPxfuC?= =?us-ascii?Q?jpedNanwOWM7F9DVcBZfzMAE5i4BZx5KgAmEBCQe3HPOLsVq6tCRhIj0G284?= =?us-ascii?Q?as6aSPlyjJ+iEqIRoSXFkzsRuEUvB+iXwgqtRk8VKqbIbpRrFc7yDMWFpTyh?= =?us-ascii?Q?5CiAWSJXI2TlLSb8t8pAp+j8xYeENY12qw84AZq+hVnDvscuIFY1CBs+IIQX?= =?us-ascii?Q?Skph6NIVIUiOOwsc5/LM4mj2ScUPOgIAOtSFIqrKof0lElJqnU8xs7F/8SwC?= =?us-ascii?Q?0Wo4LaVLYQ5LNOuSPcenB1w2eIYFxXmIpOKDU6duYAhDTsgfW+07qGEsCS4n?= =?us-ascii?Q?+GdWICCDtTLfImwzdm6PO4je4hDZM+7KfrB5hQxG4ecMQMyQDTVfZRDJujSL?= =?us-ascii?Q?gw73Fu7C+LpslTjhLHBUji6WjMSEh6NfZmuWN+E8aUvE1MlrZJit0dQ9VFVi?= =?us-ascii?Q?mt5w0W64udSD+COtLo21EveuJjk5eTF1yKRVU2KhFRLs3aco+lg73f/JysG7?= =?us-ascii?Q?HWELmzr6bopQrETcLs6OIdwvnlcFfBQGut3CNNCsj25nzu/jAtgv247rcQ/6?= =?us-ascii?Q?PTNMmSbPIhOglwpZuO2/+ORFJLUWkUJsHbraVMeR32es2V3YsQQp77cX90d/?= =?us-ascii?Q?q71C0XMrWAVKR9D4JLE2VZJMaN8YZ+ytJfsvQQ3KaNQED4/jjd6Th018m8jb?= =?us-ascii?Q?0r9gKQzwQ5iZA5C/ZGaTh6euL6+KQyiXPagFidTONDyyioTJwpbAijAOduF4?= =?us-ascii?Q?rtiq3gGoGllqgGyckMhpi+U5xTSxpteCN/BjEFsVVQlvlqyiFdgVm01kNgKN?= =?us-ascii?Q?ki9Erkh55/UA3gCCqyBbznHZDNMTDXY+lhbKkV6ENfg14QesLCmY6Mf/8stX?= =?us-ascii?Q?npCPILaKAjIFL/xBJ1Gj1kR+r06xov8anU8KeqUY44/wZaY/YNlAqJSs7Hxo?= =?us-ascii?Q?1iEFl5Hj9snaR0nXdzo1HMxEPsVwY+nrCth6duLYehzDNSgbgj1dkujKvbAg?= =?us-ascii?Q?7xGQQRRObkKesx8BAoTILatd/A=3D?= X-Microsoft-Exchange-Diagnostics-untrusted: 1;BY1PR03MB1516;5:uHsI9rX52+/iOCOuAVNBfcNoaTq9NqQHDXiqNzqTvDHUNhWLzroFb6UxxhrM6LMp5gN6z3HxjCf6hcP1LUd5OzcGWSXmGuGFOITaW8ikvSktmC8uNmU+4WJZZyw0u3zd1GVmhDYmyE1SC4QqXqF4PQ==;24:PVpbO2Vt7dHGSP5/Lv7k0stVBczN4zFOGqMoh13HlizwDlQ5bv8owlMFNqpsienhTwDFpBsbZbHaL/fyVlLn0THi9PdHbjh3cEBN0cADj2o=;20:syiGJocxE3Oh1nRVWLmeicJ1zy7pz1i9yWgB6oA5BZnC6jesqkjphRhJ0ZiWqIsOSsuBvR5A7BsbG/trRyPV4Ne9W5JQJWk0yWc6gt/6nxd6siQ9MeBfjVJal7Mce57YRShQJ7duH80vm+Jl3Rv/gtn8Mqb9pfFSTqTttG8FWBM= SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY1PR03MB1516 X-EOPAttributedMessage: 0 X-MS-Exchange-Transport-CrossTenantHeadersStripped: BN1AFFO11OLC001.protection.gbl X-Microsoft-Exchange-Diagnostics: 1;BN1AFFO11OLC001;1:C4eHtY4e3GywqX0OgbD9PJDLBJIWOlccqLRfRGy+R+A3o+wc6vd18O28nQome+Hwddn7osmnKVbNP2a6GhKP7o8rr+YERMVnbq3nBHeGZ0FJKdbDC2DI1FepiGyZBa6P78ohXYe8UtPRUt9w8zdXSwCUCnJP/6TAMBTyrAabGJ4Z+AiBbj41gd1rOC5eMcG1ymFN6NuNnqD7PPH2SYdE3piK4Ez/EQfVXuQ55kzfLkHdgB9xvAGl4wHtEOIMwVWDJy6Rpcb94JK3qgTzzsHBjn752vVVWLbdJkDEE74p5LrJyKllL2uaIukYl5n4mn/R3HhFMfKe4VJs4RpQ+i4+o4mAZbL6f3AsA5Z6RHJVm0AFu39t/LYCCbOKQI3JAu/QMiyRBqWt1ZGG+jmkYvOewA== X-Forefront-Antispam-Report: CIP:66.35.236.227;CTRY:US;IPV:NLI;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(2980300002)(1110001)(1109001)(339900001)(189002)(199003)(5003940100001)(50986999)(50226001)(5004730100002)(76176999)(85426001)(5007970100001)(81156007)(5001770100001)(11100500001)(97736004)(2950100001)(5001830100001)(4001540100001)(5001860100001)(122386002)(6070500001)(62966003)(77096005)(40100003)(15975445007)(64706001)(33646002)(77156002)(92566002)(105606002)(87936001)(19580405001)(5001960100002)(53416004)(107886002)(5001920100001)(19580395003)(68736005)(189998001)(16796002)(46102003)(6806004)(86362001)(229853001)(2201001)(66066001)(21840400001)(47776003)(575784001)(50466002)(86152002)(106466001)(48376002)(7099028)(7059030)(2004002)(4001430100001)(2101003);DIR:OUT;SFP:1101;SCL:1;SRVR:BLUPR03MB310;H:sj-itexedge03.altera.priv.altera.com;FPR:;SPF:Fail;PTR:InfoDomainNonexistent;MX:1;A:0;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;BLUPR03MB310;2:erQQWOE80+AIksBx8t24UJmOXsFsmqrHI1PGDIWezNchFWx8T+PW2vF71Aq+ke25EPOiHaDDPnDZhVKAo9UyHaw8lYNcaY9rohMEJmO1lfgXuth/liEiQgtQF/Eu9DRhq6fOK20utq9Dlmw99O0az8OUjfyUFYybyk6rnGqRatU=;3:jFv0pdESH2bzQC6Z1UHj8sNXjRmpt5J6h2NJ6grEnetLqPrhfe5uBQ3EaR5QWTc2OadU+j72vDdfDpwE3SZQOWfOgjgv80T4yGIAv7CnwRJmVK8/SGl2SOyWGWt7OOw8rpN+n+BG+JFOn/04cNsnt+YRB8zBOzTxWHP7nxCWb0E+MSNdwuWJUa/YbHtlaJbSeHJIBb3mXPgHSsY2P/nbc2fpDMOQT+Qd8nGgOlgzZno=;25:uerG/Jf+2eA0lMGs6CTUj7cmKGhmK1utkMnL+K8YlNR1DJlD9S+yR700VNd/kJYseSWVY3qpPoDU7Dp83b1I2ms4/xLaSv4cpnA2v09bqlJ49gdoqgy0VqmgjrWfl61r5RRedyzCk1TjUyBWImEPPv/+pFB3LK5BTA7AU7yxzs9XXX3L7Sh73oVdiaFgam6+DCgxBfhdYJ4oLoT3IzzMw7BvuYtGqaJSBlY5Z24L+I7h41qoxkPNqurTnjo9XlCg;20:Ay96gATXZ+5gFSLfbKyo8gRpz3+LPuSUBb0DdfXf7qFIiTry84Ebpbrr9ygD8TAGnHYWoXACe97yl8jLFJ0VRiB+okvbemOI/JpCtpjZDS/Woe6cNZlbAy/gWUXRnpGkEoX6QQJOIQtaQAhxbmJaALrF4L+eX1jr57fPvk6pwS8= X-Microsoft-Exchange-Diagnostics: 1;BLUPR03MB310;4:61Tz0Ac2zTchDMSDM2UuBy73muk8CTBpVxO1zCorC5Gz/5naoHwrO29xriJWdSY7n3oH8PqPZttBHNmA/1BqH3ilz27yhta7bghbnzZOywskLH101thTj8vzEsAMwjyDbYkgoFU/ILFcradPbF5j0wCLBj0VOfYxsAI64+YLSwIlZXzUNzXZhHgqDs/b4W7HzXpIYKrQWQS45cP0D6EPsXtY5Fjg4XE9CXEDhe6fKKCxDCBCtKfEyMx2789GY8GiLRtA19dxexDtgTXjlXW+DY7OnUhohzyAbVPwQ0+NigLddV+l1MFEfzYKXdtRqRnOM0tz+HdOqXkgi9KrWZFwMHVYV4vaP5Woz0pBqFuhM/Y= X-Forefront-PRVS: 0707248B64 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BLUPR03MB310;23:fUG4hj8kI7YVPTTaP2v3r+k8zQmsShEg37OZqRW/He?= =?us-ascii?Q?Qb2TMmHJtM+0/JYKKTdHCOay6GHu/oOUC1jF/wc7MKz1Ym+L/e+ZtJWSo2yl?= =?us-ascii?Q?VroXry+NatfSw+xeEHqukIYrtEe9v1Fo47waRGYkE5VIRQ5OBsR3cmrTlL3R?= =?us-ascii?Q?d/txsNWweNCYTJZgo20AeTRbBrK4OfuRDQOxmyuyzFVIxE+Phg9/vG+Sxp5A?= =?us-ascii?Q?6cLb9lhKOCITnopSsoDGhGElOU8BxfUUaYt8kPuzfufUSRFHXPn5yrBOex8g?= =?us-ascii?Q?vNynTX4C7k337FMNvFoemJkuc6Z5q4QPhk0PuJiiaQLsVozxc09lOZRE4WH1?= =?us-ascii?Q?0Qgs5A2LzXX/lbVOmeGWVI7C16mWMVpl7DP5LBkic1bFhXl3sUFPRAeKSR3g?= =?us-ascii?Q?GP+CsM7I69u5A+tyl2yZovKLN3x87E2FQdlEIKq8ZA++eFIStShERU28V748?= =?us-ascii?Q?79nZPfYW3P1EvErZj7gw41LJCxFx8k3fpU6UpK1EreT+tieAocT0gYR5oz49?= =?us-ascii?Q?gttY5sLzpe8E23Yb4uNeF04UrX41GJ2CaghEwsY8/TR1AMm4VNFrkbJDulnK?= =?us-ascii?Q?mLiai5YsGdi31w2/L8GG7AOuc9e+BvtdfF9/5K5qutBY14fCkF/+hQ3O87Dy?= =?us-ascii?Q?Z9EMzIn0byrDWTNrpSD6Oftw2U5AvEyWTVqCUCe+5BnRk/hza7d/qY826UJu?= =?us-ascii?Q?/+LvbphjzfJ0cbusYhs8ut9+GK2Sn5REVEErV1FulkmoLXBH4Xgik9RoS5rD?= =?us-ascii?Q?Rq5qsYLX5v6CpBhp+WwJgF17cWDuXyiB87iMYrXEXawoSY+Ci2MpHJPKgztO?= =?us-ascii?Q?KnqlogGsnNO55CW0/sPc0N6/MnjmBUlIWCxH3Czz1F+OpyYV6Zz/KOJvz4FM?= =?us-ascii?Q?s6oYAqZPBbCAUTEhxvnljpdMQSr2GUnzVt/2ZJ07KSGkW+Tt8oOQYvDFwuUR?= =?us-ascii?Q?D50r51OpHlYwegilzdYEVuI4YncOyjPAzQthxnBS7Yf2oYFoX4SnK8A5yFTa?= =?us-ascii?Q?dUziXJftAV8tlYWUa1OLXhop/1FV/nsPIEQQO2R7rX55mbspn+0lArmduNEQ?= =?us-ascii?Q?z3w9IjRzmjE2wVBVb7w34ZHWvIFbh+1oW4TKhT0ULmZ3uc763hxuca8MwCtu?= =?us-ascii?Q?26r18J7n+RuQ1jlxd7+0jfaS/wuUbruZFTeyPl9c27NNhZsGkscexIiINhRx?= =?us-ascii?Q?4fqoI8mAaEIKlaBFEjzGmcsFOYmNcrcVpE1vZy/eH/ayn91QhJXuOuapEMSH?= =?us-ascii?Q?xZPl1LVFjSwZXjMEd0os4zoNZ7ua5KANSkdsjv4clk5yTPyEwbcTj56FVgCL?= =?us-ascii?Q?lQSYUADqxAJADDQ93iIR3Hw/oNVnmNu24DtRG7srdbOTI+aTq+C40qMHpFok?= =?us-ascii?Q?X325434h2d1PXFC9IE1W9gbtWfZT5cRNZJizMIf6+nCmoVjQCqNMUit7JyAB?= =?us-ascii?Q?EDDG043hVBfRVa2s46v0WbhaiUOdpZ1MP/msHHsf96djjdDd++VPXTXLcmP5?= =?us-ascii?Q?clQVJB24A9KBwLeiqGya7FH5NtD6YBixLsMErUL0fEqw8uGCAUAb06PMwL/W?= =?us-ascii?Q?DHmlqR2R5hlDwoAn4NlVv5cC4vboUUWa7BGnkRHQNSDg6D9cawlA6X/0nb?= X-Microsoft-Exchange-Diagnostics: 1;BLUPR03MB310;5:tqKCF7Efu0JhcpgbqQMWFrFCD+hIdZ1LVYMcAQoNbOvVhugKQrPl4MJLAyhHj8QwX8p28uh+pUkOQyxtepftNHTiMBdkeWA2FggXRTm4PnJrvUQKqyKzs3onVJ/pTKfcu0ZLFyz6PVwchf/j2leM+w==;24:GxJIQGbiXI6NhcnNG085Xycu3SyEsp4SJF7tOYxoO8/BWeQ+gaoNIhjwKdPIdyvZ0tXaDyh2U7C1Ku81nzajv9goAeYpo4/JQp6jAxd8F9E=;20:ivDsf/cI+Z+hTahiifrFgMTvyyjz2ti9b1G1kk6Ip14B7cKxLyqEyBV+JxtIyGQ3sxqKFSRqwJez7k0NGfeZbT3UqoWBh1h7KvcxAG7kcSE7vRoTMLCjRpZtaDPJw95FNntq759whFhksicoVTyZftKJz0G+NjPon7sbw7BR+f4= X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Sep 2015 15:27:42.2819 (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: BLUPR03MB310 X-Microsoft-Exchange-Diagnostics: 1;BLUPR03MB248;2:U7jAPT0IM/ozIUmdAxSOMBc5GgyCwbT6QM8UT3l96bwPkBIOJob8z0KJW4vQBggaWAdnrCeK1r1F+WzLnYE0izM7xflHJktntooS5Z74vg9AEcl8ghZTgvnXFIaA78b8OpF/ANfhDVH0OdEQu21baCeXhQY1oW0URG4Psee/qzw=;23:bdYQI7ShEOtWc4LzaP7WPVLgu62SyA9mAu/zd0byNg75vHhus3+yAOaMNcppzzWjksnuzPpYK7OxZ1lWgmI0Yy5I4DlNn4/vwAAVuEfDoOlahQYQXCNMEL1WVof/wGDw5plAg38fmQvmtUVLvPxm2loiD9S2xCPAHgY7swC4UpZVbU8OqGB01pH545nDxIwV X-OriginatorOrg: opensource.altera.com Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Alan Tull Add driver to fpga manager framework to allow configuration of FPGA in Altera SoCFPGA parts. Signed-off-by: Alan Tull Acked-by: Michal Simek Acked-by: Moritz Fischer --- v2: fpga_manager struct now contains struct device fpga_manager_register parameters now take device v3: skip a version to align versions v4: move to drivers/staging v5: fix array_size.cocci warnings fix platform_no_drv_owner.cocci warnings Remove .owner = THIS_MODULE include asm/irq.h clean up list of includes use altera_fpga_reset for ops use enum fpga_mgr_states or u32 as needed use devm_request_irq check irq <= 0 instead of == NO_IRQ Use ARRAY_SIZE rename altera -> socfpga static const socfpga_fpga_ops header moved to linux/fpga/ folder remove ifdef'ed code use platform_get_resource and platform_get_irq move .probe and .remove lines adjacent use module_platform_driver use __maybe_unused only need to 'if (IS_ENABLED(CONFIG_REGULATOR))' in one fn fix "unsigned 'mode' is never < 0" v6: return error for (unused) default of case statement v7: PTR_ERR should access the value just tested by IS_ERR v8: change compatible string to be more chip specific v9: update copyright year remove suspend/resume support and regulators use updated fn names for register/unregister use updated params for write_init check for partial reconfiguration request v10: make tristate in Kconfig clean up include add flags param to write_complete() move do drivers/fpga v11: No code change in this patch for v11 of the patch set Adding Moritz' ACK --- drivers/fpga/Kconfig | 10 + drivers/fpga/Makefile | 1 + drivers/fpga/socfpga.c | 616 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 627 insertions(+) create mode 100644 drivers/fpga/socfpga.c diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index f1f1f6d..dfc1f1e 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -11,4 +11,14 @@ config FPGA kernel. The FPGA framework adds a FPGA manager class and FPGA manager drivers. +if FPGA + +config FPGA_MGR_SOCFPGA + tristate "Altera SOCFPGA FPGA Manager" + depends on ARCH_SOCFPGA + help + FPGA manager driver support for Altera SOCFPGA. + +endif # FPGA + endmenu diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index 3313c52..ba6c5c5 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_FPGA) += fpga-mgr.o # FPGA Manager Drivers +obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o diff --git a/drivers/fpga/socfpga.c b/drivers/fpga/socfpga.c new file mode 100644 index 0000000..706b80d --- /dev/null +++ b/drivers/fpga/socfpga.c @@ -0,0 +1,616 @@ +/* + * FPGA Manager Driver for Altera SOCFPGA + * + * Copyright (C) 2013-2015 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 +#include + +/* Register offsets */ +#define SOCFPGA_FPGMGR_STAT_OFST 0x0 +#define SOCFPGA_FPGMGR_CTL_OFST 0x4 +#define SOCFPGA_FPGMGR_DCLKCNT_OFST 0x8 +#define SOCFPGA_FPGMGR_DCLKSTAT_OFST 0xc +#define SOCFPGA_FPGMGR_GPIO_INTEN_OFST 0x830 +#define SOCFPGA_FPGMGR_GPIO_INTMSK_OFST 0x834 +#define SOCFPGA_FPGMGR_GPIO_INTTYPE_LEVEL_OFST 0x838 +#define SOCFPGA_FPGMGR_GPIO_INT_POL_OFST 0x83c +#define SOCFPGA_FPGMGR_GPIO_INTSTAT_OFST 0x840 +#define SOCFPGA_FPGMGR_GPIO_RAW_INTSTAT_OFST 0x844 +#define SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST 0x84c +#define SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST 0x850 + +/* Register bit defines */ +/* SOCFPGA_FPGMGR_STAT register mode field values */ +#define SOCFPGA_FPGMGR_STAT_POWER_UP 0x0 /*ramping*/ +#define SOCFPGA_FPGMGR_STAT_RESET 0x1 +#define SOCFPGA_FPGMGR_STAT_CFG 0x2 +#define SOCFPGA_FPGMGR_STAT_INIT 0x3 +#define SOCFPGA_FPGMGR_STAT_USER_MODE 0x4 +#define SOCFPGA_FPGMGR_STAT_UNKNOWN 0x5 +#define SOCFPGA_FPGMGR_STAT_STATE_MASK 0x7 +/* This is a flag value that doesn't really happen in this register field */ +#define SOCFPGA_FPGMGR_STAT_POWER_OFF 0x0 + +#define MSEL_PP16_FAST_NOAES_NODC 0x0 +#define MSEL_PP16_FAST_AES_NODC 0x1 +#define MSEL_PP16_FAST_AESOPT_DC 0x2 +#define MSEL_PP16_SLOW_NOAES_NODC 0x4 +#define MSEL_PP16_SLOW_AES_NODC 0x5 +#define MSEL_PP16_SLOW_AESOPT_DC 0x6 +#define MSEL_PP32_FAST_NOAES_NODC 0x8 +#define MSEL_PP32_FAST_AES_NODC 0x9 +#define MSEL_PP32_FAST_AESOPT_DC 0xa +#define MSEL_PP32_SLOW_NOAES_NODC 0xc +#define MSEL_PP32_SLOW_AES_NODC 0xd +#define MSEL_PP32_SLOW_AESOPT_DC 0xe +#define SOCFPGA_FPGMGR_STAT_MSEL_MASK 0x000000f8 +#define SOCFPGA_FPGMGR_STAT_MSEL_SHIFT 3 + +/* SOCFPGA_FPGMGR_CTL register */ +#define SOCFPGA_FPGMGR_CTL_EN 0x00000001 +#define SOCFPGA_FPGMGR_CTL_NCE 0x00000002 +#define SOCFPGA_FPGMGR_CTL_NCFGPULL 0x00000004 + +#define CDRATIO_X1 0x00000000 +#define CDRATIO_X2 0x00000040 +#define CDRATIO_X4 0x00000080 +#define CDRATIO_X8 0x000000c0 +#define SOCFPGA_FPGMGR_CTL_CDRATIO_MASK 0x000000c0 + +#define SOCFPGA_FPGMGR_CTL_AXICFGEN 0x00000100 + +#define CFGWDTH_16 0x00000000 +#define CFGWDTH_32 0x00000200 +#define SOCFPGA_FPGMGR_CTL_CFGWDTH_MASK 0x00000200 + +/* SOCFPGA_FPGMGR_DCLKSTAT register */ +#define SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE 0x1 + +/* SOCFPGA_FPGMGR_GPIO_* registers share the same bit positions */ +#define SOCFPGA_FPGMGR_MON_NSTATUS 0x0001 +#define SOCFPGA_FPGMGR_MON_CONF_DONE 0x0002 +#define SOCFPGA_FPGMGR_MON_INIT_DONE 0x0004 +#define SOCFPGA_FPGMGR_MON_CRC_ERROR 0x0008 +#define SOCFPGA_FPGMGR_MON_CVP_CONF_DONE 0x0010 +#define SOCFPGA_FPGMGR_MON_PR_READY 0x0020 +#define SOCFPGA_FPGMGR_MON_PR_ERROR 0x0040 +#define SOCFPGA_FPGMGR_MON_PR_DONE 0x0080 +#define SOCFPGA_FPGMGR_MON_NCONFIG_PIN 0x0100 +#define SOCFPGA_FPGMGR_MON_NSTATUS_PIN 0x0200 +#define SOCFPGA_FPGMGR_MON_CONF_DONE_PIN 0x0400 +#define SOCFPGA_FPGMGR_MON_FPGA_POWER_ON 0x0800 +#define SOCFPGA_FPGMGR_MON_STATUS_MASK 0x0fff + +#define SOCFPGA_FPGMGR_NUM_SUPPLIES 3 +#define SOCFPGA_RESUME_TIMEOUT 3 + +/* In power-up order. Reverse for power-down. */ +static const char *supply_names[SOCFPGA_FPGMGR_NUM_SUPPLIES] __maybe_unused = { + "FPGA-1.5V", + "FPGA-1.1V", + "FPGA-2.5V", +}; + +struct socfpga_fpga_priv { + void __iomem *fpga_base_addr; + void __iomem *fpga_data_addr; + struct completion status_complete; + int irq; +}; + +struct cfgmgr_mode { + /* Values to set in the CTRL register */ + u32 ctrl; + + /* flag that this table entry is a valid mode */ + bool valid; +}; + +/* For SOCFPGA_FPGMGR_STAT_MSEL field */ +static struct cfgmgr_mode cfgmgr_modes[] = { + [MSEL_PP16_FAST_NOAES_NODC] = { CFGWDTH_16 | CDRATIO_X1, 1 }, + [MSEL_PP16_FAST_AES_NODC] = { CFGWDTH_16 | CDRATIO_X2, 1 }, + [MSEL_PP16_FAST_AESOPT_DC] = { CFGWDTH_16 | CDRATIO_X4, 1 }, + [MSEL_PP16_SLOW_NOAES_NODC] = { CFGWDTH_16 | CDRATIO_X1, 1 }, + [MSEL_PP16_SLOW_AES_NODC] = { CFGWDTH_16 | CDRATIO_X2, 1 }, + [MSEL_PP16_SLOW_AESOPT_DC] = { CFGWDTH_16 | CDRATIO_X4, 1 }, + [MSEL_PP32_FAST_NOAES_NODC] = { CFGWDTH_32 | CDRATIO_X1, 1 }, + [MSEL_PP32_FAST_AES_NODC] = { CFGWDTH_32 | CDRATIO_X4, 1 }, + [MSEL_PP32_FAST_AESOPT_DC] = { CFGWDTH_32 | CDRATIO_X8, 1 }, + [MSEL_PP32_SLOW_NOAES_NODC] = { CFGWDTH_32 | CDRATIO_X1, 1 }, + [MSEL_PP32_SLOW_AES_NODC] = { CFGWDTH_32 | CDRATIO_X4, 1 }, + [MSEL_PP32_SLOW_AESOPT_DC] = { CFGWDTH_32 | CDRATIO_X8, 1 }, +}; + +static u32 socfpga_fpga_readl(struct socfpga_fpga_priv *priv, u32 reg_offset) +{ + return readl(priv->fpga_base_addr + reg_offset); +} + +static void socfpga_fpga_writel(struct socfpga_fpga_priv *priv, u32 reg_offset, + u32 value) +{ + writel(value, priv->fpga_base_addr + reg_offset); +} + +static u32 socfpga_fpga_raw_readl(struct socfpga_fpga_priv *priv, + u32 reg_offset) +{ + return __raw_readl(priv->fpga_base_addr + reg_offset); +} + +static void socfpga_fpga_raw_writel(struct socfpga_fpga_priv *priv, + u32 reg_offset, u32 value) +{ + __raw_writel(value, priv->fpga_base_addr + reg_offset); +} + +static void socfpga_fpga_data_writel(struct socfpga_fpga_priv *priv, u32 value) +{ + writel(value, priv->fpga_data_addr); +} + +static inline void socfpga_fpga_set_bitsl(struct socfpga_fpga_priv *priv, + u32 offset, u32 bits) +{ + u32 val; + + val = socfpga_fpga_readl(priv, offset); + val |= bits; + socfpga_fpga_writel(priv, offset, val); +} + +static inline void socfpga_fpga_clr_bitsl(struct socfpga_fpga_priv *priv, + u32 offset, u32 bits) +{ + u32 val; + + val = socfpga_fpga_readl(priv, offset); + val &= ~bits; + socfpga_fpga_writel(priv, offset, val); +} + +static u32 socfpga_fpga_mon_status_get(struct socfpga_fpga_priv *priv) +{ + return socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST) & + SOCFPGA_FPGMGR_MON_STATUS_MASK; +} + +static u32 socfpga_fpga_state_get(struct socfpga_fpga_priv *priv) +{ + u32 status = socfpga_fpga_mon_status_get(priv); + + if ((status & SOCFPGA_FPGMGR_MON_FPGA_POWER_ON) == 0) + return SOCFPGA_FPGMGR_STAT_POWER_OFF; + + return socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_STAT_OFST) & + SOCFPGA_FPGMGR_STAT_STATE_MASK; +} + +static void socfpga_fpga_clear_done_status(struct socfpga_fpga_priv *priv) +{ + socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST, + SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE); +} + +/* + * Set the DCLKCNT, wait for DCLKSTAT to report the count completed, and clear + * the complete status. + */ +static int socfpga_fpga_dclk_set_and_wait_clear(struct socfpga_fpga_priv *priv, + u32 count) +{ + int timeout = 2; + u32 done; + + /* Clear any existing DONE status. */ + if (socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST)) + socfpga_fpga_clear_done_status(priv); + + /* Issue the DCLK count. */ + socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_DCLKCNT_OFST, count); + + /* Poll DCLKSTAT to see if it completed in the timeout period. */ + do { + done = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_DCLKSTAT_OFST); + if (done == SOCFPGA_FPGMGR_DCLKSTAT_DCNTDONE_E_DONE) { + socfpga_fpga_clear_done_status(priv); + return 0; + } + udelay(1); + } while (timeout--); + + return -ETIMEDOUT; +} + +static int socfpga_fpga_wait_for_state(struct socfpga_fpga_priv *priv, + u32 state) +{ + int timeout = 2; + + /* + * HW doesn't support an interrupt for changes in state, so poll to see + * if it matches the requested state within the timeout period. + */ + do { + if ((socfpga_fpga_state_get(priv) & state) != 0) + return 0; + msleep(20); + } while (timeout--); + + return -ETIMEDOUT; +} + +static void socfpga_fpga_enable_irqs(struct socfpga_fpga_priv *priv, u32 irqs) +{ + /* set irqs to level sensitive */ + socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTTYPE_LEVEL_OFST, 0); + + /* set interrupt polarity */ + socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INT_POL_OFST, irqs); + + /* clear irqs */ + socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST, irqs); + + /* unmask interrupts */ + socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTMSK_OFST, 0); + + /* enable interrupts */ + socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTEN_OFST, irqs); +} + +static void socfpga_fpga_disable_irqs(struct socfpga_fpga_priv *priv) +{ + socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_INTEN_OFST, 0); +} + +static irqreturn_t socfpga_fpga_isr(int irq, void *dev_id) +{ + struct socfpga_fpga_priv *priv = dev_id; + u32 irqs, st; + bool conf_done, nstatus; + + /* clear irqs */ + irqs = socfpga_fpga_raw_readl(priv, SOCFPGA_FPGMGR_GPIO_INTSTAT_OFST); + + socfpga_fpga_raw_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST, irqs); + + st = socfpga_fpga_raw_readl(priv, SOCFPGA_FPGMGR_GPIO_EXT_PORTA_OFST); + conf_done = (st & SOCFPGA_FPGMGR_MON_CONF_DONE) != 0; + nstatus = (st & SOCFPGA_FPGMGR_MON_NSTATUS) != 0; + + /* success */ + if (conf_done && nstatus) { + /* disable irqs */ + socfpga_fpga_raw_writel(priv, + SOCFPGA_FPGMGR_GPIO_INTEN_OFST, 0); + complete(&priv->status_complete); + } + + return IRQ_HANDLED; +} + +static int socfpga_fpga_wait_for_config_done(struct socfpga_fpga_priv *priv) +{ + int timeout, ret = 0; + + socfpga_fpga_disable_irqs(priv); + init_completion(&priv->status_complete); + socfpga_fpga_enable_irqs(priv, SOCFPGA_FPGMGR_MON_CONF_DONE); + + timeout = wait_for_completion_interruptible_timeout( + &priv->status_complete, + msecs_to_jiffies(10)); + if (timeout == 0) + ret = -ETIMEDOUT; + + socfpga_fpga_disable_irqs(priv); + return ret; +} + +static int socfpga_fpga_cfg_mode_get(struct socfpga_fpga_priv *priv) +{ + u32 msel; + + msel = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_STAT_OFST); + msel &= SOCFPGA_FPGMGR_STAT_MSEL_MASK; + msel >>= SOCFPGA_FPGMGR_STAT_MSEL_SHIFT; + + /* Check that this MSEL setting is supported */ + if ((msel >= ARRAY_SIZE(cfgmgr_modes)) || !cfgmgr_modes[msel].valid) + return -EINVAL; + + return msel; +} + +static int socfpga_fpga_cfg_mode_set(struct socfpga_fpga_priv *priv) +{ + u32 ctrl_reg; + int mode; + + /* get value from MSEL pins */ + mode = socfpga_fpga_cfg_mode_get(priv); + if (mode < 0) + return mode; + + /* Adjust CTRL for the CDRATIO */ + ctrl_reg = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_CTL_OFST); + ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_CDRATIO_MASK; + ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_CFGWDTH_MASK; + ctrl_reg |= cfgmgr_modes[mode].ctrl; + + /* Set NCE to 0. */ + ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_NCE; + socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg); + + return 0; +} + +static int socfpga_fpga_reset(struct fpga_manager *mgr) +{ + struct socfpga_fpga_priv *priv = mgr->priv; + u32 ctrl_reg, status; + int ret; + + /* + * Step 1: + * - Set CTRL.CFGWDTH, CTRL.CDRATIO to match cfg mode + * - Set CTRL.NCE to 0 + */ + ret = socfpga_fpga_cfg_mode_set(priv); + if (ret) + return ret; + + /* Step 2: Set CTRL.EN to 1 */ + socfpga_fpga_set_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST, + SOCFPGA_FPGMGR_CTL_EN); + + /* Step 3: Set CTRL.NCONFIGPULL to 1 to put FPGA in reset */ + ctrl_reg = socfpga_fpga_readl(priv, SOCFPGA_FPGMGR_CTL_OFST); + ctrl_reg |= SOCFPGA_FPGMGR_CTL_NCFGPULL; + socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg); + + /* Step 4: Wait for STATUS.MODE to report FPGA is in reset phase */ + status = socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_RESET); + + /* Step 5: Set CONTROL.NCONFIGPULL to 0 to release FPGA from reset */ + ctrl_reg &= ~SOCFPGA_FPGMGR_CTL_NCFGPULL; + socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_CTL_OFST, ctrl_reg); + + /* Timeout waiting for reset */ + if (status) + return -ETIMEDOUT; + + return 0; +} + +/* + * Prepare the FPGA to receive the configuration data. + */ +static int socfpga_fpga_ops_configure_init(struct fpga_manager *mgr, u32 flags, + const char *buf, size_t count) +{ + struct socfpga_fpga_priv *priv = mgr->priv; + int ret; + + if (flags & FPGA_MGR_PARTIAL_RECONFIG) { + dev_err(&mgr->dev, "Partial reconfiguration not supported.\n"); + return -EINVAL; + } + /* Steps 1 - 5: Reset the FPGA */ + ret = socfpga_fpga_reset(mgr); + if (ret) + return ret; + + /* Step 6: Wait for FPGA to enter configuration phase */ + if (socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_CFG)) + return -ETIMEDOUT; + + /* Step 7: Clear nSTATUS interrupt */ + socfpga_fpga_writel(priv, SOCFPGA_FPGMGR_GPIO_PORTA_EOI_OFST, + SOCFPGA_FPGMGR_MON_NSTATUS); + + /* Step 8: Set CTRL.AXICFGEN to 1 to enable transfer of config data */ + socfpga_fpga_set_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST, + SOCFPGA_FPGMGR_CTL_AXICFGEN); + + return 0; +} + +/* + * Step 9: write data to the FPGA data register + */ +static int socfpga_fpga_ops_configure_write(struct fpga_manager *mgr, + const char *buf, size_t count) +{ + struct socfpga_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)) { + socfpga_fpga_data_writel(priv, buffer_32[i++]); + count -= sizeof(u32); + } + + /* Write out remaining non 32-bit chunks. */ + switch (count) { + case 3: + socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x00ffffff); + break; + case 2: + socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x0000ffff); + break; + case 1: + socfpga_fpga_data_writel(priv, buffer_32[i++] & 0x000000ff); + break; + case 0: + break; + default: + /* This will never happen. */ + return -EFAULT; + } + + return 0; +} + +static int socfpga_fpga_ops_configure_complete(struct fpga_manager *mgr, + u32 flags) +{ + struct socfpga_fpga_priv *priv = mgr->priv; + u32 status; + + /* + * Step 10: + * - Observe CONF_DONE and nSTATUS (active low) + * - if CONF_DONE = 1 and nSTATUS = 1, configuration was successful + * - if CONF_DONE = 0 and nSTATUS = 0, configuration failed + */ + status = socfpga_fpga_wait_for_config_done(priv); + if (status) + return status; + + /* Step 11: Clear CTRL.AXICFGEN to disable transfer of config data */ + socfpga_fpga_clr_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST, + SOCFPGA_FPGMGR_CTL_AXICFGEN); + + /* + * Step 12: + * - Write 4 to DCLKCNT + * - Wait for STATUS.DCNTDONE = 1 + * - Clear W1C bit in STATUS.DCNTDONE + */ + if (socfpga_fpga_dclk_set_and_wait_clear(priv, 4)) + return -ETIMEDOUT; + + /* Step 13: Wait for STATUS.MODE to report USER MODE */ + if (socfpga_fpga_wait_for_state(priv, SOCFPGA_FPGMGR_STAT_USER_MODE)) + return -ETIMEDOUT; + + /* Step 14: Set CTRL.EN to 0 */ + socfpga_fpga_clr_bitsl(priv, SOCFPGA_FPGMGR_CTL_OFST, + SOCFPGA_FPGMGR_CTL_EN); + + return 0; +} + +/* Translate state register values to FPGA framework state */ +static const enum fpga_mgr_states socfpga_state_to_framework_state[] = { + [SOCFPGA_FPGMGR_STAT_POWER_OFF] = FPGA_MGR_STATE_POWER_OFF, + [SOCFPGA_FPGMGR_STAT_RESET] = FPGA_MGR_STATE_RESET, + [SOCFPGA_FPGMGR_STAT_CFG] = FPGA_MGR_STATE_WRITE_INIT, + [SOCFPGA_FPGMGR_STAT_INIT] = FPGA_MGR_STATE_WRITE_INIT, + [SOCFPGA_FPGMGR_STAT_USER_MODE] = FPGA_MGR_STATE_OPERATING, + [SOCFPGA_FPGMGR_STAT_UNKNOWN] = FPGA_MGR_STATE_UNKNOWN, +}; + +static enum fpga_mgr_states socfpga_fpga_ops_state(struct fpga_manager *mgr) +{ + struct socfpga_fpga_priv *priv = mgr->priv; + enum fpga_mgr_states ret; + u32 state; + + state = socfpga_fpga_state_get(priv); + + if (state < ARRAY_SIZE(socfpga_state_to_framework_state)) + ret = socfpga_state_to_framework_state[state]; + else + ret = FPGA_MGR_STATE_UNKNOWN; + + return ret; +} + +static const struct fpga_manager_ops socfpga_fpga_ops = { + .state = socfpga_fpga_ops_state, + .write_init = socfpga_fpga_ops_configure_init, + .write = socfpga_fpga_ops_configure_write, + .write_complete = socfpga_fpga_ops_configure_complete, +}; + +static int socfpga_fpga_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct socfpga_fpga_priv *priv; + struct resource *res; + int ret; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + priv->fpga_base_addr = devm_ioremap_resource(dev, res); + if (IS_ERR(priv->fpga_base_addr)) + return PTR_ERR(priv->fpga_base_addr); + + 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); + + priv->irq = platform_get_irq(pdev, 0); + if (priv->irq < 0) + return priv->irq; + + ret = devm_request_irq(dev, priv->irq, socfpga_fpga_isr, 0, + dev_name(dev), priv); + if (IS_ERR_VALUE(ret)) + return ret; + + return fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager", + &socfpga_fpga_ops, priv); +} + +static int socfpga_fpga_remove(struct platform_device *pdev) +{ + fpga_mgr_unregister(&pdev->dev); + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id socfpga_fpga_of_match[] = { + { .compatible = "altr,socfpga-fpga-mgr", }, + {}, +}; + +MODULE_DEVICE_TABLE(of, socfpga_fpga_of_match); +#endif + +static struct platform_driver socfpga_fpga_driver = { + .probe = socfpga_fpga_probe, + .remove = socfpga_fpga_remove, + .driver = { + .name = "socfpga_fpga_manager", + .of_match_table = of_match_ptr(socfpga_fpga_of_match), + }, +}; + +module_platform_driver(socfpga_fpga_driver); + +MODULE_AUTHOR("Alan Tull "); +MODULE_DESCRIPTION("Altera SOCFPGA FPGA Manager"); +MODULE_LICENSE("GPL v2"); -- 1.7.9.5