File Index
Files and directories
Sign in
FILE

pwm-mediatek.c

File preview with syntax highlighting.

linux-6.19.14/drivers/pwm/pwm-mediatek.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * MediaTek Pulse Width Modulator driver
  4 *
  5 * Copyright (C) 2015 John Crispin <blogic@openwrt.org>
  6 * Copyright (C) 2017 Zhi Mao <zhi.mao@mediatek.com>
  7 *
  8 */
  9
 10#include <linux/bitfield.h>
 11#include <linux/err.h>
 12#include <linux/io.h>
 13#include <linux/ioport.h>
 14#include <linux/kernel.h>
 15#include <linux/module.h>
 16#include <linux/clk.h>
 17#include <linux/of.h>
 18#include <linux/platform_device.h>
 19#include <linux/pwm.h>
 20#include <linux/slab.h>
 21#include <linux/types.h>
 22
 23/* PWM registers and bits definitions */
 24#define PWMCON			0x00
 25#define PWMCON_CLKDIV			GENMASK(2, 0)
 26#define PWMHDUR			0x04
 27#define PWMLDUR			0x08
 28#define PWMGDUR			0x0c
 29#define PWMWAVENUM		0x28
 30#define PWMDWIDTH		0x2c
 31#define PWMDWIDTH_PERIOD		GENMASK(12, 0)
 32#define PWM45DWIDTH_FIXUP	0x30
 33#define PWMTHRES		0x30
 34#define PWMTHRES_DUTY			GENMASK(12, 0)
 35#define PWM45THRES_FIXUP	0x34
 36#define PWM_CK_26M_SEL_V3	0x74
 37#define PWM_CK_26M_SEL		0x210
 38
 39struct pwm_mediatek_of_data {
 40	unsigned int num_pwms;
 41	bool pwm45_fixup;
 42	u16 pwm_ck_26m_sel_reg;
 43	unsigned int chanreg_base;
 44	unsigned int chanreg_width;
 45};
 46
 47/**
 48 * struct pwm_mediatek_chip - struct representing PWM chip
 49 * @regs: base address of PWM chip
 50 * @clk_top: the top clock generator
 51 * @clk_main: the clock used by PWM core
 52 * @soc: pointer to chip's platform data
 53 * @clk_pwms: the clock and clkrate used by each PWM channel
 54 */
 55struct pwm_mediatek_chip {
 56	void __iomem *regs;
 57	struct clk *clk_top;
 58	struct clk *clk_main;
 59	const struct pwm_mediatek_of_data *soc;
 60	struct {
 61		struct clk *clk;
 62		unsigned long rate;
 63	} clk_pwms[];
 64};
 65
 66static inline struct pwm_mediatek_chip *
 67to_pwm_mediatek_chip(struct pwm_chip *chip)
 68{
 69	return pwmchip_get_drvdata(chip);
 70}
 71
 72static int pwm_mediatek_clk_enable(struct pwm_mediatek_chip *pc,
 73				   unsigned int hwpwm)
 74{
 75	int ret;
 76
 77	ret = clk_prepare_enable(pc->clk_top);
 78	if (ret < 0)
 79		return ret;
 80
 81	ret = clk_prepare_enable(pc->clk_main);
 82	if (ret < 0)
 83		goto disable_clk_top;
 84
 85	ret = clk_prepare_enable(pc->clk_pwms[hwpwm].clk);
 86	if (ret < 0)
 87		goto disable_clk_main;
 88
 89	if (!pc->clk_pwms[hwpwm].rate) {
 90		pc->clk_pwms[hwpwm].rate = clk_get_rate(pc->clk_pwms[hwpwm].clk);
 91
 92		/*
 93		 * With the clk running with not more than 1 GHz the
 94		 * calculations in .apply() won't overflow.
 95		 */
 96		if (!pc->clk_pwms[hwpwm].rate ||
 97		    pc->clk_pwms[hwpwm].rate > 1000000000) {
 98			ret = -EINVAL;
 99			goto disable_clk_hwpwm;
100		}
101	}
102
103	return 0;
104
105disable_clk_hwpwm:
106	clk_disable_unprepare(pc->clk_pwms[hwpwm].clk);
107disable_clk_main:
108	clk_disable_unprepare(pc->clk_main);
109disable_clk_top:
110	clk_disable_unprepare(pc->clk_top);
111
112	return ret;
113}
114
115static void pwm_mediatek_clk_disable(struct pwm_mediatek_chip *pc,
116				     unsigned int hwpwm)
117{
118	clk_disable_unprepare(pc->clk_pwms[hwpwm].clk);
119	clk_disable_unprepare(pc->clk_main);
120	clk_disable_unprepare(pc->clk_top);
121}
122
123static inline void pwm_mediatek_writel(struct pwm_mediatek_chip *chip,
124				       unsigned int num, unsigned int offset,
125				       u32 value)
126{
127	writel(value, chip->regs + chip->soc->chanreg_base +
128	       num * chip->soc->chanreg_width + offset);
129}
130
131static inline u32 pwm_mediatek_readl(struct pwm_mediatek_chip *chip,
132				     unsigned int num, unsigned int offset)
133{
134	return readl(chip->regs + chip->soc->chanreg_base +
135		     num * chip->soc->chanreg_width + offset);
136}
137
138struct pwm_mediatek_waveform {
139	u32 enable;
140	u32 con;
141	u32 width;
142	u32 thres;
143};
144
145static int pwm_mediatek_round_waveform_tohw(struct pwm_chip *chip, struct pwm_device *pwm,
146					    const struct pwm_waveform *wf, void *_wfhw)
147{
148	struct pwm_mediatek_waveform *wfhw = _wfhw;
149	struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
150	u32 clkdiv, enable;
151	u64 cnt_period, cnt_duty;
152	unsigned long clk_rate;
153	int ret = 0;
154
155	if (wf->period_length_ns == 0) {
156		*wfhw = (typeof(*wfhw)){
157			.enable = 0,
158		};
159
160		return 0;
161	}
162
163	if (!pc->clk_pwms[pwm->hwpwm].rate) {
164		struct clk *clk = pc->clk_pwms[pwm->hwpwm].clk;
165
166		ret = clk_prepare_enable(clk);
167		if (ret)
168			return ret;
169
170		pc->clk_pwms[pwm->hwpwm].rate = clk_get_rate(clk);
171
172		clk_disable_unprepare(clk);
173	}
174
175	clk_rate = pc->clk_pwms[pwm->hwpwm].rate;
176	if (clk_rate == 0 || clk_rate > 1000000000)
177		return -EINVAL;
178
179	cnt_period = mul_u64_u64_div_u64(wf->period_length_ns, clk_rate, NSEC_PER_SEC);
180	if (cnt_period == 0) {
181		cnt_period = 1;
182		ret = 1;
183	}
184
185	if (cnt_period > FIELD_MAX(PWMDWIDTH_PERIOD) + 1) {
186		if (cnt_period >= ((FIELD_MAX(PWMDWIDTH_PERIOD) + 1) << FIELD_MAX(PWMCON_CLKDIV))) {
187			clkdiv = FIELD_MAX(PWMCON_CLKDIV);
188			cnt_period = FIELD_MAX(PWMDWIDTH_PERIOD) + 1;
189		} else {
190			clkdiv = ilog2(cnt_period) - ilog2(FIELD_MAX(PWMDWIDTH_PERIOD));
191			cnt_period >>= clkdiv;
192		}
193	} else {
194		clkdiv = 0;
195	}
196
197	cnt_duty = mul_u64_u64_div_u64(wf->duty_length_ns, clk_rate, NSEC_PER_SEC) >> clkdiv;
198	if (cnt_duty > cnt_period)
199		cnt_duty = cnt_period;
200
201	if (cnt_duty) {
202		cnt_duty -= 1;
203		enable = BIT(pwm->hwpwm);
204	} else {
205		enable = 0;
206	}
207
208	cnt_period -= 1;
209
210	dev_dbg(&chip->dev, "pwm#%u: %lld/%lld @%lu -> ENABLE: %x, CON: %x, PERIOD: %llx, DUTY: %llx\n",
211		pwm->hwpwm, wf->duty_length_ns, wf->period_length_ns, clk_rate,
212		enable, clkdiv, cnt_period, cnt_duty);
213
214	*wfhw = (typeof(*wfhw)){
215		.enable = enable,
216		.con = clkdiv,
217		.width = cnt_period,
218		.thres = cnt_duty,
219	};
220
221	return ret;
222}
223
224static int pwm_mediatek_round_waveform_fromhw(struct pwm_chip *chip, struct pwm_device *pwm,
225					      const void *_wfhw, struct pwm_waveform *wf)
226{
227	const struct pwm_mediatek_waveform *wfhw = _wfhw;
228	struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
229	u32 clkdiv, cnt_period, cnt_duty;
230	unsigned long clk_rate;
231
232	/*
233	 * When _wfhw was populated, the clock was on, so .rate is
234	 * already set appropriately.
235	 */
236	clk_rate = pc->clk_pwms[pwm->hwpwm].rate;
237
238	if (wfhw->enable) {
239		clkdiv = FIELD_GET(PWMCON_CLKDIV, wfhw->con);
240		cnt_period = FIELD_GET(PWMDWIDTH_PERIOD, wfhw->width);
241		cnt_duty = FIELD_GET(PWMTHRES_DUTY, wfhw->thres);
242
243		/*
244		 * cnt_period is a 13 bit value, NSEC_PER_SEC is 30 bits wide
245		 * and clkdiv is less than 8, so the multiplication doesn't
246		 * overflow an u64.
247		 */
248		*wf = (typeof(*wf)){
249			.period_length_ns =
250				DIV_ROUND_UP_ULL((u64)(cnt_period + 1) * NSEC_PER_SEC << clkdiv, clk_rate),
251			.duty_length_ns =
252				DIV_ROUND_UP_ULL((u64)(cnt_duty + 1) * NSEC_PER_SEC << clkdiv, clk_rate),
253		};
254	} else {
255		clkdiv = 0;
256		cnt_period = 0;
257		cnt_duty = 0;
258
259		/*
260		 * .enable = 0 is also used for too small duty_cycle values, so
261		 * report the HW as being enabled to communicate the minimal
262		 * period.
263		 */
264		*wf = (typeof(*wf)){
265			.period_length_ns =
266				DIV_ROUND_UP_ULL(NSEC_PER_SEC, clk_rate),
267			.duty_length_ns = 0,
268		};
269	}
270
271	dev_dbg(&chip->dev, "pwm#%u: ENABLE: %x, CLKDIV: %x, PERIOD: %x, DUTY: %x @%lu -> %lld/%lld\n",
272		pwm->hwpwm, wfhw->enable, clkdiv, cnt_period, cnt_duty, clk_rate,
273		wf->duty_length_ns, wf->period_length_ns);
274
275	return 0;
276}
277
278static int pwm_mediatek_read_waveform(struct pwm_chip *chip,
279				      struct pwm_device *pwm, void *_wfhw)
280{
281	struct pwm_mediatek_waveform *wfhw = _wfhw;
282	struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
283	u32 enable, clkdiv, cnt_period, cnt_duty;
284	u32 reg_width = PWMDWIDTH, reg_thres = PWMTHRES;
285	int ret;
286
287	ret = pwm_mediatek_clk_enable(pc, pwm->hwpwm);
288	if (ret < 0)
289		return ret;
290
291	enable = readl(pc->regs) & BIT(pwm->hwpwm);
292
293	if (enable) {
294		if (pc->soc->pwm45_fixup && pwm->hwpwm > 2) {
295			/*
296			 * PWM[4,5] has distinct offset for PWMDWIDTH and PWMTHRES
297			 * from the other PWMs on MT7623.
298			 */
299			reg_width = PWM45DWIDTH_FIXUP;
300			reg_thres = PWM45THRES_FIXUP;
301		}
302
303		clkdiv = FIELD_GET(PWMCON_CLKDIV, pwm_mediatek_readl(pc, pwm->hwpwm, PWMCON));
304		cnt_period = FIELD_GET(PWMDWIDTH_PERIOD, pwm_mediatek_readl(pc, pwm->hwpwm, reg_width));
305		cnt_duty = FIELD_GET(PWMTHRES_DUTY, pwm_mediatek_readl(pc, pwm->hwpwm, reg_thres));
306
307		*wfhw = (typeof(*wfhw)){
308			.enable = enable,
309			.con = BIT(15) | clkdiv,
310			.width = cnt_period,
311			.thres = cnt_duty,
312		};
313	} else {
314		*wfhw = (typeof(*wfhw)){
315			.enable = 0,
316		};
317	}
318
319	pwm_mediatek_clk_disable(pc, pwm->hwpwm);
320
321	return ret;
322}
323
324static int pwm_mediatek_write_waveform(struct pwm_chip *chip,
325				       struct pwm_device *pwm, const void *_wfhw)
326{
327	const struct pwm_mediatek_waveform *wfhw = _wfhw;
328	struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
329	u32 ctrl;
330	int ret;
331
332	ret = pwm_mediatek_clk_enable(pc, pwm->hwpwm);
333	if (ret < 0)
334		return ret;
335
336	ctrl = readl(pc->regs);
337
338	if (wfhw->enable) {
339		u32 reg_width = PWMDWIDTH, reg_thres = PWMTHRES;
340
341		if (pc->soc->pwm45_fixup && pwm->hwpwm > 2) {
342			/*
343			 * PWM[4,5] has distinct offset for PWMDWIDTH and PWMTHRES
344			 * from the other PWMs on MT7623.
345			 */
346			reg_width = PWM45DWIDTH_FIXUP;
347			reg_thres = PWM45THRES_FIXUP;
348		}
349
350		if (!(ctrl & BIT(pwm->hwpwm))) {
351			/*
352			 * The clks are already on, just increasing the usage
353			 * counter doesn't fail.
354			 */
355			ret = pwm_mediatek_clk_enable(pc, pwm->hwpwm);
356			if (unlikely(ret < 0))
357				goto out;
358
359			ctrl |= BIT(pwm->hwpwm);
360			writel(ctrl, pc->regs);
361		}
362
363		/* Make sure we use the bus clock and not the 26MHz clock */
364		if (pc->soc->pwm_ck_26m_sel_reg)
365			writel(0, pc->regs + pc->soc->pwm_ck_26m_sel_reg);
366
367		pwm_mediatek_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | wfhw->con);
368		pwm_mediatek_writel(pc, pwm->hwpwm, reg_width, wfhw->width);
369		pwm_mediatek_writel(pc, pwm->hwpwm, reg_thres, wfhw->thres);
370	} else {
371		if (ctrl & BIT(pwm->hwpwm)) {
372			ctrl &= ~BIT(pwm->hwpwm);
373			writel(ctrl, pc->regs);
374
375			pwm_mediatek_clk_disable(pc, pwm->hwpwm);
376		}
377	}
378
379out:
380	pwm_mediatek_clk_disable(pc, pwm->hwpwm);
381
382	return ret;
383}
384
385static const struct pwm_ops pwm_mediatek_ops = {
386	.sizeof_wfhw = sizeof(struct pwm_mediatek_waveform),
387	.round_waveform_tohw = pwm_mediatek_round_waveform_tohw,
388	.round_waveform_fromhw = pwm_mediatek_round_waveform_fromhw,
389	.read_waveform = pwm_mediatek_read_waveform,
390	.write_waveform = pwm_mediatek_write_waveform,
391};
392
393static int pwm_mediatek_init_used_clks(struct pwm_mediatek_chip *pc)
394{
395	const struct pwm_mediatek_of_data *soc = pc->soc;
396	unsigned int hwpwm;
397	u32 enabled, handled = 0;
398	int ret;
399
400	ret = clk_prepare_enable(pc->clk_top);
401	if (ret)
402		return ret;
403
404	ret = clk_prepare_enable(pc->clk_main);
405	if (ret)
406		goto err_enable_main;
407
408	enabled = readl(pc->regs) & GENMASK(soc->num_pwms - 1, 0);
409
410	while (enabled & ~handled) {
411		hwpwm = ilog2(enabled & ~handled);
412
413		ret = pwm_mediatek_clk_enable(pc, hwpwm);
414		if (ret) {
415			while (handled) {
416				hwpwm = ilog2(handled);
417
418				pwm_mediatek_clk_disable(pc, hwpwm);
419				handled &= ~BIT(hwpwm);
420			}
421
422			break;
423		}
424
425		handled |= BIT(hwpwm);
426	}
427
428	clk_disable_unprepare(pc->clk_main);
429err_enable_main:
430
431	clk_disable_unprepare(pc->clk_top);
432
433	return ret;
434}
435
436static int pwm_mediatek_probe(struct platform_device *pdev)
437{
438	struct pwm_chip *chip;
439	struct pwm_mediatek_chip *pc;
440	const struct pwm_mediatek_of_data *soc;
441	unsigned int i;
442	int ret;
443
444	soc = of_device_get_match_data(&pdev->dev);
445
446	chip = devm_pwmchip_alloc(&pdev->dev, soc->num_pwms,
447				  struct_size(pc, clk_pwms, soc->num_pwms));
448	if (IS_ERR(chip))
449		return PTR_ERR(chip);
450	pc = to_pwm_mediatek_chip(chip);
451
452	pc->soc = soc;
453
454	pc->regs = devm_platform_ioremap_resource(pdev, 0);
455	if (IS_ERR(pc->regs))
456		return PTR_ERR(pc->regs);
457
458	pc->clk_top = devm_clk_get(&pdev->dev, "top");
459	if (IS_ERR(pc->clk_top))
460		return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_top),
461				     "Failed to get top clock\n");
462
463	pc->clk_main = devm_clk_get(&pdev->dev, "main");
464	if (IS_ERR(pc->clk_main))
465		return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_main),
466				     "Failed to get main clock\n");
467
468	for (i = 0; i < soc->num_pwms; i++) {
469		char name[8];
470
471		snprintf(name, sizeof(name), "pwm%d", i + 1);
472
473		pc->clk_pwms[i].clk = devm_clk_get(&pdev->dev, name);
474		if (IS_ERR(pc->clk_pwms[i].clk))
475			return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_pwms[i].clk),
476					     "Failed to get %s clock\n", name);
477
478		ret = devm_clk_rate_exclusive_get(&pdev->dev, pc->clk_pwms[i].clk);
479		if (ret)
480			return dev_err_probe(&pdev->dev, ret,
481					     "Failed to lock clock rate for %s\n", name);
482	}
483
484	ret = pwm_mediatek_init_used_clks(pc);
485	if (ret)
486		return dev_err_probe(&pdev->dev, ret, "Failed to initialize used clocks\n");
487
488	chip->ops = &pwm_mediatek_ops;
489
490	ret = devm_pwmchip_add(&pdev->dev, chip);
491	if (ret < 0)
492		return dev_err_probe(&pdev->dev, ret, "pwmchip_add() failed\n");
493
494	return 0;
495}
496
497static const struct pwm_mediatek_of_data mt2712_pwm_data = {
498	.num_pwms = 8,
499	.pwm45_fixup = false,
500	.chanreg_base = 0x10,
501	.chanreg_width = 0x40,
502};
503
504static const struct pwm_mediatek_of_data mt6795_pwm_data = {
505	.num_pwms = 7,
506	.pwm45_fixup = false,
507	.chanreg_base = 0x10,
508	.chanreg_width = 0x40,
509};
510
511static const struct pwm_mediatek_of_data mt7622_pwm_data = {
512	.num_pwms = 6,
513	.pwm45_fixup = false,
514	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
515	.chanreg_base = 0x10,
516	.chanreg_width = 0x40,
517};
518
519static const struct pwm_mediatek_of_data mt7623_pwm_data = {
520	.num_pwms = 5,
521	.pwm45_fixup = true,
522	.chanreg_base = 0x10,
523	.chanreg_width = 0x40,
524};
525
526static const struct pwm_mediatek_of_data mt7628_pwm_data = {
527	.num_pwms = 4,
528	.pwm45_fixup = true,
529	.chanreg_base = 0x10,
530	.chanreg_width = 0x40,
531};
532
533static const struct pwm_mediatek_of_data mt7629_pwm_data = {
534	.num_pwms = 1,
535	.pwm45_fixup = false,
536	.chanreg_base = 0x10,
537	.chanreg_width = 0x40,
538};
539
540static const struct pwm_mediatek_of_data mt7981_pwm_data = {
541	.num_pwms = 3,
542	.pwm45_fixup = false,
543	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
544	.chanreg_base = 0x80,
545	.chanreg_width = 0x40,
546};
547
548static const struct pwm_mediatek_of_data mt7986_pwm_data = {
549	.num_pwms = 2,
550	.pwm45_fixup = false,
551	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
552	.chanreg_base = 0x10,
553	.chanreg_width = 0x40,
554};
555
556static const struct pwm_mediatek_of_data mt7988_pwm_data = {
557	.num_pwms = 8,
558	.pwm45_fixup = false,
559	.chanreg_base = 0x80,
560	.chanreg_width = 0x40,
561};
562
563static const struct pwm_mediatek_of_data mt8183_pwm_data = {
564	.num_pwms = 4,
565	.pwm45_fixup = false,
566	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
567	.chanreg_base = 0x10,
568	.chanreg_width = 0x40,
569};
570
571static const struct pwm_mediatek_of_data mt8365_pwm_data = {
572	.num_pwms = 3,
573	.pwm45_fixup = false,
574	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
575	.chanreg_base = 0x10,
576	.chanreg_width = 0x40,
577};
578
579static const struct pwm_mediatek_of_data mt8516_pwm_data = {
580	.num_pwms = 5,
581	.pwm45_fixup = false,
582	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL,
583	.chanreg_base = 0x10,
584	.chanreg_width = 0x40,
585};
586
587static const struct pwm_mediatek_of_data mt6991_pwm_data = {
588	.num_pwms = 4,
589	.pwm45_fixup = false,
590	.pwm_ck_26m_sel_reg = PWM_CK_26M_SEL_V3,
591	.chanreg_base = 0x100,
592	.chanreg_width = 0x100,
593};
594
595static const struct of_device_id pwm_mediatek_of_match[] = {
596	{ .compatible = "mediatek,mt2712-pwm", .data = &mt2712_pwm_data },
597	{ .compatible = "mediatek,mt6795-pwm", .data = &mt6795_pwm_data },
598	{ .compatible = "mediatek,mt6991-pwm", .data = &mt6991_pwm_data },
599	{ .compatible = "mediatek,mt7622-pwm", .data = &mt7622_pwm_data },
600	{ .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data },
601	{ .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data },
602	{ .compatible = "mediatek,mt7629-pwm", .data = &mt7629_pwm_data },
603	{ .compatible = "mediatek,mt7981-pwm", .data = &mt7981_pwm_data },
604	{ .compatible = "mediatek,mt7986-pwm", .data = &mt7986_pwm_data },
605	{ .compatible = "mediatek,mt7988-pwm", .data = &mt7988_pwm_data },
606	{ .compatible = "mediatek,mt8183-pwm", .data = &mt8183_pwm_data },
607	{ .compatible = "mediatek,mt8365-pwm", .data = &mt8365_pwm_data },
608	{ .compatible = "mediatek,mt8516-pwm", .data = &mt8516_pwm_data },
609	{ },
610};
611MODULE_DEVICE_TABLE(of, pwm_mediatek_of_match);
612
613static struct platform_driver pwm_mediatek_driver = {
614	.driver = {
615		.name = "pwm-mediatek",
616		.of_match_table = pwm_mediatek_of_match,
617	},
618	.probe = pwm_mediatek_probe,
619};
620module_platform_driver(pwm_mediatek_driver);
621
622MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
623MODULE_DESCRIPTION("MediaTek general purpose Pulse Width Modulator driver");
624MODULE_LICENSE("GPL v2");
~/ Read-only file preview.