199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart/* 299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * R-Mobile TPU PWM driver 399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * 499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * Copyright (C) 2012 Renesas Solutions Corp. 599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * 699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * This program is free software; you can redistribute it and/or modify 799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * it under the terms of the GNU General Public License as published by 899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * the Free Software Foundation; either version 2 of the License 999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * 1099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * This program is distributed in the hope that it will be useful, 1199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * but WITHOUT ANY WARRANTY; without even the implied warranty of 1299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * GNU General Public License for more details. 1499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart */ 1599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 1699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#include <linux/clk.h> 1799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#include <linux/err.h> 1899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#include <linux/io.h> 1999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#include <linux/init.h> 2099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#include <linux/ioport.h> 2199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#include <linux/module.h> 2299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#include <linux/mutex.h> 23382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent Pinchart#include <linux/of.h> 2499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#include <linux/platform_device.h> 2599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#include <linux/pm_runtime.h> 2699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#include <linux/pwm.h> 2799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#include <linux/slab.h> 2899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#include <linux/spinlock.h> 2999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 30dc671157139918eaf61f73db1bd6dd02960b66e2Alexandre Belloni#define TPU_CHANNEL_MAX 4 31dc671157139918eaf61f73db1bd6dd02960b66e2Alexandre Belloni 3299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TSTR 0x00 /* Timer start register (shared) */ 3399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 3499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TCRn 0x00 /* Timer control register */ 3599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TCR_CCLR_NONE (0 << 5) 3699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TCR_CCLR_TGRA (1 << 5) 3799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TCR_CCLR_TGRB (2 << 5) 3899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TCR_CCLR_TGRC (5 << 5) 3999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TCR_CCLR_TGRD (6 << 5) 4099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TCR_CKEG_RISING (0 << 3) 4199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TCR_CKEG_FALLING (1 << 3) 4299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TCR_CKEG_BOTH (2 << 3) 4399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TMDRn 0x04 /* Timer mode register */ 4499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TMDR_BFWT (1 << 6) 4599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TMDR_BFB (1 << 5) 4699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TMDR_BFA (1 << 4) 4799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TMDR_MD_NORMAL (0 << 0) 4899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TMDR_MD_PWM (2 << 0) 4999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TIORn 0x08 /* Timer I/O control register */ 5099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TIOR_IOA_0 (0 << 0) 5199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TIOR_IOA_0_CLR (1 << 0) 5299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TIOR_IOA_0_SET (2 << 0) 5399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TIOR_IOA_0_TOGGLE (3 << 0) 5499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TIOR_IOA_1 (4 << 0) 5599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TIOR_IOA_1_CLR (5 << 0) 5699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TIOR_IOA_1_SET (6 << 0) 5799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TIOR_IOA_1_TOGGLE (7 << 0) 5899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TIERn 0x0c /* Timer interrupt enable register */ 5999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TSRn 0x10 /* Timer status register */ 6099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TCNTn 0x14 /* Timer counter */ 6199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TGRAn 0x18 /* Timer general register A */ 6299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TGRBn 0x1c /* Timer general register B */ 6399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TGRCn 0x20 /* Timer general register C */ 6499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_TGRDn 0x24 /* Timer general register D */ 6599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 6699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_CHANNEL_OFFSET 0x10 6799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define TPU_CHANNEL_SIZE 0x40 6899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 6999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartenum tpu_pin_state { 7099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart TPU_PIN_INACTIVE, /* Pin is driven inactive */ 7199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart TPU_PIN_PWM, /* Pin is driven by PWM */ 7299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart TPU_PIN_ACTIVE, /* Pin is driven active */ 7399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart}; 7499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 7599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartstruct tpu_device; 7699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 7799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartstruct tpu_pwm_device { 7899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart bool timer_on; /* Whether the timer is running */ 7999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 8099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart struct tpu_device *tpu; 8199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart unsigned int channel; /* Channel number in the TPU */ 8299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 8399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart enum pwm_polarity polarity; 8499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart unsigned int prescaler; 8599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart u16 period; 8699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart u16 duty; 8799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart}; 8899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 8999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartstruct tpu_device { 9099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart struct platform_device *pdev; 9199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart struct pwm_chip chip; 9299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart spinlock_t lock; 9399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 9499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart void __iomem *base; 9599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart struct clk *clk; 9699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart}; 9799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 9899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart#define to_tpu_device(c) container_of(c, struct tpu_device, chip) 9999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 10099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartstatic void tpu_pwm_write(struct tpu_pwm_device *pwm, int reg_nr, u16 value) 10199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart{ 10299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart void __iomem *base = pwm->tpu->base + TPU_CHANNEL_OFFSET 10399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart + pwm->channel * TPU_CHANNEL_SIZE; 10499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 10599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart iowrite16(value, base + reg_nr); 10699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart} 10799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 10899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartstatic void tpu_pwm_set_pin(struct tpu_pwm_device *pwm, 10999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart enum tpu_pin_state state) 11099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart{ 11199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart static const char * const states[] = { "inactive", "PWM", "active" }; 11299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 11399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart dev_dbg(&pwm->tpu->pdev->dev, "%u: configuring pin as %s\n", 11499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm->channel, states[state]); 11599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 11699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart switch (state) { 11799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart case TPU_PIN_INACTIVE: 11899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_write(pwm, TPU_TIORn, 11999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm->polarity == PWM_POLARITY_INVERSED ? 12099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart TPU_TIOR_IOA_1 : TPU_TIOR_IOA_0); 12199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart break; 12299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart case TPU_PIN_PWM: 12399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_write(pwm, TPU_TIORn, 12499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm->polarity == PWM_POLARITY_INVERSED ? 12599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart TPU_TIOR_IOA_0_SET : TPU_TIOR_IOA_1_CLR); 12699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart break; 12799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart case TPU_PIN_ACTIVE: 12899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_write(pwm, TPU_TIORn, 12999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm->polarity == PWM_POLARITY_INVERSED ? 13099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart TPU_TIOR_IOA_0 : TPU_TIOR_IOA_1); 13199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart break; 13299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart } 13399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart} 13499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 13599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartstatic void tpu_pwm_start_stop(struct tpu_pwm_device *pwm, int start) 13699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart{ 13799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart unsigned long flags; 13899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart u16 value; 13999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 14099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart spin_lock_irqsave(&pwm->tpu->lock, flags); 14199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart value = ioread16(pwm->tpu->base + TPU_TSTR); 14299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 14399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (start) 14499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart value |= 1 << pwm->channel; 14599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart else 14699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart value &= ~(1 << pwm->channel); 14799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 14899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart iowrite16(value, pwm->tpu->base + TPU_TSTR); 14999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart spin_unlock_irqrestore(&pwm->tpu->lock, flags); 15099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart} 15199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 15299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartstatic int tpu_pwm_timer_start(struct tpu_pwm_device *pwm) 15399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart{ 15499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart int ret; 15599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 15699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (!pwm->timer_on) { 15799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart /* Wake up device and enable clock. */ 15899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pm_runtime_get_sync(&pwm->tpu->pdev->dev); 15999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart ret = clk_prepare_enable(pwm->tpu->clk); 16099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (ret) { 16199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart dev_err(&pwm->tpu->pdev->dev, "cannot enable clock\n"); 16299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return ret; 16399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart } 16499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm->timer_on = true; 16599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart } 16699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 16799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart /* 16899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * Make sure the channel is stopped, as we need to reconfigure it 16999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * completely. First drive the pin to the inactive state to avoid 17099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * glitches. 17199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart */ 17299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_set_pin(pwm, TPU_PIN_INACTIVE); 17399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_start_stop(pwm, false); 17499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 17599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart /* 17699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * - Clear TCNT on TGRB match 17799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * - Count on rising edge 17899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * - Set prescaler 17999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * - Output 0 until TGRA, output 1 until TGRB (active low polarity) 18099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * - Output 1 until TGRA, output 0 until TGRB (active high polarity 18199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * - PWM mode 18299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart */ 18399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_write(pwm, TPU_TCRn, TPU_TCR_CCLR_TGRB | TPU_TCR_CKEG_RISING | 18499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm->prescaler); 18599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_write(pwm, TPU_TMDRn, TPU_TMDR_MD_PWM); 18699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_set_pin(pwm, TPU_PIN_PWM); 18799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_write(pwm, TPU_TGRAn, pwm->duty); 18899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_write(pwm, TPU_TGRBn, pwm->period); 18999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 19099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart dev_dbg(&pwm->tpu->pdev->dev, "%u: TGRA 0x%04x TGRB 0x%04x\n", 19199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm->channel, pwm->duty, pwm->period); 19299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 19399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart /* Start the channel. */ 19499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_start_stop(pwm, true); 19599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 19699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return 0; 19799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart} 19899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 19999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartstatic void tpu_pwm_timer_stop(struct tpu_pwm_device *pwm) 20099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart{ 20199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (!pwm->timer_on) 20299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return; 20399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 20499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart /* Disable channel. */ 20599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_start_stop(pwm, false); 20699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 20799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart /* Stop clock and mark device as idle. */ 20899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart clk_disable_unprepare(pwm->tpu->clk); 20999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pm_runtime_put(&pwm->tpu->pdev->dev); 21099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 21199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm->timer_on = false; 21299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart} 21399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 21499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart/* ----------------------------------------------------------------------------- 21599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * PWM API 21699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart */ 21799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 21899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartstatic int tpu_pwm_request(struct pwm_chip *chip, struct pwm_device *_pwm) 21999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart{ 22099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart struct tpu_device *tpu = to_tpu_device(chip); 22199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart struct tpu_pwm_device *pwm; 22299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 22399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (_pwm->hwpwm >= TPU_CHANNEL_MAX) 22499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return -EINVAL; 22599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 22699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm = kzalloc(sizeof(*pwm), GFP_KERNEL); 22799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (pwm == NULL) 22899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return -ENOMEM; 22999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 23099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm->tpu = tpu; 23199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm->channel = _pwm->hwpwm; 232dc671157139918eaf61f73db1bd6dd02960b66e2Alexandre Belloni pwm->polarity = PWM_POLARITY_NORMAL; 23399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm->prescaler = 0; 23499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm->period = 0; 23599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm->duty = 0; 23699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 23799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm->timer_on = false; 23899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 23999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm_set_chip_data(_pwm, pwm); 24099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 24199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return 0; 24299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart} 24399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 24499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartstatic void tpu_pwm_free(struct pwm_chip *chip, struct pwm_device *_pwm) 24599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart{ 24699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart struct tpu_pwm_device *pwm = pwm_get_chip_data(_pwm); 24799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 24899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_timer_stop(pwm); 24999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart kfree(pwm); 25099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart} 25199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 25299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartstatic int tpu_pwm_config(struct pwm_chip *chip, struct pwm_device *_pwm, 25399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart int duty_ns, int period_ns) 25499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart{ 25599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart static const unsigned int prescalers[] = { 1, 4, 16, 64 }; 25699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart struct tpu_pwm_device *pwm = pwm_get_chip_data(_pwm); 25799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart struct tpu_device *tpu = to_tpu_device(chip); 25899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart unsigned int prescaler; 25999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart bool duty_only = false; 26099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart u32 clk_rate; 26199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart u32 period; 26299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart u32 duty; 26399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart int ret; 26499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 26599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart /* 26699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * Pick a prescaler to avoid overflowing the counter. 26799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * TODO: Pick the highest acceptable prescaler. 26899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart */ 26999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart clk_rate = clk_get_rate(tpu->clk); 27099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 27199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart for (prescaler = 0; prescaler < ARRAY_SIZE(prescalers); ++prescaler) { 27299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart period = clk_rate / prescalers[prescaler] 27399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart / (NSEC_PER_SEC / period_ns); 27499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (period <= 0xffff) 27599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart break; 27699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart } 27799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 27899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (prescaler == ARRAY_SIZE(prescalers) || period == 0) { 27999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart dev_err(&tpu->pdev->dev, "clock rate mismatch\n"); 28099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return -ENOTSUPP; 28199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart } 28299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 28399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (duty_ns) { 28499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart duty = clk_rate / prescalers[prescaler] 28599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart / (NSEC_PER_SEC / duty_ns); 28699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (duty > period) 28799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return -EINVAL; 28899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart } else { 28999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart duty = 0; 29099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart } 29199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 29299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart dev_dbg(&tpu->pdev->dev, 29399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart "rate %u, prescaler %u, period %u, duty %u\n", 29499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart clk_rate, prescalers[prescaler], period, duty); 29599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 29699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (pwm->prescaler == prescaler && pwm->period == period) 29799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart duty_only = true; 29899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 29999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm->prescaler = prescaler; 30099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm->period = period; 30199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm->duty = duty; 30299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 30399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart /* If the channel is disabled we're done. */ 30499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (!test_bit(PWMF_ENABLED, &_pwm->flags)) 30599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return 0; 30699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 30799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (duty_only && pwm->timer_on) { 30899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart /* 30999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * If only the duty cycle changed and the timer is already 31099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * running, there's no need to reconfigure it completely, Just 31199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * modify the duty cycle. 31299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart */ 31399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_write(pwm, TPU_TGRAn, pwm->duty); 31499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart dev_dbg(&tpu->pdev->dev, "%u: TGRA 0x%04x\n", pwm->channel, 31599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm->duty); 31699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart } else { 31799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart /* Otherwise perform a full reconfiguration. */ 31899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart ret = tpu_pwm_timer_start(pwm); 31999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (ret < 0) 32099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return ret; 32199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart } 32299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 32399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (duty == 0 || duty == period) { 32499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart /* 32599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * To avoid running the timer when not strictly required, handle 32699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * 0% and 100% duty cycles as fixed levels and stop the timer. 32799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart */ 32899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_set_pin(pwm, duty ? TPU_PIN_ACTIVE : TPU_PIN_INACTIVE); 32999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_timer_stop(pwm); 33099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart } 33199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 33299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return 0; 33399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart} 33499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 33599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartstatic int tpu_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *_pwm, 33699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart enum pwm_polarity polarity) 33799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart{ 33899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart struct tpu_pwm_device *pwm = pwm_get_chip_data(_pwm); 33999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 34099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pwm->polarity = polarity; 34199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 34299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return 0; 34399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart} 34499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 34599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartstatic int tpu_pwm_enable(struct pwm_chip *chip, struct pwm_device *_pwm) 34699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart{ 34799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart struct tpu_pwm_device *pwm = pwm_get_chip_data(_pwm); 34899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart int ret; 34999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 35099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart ret = tpu_pwm_timer_start(pwm); 35199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (ret < 0) 35299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return ret; 35399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 35499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart /* 35599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * To avoid running the timer when not strictly required, handle 0% and 35699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * 100% duty cycles as fixed levels and stop the timer. 35799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart */ 35899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (pwm->duty == 0 || pwm->duty == pwm->period) { 35999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_set_pin(pwm, pwm->duty ? 36099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart TPU_PIN_ACTIVE : TPU_PIN_INACTIVE); 36199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_timer_stop(pwm); 36299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart } 36399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 36499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return 0; 36599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart} 36699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 36799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartstatic void tpu_pwm_disable(struct pwm_chip *chip, struct pwm_device *_pwm) 36899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart{ 36999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart struct tpu_pwm_device *pwm = pwm_get_chip_data(_pwm); 37099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 37199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart /* The timer must be running to modify the pin output configuration. */ 37299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_timer_start(pwm); 37399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_set_pin(pwm, TPU_PIN_INACTIVE); 37499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu_pwm_timer_stop(pwm); 37599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart} 37699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 37799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartstatic const struct pwm_ops tpu_pwm_ops = { 37899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart .request = tpu_pwm_request, 37999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart .free = tpu_pwm_free, 38099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart .config = tpu_pwm_config, 38199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart .set_polarity = tpu_pwm_set_polarity, 38299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart .enable = tpu_pwm_enable, 38399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart .disable = tpu_pwm_disable, 38499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart .owner = THIS_MODULE, 38599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart}; 38699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 38799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart/* ----------------------------------------------------------------------------- 38899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart * Probe and remove 38999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart */ 39099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 39199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartstatic int tpu_probe(struct platform_device *pdev) 39299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart{ 39399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart struct tpu_device *tpu; 39499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart struct resource *res; 39599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart int ret; 39699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 39799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu = devm_kzalloc(&pdev->dev, sizeof(*tpu), GFP_KERNEL); 3986c5059ccce2b66c9ca73f9c826b8e26d883fcf32Jingoo Han if (tpu == NULL) 39999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return -ENOMEM; 40099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 401382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent Pinchart spin_lock_init(&tpu->lock); 402382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent Pinchart tpu->pdev = pdev; 403382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent Pinchart 40499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart /* Map memory, get clock and pin control. */ 40599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 40699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu->base = devm_ioremap_resource(&pdev->dev, res); 40700cf99ee00c9f1241359c8ee5ca9230318e27a57Wei Yongjun if (IS_ERR(tpu->base)) 40800cf99ee00c9f1241359c8ee5ca9230318e27a57Wei Yongjun return PTR_ERR(tpu->base); 40999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 41099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu->clk = devm_clk_get(&pdev->dev, NULL); 41199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (IS_ERR(tpu->clk)) { 41299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart dev_err(&pdev->dev, "cannot get clock\n"); 41399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return PTR_ERR(tpu->clk); 41499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart } 41599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 41699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart /* Initialize and register the device. */ 41799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart platform_set_drvdata(pdev, tpu); 41899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 41999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu->chip.dev = &pdev->dev; 42099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu->chip.ops = &tpu_pwm_ops; 421382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent Pinchart tpu->chip.of_xlate = of_pwm_xlate_with_flags; 422382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent Pinchart tpu->chip.of_pwm_n_cells = 3; 42399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu->chip.base = -1; 42499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart tpu->chip.npwm = TPU_CHANNEL_MAX; 42599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 42699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart ret = pwmchip_add(&tpu->chip); 42799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (ret < 0) { 42899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart dev_err(&pdev->dev, "failed to register PWM chip\n"); 42999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return ret; 43099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart } 43199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 43299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart dev_info(&pdev->dev, "TPU PWM %d registered\n", tpu->pdev->id); 43399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 43499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pm_runtime_enable(&pdev->dev); 43599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 43699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return 0; 43799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart} 43899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 43999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartstatic int tpu_remove(struct platform_device *pdev) 44099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart{ 44199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart struct tpu_device *tpu = platform_get_drvdata(pdev); 44299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart int ret; 44399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 44499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart ret = pwmchip_remove(&tpu->chip); 44599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart if (ret) 44699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return ret; 44799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 44899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart pm_runtime_disable(&pdev->dev); 44999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 45099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart return 0; 45199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart} 45299b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 453382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent Pinchart#ifdef CONFIG_OF 454382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent Pinchartstatic const struct of_device_id tpu_of_table[] = { 455382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent Pinchart { .compatible = "renesas,tpu-r8a73a4", }, 456382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent Pinchart { .compatible = "renesas,tpu-r8a7740", }, 457382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent Pinchart { .compatible = "renesas,tpu-r8a7790", }, 458382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent Pinchart { .compatible = "renesas,tpu-sh7372", }, 459382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent Pinchart { .compatible = "renesas,tpu", }, 460382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent Pinchart { }, 461382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent Pinchart}; 462382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent Pinchart 463382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent PinchartMODULE_DEVICE_TABLE(of, tpu_of_table); 464382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent Pinchart#endif 465382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent Pinchart 46699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartstatic struct platform_driver tpu_driver = { 46799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart .probe = tpu_probe, 46899b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart .remove = tpu_remove, 46999b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart .driver = { 47099b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart .name = "renesas-tpu-pwm", 47199b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart .owner = THIS_MODULE, 472382457e562bbb1ea7d94923e58fcbac9e981ff18Laurent Pinchart .of_match_table = of_match_ptr(tpu_of_table), 47399b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart } 47499b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart}; 47599b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 47699b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchartmodule_platform_driver(tpu_driver); 47799b82abb0a35b07310ea6334257829af168c8e08Laurent Pinchart 47899b82abb0a35b07310ea6334257829af168c8e08Laurent PinchartMODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); 47999b82abb0a35b07310ea6334257829af168c8e08Laurent PinchartMODULE_DESCRIPTION("Renesas TPU PWM Driver"); 48099b82abb0a35b07310ea6334257829af168c8e08Laurent PinchartMODULE_LICENSE("GPL v2"); 48171077bc8db67f560453d62c48e3bec467ec6b37fAxel LinMODULE_ALIAS("platform:renesas-tpu-pwm"); 482