#include <linux/math64.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#define RCAR_PWM_MAX_DIVISION 24
#define RCAR_PWM_MAX_CYCLE 1023
#define RCAR_PWMCR_CC0_MASK 0x000f0000
#define RCAR_PWMCR_CC0_SHIFT 16
#define RCAR_PWMCR_CCMD BIT(15)
#define RCAR_PWMCR_SYNC BIT(11)
#define RCAR_PWMCR_SS0 BIT(4)
#define RCAR_PWMCR_EN0 BIT(0)
#define RCAR_PWMCNT_CYC0_MASK 0x03ff0000
#define RCAR_PWMCNT_CYC0_SHIFT 16
#define RCAR_PWMCNT_PH0_MASK 0x000003ff
#define RCAR_PWMCNT_PH0_SHIFT 0
static inline struct rcar_pwm_chip *to_rcar_pwm_chip(struct pwm_chip *chip)
return container_of(chip, struct rcar_pwm_chip, chip);
static void rcar_pwm_write(struct rcar_pwm_chip *rp, u32 data,
writel(data, rp->base + offset);
static u32 rcar_pwm_read(struct rcar_pwm_chip *rp, unsigned int offset)
return readl(rp->base + offset);
static void rcar_pwm_update(struct rcar_pwm_chip *rp, u32 mask, u32 data,
value = rcar_pwm_read(rp, offset);
rcar_pwm_write(rp, value, offset);
static int rcar_pwm_get_clock_division(struct rcar_pwm_chip *rp, int period_ns)
unsigned long clk_rate = clk_get_rate(rp->clk);
div = (u64)NSEC_PER_SEC * RCAR_PWM_MAX_CYCLE;
tmp = (u64)period_ns * clk_rate + div - 1;
tmp = div64_u64(tmp, div);
div = ilog2(tmp - 1) + 1;
return (div <= RCAR_PWM_MAX_DIVISION) ? div : -ERANGE;
static void rcar_pwm_set_clock_control(struct rcar_pwm_chip *rp,
value = rcar_pwm_read(rp, RCAR_PWMCR);
value &= ~(RCAR_PWMCR_CCMD | RCAR_PWMCR_CC0_MASK);