1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2024 Liebherr-Electronics and Drives GmbH 4 * 5 * Reference Manual : https://www.nxp.com/docs/en/data-sheet/MC33XS2410.pdf 6 * 7 * Limitations: 8 * - Supports frequencies between 0.5Hz and 2048Hz with following steps: 9 * - 0.5 Hz steps from 0.5 Hz to 32 Hz 10 * - 2 Hz steps from 2 Hz to 128 Hz 11 * - 8 Hz steps from 8 Hz to 512 Hz 12 * - 32 Hz steps from 32 Hz to 2048 Hz 13 * - Cannot generate a 0 % duty cycle. 14 * - Always produces low output if disabled. 15 * - Configuration isn't atomic. When changing polarity, duty cycle or period 16 * the data is taken immediately, counters not being affected, resulting in a 17 * behavior of the output pin that is neither the old nor the new state, 18 * rather something in between. 19 */ 20 21 #include <linux/bitfield.h> 22 #include <linux/delay.h> 23 #include <linux/err.h> 24 #include <linux/math64.h> 25 #include <linux/minmax.h> 26 #include <linux/module.h> 27 #include <linux/of.h> 28 #include <linux/pwm.h> 29 30 #include <linux/spi/spi.h> 31 32 #define MC33XS2410_GLB_CTRL 0x00 33 #define MC33XS2410_GLB_CTRL_MODE GENMASK(7, 6) 34 #define MC33XS2410_GLB_CTRL_MODE_NORMAL FIELD_PREP(MC33XS2410_GLB_CTRL_MODE, 1) 35 36 #define MC33XS2410_PWM_CTRL1 0x05 37 /* chan in { 1 ... 4 } */ 38 #define MC33XS2410_PWM_CTRL1_POL_INV(chan) BIT((chan) + 1) 39 40 #define MC33XS2410_PWM_CTRL3 0x07 41 /* chan in { 1 ... 4 } */ 42 #define MC33XS2410_PWM_CTRL3_EN(chan) BIT(4 + (chan) - 1) 43 44 /* chan in { 1 ... 4 } */ 45 #define MC33XS2410_PWM_FREQ(chan) (0x08 + (chan) - 1) 46 #define MC33XS2410_PWM_FREQ_STEP GENMASK(7, 6) 47 #define MC33XS2410_PWM_FREQ_COUNT GENMASK(5, 0) 48 49 /* chan in { 1 ... 4 } */ 50 #define MC33XS2410_PWM_DC(chan) (0x0c + (chan) - 1) 51 52 #define MC33XS2410_WDT 0x14 53 54 #define MC33XS2410_PWM_MIN_PERIOD 488282 55 /* step in { 0 ... 3 } */ 56 #define MC33XS2410_PWM_MAX_PERIOD(step) (2000000000 >> (2 * (step))) 57 58 #define MC33XS2410_FRAME_IN_ADDR GENMASK(15, 8) 59 #define MC33XS2410_FRAME_IN_DATA GENMASK(7, 0) 60 #define MC33XS2410_FRAME_IN_ADDR_WR BIT(7) 61 #define MC33XS2410_FRAME_IN_DATA_RD BIT(7) 62 #define MC33XS2410_FRAME_OUT_DATA GENMASK(13, 0) 63 64 #define MC33XS2410_MAX_TRANSFERS 5 65 66 static int mc33xs2410_write_regs(struct spi_device *spi, u8 *reg, u8 *val, 67 unsigned int len) 68 { 69 u16 tx[MC33XS2410_MAX_TRANSFERS]; 70 int i; 71 72 if (len > MC33XS2410_MAX_TRANSFERS) 73 return -EINVAL; 74 75 for (i = 0; i < len; i++) 76 tx[i] = FIELD_PREP(MC33XS2410_FRAME_IN_DATA, val[i]) | 77 FIELD_PREP(MC33XS2410_FRAME_IN_ADDR, 78 MC33XS2410_FRAME_IN_ADDR_WR | reg[i]); 79 80 return spi_write(spi, tx, len * 2); 81 } 82 83 static int mc33xs2410_read_regs(struct spi_device *spi, u8 *reg, u8 flag, 84 u16 *val, unsigned int len) 85 { 86 u16 tx[MC33XS2410_MAX_TRANSFERS]; 87 u16 rx[MC33XS2410_MAX_TRANSFERS]; 88 struct spi_transfer t = { 89 .tx_buf = tx, 90 .rx_buf = rx, 91 }; 92 int i, ret; 93 94 len++; 95 if (len > MC33XS2410_MAX_TRANSFERS) 96 return -EINVAL; 97 98 t.len = len * 2; 99 for (i = 0; i < len - 1; i++) 100 tx[i] = FIELD_PREP(MC33XS2410_FRAME_IN_DATA, flag) | 101 FIELD_PREP(MC33XS2410_FRAME_IN_ADDR, reg[i]); 102 103 ret = spi_sync_transfer(spi, &t, 1); 104 if (ret < 0) 105 return ret; 106 107 for (i = 1; i < len; i++) 108 val[i - 1] = FIELD_GET(MC33XS2410_FRAME_OUT_DATA, rx[i]); 109 110 return 0; 111 } 112 113 static int mc33xs2410_write_reg(struct spi_device *spi, u8 reg, u8 val) 114 { 115 return mc33xs2410_write_regs(spi, ®, &val, 1); 116 } 117 118 static int mc33xs2410_read_reg(struct spi_device *spi, u8 reg, u16 *val, u8 flag) 119 { 120 return mc33xs2410_read_regs(spi, ®, flag, val, 1); 121 } 122 123 static int mc33xs2410_read_reg_ctrl(struct spi_device *spi, u8 reg, u16 *val) 124 { 125 return mc33xs2410_read_reg(spi, reg, val, MC33XS2410_FRAME_IN_DATA_RD); 126 } 127 128 static int mc33xs2410_modify_reg(struct spi_device *spi, u8 reg, u8 mask, u8 val) 129 { 130 u16 tmp; 131 int ret; 132 133 ret = mc33xs2410_read_reg_ctrl(spi, reg, &tmp); 134 if (ret < 0) 135 return ret; 136 137 tmp &= ~mask; 138 tmp |= val & mask; 139 140 return mc33xs2410_write_reg(spi, reg, tmp); 141 } 142 143 static u8 mc33xs2410_pwm_get_freq(u64 period) 144 { 145 u8 step, count; 146 147 /* 148 * Check which step [0 .. 3] is appropriate for the given period. The 149 * period ranges for the different step values overlap. Prefer big step 150 * values as these allow more finegrained period and duty cycle 151 * selection. 152 */ 153 154 switch (period) { 155 case MC33XS2410_PWM_MIN_PERIOD ... MC33XS2410_PWM_MAX_PERIOD(3): 156 step = 3; 157 break; 158 case MC33XS2410_PWM_MAX_PERIOD(3) + 1 ... MC33XS2410_PWM_MAX_PERIOD(2): 159 step = 2; 160 break; 161 case MC33XS2410_PWM_MAX_PERIOD(2) + 1 ... MC33XS2410_PWM_MAX_PERIOD(1): 162 step = 1; 163 break; 164 case MC33XS2410_PWM_MAX_PERIOD(1) + 1 ... MC33XS2410_PWM_MAX_PERIOD(0): 165 step = 0; 166 break; 167 } 168 169 /* 170 * Round up here because a higher count results in a higher frequency 171 * and so a smaller period. 172 */ 173 count = DIV_ROUND_UP((u32)MC33XS2410_PWM_MAX_PERIOD(step), (u32)period); 174 return FIELD_PREP(MC33XS2410_PWM_FREQ_STEP, step) | 175 FIELD_PREP(MC33XS2410_PWM_FREQ_COUNT, count - 1); 176 } 177 178 static u64 mc33xs2410_pwm_get_period(u8 reg) 179 { 180 u32 doubled_freq, code, doubled_steps; 181 182 /* 183 * steps: 184 * - 0 = 0.5Hz 185 * - 1 = 2Hz 186 * - 2 = 8Hz 187 * - 3 = 32Hz 188 * frequency = (code + 1) x steps. 189 * 190 * To avoid losing precision in case steps value is zero, scale the 191 * steps value for now by two and keep it in mind when calculating the 192 * period that the frequency had been doubled. 193 */ 194 doubled_steps = 1 << (FIELD_GET(MC33XS2410_PWM_FREQ_STEP, reg) * 2); 195 code = FIELD_GET(MC33XS2410_PWM_FREQ_COUNT, reg); 196 doubled_freq = (code + 1) * doubled_steps; 197 198 /* Convert frequency to period, considering the doubled frequency. */ 199 return DIV_ROUND_UP(2 * NSEC_PER_SEC, doubled_freq); 200 } 201 202 /* 203 * The hardware cannot generate a 0% relative duty cycle for normal and inversed 204 * polarity. For normal polarity, the channel must be disabled, the device then 205 * emits a constant low signal. 206 * For inverted polarity, the channel must be enabled, the polarity must be set 207 * to normal and the relative duty cylce must be set to 100%. The device then 208 * emits a constant high signal. 209 */ 210 static int mc33xs2410_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, 211 const struct pwm_state *state) 212 { 213 struct spi_device *spi = pwmchip_get_drvdata(chip); 214 u8 reg[4] = { 215 MC33XS2410_PWM_FREQ(pwm->hwpwm + 1), 216 MC33XS2410_PWM_DC(pwm->hwpwm + 1), 217 MC33XS2410_PWM_CTRL1, 218 MC33XS2410_PWM_CTRL3 219 }; 220 u64 period, duty_cycle; 221 int ret, rel_dc; 222 u16 rd_val[2]; 223 u8 wr_val[4]; 224 u8 mask; 225 226 period = min(state->period, MC33XS2410_PWM_MAX_PERIOD(0)); 227 if (period < MC33XS2410_PWM_MIN_PERIOD) 228 return -EINVAL; 229 230 ret = mc33xs2410_read_regs(spi, ®[2], MC33XS2410_FRAME_IN_DATA_RD, rd_val, 2); 231 if (ret < 0) 232 return ret; 233 234 /* Frequency */ 235 wr_val[0] = mc33xs2410_pwm_get_freq(period); 236 /* Continue calculations with the possibly truncated period */ 237 period = mc33xs2410_pwm_get_period(wr_val[0]); 238 239 /* Duty cycle */ 240 duty_cycle = min(period, state->duty_cycle); 241 rel_dc = div64_u64(duty_cycle * 256, period) - 1; 242 if (rel_dc >= 0) 243 wr_val[1] = rel_dc; 244 else if (state->polarity == PWM_POLARITY_NORMAL) 245 wr_val[1] = 0; 246 else 247 wr_val[1] = 255; 248 249 /* Polarity */ 250 mask = MC33XS2410_PWM_CTRL1_POL_INV(pwm->hwpwm + 1); 251 if (state->polarity == PWM_POLARITY_INVERSED && rel_dc >= 0) 252 wr_val[2] = rd_val[0] | mask; 253 else 254 wr_val[2] = rd_val[0] & ~mask; 255 256 /* Enable */ 257 mask = MC33XS2410_PWM_CTRL3_EN(pwm->hwpwm + 1); 258 if (state->enabled && 259 !(state->polarity == PWM_POLARITY_NORMAL && rel_dc < 0)) 260 wr_val[3] = rd_val[1] | mask; 261 else 262 wr_val[3] = rd_val[1] & ~mask; 263 264 return mc33xs2410_write_regs(spi, reg, wr_val, 4); 265 } 266 267 static int mc33xs2410_pwm_get_state(struct pwm_chip *chip, 268 struct pwm_device *pwm, 269 struct pwm_state *state) 270 { 271 struct spi_device *spi = pwmchip_get_drvdata(chip); 272 u8 reg[4] = { 273 MC33XS2410_PWM_FREQ(pwm->hwpwm + 1), 274 MC33XS2410_PWM_DC(pwm->hwpwm + 1), 275 MC33XS2410_PWM_CTRL1, 276 MC33XS2410_PWM_CTRL3, 277 }; 278 u16 val[4]; 279 int ret; 280 281 ret = mc33xs2410_read_regs(spi, reg, MC33XS2410_FRAME_IN_DATA_RD, val, 282 ARRAY_SIZE(reg)); 283 if (ret < 0) 284 return ret; 285 286 state->period = mc33xs2410_pwm_get_period(val[0]); 287 state->polarity = (val[2] & MC33XS2410_PWM_CTRL1_POL_INV(pwm->hwpwm + 1)) ? 288 PWM_POLARITY_INVERSED : PWM_POLARITY_NORMAL; 289 state->enabled = !!(val[3] & MC33XS2410_PWM_CTRL3_EN(pwm->hwpwm + 1)); 290 state->duty_cycle = DIV_ROUND_UP_ULL((val[1] + 1) * state->period, 256); 291 292 return 0; 293 } 294 295 static const struct pwm_ops mc33xs2410_pwm_ops = { 296 .apply = mc33xs2410_pwm_apply, 297 .get_state = mc33xs2410_pwm_get_state, 298 }; 299 300 static int mc33xs2410_reset(struct device *dev) 301 { 302 struct gpio_desc *reset_gpio; 303 304 reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); 305 if (IS_ERR_OR_NULL(reset_gpio)) 306 return PTR_ERR_OR_ZERO(reset_gpio); 307 308 /* Wake-up time */ 309 fsleep(10000); 310 311 return 0; 312 } 313 314 static int mc33xs2410_probe(struct spi_device *spi) 315 { 316 struct device *dev = &spi->dev; 317 struct pwm_chip *chip; 318 int ret; 319 320 chip = devm_pwmchip_alloc(dev, 4, 0); 321 if (IS_ERR(chip)) 322 return PTR_ERR(chip); 323 324 spi->bits_per_word = 16; 325 spi->mode |= SPI_CS_WORD; 326 ret = spi_setup(spi); 327 if (ret < 0) 328 return ret; 329 330 pwmchip_set_drvdata(chip, spi); 331 chip->ops = &mc33xs2410_pwm_ops; 332 333 /* 334 * Deasserts the reset of the device. Shouldn't change the output signal 335 * if the device was setup prior to probing. 336 */ 337 ret = mc33xs2410_reset(dev); 338 if (ret) 339 return ret; 340 341 /* 342 * Disable watchdog and keep in mind that the watchdog won't trigger a 343 * reset of the machine when running into an timeout, instead the 344 * control over the outputs is handed over to the INx input logic 345 * signals of the device. Disabling it here just deactivates this 346 * feature until a proper solution is found. 347 */ 348 ret = mc33xs2410_write_reg(spi, MC33XS2410_WDT, 0x0); 349 if (ret < 0) 350 return dev_err_probe(dev, ret, "Failed to disable watchdog\n"); 351 352 /* Transition to normal mode */ 353 ret = mc33xs2410_modify_reg(spi, MC33XS2410_GLB_CTRL, 354 MC33XS2410_GLB_CTRL_MODE, 355 MC33XS2410_GLB_CTRL_MODE_NORMAL); 356 if (ret < 0) 357 return dev_err_probe(dev, ret, 358 "Failed to transition to normal mode\n"); 359 360 ret = devm_pwmchip_add(dev, chip); 361 if (ret < 0) 362 return dev_err_probe(dev, ret, "Failed to add pwm chip\n"); 363 364 return 0; 365 } 366 367 static const struct spi_device_id mc33xs2410_spi_id[] = { 368 { "mc33xs2410" }, 369 { } 370 }; 371 MODULE_DEVICE_TABLE(spi, mc33xs2410_spi_id); 372 373 static const struct of_device_id mc33xs2410_of_match[] = { 374 { .compatible = "nxp,mc33xs2410" }, 375 { } 376 }; 377 MODULE_DEVICE_TABLE(of, mc33xs2410_of_match); 378 379 static struct spi_driver mc33xs2410_driver = { 380 .driver = { 381 .name = "mc33xs2410-pwm", 382 .of_match_table = mc33xs2410_of_match, 383 }, 384 .probe = mc33xs2410_probe, 385 .id_table = mc33xs2410_spi_id, 386 }; 387 module_spi_driver(mc33xs2410_driver); 388 389 MODULE_DESCRIPTION("NXP MC33XS2410 high-side switch driver"); 390 MODULE_AUTHOR("Dimitri Fedrau <dimitri.fedrau@liebherr.com>"); 391 MODULE_LICENSE("GPL"); 392