Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pwm-tegra.c
Go to the documentation of this file.
1 /*
2  * drivers/pwm/pwm-tegra.c
3  *
4  * Tegra pulse-width-modulation controller driver
5  *
6  * Copyright (c) 2010, NVIDIA Corporation.
7  * Based on arch/arm/plat-mxc/pwm.c by Sascha Hauer <[email protected]>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17  * more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  */
23 
24 #include <linux/clk.h>
25 #include <linux/err.h>
26 #include <linux/io.h>
27 #include <linux/module.h>
28 #include <linux/of.h>
29 #include <linux/pwm.h>
30 #include <linux/platform_device.h>
31 #include <linux/slab.h>
32 
33 #define PWM_ENABLE (1 << 31)
34 #define PWM_DUTY_WIDTH 8
35 #define PWM_DUTY_SHIFT 16
36 #define PWM_SCALE_WIDTH 13
37 #define PWM_SCALE_SHIFT 0
38 
39 #define NUM_PWM 4
40 
42  struct pwm_chip chip;
43  struct device *dev;
44 
45  struct clk *clk;
46 
48 };
49 
50 static inline struct tegra_pwm_chip *to_tegra_pwm_chip(struct pwm_chip *chip)
51 {
52  return container_of(chip, struct tegra_pwm_chip, chip);
53 }
54 
55 static inline u32 pwm_readl(struct tegra_pwm_chip *chip, unsigned int num)
56 {
57  return readl(chip->mmio_base + (num << 4));
58 }
59 
60 static inline void pwm_writel(struct tegra_pwm_chip *chip, unsigned int num,
61  unsigned long val)
62 {
63  writel(val, chip->mmio_base + (num << 4));
64 }
65 
66 static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
67  int duty_ns, int period_ns)
68 {
69  struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
70  unsigned long long c;
71  unsigned long rate, hz;
72  u32 val = 0;
73  int err;
74 
75  /*
76  * Convert from duty_ns / period_ns to a fixed number of duty ticks
77  * per (1 << PWM_DUTY_WIDTH) cycles and make sure to round to the
78  * nearest integer during division.
79  */
80  c = duty_ns * ((1 << PWM_DUTY_WIDTH) - 1) + period_ns / 2;
81  do_div(c, period_ns);
82 
83  val = (u32)c << PWM_DUTY_SHIFT;
84 
85  /*
86  * Compute the prescaler value for which (1 << PWM_DUTY_WIDTH)
87  * cycles at the PWM clock rate will take period_ns nanoseconds.
88  */
90  hz = 1000000000ul / period_ns;
91 
92  rate = (rate + (hz / 2)) / hz;
93 
94  /*
95  * Since the actual PWM divider is the register's frequency divider
96  * field minus 1, we need to decrement to get the correct value to
97  * write to the register.
98  */
99  if (rate > 0)
100  rate--;
101 
102  /*
103  * Make sure that the rate will fit in the register's frequency
104  * divider field.
105  */
106  if (rate >> PWM_SCALE_WIDTH)
107  return -EINVAL;
108 
109  val |= rate << PWM_SCALE_SHIFT;
110 
111  /*
112  * If the PWM channel is disabled, make sure to turn on the clock
113  * before writing the register. Otherwise, keep it enabled.
114  */
115  if (!test_bit(PWMF_ENABLED, &pwm->flags)) {
116  err = clk_prepare_enable(pc->clk);
117  if (err < 0)
118  return err;
119  } else
120  val |= PWM_ENABLE;
121 
122  pwm_writel(pc, pwm->hwpwm, val);
123 
124  /*
125  * If the PWM is not enabled, turn the clock off again to save power.
126  */
127  if (!test_bit(PWMF_ENABLED, &pwm->flags))
128  clk_disable_unprepare(pc->clk);
129 
130  return 0;
131 }
132 
133 static int tegra_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
134 {
135  struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
136  int rc = 0;
137  u32 val;
138 
139  rc = clk_prepare_enable(pc->clk);
140  if (rc < 0)
141  return rc;
142 
143  val = pwm_readl(pc, pwm->hwpwm);
144  val |= PWM_ENABLE;
145  pwm_writel(pc, pwm->hwpwm, val);
146 
147  return 0;
148 }
149 
150 static void tegra_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
151 {
152  struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
153  u32 val;
154 
155  val = pwm_readl(pc, pwm->hwpwm);
156  val &= ~PWM_ENABLE;
157  pwm_writel(pc, pwm->hwpwm, val);
158 
159  clk_disable_unprepare(pc->clk);
160 }
161 
162 static const struct pwm_ops tegra_pwm_ops = {
163  .config = tegra_pwm_config,
164  .enable = tegra_pwm_enable,
165  .disable = tegra_pwm_disable,
166  .owner = THIS_MODULE,
167 };
168 
169 static int tegra_pwm_probe(struct platform_device *pdev)
170 {
171  struct tegra_pwm_chip *pwm;
172  struct resource *r;
173  int ret;
174 
175  pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
176  if (!pwm) {
177  dev_err(&pdev->dev, "failed to allocate memory\n");
178  return -ENOMEM;
179  }
180 
181  pwm->dev = &pdev->dev;
182 
184  if (!r) {
185  dev_err(&pdev->dev, "no memory resources defined\n");
186  return -ENODEV;
187  }
188 
189  pwm->mmio_base = devm_request_and_ioremap(&pdev->dev, r);
190  if (!pwm->mmio_base)
191  return -EADDRNOTAVAIL;
192 
193  platform_set_drvdata(pdev, pwm);
194 
195  pwm->clk = devm_clk_get(&pdev->dev, NULL);
196  if (IS_ERR(pwm->clk))
197  return PTR_ERR(pwm->clk);
198 
199  pwm->chip.dev = &pdev->dev;
200  pwm->chip.ops = &tegra_pwm_ops;
201  pwm->chip.base = -1;
202  pwm->chip.npwm = NUM_PWM;
203 
204  ret = pwmchip_add(&pwm->chip);
205  if (ret < 0) {
206  dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
207  return ret;
208  }
209 
210  return 0;
211 }
212 
213 static int __devexit tegra_pwm_remove(struct platform_device *pdev)
214 {
215  struct tegra_pwm_chip *pc = platform_get_drvdata(pdev);
216  int i;
217 
218  if (WARN_ON(!pc))
219  return -ENODEV;
220 
221  for (i = 0; i < NUM_PWM; i++) {
222  struct pwm_device *pwm = &pc->chip.pwms[i];
223 
224  if (!test_bit(PWMF_ENABLED, &pwm->flags))
225  if (clk_prepare_enable(pc->clk) < 0)
226  continue;
227 
228  pwm_writel(pc, i, 0);
229 
230  clk_disable_unprepare(pc->clk);
231  }
232 
233  return pwmchip_remove(&pc->chip);
234 }
235 
236 #ifdef CONFIG_OF
237 static struct of_device_id tegra_pwm_of_match[] = {
238  { .compatible = "nvidia,tegra20-pwm" },
239  { .compatible = "nvidia,tegra30-pwm" },
240  { }
241 };
242 
243 MODULE_DEVICE_TABLE(of, tegra_pwm_of_match);
244 #endif
245 
246 static struct platform_driver tegra_pwm_driver = {
247  .driver = {
248  .name = "tegra-pwm",
249  .of_match_table = of_match_ptr(tegra_pwm_of_match),
250  },
251  .probe = tegra_pwm_probe,
252  .remove = __devexit_p(tegra_pwm_remove),
253 };
254 
255 module_platform_driver(tegra_pwm_driver);
256 
257 MODULE_LICENSE("GPL");
258 MODULE_AUTHOR("NVIDIA Corporation");
259 MODULE_ALIAS("platform:tegra-pwm");