From patchwork Wed May 20 03:22:42 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: dinguyen@opensource.altera.com X-Patchwork-Id: 6441871 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id F339BC0432 for ; Wed, 20 May 2015 03:31:55 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5F54E203E5 for ; Wed, 20 May 2015 03:31:54 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 93ABB203DF for ; Wed, 20 May 2015 03:31:52 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Yuugr-0005lH-V8; Wed, 20 May 2015 03:29:05 +0000 Received: from mail-bn1bn0100.outbound.protection.outlook.com ([157.56.110.100] helo=na01-bn1-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YuugX-0005ga-5q for linux-arm-kernel@lists.infradead.org; Wed, 20 May 2015 03:28:47 +0000 Received: from BN3PR0301CA0036.namprd03.prod.outlook.com (10.160.180.174) by SN2PR03MB047.namprd03.prod.outlook.com (10.255.175.147) with Microsoft SMTP Server (TLS) id 15.1.166.22; Wed, 20 May 2015 03:28:20 +0000 Received: from BY2FFO11FD017.protection.gbl (2a01:111:f400:7c0c::134) by BN3PR0301CA0036.outlook.office365.com (2a01:111:e400:4000::46) with Microsoft SMTP Server (TLS) id 15.1.166.22 via Frontend Transport; Wed, 20 May 2015 03:28:19 +0000 Authentication-Results: spf=fail (sender IP is 66.35.236.227) smtp.mailfrom=opensource.altera.com; codeaurora.org; dkim=none (message not signed) header.d=none; Received-SPF: Fail (protection.outlook.com: domain of opensource.altera.com does not designate 66.35.236.227 as permitted sender) receiver=protection.outlook.com; client-ip=66.35.236.227; helo=sj-itexedge03.altera.priv.altera.com; Received: from sj-itexedge03.altera.priv.altera.com (66.35.236.227) by BY2FFO11FD017.mail.protection.outlook.com (10.1.14.105) with Microsoft SMTP Server (TLS) id 15.1.172.14 via Frontend Transport; Wed, 20 May 2015 03:28:19 +0000 Received: from na01-bl2-obe.outbound.protection.outlook.com (207.46.163.207) by webmail.altera.com (66.35.236.227) with Microsoft SMTP Server (TLS) id 14.3.174.1; Tue, 19 May 2015 20:27:03 -0700 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=dinguyen@opensource.altera.com; Received: from linux-builds1.altera.com (64.129.157.38) by BN3PR03MB1365.namprd03.prod.outlook.com (10.163.34.151) with Microsoft SMTP Server (TLS) id 15.1.166.22; Wed, 20 May 2015 03:28:13 +0000 From: To: , Subject: [PATCHv4 2/2] clk: socfpga: add a clock driver for the Arria 10 platform Date: Tue, 19 May 2015 22:22:42 -0500 Message-ID: <1432092162-8889-3-git-send-email-dinguyen@opensource.altera.com> X-Mailer: git-send-email 2.2.1 In-Reply-To: <1432092162-8889-1-git-send-email-dinguyen@opensource.altera.com> References: <1432092162-8889-1-git-send-email-dinguyen@opensource.altera.com> MIME-Version: 1.0 X-Originating-IP: [64.129.157.38] X-ClientProxiedBy: DM2PR10CA0067.namprd10.prod.outlook.com (10.141.241.35) To BN3PR03MB1365.namprd03.prod.outlook.com (25.163.34.151) X-Microsoft-Exchange-Diagnostics-untrusted: 1; BN3PR03MB1365; 2:zPDQa0b6I4dx/wMLQf7BIgAhPF4lHAp2M+hWjNucXIQ3c7PXRMxWK6UxDfj2QBKQ; 2:ENovFbE4x/CEDuN1E+riz/+tauc1lwMhGInb7Uz8tEic7Oeid1ffx7x9+cInYtZLOe5YjPNyOMq1WTdtnGJKpVvMj1MFlrH1I+gyw/yZYZcBD7IdlbeAzoucqOboGnDkXrYJLH8R3i85rRujl6VYbw==; 6:pb2E7TBZ0/dq2K+RYC8nzYOwEcQAy8j3zLsKNjq5pdUu3QRMRTXJwIwNwEhnsHqhLr4jC7HCeSlVryt0sIrqDPf1C3Su+aSHv1dmJjXfSrRSDVHbS8Vy+wf+1LBzQM4+pbnA1gA9/mrBGpmKuIdnaA==; 3:58R5f+f00w0LdLPd49HSninRO4LsLcvDhH1Pn1jzCavMMUGGNUxaLEzsXLtw9GJxW6VCKh9dDsJxNJXQgoGq5R2j5TFbfGEJJwN1GN2mZjIH9Fp84TzIj6O+7PYhvEWpmsnAyhcTkyoNsaEiwK+K4Ig8vXJfvwlD0Sfv9wV1ftrRJGTFMbZevwnLmXLGGizuqy0i9khe47hiJz3XZLfMqnD+Hn2upGtklPVY/P2dM6No2Oc+xRoHFHEaZWxntqNM1Z09z0eH6aTz8beAz+0FEOtyvykZxZ7mamLiXmsOmnc= X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:; SRVR:BN3PR03MB1365; UriScan:; BCL:0; PCL:0; RULEID:; SRVR:SN2PR03MB047; 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:BN3PR03MB1365; BCL:0; PCL:0; RULEID:; SRVR:BN3PR03MB1365; BCL:0; PCL:0; RULEID:(601004)(5005006)(3002001); SRVR:SN2PR03MB047; BCL:0; PCL:0; RULEID:; SRVR:SN2PR03MB047; X-Forefront-PRVS: 0582641F53 X-Forefront-Antispam-Report-Untrusted: SFV:NSPM; SFS:(10009020)(6009001)(189002)(199003)(122386002)(66066001)(50466002)(77156002)(46102003)(53416004)(62966003)(42186005)(101416001)(92566002)(86152002)(87976001)(40100003)(189998001)(86362001)(48376002)(229853001)(47776003)(64706001)(19580395003)(5001960100002)(5001770100001)(5001830100001)(69596002)(5001920100001)(97736004)(5001860100001)(19580405001)(2950100001)(50986999)(77096005)(68736005)(15975445007)(76176999)(81156007)(4001540100001)(106356001)(105586002)(50226001)(33646002)(107886002)(2004002)(4001430100001); DIR:OUT; SFP:1101; SCL:1; SRVR:BN3PR03MB1365; H:linux-builds1.altera.com; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A:0; LANG:en; Received-SPF: None (protection.outlook.com: opensource.altera.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics-untrusted: =?us-ascii?Q?1; BN3PR03MB1365; 9:qPGqCs1qCHjSDcnJAl+ry294bTZYzcvTGD2aWN0GMn?= =?us-ascii?Q?8GhcyZdT7yu33aQAZVnws6sv44XNtutZ93WmyycT45KuAVreDjONVxzZbT4Z?= =?us-ascii?Q?cU7IT024zwBsfffsBgW7qc+YOV/YIt7ID0/0IW/zWP0A66/XXoFO1j0Zp460?= =?us-ascii?Q?3p/K6Fxp+zbmuGHv3PTBQzEbSf5IlZDRD9K6wJc8prcEZxXo+qGCEGeb+GYv?= =?us-ascii?Q?otRIM4X8mdr5YTv3e6w+bemTHR+NuANIVFlpIHlYBCku9ag4UdSqE7nFYUUV?= =?us-ascii?Q?fjuo6R5ydD775XHek/W5kK8IbZIl95bIcEhDjHrpQhS9GWmKe5NddMuOt67X?= =?us-ascii?Q?Vlo1BED6t9KF0KrvMTOEzgLKRzJTGPK40lb34Dmv42HwvzVmwx25ewjEqwzS?= =?us-ascii?Q?C5lpHq51IjH8pArQfzqEyYpdiU8oA5hiaecZGvkJr/jdB9O8hMzywsnO4ya2?= =?us-ascii?Q?GXDzWyVJIE/LS+CtRBK6NfhHIa+qKAISt87Cs9d9hrm1dO91E0NPShJZdRsZ?= =?us-ascii?Q?ipCF+offvmC6k25h6Bih77kyhESWiJnRxDMBvMz+Y7O+RLhoqCTwfgkaDStP?= =?us-ascii?Q?vYXrEVzRQS66iNEVE3X80Y8eK5TEafnvieTP7Tu85wAG+9w+tPhzjTvqXdQN?= =?us-ascii?Q?ktAwHhlBI0BO/JIoPWa/FM6kV6iIDR2AtoXnkrVrdsxDa0+FjvsbIOh7kQTP?= =?us-ascii?Q?0PP76y78vGDMSiLaJS73rgZ9GNxNU1HHmxrRnkMjJ+bclW0Oxd94Ptt/AxIr?= =?us-ascii?Q?8nEPudzu9+sGfflsJ7M9VuMfmnx9ptBLliuUSra08k40chy11jKQ3BbHd5nm?= =?us-ascii?Q?213WlZk844fzDQPRh+i4/wK2ykd535gCLpT093RJS8+p6+eAtsKXVN3OXPmS?= =?us-ascii?Q?Bkv3DQvD7veFWkybMik8GkNTMrHPeewOcylrS9wbpmiRaCng6N0xBf2MWInZ?= =?us-ascii?Q?sZ9+xv35M0NPgp2PpwhjwPG3l8J02w6GyI3gFZQz8iS2TGKu7XZK7B2G5bkx?= =?us-ascii?Q?u6B09aOXuauQA237ezbS49IAOlJ9cl02g9ZojRjD2yVwZFo1nkZbqtWouibE?= =?us-ascii?Q?rRST2nWlPUp4zuL1UyeGell8/g9bHX/V2OEZBWq1ch3raFoD9wRS7UhjNifu?= =?us-ascii?Q?MJbyViPVsdEopfHd1GRkmZ0HdmdLHYjwIBKhhigB7wakXfvQ4E+QXcHpeuJu?= =?us-ascii?Q?xYR255pGtoDNZcq3aTNTq1YwrI1ZJ6PVqxSmwDIvNkbfq5y93zYCdoJQ=3D?= =?us-ascii?Q?=3D?= X-Microsoft-Exchange-Diagnostics-untrusted: 1; BN3PR03MB1365; 3:zgJdCUHVK1Ylo12pHsByZX6/3BqfGflsTYKGCQDVOI2mz7DaY9y/rMI59YLxOA7TNF39cCouPTedxOLyiQIPu6SKZfhGpQjWCml25C1BSLltYk+WLIlE9gL5nRG9tCJsEmCpz+J7Jrz/75N6wWAmHw==; 10:gjzM0P3Go94uhXkExmqsNyBzhU9OSZcW0V2YELUEoQWnUbrdOs8ebgqy8vSqgklme2Gr8jEN+K28g3TJ6QRyMJzxGz6IvQi0/McspHttnBU=; 6:hr64rqhMyIfLqZvQXzhrc+L8X5Ha8zdY2BIpRJwsDYwDB+EB7URLi0Op9XmNhZh1 X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN3PR03MB1365 X-EOPAttributedMessage: 0 X-MS-Exchange-Transport-CrossTenantHeadersStripped: BY2FFO11FD017.protection.gbl X-Microsoft-Exchange-Diagnostics: 1; BY2FFO11FD017; 1:lbv5ibUxbNzKhNAcMKUrtKOlvwCw2CE8Vto+Ck74YlTRCE0h5eKMTIzAZ/VdYeVJhvwn5VSmG00hT/8zr4X1W+klT/sHKkrncMMT60LuDqA1p3IRG0/yygqcNZpYrtVxe14ApgCPlEEZMXWHJeiPFVhZXp7fh1iiVM7cfMS5FPs64sCyAOd+DFWuol2YLPBeyIPosKgKWiFV5XHDALRQ8w3knYqj5wWN7XKpYciLd7wvT722+w7H7UxvgIB16SzkP7GOKpEYEP7nrgM9fVCw9w== X-Forefront-Antispam-Report: CIP:66.35.236.227; CTRY:US; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(339900001)(199003)(189002)(86362001)(92566002)(50466002)(2950100001)(87936001)(122386002)(189998001)(76176999)(86152002)(53416004)(40100003)(105606002)(15975445007)(5001830100001)(229853001)(5001860100001)(16796002)(68736005)(77156002)(62966003)(77096005)(48376002)(64706001)(47776003)(5001960100002)(107886002)(5001770100001)(6070500001)(66066001)(46102003)(50986999)(19580395003)(19580405001)(97736004)(50226001)(106466001)(85426001)(33646002)(4001540100001)(6806004)(81156007)(7099028)(2004002)(4001430100001); DIR:OUT; SFP:1101; SCL:1; SRVR:SN2PR03MB047; H:sj-itexedge03.altera.priv.altera.com; FPR:; SPF:Fail; PTR:InfoDomainNonexistent; A:0; MX:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; SN2PR03MB047; 2:d6uRN+BKefFRy39Ce0bmGC6sYY6x6zOAZr4n0JaTkIjZNH+wtSF9tVs9gdc3ev20; 2:AkZnxdHz+i7CXMhN1z5G6Lf+k1m6IwjknqKBaO1/7GPE273PsKHIotjHgiWpAhA+JiEfn/8oXphpomsGWEhZOarjkG3Li/qV3bAy/1VXSZ6U94GPTMJdbiINOntXhXmWvgjJgV/qGMUS/pMFeOyqqiMDLPVIK61g02hDodl2nWRAaCIUzObmup/x7V3MXOj4gN3b41w1oyGIp7ouc2HFS6S9OKMsNJZbms1mG67l6N4=; 6:GmM33uTQ0AbEEYN3UZBuaHGdGWJpur8xFQF4gVegN/t7hyx6enELgiVDLSYQSJ2ACzSqkxjZcRRyjsCZkVFJg2JJKoAUwQGC+3Q5SZX5PGsxKYgk9So3wC8LNT8zcQzirS2Ohr4+C+X2LoqNQA/jOg==; 3:iHPm16b0Mix26NNsgxOFvlarXpHLq7Vz3yOuEz7Qm+kuC4lp77KRcwM2xNlg+1MX0U45IcUXVll4EOGiTqI4MUJTtzlCgv/1GFef4IRo3MDxCFIDKChIBt/4imWm+oV1De9lE584ScelFCaICNH1QKCZAbbHM4zo3M4wKhX6MGat+Fhg6ZXz5rd4nIoVRfHlG2wyJ1Qr5pR9KHnegMWI8DTLd9EzF+VNhO4GTShwcIZuz3Sl02dBNIjR9+uvvMg3vOVwg8L/lNjrMVRToJ06MOHvcvJ23p9tFHC9vRh0DpY= X-Forefront-PRVS: 0582641F53 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; SN2PR03MB047; 9:oa6ukv86doT090o9F4Nm6r1UsgYaNs9zvaip7VkplmZ?= =?us-ascii?Q?eL5r59oixKUy39ELLmo45s3o+kPO73xoZ3uZuu9m0dedkL+nAMaWjrw2S968?= =?us-ascii?Q?ORQIZ7K9qNsMJHY4XSeAkKbOFFzEQPy0LVrhE42cistP/V4f+u6F5ujq01sQ?= =?us-ascii?Q?276D+/cTxoupaIWgFSi7d4FH5u4bV82RfXzK+oqx/8R+vj9QeUWSkywEWPkV?= =?us-ascii?Q?ahjiiQ1LYWoRyDiS0vCA5Tcf3OqREeEi+uCxYoTKymQrK4hn1JBFCnyrcVfT?= =?us-ascii?Q?2vcUbjPpQI9TvZpwb/gHNQcsEjfHeHQJE3WjKJ4XiHCyZ4P2bcRzv7GpDSMC?= =?us-ascii?Q?4AMnXcf/of4Gra635TrzleN/kVopuURY+3+hMuYwWGIUd7PHKpdGgs/iTbl1?= =?us-ascii?Q?dp3ZzjR4RDHZsQWg2nww1oY5EyEYn/TLYcyySfLgbst6m33iLt/SfQx8dYFW?= =?us-ascii?Q?NsLYVeOUCAMqg3NhxrZgtKDSimVnljh6S5BhCXtRowEqnMQrT6aQB2Cjku1T?= =?us-ascii?Q?w9+M9LjbOmZTRy5wo7zT1zuh1nNR7WOPSvmhJnB87Mt68rrrJIlYbtY3ZEP9?= =?us-ascii?Q?o3EQbxu7hJNmjHqfKFQbBcxnjK7hOKyHyfc+RTbhCFwtvWIzm8voJloiN+BJ?= =?us-ascii?Q?Ku7y2wZPEBBetQM+oh0Go+glz6NV+H+dUCnWsQ1oRajBCXtNuySrDb/BaCQd?= =?us-ascii?Q?4Sa8O4dsHGt5+gttIdXCVYM3qoDRpaF5U3IDzlLsCiBUAWeNvFWiRlNfYBzs?= =?us-ascii?Q?f+fFbLhl3r5jskjT/kRDc3Xe3YjCI4yuJvubJfhFXDRciNInBWZ37qAuaOWf?= =?us-ascii?Q?a+zuCro3M0k6c0zc8o+FXPfQ6Jsgt2+A7GUHCxWWcQ6vVtKn8+PSOm/4xLpc?= =?us-ascii?Q?ydSMISaCyPdCcae+Vg6qaXGLEZ+XL1lKZEKNctd1Qw2Zu7BRONOHMHSgMj0M?= =?us-ascii?Q?tM9NX2O14F3G0JhnjGR6disiHsSQzigJMo5hQl/a9m04emc9YgXvJvkVCeGu?= =?us-ascii?Q?b4LrbCeXurvZ5EH2uXZM3UH4qqcKaysvnQCVFvBo6da58JfR2NUbfSOa03PV?= =?us-ascii?Q?P/FZ4R60IFdhKDeWN+zepKP719hwSiFIRW/4W4aw0C3TOcRM6L06bgBV+pND?= =?us-ascii?Q?Rhba2E6Af9c9Nte+3KbbUpJmpK+XziSeeVOfQiSWO+U+lCDFXiXmLy/dS6GJ?= =?us-ascii?Q?F7R4Rg9cYK/47/pDN2CP5bvCYbr3ST9TywZV1CQNJy+F388VHWELag4/jTVK?= =?us-ascii?Q?Ev90TsGpsLnADfZI=3D?= X-Microsoft-Exchange-Diagnostics: 1; SN2PR03MB047; 3:z7obymItZaskGX9ahVJqYNF9drE7PG6WyAvOXetdmjvwbJc6LQnIUx9fM0sfyTxAOXCAsFonE9Llylpd0J0+zljLzD1suYbP+P/UAohXhZTkXea+NaNNYzs/NHKBL6gkL7bO9get1RzjExaesg/AYg==; 10:n+B28mLjqvmqmohUyQNexfkt3wYhUfigfYV4T+sA4S1ZMIwpqpoNGJd6Be6TJYLgYydQfeusZinTpJFc+nKIs4jBydLli4T2uUD6Q/CTvPc=; 6:q4OLI6N9kutACWomklJLWxh6rNTzGVnRucJrBFFArzCQVq3bZZtg6RFb/VPoKP1P X-OriginatorOrg: opensource.altera.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 May 2015 03:28:19.0109 (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: SN2PR03MB047 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150519_202845_603424_9BD74F05 X-CRM114-Status: GOOD ( 15.21 ) X-Spam-Score: -1.1 (-) Cc: Dinh Nguyen , dinh.linux@gmail.com, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAD_ENC_HEADER,BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Dinh Nguyen The clocks on the Arria 10 platform is a bit different than the Cyclone/Arria 5 platform that it should just have it's own driver. Signed-off-by: Dinh Nguyen --- v4: Move lookup of syscon for clk_phase to gate_clk_init() Remove unused includes v3: Assign pointer to NULL instead of integer 0 per sparse check --- drivers/clk/socfpga/Makefile | 1 + drivers/clk/socfpga/clk-gate-a10.c | 188 +++++++++++++++++++++++++++++++++++ drivers/clk/socfpga/clk-periph-a10.c | 138 +++++++++++++++++++++++++ drivers/clk/socfpga/clk-pll-a10.c | 129 ++++++++++++++++++++++++ drivers/clk/socfpga/clk.c | 7 +- drivers/clk/socfpga/clk.h | 5 + 6 files changed, 467 insertions(+), 1 deletion(-) create mode 100644 drivers/clk/socfpga/clk-gate-a10.c create mode 100644 drivers/clk/socfpga/clk-periph-a10.c create mode 100644 drivers/clk/socfpga/clk-pll-a10.c diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile index 7e2d15a..d8bb239 100644 --- a/drivers/clk/socfpga/Makefile +++ b/drivers/clk/socfpga/Makefile @@ -2,3 +2,4 @@ obj-y += clk.o obj-y += clk-gate.o obj-y += clk-pll.o obj-y += clk-periph.o +obj-y += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o diff --git a/drivers/clk/socfpga/clk-gate-a10.c b/drivers/clk/socfpga/clk-gate-a10.c new file mode 100644 index 0000000..01fee80 --- /dev/null +++ b/drivers/clk/socfpga/clk-gate-a10.c @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2015 Altera Corporation. All rights reserved + * + * 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 "clk.h" + +#define streq(a, b) (strcmp((a), (b)) == 0) + +#define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw) + +/* SDMMC Group for System Manager defines */ +#define SYSMGR_SDMMCGRP_CTRL_OFFSET 0x28 + +static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk, + unsigned long parent_rate) +{ + struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk); + u32 div = 1, val; + + if (socfpgaclk->fixed_div) + div = socfpgaclk->fixed_div; + else if (socfpgaclk->div_reg) { + val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift; + val &= div_mask(socfpgaclk->width); + div = (1 << val); + } + + return parent_rate / div; +} + +static int socfpga_clk_prepare(struct clk_hw *hwclk) +{ + struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk); + int i; + u32 hs_timing; + u32 clk_phase[2]; + + if (socfpgaclk->clk_phase[0] || socfpgaclk->clk_phase[1]) { + for (i = 0; i < ARRAY_SIZE(clk_phase); i++) { + switch (socfpgaclk->clk_phase[i]) { + case 0: + clk_phase[i] = 0; + break; + case 45: + clk_phase[i] = 1; + break; + case 90: + clk_phase[i] = 2; + break; + case 135: + clk_phase[i] = 3; + break; + case 180: + clk_phase[i] = 4; + break; + case 225: + clk_phase[i] = 5; + break; + case 270: + clk_phase[i] = 6; + break; + case 315: + clk_phase[i] = 7; + break; + default: + clk_phase[i] = 0; + break; + } + } + + hs_timing = SYSMGR_SDMMC_CTRL_SET(clk_phase[0], clk_phase[1]); + if (!IS_ERR(socfpgaclk->sys_mgr_base_addr)) + regmap_write(socfpgaclk->sys_mgr_base_addr, + SYSMGR_SDMMCGRP_CTRL_OFFSET, hs_timing); + else + pr_err("%s: cannot set clk_phase because sys_mgr_base_addr\ + is not available!\n", __func__); + } + return 0; +} + +static struct clk_ops gateclk_ops = { + .prepare = socfpga_clk_prepare, + .recalc_rate = socfpga_gate_clk_recalc_rate, +}; + +static void __init __socfpga_gate_init(struct device_node *node, + const struct clk_ops *ops) +{ + u32 clk_gate[2]; + u32 div_reg[3]; + u32 clk_phase[2]; + u32 fixed_div; + struct clk *clk; + struct socfpga_gate_clk *socfpga_clk; + const char *clk_name = node->name; + const char *parent_name[SOCFPGA_MAX_PARENTS]; + struct clk_init_data init; + int rc; + int i = 0; + + socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL); + if (WARN_ON(!socfpga_clk)) + return; + + rc = of_property_read_u32_array(node, "clk-gate", clk_gate, 2); + if (rc) + clk_gate[0] = 0; + + if (clk_gate[0]) { + socfpga_clk->hw.reg = clk_mgr_a10_base_addr + clk_gate[0]; + socfpga_clk->hw.bit_idx = clk_gate[1]; + + gateclk_ops.enable = clk_gate_ops.enable; + gateclk_ops.disable = clk_gate_ops.disable; + } + + rc = of_property_read_u32(node, "fixed-divider", &fixed_div); + if (rc) + socfpga_clk->fixed_div = 0; + else + socfpga_clk->fixed_div = fixed_div; + + rc = of_property_read_u32_array(node, "div-reg", div_reg, 3); + if (!rc) { + socfpga_clk->div_reg = clk_mgr_a10_base_addr + div_reg[0]; + socfpga_clk->shift = div_reg[1]; + socfpga_clk->width = div_reg[2]; + } else { + socfpga_clk->div_reg = NULL; + } + + rc = of_property_read_u32_array(node, "clk-phase", clk_phase, 2); + if (!rc) { + socfpga_clk->clk_phase[0] = clk_phase[0]; + socfpga_clk->clk_phase[1] = clk_phase[1]; + + socfpga_clk->sys_mgr_base_addr = syscon_regmap_lookup_by_compatible("altr,sys-mgr"); + if (IS_ERR(socfpga_clk->sys_mgr_base_addr)) { + pr_err("%s: failed to find altr,sys-mgr regmap!\n", __func__); + return; + } + } + + of_property_read_string(node, "clock-output-names", &clk_name); + + init.name = clk_name; + init.ops = ops; + init.flags = 0; + while (i < SOCFPGA_MAX_PARENTS && (parent_name[i] = + of_clk_get_parent_name(node, i)) != NULL) + i++; + + init.parent_names = parent_name; + init.num_parents = i; + socfpga_clk->hw.hw.init = &init; + + clk = clk_register(NULL, &socfpga_clk->hw.hw); + if (WARN_ON(IS_ERR(clk))) { + kfree(socfpga_clk); + return; + } + rc = of_clk_add_provider(node, of_clk_src_simple_get, clk); + if (WARN_ON(rc)) + return; +} + +void __init socfpga_a10_gate_init(struct device_node *node) +{ + __socfpga_gate_init(node, &gateclk_ops); +} diff --git a/drivers/clk/socfpga/clk-periph-a10.c b/drivers/clk/socfpga/clk-periph-a10.c new file mode 100644 index 0000000..9d0181b --- /dev/null +++ b/drivers/clk/socfpga/clk-periph-a10.c @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2015 Altera Corporation. All rights reserved + * + * 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 "clk.h" + +#define CLK_MGR_FREE_SHIFT 16 +#define CLK_MGR_FREE_MASK 0x7 + +#define SOCFPGA_MPU_FREE_CLK "mpu_free_clk" +#define SOCFPGA_NOC_FREE_CLK "noc_free_clk" +#define SOCFPGA_SDMMC_FREE_CLK "sdmmc_free_clk" +#define to_socfpga_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw.hw) + +static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk, + unsigned long parent_rate) +{ + struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hwclk); + u32 div; + + if (socfpgaclk->fixed_div) { + div = socfpgaclk->fixed_div; + } else if (socfpgaclk->div_reg) { + div = readl(socfpgaclk->div_reg) >> socfpgaclk->shift; + div &= div_mask(socfpgaclk->width); + div += 1; + } else { + div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1); + } + + return parent_rate / div; +} + +static u8 clk_periclk_get_parent(struct clk_hw *hwclk) +{ + struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hwclk); + u32 clk_src; + + clk_src = readl(socfpgaclk->hw.reg); + if (streq(hwclk->init->name, SOCFPGA_MPU_FREE_CLK) || + streq(hwclk->init->name, SOCFPGA_NOC_FREE_CLK) || + streq(hwclk->init->name, SOCFPGA_SDMMC_FREE_CLK)) + return (clk_src >> CLK_MGR_FREE_SHIFT) & + CLK_MGR_FREE_MASK; + else + return 0; +} + +static const struct clk_ops periclk_ops = { + .recalc_rate = clk_periclk_recalc_rate, + .get_parent = clk_periclk_get_parent, +}; + +static __init void __socfpga_periph_init(struct device_node *node, + const struct clk_ops *ops) +{ + u32 reg; + struct clk *clk; + struct socfpga_periph_clk *periph_clk; + const char *clk_name = node->name; + const char *parent_name; + struct clk_init_data init; + int rc; + u32 fixed_div; + u32 div_reg[3]; + + of_property_read_u32(node, "reg", ®); + + periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL); + if (WARN_ON(!periph_clk)) + return; + + periph_clk->hw.reg = clk_mgr_a10_base_addr + reg; + + rc = of_property_read_u32_array(node, "div-reg", div_reg, 3); + if (!rc) { + periph_clk->div_reg = clk_mgr_a10_base_addr + div_reg[0]; + periph_clk->shift = div_reg[1]; + periph_clk->width = div_reg[2]; + } else { + periph_clk->div_reg = NULL; + } + + rc = of_property_read_u32(node, "fixed-divider", &fixed_div); + if (rc) + periph_clk->fixed_div = 0; + else + periph_clk->fixed_div = fixed_div; + + of_property_read_string(node, "clock-output-names", &clk_name); + + init.name = clk_name; + init.ops = ops; + init.flags = 0; + + parent_name = of_clk_get_parent_name(node, 0); + init.num_parents = 1; + init.parent_names = &parent_name; + + periph_clk->hw.hw.init = &init; + + clk = clk_register(NULL, &periph_clk->hw.hw); + if (WARN_ON(IS_ERR(clk))) { + kfree(periph_clk); + return; + } + rc = of_clk_add_provider(node, of_clk_src_simple_get, clk); + if (rc < 0) { + pr_err("Could not register clock provider for node:%s\n", + clk_name); + goto err_clk; + } + + return; + +err_clk: + clk_unregister(clk); +} + +void __init socfpga_a10_periph_init(struct device_node *node) +{ + __socfpga_periph_init(node, &periclk_ops); +} diff --git a/drivers/clk/socfpga/clk-pll-a10.c b/drivers/clk/socfpga/clk-pll-a10.c new file mode 100644 index 0000000..1178b11 --- /dev/null +++ b/drivers/clk/socfpga/clk-pll-a10.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2015 Altera Corporation. All rights reserved + * + * 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 "clk.h" + +/* Clock Manager offsets */ +#define CLK_MGR_PLL_CLK_SRC_SHIFT 8 +#define CLK_MGR_PLL_CLK_SRC_MASK 0x3 + +/* Clock bypass bits */ +#define SOCFPGA_PLL_BG_PWRDWN 0 +#define SOCFPGA_PLL_PWR_DOWN 1 +#define SOCFPGA_PLL_EXT_ENA 2 +#define SOCFPGA_PLL_DIVF_MASK 0x00001FFF +#define SOCFPGA_PLL_DIVF_SHIFT 0 +#define SOCFPGA_PLL_DIVQ_MASK 0x003F0000 +#define SOCFPGA_PLL_DIVQ_SHIFT 16 +#define SOCFGPA_MAX_PARENTS 5 + +#define SOCFPGA_MAIN_PLL_CLK "main_pll" +#define SOCFPGA_PERIP_PLL_CLK "periph_pll" + +#define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw) + +void __iomem *clk_mgr_a10_base_addr; + +static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk, + unsigned long parent_rate) +{ + struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk); + unsigned long divf, divq, reg; + unsigned long long vco_freq; + + /* read VCO1 reg for numerator and denominator */ + reg = readl(socfpgaclk->hw.reg + 0x4); + divf = (reg & SOCFPGA_PLL_DIVF_MASK) >> SOCFPGA_PLL_DIVF_SHIFT; + divq = (reg & SOCFPGA_PLL_DIVQ_MASK) >> SOCFPGA_PLL_DIVQ_SHIFT; + vco_freq = (unsigned long long)parent_rate * (divf + 1); + do_div(vco_freq, (1 + divq)); + return (unsigned long)vco_freq; +} + +static u8 clk_pll_get_parent(struct clk_hw *hwclk) +{ + struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk); + u32 pll_src; + + pll_src = readl(socfpgaclk->hw.reg); + + return (pll_src >> CLK_MGR_PLL_CLK_SRC_SHIFT) & + CLK_MGR_PLL_CLK_SRC_MASK; +} + +static struct clk_ops clk_pll_ops = { + .recalc_rate = clk_pll_recalc_rate, + .get_parent = clk_pll_get_parent, +}; + +static struct __init clk * __socfpga_pll_init(struct device_node *node, + const struct clk_ops *ops) +{ + u32 reg; + struct clk *clk; + struct socfpga_pll *pll_clk; + const char *clk_name = node->name; + const char *parent_name[SOCFGPA_MAX_PARENTS]; + struct clk_init_data init; + struct device_node *clkmgr_np; + int rc; + int i = 0; + + of_property_read_u32(node, "reg", ®); + + pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); + if (WARN_ON(!pll_clk)) + return NULL; + + clkmgr_np = of_find_compatible_node(NULL, NULL, "altr,clk-mgr"); + clk_mgr_a10_base_addr = of_iomap(clkmgr_np, 0); + BUG_ON(!clk_mgr_a10_base_addr); + pll_clk->hw.reg = clk_mgr_a10_base_addr + reg; + + of_property_read_string(node, "clock-output-names", &clk_name); + + init.name = clk_name; + init.ops = ops; + init.flags = 0; + + while (i < SOCFGPA_MAX_PARENTS && (parent_name[i] = + of_clk_get_parent_name(node, i)) != NULL) + i++; + init.num_parents = i; + init.parent_names = parent_name; + pll_clk->hw.hw.init = &init; + + pll_clk->hw.bit_idx = SOCFPGA_PLL_EXT_ENA; + clk_pll_ops.enable = clk_gate_ops.enable; + clk_pll_ops.disable = clk_gate_ops.disable; + + clk = clk_register(NULL, &pll_clk->hw.hw); + if (WARN_ON(IS_ERR(clk))) { + kfree(pll_clk); + return NULL; + } + rc = of_clk_add_provider(node, of_clk_src_simple_get, clk); + return clk; +} + +void __init socfpga_a10_pll_init(struct device_node *node) +{ + __socfpga_pll_init(node, &clk_pll_ops); +} diff --git a/drivers/clk/socfpga/clk.c b/drivers/clk/socfpga/clk.c index 43db947..7564d2e 100644 --- a/drivers/clk/socfpga/clk.c +++ b/drivers/clk/socfpga/clk.c @@ -24,4 +24,9 @@ CLK_OF_DECLARE(socfpga_pll_clk, "altr,socfpga-pll-clock", socfpga_pll_init); CLK_OF_DECLARE(socfpga_perip_clk, "altr,socfpga-perip-clk", socfpga_periph_init); CLK_OF_DECLARE(socfpga_gate_clk, "altr,socfpga-gate-clk", socfpga_gate_init); - +CLK_OF_DECLARE(socfpga_a10_pll_clk, "altr,socfpga-a10-pll-clock", + socfpga_a10_pll_init); +CLK_OF_DECLARE(socfpga_a10_perip_clk, "altr,socfpga-a10-perip-clk", + socfpga_a10_periph_init); +CLK_OF_DECLARE(socfpga_a10_gate_clk, "altr,socfpga-a10-gate-clk", + socfpga_a10_gate_init); diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h index b09a5d5..603973a 100644 --- a/drivers/clk/socfpga/clk.h +++ b/drivers/clk/socfpga/clk.h @@ -34,10 +34,14 @@ ((((smplsel) & 0x7) << 3) | (((drvsel) & 0x7) << 0)) extern void __iomem *clk_mgr_base_addr; +extern void __iomem *clk_mgr_a10_base_addr; void __init socfpga_pll_init(struct device_node *node); void __init socfpga_periph_init(struct device_node *node); void __init socfpga_gate_init(struct device_node *node); +void socfpga_a10_pll_init(struct device_node *node); +void socfpga_a10_periph_init(struct device_node *node); +void socfpga_a10_gate_init(struct device_node *node); struct socfpga_pll { struct clk_gate hw; @@ -48,6 +52,7 @@ struct socfpga_gate_clk { char *parent_name; u32 fixed_div; void __iomem *div_reg; + struct regmap *sys_mgr_base_addr; u32 width; /* only valid if div_reg != 0 */ u32 shift; /* only valid if div_reg != 0 */ u32 clk_phase[2];