1 /* 2 * drivers/pwm/pwm-pxa.c 3 * 4 * simple driver for PWM (Pulse Width Modulator) controller 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * 2008-02-13 initial version 11 * eric miao <eric.miao@marvell.com> 12 */ 13 14 #include <linux/module.h> 15 #include <linux/kernel.h> 16 #include <linux/platform_device.h> 17 #include <linux/slab.h> 18 #include <linux/err.h> 19 #include <linux/clk.h> 20 #include <linux/io.h> 21 #include <linux/pwm.h> 22 23 #include <asm/div64.h> 24 25 #define HAS_SECONDARY_PWM 0x10 26 27 static const struct platform_device_id pwm_id_table[] = { 28 /* PWM has_secondary_pwm? */ 29 { "pxa25x-pwm", 0 }, 30 { "pxa27x-pwm", HAS_SECONDARY_PWM }, 31 { "pxa168-pwm", 0 }, 32 { "pxa910-pwm", 0 }, 33 { }, 34 }; 35 MODULE_DEVICE_TABLE(platform, pwm_id_table); 36 37 /* PWM registers and bits definitions */ 38 #define PWMCR (0x00) 39 #define PWMDCR (0x04) 40 #define PWMPCR (0x08) 41 42 #define PWMCR_SD (1 << 6) 43 #define PWMDCR_FD (1 << 10) 44 45 struct pxa_pwm_chip { 46 struct pwm_chip chip; 47 struct device *dev; 48 49 struct clk *clk; 50 void __iomem *mmio_base; 51 }; 52 53 static inline struct pxa_pwm_chip *to_pxa_pwm_chip(struct pwm_chip *chip) 54 { 55 return container_of(chip, struct pxa_pwm_chip, chip); 56 } 57 58 /* 59 * period_ns = 10^9 * (PRESCALE + 1) * (PV + 1) / PWM_CLK_RATE 60 * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE 61 */ 62 static int pxa_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 63 int duty_ns, int period_ns) 64 { 65 struct pxa_pwm_chip *pc = to_pxa_pwm_chip(chip); 66 unsigned long long c; 67 unsigned long period_cycles, prescale, pv, dc; 68 unsigned long offset; 69 int rc; 70 71 offset = pwm->hwpwm ? 0x10 : 0; 72 73 c = clk_get_rate(pc->clk); 74 c = c * period_ns; 75 do_div(c, 1000000000); 76 period_cycles = c; 77 78 if (period_cycles < 1) 79 period_cycles = 1; 80 prescale = (period_cycles - 1) / 1024; 81 pv = period_cycles / (prescale + 1) - 1; 82 83 if (prescale > 63) 84 return -EINVAL; 85 86 if (duty_ns == period_ns) 87 dc = PWMDCR_FD; 88 else 89 dc = (pv + 1) * duty_ns / period_ns; 90 91 /* NOTE: the clock to PWM has to be enabled first 92 * before writing to the registers 93 */ 94 rc = clk_prepare_enable(pc->clk); 95 if (rc < 0) 96 return rc; 97 98 writel(prescale, pc->mmio_base + offset + PWMCR); 99 writel(dc, pc->mmio_base + offset + PWMDCR); 100 writel(pv, pc->mmio_base + offset + PWMPCR); 101 102 clk_disable_unprepare(pc->clk); 103 return 0; 104 } 105 106 static int pxa_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 107 { 108 struct pxa_pwm_chip *pc = to_pxa_pwm_chip(chip); 109 110 return clk_prepare_enable(pc->clk); 111 } 112 113 static void pxa_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) 114 { 115 struct pxa_pwm_chip *pc = to_pxa_pwm_chip(chip); 116 117 clk_disable_unprepare(pc->clk); 118 } 119 120 static struct pwm_ops pxa_pwm_ops = { 121 .config = pxa_pwm_config, 122 .enable = pxa_pwm_enable, 123 .disable = pxa_pwm_disable, 124 .owner = THIS_MODULE, 125 }; 126 127 static int pwm_probe(struct platform_device *pdev) 128 { 129 const struct platform_device_id *id = platform_get_device_id(pdev); 130 struct pxa_pwm_chip *pwm; 131 struct resource *r; 132 int ret = 0; 133 134 pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); 135 if (pwm == NULL) { 136 dev_err(&pdev->dev, "failed to allocate memory\n"); 137 return -ENOMEM; 138 } 139 140 pwm->clk = devm_clk_get(&pdev->dev, NULL); 141 if (IS_ERR(pwm->clk)) 142 return PTR_ERR(pwm->clk); 143 144 pwm->chip.dev = &pdev->dev; 145 pwm->chip.ops = &pxa_pwm_ops; 146 pwm->chip.base = -1; 147 pwm->chip.npwm = (id->driver_data & HAS_SECONDARY_PWM) ? 2 : 1; 148 149 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 150 if (r == NULL) { 151 dev_err(&pdev->dev, "no memory resource defined\n"); 152 return -ENODEV; 153 } 154 155 pwm->mmio_base = devm_ioremap_resource(&pdev->dev, r); 156 if (IS_ERR(pwm->mmio_base)) 157 return PTR_ERR(pwm->mmio_base); 158 159 ret = pwmchip_add(&pwm->chip); 160 if (ret < 0) { 161 dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); 162 return ret; 163 } 164 165 platform_set_drvdata(pdev, pwm); 166 return 0; 167 } 168 169 static int pwm_remove(struct platform_device *pdev) 170 { 171 struct pxa_pwm_chip *chip; 172 173 chip = platform_get_drvdata(pdev); 174 if (chip == NULL) 175 return -ENODEV; 176 177 return pwmchip_remove(&chip->chip); 178 } 179 180 static struct platform_driver pwm_driver = { 181 .driver = { 182 .name = "pxa25x-pwm", 183 .owner = THIS_MODULE, 184 }, 185 .probe = pwm_probe, 186 .remove = pwm_remove, 187 .id_table = pwm_id_table, 188 }; 189 190 static int __init pwm_init(void) 191 { 192 return platform_driver_register(&pwm_driver); 193 } 194 arch_initcall(pwm_init); 195 196 static void __exit pwm_exit(void) 197 { 198 platform_driver_unregister(&pwm_driver); 199 } 200 module_exit(pwm_exit); 201 202 MODULE_LICENSE("GPL v2"); 203