Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933593AbbHLF7A (ORCPT ); Wed, 12 Aug 2015 01:59:00 -0400 Received: from mail-bl2on0138.outbound.protection.outlook.com ([65.55.169.138]:63408 "EHLO na01-bl2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932127AbbHLF64 (ORCPT ); Wed, 12 Aug 2015 01:58:56 -0400 Authentication-Results: spf=fail (sender IP is 192.88.158.2) smtp.mailfrom=freescale.com; freescale.mail.onmicrosoft.com; dkim=none (message not signed) header.d=none; From: Dongsheng Wang To: CC: , , , , , , Wang Dongsheng Subject: [PATCH 2/2] soc/fsl: add ftm alarm driver for ls1021a platform Date: Wed, 12 Aug 2015 13:53:27 +0800 Message-ID: <1439358807-9024-2-git-send-email-dongsheng.wang@freescale.com> X-Mailer: git-send-email 2.1.0.27.g96db324 In-Reply-To: <1439358807-9024-1-git-send-email-dongsheng.wang@freescale.com> References: <1439358807-9024-1-git-send-email-dongsheng.wang@freescale.com> X-EOPAttributedMessage: 0 X-Microsoft-Exchange-Diagnostics: 1;BN1AFFO11FD028;1:FUbcoUo2hNftw0ln+Ezy8pUiv/V4UBt2iuNUzPkNudAgyHPmJKPYX/Wih139lKTzi/tBJznRrXuserXVJ09vQTKlmDPp42tBGtmMPT8oY6AeOO/h5U9BWKsE58Qzbyl0Etjc5x3ag++8btsixc6VqvCRlVYgNcBd89VDJEQaGG52kek9mfKKz84X+0ZuBZvtSqz4UatKblfVdjpzJ6/o9jI2rxLiZyrkK0yP33rNEDn5s+9zLp4vt50A0KZLar1IukA7aftFwQMs13Yfku+n3DuuogpDdQTuWiu0xt0i4NV1wkTy76xdhDquOAZQap9rglph7T1Z2MWZK8F5iMh6tcTVqDAYH5wirkj9f2NEEDabYORST0NdaFzwK7q3HBnFC7L+CZ+AzRxx8oquwfFf4w== X-Forefront-Antispam-Report: CIP:192.88.158.2;CTRY:US;IPV:NLI;EFV:NLI;SFV:NSPM;SFS:(10019020)(6009001)(2980300002)(339900001)(3050300001)(189002)(199003)(97736004)(5001860100001)(5001830100001)(46102003)(69596002)(81156007)(85426001)(4001540100001)(87936001)(68736005)(6806004)(77096005)(5003940100001)(2950100001)(50226001)(19580395003)(19580405001)(76176999)(50986999)(92566002)(50466002)(48376002)(189998001)(86362001)(77156002)(62966003)(33646002)(105606002)(36756003)(229853001)(2351001)(104016003)(106466001)(64706001)(110136002)(107886002)(5001960100002)(47776003)(2004002)(4001430100001);DIR:OUT;SFP:1102;SCL:1;SRVR:BY2PR0301MB1607;H:az84smr01.freescale.net;FPR:;SPF:Fail;PTR:InfoDomainNonexistent;MX:1;A:1;LANG:en; MIME-Version: 1.0 Content-Type: text/plain X-Microsoft-Exchange-Diagnostics: 1;BY2PR0301MB1607;2:p+N2WZdLmAkKNmAvfgC1n3alWwI++kkn2v4eiEptKRtMWVXVJEZY5E0M+zxA6MyiWeW0R88R/ekkhXnVp+Bj9aR+7z2jnFw8EYMn2UZedsMVjX6bpDmexgpXJ/gNmHhOOnahM8EjADGuI8dsUp/P4uXhL11G5mPedYKV5Hfjiho=;3:I4sApT3PberjFJ9eGrHp/M+65SWLJBD2G1U4aqxjPvGRCwsnUH+vTaGa9fAYsazLR0cuUpE3qDHyS/9XCjzc0pTbQD918XYC6HmK/ff37JX9C7d3JXQg+CEQMgxeSh4J+VXLyWYy7GfdCg3Z1NkycFQMljkRTCbdsrWF7PeFEFbBQTMQ6yiBjee9lHgEhOO5SXefXioxs0F21AUdYFFLct6mbrj2OxRKQUpzllyvi7g=;25:D3+neT0vmNCiKTI8OdVVda+QO9aSEiAvXAaquRWeVARsPoEz1o+nFITt0U/95UbgNzEy3C5+uXw5/V4hoGyWTraqA66ie0MPLdmpkzauW6sZ5/UQIXqG5aEul91+6sjlFPsn718QpvBL3N/GeeZ76kqYxSDP+fh7aNXzQKUg1CyoHO9EK9erQ1ZyFpyoKs+yX38qtdQnRF9MhzPkwacXgMk1AH6gbl8wmS3W3bgZU6egoexrurFoAfquxewm0X0P X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BY2PR0301MB1607; X-Microsoft-Exchange-Diagnostics: 1;BY2PR0301MB1607;20:dA/Sfvs5ZpVeFp8BphnVvNMzAXAqUBScXqRPR5HcuP+AmmkyaGsokmtFj8FWTVWpBKvNqGXQWgIr1uznie3epKxxGIXR+w7t0a3/x/Di5z7F6EQef73yfpU9yNwSDYstRTjBQM40/sDuWAtluItX0jEJltuThMVvkKDl8rTOrsLa+6MV0urQEF6kgk+27bdWKMDm13JfYYOe2RxKIFcOfsAnsHSyxqAlTl1hEQm0+3898FHdX0YQmk5pZaMBIvHGfg97P/rTkI85WG+STcwr5B3NoN0/m4zBUKKEEBiWXpjVfz4ZlOWlly4UXixt01gYNiojgy+XJ2nzcmydc7fTuRfvpETjTwuOlqR1FbIJt4E=;4:hBCfvBlYHwaPin92WT2+zIyU1VTu3W8iH9XuwLS0PpyStvB3dm/Fdutu+AHA+IhRBJvJoT2tX0JgDMwLYrLVW3O76vIHv2fZxKM/JpRnQ3fgES1eMHbThoLA8CdIY3ApD9rktxqn2Wx9f+fsVzEFdgXFADRQ+KprOmI0Lq/Yzget35i0tBCaTYv17hM348FXJpBXQCpJpwgtaWLSJo5kdHm3X2mtO44JgSLuAF/ne+0789s0wBld7g8JWXTUaiIh9rTSXxotzpm5qfKobZJ8c1D6yb5jjBH0/Vf4kb2WpIc= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(5005006)(3002001);SRVR:BY2PR0301MB1607;BCL:0;PCL:0;RULEID:;SRVR:BY2PR0301MB1607; X-Forefront-PRVS: 0666E15D35 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;BY2PR0301MB1607;23:UJrvui9kWvYsxOCG1Iurvc9HgevcwWr5Fa7d1yT?= =?us-ascii?Q?eRdJtd1mtV/huZygKvwyWkxx/NuEL82RiEPTNm66SV1EHMznrUUiXgXDs6Q6?= =?us-ascii?Q?U+8+Va0aTpHXak7c1us7oogkK2LUwCMV8QZ9MP+JiCBgWs0a/mrwZpO2Zmtt?= =?us-ascii?Q?BMay6/7qVOgzV8jwxVmibFasvE4RR/N5h6o3Pa8AAPbIgN4rdVneFo1LfmKE?= =?us-ascii?Q?POBlAFK1rI1ce2slfW79HObKu6TACuQjVb2VBCnWI/CBUvhx4scLcFkUu60b?= =?us-ascii?Q?AizFUJKFs0MC2XIlnoDM6nYX9QVFL0oJB2KLx+i+SZi7OsNxV6AxH280wtfe?= =?us-ascii?Q?po1SfGDLV1ciCdKwNK0tFqzc8p3hxGKd047/y1zk0qCd2GNrg5vp1gRWQEJO?= =?us-ascii?Q?RNVkHAjURBwOh6VVqoz3+9C5nA5sUppbhs4nlZtaIDHGZI44QMvG8UgHBWT1?= =?us-ascii?Q?0ws2TXmS1128d9cOAdapJFCibuH0OwmDLYy31AG6qnRpOYQUoiKhGvw3nwHz?= =?us-ascii?Q?vrIOUmRowBdLSLkk709SRrf4rZD7W0uo4AmVDb4Q0xjAy7619UuyHTiZ2YJN?= =?us-ascii?Q?U3Yyst/wBM+ybUSbKucfitks84WnWOq5GKyV+8WKQ+6Kne/LqilNwnphaenZ?= =?us-ascii?Q?WTabrTBvI9voWudFB16vg5jJMvuLBbGH7bSpt4pc6m3eQx/SD1SCL4bL6WL4?= =?us-ascii?Q?j2ihv+m9nAP7ROFkhfVP3/nCkNy9cyR4dBtciINhPnwM02FochiFb71IEykF?= =?us-ascii?Q?O6xWLKOAHMJTD1ai38KqIZFgY/zxL34mJYC+wAH8hOtXwzsrC85QPpmBNG2+?= =?us-ascii?Q?rHWBsNwjEskCljIEbaGuYq9vtbEs5otb/rBYF1Hb+rLx134fNk71OYJST3Dl?= =?us-ascii?Q?yVuBaTjgrxyJCIt45TLXUcDzlitV4mxf6Hqc2yG6d1LCMd/N51oNlEKwCSC2?= =?us-ascii?Q?Oh6yRGYWMHI7waZBQe9Tv4Ldk73+GhYYQ7jv7cQ97WW6N33CWhQzb7Yxobnq?= =?us-ascii?Q?imcG/FgNi7rvr87BEZze5DK45RiZxtTtLiN5zxX+RVSzUVDbS/uBhqWnVjPo?= =?us-ascii?Q?qcXYj2D1qIeDpZUws1NYBIs4qr0pdorDJApxIPgx2PkdGado4XZHo2RbUkHI?= =?us-ascii?Q?NimXy7qShrMvQRZ4TQhBPNOCMMcniRYg8n0hVRCDaHhzAXrmJxG6qYUFMu0k?= =?us-ascii?Q?KWmTF6fOWDBJ5tWhfoR0WFLRkyraDi6GE8bm5?= X-Microsoft-Exchange-Diagnostics: 1;BY2PR0301MB1607;5:WI8f49u5p/iCAkWm9G28hO8ZgWGEorFQIEIZ/3NL+Ba+EXaE/dYgGeJWoangiZo2EzgaNMqUuf0LxxCjVi0BDc/PJSXY854BeJfdxZCW5UGZyHbT8BprQox17RyO+uJRssopQmqGDwaHg7ONfLRlIQ==;24:mPZuzhu28rXR4+FbmtebyKhFAbtpBb+km1UMXOc0Jsic7HxwfJEEZk+7OJY3QyOpVzQscLQ2j3FyryDx371xO2Ojmwj46UdntiYhPQwPgs0=;20:SotJHKI41dKf3lHlHKGawet0NfanTWem0M+/0791WwXF2b5sBsKwRLn/qfj/px+35lys14mKh2h7Z9V9Vw+t7A== X-OriginatorOrg: freescale.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Aug 2015 05:58:52.3513 (UTC) X-MS-Exchange-CrossTenant-Id: 710a03f5-10f6-4d38-9ff4-a80b81da590d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=710a03f5-10f6-4d38-9ff4-a80b81da590d;Ip=[192.88.158.2];Helo=[az84smr01.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY2PR0301MB1607 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 7560 Lines: 319 From: Wang Dongsheng Only Ftm0 can be used when system going to deep sleep. So this driver to support ftm0 as a wakeup source. Signed-off-by: Wang Dongsheng --- *V2* Change Copyright 2014 to 2015. diff --git a/drivers/soc/fsl/ls1/Kconfig b/drivers/soc/fsl/ls1/Kconfig index 7556f44..e6282dc 100644 --- a/drivers/soc/fsl/ls1/Kconfig +++ b/drivers/soc/fsl/ls1/Kconfig @@ -1,3 +1,11 @@ # # LS-1 Soc drivers # +config FTM_ALARM + bool "FTM alarm driver" + depends on SOC_LS1021A + 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/ls1/Makefile b/drivers/soc/fsl/ls1/Makefile new file mode 100644 index 0000000..6299aa1 --- /dev/null +++ b/drivers/soc/fsl/ls1/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_FTM_ALARM) += ftm_alarm.o diff --git a/drivers/soc/fsl/ls1/ftm_alarm.c b/drivers/soc/fsl/ls1/ftm_alarm.c new file mode 100644 index 0000000..f7629cd --- /dev/null +++ b/drivers/soc/fsl/ls1/ftm_alarm.c @@ -0,0 +1,272 @@ +/* + * Freescale FlexTimer Module (FTM) Alarm driver. + * + * Copyright 2015 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(~0UL, 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(); + + 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 -- 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/