1 #include <linux/module.h>
2 #include <linux/platform_device.h>
3 #include <linux/mod_devicetable.h>
5 #include <linux/of_platform.h>
6 #include <asm-powerpc/mpc52xx.h>
7 #include <linux/interrupt.h>
10 struct mpc52xx_gpt *pwmf, *pwmb;
16 static ssize_t show_position(struct device *dev,
17 struct device_attribute *attr, char *buf)
19 struct platform_device *pdev = to_platform_device(dev);
20 struct motorek *m = platform_get_drvdata(pdev);
22 int len = snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&m->pos));
23 return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
26 static ssize_t show_action(struct device *dev,
27 struct device_attribute *attr, char *buf)
29 struct platform_device *pdev = to_platform_device(dev);
30 struct motorek *m = platform_get_drvdata(pdev);
32 int len = snprintf(buf, PAGE_SIZE, "%d\n", m->action);
33 return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
36 static void motorek_action(struct motorek *m, int action_permile);
37 static ssize_t store_action(struct device *dev, struct device_attribute *attr,
38 const char *buf, size_t count)
40 struct platform_device *pdev = to_platform_device(dev);
41 struct motorek *m = platform_get_drvdata(pdev);
44 sscanf(buf, "%d", &a);
46 return strnlen(buf, PAGE_SIZE);
49 DEVICE_ATTR(position,0444,show_position,NULL);
50 DEVICE_ATTR(action,0644,show_action,store_action);
52 #define MPC52xx_GPT_MODE_DISABLED 0
53 #define MPC52xx_GPT_MODE_INCAPT 1
54 #define MPC52xx_GPT_MODE_OUTCMP 2
55 #define MPC52xx_GPT_MODE_PWM 3
56 #define MPC52xx_GPT_MODE_GPIO 4
58 #define MPC52xx_GPT_PWM_OP (1<<8)
61 * (/proc/device-tree/cpus/PowerPC,5200@0/bus-frequency) */
62 #define PWM_PERIOD 6600 /* = 132 000 kHz / 20 kHz */
65 static void pwm_width(struct mpc52xx_gpt *gpt, u16 width)
67 out_be32(&gpt->pwm, (width<<16) | MPC52xx_GPT_PWM_OP);
68 //printk("pwm: %p=0x%x\n", gpt, width);
72 static void __devinit pwm_init(struct mpc52xx_gpt *gpt)
74 //while (((unsigned)gpt & 0xff) != 0x50) gpt++;
75 out_be32(&gpt->count, (1<<16) | PWM_PERIOD);
77 out_be32(&gpt->mode, MPC52xx_GPT_MODE_PWM);
79 //out_be32(&gpt->pwm, (500<<16) | MPC52xx_GPT_PWM_OP); /* REMOVE ME */
81 //out_be32(&gpt->mode, MPC52xx_GPT_MODE_GPIO | (2<<4));
82 //printk("pwm: %p\n", gpt);
85 static void pwm_done(struct mpc52xx_gpt *gpt)
87 out_be32(&gpt->mode, 0);
88 out_be32(&gpt->count, 0);
92 static void motorek_action(struct motorek *m, int action_permile)
94 m->action = action_permile;
95 if (action_permile >= 0) {
96 pwm_width(m->pwmb, 0);
97 pwm_width(m->pwmf, +action_permile*PWM_PERIOD/1000);
99 pwm_width(m->pwmf, 0);
100 pwm_width(m->pwmb, -action_permile*PWM_PERIOD/1000);
104 static int __devinit motorek_init(struct motorek *m)
108 //motorek_action(m, +0);
112 static int motorek_done(struct motorek *m)
119 static irqreturn_t motorek_irq(int irq, void *dev_id)
121 struct motorek *m = dev_id;
126 struct mpc52xx_gpt __iomem *iomap_gpt_by_phandle(const phandle *phandle)
128 struct device_node *np;
129 struct mpc52xx_gpt __iomem *gpt;
134 np = of_find_node_by_phandle(*phandle);
137 gpt = of_iomap(np, 0);
142 static int __devinit motorek_probe(struct of_device* dev,
143 const struct of_device_id *match)
145 struct device_node *dn = dev->node;
149 m = kzalloc(sizeof(*m), GFP_KERNEL);
155 m->pwmf = iomap_gpt_by_phandle(of_get_property(dn, "pwmf", NULL));
159 m->pwmb = iomap_gpt_by_phandle(of_get_property(dn, "pwmb", NULL));
163 m->irq = irq_of_parse_and_map(dn, 0);
164 if (m->irq == NO_IRQ)
167 err = request_irq(m->irq, motorek_irq, 0, "motorek", m);
173 platform_set_drvdata(dev, m);
175 err = device_create_file(&dev->dev,&dev_attr_position);
178 err = device_create_file(&dev->dev,&dev_attr_action);
182 printk(KERN_NOTICE "Motorek initialized\n");
197 static int __devexit motorek_remove(struct of_device* dev)
201 printk(KERN_NOTICE "Removing motorek\n");
202 m = platform_get_drvdata(dev);
209 static struct of_device_id motorek_match[] = {
210 { .type = "motorek", },
213 static struct of_platform_driver motorek_driver = {
214 .owner = THIS_MODULE,
216 .match_table = motorek_match,
217 .probe = motorek_probe,
218 .remove = __devexit_p(motorek_remove),
222 static int __init motorek_init_module(void)
225 struct of_device *dev;
226 struct device_node *dn;
228 for_each_node_by_type(dn, "motorek") {
229 if (!of_find_device_by_node(dn)) {
230 dev = of_platform_device_create(dn, NULL, NULL);
236 ret = of_register_platform_driver(&motorek_driver);
240 static void __exit motorek_exit_module(void)
242 struct of_device *dev;
243 struct device_node *dn;
245 for_each_node_by_type(dn, "motorek") {
246 while ((dev = of_find_device_by_node(dn))) {
247 of_device_unregister(dev);
250 of_unregister_platform_driver(&motorek_driver);
253 module_init(motorek_init_module);
254 module_exit(motorek_exit_module);
257 MODULE_LICENSE("GPL v2");
258 MODULE_VERSION("0.1");
259 MODULE_AUTHOR("Michal Sojka <sojkam1@fel.cvut.cz>");