18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * sl28cpld PWM driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2020 Michael Walle <michael@walle.cc> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * There is no public datasheet available for this PWM core. But it is easy 88c2ecf20Sopenharmony_ci * enough to be briefly explained. It consists of one 8-bit counter. The PWM 98c2ecf20Sopenharmony_ci * supports four distinct frequencies by selecting when to reset the counter. 108c2ecf20Sopenharmony_ci * With the prescaler setting you can select which bit of the counter is used 118c2ecf20Sopenharmony_ci * to reset it. This implies that the higher the frequency the less remaining 128c2ecf20Sopenharmony_ci * bits are available for the actual counter. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * Let cnt[7:0] be the counter, clocked at 32kHz: 158c2ecf20Sopenharmony_ci * +-----------+--------+--------------+-----------+---------------+ 168c2ecf20Sopenharmony_ci * | prescaler | reset | counter bits | frequency | period length | 178c2ecf20Sopenharmony_ci * +-----------+--------+--------------+-----------+---------------+ 188c2ecf20Sopenharmony_ci * | 0 | cnt[7] | cnt[6:0] | 250 Hz | 4000000 ns | 198c2ecf20Sopenharmony_ci * | 1 | cnt[6] | cnt[5:0] | 500 Hz | 2000000 ns | 208c2ecf20Sopenharmony_ci * | 2 | cnt[5] | cnt[4:0] | 1 kHz | 1000000 ns | 218c2ecf20Sopenharmony_ci * | 3 | cnt[4] | cnt[3:0] | 2 kHz | 500000 ns | 228c2ecf20Sopenharmony_ci * +-----------+--------+--------------+-----------+---------------+ 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * Limitations: 258c2ecf20Sopenharmony_ci * - The hardware cannot generate a 100% duty cycle if the prescaler is 0. 268c2ecf20Sopenharmony_ci * - The hardware cannot atomically set the prescaler and the counter value, 278c2ecf20Sopenharmony_ci * which might lead to glitches and inconsistent states if a write fails. 288c2ecf20Sopenharmony_ci * - The counter is not reset if you switch the prescaler which leads 298c2ecf20Sopenharmony_ci * to glitches, too. 308c2ecf20Sopenharmony_ci * - The duty cycle will switch immediately and not after a complete cycle. 318c2ecf20Sopenharmony_ci * - Depending on the actual implementation, disabling the PWM might have 328c2ecf20Sopenharmony_ci * side effects. For example, if the output pin is shared with a GPIO pin 338c2ecf20Sopenharmony_ci * it will automatically switch back to GPIO mode. 348c2ecf20Sopenharmony_ci */ 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#include <linux/bitfield.h> 378c2ecf20Sopenharmony_ci#include <linux/kernel.h> 388c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h> 398c2ecf20Sopenharmony_ci#include <linux/module.h> 408c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 418c2ecf20Sopenharmony_ci#include <linux/pwm.h> 428c2ecf20Sopenharmony_ci#include <linux/regmap.h> 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci/* 458c2ecf20Sopenharmony_ci * PWM timer block registers. 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_ci#define SL28CPLD_PWM_CTRL 0x00 488c2ecf20Sopenharmony_ci#define SL28CPLD_PWM_CTRL_ENABLE BIT(7) 498c2ecf20Sopenharmony_ci#define SL28CPLD_PWM_CTRL_PRESCALER_MASK GENMASK(1, 0) 508c2ecf20Sopenharmony_ci#define SL28CPLD_PWM_CYCLE 0x01 518c2ecf20Sopenharmony_ci#define SL28CPLD_PWM_CYCLE_MAX GENMASK(6, 0) 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#define SL28CPLD_PWM_CLK 32000 /* 32 kHz */ 548c2ecf20Sopenharmony_ci#define SL28CPLD_PWM_MAX_DUTY_CYCLE(prescaler) (1 << (7 - (prescaler))) 558c2ecf20Sopenharmony_ci#define SL28CPLD_PWM_PERIOD(prescaler) \ 568c2ecf20Sopenharmony_ci (NSEC_PER_SEC / SL28CPLD_PWM_CLK * SL28CPLD_PWM_MAX_DUTY_CYCLE(prescaler)) 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/* 598c2ecf20Sopenharmony_ci * We calculate the duty cycle like this: 608c2ecf20Sopenharmony_ci * duty_cycle_ns = pwm_cycle_reg * max_period_ns / max_duty_cycle 618c2ecf20Sopenharmony_ci * 628c2ecf20Sopenharmony_ci * With 638c2ecf20Sopenharmony_ci * max_period_ns = 1 << (7 - prescaler) / SL28CPLD_PWM_CLK * NSEC_PER_SEC 648c2ecf20Sopenharmony_ci * max_duty_cycle = 1 << (7 - prescaler) 658c2ecf20Sopenharmony_ci * this then simplifies to: 668c2ecf20Sopenharmony_ci * duty_cycle_ns = pwm_cycle_reg / SL28CPLD_PWM_CLK * NSEC_PER_SEC 678c2ecf20Sopenharmony_ci * = NSEC_PER_SEC / SL28CPLD_PWM_CLK * pwm_cycle_reg 688c2ecf20Sopenharmony_ci * 698c2ecf20Sopenharmony_ci * NSEC_PER_SEC is a multiple of SL28CPLD_PWM_CLK, therefore we're not losing 708c2ecf20Sopenharmony_ci * precision by doing the divison first. 718c2ecf20Sopenharmony_ci */ 728c2ecf20Sopenharmony_ci#define SL28CPLD_PWM_TO_DUTY_CYCLE(reg) \ 738c2ecf20Sopenharmony_ci (NSEC_PER_SEC / SL28CPLD_PWM_CLK * (reg)) 748c2ecf20Sopenharmony_ci#define SL28CPLD_PWM_FROM_DUTY_CYCLE(duty_cycle) \ 758c2ecf20Sopenharmony_ci (DIV_ROUND_DOWN_ULL((duty_cycle), NSEC_PER_SEC / SL28CPLD_PWM_CLK)) 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci#define sl28cpld_pwm_read(priv, reg, val) \ 788c2ecf20Sopenharmony_ci regmap_read((priv)->regmap, (priv)->offset + (reg), (val)) 798c2ecf20Sopenharmony_ci#define sl28cpld_pwm_write(priv, reg, val) \ 808c2ecf20Sopenharmony_ci regmap_write((priv)->regmap, (priv)->offset + (reg), (val)) 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistruct sl28cpld_pwm { 838c2ecf20Sopenharmony_ci struct pwm_chip pwm_chip; 848c2ecf20Sopenharmony_ci struct regmap *regmap; 858c2ecf20Sopenharmony_ci u32 offset; 868c2ecf20Sopenharmony_ci}; 878c2ecf20Sopenharmony_ci#define sl28cpld_pwm_from_chip(_chip) \ 888c2ecf20Sopenharmony_ci container_of(_chip, struct sl28cpld_pwm, pwm_chip) 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic void sl28cpld_pwm_get_state(struct pwm_chip *chip, 918c2ecf20Sopenharmony_ci struct pwm_device *pwm, 928c2ecf20Sopenharmony_ci struct pwm_state *state) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci struct sl28cpld_pwm *priv = sl28cpld_pwm_from_chip(chip); 958c2ecf20Sopenharmony_ci unsigned int reg; 968c2ecf20Sopenharmony_ci int prescaler; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci sl28cpld_pwm_read(priv, SL28CPLD_PWM_CTRL, ®); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci state->enabled = reg & SL28CPLD_PWM_CTRL_ENABLE; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci prescaler = FIELD_GET(SL28CPLD_PWM_CTRL_PRESCALER_MASK, reg); 1038c2ecf20Sopenharmony_ci state->period = SL28CPLD_PWM_PERIOD(prescaler); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci sl28cpld_pwm_read(priv, SL28CPLD_PWM_CYCLE, ®); 1068c2ecf20Sopenharmony_ci state->duty_cycle = SL28CPLD_PWM_TO_DUTY_CYCLE(reg); 1078c2ecf20Sopenharmony_ci state->polarity = PWM_POLARITY_NORMAL; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci /* 1108c2ecf20Sopenharmony_ci * Sanitize values for the PWM core. Depending on the prescaler it 1118c2ecf20Sopenharmony_ci * might happen that we calculate a duty_cycle greater than the actual 1128c2ecf20Sopenharmony_ci * period. This might happen if someone (e.g. the bootloader) sets an 1138c2ecf20Sopenharmony_ci * invalid combination of values. The behavior of the hardware is 1148c2ecf20Sopenharmony_ci * undefined in this case. But we need to report sane values back to 1158c2ecf20Sopenharmony_ci * the PWM core. 1168c2ecf20Sopenharmony_ci */ 1178c2ecf20Sopenharmony_ci state->duty_cycle = min(state->duty_cycle, state->period); 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic int sl28cpld_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, 1218c2ecf20Sopenharmony_ci const struct pwm_state *state) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci struct sl28cpld_pwm *priv = sl28cpld_pwm_from_chip(chip); 1248c2ecf20Sopenharmony_ci unsigned int cycle, prescaler; 1258c2ecf20Sopenharmony_ci bool write_duty_cycle_first; 1268c2ecf20Sopenharmony_ci int ret; 1278c2ecf20Sopenharmony_ci u8 ctrl; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci /* Polarity inversion is not supported */ 1308c2ecf20Sopenharmony_ci if (state->polarity != PWM_POLARITY_NORMAL) 1318c2ecf20Sopenharmony_ci return -EINVAL; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci /* 1348c2ecf20Sopenharmony_ci * Calculate the prescaler. Pick the biggest period that isn't 1358c2ecf20Sopenharmony_ci * bigger than the requested period. 1368c2ecf20Sopenharmony_ci */ 1378c2ecf20Sopenharmony_ci prescaler = DIV_ROUND_UP_ULL(SL28CPLD_PWM_PERIOD(0), state->period); 1388c2ecf20Sopenharmony_ci prescaler = order_base_2(prescaler); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci if (prescaler > field_max(SL28CPLD_PWM_CTRL_PRESCALER_MASK)) 1418c2ecf20Sopenharmony_ci return -ERANGE; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci ctrl = FIELD_PREP(SL28CPLD_PWM_CTRL_PRESCALER_MASK, prescaler); 1448c2ecf20Sopenharmony_ci if (state->enabled) 1458c2ecf20Sopenharmony_ci ctrl |= SL28CPLD_PWM_CTRL_ENABLE; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci cycle = SL28CPLD_PWM_FROM_DUTY_CYCLE(state->duty_cycle); 1488c2ecf20Sopenharmony_ci cycle = min_t(unsigned int, cycle, SL28CPLD_PWM_MAX_DUTY_CYCLE(prescaler)); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci /* 1518c2ecf20Sopenharmony_ci * Work around the hardware limitation. See also above. Trap 100% duty 1528c2ecf20Sopenharmony_ci * cycle if the prescaler is 0. Set prescaler to 1 instead. We don't 1538c2ecf20Sopenharmony_ci * care about the frequency because its "all-one" in either case. 1548c2ecf20Sopenharmony_ci * 1558c2ecf20Sopenharmony_ci * We don't need to check the actual prescaler setting, because only 1568c2ecf20Sopenharmony_ci * if the prescaler is 0 we can have this particular value. 1578c2ecf20Sopenharmony_ci */ 1588c2ecf20Sopenharmony_ci if (cycle == SL28CPLD_PWM_MAX_DUTY_CYCLE(0)) { 1598c2ecf20Sopenharmony_ci ctrl &= ~SL28CPLD_PWM_CTRL_PRESCALER_MASK; 1608c2ecf20Sopenharmony_ci ctrl |= FIELD_PREP(SL28CPLD_PWM_CTRL_PRESCALER_MASK, 1); 1618c2ecf20Sopenharmony_ci cycle = SL28CPLD_PWM_MAX_DUTY_CYCLE(1); 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci /* 1658c2ecf20Sopenharmony_ci * To avoid glitches when we switch the prescaler, we have to make sure 1668c2ecf20Sopenharmony_ci * we have a valid duty cycle for the new mode. 1678c2ecf20Sopenharmony_ci * 1688c2ecf20Sopenharmony_ci * Take the current prescaler (or the current period length) into 1698c2ecf20Sopenharmony_ci * account to decide whether we have to write the duty cycle or the new 1708c2ecf20Sopenharmony_ci * prescaler first. If the period length is decreasing we have to 1718c2ecf20Sopenharmony_ci * write the duty cycle first. 1728c2ecf20Sopenharmony_ci */ 1738c2ecf20Sopenharmony_ci write_duty_cycle_first = pwm->state.period > state->period; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci if (write_duty_cycle_first) { 1768c2ecf20Sopenharmony_ci ret = sl28cpld_pwm_write(priv, SL28CPLD_PWM_CYCLE, cycle); 1778c2ecf20Sopenharmony_ci if (ret) 1788c2ecf20Sopenharmony_ci return ret; 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci ret = sl28cpld_pwm_write(priv, SL28CPLD_PWM_CTRL, ctrl); 1828c2ecf20Sopenharmony_ci if (ret) 1838c2ecf20Sopenharmony_ci return ret; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci if (!write_duty_cycle_first) { 1868c2ecf20Sopenharmony_ci ret = sl28cpld_pwm_write(priv, SL28CPLD_PWM_CYCLE, cycle); 1878c2ecf20Sopenharmony_ci if (ret) 1888c2ecf20Sopenharmony_ci return ret; 1898c2ecf20Sopenharmony_ci } 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci return 0; 1928c2ecf20Sopenharmony_ci} 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_cistatic const struct pwm_ops sl28cpld_pwm_ops = { 1958c2ecf20Sopenharmony_ci .apply = sl28cpld_pwm_apply, 1968c2ecf20Sopenharmony_ci .get_state = sl28cpld_pwm_get_state, 1978c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 1988c2ecf20Sopenharmony_ci}; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_cistatic int sl28cpld_pwm_probe(struct platform_device *pdev) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci struct sl28cpld_pwm *priv; 2038c2ecf20Sopenharmony_ci struct pwm_chip *chip; 2048c2ecf20Sopenharmony_ci int ret; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci if (!pdev->dev.parent) { 2078c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "no parent device\n"); 2088c2ecf20Sopenharmony_ci return -ENODEV; 2098c2ecf20Sopenharmony_ci } 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 2128c2ecf20Sopenharmony_ci if (!priv) 2138c2ecf20Sopenharmony_ci return -ENOMEM; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci priv->regmap = dev_get_regmap(pdev->dev.parent, NULL); 2168c2ecf20Sopenharmony_ci if (!priv->regmap) { 2178c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "could not get parent regmap\n"); 2188c2ecf20Sopenharmony_ci return -ENODEV; 2198c2ecf20Sopenharmony_ci } 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci ret = device_property_read_u32(&pdev->dev, "reg", &priv->offset); 2228c2ecf20Sopenharmony_ci if (ret) { 2238c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "no 'reg' property found (%pe)\n", 2248c2ecf20Sopenharmony_ci ERR_PTR(ret)); 2258c2ecf20Sopenharmony_ci return -EINVAL; 2268c2ecf20Sopenharmony_ci } 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci /* Initialize the pwm_chip structure */ 2298c2ecf20Sopenharmony_ci chip = &priv->pwm_chip; 2308c2ecf20Sopenharmony_ci chip->dev = &pdev->dev; 2318c2ecf20Sopenharmony_ci chip->ops = &sl28cpld_pwm_ops; 2328c2ecf20Sopenharmony_ci chip->base = -1; 2338c2ecf20Sopenharmony_ci chip->npwm = 1; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci ret = pwmchip_add(&priv->pwm_chip); 2368c2ecf20Sopenharmony_ci if (ret) { 2378c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to add PWM chip (%pe)", 2388c2ecf20Sopenharmony_ci ERR_PTR(ret)); 2398c2ecf20Sopenharmony_ci return ret; 2408c2ecf20Sopenharmony_ci } 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, priv); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci return 0; 2458c2ecf20Sopenharmony_ci} 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_cistatic int sl28cpld_pwm_remove(struct platform_device *pdev) 2488c2ecf20Sopenharmony_ci{ 2498c2ecf20Sopenharmony_ci struct sl28cpld_pwm *priv = platform_get_drvdata(pdev); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci return pwmchip_remove(&priv->pwm_chip); 2528c2ecf20Sopenharmony_ci} 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_cistatic const struct of_device_id sl28cpld_pwm_of_match[] = { 2558c2ecf20Sopenharmony_ci { .compatible = "kontron,sl28cpld-pwm" }, 2568c2ecf20Sopenharmony_ci {} 2578c2ecf20Sopenharmony_ci}; 2588c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, sl28cpld_pwm_of_match); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_cistatic struct platform_driver sl28cpld_pwm_driver = { 2618c2ecf20Sopenharmony_ci .probe = sl28cpld_pwm_probe, 2628c2ecf20Sopenharmony_ci .remove = sl28cpld_pwm_remove, 2638c2ecf20Sopenharmony_ci .driver = { 2648c2ecf20Sopenharmony_ci .name = "sl28cpld-pwm", 2658c2ecf20Sopenharmony_ci .of_match_table = sl28cpld_pwm_of_match, 2668c2ecf20Sopenharmony_ci }, 2678c2ecf20Sopenharmony_ci}; 2688c2ecf20Sopenharmony_cimodule_platform_driver(sl28cpld_pwm_driver); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("sl28cpld PWM Driver"); 2718c2ecf20Sopenharmony_ciMODULE_AUTHOR("Michael Walle <michael@walle.cc>"); 2728c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 273