Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753875AbbHMRn7 (ORCPT ); Thu, 13 Aug 2015 13:43:59 -0400 Received: from mail-bl2on0075.outbound.protection.outlook.com ([65.55.169.75]:17040 "EHLO na01-bl2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753513AbbHMRng (ORCPT ); Thu, 13 Aug 2015 13:43:36 -0400 Authentication-Results: spf=fail (sender IP is 66.35.236.236) smtp.mailfrom=opensource.altera.com; ettus.com; dkim=none (message not signed) header.d=none; Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=atull@opensource.altera.com; From: To: , , , , , CC: Moritz Fischer , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Petr Cvek , , , Alan Tull Subject: [PATCH v10 4/8] fpga manager: add driver for socfpga fpga manager Date: Thu, 13 Aug 2015 12:37:28 -0500 Message-ID: <1439487452-23977-6-git-send-email-atull@opensource.altera.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1439487452-23977-1-git-send-email-atull@opensource.altera.com> References: <1439487452-23977-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: CY1PR13CA0115.namprd13.prod.outlook.com (25.164.65.41) To BN3PR03MB1510.namprd03.prod.outlook.com (25.163.35.149) X-Microsoft-Exchange-Diagnostics-untrusted: 1;BN3PR03MB1510;2:xbnKAW6ajpS2PlvKRP0J/C74tqwslJBjBdO/nfKfCP9pr3caFuXGtYNoZBRpexJPD2J2e/cFi/Qkjo/j8taOZDOiyobVZa5pqKuALd0GDoOj+RLrKrtd8bLlTzS0IUsj0YIs9MqVwXLG/Ce01bKHfxbtQIxN6lQSfX642PgUEeM=;3:PVAV5vlTxoJLjuvFss/j6D4XxYPESrfp5M7tFxitG34KGrh5W3LOZMNN7XBFG6zA8AIZygfz5BiSEFEUtmX4zvGJ4cSQpJEe0HdWKeij0BpdGtPKNEaf+OWdWGOFLCsYqjfoKLoe7/EuPNqN5gmedg==;25:06dXBoAbKSA86QODMl00Hwnn8IG4pDWdGAK77CjdDc80A6hfBTybu9ZA6kJcfOeencORjyLp3/rZaR0LbsrA9Ig3HlJxe6gqlc8jpy9bFqfxXs4Jhb2BPVYNho1eZb1RTO4jVAlS0EWhywGZoghsWveaL/U8fj2CzyDYPcLB6awd8498f4OCTogtqRKWjCT0SE01MxoBmcFmd12/O67t+AL0xzp81bsKgOxaxSOTlJKWxwQlcxD7qv8tp+gVAuu5;20:zyodzcD2XebcO1M3W5waD3+q+bDlJDlPw3JxI5ddoWOndwSu0d8xJoIn9x8dysTgc6V3mNyRYAexfqO6aB5u5n7URskGFAt9vm/N4NehklOCZ8zVH/AtlZPLvjd3YeNvu4lzVZFJwMeYQ8Bw3jIBuhUZ/eaCGw49SjajsbZCp+Y= X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BN3PR03MB1510;UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BN1PR03MB040;UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BN1PR03MB071; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:;UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(5005006)(3002001);SRVR:BN3PR03MB1510;BCL:0;PCL:0;RULEID:;SRVR:BN3PR03MB1510;BCL:0;PCL:0;RULEID:(601004)(5005006)(3002001);SRVR:BN1PR03MB040;BCL:0;PCL:0;RULEID:;SRVR:BN1PR03MB040; X-Microsoft-Exchange-Diagnostics-untrusted: 1;BN3PR03MB1510;4:Oz1TKpHA0pQ/FCW1D+sObMwXEvrRfELWaEn+Sgls77hDEQ6RmOrzk6uVOlYmQyCXCh56PbfHUEB6I+fA2Ec8f1/bomGBiyA01MO9vOHsCViSIuNaQA9amhwE5Iix0hcOdltj9zhc9TJQ59eabj2HIagHQ2x3hYtaAkrqCkKLUwF4V6YWXaGNvDKFueZ4noiepDbmxeoHlLYav/S/gzTEje7Qdj6GJtu3HD8Y5nMHvOo3d54q15+A+w4vf7W80y+bbtt8JBVOSgSbGREkBnwti9TzfcZnD4IuNSDoWoC9fgg= X-Forefront-PRVS: 0667289FF8 X-Forefront-Antispam-Report-Untrusted: SFV:NSPM;SFS:(10009020)(6009001)(199003)(189002)(50986999)(86362001)(87976001)(48376002)(50466002)(77156002)(101416001)(2950100001)(76176999)(5003940100001)(122386002)(15975445007)(69596002)(53416004)(42186005)(62966003)(97736004)(40100003)(229853001)(189998001)(575784001)(5001960100002)(81156007)(107886002)(50226001)(5001860100001)(86152002)(4001540100001)(64706001)(66066001)(2201001)(47776003)(5001920100001)(5001770100001)(46102003)(19580395003)(68736005)(33646002)(92566002)(77096005)(19580405001)(106356001)(105586002)(5001830100001)(7059030)(2004002)(2101003)(4001430100001);DIR:OUT;SFP:1101;SCL:1;SRVR:BN3PR03MB1510;H:linuxheads99.altera.com;FPR:;SPF:None;PTR:InfoNoRecords;A:0;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics-untrusted: =?us-ascii?Q?1;BN3PR03MB1510;23:0y8Q0kzwXtLklVVsy3esVGQ4laZCk7jNGA3v2Al86?= =?us-ascii?Q?0DXZc+HOP8tomQ3WT11fKxqWesxm90CpEf/yY/TKfqQZ5SrkERvNEA67OCu5?= =?us-ascii?Q?A48v3mF5nizsB2I51zpVWpzXNO9x2R5QwJx11dcPDYVzq6I4U/NruzSkbI/K?= =?us-ascii?Q?l4xDPWwsU1BiTA78yE5mXNMXIL4U7s1s2GNO2TXuSrf1cJTvER7oQ7WFERGN?= =?us-ascii?Q?NLGxM+8F0jG48/vYZO1UW1VPvzdH1ENX6Ci8u6PLGsYEmEpp09j8uBHEn0yN?= =?us-ascii?Q?eYv14A7Fl9+B8R1P2K+KNqG7s1OBUSf5Y8gwMyUlDI1J0oU/tYv6yrc0nsU0?= =?us-ascii?Q?7V3Mq5cXolzx8azWuNX10L77FuPM3FWa6TMoCibRy6qv9IKwNaVLHL7L2j7i?= =?us-ascii?Q?8E/Mk0AypjgT2G+3LejzP7HlBBMCnOgoeTQ5SxpklsPpQT7596/l7cAR+20F?= =?us-ascii?Q?lTWqQib+xhu8IIHdu/tnzaUiGMtXbQPDvuPqGpJA8TkYEmhX/6+5ybbXJ35F?= =?us-ascii?Q?jqg/1rFC/7heGSevg7qGRpdw5601bpRsy+vSle+xl+dajGeMPfbi3AwHza5j?= =?us-ascii?Q?7dyQWL/xhB/kPfR54mvclBKQc4tuLwX5Jb4o+GiCkkmwmjm+XI+ODgbF502Q?= =?us-ascii?Q?89+o4MRtRG0KB0GQNST+q/qlD2d5wiepL9ncob7WWp+tdPZSTB1AHjVWF4QK?= =?us-ascii?Q?lksFh3WTojPXPTD20xH2GFV3IMRVm1qPddj8pX9jR82r5+L84xf41zEqVdNm?= =?us-ascii?Q?2i4mT+aHto7i4voucCEKsLs1HmhhyJbJy0UCf6KaQA3774NQmzSJMLuaTg0b?= =?us-ascii?Q?yDn+rAuo9NqQkwdkCrCw8v6zf5TRMMztd7Eax0XKqTHbi9Gl7HweUhcetLWd?= =?us-ascii?Q?y8sYh2JarW3OQDkzQg6ElIzNKy/SQKm0rOtvasA5EpVkKSXTBffbESXhAJMU?= =?us-ascii?Q?REUQ7AJ10o3tUnkwWyQwhe0fG9iz+4dYg/DLFdlwNfrRbkJzZ9fqdJjcjaWN?= =?us-ascii?Q?LePzQNaomhTXulYluLAFfJpn/X6c7vI7zJqp26OeEZEYlnoV/7mU8cNCsldV?= =?us-ascii?Q?A7TfhkURdvHPdD9i+GLJjken+soJGrlVI1gL7cmWGDOE8c5SvZcIwj75s4rc?= =?us-ascii?Q?GZ7EyOzIWDhFtNVwRFjfSG3zSWK8JMcpjAKcVZkPPTmjzErKvXAtZcLqmwHv?= =?us-ascii?Q?GQFw3tv+lafsVW7cEfb3ni+5t0nvkP0uPIprGlq0nlrr7ClezFr9h05w6f1b?= =?us-ascii?Q?56oWPxhifXyoll2k/3us4Km/qW1/aUgF/nGJzS6qsaYivE45tDOK3Ypx+N1F?= =?us-ascii?Q?uvdQqdwL6dJCdNtqEgyQyuBrdz++bhAmOs8npgvOPn+?= X-Microsoft-Exchange-Diagnostics-untrusted: 1;BN3PR03MB1510;5:ghpcR98pgI6bDCDllCHkIBIuNGBcM6Y+dj699hJduNYboBFWDGA/7LqyC95HXJ+Q0Ue8/h57mGDpSVOAOkep7GF5hUutjBBcnIausbXTVSyXn+6g9OrxdPOrvQ/s95BvFKyj1sYkZ1Mdw7G1YJ9LVA==;24:NlMEpZMOduyFppiXZdvIMr5Z/MKubcUzIdS7kS0ZCjbf5h1Q8cWwmpUdUkI6UoWfmQa2EJEXB80sQJNxyE2mLYynyr2Am7yeRaWSfi6tU4Q=;20:i4Htxj5XhXkg7gjP4xTamG3FXrL5REWm80sh1IF8X/4DciQZ8tSDRFGVNIWBuKGc77+yiFaTMXSd53KcR6zw1fW7kCi7CeUEvD5zdaHjaXbPEIFkLSXbY6/Y5TFlNp5T2+sAYymf3ILknLtIUfLBiWiKJnS8zZ6vKIRrXFtA0kc= SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN3PR03MB1510 X-EOPAttributedMessage: 0 X-MS-Exchange-Transport-CrossTenantHeadersStripped: BN1BFFO11FD041.protection.gbl X-Microsoft-Exchange-Diagnostics: 1;BN1BFFO11FD041;1:TqrLYTzNZSrwLlqLaLXgjWduUwTbBJOhnPq+uzntZVIjizCswZ4PcHcV5T7p989A2nqcZRL3J8TLA2DmnL7HuotU/2VLbj/zr+AeJvr4rHDA6SybD5R0+xKzAinDTuBgBUcIOB7PPTepeWmIZbpRjT9epZK7C9J7crgZEv3ka4S8Q64Y02wAcKuBfvWWMnBDDKzUGHp2mmCPiI+8tAi0Q8i5cMoE4cjd8gwnHui/ijRnyCjiz6D4VQn9tcK79Q0evBfQ56TnF2oOuPGNV6HYtXQ5jYBKgWNVohVQo0KeLvZVGjI2GRb7N8ix0YYKUqH0KiscL7VCSfsXKuXjx2cCS9PfHzdCIbq3c8zqY5otfX6gx/DncKpDw4WOnjDKtKHDmEkAqHKAuBAaYj+mmYrdqQ== X-Forefront-Antispam-Report: CIP:66.35.236.236;CTRY:US;IPV:NLI;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(2980300002)(339900001)(3050300001)(199003)(189002)(4001540100001)(68736005)(16796002)(105606002)(19580405001)(33646002)(2950100001)(6806004)(77096005)(15975445007)(106466001)(40100003)(48376002)(50986999)(62966003)(50226001)(77156002)(50466002)(66066001)(64706001)(2201001)(122386002)(86152002)(86362001)(87936001)(19580395003)(85426001)(53416004)(76176999)(575784001)(92566002)(107886002)(81156007)(5001960100002)(5003940100001)(189998001)(229853001)(5001830100001)(5001920100001)(46102003)(5001860100001)(47776003)(97736004)(5001770100001)(6070500001)(7099028)(7059030)(2004002)(2101003)(4001430100001);DIR:OUT;SFP:1101;SCL:1;SRVR:BN1PR03MB040;H:sj-itexedge04.altera.priv.altera.com;FPR:;SPF:Fail;PTR:InfoDomainNonexistent;A:0;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;BN1PR03MB040;2:RAfZjYq1A17QRDDO4CERHwS17eNdSuQssdgUySeekBtESMCiRsKwEgNljcyzmUhBkOLl488oE53Gp18IBDiUZCo9ox8zSuqylQxp29aAjQVOasJH51B9jDYgocKuK6oLXL5EbVTxdxStAS6+98pP1yKpspTDZtAfFeWwS8pEg6Y=;3:dEcfV1Cl6aQMMQypr4GXpr6u7UP7RTSz1z4hpTYRp+WEiq5TnU5TaExHNXR0rR1qx5jQPgADaqpHKDAmiY+St8KaaW/EgCo70Hrq02VVR9sncLQZNMrvwyf9sfIPt4wMMpoZR9UH0KYoAdbQL72AclWqyZRucllr4LwHqSPRFtZr4/P5z1mZTl5i7vsxK7PFpb88pSRmNaVnRBumjFae/mMlmh2/Yu1PxDng88tya9s=;25:xBSWK0hO4lioMFFDSB8VkMSexuoXpSfMbwPOOxeTzRD+heS2fU0vFmxKmb1lUBJCqCo6Y0vPmS4YYelGdcpYc8M04agW7mzmPpGXoDv9YUxLfzyMEe56zERXwpVQ+jFgzAcndCMnj6Qkd/YzWihP5i3o09UDf8TwnnWLNvMqPSk2mj4XEedFeY3WqHHtMHK9X21LXoTkme8V1r9VZ57AUUuUlmCOnE9Xep60aPz+ZcSdzRqGwJ7smhH2sAGGbtZO;20:C5vemghUc+RUAa2PxFqn26BtvSkl0GLXHUH6MJN/+r0Pa+wcVal2dHoHrmVheIV0tUVTwbDfpdx6KEezJynIvF25P53/z9GbdbW1dHITPwLhXJhgMz1y++TmNI1vExEX1FHbUKtSov8seSLCOx/xeH4D4Ct+j0E0vuW0EVEherc= BN1PR03MB040: X-MS-Exchange-Organization-RulesExecuted X-Microsoft-Exchange-Diagnostics: 1;BN1PR03MB040;4:i+rRhy4zFBSR6Vura5zvJp6ifFhs2BpaANBwJCSj2LuJXmwN18IBLdafPn5zXiQiLuGQ/Mq5NGNDuDxJug1FVQg1xoqJJK/HD0OD07Bjc1TRrqWIKXWPUhlbUJakC39E8QfRHs1mOg0J/gYyvO9pgDZjsQSaELokorhpbDvHDkdrUkLwzp4T6ZVWY3FoFYFWj82XNMlcLNkgLsyXVhjbta52dJ6hpbmocPftaBaSdzMNjtwz82LNWq6idhDCjWMv6X7QohzSlWU1JaF1eODunTvnlugMMxWmnHAabHZaNC4= X-Forefront-PRVS: 0667289FF8 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BN1PR03MB040;23:UvDYO0GapL3XI+AtVHqeHmPVY6IYs6CW1PuFVy3oeP?= =?us-ascii?Q?xcDQ026GCRyf3HIz8d+nsRBy8VrbokCzf/NLVmo5nQAhW74dFdZNW+BSx0d1?= =?us-ascii?Q?IdTYYzowqe2rbNmq4dOhUYQ0EPnc78P+cqwG5f1GaUM8l1XyHH+vdGQ8Xb7G?= =?us-ascii?Q?6N1zCFECWSpU3GON9VgT3K3/NfCEML4HoROQgTVk3qswdKXgByu92Ld9gTCM?= =?us-ascii?Q?DKQk5IeCsVZt/HqXPGqEVxmezpfDA1YRLC0nw8urddkEHdxxsXyfWRH46N7H?= =?us-ascii?Q?0lWlJ52tbgeb2n97DZHBhNNZnzObOrQRy8I+KRGCbRMh558i2WQRq1VbdlUy?= =?us-ascii?Q?NQOPX5AO/4+JZTr5Hta6yOB8Cyu4n/Z7ySUi3PoWju1zxr7kM2C2TSn9W8AY?= =?us-ascii?Q?lJPW3EZZedP0euDLQ8p1RCB7OnmCV+CDl7weYxJb+tTdYyYD2XqTigRKUR5V?= =?us-ascii?Q?a4Jgnjcjmjly6J9X00PhMX/gwdZGjmTcK/ZuOLEBda2WfVf7buqgfI03f1+e?= =?us-ascii?Q?fZkJD+vN/i6NNlYHQUoXl2GQzum9absi2rltVKeoogfkqQ4Zew4Rv3tddqZ/?= =?us-ascii?Q?arYeUmqgNGcMZaPRl9euAEMd/xq3osOpuXcuUe32nLiCfNvvXL75Nu6Bebcf?= =?us-ascii?Q?k6D133fmqxHgy27n4Q2JrnIEy4EXdYj8Dp2czpmeXmTEfa8Eec779F6IQJaz?= =?us-ascii?Q?URJk3qrFu21WEeu4eWrtqE2yDo+lziRcymcbaL4i9uzgtYtjBBOfjjJJaYi9?= =?us-ascii?Q?zLAj0qWofBQmXIqcVWIu9N0Zhx/f1WHlj6d/wU4vifK/2KsAuLrM6J3XwwjH?= =?us-ascii?Q?n08dL9E3K4ZVBFRoBzwunZgm70jFiiazBLpyRyZp1xh6zpOv2QERG6dZi4/Q?= =?us-ascii?Q?xdnq7EVbYdovK66aV/qpA0R8vasgbpD8QwsyhwmZTqmeFTthDyXRcwPT73dV?= =?us-ascii?Q?3ohvGeFRK4o8RobGcJLh32Xr+J1Zz5VTE82JNCKg6rSb5w7VdhzqG2KK+lQP?= =?us-ascii?Q?5TdcSLmJqovCIZF00c00SlzRzAkm5V9jq1wsYrBhPzJh1CFiFpqZSBvi0GWk?= =?us-ascii?Q?ASHR0HeohS2aIomUAnr/MNtMQ3mvOdcMabwk2yqF9/+SYsW5Jp+gyScq3RJB?= =?us-ascii?Q?CBYCiygkAMCwKm1mLriJgpSI2KVebVatuCbLtXJFwLPBHU+OhGfX1VgYsG5p?= =?us-ascii?Q?w4Uf0WGpJWXIETJYULAhfMo3PFhVF4GY6BslD+7SNhFmaJArkAjX4arQvXPI?= =?us-ascii?Q?nLJUbNjVozY1cJBufKCO/sJ6eSOyYr+45bhynUnCJNjbAx72o886wEuoUGh5?= =?us-ascii?Q?xvyvQLM0Pc3rrXylaE9w8XZUBcSPW7B2WUaXUPmpRrlVjOATOcurVnFF9RM5?= =?us-ascii?Q?pta95WZmHXeLxgcLAq464Lqy3jp8Ayacro5rC2p5Rgq0mSebUuVFIxoqYBtM?= =?us-ascii?Q?KBkAdqklfg0ZUC98Pz0qqLLQT2eGwLMOLtTmrbOcjKcX/uH0SI?= X-Microsoft-Exchange-Diagnostics: 1;BN1PR03MB040;5:TzWWV1pIXlnJfvQhrYOLqPovWroFVMEk8Qe3ODeCqhd/Gus+8W3UIJEmyQys5e6KK4H0JfI2oMUpEJeKlR3Kx5Jf2OcgqC8S/aLda5whjb6lTkjdfqxY4ExI0rYUXk8570iyqYalDUa2zKSCgPXUVg==;24:ndTGcGvRi/xBis+5oLyIbR28RFOWzVbM5Bfnyi3Eyx9f27MHox0Rnfw6sE01yGET00m+TcQfy/7Lhb/W4evvpsHTkztEmQS9N/026TspDa0=;20:yw1+ruSMR4Q9+u9HRjrIO0JNcKLscNm+x84Byk3yZN5RSkSOdEt6NLVPltXd6RNaLx6uwOCgf+LtIk+M29sR2gT+4YPyBAZkSdrEPAFskm4PoxYNFOGxvVJLUT7NIOS7xu7RipKGQyp1xv8+kDvYVHRbNbeBOZGtTun2X69+itE= X-MS-Exchange-CrossTenant-OriginalArrivalTime: 13 Aug 2015 17:43:13.7949 (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.236];Helo=[sj-itexedge04.altera.priv.altera.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN1PR03MB040 X-Microsoft-Exchange-Diagnostics: 1;BN1PR03MB071;2:2t6fTPZ+W5IOL884a1Gart6pwbHXYQyvTTeuWMZ+XmTdtesd1eVWvOb87aV3mdyPUMf8q/8X44hfnmePjw2qx+MT7blxeneol6C3y2Aqph33kR8tnm1eA+Lb1gr3HZE1QTNmUIPHDy3fgr266ErKJkfrV6b5UWSaIinWHmUyTsU=;3:o0NMEpPytY0Wo+1+S0BQuBCtIkUWmyV/kXdXXuEWcTWVfVylKUM0h8EMB/O3NB1u4f26w7c+wSqyO/t9Ct/vlRgmbyxw9qk1x4/vePDH+Jo3AL0W54teo4/elh0kN7Vqa7nVs+yuhrcNq04udzI0gyVEDNxjss76hMd69pkbq9hTwouwxbzgsaCYdWFNx4QVct5Kv6rPce/oZ9OMybKDrsGyYml3nPF/BIIZFmq8fV4=;25:UrI+iVsPh1Ecqg18crppTp47mx0OLyJI1v65rfGKaVP0XX7d9/mk0Sjh5jVL21B10Idu16cKJDiOpMhi5ZIgz7A5EYExPirbZX4vExeHQda9s2T6x5L9pZ4k8uLj9XnttzfuWVUiOHGNb2cFtG96zx155atEdI1Bcln+jHtNUieWJhwIpsjj6s8iRvrnhcj+GwrlxsED5s5sWog8cNyt6So/62w3iVAOg/UA0iroi2PNHwu9deRpuEP4oenxDIbU;23:29iAYPQqVJE9dIcz2TESqSjw98VyQt54Xh7Qb8Zg2EWMNJykX+eGaIxF030ycykZd7RE6spAstkG5QHU5szyggoSQwOlLi7o/8fNW1xFB8ufjMQbOwU6CEmg8khYDoLKkr85zlaS9PqM1EuyhvMOjti+G3kZksXU0HWnhKN6/gjV2c5UtvvCiRetFfKvke132Vzu9moz57n9pEUCGZpsAYFhU7TxQuXKBdvvOfNoMGn74tXcXbz3umZO6b2PUuqE X-OriginatorOrg: opensource.altera.com Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 21412 Lines: 717 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 --- 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 --- 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 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/