2 * Blackfin Pulse Width Modulation (PWM) core
4 * Copyright (c) 2011 Analog Devices Inc.
6 * Licensed under the GPL-2 or later.
9 #include <linux/module.h>
10 #include <linux/platform_device.h>
11 #include <linux/pwm.h>
12 #include <linux/slab.h>
14 #include <asm/gptimers.h>
15 #include <asm/portmux.h>
17 struct bfin_pwm_chip
{
25 static const unsigned short pwm_to_gptimer_per
[] = {
26 P_TMR0
, P_TMR1
, P_TMR2
, P_TMR3
, P_TMR4
, P_TMR5
,
27 P_TMR6
, P_TMR7
, P_TMR8
, P_TMR9
, P_TMR10
, P_TMR11
,
30 static int bfin_pwm_request(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
32 struct bfin_pwm
*priv
;
35 if (pwm
->hwpwm
>= ARRAY_SIZE(pwm_to_gptimer_per
))
38 priv
= kzalloc(sizeof(*priv
), GFP_KERNEL
);
42 priv
->pin
= pwm_to_gptimer_per
[pwm
->hwpwm
];
44 ret
= peripheral_request(priv
->pin
, NULL
);
50 pwm_set_chip_data(pwm
, priv
);
55 static void bfin_pwm_free(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
57 struct bfin_pwm
*priv
= pwm_get_chip_data(pwm
);
60 peripheral_free(priv
->pin
);
65 static int bfin_pwm_config(struct pwm_chip
*chip
, struct pwm_device
*pwm
,
66 int duty_ns
, int period_ns
)
68 struct bfin_pwm
*priv
= pwm_get_chip_data(pwm
);
69 unsigned long period
, duty
;
70 unsigned long long val
;
72 val
= (unsigned long long)get_sclk() * period_ns
;
73 do_div(val
, NSEC_PER_SEC
);
76 val
= (unsigned long long)period
* duty_ns
;
77 do_div(val
, period_ns
);
83 set_gptimer_config(priv
->pin
, TIMER_MODE_PWM
| TIMER_PERIOD_CNT
);
84 set_gptimer_pwidth(priv
->pin
, duty
);
85 set_gptimer_period(priv
->pin
, period
);
90 static int bfin_pwm_enable(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
92 struct bfin_pwm
*priv
= pwm_get_chip_data(pwm
);
94 enable_gptimer(priv
->pin
);
99 static void bfin_pwm_disable(struct pwm_chip
*chip
, struct pwm_device
*pwm
)
101 struct bfin_pwm
*priv
= pwm_get_chip_data(pwm
);
103 disable_gptimer(priv
->pin
);
106 static struct pwm_ops bfin_pwm_ops
= {
107 .request
= bfin_pwm_request
,
108 .free
= bfin_pwm_free
,
109 .config
= bfin_pwm_config
,
110 .enable
= bfin_pwm_enable
,
111 .disable
= bfin_pwm_disable
,
112 .owner
= THIS_MODULE
,
115 static int bfin_pwm_probe(struct platform_device
*pdev
)
117 struct bfin_pwm_chip
*pwm
;
120 pwm
= devm_kzalloc(&pdev
->dev
, sizeof(*pwm
), GFP_KERNEL
);
122 dev_err(&pdev
->dev
, "failed to allocate memory\n");
126 platform_set_drvdata(pdev
, pwm
);
128 pwm
->chip
.dev
= &pdev
->dev
;
129 pwm
->chip
.ops
= &bfin_pwm_ops
;
133 ret
= pwmchip_add(&pwm
->chip
);
135 dev_err(&pdev
->dev
, "pwmchip_add() failed: %d\n", ret
);
142 static int bfin_pwm_remove(struct platform_device
*pdev
)
144 struct bfin_pwm_chip
*pwm
= platform_get_drvdata(pdev
);
146 return pwmchip_remove(&pwm
->chip
);
149 static struct platform_driver bfin_pwm_driver
= {
152 .owner
= THIS_MODULE
,
154 .probe
= bfin_pwm_probe
,
155 .remove
= bfin_pwm_remove
,
158 module_platform_driver(bfin_pwm_driver
);
160 MODULE_LICENSE("GPL");