File Index
Files and directories
Sign in
FILE

clk-sg2044-pll.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/sophgo/clk-sg2044-pll.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Sophgo SG2044 PLL clock controller driver
  4 *
  5 * Copyright (C) 2025 Inochi Amaoto <inochiama@gmail.com>
  6 */
  7
  8#include <linux/array_size.h>
  9#include <linux/bitfield.h>
 10#include <linux/bits.h>
 11#include <linux/cleanup.h>
 12#include <linux/clk.h>
 13#include <linux/clk-provider.h>
 14#include <linux/io.h>
 15#include <linux/iopoll.h>
 16#include <linux/math64.h>
 17#include <linux/mfd/syscon.h>
 18#include <linux/platform_device.h>
 19#include <linux/regmap.h>
 20#include <linux/spinlock.h>
 21
 22#include <dt-bindings/clock/sophgo,sg2044-pll.h>
 23
 24/* Low Control part */
 25#define PLL_VCOSEL_MASK		GENMASK(17, 16)
 26
 27/* High Control part */
 28#define PLL_FBDIV_MASK		GENMASK(11, 0)
 29#define PLL_REFDIV_MASK		GENMASK(17, 12)
 30#define PLL_POSTDIV1_MASK	GENMASK(20, 18)
 31#define PLL_POSTDIV2_MASK	GENMASK(23, 21)
 32
 33#define PLL_CALIBRATE_EN	BIT(24)
 34#define PLL_CALIBRATE_MASK	GENMASK(29, 27)
 35#define PLL_CALIBRATE_DEFAULT	FIELD_PREP(PLL_CALIBRATE_MASK, 2)
 36#define PLL_UPDATE_EN		BIT(30)
 37
 38#define PLL_HIGH_CTRL_MASK	\
 39	(PLL_FBDIV_MASK | PLL_REFDIV_MASK | \
 40	 PLL_POSTDIV1_MASK | PLL_POSTDIV2_MASK | \
 41	 PLL_CALIBRATE_EN | PLL_CALIBRATE_MASK | \
 42	 PLL_UPDATE_EN)
 43
 44#define PLL_HIGH_CTRL_OFFSET	4
 45
 46#define PLL_VCOSEL_1G6		0x2
 47#define PLL_VCOSEL_2G4		0x3
 48
 49#define PLL_LIMIT_FOUTVCO	0
 50#define PLL_LIMIT_FOUT		1
 51#define PLL_LIMIT_REFDIV	2
 52#define PLL_LIMIT_FBDIV		3
 53#define PLL_LIMIT_POSTDIV1	4
 54#define PLL_LIMIT_POSTDIV2	5
 55
 56#define for_each_pll_limit_range(_var, _limit) \
 57	for (_var = (_limit)->min; _var <= (_limit)->max; _var++)
 58
 59struct sg2044_pll_limit {
 60	u64 min;
 61	u64 max;
 62};
 63
 64struct sg2044_pll_internal {
 65	u32 ctrl_offset;
 66	u32 status_offset;
 67	u32 enable_offset;
 68
 69	u8 status_lock_bit;
 70	u8 status_updating_bit;
 71	u8 enable_bit;
 72
 73	const struct sg2044_pll_limit *limits;
 74};
 75
 76struct sg2044_clk_common {
 77	struct clk_hw	hw;
 78	struct regmap	*regmap;
 79	spinlock_t	*lock;
 80	unsigned int	id;
 81};
 82
 83struct sg2044_pll {
 84	struct sg2044_clk_common	common;
 85	struct sg2044_pll_internal	pll;
 86	unsigned int			syscon_offset;
 87};
 88
 89struct sg2044_pll_desc_data {
 90	struct sg2044_clk_common	* const *pll;
 91	u16				num_pll;
 92};
 93
 94#define SG2044_SYSCON_PLL_OFFSET	0x98
 95
 96struct sg2044_pll_ctrl {
 97	spinlock_t			lock;
 98	struct clk_hw_onecell_data	data;
 99};
100
101#define hw_to_sg2044_clk_common(_hw)					\
102	container_of((_hw), struct sg2044_clk_common, hw)
103
104static inline bool sg2044_clk_fit_limit(u64 value,
105					const struct sg2044_pll_limit *limit)
106{
107	return value >= limit->min && value <= limit->max;
108}
109
110static inline struct sg2044_pll *hw_to_sg2044_pll(struct clk_hw *hw)
111{
112	return container_of(hw_to_sg2044_clk_common(hw),
113			    struct sg2044_pll, common);
114}
115
116static unsigned long sg2044_pll_calc_vco_rate(unsigned long parent_rate,
117					      unsigned long refdiv,
118					      unsigned long fbdiv)
119{
120	u64 numerator = parent_rate * fbdiv;
121
122	return div64_ul(numerator, refdiv);
123}
124
125static unsigned long sg2044_pll_calc_rate(unsigned long parent_rate,
126					  unsigned long refdiv,
127					  unsigned long fbdiv,
128					  unsigned long postdiv1,
129					  unsigned long postdiv2)
130{
131	u64 numerator, denominator;
132
133	numerator = parent_rate * fbdiv;
134	denominator = refdiv * (postdiv1 + 1) * (postdiv2 + 1);
135
136	return div64_u64(numerator, denominator);
137}
138
139static unsigned long sg2044_pll_recalc_rate(struct clk_hw *hw,
140					    unsigned long parent_rate)
141{
142	struct sg2044_pll *pll = hw_to_sg2044_pll(hw);
143	u32 value;
144	int ret;
145
146	ret = regmap_read(pll->common.regmap,
147			  pll->syscon_offset + pll->pll.ctrl_offset + PLL_HIGH_CTRL_OFFSET,
148			  &value);
149	if (ret < 0)
150		return 0;
151
152	return sg2044_pll_calc_rate(parent_rate,
153				    FIELD_GET(PLL_REFDIV_MASK, value),
154				    FIELD_GET(PLL_FBDIV_MASK, value),
155				    FIELD_GET(PLL_POSTDIV1_MASK, value),
156				    FIELD_GET(PLL_POSTDIV2_MASK, value));
157}
158
159static bool pll_is_better_rate(unsigned long target, unsigned long now,
160			       unsigned long best)
161{
162	return abs_diff(target, now) < abs_diff(target, best);
163}
164
165static int sg2042_pll_compute_postdiv(const struct sg2044_pll_limit *limits,
166				      unsigned long target,
167				      unsigned long parent_rate,
168				      unsigned int refdiv,
169				      unsigned int fbdiv,
170				      unsigned int *postdiv1,
171				      unsigned int *postdiv2)
172{
173	unsigned int div1, div2;
174	unsigned long tmp, best_rate = 0;
175	unsigned int best_div1 = 0, best_div2 = 0;
176
177	for_each_pll_limit_range(div2, &limits[PLL_LIMIT_POSTDIV2]) {
178		for_each_pll_limit_range(div1, &limits[PLL_LIMIT_POSTDIV1]) {
179			tmp = sg2044_pll_calc_rate(parent_rate,
180						   refdiv, fbdiv,
181						   div1, div2);
182
183			if (tmp > target)
184				continue;
185
186			if (pll_is_better_rate(target, tmp, best_rate)) {
187				best_div1 = div1;
188				best_div2 = div2;
189				best_rate = tmp;
190
191				if (tmp == target)
192					goto find;
193			}
194		}
195	}
196
197find:
198	if (best_rate) {
199		*postdiv1 = best_div1;
200		*postdiv2 = best_div2;
201		return 0;
202	}
203
204	return -EINVAL;
205}
206
207static int sg2044_compute_pll_setting(const struct sg2044_pll_limit *limits,
208				      unsigned long req_rate,
209				      unsigned long parent_rate,
210				      unsigned int *value)
211{
212	unsigned int refdiv, fbdiv, postdiv1, postdiv2;
213	unsigned int best_refdiv, best_fbdiv, best_postdiv1, best_postdiv2;
214	unsigned long tmp, best_rate = 0;
215	int ret;
216
217	for_each_pll_limit_range(fbdiv, &limits[PLL_LIMIT_FBDIV]) {
218		for_each_pll_limit_range(refdiv, &limits[PLL_LIMIT_REFDIV]) {
219			u64 vco = sg2044_pll_calc_vco_rate(parent_rate,
220							   refdiv, fbdiv);
221			if (!sg2044_clk_fit_limit(vco, &limits[PLL_LIMIT_FOUTVCO]))
222				continue;
223
224			ret = sg2042_pll_compute_postdiv(limits,
225							 req_rate, parent_rate,
226							 refdiv, fbdiv,
227							 &postdiv1, &postdiv2);
228			if (ret)
229				continue;
230
231			tmp = sg2044_pll_calc_rate(parent_rate,
232						   refdiv, fbdiv,
233						   postdiv1, postdiv2);
234
235			if (pll_is_better_rate(req_rate, tmp, best_rate)) {
236				best_refdiv = refdiv;
237				best_fbdiv = fbdiv;
238				best_postdiv1 = postdiv1;
239				best_postdiv2 = postdiv2;
240				best_rate = tmp;
241
242				if (tmp == req_rate)
243					goto find;
244			}
245		}
246	}
247
248find:
249	if (best_rate) {
250		*value = FIELD_PREP(PLL_REFDIV_MASK, best_refdiv) |
251			 FIELD_PREP(PLL_FBDIV_MASK, best_fbdiv) |
252			 FIELD_PREP(PLL_POSTDIV1_MASK, best_postdiv1) |
253			 FIELD_PREP(PLL_POSTDIV2_MASK, best_postdiv2);
254		return 0;
255	}
256
257	return -EINVAL;
258}
259
260static int sg2044_pll_determine_rate(struct clk_hw *hw,
261				     struct clk_rate_request *req)
262{
263	struct sg2044_pll *pll = hw_to_sg2044_pll(hw);
264	unsigned int value;
265	u64 target;
266	int ret;
267
268	target = clamp(req->rate, pll->pll.limits[PLL_LIMIT_FOUT].min,
269		       pll->pll.limits[PLL_LIMIT_FOUT].max);
270
271	ret = sg2044_compute_pll_setting(pll->pll.limits, target,
272					 req->best_parent_rate, &value);
273	if (ret < 0)
274		return ret;
275
276	req->rate = sg2044_pll_calc_rate(req->best_parent_rate,
277					 FIELD_GET(PLL_REFDIV_MASK, value),
278					 FIELD_GET(PLL_FBDIV_MASK, value),
279					 FIELD_GET(PLL_POSTDIV1_MASK, value),
280					 FIELD_GET(PLL_POSTDIV2_MASK, value));
281
282	return 0;
283}
284
285static int sg2044_pll_poll_update(struct sg2044_pll *pll)
286{
287	int ret;
288	unsigned int value;
289
290	ret = regmap_read_poll_timeout_atomic(pll->common.regmap,
291					      pll->syscon_offset + pll->pll.status_offset,
292					      value,
293					      (value & BIT(pll->pll.status_lock_bit)),
294					      1, 100000);
295	if (ret)
296		return ret;
297
298	return regmap_read_poll_timeout_atomic(pll->common.regmap,
299					       pll->syscon_offset + pll->pll.status_offset,
300					       value,
301					       (!(value & BIT(pll->pll.status_updating_bit))),
302					       1, 100000);
303}
304
305static int sg2044_pll_enable(struct sg2044_pll *pll, bool en)
306{
307	if (en) {
308		if (sg2044_pll_poll_update(pll) < 0)
309			pr_warn("%s: fail to lock pll\n", clk_hw_get_name(&pll->common.hw));
310
311		return regmap_set_bits(pll->common.regmap,
312				       pll->syscon_offset + pll->pll.enable_offset,
313				       BIT(pll->pll.enable_bit));
314	}
315
316	return regmap_clear_bits(pll->common.regmap,
317				 pll->syscon_offset + pll->pll.enable_offset,
318				 BIT(pll->pll.enable_bit));
319}
320
321static int sg2044_pll_update_vcosel(struct sg2044_pll *pll, u64 rate)
322{
323	unsigned int sel;
324
325	if (rate < U64_C(2400000000))
326		sel = PLL_VCOSEL_1G6;
327	else
328		sel = PLL_VCOSEL_2G4;
329
330	return regmap_write_bits(pll->common.regmap,
331				 pll->syscon_offset + pll->pll.ctrl_offset,
332				 PLL_VCOSEL_MASK,
333				 FIELD_PREP(PLL_VCOSEL_MASK, sel));
334}
335
336static int sg2044_pll_set_rate(struct clk_hw *hw,
337			       unsigned long rate, unsigned long parent_rate)
338{
339	struct sg2044_pll *pll = hw_to_sg2044_pll(hw);
340	unsigned int value;
341	u64 vco;
342	int ret;
343
344	ret = sg2044_compute_pll_setting(pll->pll.limits, rate,
345					 parent_rate, &value);
346	if (ret < 0)
347		return ret;
348
349	vco = sg2044_pll_calc_vco_rate(parent_rate,
350				       FIELD_GET(PLL_REFDIV_MASK, value),
351				       FIELD_GET(PLL_FBDIV_MASK, value));
352
353	value |= PLL_CALIBRATE_EN;
354	value |= PLL_CALIBRATE_DEFAULT;
355	value |= PLL_UPDATE_EN;
356
357	guard(spinlock_irqsave)(pll->common.lock);
358
359	ret = sg2044_pll_enable(pll, false);
360	if (ret)
361		return ret;
362
363	sg2044_pll_update_vcosel(pll, vco);
364
365	regmap_write_bits(pll->common.regmap,
366			  pll->syscon_offset + pll->pll.ctrl_offset +
367			  PLL_HIGH_CTRL_OFFSET,
368			  PLL_HIGH_CTRL_MASK, value);
369
370	sg2044_pll_enable(pll, true);
371
372	return ret;
373}
374
375static const struct clk_ops sg2044_pll_ops = {
376	.recalc_rate = sg2044_pll_recalc_rate,
377	.determine_rate = sg2044_pll_determine_rate,
378	.set_rate = sg2044_pll_set_rate,
379};
380
381static const struct clk_ops sg2044_pll_ro_ops = {
382	.recalc_rate = sg2044_pll_recalc_rate,
383};
384
385#define SG2044_CLK_COMMON_PDATA(_id, _name, _parents, _op, _flags)	\
386	{								\
387		.hw.init = CLK_HW_INIT_PARENTS_DATA(_name, _parents,	\
388						    _op, (_flags)),	\
389		.id = (_id),						\
390	}
391
392#define DEFINE_SG2044_PLL(_id, _name, _parent, _flags,			\
393			  _ctrl_offset,					\
394			  _status_offset, _status_lock_bit,		\
395			  _status_updating_bit,				\
396			  _enable_offset, _enable_bit,			\
397			  _limits)					\
398	struct sg2044_pll _name = {					\
399		.common	= SG2044_CLK_COMMON_PDATA(_id, #_name, _parent,	\
400						  &sg2044_pll_ops,	\
401						  (_flags)),		\
402		.pll = {						\
403			.ctrl_offset = (_ctrl_offset),			\
404			.status_offset = (_status_offset),		\
405			.enable_offset = (_enable_offset),		\
406			.status_lock_bit = (_status_lock_bit),		\
407			.status_updating_bit = (_status_updating_bit),	\
408			.enable_bit = (_enable_bit),			\
409			.limits = (_limits),				\
410		},							\
411	}
412
413#define DEFINE_SG2044_PLL_RO(_id, _name, _parent, _flags,		\
414			     _ctrl_offset,				\
415			     _status_offset, _status_lock_bit,		\
416			     _status_updating_bit,			\
417			     _enable_offset, _enable_bit,		\
418			     _limits)					\
419	struct sg2044_pll _name = {					\
420		.common	= SG2044_CLK_COMMON_PDATA(_id, #_name, _parent,	\
421						  &sg2044_pll_ro_ops,	\
422						  (_flags)),		\
423		.pll = {						\
424			.ctrl_offset = (_ctrl_offset),			\
425			.status_offset = (_status_offset),		\
426			.enable_offset = (_enable_offset),		\
427			.status_lock_bit = (_status_lock_bit),		\
428			.status_updating_bit = (_status_updating_bit),	\
429			.enable_bit = (_enable_bit),			\
430			.limits = (_limits),				\
431		},							\
432	}
433
434static const struct clk_parent_data osc_parents[] = {
435	{ .index = 0 },
436};
437
438static const struct sg2044_pll_limit pll_limits[] = {
439	[PLL_LIMIT_FOUTVCO] = {
440		.min = U64_C(1600000000),
441		.max = U64_C(3200000000),
442	},
443	[PLL_LIMIT_FOUT] = {
444		.min = U64_C(25000),
445		.max = U64_C(3200000000),
446	},
447	[PLL_LIMIT_REFDIV] = {
448		.min = U64_C(1),
449		.max = U64_C(63),
450	},
451	[PLL_LIMIT_FBDIV] = {
452		.min = U64_C(8),
453		.max = U64_C(1066),
454	},
455	[PLL_LIMIT_POSTDIV1] = {
456		.min = U64_C(0),
457		.max = U64_C(7),
458	},
459	[PLL_LIMIT_POSTDIV2] = {
460		.min = U64_C(0),
461		.max = U64_C(7),
462	},
463};
464
465static DEFINE_SG2044_PLL_RO(CLK_FPLL0, clk_fpll0, osc_parents, CLK_IS_CRITICAL,
466			    0x58, 0x00, 22, 6,
467			    0x04, 6, pll_limits);
468
469static DEFINE_SG2044_PLL_RO(CLK_FPLL1, clk_fpll1, osc_parents, CLK_IS_CRITICAL,
470			    0x60, 0x00, 23, 7,
471			    0x04, 7, pll_limits);
472
473static DEFINE_SG2044_PLL_RO(CLK_FPLL2, clk_fpll2, osc_parents, CLK_IS_CRITICAL,
474			    0x20, 0x08, 16, 0,
475			    0x0c, 0, pll_limits);
476
477static DEFINE_SG2044_PLL_RO(CLK_DPLL0, clk_dpll0, osc_parents, CLK_IS_CRITICAL,
478			    0x68, 0x00, 24, 8,
479			    0x04, 8, pll_limits);
480
481static DEFINE_SG2044_PLL_RO(CLK_DPLL1, clk_dpll1, osc_parents, CLK_IS_CRITICAL,
482			    0x70, 0x00, 25, 9,
483			    0x04, 9, pll_limits);
484
485static DEFINE_SG2044_PLL_RO(CLK_DPLL2, clk_dpll2, osc_parents, CLK_IS_CRITICAL,
486			    0x78, 0x00, 26, 10,
487			    0x04, 10, pll_limits);
488
489static DEFINE_SG2044_PLL_RO(CLK_DPLL3, clk_dpll3, osc_parents, CLK_IS_CRITICAL,
490			    0x80, 0x00, 27, 11,
491			    0x04, 11, pll_limits);
492
493static DEFINE_SG2044_PLL_RO(CLK_DPLL4, clk_dpll4, osc_parents, CLK_IS_CRITICAL,
494			    0x88, 0x00, 28, 12,
495			    0x04, 12, pll_limits);
496
497static DEFINE_SG2044_PLL_RO(CLK_DPLL5, clk_dpll5, osc_parents, CLK_IS_CRITICAL,
498			    0x90, 0x00, 29, 13,
499			    0x04, 13, pll_limits);
500
501static DEFINE_SG2044_PLL_RO(CLK_DPLL6, clk_dpll6, osc_parents, CLK_IS_CRITICAL,
502			    0x98, 0x00, 30, 14,
503			    0x04, 14, pll_limits);
504
505static DEFINE_SG2044_PLL_RO(CLK_DPLL7, clk_dpll7, osc_parents, CLK_IS_CRITICAL,
506			    0xa0, 0x00, 31, 15,
507			    0x04, 15, pll_limits);
508
509static DEFINE_SG2044_PLL(CLK_MPLL0, clk_mpll0, osc_parents, CLK_IS_CRITICAL,
510			 0x28, 0x00, 16, 0,
511			 0x04, 0, pll_limits);
512
513static DEFINE_SG2044_PLL(CLK_MPLL1, clk_mpll1, osc_parents, CLK_IS_CRITICAL,
514			 0x30, 0x00, 17, 1,
515			 0x04, 1, pll_limits);
516
517static DEFINE_SG2044_PLL(CLK_MPLL2, clk_mpll2, osc_parents, CLK_IS_CRITICAL,
518			 0x38, 0x00, 18, 2,
519			 0x04, 2, pll_limits);
520
521static DEFINE_SG2044_PLL(CLK_MPLL3, clk_mpll3, osc_parents, CLK_IS_CRITICAL,
522			 0x40, 0x00, 19, 3,
523			 0x04, 3, pll_limits);
524
525static DEFINE_SG2044_PLL(CLK_MPLL4, clk_mpll4, osc_parents, CLK_IS_CRITICAL,
526			 0x48, 0x00, 20, 4,
527			 0x04, 4, pll_limits);
528
529static DEFINE_SG2044_PLL(CLK_MPLL5, clk_mpll5, osc_parents, CLK_IS_CRITICAL,
530			 0x50, 0x00, 21, 5,
531			 0x04, 5, pll_limits);
532
533static struct sg2044_clk_common * const sg2044_pll_commons[] = {
534	&clk_fpll0.common,
535	&clk_fpll1.common,
536	&clk_fpll2.common,
537	&clk_dpll0.common,
538	&clk_dpll1.common,
539	&clk_dpll2.common,
540	&clk_dpll3.common,
541	&clk_dpll4.common,
542	&clk_dpll5.common,
543	&clk_dpll6.common,
544	&clk_dpll7.common,
545	&clk_mpll0.common,
546	&clk_mpll1.common,
547	&clk_mpll2.common,
548	&clk_mpll3.common,
549	&clk_mpll4.common,
550	&clk_mpll5.common,
551};
552
553static int sg2044_pll_init_ctrl(struct device *dev, struct regmap *regmap,
554				struct sg2044_pll_ctrl *ctrl,
555				const struct sg2044_pll_desc_data *desc)
556{
557	int ret, i;
558
559	spin_lock_init(&ctrl->lock);
560
561	for (i = 0; i < desc->num_pll; i++) {
562		struct sg2044_clk_common *common = desc->pll[i];
563		struct sg2044_pll *pll = hw_to_sg2044_pll(&common->hw);
564
565		common->lock = &ctrl->lock;
566		common->regmap = regmap;
567		pll->syscon_offset = SG2044_SYSCON_PLL_OFFSET;
568
569		ret = devm_clk_hw_register(dev, &common->hw);
570		if (ret)
571			return ret;
572
573		ctrl->data.hws[common->id] = &common->hw;
574	}
575
576	return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
577					   &ctrl->data);
578}
579
580static int sg2044_pll_probe(struct platform_device *pdev)
581{
582	struct device *dev = &pdev->dev;
583	struct sg2044_pll_ctrl *ctrl;
584	const struct sg2044_pll_desc_data *desc;
585	struct regmap *regmap;
586
587	regmap = device_node_to_regmap(pdev->dev.parent->of_node);
588	if (IS_ERR(regmap))
589		return dev_err_probe(dev, PTR_ERR(regmap),
590				     "fail to get the regmap for PLL\n");
591
592	desc = (const struct sg2044_pll_desc_data *)platform_get_device_id(pdev)->driver_data;
593	if (!desc)
594		return dev_err_probe(dev, -EINVAL, "no match data for platform\n");
595
596	ctrl = devm_kzalloc(dev, struct_size(ctrl, data.hws, desc->num_pll), GFP_KERNEL);
597	if (!ctrl)
598		return -ENOMEM;
599
600	ctrl->data.num = desc->num_pll;
601
602	return sg2044_pll_init_ctrl(dev, regmap, ctrl, desc);
603}
604
605static const struct sg2044_pll_desc_data sg2044_pll_desc_data = {
606	.pll = sg2044_pll_commons,
607	.num_pll = ARRAY_SIZE(sg2044_pll_commons),
608};
609
610static const struct platform_device_id sg2044_pll_match[] = {
611	{ .name = "sg2044-pll",
612	  .driver_data = (unsigned long)&sg2044_pll_desc_data },
613	{ /* sentinel */ }
614};
615MODULE_DEVICE_TABLE(platform, sg2044_pll_match);
616
617static struct platform_driver sg2044_clk_driver = {
618	.probe = sg2044_pll_probe,
619	.driver = {
620		.name = "sg2044-pll",
621	},
622	.id_table = sg2044_pll_match,
623};
624module_platform_driver(sg2044_clk_driver);
625
626MODULE_AUTHOR("Inochi Amaoto <inochiama@gmail.com>");
627MODULE_DESCRIPTION("Sophgo SG2044 pll clock driver");
628MODULE_LICENSE("GPL");
~/ Read-only file preview.