VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   33 Branches   57 Tags
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200   1) /*
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200   2)  * Marvell Berlin PWM driver
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200   3)  *
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200   4)  * Copyright (C) 2015 Marvell Technology Group Ltd.
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200   5)  *
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200   6)  * Author: Antoine Tenart <antoine.tenart@free-electrons.com>
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200   7)  *
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200   8)  * This file is licensed under the terms of the GNU General Public
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200   9)  * License version 2. This program is licensed "as is" without any
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  10)  * warranty of any kind, whether express or implied.
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  11)  */
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  12) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  13) #include <linux/clk.h>
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  14) #include <linux/io.h>
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  15) #include <linux/kernel.h>
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  16) #include <linux/module.h>
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  17) #include <linux/platform_device.h>
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  18) #include <linux/pwm.h>
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  19) #include <linux/slab.h>
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  20) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  21) #define BERLIN_PWM_EN			0x0
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  22) #define  BERLIN_PWM_ENABLE		BIT(0)
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  23) #define BERLIN_PWM_CONTROL		0x4
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400  24) /*
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400  25)  * The prescaler claims to support 8 different moduli, configured using the
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400  26)  * low three bits of PWM_CONTROL. (Sequentially, they are 1, 4, 8, 16, 64,
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400  27)  * 256, 1024, and 4096.)  However, the moduli from 4 to 1024 appear to be
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400  28)  * implemented by internally shifting TCNT left without adding additional
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400  29)  * bits. So, the max TCNT that actually works for a modulus of 4 is 0x3fff;
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400  30)  * for 8, 0x1fff; and so on. This means that those moduli are entirely
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400  31)  * useless, as we could just do the shift ourselves. The 4096 modulus is
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400  32)  * implemented with a real prescaler, so we do use that, but we treat it
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400  33)  * as a flag instead of pretending the modulus is actually configurable.
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400  34)  */
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400  35) #define  BERLIN_PWM_PRESCALE_4096	0x7
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  36) #define  BERLIN_PWM_INVERT_POLARITY	BIT(3)
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  37) #define BERLIN_PWM_DUTY			0x8
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  38) #define BERLIN_PWM_TCNT			0xc
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  39) #define  BERLIN_PWM_MAX_TCNT		65535
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  40) 
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  41) struct berlin_pwm_channel {
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  42) 	u32 enable;
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  43) 	u32 ctrl;
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  44) 	u32 duty;
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  45) 	u32 tcnt;
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  46) };
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  47) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  48) struct berlin_pwm_chip {
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  49) 	struct pwm_chip chip;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  50) 	struct clk *clk;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  51) 	void __iomem *base;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  52) };
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  53) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  54) static inline struct berlin_pwm_chip *to_berlin_pwm_chip(struct pwm_chip *chip)
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  55) {
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  56) 	return container_of(chip, struct berlin_pwm_chip, chip);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  57) }
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  58) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  59) static inline u32 berlin_pwm_readl(struct berlin_pwm_chip *chip,
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  60) 				   unsigned int channel, unsigned long offset)
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  61) {
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  62) 	return readl_relaxed(chip->base + channel * 0x10 + offset);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  63) }
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  64) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  65) static inline void berlin_pwm_writel(struct berlin_pwm_chip *chip,
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  66) 				     unsigned int channel, u32 value,
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  67) 				     unsigned long offset)
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  68) {
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  69) 	writel_relaxed(value, chip->base + channel * 0x10 + offset);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  70) }
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  71) 
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  72) static int berlin_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  73) {
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  74) 	struct berlin_pwm_channel *channel;
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  75) 
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  76) 	channel = kzalloc(sizeof(*channel), GFP_KERNEL);
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  77) 	if (!channel)
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  78) 		return -ENOMEM;
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  79) 
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  80) 	return pwm_set_chip_data(pwm, channel);
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  81) }
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  82) 
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  83) static void berlin_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  84) {
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  85) 	struct berlin_pwm_channel *channel = pwm_get_chip_data(pwm);
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  86) 
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  87) 	kfree(channel);
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  88) }
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800  89) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  90) static int berlin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm_dev,
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  91) 			     int duty_ns, int period_ns)
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  92) {
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  93) 	struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip);
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400  94) 	bool prescale_4096 = false;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  95) 	u32 value, duty, period;
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400  96) 	u64 cycles;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  97) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  98) 	cycles = clk_get_rate(pwm->clk);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200  99) 	cycles *= period_ns;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 100) 	do_div(cycles, NSEC_PER_SEC);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 101) 
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400 102) 	if (cycles > BERLIN_PWM_MAX_TCNT) {
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400 103) 		prescale_4096 = true;
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400 104) 		cycles >>= 12; // Prescaled by 4096
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 105) 
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400 106) 		if (cycles > BERLIN_PWM_MAX_TCNT)
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400 107) 			return -ERANGE;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 108) 	}
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 109) 
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400 110) 	period = cycles;
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400 111) 	cycles *= duty_ns;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 112) 	do_div(cycles, period_ns);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 113) 	duty = cycles;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 114) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 115) 	value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL);
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400 116) 	if (prescale_4096)
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400 117) 		value |= BERLIN_PWM_PRESCALE_4096;
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400 118) 	else
4de445cb431eb (Thomas Hebb    2018-06-06 13:42:10 -0400 119) 		value &= ~BERLIN_PWM_PRESCALE_4096;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 120) 	berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_CONTROL);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 121) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 122) 	berlin_pwm_writel(pwm, pwm_dev->hwpwm, duty, BERLIN_PWM_DUTY);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 123) 	berlin_pwm_writel(pwm, pwm_dev->hwpwm, period, BERLIN_PWM_TCNT);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 124) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 125) 	return 0;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 126) }
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 127) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 128) static int berlin_pwm_set_polarity(struct pwm_chip *chip,
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 129) 				   struct pwm_device *pwm_dev,
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 130) 				   enum pwm_polarity polarity)
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 131) {
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 132) 	struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 133) 	u32 value;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 134) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 135) 	value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 136) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 137) 	if (polarity == PWM_POLARITY_NORMAL)
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 138) 		value &= ~BERLIN_PWM_INVERT_POLARITY;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 139) 	else
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 140) 		value |= BERLIN_PWM_INVERT_POLARITY;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 141) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 142) 	berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_CONTROL);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 143) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 144) 	return 0;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 145) }
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 146) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 147) static int berlin_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm_dev)
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 148) {
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 149) 	struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 150) 	u32 value;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 151) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 152) 	value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_EN);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 153) 	value |= BERLIN_PWM_ENABLE;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 154) 	berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_EN);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 155) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 156) 	return 0;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 157) }
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 158) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 159) static void berlin_pwm_disable(struct pwm_chip *chip,
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 160) 			       struct pwm_device *pwm_dev)
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 161) {
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 162) 	struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 163) 	u32 value;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 164) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 165) 	value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_EN);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 166) 	value &= ~BERLIN_PWM_ENABLE;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 167) 	berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_EN);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 168) }
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 169) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 170) static const struct pwm_ops berlin_pwm_ops = {
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 171) 	.request = berlin_pwm_request,
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 172) 	.free = berlin_pwm_free,
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 173) 	.config = berlin_pwm_config,
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 174) 	.set_polarity = berlin_pwm_set_polarity,
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 175) 	.enable = berlin_pwm_enable,
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 176) 	.disable = berlin_pwm_disable,
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 177) 	.owner = THIS_MODULE,
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 178) };
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 179) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 180) static const struct of_device_id berlin_pwm_match[] = {
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 181) 	{ .compatible = "marvell,berlin-pwm" },
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 182) 	{ },
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 183) };
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 184) MODULE_DEVICE_TABLE(of, berlin_pwm_match);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 185) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 186) static int berlin_pwm_probe(struct platform_device *pdev)
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 187) {
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 188) 	struct berlin_pwm_chip *pwm;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 189) 	int ret;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 190) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 191) 	pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 192) 	if (!pwm)
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 193) 		return -ENOMEM;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 194) 
05baa59601ee1 (Yangtao Li     2019-12-29 08:06:01 +0000 195) 	pwm->base = devm_platform_ioremap_resource(pdev, 0);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 196) 	if (IS_ERR(pwm->base))
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 197) 		return PTR_ERR(pwm->base);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 198) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 199) 	pwm->clk = devm_clk_get(&pdev->dev, NULL);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 200) 	if (IS_ERR(pwm->clk))
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 201) 		return PTR_ERR(pwm->clk);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 202) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 203) 	ret = clk_prepare_enable(pwm->clk);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 204) 	if (ret)
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 205) 		return ret;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 206) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 207) 	pwm->chip.dev = &pdev->dev;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 208) 	pwm->chip.ops = &berlin_pwm_ops;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 209) 	pwm->chip.npwm = 4;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 210) 	pwm->chip.of_xlate = of_pwm_xlate_with_flags;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 211) 	pwm->chip.of_pwm_n_cells = 3;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 212) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 213) 	ret = pwmchip_add(&pwm->chip);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 214) 	if (ret < 0) {
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 215) 		dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 216) 		clk_disable_unprepare(pwm->clk);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 217) 		return ret;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 218) 	}
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 219) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 220) 	platform_set_drvdata(pdev, pwm);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 221) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 222) 	return 0;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 223) }
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 224) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 225) static int berlin_pwm_remove(struct platform_device *pdev)
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 226) {
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 227) 	struct berlin_pwm_chip *pwm = platform_get_drvdata(pdev);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 228) 	int ret;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 229) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 230) 	ret = pwmchip_remove(&pwm->chip);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 231) 	clk_disable_unprepare(pwm->clk);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 232) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 233) 	return ret;
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 234) }
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 235) 
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 236) #ifdef CONFIG_PM_SLEEP
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 237) static int berlin_pwm_suspend(struct device *dev)
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 238) {
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 239) 	struct berlin_pwm_chip *pwm = dev_get_drvdata(dev);
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 240) 	unsigned int i;
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 241) 
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 242) 	for (i = 0; i < pwm->chip.npwm; i++) {
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 243) 		struct berlin_pwm_channel *channel;
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 244) 
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 245) 		channel = pwm_get_chip_data(&pwm->chip.pwms[i]);
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 246) 		if (!channel)
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 247) 			continue;
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 248) 
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 249) 		channel->enable = berlin_pwm_readl(pwm, i, BERLIN_PWM_ENABLE);
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 250) 		channel->ctrl = berlin_pwm_readl(pwm, i, BERLIN_PWM_CONTROL);
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 251) 		channel->duty = berlin_pwm_readl(pwm, i, BERLIN_PWM_DUTY);
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 252) 		channel->tcnt = berlin_pwm_readl(pwm, i, BERLIN_PWM_TCNT);
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 253) 	}
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 254) 
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 255) 	clk_disable_unprepare(pwm->clk);
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 256) 
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 257) 	return 0;
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 258) }
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 259) 
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 260) static int berlin_pwm_resume(struct device *dev)
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 261) {
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 262) 	struct berlin_pwm_chip *pwm = dev_get_drvdata(dev);
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 263) 	unsigned int i;
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 264) 	int ret;
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 265) 
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 266) 	ret = clk_prepare_enable(pwm->clk);
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 267) 	if (ret)
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 268) 		return ret;
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 269) 
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 270) 	for (i = 0; i < pwm->chip.npwm; i++) {
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 271) 		struct berlin_pwm_channel *channel;
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 272) 
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 273) 		channel = pwm_get_chip_data(&pwm->chip.pwms[i]);
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 274) 		if (!channel)
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 275) 			continue;
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 276) 
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 277) 		berlin_pwm_writel(pwm, i, channel->ctrl, BERLIN_PWM_CONTROL);
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 278) 		berlin_pwm_writel(pwm, i, channel->duty, BERLIN_PWM_DUTY);
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 279) 		berlin_pwm_writel(pwm, i, channel->tcnt, BERLIN_PWM_TCNT);
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 280) 		berlin_pwm_writel(pwm, i, channel->enable, BERLIN_PWM_ENABLE);
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 281) 	}
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 282) 
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 283) 	return 0;
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 284) }
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 285) #endif
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 286) 
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 287) static SIMPLE_DEV_PM_OPS(berlin_pwm_pm_ops, berlin_pwm_suspend,
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 288) 			 berlin_pwm_resume);
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 289) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 290) static struct platform_driver berlin_pwm_driver = {
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 291) 	.probe = berlin_pwm_probe,
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 292) 	.remove = berlin_pwm_remove,
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 293) 	.driver = {
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 294) 		.name = "berlin-pwm",
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 295) 		.of_match_table = berlin_pwm_match,
bbf0722c1c663 (Jisheng Zhang  2015-11-25 17:41:25 +0800 296) 		.pm = &berlin_pwm_pm_ops,
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 297) 	},
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 298) };
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 299) module_platform_driver(berlin_pwm_driver);
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 300) 
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 301) MODULE_AUTHOR("Antoine Tenart <antoine.tenart@free-electrons.com>");
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 302) MODULE_DESCRIPTION("Marvell Berlin PWM driver");
59d5c8b1537da (Antoine Tenart 2015-10-02 16:59:47 +0200 303) MODULE_LICENSE("GPL v2");