cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pwm-tiehrpwm.c (15639B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * EHRPWM PWM driver
      4 *
      5 * Copyright (C) 2012 Texas Instruments, Inc. - https://www.ti.com/
      6 */
      7
      8#include <linux/module.h>
      9#include <linux/platform_device.h>
     10#include <linux/pwm.h>
     11#include <linux/io.h>
     12#include <linux/err.h>
     13#include <linux/clk.h>
     14#include <linux/pm_runtime.h>
     15#include <linux/of_device.h>
     16
     17/* EHRPWM registers and bits definitions */
     18
     19/* Time base module registers */
     20#define TBCTL			0x00
     21#define TBPRD			0x0A
     22
     23#define TBCTL_PRDLD_MASK	BIT(3)
     24#define TBCTL_PRDLD_SHDW	0
     25#define TBCTL_PRDLD_IMDT	BIT(3)
     26#define TBCTL_CLKDIV_MASK	(BIT(12) | BIT(11) | BIT(10) | BIT(9) | \
     27				BIT(8) | BIT(7))
     28#define TBCTL_CTRMODE_MASK	(BIT(1) | BIT(0))
     29#define TBCTL_CTRMODE_UP	0
     30#define TBCTL_CTRMODE_DOWN	BIT(0)
     31#define TBCTL_CTRMODE_UPDOWN	BIT(1)
     32#define TBCTL_CTRMODE_FREEZE	(BIT(1) | BIT(0))
     33
     34#define TBCTL_HSPCLKDIV_SHIFT	7
     35#define TBCTL_CLKDIV_SHIFT	10
     36
     37#define CLKDIV_MAX		7
     38#define HSPCLKDIV_MAX		7
     39#define PERIOD_MAX		0xFFFF
     40
     41/* compare module registers */
     42#define CMPA			0x12
     43#define CMPB			0x14
     44
     45/* Action qualifier module registers */
     46#define AQCTLA			0x16
     47#define AQCTLB			0x18
     48#define AQSFRC			0x1A
     49#define AQCSFRC			0x1C
     50
     51#define AQCTL_CBU_MASK		(BIT(9) | BIT(8))
     52#define AQCTL_CBU_FRCLOW	BIT(8)
     53#define AQCTL_CBU_FRCHIGH	BIT(9)
     54#define AQCTL_CBU_FRCTOGGLE	(BIT(9) | BIT(8))
     55#define AQCTL_CAU_MASK		(BIT(5) | BIT(4))
     56#define AQCTL_CAU_FRCLOW	BIT(4)
     57#define AQCTL_CAU_FRCHIGH	BIT(5)
     58#define AQCTL_CAU_FRCTOGGLE	(BIT(5) | BIT(4))
     59#define AQCTL_PRD_MASK		(BIT(3) | BIT(2))
     60#define AQCTL_PRD_FRCLOW	BIT(2)
     61#define AQCTL_PRD_FRCHIGH	BIT(3)
     62#define AQCTL_PRD_FRCTOGGLE	(BIT(3) | BIT(2))
     63#define AQCTL_ZRO_MASK		(BIT(1) | BIT(0))
     64#define AQCTL_ZRO_FRCLOW	BIT(0)
     65#define AQCTL_ZRO_FRCHIGH	BIT(1)
     66#define AQCTL_ZRO_FRCTOGGLE	(BIT(1) | BIT(0))
     67
     68#define AQCTL_CHANA_POLNORMAL	(AQCTL_CAU_FRCLOW | AQCTL_PRD_FRCHIGH | \
     69				AQCTL_ZRO_FRCHIGH)
     70#define AQCTL_CHANA_POLINVERSED	(AQCTL_CAU_FRCHIGH | AQCTL_PRD_FRCLOW | \
     71				AQCTL_ZRO_FRCLOW)
     72#define AQCTL_CHANB_POLNORMAL	(AQCTL_CBU_FRCLOW | AQCTL_PRD_FRCHIGH | \
     73				AQCTL_ZRO_FRCHIGH)
     74#define AQCTL_CHANB_POLINVERSED	(AQCTL_CBU_FRCHIGH | AQCTL_PRD_FRCLOW | \
     75				AQCTL_ZRO_FRCLOW)
     76
     77#define AQSFRC_RLDCSF_MASK	(BIT(7) | BIT(6))
     78#define AQSFRC_RLDCSF_ZRO	0
     79#define AQSFRC_RLDCSF_PRD	BIT(6)
     80#define AQSFRC_RLDCSF_ZROPRD	BIT(7)
     81#define AQSFRC_RLDCSF_IMDT	(BIT(7) | BIT(6))
     82
     83#define AQCSFRC_CSFB_MASK	(BIT(3) | BIT(2))
     84#define AQCSFRC_CSFB_FRCDIS	0
     85#define AQCSFRC_CSFB_FRCLOW	BIT(2)
     86#define AQCSFRC_CSFB_FRCHIGH	BIT(3)
     87#define AQCSFRC_CSFB_DISSWFRC	(BIT(3) | BIT(2))
     88#define AQCSFRC_CSFA_MASK	(BIT(1) | BIT(0))
     89#define AQCSFRC_CSFA_FRCDIS	0
     90#define AQCSFRC_CSFA_FRCLOW	BIT(0)
     91#define AQCSFRC_CSFA_FRCHIGH	BIT(1)
     92#define AQCSFRC_CSFA_DISSWFRC	(BIT(1) | BIT(0))
     93
     94#define NUM_PWM_CHANNEL		2	/* EHRPWM channels */
     95
     96struct ehrpwm_context {
     97	u16 tbctl;
     98	u16 tbprd;
     99	u16 cmpa;
    100	u16 cmpb;
    101	u16 aqctla;
    102	u16 aqctlb;
    103	u16 aqsfrc;
    104	u16 aqcsfrc;
    105};
    106
    107struct ehrpwm_pwm_chip {
    108	struct pwm_chip chip;
    109	unsigned long clk_rate;
    110	void __iomem *mmio_base;
    111	unsigned long period_cycles[NUM_PWM_CHANNEL];
    112	enum pwm_polarity polarity[NUM_PWM_CHANNEL];
    113	struct clk *tbclk;
    114	struct ehrpwm_context ctx;
    115};
    116
    117static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip)
    118{
    119	return container_of(chip, struct ehrpwm_pwm_chip, chip);
    120}
    121
    122static inline u16 ehrpwm_read(void __iomem *base, unsigned int offset)
    123{
    124	return readw(base + offset);
    125}
    126
    127static inline void ehrpwm_write(void __iomem *base, unsigned int offset,
    128				u16 value)
    129{
    130	writew(value, base + offset);
    131}
    132
    133static void ehrpwm_modify(void __iomem *base, unsigned int offset, u16 mask,
    134			  u16 value)
    135{
    136	unsigned short val;
    137
    138	val = readw(base + offset);
    139	val &= ~mask;
    140	val |= value & mask;
    141	writew(val, base + offset);
    142}
    143
    144/**
    145 * set_prescale_div -	Set up the prescaler divider function
    146 * @rqst_prescaler:	prescaler value min
    147 * @prescale_div:	prescaler value set
    148 * @tb_clk_div:		Time Base Control prescaler bits
    149 */
    150static int set_prescale_div(unsigned long rqst_prescaler, u16 *prescale_div,
    151			    u16 *tb_clk_div)
    152{
    153	unsigned int clkdiv, hspclkdiv;
    154
    155	for (clkdiv = 0; clkdiv <= CLKDIV_MAX; clkdiv++) {
    156		for (hspclkdiv = 0; hspclkdiv <= HSPCLKDIV_MAX; hspclkdiv++) {
    157			/*
    158			 * calculations for prescaler value :
    159			 * prescale_div = HSPCLKDIVIDER * CLKDIVIDER.
    160			 * HSPCLKDIVIDER =  2 ** hspclkdiv
    161			 * CLKDIVIDER = (1),		if clkdiv == 0 *OR*
    162			 *		(2 * clkdiv),	if clkdiv != 0
    163			 *
    164			 * Configure prescale_div value such that period
    165			 * register value is less than 65535.
    166			 */
    167
    168			*prescale_div = (1 << clkdiv) *
    169					(hspclkdiv ? (hspclkdiv * 2) : 1);
    170			if (*prescale_div > rqst_prescaler) {
    171				*tb_clk_div = (clkdiv << TBCTL_CLKDIV_SHIFT) |
    172					(hspclkdiv << TBCTL_HSPCLKDIV_SHIFT);
    173				return 0;
    174			}
    175		}
    176	}
    177
    178	return 1;
    179}
    180
    181static void configure_polarity(struct ehrpwm_pwm_chip *pc, int chan)
    182{
    183	u16 aqctl_val, aqctl_mask;
    184	unsigned int aqctl_reg;
    185
    186	/*
    187	 * Configure PWM output to HIGH/LOW level on counter
    188	 * reaches compare register value and LOW/HIGH level
    189	 * on counter value reaches period register value and
    190	 * zero value on counter
    191	 */
    192	if (chan == 1) {
    193		aqctl_reg = AQCTLB;
    194		aqctl_mask = AQCTL_CBU_MASK;
    195
    196		if (pc->polarity[chan] == PWM_POLARITY_INVERSED)
    197			aqctl_val = AQCTL_CHANB_POLINVERSED;
    198		else
    199			aqctl_val = AQCTL_CHANB_POLNORMAL;
    200	} else {
    201		aqctl_reg = AQCTLA;
    202		aqctl_mask = AQCTL_CAU_MASK;
    203
    204		if (pc->polarity[chan] == PWM_POLARITY_INVERSED)
    205			aqctl_val = AQCTL_CHANA_POLINVERSED;
    206		else
    207			aqctl_val = AQCTL_CHANA_POLNORMAL;
    208	}
    209
    210	aqctl_mask |= AQCTL_PRD_MASK | AQCTL_ZRO_MASK;
    211	ehrpwm_modify(pc->mmio_base, aqctl_reg, aqctl_mask, aqctl_val);
    212}
    213
    214/*
    215 * period_ns = 10^9 * (ps_divval * period_cycles) / PWM_CLK_RATE
    216 * duty_ns   = 10^9 * (ps_divval * duty_cycles) / PWM_CLK_RATE
    217 */
    218static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
    219			     u64 duty_ns, u64 period_ns)
    220{
    221	struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
    222	u32 period_cycles, duty_cycles;
    223	u16 ps_divval, tb_divval;
    224	unsigned int i, cmp_reg;
    225	unsigned long long c;
    226
    227	if (period_ns > NSEC_PER_SEC)
    228		return -ERANGE;
    229
    230	c = pc->clk_rate;
    231	c = c * period_ns;
    232	do_div(c, NSEC_PER_SEC);
    233	period_cycles = (unsigned long)c;
    234
    235	if (period_cycles < 1) {
    236		period_cycles = 1;
    237		duty_cycles = 1;
    238	} else {
    239		c = pc->clk_rate;
    240		c = c * duty_ns;
    241		do_div(c, NSEC_PER_SEC);
    242		duty_cycles = (unsigned long)c;
    243	}
    244
    245	/*
    246	 * Period values should be same for multiple PWM channels as IP uses
    247	 * same period register for multiple channels.
    248	 */
    249	for (i = 0; i < NUM_PWM_CHANNEL; i++) {
    250		if (pc->period_cycles[i] &&
    251				(pc->period_cycles[i] != period_cycles)) {
    252			/*
    253			 * Allow channel to reconfigure period if no other
    254			 * channels being configured.
    255			 */
    256			if (i == pwm->hwpwm)
    257				continue;
    258
    259			dev_err(chip->dev,
    260				"period value conflicts with channel %u\n",
    261				i);
    262			return -EINVAL;
    263		}
    264	}
    265
    266	pc->period_cycles[pwm->hwpwm] = period_cycles;
    267
    268	/* Configure clock prescaler to support Low frequency PWM wave */
    269	if (set_prescale_div(period_cycles/PERIOD_MAX, &ps_divval,
    270			     &tb_divval)) {
    271		dev_err(chip->dev, "Unsupported values\n");
    272		return -EINVAL;
    273	}
    274
    275	pm_runtime_get_sync(chip->dev);
    276
    277	/* Update clock prescaler values */
    278	ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CLKDIV_MASK, tb_divval);
    279
    280	/* Update period & duty cycle with presacler division */
    281	period_cycles = period_cycles / ps_divval;
    282	duty_cycles = duty_cycles / ps_divval;
    283
    284	/* Configure shadow loading on Period register */
    285	ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_PRDLD_MASK, TBCTL_PRDLD_SHDW);
    286
    287	ehrpwm_write(pc->mmio_base, TBPRD, period_cycles);
    288
    289	/* Configure ehrpwm counter for up-count mode */
    290	ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_CTRMODE_MASK,
    291		      TBCTL_CTRMODE_UP);
    292
    293	if (pwm->hwpwm == 1)
    294		/* Channel 1 configured with compare B register */
    295		cmp_reg = CMPB;
    296	else
    297		/* Channel 0 configured with compare A register */
    298		cmp_reg = CMPA;
    299
    300	ehrpwm_write(pc->mmio_base, cmp_reg, duty_cycles);
    301
    302	pm_runtime_put_sync(chip->dev);
    303
    304	return 0;
    305}
    306
    307static int ehrpwm_pwm_set_polarity(struct pwm_chip *chip,
    308				   struct pwm_device *pwm,
    309				   enum pwm_polarity polarity)
    310{
    311	struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
    312
    313	/* Configuration of polarity in hardware delayed, do at enable */
    314	pc->polarity[pwm->hwpwm] = polarity;
    315
    316	return 0;
    317}
    318
    319static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
    320{
    321	struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
    322	u16 aqcsfrc_val, aqcsfrc_mask;
    323	int ret;
    324
    325	/* Leave clock enabled on enabling PWM */
    326	pm_runtime_get_sync(chip->dev);
    327
    328	/* Disabling Action Qualifier on PWM output */
    329	if (pwm->hwpwm) {
    330		aqcsfrc_val = AQCSFRC_CSFB_FRCDIS;
    331		aqcsfrc_mask = AQCSFRC_CSFB_MASK;
    332	} else {
    333		aqcsfrc_val = AQCSFRC_CSFA_FRCDIS;
    334		aqcsfrc_mask = AQCSFRC_CSFA_MASK;
    335	}
    336
    337	/* Changes to shadow mode */
    338	ehrpwm_modify(pc->mmio_base, AQSFRC, AQSFRC_RLDCSF_MASK,
    339		      AQSFRC_RLDCSF_ZRO);
    340
    341	ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
    342
    343	/* Channels polarity can be configured from action qualifier module */
    344	configure_polarity(pc, pwm->hwpwm);
    345
    346	/* Enable TBCLK */
    347	ret = clk_enable(pc->tbclk);
    348	if (ret) {
    349		dev_err(chip->dev, "Failed to enable TBCLK for %s: %d\n",
    350			dev_name(pc->chip.dev), ret);
    351		return ret;
    352	}
    353
    354	return 0;
    355}
    356
    357static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
    358{
    359	struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
    360	u16 aqcsfrc_val, aqcsfrc_mask;
    361
    362	/* Action Qualifier puts PWM output low forcefully */
    363	if (pwm->hwpwm) {
    364		aqcsfrc_val = AQCSFRC_CSFB_FRCLOW;
    365		aqcsfrc_mask = AQCSFRC_CSFB_MASK;
    366	} else {
    367		aqcsfrc_val = AQCSFRC_CSFA_FRCLOW;
    368		aqcsfrc_mask = AQCSFRC_CSFA_MASK;
    369	}
    370
    371	/* Update shadow register first before modifying active register */
    372	ehrpwm_modify(pc->mmio_base, AQSFRC, AQSFRC_RLDCSF_MASK,
    373		      AQSFRC_RLDCSF_ZRO);
    374	ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
    375	/*
    376	 * Changes to immediate action on Action Qualifier. This puts
    377	 * Action Qualifier control on PWM output from next TBCLK
    378	 */
    379	ehrpwm_modify(pc->mmio_base, AQSFRC, AQSFRC_RLDCSF_MASK,
    380		      AQSFRC_RLDCSF_IMDT);
    381
    382	ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
    383
    384	/* Disabling TBCLK on PWM disable */
    385	clk_disable(pc->tbclk);
    386
    387	/* Disable clock on PWM disable */
    388	pm_runtime_put_sync(chip->dev);
    389}
    390
    391static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
    392{
    393	struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
    394
    395	if (pwm_is_enabled(pwm)) {
    396		dev_warn(chip->dev, "Removing PWM device without disabling\n");
    397		pm_runtime_put_sync(chip->dev);
    398	}
    399
    400	/* set period value to zero on free */
    401	pc->period_cycles[pwm->hwpwm] = 0;
    402}
    403
    404static int ehrpwm_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
    405			    const struct pwm_state *state)
    406{
    407	int err;
    408	bool enabled = pwm->state.enabled;
    409
    410	if (state->polarity != pwm->state.polarity) {
    411		if (enabled) {
    412			ehrpwm_pwm_disable(chip, pwm);
    413			enabled = false;
    414		}
    415
    416		err = ehrpwm_pwm_set_polarity(chip, pwm, state->polarity);
    417		if (err)
    418			return err;
    419	}
    420
    421	if (!state->enabled) {
    422		if (enabled)
    423			ehrpwm_pwm_disable(chip, pwm);
    424		return 0;
    425	}
    426
    427	err = ehrpwm_pwm_config(chip, pwm, state->duty_cycle, state->period);
    428	if (err)
    429		return err;
    430
    431	if (!enabled)
    432		err = ehrpwm_pwm_enable(chip, pwm);
    433
    434	return err;
    435}
    436
    437static const struct pwm_ops ehrpwm_pwm_ops = {
    438	.free = ehrpwm_pwm_free,
    439	.apply = ehrpwm_pwm_apply,
    440	.owner = THIS_MODULE,
    441};
    442
    443static const struct of_device_id ehrpwm_of_match[] = {
    444	{ .compatible = "ti,am3352-ehrpwm" },
    445	{ .compatible = "ti,am33xx-ehrpwm" },
    446	{},
    447};
    448MODULE_DEVICE_TABLE(of, ehrpwm_of_match);
    449
    450static int ehrpwm_pwm_probe(struct platform_device *pdev)
    451{
    452	struct device_node *np = pdev->dev.of_node;
    453	struct ehrpwm_pwm_chip *pc;
    454	struct clk *clk;
    455	int ret;
    456
    457	pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
    458	if (!pc)
    459		return -ENOMEM;
    460
    461	clk = devm_clk_get(&pdev->dev, "fck");
    462	if (IS_ERR(clk)) {
    463		if (of_device_is_compatible(np, "ti,am33xx-ecap")) {
    464			dev_warn(&pdev->dev, "Binding is obsolete.\n");
    465			clk = devm_clk_get(pdev->dev.parent, "fck");
    466		}
    467	}
    468
    469	if (IS_ERR(clk))
    470		return dev_err_probe(&pdev->dev, PTR_ERR(clk), "Failed to get fck\n");
    471
    472	pc->clk_rate = clk_get_rate(clk);
    473	if (!pc->clk_rate) {
    474		dev_err(&pdev->dev, "failed to get clock rate\n");
    475		return -EINVAL;
    476	}
    477
    478	pc->chip.dev = &pdev->dev;
    479	pc->chip.ops = &ehrpwm_pwm_ops;
    480	pc->chip.npwm = NUM_PWM_CHANNEL;
    481
    482	pc->mmio_base = devm_platform_ioremap_resource(pdev, 0);
    483	if (IS_ERR(pc->mmio_base))
    484		return PTR_ERR(pc->mmio_base);
    485
    486	/* Acquire tbclk for Time Base EHRPWM submodule */
    487	pc->tbclk = devm_clk_get(&pdev->dev, "tbclk");
    488	if (IS_ERR(pc->tbclk))
    489		return dev_err_probe(&pdev->dev, PTR_ERR(pc->tbclk), "Failed to get tbclk\n");
    490
    491	ret = clk_prepare(pc->tbclk);
    492	if (ret < 0) {
    493		dev_err(&pdev->dev, "clk_prepare() failed: %d\n", ret);
    494		return ret;
    495	}
    496
    497	ret = pwmchip_add(&pc->chip);
    498	if (ret < 0) {
    499		dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
    500		goto err_clk_unprepare;
    501	}
    502
    503	platform_set_drvdata(pdev, pc);
    504	pm_runtime_enable(&pdev->dev);
    505
    506	return 0;
    507
    508err_clk_unprepare:
    509	clk_unprepare(pc->tbclk);
    510
    511	return ret;
    512}
    513
    514static int ehrpwm_pwm_remove(struct platform_device *pdev)
    515{
    516	struct ehrpwm_pwm_chip *pc = platform_get_drvdata(pdev);
    517
    518	pwmchip_remove(&pc->chip);
    519
    520	clk_unprepare(pc->tbclk);
    521
    522	pm_runtime_disable(&pdev->dev);
    523
    524	return 0;
    525}
    526
    527#ifdef CONFIG_PM_SLEEP
    528static void ehrpwm_pwm_save_context(struct ehrpwm_pwm_chip *pc)
    529{
    530	pm_runtime_get_sync(pc->chip.dev);
    531
    532	pc->ctx.tbctl = ehrpwm_read(pc->mmio_base, TBCTL);
    533	pc->ctx.tbprd = ehrpwm_read(pc->mmio_base, TBPRD);
    534	pc->ctx.cmpa = ehrpwm_read(pc->mmio_base, CMPA);
    535	pc->ctx.cmpb = ehrpwm_read(pc->mmio_base, CMPB);
    536	pc->ctx.aqctla = ehrpwm_read(pc->mmio_base, AQCTLA);
    537	pc->ctx.aqctlb = ehrpwm_read(pc->mmio_base, AQCTLB);
    538	pc->ctx.aqsfrc = ehrpwm_read(pc->mmio_base, AQSFRC);
    539	pc->ctx.aqcsfrc = ehrpwm_read(pc->mmio_base, AQCSFRC);
    540
    541	pm_runtime_put_sync(pc->chip.dev);
    542}
    543
    544static void ehrpwm_pwm_restore_context(struct ehrpwm_pwm_chip *pc)
    545{
    546	ehrpwm_write(pc->mmio_base, TBPRD, pc->ctx.tbprd);
    547	ehrpwm_write(pc->mmio_base, CMPA, pc->ctx.cmpa);
    548	ehrpwm_write(pc->mmio_base, CMPB, pc->ctx.cmpb);
    549	ehrpwm_write(pc->mmio_base, AQCTLA, pc->ctx.aqctla);
    550	ehrpwm_write(pc->mmio_base, AQCTLB, pc->ctx.aqctlb);
    551	ehrpwm_write(pc->mmio_base, AQSFRC, pc->ctx.aqsfrc);
    552	ehrpwm_write(pc->mmio_base, AQCSFRC, pc->ctx.aqcsfrc);
    553	ehrpwm_write(pc->mmio_base, TBCTL, pc->ctx.tbctl);
    554}
    555
    556static int ehrpwm_pwm_suspend(struct device *dev)
    557{
    558	struct ehrpwm_pwm_chip *pc = dev_get_drvdata(dev);
    559	unsigned int i;
    560
    561	ehrpwm_pwm_save_context(pc);
    562
    563	for (i = 0; i < pc->chip.npwm; i++) {
    564		struct pwm_device *pwm = &pc->chip.pwms[i];
    565
    566		if (!pwm_is_enabled(pwm))
    567			continue;
    568
    569		/* Disable explicitly if PWM is running */
    570		pm_runtime_put_sync(dev);
    571	}
    572
    573	return 0;
    574}
    575
    576static int ehrpwm_pwm_resume(struct device *dev)
    577{
    578	struct ehrpwm_pwm_chip *pc = dev_get_drvdata(dev);
    579	unsigned int i;
    580
    581	for (i = 0; i < pc->chip.npwm; i++) {
    582		struct pwm_device *pwm = &pc->chip.pwms[i];
    583
    584		if (!pwm_is_enabled(pwm))
    585			continue;
    586
    587		/* Enable explicitly if PWM was running */
    588		pm_runtime_get_sync(dev);
    589	}
    590
    591	ehrpwm_pwm_restore_context(pc);
    592
    593	return 0;
    594}
    595#endif
    596
    597static SIMPLE_DEV_PM_OPS(ehrpwm_pwm_pm_ops, ehrpwm_pwm_suspend,
    598			 ehrpwm_pwm_resume);
    599
    600static struct platform_driver ehrpwm_pwm_driver = {
    601	.driver = {
    602		.name = "ehrpwm",
    603		.of_match_table = ehrpwm_of_match,
    604		.pm = &ehrpwm_pwm_pm_ops,
    605	},
    606	.probe = ehrpwm_pwm_probe,
    607	.remove = ehrpwm_pwm_remove,
    608};
    609module_platform_driver(ehrpwm_pwm_driver);
    610
    611MODULE_DESCRIPTION("EHRPWM PWM driver");
    612MODULE_AUTHOR("Texas Instruments");
    613MODULE_LICENSE("GPL");