pwm-airoha.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright 2022 Markus Gothe <markus.gothe@genexis.eu>
  4. * Copyright 2025 Christian Marangi <ansuelsmth@gmail.com>
  5. *
  6. * Limitations:
  7. * - Only 8 concurrent waveform generators are available for 8 combinations of
  8. * duty_cycle and period. Waveform generators are shared between 16 GPIO
  9. * pins and 17 SIPO GPIO pins.
  10. * - Supports only normal polarity.
  11. * - On configuration the currently running period is completed.
  12. * - Minimum supported period is 4 ms
  13. * - Maximum supported period is 1s
  14. */
  15. #include <linux/array_size.h>
  16. #include <linux/bitfield.h>
  17. #include <linux/bitmap.h>
  18. #include <linux/err.h>
  19. #include <linux/io.h>
  20. #include <linux/iopoll.h>
  21. #include <linux/math64.h>
  22. #include <linux/mfd/syscon.h>
  23. #include <linux/module.h>
  24. #include <linux/mod_devicetable.h>
  25. #include <linux/platform_device.h>
  26. #include <linux/pwm.h>
  27. #include <linux/regmap.h>
  28. #include <linux/types.h>
  29. #define AIROHA_PWM_REG_SGPIO_LED_DATA 0x0024
  30. #define AIROHA_PWM_SGPIO_LED_DATA_SHIFT_FLAG BIT(31)
  31. #define AIROHA_PWM_SGPIO_LED_DATA_DATA GENMASK(16, 0)
  32. #define AIROHA_PWM_REG_SGPIO_CLK_DIVR 0x0028
  33. #define AIROHA_PWM_SGPIO_CLK_DIVR GENMASK(1, 0)
  34. #define AIROHA_PWM_SGPIO_CLK_DIVR_32 FIELD_PREP_CONST(AIROHA_PWM_SGPIO_CLK_DIVR, 3)
  35. #define AIROHA_PWM_SGPIO_CLK_DIVR_16 FIELD_PREP_CONST(AIROHA_PWM_SGPIO_CLK_DIVR, 2)
  36. #define AIROHA_PWM_SGPIO_CLK_DIVR_8 FIELD_PREP_CONST(AIROHA_PWM_SGPIO_CLK_DIVR, 1)
  37. #define AIROHA_PWM_SGPIO_CLK_DIVR_4 FIELD_PREP_CONST(AIROHA_PWM_SGPIO_CLK_DIVR, 0)
  38. #define AIROHA_PWM_REG_SGPIO_CLK_DLY 0x002c
  39. #define AIROHA_PWM_REG_SIPO_FLASH_MODE_CFG 0x0030
  40. #define AIROHA_PWM_SERIAL_GPIO_FLASH_MODE BIT(1)
  41. #define AIROHA_PWM_SERIAL_GPIO_MODE_74HC164 BIT(0)
  42. #define AIROHA_PWM_REG_GPIO_FLASH_PRD_SET(_n) (0x003c + (4 * (_n)))
  43. #define AIROHA_PWM_REG_GPIO_FLASH_PRD_SHIFT(_n) (16 * (_n))
  44. #define AIROHA_PWM_GPIO_FLASH_PRD_LOW GENMASK(15, 8)
  45. #define AIROHA_PWM_GPIO_FLASH_PRD_HIGH GENMASK(7, 0)
  46. #define AIROHA_PWM_REG_GPIO_FLASH_MAP(_n) (0x004c + (4 * (_n)))
  47. #define AIROHA_PWM_REG_GPIO_FLASH_MAP_SHIFT(_n) (4 * (_n))
  48. #define AIROHA_PWM_GPIO_FLASH_EN BIT(3)
  49. #define AIROHA_PWM_GPIO_FLASH_SET_ID GENMASK(2, 0)
  50. /* Register map is equal to GPIO flash map */
  51. #define AIROHA_PWM_REG_SIPO_FLASH_MAP(_n) (0x0054 + (4 * (_n)))
  52. #define AIROHA_PWM_REG_CYCLE_CFG_VALUE(_n) (0x0098 + (4 * (_n)))
  53. #define AIROHA_PWM_REG_CYCLE_CFG_SHIFT(_n) (8 * (_n))
  54. #define AIROHA_PWM_WAVE_GEN_CYCLE GENMASK(7, 0)
  55. /* GPIO/SIPO flash map handles 8 pins in one register */
  56. #define AIROHA_PWM_PINS_PER_FLASH_MAP 8
  57. /* Cycle(Period) registers handles 4 generators in one 32-bit register */
  58. #define AIROHA_PWM_BUCKET_PER_CYCLE_CFG 4
  59. /* Flash(Duty) producer handles 2 generators in one 32-bit register */
  60. #define AIROHA_PWM_BUCKET_PER_FLASH_PROD 2
  61. #define AIROHA_PWM_NUM_BUCKETS 8
  62. /*
  63. * The first 16 GPIO pins, GPIO0-GPIO15, are mapped into 16 PWM channels, 0-15.
  64. * The SIPO GPIO pins are 17 pins which are mapped into 17 PWM channels, 16-32.
  65. * However, we've only got 8 concurrent waveform generators and can therefore
  66. * only use up to 8 different combinations of duty cycle and period at a time.
  67. */
  68. #define AIROHA_PWM_NUM_GPIO 16
  69. #define AIROHA_PWM_NUM_SIPO 17
  70. #define AIROHA_PWM_MAX_CHANNELS (AIROHA_PWM_NUM_GPIO + AIROHA_PWM_NUM_SIPO)
  71. struct airoha_pwm_bucket {
  72. /* Concurrent access protected by PWM core */
  73. int used;
  74. u32 period_ticks;
  75. u32 duty_ticks;
  76. };
  77. struct airoha_pwm {
  78. struct regmap *regmap;
  79. DECLARE_BITMAP(initialized, AIROHA_PWM_MAX_CHANNELS);
  80. struct airoha_pwm_bucket buckets[AIROHA_PWM_NUM_BUCKETS];
  81. /* Cache bucket used by each pwm channel */
  82. u8 channel_bucket[AIROHA_PWM_MAX_CHANNELS];
  83. };
  84. /* The PWM hardware supports periods between 4 ms and 1 s */
  85. #define AIROHA_PWM_PERIOD_TICK_NS (4 * NSEC_PER_MSEC)
  86. #define AIROHA_PWM_PERIOD_MAX_NS (1 * NSEC_PER_SEC)
  87. /* It is represented internally as 1/250 s between 1 and 250. Unit is ticks. */
  88. #define AIROHA_PWM_PERIOD_MIN 1
  89. #define AIROHA_PWM_PERIOD_MAX 250
  90. /* Duty cycle is relative with 255 corresponding to 100% */
  91. #define AIROHA_PWM_DUTY_FULL 255
  92. static void airoha_pwm_get_flash_map_addr_and_shift(unsigned int hwpwm,
  93. u32 *addr, u32 *shift)
  94. {
  95. unsigned int offset, hwpwm_bit;
  96. if (hwpwm >= AIROHA_PWM_NUM_GPIO) {
  97. unsigned int sipohwpwm = hwpwm - AIROHA_PWM_NUM_GPIO;
  98. offset = sipohwpwm / AIROHA_PWM_PINS_PER_FLASH_MAP;
  99. hwpwm_bit = sipohwpwm % AIROHA_PWM_PINS_PER_FLASH_MAP;
  100. /* One FLASH_MAP register handles 8 pins */
  101. *shift = AIROHA_PWM_REG_GPIO_FLASH_MAP_SHIFT(hwpwm_bit);
  102. *addr = AIROHA_PWM_REG_SIPO_FLASH_MAP(offset);
  103. } else {
  104. offset = hwpwm / AIROHA_PWM_PINS_PER_FLASH_MAP;
  105. hwpwm_bit = hwpwm % AIROHA_PWM_PINS_PER_FLASH_MAP;
  106. /* One FLASH_MAP register handles 8 pins */
  107. *shift = AIROHA_PWM_REG_GPIO_FLASH_MAP_SHIFT(hwpwm_bit);
  108. *addr = AIROHA_PWM_REG_GPIO_FLASH_MAP(offset);
  109. }
  110. }
  111. static u32 airoha_pwm_get_period_ticks_from_ns(u32 period_ns)
  112. {
  113. return period_ns / AIROHA_PWM_PERIOD_TICK_NS;
  114. }
  115. static u32 airoha_pwm_get_duty_ticks_from_ns(u32 period_ns, u32 duty_ns)
  116. {
  117. return mul_u64_u32_div(duty_ns, AIROHA_PWM_DUTY_FULL, period_ns);
  118. }
  119. static u32 airoha_pwm_get_period_ns_from_ticks(u32 period_tick)
  120. {
  121. return period_tick * AIROHA_PWM_PERIOD_TICK_NS;
  122. }
  123. static u32 airoha_pwm_get_duty_ns_from_ticks(u32 period_tick, u32 duty_tick)
  124. {
  125. u32 period_ns = period_tick * AIROHA_PWM_PERIOD_TICK_NS;
  126. /*
  127. * Overflow can't occur in multiplication as duty_tick is just 8 bit
  128. * and period_ns is clamped to AIROHA_PWM_PERIOD_MAX_NS and fit in a
  129. * u64.
  130. */
  131. return DIV_U64_ROUND_UP(duty_tick * period_ns, AIROHA_PWM_DUTY_FULL);
  132. }
  133. static int airoha_pwm_get_bucket(struct airoha_pwm *pc, int bucket,
  134. u64 *period_ns, u64 *duty_ns)
  135. {
  136. struct regmap *map = pc->regmap;
  137. u32 period_tick, duty_tick;
  138. unsigned int offset;
  139. u32 shift, val;
  140. int ret;
  141. offset = bucket / AIROHA_PWM_BUCKET_PER_CYCLE_CFG;
  142. shift = bucket % AIROHA_PWM_BUCKET_PER_CYCLE_CFG;
  143. shift = AIROHA_PWM_REG_CYCLE_CFG_SHIFT(shift);
  144. ret = regmap_read(map, AIROHA_PWM_REG_CYCLE_CFG_VALUE(offset), &val);
  145. if (ret)
  146. return ret;
  147. period_tick = FIELD_GET(AIROHA_PWM_WAVE_GEN_CYCLE, val >> shift);
  148. *period_ns = airoha_pwm_get_period_ns_from_ticks(period_tick);
  149. offset = bucket / AIROHA_PWM_BUCKET_PER_FLASH_PROD;
  150. shift = bucket % AIROHA_PWM_BUCKET_PER_FLASH_PROD;
  151. shift = AIROHA_PWM_REG_GPIO_FLASH_PRD_SHIFT(shift);
  152. ret = regmap_read(map, AIROHA_PWM_REG_GPIO_FLASH_PRD_SET(offset),
  153. &val);
  154. if (ret)
  155. return ret;
  156. duty_tick = FIELD_GET(AIROHA_PWM_GPIO_FLASH_PRD_HIGH, val >> shift);
  157. *duty_ns = airoha_pwm_get_duty_ns_from_ticks(period_tick, duty_tick);
  158. return 0;
  159. }
  160. static int airoha_pwm_get_generator(struct airoha_pwm *pc, u32 duty_ticks,
  161. u32 period_ticks)
  162. {
  163. int best = -ENOENT, unused = -ENOENT;
  164. u32 duty_ns, best_duty_ns = 0;
  165. u32 best_period_ticks = 0;
  166. unsigned int i;
  167. duty_ns = airoha_pwm_get_duty_ns_from_ticks(period_ticks, duty_ticks);
  168. for (i = 0; i < ARRAY_SIZE(pc->buckets); i++) {
  169. struct airoha_pwm_bucket *bucket = &pc->buckets[i];
  170. u32 bucket_period_ticks = bucket->period_ticks;
  171. u32 bucket_duty_ticks = bucket->duty_ticks;
  172. /* If found, save an unused bucket to return it later */
  173. if (!bucket->used) {
  174. unused = i;
  175. continue;
  176. }
  177. /* We found a matching bucket, exit early */
  178. if (duty_ticks == bucket_duty_ticks &&
  179. period_ticks == bucket_period_ticks)
  180. return i;
  181. /*
  182. * Unlike duty cycle zero, which can be handled by
  183. * disabling PWM, a generator is needed for full duty
  184. * cycle but it can be reused regardless of period
  185. */
  186. if (duty_ticks == AIROHA_PWM_DUTY_FULL &&
  187. bucket_duty_ticks == AIROHA_PWM_DUTY_FULL)
  188. return i;
  189. /*
  190. * With an unused bucket available, skip searching for
  191. * a bucket to recycle (closer to the requested period/duty)
  192. */
  193. if (unused >= 0)
  194. continue;
  195. /* Ignore bucket with invalid period */
  196. if (bucket_period_ticks > period_ticks)
  197. continue;
  198. /*
  199. * Search for a bucket closer to the requested period
  200. * that has the maximal possible period that isn't bigger
  201. * than the requested period. For that period pick the maximal
  202. * duty cycle that isn't bigger than the requested duty_cycle.
  203. */
  204. if (bucket_period_ticks >= best_period_ticks) {
  205. u32 bucket_duty_ns = airoha_pwm_get_duty_ns_from_ticks(bucket_period_ticks,
  206. bucket_duty_ticks);
  207. /* Skip bucket that goes over the requested duty */
  208. if (bucket_duty_ns > duty_ns)
  209. continue;
  210. if (bucket_duty_ns > best_duty_ns) {
  211. best_period_ticks = bucket_period_ticks;
  212. best_duty_ns = bucket_duty_ns;
  213. best = i;
  214. }
  215. }
  216. }
  217. /* Return an unused bucket or the best one found (if ever) */
  218. return unused >= 0 ? unused : best;
  219. }
  220. static void airoha_pwm_release_bucket_config(struct airoha_pwm *pc,
  221. unsigned int hwpwm)
  222. {
  223. int bucket;
  224. /* Nothing to clear, PWM channel never used */
  225. if (!test_bit(hwpwm, pc->initialized))
  226. return;
  227. bucket = pc->channel_bucket[hwpwm];
  228. pc->buckets[bucket].used--;
  229. }
  230. static int airoha_pwm_apply_bucket_config(struct airoha_pwm *pc, unsigned int bucket,
  231. u32 duty_ticks, u32 period_ticks)
  232. {
  233. u32 mask, shift, val;
  234. u32 offset;
  235. int ret;
  236. offset = bucket / AIROHA_PWM_BUCKET_PER_CYCLE_CFG;
  237. shift = bucket % AIROHA_PWM_BUCKET_PER_CYCLE_CFG;
  238. shift = AIROHA_PWM_REG_CYCLE_CFG_SHIFT(shift);
  239. /* Configure frequency divisor */
  240. mask = AIROHA_PWM_WAVE_GEN_CYCLE << shift;
  241. val = FIELD_PREP(AIROHA_PWM_WAVE_GEN_CYCLE, period_ticks) << shift;
  242. ret = regmap_update_bits(pc->regmap, AIROHA_PWM_REG_CYCLE_CFG_VALUE(offset),
  243. mask, val);
  244. if (ret)
  245. return ret;
  246. offset = bucket / AIROHA_PWM_BUCKET_PER_FLASH_PROD;
  247. shift = bucket % AIROHA_PWM_BUCKET_PER_FLASH_PROD;
  248. shift = AIROHA_PWM_REG_GPIO_FLASH_PRD_SHIFT(shift);
  249. /* Configure duty cycle */
  250. mask = AIROHA_PWM_GPIO_FLASH_PRD_HIGH << shift;
  251. val = FIELD_PREP(AIROHA_PWM_GPIO_FLASH_PRD_HIGH, duty_ticks) << shift;
  252. ret = regmap_update_bits(pc->regmap, AIROHA_PWM_REG_GPIO_FLASH_PRD_SET(offset),
  253. mask, val);
  254. if (ret)
  255. return ret;
  256. mask = AIROHA_PWM_GPIO_FLASH_PRD_LOW << shift;
  257. val = FIELD_PREP(AIROHA_PWM_GPIO_FLASH_PRD_LOW,
  258. AIROHA_PWM_DUTY_FULL - duty_ticks) << shift;
  259. return regmap_update_bits(pc->regmap, AIROHA_PWM_REG_GPIO_FLASH_PRD_SET(offset),
  260. mask, val);
  261. }
  262. static int airoha_pwm_consume_generator(struct airoha_pwm *pc,
  263. u32 duty_ticks, u32 period_ticks,
  264. unsigned int hwpwm)
  265. {
  266. bool config_bucket = false;
  267. int bucket, ret;
  268. /*
  269. * Search for a bucket that already satisfies duty and period
  270. * or an unused one.
  271. * If not found, -ENOENT is returned.
  272. */
  273. bucket = airoha_pwm_get_generator(pc, duty_ticks, period_ticks);
  274. if (bucket < 0)
  275. return bucket;
  276. /* Release previous used bucket (if any) */
  277. airoha_pwm_release_bucket_config(pc, hwpwm);
  278. if (!pc->buckets[bucket].used)
  279. config_bucket = true;
  280. pc->buckets[bucket].used++;
  281. if (config_bucket) {
  282. pc->buckets[bucket].period_ticks = period_ticks;
  283. pc->buckets[bucket].duty_ticks = duty_ticks;
  284. ret = airoha_pwm_apply_bucket_config(pc, bucket,
  285. duty_ticks,
  286. period_ticks);
  287. if (ret) {
  288. pc->buckets[bucket].used--;
  289. return ret;
  290. }
  291. }
  292. return bucket;
  293. }
  294. static int airoha_pwm_sipo_init(struct airoha_pwm *pc)
  295. {
  296. u32 val;
  297. int ret;
  298. ret = regmap_clear_bits(pc->regmap, AIROHA_PWM_REG_SIPO_FLASH_MODE_CFG,
  299. AIROHA_PWM_SERIAL_GPIO_MODE_74HC164);
  300. if (ret)
  301. return ret;
  302. /* Configure shift register chip clock timings, use 32x divisor */
  303. ret = regmap_write(pc->regmap, AIROHA_PWM_REG_SGPIO_CLK_DIVR,
  304. AIROHA_PWM_SGPIO_CLK_DIVR_32);
  305. if (ret)
  306. return ret;
  307. /*
  308. * Configure the shift register chip clock delay. This needs
  309. * to be configured based on the chip characteristics when the SoC
  310. * apply the shift register configuration.
  311. * This doesn't affect actual PWM operation and is only specific to
  312. * the shift register chip.
  313. *
  314. * For 74HC164 we set it to 0.
  315. *
  316. * For reference, the actual delay applied is the internal clock
  317. * feed to the SGPIO chip + 1.
  318. *
  319. * From documentation is specified that clock delay should not be
  320. * greater than (AIROHA_PWM_REG_SGPIO_CLK_DIVR / 2) - 1.
  321. */
  322. ret = regmap_write(pc->regmap, AIROHA_PWM_REG_SGPIO_CLK_DLY, 0);
  323. if (ret)
  324. return ret;
  325. /*
  326. * It is necessary to explicitly shift out all zeros after muxing
  327. * to initialize the shift register before enabling PWM
  328. * mode because in PWM mode SIPO will not start shifting until
  329. * it needs to output a non-zero value (bit 31 of led_data
  330. * indicates shifting in progress and it must return to zero
  331. * before led_data can be written or PWM mode can be set).
  332. */
  333. ret = regmap_read_poll_timeout(pc->regmap, AIROHA_PWM_REG_SGPIO_LED_DATA, val,
  334. !(val & AIROHA_PWM_SGPIO_LED_DATA_SHIFT_FLAG),
  335. 10, 200 * USEC_PER_MSEC);
  336. if (ret)
  337. return ret;
  338. ret = regmap_clear_bits(pc->regmap, AIROHA_PWM_REG_SGPIO_LED_DATA,
  339. AIROHA_PWM_SGPIO_LED_DATA_DATA);
  340. if (ret)
  341. return ret;
  342. ret = regmap_read_poll_timeout(pc->regmap, AIROHA_PWM_REG_SGPIO_LED_DATA, val,
  343. !(val & AIROHA_PWM_SGPIO_LED_DATA_SHIFT_FLAG),
  344. 10, 200 * USEC_PER_MSEC);
  345. if (ret)
  346. return ret;
  347. /* Set SIPO in PWM mode */
  348. return regmap_set_bits(pc->regmap, AIROHA_PWM_REG_SIPO_FLASH_MODE_CFG,
  349. AIROHA_PWM_SERIAL_GPIO_FLASH_MODE);
  350. }
  351. static int airoha_pwm_config_flash_map(struct airoha_pwm *pc,
  352. unsigned int hwpwm, int index)
  353. {
  354. unsigned int addr;
  355. u32 shift;
  356. int ret;
  357. airoha_pwm_get_flash_map_addr_and_shift(hwpwm, &addr, &shift);
  358. /* negative index means disable PWM channel */
  359. if (index < 0) {
  360. /*
  361. * If we need to disable the PWM, we just put low the
  362. * GPIO. No need to setup buckets.
  363. */
  364. return regmap_clear_bits(pc->regmap, addr,
  365. AIROHA_PWM_GPIO_FLASH_EN << shift);
  366. }
  367. ret = regmap_update_bits(pc->regmap, addr,
  368. AIROHA_PWM_GPIO_FLASH_SET_ID << shift,
  369. FIELD_PREP(AIROHA_PWM_GPIO_FLASH_SET_ID, index) << shift);
  370. if (ret)
  371. return ret;
  372. return regmap_set_bits(pc->regmap, addr, AIROHA_PWM_GPIO_FLASH_EN << shift);
  373. }
  374. static int airoha_pwm_config(struct airoha_pwm *pc, struct pwm_device *pwm,
  375. u32 period_ticks, u32 duty_ticks)
  376. {
  377. unsigned int hwpwm = pwm->hwpwm;
  378. int bucket, ret;
  379. bucket = airoha_pwm_consume_generator(pc, duty_ticks, period_ticks,
  380. hwpwm);
  381. if (bucket < 0)
  382. return bucket;
  383. ret = airoha_pwm_config_flash_map(pc, hwpwm, bucket);
  384. if (ret) {
  385. pc->buckets[bucket].used--;
  386. return ret;
  387. }
  388. __set_bit(hwpwm, pc->initialized);
  389. pc->channel_bucket[hwpwm] = bucket;
  390. /*
  391. * SIPO are special GPIO attached to a shift register chip. The handling
  392. * of this chip is internal to the SoC that takes care of applying the
  393. * values based on the flash map. To apply a new flash map, it's needed
  394. * to trigger a refresh on the shift register chip.
  395. * If a SIPO is getting configuring , always reinit the shift register
  396. * chip to make sure the correct flash map is applied.
  397. * Skip reconfiguring the shift register if the related hwpwm
  398. * is disabled (as it doesn't need to be mapped).
  399. */
  400. if (hwpwm >= AIROHA_PWM_NUM_GPIO) {
  401. ret = airoha_pwm_sipo_init(pc);
  402. if (ret) {
  403. airoha_pwm_release_bucket_config(pc, hwpwm);
  404. return ret;
  405. }
  406. }
  407. return 0;
  408. }
  409. static void airoha_pwm_disable(struct airoha_pwm *pc, struct pwm_device *pwm)
  410. {
  411. /* Disable PWM and release the bucket */
  412. airoha_pwm_config_flash_map(pc, pwm->hwpwm, -1);
  413. airoha_pwm_release_bucket_config(pc, pwm->hwpwm);
  414. __clear_bit(pwm->hwpwm, pc->initialized);
  415. /* If no SIPO is used, disable the shift register chip */
  416. if (!bitmap_read(pc->initialized,
  417. AIROHA_PWM_NUM_GPIO, AIROHA_PWM_NUM_SIPO))
  418. regmap_clear_bits(pc->regmap, AIROHA_PWM_REG_SIPO_FLASH_MODE_CFG,
  419. AIROHA_PWM_SERIAL_GPIO_FLASH_MODE);
  420. }
  421. static int airoha_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
  422. const struct pwm_state *state)
  423. {
  424. struct airoha_pwm *pc = pwmchip_get_drvdata(chip);
  425. u32 period_ticks, duty_ticks;
  426. u32 period_ns, duty_ns;
  427. if (!state->enabled) {
  428. airoha_pwm_disable(pc, pwm);
  429. return 0;
  430. }
  431. /* Only normal polarity is supported */
  432. if (state->polarity == PWM_POLARITY_INVERSED)
  433. return -EINVAL;
  434. /* Exit early if period is less than minimum supported */
  435. if (state->period < AIROHA_PWM_PERIOD_TICK_NS)
  436. return -EINVAL;
  437. /* Clamp period to MAX supported value */
  438. if (state->period > AIROHA_PWM_PERIOD_MAX_NS)
  439. period_ns = AIROHA_PWM_PERIOD_MAX_NS;
  440. else
  441. period_ns = state->period;
  442. /* Validate duty to configured period */
  443. if (state->duty_cycle > period_ns)
  444. duty_ns = period_ns;
  445. else
  446. duty_ns = state->duty_cycle;
  447. /* Convert period ns to ticks */
  448. period_ticks = airoha_pwm_get_period_ticks_from_ns(period_ns);
  449. /* Convert period ticks to ns again for cosistent duty tick calculation */
  450. period_ns = airoha_pwm_get_period_ns_from_ticks(period_ticks);
  451. duty_ticks = airoha_pwm_get_duty_ticks_from_ns(period_ns, duty_ns);
  452. return airoha_pwm_config(pc, pwm, period_ticks, duty_ticks);
  453. }
  454. static int airoha_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
  455. struct pwm_state *state)
  456. {
  457. struct airoha_pwm *pc = pwmchip_get_drvdata(chip);
  458. int ret, hwpwm = pwm->hwpwm;
  459. u32 addr, shift, val;
  460. u8 bucket;
  461. airoha_pwm_get_flash_map_addr_and_shift(hwpwm, &addr, &shift);
  462. ret = regmap_read(pc->regmap, addr, &val);
  463. if (ret)
  464. return ret;
  465. state->enabled = FIELD_GET(AIROHA_PWM_GPIO_FLASH_EN, val >> shift);
  466. if (!state->enabled)
  467. return 0;
  468. state->polarity = PWM_POLARITY_NORMAL;
  469. bucket = FIELD_GET(AIROHA_PWM_GPIO_FLASH_SET_ID, val >> shift);
  470. return airoha_pwm_get_bucket(pc, bucket, &state->period,
  471. &state->duty_cycle);
  472. }
  473. static const struct pwm_ops airoha_pwm_ops = {
  474. .apply = airoha_pwm_apply,
  475. .get_state = airoha_pwm_get_state,
  476. };
  477. static int airoha_pwm_probe(struct platform_device *pdev)
  478. {
  479. struct device *dev = &pdev->dev;
  480. struct airoha_pwm *pc;
  481. struct pwm_chip *chip;
  482. int ret;
  483. chip = devm_pwmchip_alloc(dev, AIROHA_PWM_MAX_CHANNELS, sizeof(*pc));
  484. if (IS_ERR(chip))
  485. return PTR_ERR(chip);
  486. chip->ops = &airoha_pwm_ops;
  487. pc = pwmchip_get_drvdata(chip);
  488. pc->regmap = device_node_to_regmap(dev_of_node(dev->parent));
  489. if (IS_ERR(pc->regmap))
  490. return dev_err_probe(dev, PTR_ERR(pc->regmap), "Failed to get PWM regmap\n");
  491. ret = devm_pwmchip_add(dev, chip);
  492. if (ret)
  493. return dev_err_probe(dev, ret, "Failed to add PWM chip\n");
  494. return 0;
  495. }
  496. static const struct of_device_id airoha_pwm_of_match[] = {
  497. { .compatible = "airoha,en7581-pwm" },
  498. { /* sentinel */ }
  499. };
  500. MODULE_DEVICE_TABLE(of, airoha_pwm_of_match);
  501. static struct platform_driver airoha_pwm_driver = {
  502. .driver = {
  503. .name = "pwm-airoha",
  504. .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  505. .of_match_table = airoha_pwm_of_match,
  506. },
  507. .probe = airoha_pwm_probe,
  508. };
  509. module_platform_driver(airoha_pwm_driver);
  510. MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
  511. MODULE_AUTHOR("Markus Gothe <markus.gothe@genexis.eu>");
  512. MODULE_AUTHOR("Benjamin Larsson <benjamin.larsson@genexis.eu>");
  513. MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
  514. MODULE_DESCRIPTION("Airoha EN7581 PWM driver");
  515. MODULE_LICENSE("GPL");