297 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2019 Spreadtrum Communications Inc.4 */5 6#include <linux/clk.h>7#include <linux/err.h>8#include <linux/io.h>9#include <linux/math64.h>10#include <linux/mod_devicetable.h>11#include <linux/module.h>12#include <linux/platform_device.h>13#include <linux/pwm.h>14 15#define SPRD_PWM_PRESCALE 0x016#define SPRD_PWM_MOD 0x417#define SPRD_PWM_DUTY 0x818#define SPRD_PWM_ENABLE 0x1819 20#define SPRD_PWM_MOD_MAX GENMASK(7, 0)21#define SPRD_PWM_DUTY_MSK GENMASK(15, 0)22#define SPRD_PWM_PRESCALE_MSK GENMASK(7, 0)23#define SPRD_PWM_ENABLE_BIT BIT(0)24 25#define SPRD_PWM_CHN_NUM 426#define SPRD_PWM_REGS_SHIFT 527#define SPRD_PWM_CHN_CLKS_NUM 228#define SPRD_PWM_CHN_OUTPUT_CLK 129 30struct sprd_pwm_chn {31 struct clk_bulk_data clks[SPRD_PWM_CHN_CLKS_NUM];32 u32 clk_rate;33};34 35struct sprd_pwm_chip {36 void __iomem *base;37 struct sprd_pwm_chn chn[SPRD_PWM_CHN_NUM];38};39 40static inline struct sprd_pwm_chip* sprd_pwm_from_chip(struct pwm_chip *chip)41{42 return pwmchip_get_drvdata(chip);43}44 45/*46 * The list of clocks required by PWM channels, and each channel has 2 clocks:47 * enable clock and pwm clock.48 */49static const char * const sprd_pwm_clks[] = {50 "enable0", "pwm0",51 "enable1", "pwm1",52 "enable2", "pwm2",53 "enable3", "pwm3",54};55 56static u32 sprd_pwm_read(struct sprd_pwm_chip *spc, u32 hwid, u32 reg)57{58 u32 offset = reg + (hwid << SPRD_PWM_REGS_SHIFT);59 60 return readl_relaxed(spc->base + offset);61}62 63static void sprd_pwm_write(struct sprd_pwm_chip *spc, u32 hwid,64 u32 reg, u32 val)65{66 u32 offset = reg + (hwid << SPRD_PWM_REGS_SHIFT);67 68 writel_relaxed(val, spc->base + offset);69}70 71static int sprd_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,72 struct pwm_state *state)73{74 struct sprd_pwm_chip *spc = sprd_pwm_from_chip(chip);75 struct sprd_pwm_chn *chn = &spc->chn[pwm->hwpwm];76 u32 val, duty, prescale;77 u64 tmp;78 int ret;79 80 /*81 * The clocks to PWM channel has to be enabled first before82 * reading to the registers.83 */84 ret = clk_bulk_prepare_enable(SPRD_PWM_CHN_CLKS_NUM, chn->clks);85 if (ret) {86 dev_err(pwmchip_parent(chip), "failed to enable pwm%u clocks\n",87 pwm->hwpwm);88 return ret;89 }90 91 val = sprd_pwm_read(spc, pwm->hwpwm, SPRD_PWM_ENABLE);92 if (val & SPRD_PWM_ENABLE_BIT)93 state->enabled = true;94 else95 state->enabled = false;96 97 /*98 * The hardware provides a counter that is feed by the source clock.99 * The period length is (PRESCALE + 1) * MOD counter steps.100 * The duty cycle length is (PRESCALE + 1) * DUTY counter steps.101 * Thus the period_ns and duty_ns calculation formula should be:102 * period_ns = NSEC_PER_SEC * (prescale + 1) * mod / clk_rate103 * duty_ns = NSEC_PER_SEC * (prescale + 1) * duty / clk_rate104 */105 val = sprd_pwm_read(spc, pwm->hwpwm, SPRD_PWM_PRESCALE);106 prescale = val & SPRD_PWM_PRESCALE_MSK;107 tmp = (prescale + 1) * NSEC_PER_SEC * SPRD_PWM_MOD_MAX;108 state->period = DIV_ROUND_CLOSEST_ULL(tmp, chn->clk_rate);109 110 val = sprd_pwm_read(spc, pwm->hwpwm, SPRD_PWM_DUTY);111 duty = val & SPRD_PWM_DUTY_MSK;112 tmp = (prescale + 1) * NSEC_PER_SEC * duty;113 state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, chn->clk_rate);114 state->polarity = PWM_POLARITY_NORMAL;115 116 /* Disable PWM clocks if the PWM channel is not in enable state. */117 if (!state->enabled)118 clk_bulk_disable_unprepare(SPRD_PWM_CHN_CLKS_NUM, chn->clks);119 120 return 0;121}122 123static int sprd_pwm_config(struct sprd_pwm_chip *spc, struct pwm_device *pwm,124 int duty_ns, int period_ns)125{126 struct sprd_pwm_chn *chn = &spc->chn[pwm->hwpwm];127 u32 prescale, duty;128 u64 tmp;129 130 /*131 * The hardware provides a counter that is feed by the source clock.132 * The period length is (PRESCALE + 1) * MOD counter steps.133 * The duty cycle length is (PRESCALE + 1) * DUTY counter steps.134 *135 * To keep the maths simple we're always using MOD = SPRD_PWM_MOD_MAX.136 * The value for PRESCALE is selected such that the resulting period137 * gets the maximal length not bigger than the requested one with the138 * given settings (MOD = SPRD_PWM_MOD_MAX and input clock).139 */140 duty = duty_ns * SPRD_PWM_MOD_MAX / period_ns;141 142 tmp = (u64)chn->clk_rate * period_ns;143 do_div(tmp, NSEC_PER_SEC);144 prescale = DIV_ROUND_CLOSEST_ULL(tmp, SPRD_PWM_MOD_MAX) - 1;145 if (prescale > SPRD_PWM_PRESCALE_MSK)146 prescale = SPRD_PWM_PRESCALE_MSK;147 148 /*149 * Note: Writing DUTY triggers the hardware to actually apply the150 * values written to MOD and DUTY to the output, so must keep writing151 * DUTY last.152 *153 * The hardware can ensures that current running period is completed154 * before changing a new configuration to avoid mixed settings.155 */156 sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_PRESCALE, prescale);157 sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_MOD, SPRD_PWM_MOD_MAX);158 sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_DUTY, duty);159 160 return 0;161}162 163static int sprd_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,164 const struct pwm_state *state)165{166 struct sprd_pwm_chip *spc = sprd_pwm_from_chip(chip);167 struct sprd_pwm_chn *chn = &spc->chn[pwm->hwpwm];168 struct pwm_state *cstate = &pwm->state;169 int ret;170 171 if (state->polarity != PWM_POLARITY_NORMAL)172 return -EINVAL;173 174 if (state->enabled) {175 if (!cstate->enabled) {176 /*177 * The clocks to PWM channel has to be enabled first178 * before writing to the registers.179 */180 ret = clk_bulk_prepare_enable(SPRD_PWM_CHN_CLKS_NUM,181 chn->clks);182 if (ret) {183 dev_err(pwmchip_parent(chip),184 "failed to enable pwm%u clocks\n",185 pwm->hwpwm);186 return ret;187 }188 }189 190 ret = sprd_pwm_config(spc, pwm, state->duty_cycle,191 state->period);192 if (ret)193 return ret;194 195 sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_ENABLE, 1);196 } else if (cstate->enabled) {197 /*198 * Note: After setting SPRD_PWM_ENABLE to zero, the controller199 * will not wait for current period to be completed, instead it200 * will stop the PWM channel immediately.201 */202 sprd_pwm_write(spc, pwm->hwpwm, SPRD_PWM_ENABLE, 0);203 204 clk_bulk_disable_unprepare(SPRD_PWM_CHN_CLKS_NUM, chn->clks);205 }206 207 return 0;208}209 210static const struct pwm_ops sprd_pwm_ops = {211 .apply = sprd_pwm_apply,212 .get_state = sprd_pwm_get_state,213};214 215static int sprd_pwm_clk_init(struct device *dev,216 struct sprd_pwm_chn chn[SPRD_PWM_CHN_NUM])217{218 struct clk *clk_pwm;219 int ret, i;220 221 for (i = 0; i < SPRD_PWM_CHN_NUM; i++) {222 int j;223 224 for (j = 0; j < SPRD_PWM_CHN_CLKS_NUM; ++j)225 chn[i].clks[j].id =226 sprd_pwm_clks[i * SPRD_PWM_CHN_CLKS_NUM + j];227 228 ret = devm_clk_bulk_get(dev, SPRD_PWM_CHN_CLKS_NUM,229 chn[i].clks);230 if (ret) {231 if (ret == -ENOENT)232 break;233 234 return dev_err_probe(dev, ret,235 "failed to get channel clocks\n");236 }237 238 clk_pwm = chn[i].clks[SPRD_PWM_CHN_OUTPUT_CLK].clk;239 chn[i].clk_rate = clk_get_rate(clk_pwm);240 }241 242 if (!i)243 return dev_err_probe(dev, -ENODEV, "no available PWM channels\n");244 245 return i;246}247 248static int sprd_pwm_probe(struct platform_device *pdev)249{250 struct pwm_chip *chip;251 struct sprd_pwm_chip *spc;252 struct sprd_pwm_chn chn[SPRD_PWM_CHN_NUM];253 int ret, npwm;254 255 npwm = sprd_pwm_clk_init(&pdev->dev, chn);256 if (npwm < 0)257 return npwm;258 259 chip = devm_pwmchip_alloc(&pdev->dev, npwm, sizeof(*spc));260 if (IS_ERR(chip))261 return PTR_ERR(chip);262 spc = sprd_pwm_from_chip(chip);263 264 spc->base = devm_platform_ioremap_resource(pdev, 0);265 if (IS_ERR(spc->base))266 return PTR_ERR(spc->base);267 268 memcpy(spc->chn, chn, sizeof(chn));269 270 chip->ops = &sprd_pwm_ops;271 272 ret = devm_pwmchip_add(&pdev->dev, chip);273 if (ret)274 dev_err(&pdev->dev, "failed to add PWM chip\n");275 276 return ret;277}278 279static const struct of_device_id sprd_pwm_of_match[] = {280 { .compatible = "sprd,ums512-pwm", },281 { },282};283MODULE_DEVICE_TABLE(of, sprd_pwm_of_match);284 285static struct platform_driver sprd_pwm_driver = {286 .driver = {287 .name = "sprd-pwm",288 .of_match_table = sprd_pwm_of_match,289 },290 .probe = sprd_pwm_probe,291};292 293module_platform_driver(sprd_pwm_driver);294 295MODULE_DESCRIPTION("Spreadtrum PWM Driver");296MODULE_LICENSE("GPL v2");297