1d80f8206SUwe Kleine-König // SPDX-License-Identifier: GPL-2.0 2d80f8206SUwe Kleine-König /* 3d80f8206SUwe Kleine-König * simple driver for PWM (Pulse Width Modulator) controller 4d80f8206SUwe Kleine-König * 5d80f8206SUwe Kleine-König * Derived from pxa PWM driver by eric miao <eric.miao@marvell.com> 6d80f8206SUwe Kleine-König */ 7d80f8206SUwe Kleine-König 8d80f8206SUwe Kleine-König #include <linux/bitfield.h> 9d80f8206SUwe Kleine-König #include <linux/bitops.h> 10d80f8206SUwe Kleine-König #include <linux/clk.h> 11d80f8206SUwe Kleine-König #include <linux/delay.h> 12d80f8206SUwe Kleine-König #include <linux/err.h> 13d80f8206SUwe Kleine-König #include <linux/io.h> 14d80f8206SUwe Kleine-König #include <linux/kernel.h> 15d80f8206SUwe Kleine-König #include <linux/module.h> 16d80f8206SUwe Kleine-König #include <linux/of.h> 17d80f8206SUwe Kleine-König #include <linux/of_device.h> 18d80f8206SUwe Kleine-König #include <linux/platform_device.h> 19d80f8206SUwe Kleine-König #include <linux/pwm.h> 20d80f8206SUwe Kleine-König #include <linux/slab.h> 21d80f8206SUwe Kleine-König 22d80f8206SUwe Kleine-König #define MX3_PWMCR 0x00 /* PWM Control Register */ 23d80f8206SUwe Kleine-König #define MX3_PWMSR 0x04 /* PWM Status Register */ 24d80f8206SUwe Kleine-König #define MX3_PWMSAR 0x0C /* PWM Sample Register */ 25d80f8206SUwe Kleine-König #define MX3_PWMPR 0x10 /* PWM Period Register */ 26d80f8206SUwe Kleine-König 27d80f8206SUwe Kleine-König #define MX3_PWMCR_FWM GENMASK(27, 26) 28d80f8206SUwe Kleine-König #define MX3_PWMCR_STOPEN BIT(25) 29d80f8206SUwe Kleine-König #define MX3_PWMCR_DOZEN BIT(24) 30d80f8206SUwe Kleine-König #define MX3_PWMCR_WAITEN BIT(23) 31d80f8206SUwe Kleine-König #define MX3_PWMCR_DBGEN BIT(22) 32d80f8206SUwe Kleine-König #define MX3_PWMCR_BCTR BIT(21) 33d80f8206SUwe Kleine-König #define MX3_PWMCR_HCTR BIT(20) 34d80f8206SUwe Kleine-König 35d80f8206SUwe Kleine-König #define MX3_PWMCR_POUTC GENMASK(19, 18) 36d80f8206SUwe Kleine-König #define MX3_PWMCR_POUTC_NORMAL 0 37d80f8206SUwe Kleine-König #define MX3_PWMCR_POUTC_INVERTED 1 38d80f8206SUwe Kleine-König #define MX3_PWMCR_POUTC_OFF 2 39d80f8206SUwe Kleine-König 40d80f8206SUwe Kleine-König #define MX3_PWMCR_CLKSRC GENMASK(17, 16) 41d80f8206SUwe Kleine-König #define MX3_PWMCR_CLKSRC_OFF 0 42d80f8206SUwe Kleine-König #define MX3_PWMCR_CLKSRC_IPG 1 43d80f8206SUwe Kleine-König #define MX3_PWMCR_CLKSRC_IPG_HIGH 2 44d80f8206SUwe Kleine-König #define MX3_PWMCR_CLKSRC_IPG_32K 3 45d80f8206SUwe Kleine-König 46d80f8206SUwe Kleine-König #define MX3_PWMCR_PRESCALER GENMASK(15, 4) 47d80f8206SUwe Kleine-König 48d80f8206SUwe Kleine-König #define MX3_PWMCR_SWR BIT(3) 49d80f8206SUwe Kleine-König 50d80f8206SUwe Kleine-König #define MX3_PWMCR_REPEAT GENMASK(2, 1) 51d80f8206SUwe Kleine-König #define MX3_PWMCR_REPEAT_1X 0 52d80f8206SUwe Kleine-König #define MX3_PWMCR_REPEAT_2X 1 53d80f8206SUwe Kleine-König #define MX3_PWMCR_REPEAT_4X 2 54d80f8206SUwe Kleine-König #define MX3_PWMCR_REPEAT_8X 3 55d80f8206SUwe Kleine-König 56d80f8206SUwe Kleine-König #define MX3_PWMCR_EN BIT(0) 57d80f8206SUwe Kleine-König 58d80f8206SUwe Kleine-König #define MX3_PWMSR_FWE BIT(6) 59d80f8206SUwe Kleine-König #define MX3_PWMSR_CMP BIT(5) 60d80f8206SUwe Kleine-König #define MX3_PWMSR_ROV BIT(4) 61d80f8206SUwe Kleine-König #define MX3_PWMSR_FE BIT(3) 62d80f8206SUwe Kleine-König 63d80f8206SUwe Kleine-König #define MX3_PWMSR_FIFOAV GENMASK(2, 0) 64d80f8206SUwe Kleine-König #define MX3_PWMSR_FIFOAV_EMPTY 0 65d80f8206SUwe Kleine-König #define MX3_PWMSR_FIFOAV_1WORD 1 66d80f8206SUwe Kleine-König #define MX3_PWMSR_FIFOAV_2WORDS 2 67d80f8206SUwe Kleine-König #define MX3_PWMSR_FIFOAV_3WORDS 3 68d80f8206SUwe Kleine-König #define MX3_PWMSR_FIFOAV_4WORDS 4 69d80f8206SUwe Kleine-König 70d80f8206SUwe Kleine-König #define MX3_PWMCR_PRESCALER_SET(x) FIELD_PREP(MX3_PWMCR_PRESCALER, (x) - 1) 71d80f8206SUwe Kleine-König #define MX3_PWMCR_PRESCALER_GET(x) (FIELD_GET(MX3_PWMCR_PRESCALER, \ 72d80f8206SUwe Kleine-König (x)) + 1) 73d80f8206SUwe Kleine-König 74d80f8206SUwe Kleine-König #define MX3_PWM_SWR_LOOP 5 75d80f8206SUwe Kleine-König 76d80f8206SUwe Kleine-König /* PWMPR register value of 0xffff has the same effect as 0xfffe */ 77d80f8206SUwe Kleine-König #define MX3_PWMPR_MAX 0xfffe 78d80f8206SUwe Kleine-König 79d80f8206SUwe Kleine-König struct pwm_imx27_chip { 80d80f8206SUwe Kleine-König struct clk *clk_ipg; 81d80f8206SUwe Kleine-König struct clk *clk_per; 82d80f8206SUwe Kleine-König void __iomem *mmio_base; 83d80f8206SUwe Kleine-König struct pwm_chip chip; 84d80f8206SUwe Kleine-König }; 85d80f8206SUwe Kleine-König 86d80f8206SUwe Kleine-König #define to_pwm_imx27_chip(chip) container_of(chip, struct pwm_imx27_chip, chip) 87d80f8206SUwe Kleine-König 88d80f8206SUwe Kleine-König static int pwm_imx27_clk_prepare_enable(struct pwm_chip *chip) 89d80f8206SUwe Kleine-König { 90d80f8206SUwe Kleine-König struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip); 91d80f8206SUwe Kleine-König int ret; 92d80f8206SUwe Kleine-König 93d80f8206SUwe Kleine-König ret = clk_prepare_enable(imx->clk_ipg); 94d80f8206SUwe Kleine-König if (ret) 95d80f8206SUwe Kleine-König return ret; 96d80f8206SUwe Kleine-König 97d80f8206SUwe Kleine-König ret = clk_prepare_enable(imx->clk_per); 98d80f8206SUwe Kleine-König if (ret) { 99d80f8206SUwe Kleine-König clk_disable_unprepare(imx->clk_ipg); 100d80f8206SUwe Kleine-König return ret; 101d80f8206SUwe Kleine-König } 102d80f8206SUwe Kleine-König 103d80f8206SUwe Kleine-König return 0; 104d80f8206SUwe Kleine-König } 105d80f8206SUwe Kleine-König 106d80f8206SUwe Kleine-König static void pwm_imx27_clk_disable_unprepare(struct pwm_chip *chip) 107d80f8206SUwe Kleine-König { 108d80f8206SUwe Kleine-König struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip); 109d80f8206SUwe Kleine-König 110d80f8206SUwe Kleine-König clk_disable_unprepare(imx->clk_per); 111d80f8206SUwe Kleine-König clk_disable_unprepare(imx->clk_ipg); 112d80f8206SUwe Kleine-König } 113d80f8206SUwe Kleine-König 114d80f8206SUwe Kleine-König static void pwm_imx27_get_state(struct pwm_chip *chip, 115d80f8206SUwe Kleine-König struct pwm_device *pwm, struct pwm_state *state) 116d80f8206SUwe Kleine-König { 117d80f8206SUwe Kleine-König struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip); 1187ca17b20SDan Carpenter u32 period, prescaler, pwm_clk, val; 119d80f8206SUwe Kleine-König u64 tmp; 1207ca17b20SDan Carpenter int ret; 121d80f8206SUwe Kleine-König 122d80f8206SUwe Kleine-König ret = pwm_imx27_clk_prepare_enable(chip); 123d80f8206SUwe Kleine-König if (ret < 0) 124d80f8206SUwe Kleine-König return; 125d80f8206SUwe Kleine-König 126d80f8206SUwe Kleine-König val = readl(imx->mmio_base + MX3_PWMCR); 127d80f8206SUwe Kleine-König 128519ef9b5SUwe Kleine-König if (val & MX3_PWMCR_EN) 129d80f8206SUwe Kleine-König state->enabled = true; 130519ef9b5SUwe Kleine-König else 131d80f8206SUwe Kleine-König state->enabled = false; 132d80f8206SUwe Kleine-König 133d80f8206SUwe Kleine-König switch (FIELD_GET(MX3_PWMCR_POUTC, val)) { 134d80f8206SUwe Kleine-König case MX3_PWMCR_POUTC_NORMAL: 135d80f8206SUwe Kleine-König state->polarity = PWM_POLARITY_NORMAL; 136d80f8206SUwe Kleine-König break; 137d80f8206SUwe Kleine-König case MX3_PWMCR_POUTC_INVERTED: 138d80f8206SUwe Kleine-König state->polarity = PWM_POLARITY_INVERSED; 139d80f8206SUwe Kleine-König break; 140d80f8206SUwe Kleine-König default: 141d80f8206SUwe Kleine-König dev_warn(chip->dev, "can't set polarity, output disconnected"); 142d80f8206SUwe Kleine-König } 143d80f8206SUwe Kleine-König 144d80f8206SUwe Kleine-König prescaler = MX3_PWMCR_PRESCALER_GET(val); 145d80f8206SUwe Kleine-König pwm_clk = clk_get_rate(imx->clk_per); 146d80f8206SUwe Kleine-König pwm_clk = DIV_ROUND_CLOSEST_ULL(pwm_clk, prescaler); 147d80f8206SUwe Kleine-König val = readl(imx->mmio_base + MX3_PWMPR); 148d80f8206SUwe Kleine-König period = val >= MX3_PWMPR_MAX ? MX3_PWMPR_MAX : val; 149d80f8206SUwe Kleine-König 150d80f8206SUwe Kleine-König /* PWMOUT (Hz) = PWMCLK / (PWMPR + 2) */ 151d80f8206SUwe Kleine-König tmp = NSEC_PER_SEC * (u64)(period + 2); 152d80f8206SUwe Kleine-König state->period = DIV_ROUND_CLOSEST_ULL(tmp, pwm_clk); 153d80f8206SUwe Kleine-König 154d80f8206SUwe Kleine-König /* PWMSAR can be read only if PWM is enabled */ 155d80f8206SUwe Kleine-König if (state->enabled) { 156d80f8206SUwe Kleine-König val = readl(imx->mmio_base + MX3_PWMSAR); 157d80f8206SUwe Kleine-König tmp = NSEC_PER_SEC * (u64)(val); 158d80f8206SUwe Kleine-König state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, pwm_clk); 159d80f8206SUwe Kleine-König } else { 160d80f8206SUwe Kleine-König state->duty_cycle = 0; 161d80f8206SUwe Kleine-König } 162d80f8206SUwe Kleine-König 163519ef9b5SUwe Kleine-König if (!state->enabled) 164d80f8206SUwe Kleine-König pwm_imx27_clk_disable_unprepare(chip); 165d80f8206SUwe Kleine-König } 166d80f8206SUwe Kleine-König 167d80f8206SUwe Kleine-König static void pwm_imx27_sw_reset(struct pwm_chip *chip) 168d80f8206SUwe Kleine-König { 169d80f8206SUwe Kleine-König struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip); 170d80f8206SUwe Kleine-König struct device *dev = chip->dev; 171d80f8206SUwe Kleine-König int wait_count = 0; 172d80f8206SUwe Kleine-König u32 cr; 173d80f8206SUwe Kleine-König 174d80f8206SUwe Kleine-König writel(MX3_PWMCR_SWR, imx->mmio_base + MX3_PWMCR); 175d80f8206SUwe Kleine-König do { 176d80f8206SUwe Kleine-König usleep_range(200, 1000); 177d80f8206SUwe Kleine-König cr = readl(imx->mmio_base + MX3_PWMCR); 178d80f8206SUwe Kleine-König } while ((cr & MX3_PWMCR_SWR) && 179d80f8206SUwe Kleine-König (wait_count++ < MX3_PWM_SWR_LOOP)); 180d80f8206SUwe Kleine-König 181d80f8206SUwe Kleine-König if (cr & MX3_PWMCR_SWR) 182d80f8206SUwe Kleine-König dev_warn(dev, "software reset timeout\n"); 183d80f8206SUwe Kleine-König } 184d80f8206SUwe Kleine-König 185d80f8206SUwe Kleine-König static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip, 186d80f8206SUwe Kleine-König struct pwm_device *pwm) 187d80f8206SUwe Kleine-König { 188d80f8206SUwe Kleine-König struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip); 189d80f8206SUwe Kleine-König struct device *dev = chip->dev; 190d80f8206SUwe Kleine-König unsigned int period_ms; 191d80f8206SUwe Kleine-König int fifoav; 192d80f8206SUwe Kleine-König u32 sr; 193d80f8206SUwe Kleine-König 194d80f8206SUwe Kleine-König sr = readl(imx->mmio_base + MX3_PWMSR); 195d80f8206SUwe Kleine-König fifoav = FIELD_GET(MX3_PWMSR_FIFOAV, sr); 196d80f8206SUwe Kleine-König if (fifoav == MX3_PWMSR_FIFOAV_4WORDS) { 197d80f8206SUwe Kleine-König period_ms = DIV_ROUND_UP(pwm_get_period(pwm), 198d80f8206SUwe Kleine-König NSEC_PER_MSEC); 199d80f8206SUwe Kleine-König msleep(period_ms); 200d80f8206SUwe Kleine-König 201d80f8206SUwe Kleine-König sr = readl(imx->mmio_base + MX3_PWMSR); 202d80f8206SUwe Kleine-König if (fifoav == FIELD_GET(MX3_PWMSR_FIFOAV, sr)) 203d80f8206SUwe Kleine-König dev_warn(dev, "there is no free FIFO slot\n"); 204d80f8206SUwe Kleine-König } 205d80f8206SUwe Kleine-König } 206d80f8206SUwe Kleine-König 207d80f8206SUwe Kleine-König static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm, 208d80f8206SUwe Kleine-König struct pwm_state *state) 209d80f8206SUwe Kleine-König { 210d80f8206SUwe Kleine-König unsigned long period_cycles, duty_cycles, prescale; 211d80f8206SUwe Kleine-König struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip); 212d80f8206SUwe Kleine-König struct pwm_state cstate; 213d80f8206SUwe Kleine-König unsigned long long c; 214d80f8206SUwe Kleine-König int ret; 215d80f8206SUwe Kleine-König u32 cr; 216d80f8206SUwe Kleine-König 217d80f8206SUwe Kleine-König pwm_get_state(pwm, &cstate); 218d80f8206SUwe Kleine-König 219d80f8206SUwe Kleine-König if (state->enabled) { 220d80f8206SUwe Kleine-König c = clk_get_rate(imx->clk_per); 221d80f8206SUwe Kleine-König c *= state->period; 222d80f8206SUwe Kleine-König 223d80f8206SUwe Kleine-König do_div(c, 1000000000); 224d80f8206SUwe Kleine-König period_cycles = c; 225d80f8206SUwe Kleine-König 226d80f8206SUwe Kleine-König prescale = period_cycles / 0x10000 + 1; 227d80f8206SUwe Kleine-König 228d80f8206SUwe Kleine-König period_cycles /= prescale; 229d80f8206SUwe Kleine-König c = (unsigned long long)period_cycles * state->duty_cycle; 230d80f8206SUwe Kleine-König do_div(c, state->period); 231d80f8206SUwe Kleine-König duty_cycles = c; 232d80f8206SUwe Kleine-König 233d80f8206SUwe Kleine-König /* 234d80f8206SUwe Kleine-König * according to imx pwm RM, the real period value should be 235d80f8206SUwe Kleine-König * PERIOD value in PWMPR plus 2. 236d80f8206SUwe Kleine-König */ 237d80f8206SUwe Kleine-König if (period_cycles > 2) 238d80f8206SUwe Kleine-König period_cycles -= 2; 239d80f8206SUwe Kleine-König else 240d80f8206SUwe Kleine-König period_cycles = 0; 241d80f8206SUwe Kleine-König 242d80f8206SUwe Kleine-König /* 243d80f8206SUwe Kleine-König * Wait for a free FIFO slot if the PWM is already enabled, and 244d80f8206SUwe Kleine-König * flush the FIFO if the PWM was disabled and is about to be 245d80f8206SUwe Kleine-König * enabled. 246d80f8206SUwe Kleine-König */ 247d80f8206SUwe Kleine-König if (cstate.enabled) { 248d80f8206SUwe Kleine-König pwm_imx27_wait_fifo_slot(chip, pwm); 249d80f8206SUwe Kleine-König } else { 250d80f8206SUwe Kleine-König ret = pwm_imx27_clk_prepare_enable(chip); 251d80f8206SUwe Kleine-König if (ret) 252d80f8206SUwe Kleine-König return ret; 253d80f8206SUwe Kleine-König 254d80f8206SUwe Kleine-König pwm_imx27_sw_reset(chip); 255d80f8206SUwe Kleine-König } 256d80f8206SUwe Kleine-König 257d80f8206SUwe Kleine-König writel(duty_cycles, imx->mmio_base + MX3_PWMSAR); 258d80f8206SUwe Kleine-König writel(period_cycles, imx->mmio_base + MX3_PWMPR); 259d80f8206SUwe Kleine-König 260d80f8206SUwe Kleine-König cr = MX3_PWMCR_PRESCALER_SET(prescale) | 261d80f8206SUwe Kleine-König MX3_PWMCR_STOPEN | MX3_PWMCR_DOZEN | MX3_PWMCR_WAITEN | 262d80f8206SUwe Kleine-König FIELD_PREP(MX3_PWMCR_CLKSRC, MX3_PWMCR_CLKSRC_IPG_HIGH) | 263d80f8206SUwe Kleine-König MX3_PWMCR_DBGEN | MX3_PWMCR_EN; 264d80f8206SUwe Kleine-König 265d80f8206SUwe Kleine-König if (state->polarity == PWM_POLARITY_INVERSED) 266d80f8206SUwe Kleine-König cr |= FIELD_PREP(MX3_PWMCR_POUTC, 267d80f8206SUwe Kleine-König MX3_PWMCR_POUTC_INVERTED); 268d80f8206SUwe Kleine-König 269d80f8206SUwe Kleine-König writel(cr, imx->mmio_base + MX3_PWMCR); 270d80f8206SUwe Kleine-König } else if (cstate.enabled) { 271d80f8206SUwe Kleine-König writel(0, imx->mmio_base + MX3_PWMCR); 272d80f8206SUwe Kleine-König 273d80f8206SUwe Kleine-König pwm_imx27_clk_disable_unprepare(chip); 274d80f8206SUwe Kleine-König } 275d80f8206SUwe Kleine-König 276d80f8206SUwe Kleine-König return 0; 277d80f8206SUwe Kleine-König } 278d80f8206SUwe Kleine-König 279d80f8206SUwe Kleine-König static const struct pwm_ops pwm_imx27_ops = { 280d80f8206SUwe Kleine-König .apply = pwm_imx27_apply, 281d80f8206SUwe Kleine-König .get_state = pwm_imx27_get_state, 282d80f8206SUwe Kleine-König .owner = THIS_MODULE, 283d80f8206SUwe Kleine-König }; 284d80f8206SUwe Kleine-König 285d80f8206SUwe Kleine-König static const struct of_device_id pwm_imx27_dt_ids[] = { 286d80f8206SUwe Kleine-König { .compatible = "fsl,imx27-pwm", }, 287d80f8206SUwe Kleine-König { /* sentinel */ } 288d80f8206SUwe Kleine-König }; 289d80f8206SUwe Kleine-König MODULE_DEVICE_TABLE(of, pwm_imx27_dt_ids); 290d80f8206SUwe Kleine-König 291d80f8206SUwe Kleine-König static int pwm_imx27_probe(struct platform_device *pdev) 292d80f8206SUwe Kleine-König { 293d80f8206SUwe Kleine-König struct pwm_imx27_chip *imx; 294d80f8206SUwe Kleine-König struct resource *r; 295d80f8206SUwe Kleine-König 296d80f8206SUwe Kleine-König imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL); 297d80f8206SUwe Kleine-König if (imx == NULL) 298d80f8206SUwe Kleine-König return -ENOMEM; 299d80f8206SUwe Kleine-König 300d80f8206SUwe Kleine-König platform_set_drvdata(pdev, imx); 301d80f8206SUwe Kleine-König 302d80f8206SUwe Kleine-König imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); 303d80f8206SUwe Kleine-König if (IS_ERR(imx->clk_ipg)) { 304d80f8206SUwe Kleine-König dev_err(&pdev->dev, "getting ipg clock failed with %ld\n", 305d80f8206SUwe Kleine-König PTR_ERR(imx->clk_ipg)); 306d80f8206SUwe Kleine-König return PTR_ERR(imx->clk_ipg); 307d80f8206SUwe Kleine-König } 308d80f8206SUwe Kleine-König 309d80f8206SUwe Kleine-König imx->clk_per = devm_clk_get(&pdev->dev, "per"); 310d80f8206SUwe Kleine-König if (IS_ERR(imx->clk_per)) { 311d80f8206SUwe Kleine-König int ret = PTR_ERR(imx->clk_per); 312d80f8206SUwe Kleine-König 313d80f8206SUwe Kleine-König if (ret != -EPROBE_DEFER) 314d80f8206SUwe Kleine-König dev_err(&pdev->dev, 315d80f8206SUwe Kleine-König "failed to get peripheral clock: %d\n", 316d80f8206SUwe Kleine-König ret); 317d80f8206SUwe Kleine-König 318d80f8206SUwe Kleine-König return ret; 319d80f8206SUwe Kleine-König } 320d80f8206SUwe Kleine-König 321d80f8206SUwe Kleine-König imx->chip.ops = &pwm_imx27_ops; 322d80f8206SUwe Kleine-König imx->chip.dev = &pdev->dev; 323d80f8206SUwe Kleine-König imx->chip.base = -1; 324d80f8206SUwe Kleine-König imx->chip.npwm = 1; 325d80f8206SUwe Kleine-König 326d80f8206SUwe Kleine-König imx->chip.of_xlate = of_pwm_xlate_with_flags; 327d80f8206SUwe Kleine-König imx->chip.of_pwm_n_cells = 3; 328d80f8206SUwe Kleine-König 329d80f8206SUwe Kleine-König r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 330d80f8206SUwe Kleine-König imx->mmio_base = devm_ioremap_resource(&pdev->dev, r); 331d80f8206SUwe Kleine-König if (IS_ERR(imx->mmio_base)) 332d80f8206SUwe Kleine-König return PTR_ERR(imx->mmio_base); 333d80f8206SUwe Kleine-König 334d80f8206SUwe Kleine-König return pwmchip_add(&imx->chip); 335d80f8206SUwe Kleine-König } 336d80f8206SUwe Kleine-König 337d80f8206SUwe Kleine-König static int pwm_imx27_remove(struct platform_device *pdev) 338d80f8206SUwe Kleine-König { 339d80f8206SUwe Kleine-König struct pwm_imx27_chip *imx; 340d80f8206SUwe Kleine-König 341d80f8206SUwe Kleine-König imx = platform_get_drvdata(pdev); 342d80f8206SUwe Kleine-König 343d80f8206SUwe Kleine-König pwm_imx27_clk_disable_unprepare(&imx->chip); 344d80f8206SUwe Kleine-König 345d80f8206SUwe Kleine-König return pwmchip_remove(&imx->chip); 346d80f8206SUwe Kleine-König } 347d80f8206SUwe Kleine-König 348d80f8206SUwe Kleine-König static struct platform_driver imx_pwm_driver = { 349d80f8206SUwe Kleine-König .driver = { 350d80f8206SUwe Kleine-König .name = "pwm-imx27", 351d80f8206SUwe Kleine-König .of_match_table = pwm_imx27_dt_ids, 352d80f8206SUwe Kleine-König }, 353d80f8206SUwe Kleine-König .probe = pwm_imx27_probe, 354d80f8206SUwe Kleine-König .remove = pwm_imx27_remove, 355d80f8206SUwe Kleine-König }; 356d80f8206SUwe Kleine-König module_platform_driver(imx_pwm_driver); 357d80f8206SUwe Kleine-König 358d80f8206SUwe Kleine-König MODULE_LICENSE("GPL v2"); 359d80f8206SUwe Kleine-König MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); 360