From patchwork Mon Mar 11 07:16:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anson Huang X-Patchwork-Id: 10846827 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5595F17DF for ; Mon, 11 Mar 2019 07:17:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 35C9928D7D for ; Mon, 11 Mar 2019 07:17:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 27F9628D95; Mon, 11 Mar 2019 07:17:16 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAD_ENC_HEADER,BAYES_00, DKIM_SIGNED,DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 17D3A28D7D for ; Mon, 11 Mar 2019 07:17:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:In-Reply-To:References: Message-ID:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=Y5BuwOvH93Ds5aMNhREO6W/FSZOq2+uhjqBWzlvpX1c=; b=BS978+FYTnXSC4 aZwpLslUUFhMc1zDsekcxlhIjHm+KanmzJsZjdhqPgi9yHWU+eefU7oSSzNrZ3f9cpfI2Mh5V8Z2t sePim+XUySD+xNXDUXgBgH9+k5kjvWjAlCkxCUBjgEG63CFpcNJg9/g6Ahlm75TbLnAgbx7QApHaF zrZ/IxmSxMNEwNYAvh7WZkTocEjFEGW1rgOz4/iuVf3GExddIHTw1JHjoN+BMvLBtf4WUVA0Digy6 SEamSL4f98/yOD3X1AfdS8lRXGdw8pcQ9TD2BYuR1Rj8YHv2onZpjfruxH25yMl4jHeHhImJ1Gt1F banlMur4t1Ite0Lz81Sw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1h3FBL-0007le-MJ; Mon, 11 Mar 2019 07:17:07 +0000 Received: from mail-eopbgr00055.outbound.protection.outlook.com ([40.107.0.55] helo=EUR02-AM5-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1h3FBB-0007Zl-Om for linux-arm-kernel@lists.infradead.org; Mon, 11 Mar 2019 07:16:59 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=8bpd/fL98pP+NX3PZGyCDkkSYEBL3ecIr3PSVBzOCc4=; b=lsusO9D0a4A4gDiHCvH+8M3phzVAcH76HeUdo7TgM330aCcZ+r0zc7X8xuatORHBUhCk7ZJBrujh8AfXkOf1DFDvbd2G/WXtEsMxo+CelmVOg6mgLXOA+ha9ihuIsLIWu2mXeg5jBToV2TDi27egExwtyruKD6c7Us31vPupRR0= Received: from DB3PR0402MB3916.eurprd04.prod.outlook.com (52.134.72.18) by DB3PR0402MB3724.eurprd04.prod.outlook.com (52.134.66.147) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1686.18; Mon, 11 Mar 2019 07:16:53 +0000 Received: from DB3PR0402MB3916.eurprd04.prod.outlook.com ([fe80::1cb4:3e1c:fc85:7ed7]) by DB3PR0402MB3916.eurprd04.prod.outlook.com ([fe80::1cb4:3e1c:fc85:7ed7%2]) with mapi id 15.20.1686.021; Mon, 11 Mar 2019 07:16:53 +0000 From: Anson Huang To: "thierry.reding@gmail.com" , "robh+dt@kernel.org" , "mark.rutland@arm.com" , "shawnguo@kernel.org" , "s.hauer@pengutronix.de" , "kernel@pengutronix.de" , "festevam@gmail.com" , "linux@armlinux.org.uk" , "stefan@agner.ch" , "otavio@ossystems.com.br" , Leonard Crestez , "schnitzeltony@gmail.com" , "jan.tuerk@emtrion.com" , Robin Gong , "linux-pwm@vger.kernel.org" , "devicetree@vger.kernel.org" , "linux-arm-kernel@lists.infradead.org" , "linux-kernel@vger.kernel.org" Subject: [PATCH 2/5] pwm: Add i.MX TPM PWM driver support Thread-Topic: [PATCH 2/5] pwm: Add i.MX TPM PWM driver support Thread-Index: AQHU19pRLIP7E/b7ake3rSFDebhjpw== Date: Mon, 11 Mar 2019 07:16:16 +0000 Message-ID: <1552288273-31028-3-git-send-email-Anson.Huang@nxp.com> References: <1552288273-31028-1-git-send-email-Anson.Huang@nxp.com> In-Reply-To: <1552288273-31028-1-git-send-email-Anson.Huang@nxp.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-mailer: git-send-email 2.7.4 x-clientproxiedby: HK0PR03CA0090.apcprd03.prod.outlook.com (2603:1096:203:72::30) To DB3PR0402MB3916.eurprd04.prod.outlook.com (2603:10a6:8:10::18) authentication-results: spf=none (sender IP is ) smtp.mailfrom=anson.huang@nxp.com; x-ms-exchange-messagesentrepresentingtype: 1 x-originating-ip: [119.31.174.66] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: c1b9ddab-bd09-450e-839f-08d6a5f17374 x-ms-office365-filtering-ht: Tenant x-microsoft-antispam: BCL:0; PCL:0; RULEID:(2390118)(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600127)(711020)(4605104)(4618075)(2017052603328)(7153060)(7193020); SRVR:DB3PR0402MB3724; x-ms-traffictypediagnostic: DB3PR0402MB3724: x-microsoft-exchange-diagnostics: =?iso-8859-1?Q?1; DB3PR0402MB3724; 23:HVQzNF0uTmuGp2sBA6dO6Hz8wgQWRCydjVhv6?= =?iso-8859-1?q?Y91psyWAzfuau/on7?= =?iso-8859-1?q?T6I/TxHsIQFc6R0RESXNoKGMaoqLSXr0bzX84gDOwZZfHDM0Df8WIBQrJH0G?= =?iso-8859-1?q?dTa467Nx9CQsXiJthOtJ3e68LlDI3m3pRG75+1VkGM2/Ay9ahxlbT+wDwXyy?= =?iso-8859-1?q?EwJR8W3xodNHOwJJU30A9aG2c6rWTxSleW6w0dxLvGI+SPcfKEpE1tMy0Q5i?= =?iso-8859-1?q?7thzpjmSqTtujvxeNqHNhfC44LzQbUPjZoAk5Ohq+YdGnm7IBP8ZF3xAbzYj?= =?iso-8859-1?q?IL1ifwcnx4qPkp+aRcoPQRCyF3A2WxoU21x8Inf8F/WbztQF1cFY8ruOrwyF?= =?iso-8859-1?q?6N3yETA4zLtQK9E2PjXao+Hv8wA7nS5CA223zxcweRWIzCX6jEXRgc5jVUf0?= =?iso-8859-1?q?fRXeouDTeLBAkSFjTQv58QNDm/HS8j7jmT8cxPsZQLBc796AFh2xq5PWPOwb?= =?iso-8859-1?q?DYWpX2CuKbCZUPKgBGz1/QMH75lsEIcsqWiyY6gFZ8ig1ZrjwTTGhE9egeb/?= =?iso-8859-1?q?2Vy9VrSE/psw4ZkHTmjCW48PTIZLALleUi0o7cxQ8zzBflaS7se/a08MyJTg?= =?iso-8859-1?q?xe3vXVWUIKso+vq4J9oPlu4lLccqyWDUga96pqYRQcXaW2cegTocOdQETEdb?= =?iso-8859-1?q?WX1fd3anYRnnIFfz0uKWyjN9M5MO+Nif2svzJx/YM3heX6zx6lpAhQmpJysp?= =?iso-8859-1?q?7uFFruliFxFDoSQ57JX3vdzF9e/JWdz88pru+BmrqCwKhR+ntK8zYXY38Baw?= =?iso-8859-1?q?jSSLHHzHBpAvL6dsMcaoolMFwD0NnQqcPw8zIqBSMBS76wekIKzCtnRGsea4?= =?iso-8859-1?q?POVn1R0jeIh5KPPJDEFw5DHLVoRWAS+au2CtAB2YfNuWXl1sIts598yOj8Pt?= =?iso-8859-1?q?/Y/uAGt/+5X6pcFTZdMpsTFLbpxWGU1D5sNRCZx3nq7VvTa/0uUKSpv2iW5k?= =?iso-8859-1?q?Z2hmc7A1Xw+DLKEoJiJPzhI/TpbIJNFd4bw7/ii5D3oAD5Glv/EmgoOYMgwF?= =?iso-8859-1?q?2oLTqc1xUYXFuIl0JERQeKiEOqhg1YzYlT9q/Th6jCHfV2PYJtZQMwosMGbl?= =?iso-8859-1?q?xar5ENFb7yIrRga0xq2hFL4eGA+mhHZYsORa05mhCfPwcQIuK+3nFvtHJWaX?= =?iso-8859-1?q?rrtVHO09TCm2tG5JDHX1qRCetmZAhaG1B0+2u+UMQZ+yF/8qMpYXq2ZW99CO?= =?iso-8859-1?q?GXB8dCSf26dxkLmMdWAboJbcSzOFNt3aMErhpB73LTfnL8i+JWf7NuuPm1XG?= =?iso-8859-1?q?lmKrvzeGu/9Y0Wkv6MwsuYhB1fH1j3ny/4BqXMYWs4jhcEtw=3D=3D?= x-microsoft-antispam-prvs: x-forefront-prvs: 09730BD177 x-forefront-antispam-report: SFV:NSPM; SFS:(10009020)(346002)(376002)(39860400002)(366004)(396003)(136003)(199004)(189003)(105586002)(6512007)(6486002)(2501003)(6436002)(97736004)(446003)(110136005)(2616005)(81166006)(81156014)(8676002)(11346002)(106356001)(478600001)(6116002)(3846002)(4326008)(25786009)(486006)(476003)(2906002)(305945005)(316002)(7736002)(102836004)(7416002)(14454004)(52116002)(256004)(6666004)(8936002)(66066001)(186003)(6506007)(386003)(71200400001)(99286004)(5660300002)(71190400001)(86362001)(76176011)(14444005)(26005)(53936002)(68736007)(50226002)(36756003)(2201001)(921003)(1121003); DIR:OUT; SFP:1101; SCL:1; SRVR:DB3PR0402MB3724; H:DB3PR0402MB3916.eurprd04.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; received-spf: None (protection.outlook.com: nxp.com does not designate permitted sender hosts) x-ms-exchange-senderadcheck: 1 x-microsoft-antispam-message-info: 9kdperg0u+TdwPmLAN+SY4rQiNz4Q+AgGdn1BAXSxr8/NNp3Tfx93pfKw/kNm5gsG0m3l7gE3yARnTU0owBVgBTA4N1n6ihBYgSJugoaRQrnhR0i9Xa+A6y1RoerX/T4F0cNaryQ71fSYvuJb+tYYRHH0qfmb3PxYoLLuPGpENHlZx8ECDYdyoA8fE7LxYdGIkoTAS9OFTs0936UF9h0nr7+yeiS/qCvT5iMNZRKtSEvyiV8NE+B2NeyRRYReGWA/oFht7eywn4AZvX8z234KoMbwcCCIQYhfBKghDCLufd58GNr5OUQpoaqGDW3X/8eB7vKFJANwZqf4uFFz7+MnvDDuoyxCFzmnZZmNeKsiiin5LXSKFHKOBXeW8NLsa1BSt9kYORcbnBAmq/cp7D8vapyAYkbPT0xmAsESWJgktA= MIME-Version: 1.0 X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: c1b9ddab-bd09-450e-839f-08d6a5f17374 X-MS-Exchange-CrossTenant-originalarrivaltime: 11 Mar 2019 07:16:16.6834 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB3PR0402MB3724 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190311_001657_951565_79A21F82 X-CRM114-Status: GOOD ( 20.49 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: dl-linux-imx Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP i.MX7ULP has TPM(Low Power Timer/Pulse Width Modulation Module) inside, add TPM PWM driver support. Signed-off-by: Anson Huang --- drivers/pwm/Kconfig | 9 ++ drivers/pwm/Makefile | 1 + drivers/pwm/pwm-imx-tpm.c | 277 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 287 insertions(+) create mode 100644 drivers/pwm/pwm-imx-tpm.c diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index a8f47df..23839ad 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -201,6 +201,15 @@ config PWM_IMX To compile this driver as a module, choose M here: the module will be called pwm-imx. +config PWM_IMX_TPM + tristate "i.MX TPM PWM support" + depends on ARCH_MXC + help + Generic PWM framework driver for i.MX TPM. + + To compile this driver as a module, choose M here: the module + will be called pwm-imx-tpm. + config PWM_JZ4740 tristate "Ingenic JZ47xx PWM support" depends on MACH_INGENIC diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 9c676a0..64e036c 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o obj-$(CONFIG_PWM_HIBVT) += pwm-hibvt.o obj-$(CONFIG_PWM_IMG) += pwm-img.o obj-$(CONFIG_PWM_IMX) += pwm-imx.o +obj-$(CONFIG_PWM_IMX_TPM) += pwm-imx-tpm.o obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o obj-$(CONFIG_PWM_LP3943) += pwm-lp3943.o obj-$(CONFIG_PWM_LPC18XX_SCT) += pwm-lpc18xx-sct.o diff --git a/drivers/pwm/pwm-imx-tpm.c b/drivers/pwm/pwm-imx-tpm.c new file mode 100644 index 0000000..a53256a --- /dev/null +++ b/drivers/pwm/pwm-imx-tpm.c @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2018-2019 NXP. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TPM_GLOBAL 0x8 +#define TPM_SC 0x10 +#define TPM_CNT 0x14 +#define TPM_MOD 0x18 +#define TPM_C0SC 0x20 +#define TPM_C0V 0x24 + +#define SC_CMOD 3 +#define SC_CPWMS BIT(5) +#define MSnB BIT(5) +#define MSnA BIT(4) +#define ELSnB BIT(3) +#define ELSnA BIT(2) + +#define TPM_SC_PS_MASK 0x7 +#define TPM_MOD_MOD_MASK 0xffff + +#define PERIOD_PERIOD_MAX 0x10000 +#define PERIOD_DIV_MAX 8 + +#define TPM_CHn_ADDR_OFFSET 0x8 +#define DEFAULT_PWM_CHANNEL_NUM 2 + +struct tpm_pwm_chip { + struct pwm_chip chip; + struct clk *clk; + void __iomem *base; +}; + +static const unsigned int prediv[8] = { + 1, 2, 4, 8, 16, 32, 64, 128 +}; + +#define to_tpm_pwm_chip(_chip) container_of(_chip, struct tpm_pwm_chip, chip) + +static int tpm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + int duty_ns, int period_ns) +{ + struct tpm_pwm_chip *tpm = to_tpm_pwm_chip(chip); + unsigned int period_cycles, duty_cycles; + unsigned long rate; + u32 val, div = 0; + u64 c; + int ret; + + rate = clk_get_rate(tpm->clk); + /* calculate the period_cycles and duty_cycles */ + while (1) { + c = rate / prediv[div]; + c = c * period_ns; + do_div(c, 1000000000); + if (c < PERIOD_PERIOD_MAX) + break; + div++; + if (div >= 8) + return -EINVAL; + } + + /* enable the clock before writing the register */ + if (!pwm_is_enabled(pwm)) { + ret = clk_prepare_enable(tpm->clk); + if (ret) { + dev_err(chip->dev, + "failed to prepare or enable clk %d\n", ret); + return ret; + } + } + + val = readl(tpm->base + TPM_SC); + val &= ~TPM_SC_PS_MASK; + val |= div; + writel(val, tpm->base + TPM_SC); + + period_cycles = c; + c *= duty_ns; + do_div(c, period_ns); + duty_cycles = c; + + writel(period_cycles & TPM_MOD_MOD_MASK, tpm->base + TPM_MOD); + writel(duty_cycles & TPM_MOD_MOD_MASK, tpm->base + + TPM_C0V + pwm->hwpwm * TPM_CHn_ADDR_OFFSET); + + /* if pwm is not enabled, disable clk after setting */ + if (!pwm_is_enabled(pwm)) + clk_disable_unprepare(tpm->clk); + + return 0; +} + +static int tpm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct tpm_pwm_chip *tpm = to_tpm_pwm_chip(chip); + int ret; + u32 val; + + ret = clk_prepare_enable(tpm->clk); + if (ret) { + dev_err(chip->dev, + "failed to prepare or enable clk %d\n", ret); + return ret; + } + + /* + * To enable a tpm channel, CPWMS = 0, MSnB:MSnA = 0x0, + * for TPM normal polarity ELSnB:ELSnA = 2b'10, + * inverse ELSnB:ELSnA = 2b'01 + */ + val = readl(tpm->base + TPM_C0SC + pwm->hwpwm * TPM_CHn_ADDR_OFFSET); + val &= ~(MSnB | MSnA | ELSnB | ELSnA); + val |= MSnB; + val |= pwm->state.polarity ? ELSnA : ELSnB; + + writel(val, tpm->base + TPM_C0SC + pwm->hwpwm * TPM_CHn_ADDR_OFFSET); + + /* start the counter */ + val = readl(tpm->base + TPM_SC); + val |= 0x1 << SC_CMOD; + writel(val, tpm->base + TPM_SC); + + return 0; +} + +static void tpm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) +{ + struct tpm_pwm_chip *tpm = to_tpm_pwm_chip(chip); + + clk_disable_unprepare(tpm->clk); +} + +static int tpm_pwm_set_polarity(struct pwm_chip *chip, + struct pwm_device *pwm, + enum pwm_polarity polarity) +{ + struct tpm_pwm_chip *tpm = to_tpm_pwm_chip(chip); + int ret; + u32 val; + + /* enable the clock before writing the register */ + if (!pwm_is_enabled(pwm)) { + ret = clk_prepare_enable(tpm->clk); + if (ret) { + dev_err(chip->dev, + "failed to prepare or enable clk %d\n", ret); + return ret; + } + } + + val = readl(tpm->base + TPM_C0SC + pwm->hwpwm * TPM_CHn_ADDR_OFFSET); + val &= ~(ELSnB | ELSnA); + val |= pwm->state.polarity ? ELSnA : ELSnB; + writel(val, tpm->base + TPM_C0SC + pwm->hwpwm * TPM_CHn_ADDR_OFFSET); + + /* disable the clock after writing the register */ + if (!pwm_is_enabled(pwm)) + clk_disable_unprepare(tpm->clk); + + return 0; +} + +static const struct pwm_ops tpm_pwm_ops = { + .config = tpm_pwm_config, + .enable = tpm_pwm_enable, + .disable = tpm_pwm_disable, + .set_polarity = tpm_pwm_set_polarity, + .owner = THIS_MODULE, +}; + +static int tpm_pwm_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct tpm_pwm_chip *tpm; + struct resource *res; + int ret; + + tpm = devm_kzalloc(&pdev->dev, sizeof(*tpm), GFP_KERNEL); + if (!tpm) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + tpm->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(tpm->base)) + return PTR_ERR(tpm->base); + + tpm->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(tpm->clk)) + return PTR_ERR(tpm->clk); + + tpm->chip.dev = &pdev->dev; + tpm->chip.ops = &tpm_pwm_ops; + tpm->chip.base = -1; + tpm->chip.npwm = DEFAULT_PWM_CHANNEL_NUM; + + /* init pwm channel number if "fsl,pwm-number" is found in DT */ + ret = of_property_read_u32(np, "fsl,pwm-number", &tpm->chip.npwm); + if (ret) + dev_warn(&pdev->dev, "two pwm channels by default\n"); + + ret = pwmchip_add(&tpm->chip); + if (ret) { + dev_err(&pdev->dev, "failed to add pwm chip %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, tpm); + + return 0; +} + +static int tpm_pwm_remove(struct platform_device *pdev) +{ + struct tpm_pwm_chip *tpm = platform_get_drvdata(pdev); + + return pwmchip_remove(&tpm->chip); +} + +static int __maybe_unused tpm_pwm_suspend(struct device *dev) +{ + struct tpm_pwm_chip *tpm = dev_get_drvdata(dev); + + clk_disable_unprepare(tpm->clk); + + return 0; +} + +static int __maybe_unused tpm_pwm_resume(struct device *dev) +{ + struct tpm_pwm_chip *tpm = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(tpm->clk); + if (ret) { + dev_err(dev, "could not prepare or enable tpm clock\n"); + return ret; + } + + return 0; +}; + +static SIMPLE_DEV_PM_OPS(tpm_pwm_pm, + tpm_pwm_suspend, tpm_pwm_resume); + +static const struct of_device_id tpm_pwm_dt_ids[] = { + { .compatible = "fsl,imx-tpm-pwm", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, tpm_pwm_dt_ids); + +static struct platform_driver tpm_pwm_driver = { + .driver = { + .name = "tpm-pwm", + .of_match_table = tpm_pwm_dt_ids, + .pm = &tpm_pwm_pm, + }, + .probe = tpm_pwm_probe, + .remove = tpm_pwm_remove, +}; +module_platform_driver(tpm_pwm_driver); + +MODULE_AUTHOR("Jacky Bai "); +MODULE_DESCRIPTION("i.MX TPM PWM Driver"); +MODULE_LICENSE("GPL v2");