Advertisement
Guest User

Untitled

a guest
Oct 6th, 2022
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.31 KB | None | 0 0
  1. From 472a1b511d48e072f728048f354746fbe56a7541 Mon Sep 17 00:00:00 2001
  2. From: root <root@abyss.local>
  3. Date: Fri, 7 Oct 2022 01:24:50 +0300
  4. Subject: [PATCH] pwm: Add new pwm driver for ARM Macs
  5.  
  6. Arm macs have a PWM controller that is hooked up to the keyboard backlight.
  7. This patch adds the controller driver and device tree bindings using pwm-leds.
  8. ---
  9. .../devicetree/bindings/pwm/pwm-apple.yaml | 41 +++++
  10. arch/arm64/boot/dts/apple/t600x-die0.dtsi | 9 ++
  11. .../arm64/boot/dts/apple/t600x-j314-j316.dtsi | 18 +++
  12. arch/arm64/boot/dts/apple/t8103-j293.dts | 16 ++
  13. arch/arm64/boot/dts/apple/t8103-j313.dts | 16 ++
  14. arch/arm64/boot/dts/apple/t8103.dtsi | 10 ++
  15. arch/arm64/boot/dts/apple/t8112-j413.dts | 16 ++
  16. arch/arm64/boot/dts/apple/t8112-j493.dts | 16 ++
  17. arch/arm64/boot/dts/apple/t8112.dtsi | 11 ++
  18. drivers/pwm/Kconfig | 12 ++
  19. drivers/pwm/Makefile | 1 +
  20. drivers/pwm/pwm-apple.c | 141 ++++++++++++++++++
  21. 12 files changed, 307 insertions(+)
  22. create mode 100644 Documentation/devicetree/bindings/pwm/pwm-apple.yaml
  23. create mode 100644 drivers/pwm/pwm-apple.c
  24.  
  25. diff --git a/Documentation/devicetree/bindings/pwm/pwm-apple.yaml b/Documentation/devicetree/bindings/pwm/pwm-apple.yaml
  26. new file mode 100644
  27. index 000000000000..fd751acec4eb
  28. --- /dev/null
  29. +++ b/Documentation/devicetree/bindings/pwm/pwm-apple.yaml
  30. @@ -0,0 +1,41 @@
  31. +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
  32. +%YAML 1.2
  33. +---
  34. +$id: http://devicetree.org/schemas/pwm/pwm-apple.yaml#
  35. +$schema: http://devicetree.org/meta-schemas/core.yaml#
  36. +
  37. +title: Apple FPWM controller
  38. +
  39. +maintainers: []
  40. +
  41. +description: |+
  42. + PWM controller used for keyboard backlight on ARM Macs
  43. +
  44. +properties:
  45. + compatible:
  46. + const: apple,s5l-fpwm
  47. + reg:
  48. + maxItems: 1
  49. +
  50. + clocks:
  51. + maxItems: 1
  52. +
  53. + "#pwm-cells":
  54. + const: 2
  55. +
  56. +required:
  57. + - compatible
  58. + - reg
  59. +
  60. +additionalProperties: false
  61. +
  62. +examples:
  63. + - |
  64. + fpwm1: fpwm@235044000 {
  65. + compatible = "apple,s5l-fpwm";
  66. + reg = <0x2 0x35044000 0x0 0x4000>;
  67. + power-domains = <&ps_fpwm1>;
  68. + clocks = <&clkref>;
  69. + #pwm-cells = <2>;
  70. + status = "disabled";
  71. + };
  72. diff --git a/arch/arm64/boot/dts/apple/t600x-die0.dtsi b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
  73. index 4c203778aa89..f90b6114036b 100644
  74. --- a/arch/arm64/boot/dts/apple/t600x-die0.dtsi
  75. +++ b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
  76. @@ -274,6 +274,15 @@ spi3: spi@39b10c000 {
  77. status = "disabled";
  78. };
  79.  
  80. + fpwm0: fpwm@39b030000 {
  81. + compatible = "apple,s5l-fpwm";
  82. + reg = <0x3 0xb9030000 0x0 0x4000>;
  83. + power-domains = <&ps_fpwm0>;
  84. + clocks = <&clkref>;
  85. + #pwm-cells = <2>;
  86. + status = "disabled";
  87. + };
  88. +
  89. serial0: serial@39b200000 {
  90. compatible = "apple,s5l-uart";
  91. reg = <0x3 0x9b200000 0x0 0x1000>;
  92. diff --git a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
  93. index bbe66ea64f09..9a79091a2e0d 100644
  94. --- a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
  95. +++ b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
  96. @@ -9,6 +9,8 @@
  97. * Copyright The Asahi Linux Contributors
  98. */
  99.  
  100. +#include <dt-bindings/leds/common.h>
  101. +
  102. / {
  103. aliases {
  104. serial0 = &serial0;
  105. @@ -339,4 +341,20 @@ codec {
  106. };
  107. };
  108. };
  109. + pwmleds {
  110. + compatible = "pwm-leds";
  111. + kbd-backlight {
  112. + pwms = <&fpwm0 0 40000>;
  113. + label = "kbd_backlight";
  114. + function = LED_FUNCTION_KBD_BACKLIGHT;
  115. + color = <LED_COLOR_ID_WHITE>;
  116. + max-brightness = <255>;
  117. + default-state = "keep";
  118. + pwm-names = "kbd-backlight";
  119. + };
  120. + };
  121. +};
  122. +
  123. +&fpwm0 {
  124. + status = "okay";
  125. };
  126. diff --git a/arch/arm64/boot/dts/apple/t8103-j293.dts b/arch/arm64/boot/dts/apple/t8103-j293.dts
  127. index 3a5ae54f0b9f..6237ce427939 100644
  128. --- a/arch/arm64/boot/dts/apple/t8103-j293.dts
  129. +++ b/arch/arm64/boot/dts/apple/t8103-j293.dts
  130. @@ -171,8 +171,24 @@ codec {
  131. };
  132. };
  133. };
  134. + pwmleds {
  135. + compatible = "pwm-leds";
  136. + kbd-backlight {
  137. + pwms = <&fpwm1 0 40000>;
  138. + label = "kbd_backlight";
  139. + function = LED_FUNCTION_KBD_BACKLIGHT;
  140. + color = <LED_COLOR_ID_WHITE>;
  141. + max-brightness = <255>;
  142. + default-state = "keep";
  143. + pwm-names = "kbd-backlight";
  144. + };
  145. + };
  146. };
  147.  
  148. &framebuffer0 {
  149. backlight = <&backlight>;
  150. };
  151. +
  152. +&fpwm1 {
  153. + status = "okay";
  154. +};
  155. diff --git a/arch/arm64/boot/dts/apple/t8103-j313.dts b/arch/arm64/boot/dts/apple/t8103-j313.dts
  156. index b51f651d2326..94d55f0afd83 100644
  157. --- a/arch/arm64/boot/dts/apple/t8103-j313.dts
  158. +++ b/arch/arm64/boot/dts/apple/t8103-j313.dts
  159. @@ -148,8 +148,24 @@ codec {
  160. };
  161. };
  162. };
  163. + pwmleds {
  164. + compatible = "pwm-leds";
  165. + kbd-backlight {
  166. + pwms = <&fpwm1 0 40000>;
  167. + label = "kbd_backlight";
  168. + function = LED_FUNCTION_KBD_BACKLIGHT;
  169. + color = <LED_COLOR_ID_WHITE>;
  170. + max-brightness = <255>;
  171. + default-state = "keep";
  172. + pwm-names = "kbd-backlight";
  173. + };
  174. + };
  175. };
  176.  
  177. &framebuffer0 {
  178. backlight = <&backlight>;
  179. };
  180. +
  181. +&fpwm1 {
  182. + status = "okay";
  183. +};
  184. diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
  185. index afb0688cb1c2..b9fee327361e 100644
  186. --- a/arch/arm64/boot/dts/apple/t8103.dtsi
  187. +++ b/arch/arm64/boot/dts/apple/t8103.dtsi
  188. @@ -12,6 +12,7 @@
  189. #include <dt-bindings/interrupt-controller/irq.h>
  190. #include <dt-bindings/pinctrl/apple.h>
  191. #include <dt-bindings/spmi/spmi.h>
  192. +#include <dt-bindings/leds/common.h>
  193.  
  194. / {
  195. compatible = "apple,t8103", "apple,arm-platform";
  196. @@ -396,6 +397,15 @@ spi3: spi@23510c000 {
  197. status = "disabled"; /* only used in J293/J313 */
  198. };
  199.  
  200. + fpwm1: fpwm@235044000 {
  201. + compatible = "apple,s5l-fpwm";
  202. + reg = <0x2 0x35044000 0x0 0x4000>;
  203. + power-domains = <&ps_fpwm1>;
  204. + clocks = <&clkref>;
  205. + #pwm-cells = <2>;
  206. + status = "disabled";
  207. + };
  208. +
  209. serial0: serial@235200000 {
  210. compatible = "apple,s5l-uart";
  211. reg = <0x2 0x35200000 0x0 0x1000>;
  212. diff --git a/arch/arm64/boot/dts/apple/t8112-j413.dts b/arch/arm64/boot/dts/apple/t8112-j413.dts
  213. index 0d4306a39fe8..7709c66ed850 100644
  214. --- a/arch/arm64/boot/dts/apple/t8112-j413.dts
  215. +++ b/arch/arm64/boot/dts/apple/t8112-j413.dts
  216. @@ -169,6 +169,18 @@ codec {
  217. };
  218. #endif
  219. };
  220. + pwmleds {
  221. + compatible = "pwm-leds";
  222. + kbd-backlight {
  223. + pwms = <&fpwm1 0 40000>;
  224. + label = "kbd_backlight";
  225. + function = LED_FUNCTION_KBD_BACKLIGHT;
  226. + color = <LED_COLOR_ID_WHITE>;
  227. + max-brightness = <255>;
  228. + default-state = "keep";
  229. + pwm-names = "kbd-backlight";
  230. + };
  231. + };
  232. };
  233.  
  234. &framebuffer0 {
  235. @@ -180,3 +192,7 @@ multi-touch {
  236. firmware-name = "apple/tpmtfw-j413.bin";
  237. };
  238. };
  239. +
  240. +&fpwm1 {
  241. + status = "okay";
  242. +};
  243. diff --git a/arch/arm64/boot/dts/apple/t8112-j493.dts b/arch/arm64/boot/dts/apple/t8112-j493.dts
  244. index aa8c045cd1ac..92b75c3c325a 100644
  245. --- a/arch/arm64/boot/dts/apple/t8112-j493.dts
  246. +++ b/arch/arm64/boot/dts/apple/t8112-j493.dts
  247. @@ -158,6 +158,18 @@ codec {
  248. };
  249. #endif
  250. };
  251. + pwmleds {
  252. + compatible = "pwm-leds";
  253. + kbd-backlight {
  254. + pwms = <&fpwm1 0 40000>;
  255. + label = "kbd_backlight";
  256. + function = LED_FUNCTION_KBD_BACKLIGHT;
  257. + color = <LED_COLOR_ID_WHITE>;
  258. + max-brightness = <255>;
  259. + default-state = "keep";
  260. + pwm-names = "kbd-backlight";
  261. + };
  262. + };
  263. };
  264.  
  265. &framebuffer0 {
  266. @@ -169,3 +181,7 @@ multi-touch {
  267. firmware-name = "apple/tpmtfw-j493.bin";
  268. };
  269. };
  270. +
  271. +&fpwm1 {
  272. + status = "okay";
  273. +};
  274. diff --git a/arch/arm64/boot/dts/apple/t8112.dtsi b/arch/arm64/boot/dts/apple/t8112.dtsi
  275. index 852937ec80ea..dda491f3d329 100644
  276. --- a/arch/arm64/boot/dts/apple/t8112.dtsi
  277. +++ b/arch/arm64/boot/dts/apple/t8112.dtsi
  278. @@ -12,6 +12,7 @@
  279. #include <dt-bindings/interrupt-controller/irq.h>
  280. #include <dt-bindings/pinctrl/apple.h>
  281. #include <dt-bindings/spmi/spmi.h>
  282. +#include <dt-bindings/leds/common.h>
  283.  
  284. / {
  285. compatible = "apple,t8112", "apple,arm-platform";
  286. @@ -416,6 +417,16 @@ spi3: spi@23510c000 {
  287. status = "disabled";
  288. };
  289.  
  290. + fpwm1: fpwm@235044000 {
  291. + compatible = "apple,s5l-fpwm";
  292. + reg = <0x2 0x35044000 0x0 0x4000>;
  293. + power-domains = <&ps_fpwm1>;
  294. + clocks = <&clkref>;
  295. + #pwm-cells = <2>;
  296. + status = "disabled";
  297. + };
  298. +
  299. +
  300. serial0: serial@235200000 {
  301. compatible = "apple,s5l-uart";
  302. reg = <0x2 0x35200000 0x0 0x1000>;
  303. diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
  304. index 904de8d61828..3ffb56549161 100644
  305. --- a/drivers/pwm/Kconfig
  306. +++ b/drivers/pwm/Kconfig
  307. @@ -51,6 +51,18 @@ config PWM_AB8500
  308. To compile this driver as a module, choose M here: the module
  309. will be called pwm-ab8500.
  310.  
  311. +config PWM_APPLE
  312. + tristate "Apple SoC PWM support"
  313. + depends on ARCH_APPLE || COMPILE_TEST
  314. + help
  315. + Generic PWM framework driver for PWM controller present on
  316. + Apple SoCs
  317. +
  318. + Say Y here if you have an ARM Apple laptop, otherwise say N
  319. +
  320. + To compile this driver as a module, choose M here: the module
  321. + will be called pwm-apple.
  322. +
  323. config PWM_ATMEL
  324. tristate "Atmel PWM support"
  325. depends on ARCH_AT91 || COMPILE_TEST
  326. diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
  327. index 5c08bdb817b4..bf0c04ce704e 100644
  328. --- a/drivers/pwm/Makefile
  329. +++ b/drivers/pwm/Makefile
  330. @@ -2,6 +2,7 @@
  331. obj-$(CONFIG_PWM) += core.o
  332. obj-$(CONFIG_PWM_SYSFS) += sysfs.o
  333. obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o
  334. +obj-$(CONFIG_PWM_APPLE) += pwm-apple.o
  335. obj-$(CONFIG_PWM_ATMEL) += pwm-atmel.o
  336. obj-$(CONFIG_PWM_ATMEL_HLCDC_PWM) += pwm-atmel-hlcdc.o
  337. obj-$(CONFIG_PWM_ATMEL_TCB) += pwm-atmel-tcb.o
  338. diff --git a/drivers/pwm/pwm-apple.c b/drivers/pwm/pwm-apple.c
  339. new file mode 100644
  340. index 000000000000..3e8f2ddb05c0
  341. --- /dev/null
  342. +++ b/drivers/pwm/pwm-apple.c
  343. @@ -0,0 +1,141 @@
  344. +// SPDX-License-Identifier: GPL-2.0
  345. +/*
  346. + * Driver for the Apple SoC PWM controller
  347. + *
  348. + * Copyright The Asahi Linux Contributors
  349. + */
  350. +
  351. +#include <linux/module.h>
  352. +#include <linux/of.h>
  353. +#include <linux/of_device.h>
  354. +#include <linux/platform_device.h>
  355. +#include <linux/pwm.h>
  356. +#include <linux/io.h>
  357. +#include <linux/clk.h>
  358. +#include <linux/pm_runtime.h>
  359. +
  360. +#define PWM_CONTROL 0x00
  361. +#define PWM_APPLY_MAGIC 0x4239
  362. +#define PWM_ON_CYCLES 0x1c
  363. +#define PWM_OFF_CYCLES 0x18
  364. +
  365. +#define CTRL_ENABLE BIT(0)
  366. +#define CTRL_MODE BIT(2)
  367. +#define CTRL_UPDATE BIT(5)
  368. +#define CTRL_TRIGGER BIT(9)
  369. +#define CTRL_INVERT BIT(10)
  370. +#define CTRL_OUTPUT_ENABLE BIT(14)
  371. +
  372. +struct apple_pwm {
  373. + struct pwm_chip chip;
  374. + void __iomem *base;
  375. + struct clk *clk;
  376. + u64 clkrate;
  377. +};
  378. +
  379. +static int apple_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
  380. + const struct pwm_state *state)
  381. +{
  382. + struct apple_pwm *fpwm;
  383. + u64 on_cycles, off_cycles;
  384. +
  385. + fpwm = container_of(chip, struct apple_pwm, chip);
  386. + on_cycles = fpwm->clkrate * state->duty_cycle / NSEC_PER_SEC;
  387. + off_cycles = (fpwm->clkrate * state->period / NSEC_PER_SEC) - on_cycles;
  388. + if (state->enabled) {
  389. + writel(on_cycles, fpwm->base + PWM_ON_CYCLES);
  390. + writel(off_cycles, fpwm->base + PWM_OFF_CYCLES);
  391. + writel(CTRL_ENABLE | CTRL_OUTPUT_ENABLE | CTRL_UPDATE,
  392. + fpwm->base + PWM_CONTROL);
  393. + } else {
  394. + writel(0, fpwm->base + PWM_CONTROL);
  395. + }
  396. + return 0;
  397. +}
  398. +
  399. +static void apple_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
  400. + struct pwm_state *state)
  401. +{
  402. + struct apple_pwm *fpwm;
  403. + u32 on_cycles, off_cycles, ctrl;
  404. +
  405. + fpwm = container_of(chip, struct apple_pwm, chip);
  406. +
  407. + ctrl = readl(fpwm->base + PWM_CONTROL);
  408. + on_cycles = readl(fpwm->base + PWM_ON_CYCLES);
  409. + off_cycles = readl(fpwm->base + PWM_OFF_CYCLES);
  410. +
  411. + state->enabled = (ctrl & CTRL_ENABLE) && (ctrl & CTRL_OUTPUT_ENABLE);
  412. + state->polarity = PWM_POLARITY_NORMAL;
  413. + state->duty_cycle = on_cycles / fpwm->clkrate * NSEC_PER_SEC;
  414. + state->period = (off_cycles / fpwm->clkrate * NSEC_PER_SEC)
  415. + + state->duty_cycle;
  416. +}
  417. +
  418. +static const struct pwm_ops apple_pwm_ops = {
  419. + .apply = apple_pwm_apply,
  420. + .get_state = apple_pwm_get_state,
  421. + .owner = THIS_MODULE,
  422. +};
  423. +
  424. +static void apple_pwm_clk_disable_unprepare(void *data)
  425. +{
  426. + clk_disable_unprepare(data);
  427. +}
  428. +
  429. +static int apple_pwm_probe(struct platform_device *pdev)
  430. +{
  431. + struct apple_pwm *pwm;
  432. + int ret;
  433. +
  434. + pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
  435. + if (!pwm)
  436. + return -ENOMEM;
  437. +
  438. + pwm->base = devm_platform_ioremap_resource(pdev, 0);
  439. + if (IS_ERR(pwm->base))
  440. + return PTR_ERR(pwm->base);
  441. +
  442. + platform_set_drvdata(pdev, pwm);
  443. +
  444. + pwm->clk = devm_clk_get(&pdev->dev, NULL);
  445. + if (IS_ERR(pwm->clk))
  446. + return PTR_ERR(pwm->clk);
  447. +
  448. + ret = clk_prepare_enable(pwm->clk);
  449. + if (ret)
  450. + return ret;
  451. +
  452. + pwm->clkrate = clk_get_rate(pwm->clk);
  453. +
  454. + ret = devm_add_action_or_reset(&pdev->dev,
  455. + apple_pwm_clk_disable_unprepare, pwm->clk);
  456. + if (ret)
  457. + return ret;
  458. +
  459. + pwm->chip.dev = &pdev->dev;
  460. + pwm->chip.npwm = 1;
  461. + pwm->chip.ops = &apple_pwm_ops;
  462. +
  463. + ret = devm_pwmchip_add(&pdev->dev, &pwm->chip);
  464. + return ret;
  465. +}
  466. +
  467. +static const struct of_device_id apple_pwm_of_match[] = {
  468. + { .compatible = "apple,s5l-fpwm" },
  469. + {}
  470. +};
  471. +MODULE_DEVICE_TABLE(of, apple_pwm_of_match);
  472. +
  473. +static struct platform_driver apple_pwm_driver = {
  474. + .probe = apple_pwm_probe,
  475. + .driver = {
  476. + .name = "apple-pwm",
  477. + .owner = THIS_MODULE,
  478. + .of_match_table = apple_pwm_of_match,
  479. + },
  480. +};
  481. +module_platform_driver(apple_pwm_driver);
  482. +
  483. +MODULE_DESCRIPTION("Apple SoC PWM driver");
  484. +MODULE_LICENSE("GPL");
  485. --
  486. 2.37.3
  487.  
  488.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement