From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1176829AbdDYJFH (ORCPT ); Tue, 25 Apr 2017 05:05:07 -0400 Received: from mail-by2nam01on0054.outbound.protection.outlook.com ([104.47.34.54]:13664 "EHLO NAM01-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1177162AbdDYJDU (ORCPT ); Tue, 25 Apr 2017 05:03:20 -0400 Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=nxp.com; nxp.com; dkim=none (message not signed) header.d=none;nxp.com; dmarc=fail action=none header.from=nxp.com; From: To: CC: , Wang Dongsheng , Zhang Ying-22455 Subject: [PATCH 2/5 v2] soc: fsl: add flextimer module alarm driver for Layerscape Date: Tue, 25 Apr 2017 16:48:22 +0800 Message-ID: <1493110102-657-2-git-send-email-ying.zhang22455@nxp.com> X-Mailer: git-send-email 2.1.0.27.g96db324 In-Reply-To: <1493110102-657-1-git-send-email-ying.zhang22455@nxp.com> References: <1493110102-657-1-git-send-email-ying.zhang22455@nxp.com> X-EOPAttributedMessage: 0 X-Matching-Connectors: 131375845982906043;(91ab9b29-cfa4-454e-5278-08d120cd25b8);() X-Forefront-Antispam-Report: CIP:192.88.168.50;IPV:NLI;CTRY:US;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(336005)(39410400002)(39400400002)(39450400003)(39840400002)(39850400002)(39860400002)(39380400002)(2980300002)(1109001)(1110001)(339900001)(199003)(189002)(9170700003)(8676002)(38730400002)(53936002)(81166006)(77096006)(4326008)(50466002)(48376002)(110136004)(50986999)(33646002)(36756003)(105606002)(76176999)(86152003)(8656002)(54906002)(8936002)(189998001)(85426001)(2351001)(106466001)(2950100002)(47776003)(356003)(6916009)(6666003)(2876002)(2906002)(50226002)(86362001)(5660300001)(5003940100001)(104016004)(305945005)(2004002);DIR:OUT;SFP:1101;SCL:1;SRVR:CY1PR0301MB1196;H:tx30smr01.am.freescale.net;FPR:;SPF:Fail;MLV:ovrnspm;A:1;MX:1;PTR:InfoDomainNonexistent;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;BL2FFO11FD021;1:qUy6TKcWW3idkrR6ZWf7irlS1rkj43c0nbs+AGglbS1bz63kT2EX8yCMmQkxLkEqqqy1ISfxRfI7D2OGbwr3zIlC92smPQ7wmfFqbOV20MzlXDZtZMSR3zToVCvSVnUAD4YdoolbG29NE9b4dsZ+J5Su1uxtl6RkcOXGzNCdDhmt6VoLA6aYgO9pPqkSTWZu4I3iFsvDyVQoj0Oolt11IQgOx4EaapKCzre0Cs+H6Z7iYe30y8I5fuxEVOwamlPsxwoT3CDU3GvOwH2gY5cUHCkHE7hIsP8MUD0/Gqb5jTGXexk5HCopUMOndtJQ8wgksWCj9iKY/vUIGH3sdQX6WEwQpZJo9LvePrAFXBRZ4YCvakGMiuq9DBl9fgfT+5uj4X0SUK7AYpjyq1A5oOf+Y0KBPV4bIQkISHa/nsBpP2mHIKIeNCnT3Od7UPsFXeagQ6mIZXynKNllhNu9h33hMRIzmcV3tzftK2IMTsQihiBEulSWhemdKLydk+uh6ssROegQZ1Sr6oSzpKLLnLwLhdbg+exDWRS7l6FGFzQnc9w0T2bHqJb82evKTv5k7lsH+XimQ6ezarGuUxUqMWZGTY83E+RybE3UWNoaR1Kp5vPiQ7us30tXxAmIh3C+pI7tRVDx4TjRoBKFibxCiSkdm6zH1BvSVfzahGl/J3jGgRp5CL2k/0mUvMllEjkm+qoDhN7M4GF76YygYl8vhHEmSoL195we3YU/Tkklwj7tVX8= MIME-Version: 1.0 Content-Type: text/plain X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 3ea0ced5-298c-4c69-a6bb-08d48bb9ea57 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001)(201703131430075)(201703131517081);SRVR:CY1PR0301MB1196; X-Microsoft-Exchange-Diagnostics: 1;CY1PR0301MB1196;3:E5hXXcH0L3NfHuYQ8MSI3jBDGM3Ot6zMxyEOW2LbyFjgzbesW/S+eSV1JSI/HKMrQljeTVdfwnI6GtcQKIKY6Aw1JXOjxeMYi9zojZqcJleGUeg7Uv0iE3U8byuhqNJV6NVkWPhHYVKki9lvuwFAJvE7u9CtHI+Y0jjCDIMxyWuQwJHtHOtDntTFy4h2MVEUxPMgyxn+gYURkwAMZU8BR4GGC66od4hJAyZ4Hk+MRQjy9rVfiineT8Xj2K61euv5UmUc9ldmQIi1XTjAHkY1nsyFzXrgWjDdtPSQ5V6Knf0EbGrU7GRPDNCSNB9WNveznzUXMTAdu7Qwa6x7Zn7pVDvcEeN7R3pjxsYEqJnC7sdMDDK89GnsIwGikMsd6dKxhXWupakSx7W2Nc9k6MTdIiMkbqzCRcnXB1Cu3QtWMhWhu5tsNlTBEGoSzbe9mrUj;25:GRwvaJbTVjj0cQ/FSZTI3KWa4BEtn6qh34UBLw7A8q7Qu7tK+ApK9AWiJTnU8I/m5iJ5Q84aWvxt+ogL/OyTNBygIjGrkRLNqPIxezOaswKB0B3RIetv8ysQW5ouZBPrgH1mhNHAV5eFKUd+eMLXcBAmjGyIwWUbIUwncHn5w35jnqucxhr+lZC72MBbiH9JRhTm2Yix+CMWedzf5dVggNXX51g6/WWrK5c3b7r+sjez6pA/pXIe/z5OdwjctACqDAnk63XJchlj9H/X62ctXLvdAGfcEAyps/R0LGMkiC8IbJPxokA0ma2a222SzU2XPhc7waSWBkZcbeeXDk0pTmfKYZWOSHfAqtlF6M9O7vJruffSsuyqbGXwfKHMhaxE6nUWCpoYDRD5vL7VrZbwbqOoghgV8qq4+BXRj7L+A0XmSYJq7gtz5i3LjF8bXipNLVH+GpyjojfCgBFg2a0PjA== X-Microsoft-Exchange-Diagnostics: 1;CY1PR0301MB1196;31:b/NMhLnpTAd1nRfpY/0iA56kpk29TdrTIOmX5czsrv7ToudWJwS8Lg9RI51CaDMljo6sXtwaCKSfNQSE3/4hrb7Oea645zes9es0lTvdHyjyxYw7aWIm906jQ4W+4d0qGI7LoeUk6aHZdb5juzgupXcxylFjkZonu4zHAAqpD6718YKLvgG3tzAs9ukushynS1bqolB+F2iJYhJUiFv76xTNTQSdjeb8VCVYyuxjw4IehUjjL9UkmfnONoa0TDTbaFFEaQcKZEwZYLI2crnW/H9+IADb6WwyQ7wOhnz7wMQ= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(185117386973197); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6095135)(601004)(2401047)(8121501046)(13015025)(5005006)(13018025)(13017025)(13024025)(13023025)(3002001)(10201501046)(93006095)(93001095)(6055026)(6096035)(20161123561025)(20161123565025)(20161123563025)(201703131430075)(201703131448075)(201703131433075)(201703161259150)(20161123556025);SRVR:CY1PR0301MB1196;BCL:0;PCL:0;RULEID:(400006);SRVR:CY1PR0301MB1196; X-Microsoft-Exchange-Diagnostics: 1;CY1PR0301MB1196;4:DgC+YWWxb19bSPKGGLDqBwDbzNgXoo8Ei+O6BH0eSf1KRCt5sSP/rqLfdgyr4alponUONpZRu4ecio1daTVLxib/ouw2nyw1MVSudnjhPQyNVWdeqvAMGNy3z06iFjJbqbD+CObTwmLP28BU4nUOcKIgDrQOHUUm3+sLj7+n6bYjSUASwzkJIvErIhts0PQWYl8nWdEjow0/Io2NZElUVXK7LJWDBYGbse1dK/E0wstyud0LhNk+obFzJT4lyWzbSBKqaruh9F+R5qQcKa/PJ6rXVesCLkuRCAJkM+Hc4TfjTxsPGygx7qtr74qXzPctk2J7EzgOQmAvpA4iHnuMHzZcfx0KoRHHmn4ij0Dh1NSHLS1MA7Ec/pTlDykcsNJp4qMEoipNibNW3YFplX3vVGCbJu+gjUrbzap0XQ/H3GMxCNlAiE9Cxf+XLVwF8eG4mLXJuIqMvaQeEKTxPIyTxYn8C/Zb4KufVqmBdgEBehVow8Eiy2k/2FeHJZVzhrCU4BLy7PXyRY4G5yNYORsfGxo4UyAOcv7BGQGhNEkI3TKdurUaKthdZ+U3G2hXux9oeW0C5ppdaRJszLIE5RctfV+m45sh9yggeRq8Lpe7bPd3O4F6FJjH+tFh54mYCktKwn5921qE2/R/JccGlfTUsnDOh/d3dHOvku5AV64Xo7cjMv+4UOAnZkagQHEAg4MjhEn9trWMQa6yKs3+Hzh0NRM5vvThTsKBYMjBKkISnD0JEeD/8eJIzNwakRYA3QYCVYd2e9+jeCzq+XfeB1epr03AEQtY9JFQCE/LUTwjbJFlrsjEzy9gevc9MUldoNfjFH5TkkPXjfpovjQnr3eU6BznwnUj3PLLBHwHwKGjQdt+EtcmiuCNUGKNCYB43eRX1crYO7ZOhGLubNGH3NyP2Q== X-Forefront-PRVS: 0288CD37D9 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;CY1PR0301MB1196;23:FXn9Jg+dYszzPXP3lUNFhae4uVBbxLzC894qORU?= =?us-ascii?Q?sJ7Mf81cuokdwU8FUu6N0CrRnBxG7k6F2EWviZjWoxjXoEWC4mIdDjq9Cqs2?= =?us-ascii?Q?bzzU2TkAuc/aSnNeL2MG+x0PoLPV3cy3X628VZRWQvRPD3Z4rtgM+EZGTNz8?= =?us-ascii?Q?nXu4FBLropX6kbs5PM7g5BvW2TFiFTvDhPsoI5yb0UEtWpZB1uTFzYVTch1b?= =?us-ascii?Q?GvBedBvj994bLyXihswqqbJcYSUPK5ziukmUP1B9B9JNXX1q+pmtyeFFrfIB?= =?us-ascii?Q?sYu6eH7OOU3uU++a3NOlPskjNZu/1OvKGA1tsaIDQuBBo7RwqW7pOuSKWNyL?= =?us-ascii?Q?ygTTR5CEh5FjZtBo63qCU0LVvL5HM5FYCEVC77A52xSWWuPteg2qqy8sjylr?= =?us-ascii?Q?STWx2eC+wP0bAube7ijL/qOpZ5oFh2ZMouVcZ1cWNUV6BsacdxfK/XkeY8Di?= =?us-ascii?Q?Q9CzhCaAYyiBYvb3o0a78QuvkELM5rjhhmLRSoMsZlQgc1qyXRXkoJx5fD0J?= =?us-ascii?Q?kewo6E18DnCemX0AMYIGZydXxyEIDcbw254iTaScwVpClalfCZF7UrN9QFr4?= =?us-ascii?Q?2AU5z8V8Gx5EXdCetQOE9ykfA7dVCQtxG4EI17EkRO/flz0c+V9UXGSi7MoQ?= =?us-ascii?Q?WUzAOGjsaXRe7ta3PEl4WwWZbIoviPZrluxq9o6sBgTonnGTpmA1DOQs/KFM?= =?us-ascii?Q?qQHvlCSHz3+DVN2SE1weLUwiK87hegsvoifl+zfICjOpvrMqJmu19Mgv67DV?= =?us-ascii?Q?YfYXumje08XvQCUN2BE/MyP6ojSRN/HZ0ZUHiFcXCWLObzawxHKsJRzgii4O?= =?us-ascii?Q?WE5OXzW4HzlrbgXvKzXbfOX5ttXsstFbSnqHWdVS72oltLoCZZPEgF22SFic?= =?us-ascii?Q?ihqh93+7fzGmOMeLH83fQn2JpVFQRAu4SUstszKrX4z5uMfpfe6qBYINbfu1?= =?us-ascii?Q?pS0xdDR+XHlWDCoCSUnzWisNdG6TS1wbN7QMqdhBYRF5+vZyONvdO0X1l8kg?= =?us-ascii?Q?NkMZNDh8zDGmsPHTv+qL3ZiSxdZEeX8ogSFy6ZcaZOE18kGJnvKKPBnjkL4a?= =?us-ascii?Q?bma1Vz1NZm2TBdP24b1X919GVicylKIQzgUEjd07xm+fghYM7UkAEYNWzSUG?= =?us-ascii?Q?dwjUJGQg4X8Jn4qpaDM/BdE6lZ94mt5dbhADRt1auOoGFdZ6Ppncnrrfp+0W?= =?us-ascii?Q?7ml7rgE886+cmGGbhmm2un/BoRyQnBInBX/0b1qjtjRKa2L8/BkvKgdKYO0M?= =?us-ascii?Q?dzTqSYJYRiN/DBEfJxKc/ohYwQFjo0VgnYZKGM3Vf?= X-Microsoft-Exchange-Diagnostics: 1;CY1PR0301MB1196;6:lRnuJmtBTR90X2lfpKvaNDN6wF3VyXSJHipAll7+MqOzIHXW28q9l7E064jYy0Q1g9540u9EOdZWnyS6hhMEhC79cVRbXxGJpsZHpdSp2rFZsEO4+YOo6Wr5+hqVsZHHsgo4/7W4r+AI5j57tiLhYKaa4UXczZsJNrvjVgrLS743eotb/ING5o9Ro4QPefgRdSkLiFuDNCmUawXMf2M1oyd0C7NVz7OKc0MzxWTEUpNxKUfbiyDSdZ2h7nFP2gKWxu3yAr220CkGLbWXbjSZem/cui05lAHYMVXr+OfjTt65tVM6BuumjsaGpglIlWgtb46GwQq5IKYOn/Nnpc/SB693LK6is39vtGOiPVNJ+UrjPRmcxHAaxZbhCKaUL2sWd//iVK27EvzRjb8RRlwvYke+Xe2Oa6q8pKTzQo5Rswss8eQ+gnfY0+8ayVD+WcfNFdOZLP1yNKbd9mtRQBAER7Hg2lJfdXffIudMHmRTeVOhTWEj3Twoz3TlJtLaGqjZ8ua8UiFSsho3agfFTj7XfQ==;5:74N6T7pgDdm2y2meWdFCkGsbKxB9fYexQn/4YM+JoFFDsbrQ/xgG8TGQ6l9pX4kpP1n9rl7tBsze7USZjx2+YIvqakWk2NKBr1Se1STDN6HidsvDQrqDbXlxcXalFXtLN1EfeFRjXVGlZBtl2c+44JSfEhTwaegMB1ZtE58yUjt+uU5+9wphwFQ2sSl/6uUc;24:qMZV2m8KzJH3eozbeqhoPGouKryK1OlhFG2qZs72kArqBUg7T3Elzr6Yxc88dXXCeTlPzz2tJNCSjJ7gLzoRZSHiyHVkgoUwLv9uAQfgBis= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;CY1PR0301MB1196;7:0i0LMQeq3P1DR3kSsVtvFEK2Y2vWSD3lBzqPGmbI9WEYmwVtahRr70di1fceiNQdAkeUum1JfOgUHeLDdoI654ktPB+7V/d02g5+xqw4Jx0QrYFRwktu0O/HHmbMx49H3DRsqY9kJfiMQzaW/wueSUrewmUa2OVRlWi1adYWv5Lc3ZqvFQAfi9mwyPznvha94UjD4hjrB88gMMtgSgLGFqesnlbsIusVz8o6sam0Mqnhfgnkr5UIf29fGCqxjRAoMrk3Q5LGUtN6VdZb/ZswmKfdqVarPT4StsO44IagltdYBTfZCdcE8wHS5uMnx0HHqT9AfKk/cOK0YlEGXASidg== X-MS-Exchange-CrossTenant-OriginalArrivalTime: 25 Apr 2017 09:03:18.1346 (UTC) X-MS-Exchange-CrossTenant-Id: 5afe0b00-7697-4969-b663-5eab37d5f47e X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=5afe0b00-7697-4969-b663-5eab37d5f47e;Ip=[192.88.168.50];Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY1PR0301MB1196 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Wang Dongsheng Signed-off-by: Zhang Ying-22455 --- Change from V1: - ftm_clean_alarm: FTM_MOD is 32bit width, modify ~0UL to ~0U. drivers/soc/fsl/layerscape/Kconfig | 10 ++ drivers/soc/fsl/layerscape/Makefile | 1 + drivers/soc/fsl/layerscape/ftm_alarm.c | 274 +++++++++++++++++++++++++++++++++ 3 files changed, 285 insertions(+) create mode 100644 drivers/soc/fsl/layerscape/Kconfig create mode 100644 drivers/soc/fsl/layerscape/Makefile create mode 100644 drivers/soc/fsl/layerscape/ftm_alarm.c diff --git a/drivers/soc/fsl/layerscape/Kconfig b/drivers/soc/fsl/layerscape/Kconfig new file mode 100644 index 0000000..e1373aa --- /dev/null +++ b/drivers/soc/fsl/layerscape/Kconfig @@ -0,0 +1,10 @@ +# +# Layerscape Soc drivers +# +config FTM_ALARM + bool "FTM alarm driver" + default n + help + Say y here to enable FTM alarm support. The FTM alarm provides + alarm functions for wakeup system from deep sleep. There is only + one FTM can be used in ALARM(FTM 0). diff --git a/drivers/soc/fsl/layerscape/Makefile b/drivers/soc/fsl/layerscape/Makefile new file mode 100644 index 0000000..6299aa1 --- /dev/null +++ b/drivers/soc/fsl/layerscape/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_FTM_ALARM) += ftm_alarm.o diff --git a/drivers/soc/fsl/layerscape/ftm_alarm.c b/drivers/soc/fsl/layerscape/ftm_alarm.c new file mode 100644 index 0000000..52d8bea --- /dev/null +++ b/drivers/soc/fsl/layerscape/ftm_alarm.c @@ -0,0 +1,274 @@ +/* + * Freescale FlexTimer Module (FTM) Alarm driver. + * + * Copyright 2014 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define FTM_SC 0x00 +#define FTM_SC_CLK_SHIFT 3 +#define FTM_SC_CLK_MASK (0x3 << FTM_SC_CLK_SHIFT) +#define FTM_SC_CLK(c) ((c) << FTM_SC_CLK_SHIFT) +#define FTM_SC_PS_MASK 0x7 +#define FTM_SC_TOIE BIT(6) +#define FTM_SC_TOF BIT(7) + +#define FTM_SC_CLKS_FIXED_FREQ 0x02 + +#define FTM_CNT 0x04 +#define FTM_MOD 0x08 +#define FTM_CNTIN 0x4C + +#define FIXED_FREQ_CLK 32000 +#define MAX_FREQ_DIV (1 << FTM_SC_PS_MASK) +#define MAX_COUNT_VAL 0xffff + +static void __iomem *ftm1_base; +static u32 alarm_freq; +static bool big_endian; + +static inline u32 ftm_readl(void __iomem *addr) +{ + if (big_endian) + return ioread32be(addr); + + return ioread32(addr); +} + +static inline void ftm_writel(u32 val, void __iomem *addr) +{ + if (big_endian) + iowrite32be(val, addr); + else + iowrite32(val, addr); +} + +static inline void ftm_counter_enable(void __iomem *base) +{ + u32 val; + + /* select and enable counter clock source */ + val = ftm_readl(base + FTM_SC); + val &= ~(FTM_SC_PS_MASK | FTM_SC_CLK_MASK); + val |= (FTM_SC_PS_MASK | FTM_SC_CLK(FTM_SC_CLKS_FIXED_FREQ)); + ftm_writel(val, base + FTM_SC); +} + +static inline void ftm_counter_disable(void __iomem *base) +{ + u32 val; + + /* disable counter clock source */ + val = ftm_readl(base + FTM_SC); + val &= ~(FTM_SC_PS_MASK | FTM_SC_CLK_MASK); + ftm_writel(val, base + FTM_SC); +} + +static inline void ftm_irq_acknowledge(void __iomem *base) +{ + u32 val; + + val = ftm_readl(base + FTM_SC); + val &= ~FTM_SC_TOF; + ftm_writel(val, base + FTM_SC); +} + +static inline void ftm_irq_enable(void __iomem *base) +{ + u32 val; + + val = ftm_readl(base + FTM_SC); + val |= FTM_SC_TOIE; + ftm_writel(val, base + FTM_SC); +} + +static inline void ftm_irq_disable(void __iomem *base) +{ + u32 val; + + val = ftm_readl(base + FTM_SC); + val &= ~FTM_SC_TOIE; + ftm_writel(val, base + FTM_SC); +} + +static inline void ftm_reset_counter(void __iomem *base) +{ + /* + * The CNT register contains the FTM counter value. + * Reset clears the CNT register. Writing any value to COUNT + * updates the counter with its initial value, CNTIN. + */ + ftm_writel(0x00, base + FTM_CNT); +} + +static u32 time_to_cycle(unsigned long time) +{ + u32 cycle; + + cycle = time * alarm_freq; + if (cycle > MAX_COUNT_VAL) { + pr_err("Out of alarm range.\n"); + cycle = 0; + } + + return cycle; +} + +static u32 cycle_to_time(u32 cycle) +{ + return cycle / alarm_freq + 1; +} + +static void ftm_clean_alarm(void) +{ + ftm_counter_disable(ftm1_base); + + ftm_writel(0x00, ftm1_base + FTM_CNTIN); + ftm_writel(~0U, ftm1_base + FTM_MOD); + + ftm_reset_counter(ftm1_base); +} + +static int ftm_set_alarm(u64 cycle) +{ + ftm_irq_disable(ftm1_base); + + /* + * The counter increments until the value of MOD is reached, + * at which point the counter is reloaded with the value of CNTIN. + * The TOF (the overflow flag) bit is set when the FTM counter + * changes from MOD to CNTIN. So we should using the cycle - 1. + */ + ftm_writel(cycle - 1, ftm1_base + FTM_MOD); + + ftm_counter_enable(ftm1_base); + + ftm_irq_enable(ftm1_base); + + return 0; +} + +static irqreturn_t ftm_alarm_interrupt(int irq, void *dev_id) +{ + ftm_irq_acknowledge(ftm1_base); + ftm_irq_disable(ftm1_base); + ftm_clean_alarm(); + + return IRQ_HANDLED; +} + +static ssize_t ftm_alarm_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + u32 count, val; + + count = ftm_readl(ftm1_base + FTM_MOD); + val = ftm_readl(ftm1_base + FTM_CNT); + val = (count & MAX_COUNT_VAL) - val; + val = cycle_to_time(val); + + return sprintf(buf, "%u\n", val); +} + +static ssize_t ftm_alarm_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + u32 cycle; + unsigned long time; + + if (kstrtoul(buf, 0, &time)) + return -EINVAL; + + ftm_clean_alarm(); + + cycle = time_to_cycle(time); + if (!cycle) + return -EINVAL; + + ftm_set_alarm(cycle); + + return count; +} + +static struct device_attribute ftm_alarm_attributes = __ATTR(ftm_alarm, 0644, + ftm_alarm_show, ftm_alarm_store); + +static int ftm_alarm_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct resource *r; + int irq; + int ret; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) + return -ENODEV; + + ftm1_base = devm_ioremap_resource(&pdev->dev, r); + if (IS_ERR(ftm1_base)) + return PTR_ERR(ftm1_base); + + irq = irq_of_parse_and_map(np, 0); + if (irq <= 0) { + pr_err("ftm: unable to get IRQ from DT, %d\n", irq); + return -EINVAL; + } + + big_endian = of_property_read_bool(np, "big-endian"); + + ret = devm_request_irq(&pdev->dev, irq, ftm_alarm_interrupt, + IRQF_NO_SUSPEND, dev_name(&pdev->dev), NULL); + if (ret < 0) { + dev_err(&pdev->dev, "failed to request irq\n"); + return ret; + } + + ret = device_create_file(&pdev->dev, &ftm_alarm_attributes); + if (ret) { + dev_err(&pdev->dev, "create sysfs fail.\n"); + return ret; + } + + alarm_freq = (u32)FIXED_FREQ_CLK / (u32)MAX_FREQ_DIV; + + ftm_clean_alarm(); + + device_init_wakeup(&pdev->dev, true); + + return ret; +} + +static const struct of_device_id ftm_alarm_match[] = { + { .compatible = "fsl,ftm-alarm", }, + { .compatible = "fsl,ftm-timer", }, + { }, +}; + +static struct platform_driver ftm_alarm_driver = { + .probe = ftm_alarm_probe, + .driver = { + .name = "ftm-alarm", + .owner = THIS_MODULE, + .of_match_table = ftm_alarm_match, + }, +}; + +static int __init ftm_alarm_init(void) +{ + return platform_driver_register(&ftm_alarm_driver); +} +device_initcall(ftm_alarm_init); -- 2.1.0.27.g96db324