1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Universal Flash Storage Host controller Platform bus based glue driver
4 * Copyright (C) 2011-2013 Samsung India Software Operations
7 * Santosh Yaraganavi <santosh.sy@samsung.com>
8 * Vinayak Holikatti <h.vinayak@samsung.com>
11 #include <linux/platform_device.h>
12 #include <linux/pm_runtime.h>
16 #include "ufshcd-pltfrm.h"
19 #define UFSHCD_DEFAULT_LANES_PER_DIRECTION 2
21 static int ufshcd_parse_clock_info(struct ufs_hba
*hba
)
26 struct device
*dev
= hba
->dev
;
27 struct device_node
*np
= dev
->of_node
;
30 struct ufs_clk_info
*clki
;
37 cnt
= of_property_count_strings(np
, "clock-names");
38 if (!cnt
|| (cnt
== -EINVAL
)) {
39 dev_info(dev
, "%s: Unable to find clocks, assuming enabled\n",
42 dev_err(dev
, "%s: count clock strings failed, err %d\n",
50 if (!of_get_property(np
, "freq-table-hz", &len
)) {
51 dev_info(dev
, "freq-table-hz property not specified\n");
58 sz
= len
/ sizeof(*clkfreq
);
60 dev_err(dev
, "%s len mismatch\n", "freq-table-hz");
65 clkfreq
= devm_kcalloc(dev
, sz
, sizeof(*clkfreq
),
72 ret
= of_property_read_u32_array(np
, "freq-table-hz",
74 if (ret
&& (ret
!= -EINVAL
)) {
75 dev_err(dev
, "%s: error reading array %d\n",
76 "freq-table-hz", ret
);
80 for (i
= 0; i
< sz
; i
+= 2) {
81 ret
= of_property_read_string_index(np
,
82 "clock-names", i
/2, (const char **)&name
);
86 clki
= devm_kzalloc(dev
, sizeof(*clki
), GFP_KERNEL
);
92 clki
->min_freq
= clkfreq
[i
];
93 clki
->max_freq
= clkfreq
[i
+1];
94 clki
->name
= kstrdup(name
, GFP_KERNEL
);
95 if (!strcmp(name
, "ref_clk"))
96 clki
->keep_link_active
= true;
97 dev_dbg(dev
, "%s: min %u max %u name %s\n", "freq-table-hz",
98 clki
->min_freq
, clki
->max_freq
, clki
->name
);
99 list_add_tail(&clki
->list
, &hba
->clk_list_head
);
105 #define MAX_PROP_SIZE 32
106 static int ufshcd_populate_vreg(struct device
*dev
, const char *name
,
107 struct ufs_vreg
**out_vreg
)
110 char prop_name
[MAX_PROP_SIZE
];
111 struct ufs_vreg
*vreg
= NULL
;
112 struct device_node
*np
= dev
->of_node
;
115 dev_err(dev
, "%s: non DT initialization\n", __func__
);
119 snprintf(prop_name
, MAX_PROP_SIZE
, "%s-supply", name
);
120 if (!of_parse_phandle(np
, prop_name
, 0)) {
121 dev_info(dev
, "%s: Unable to find %s regulator, assuming enabled\n",
122 __func__
, prop_name
);
126 vreg
= devm_kzalloc(dev
, sizeof(*vreg
), GFP_KERNEL
);
130 vreg
->name
= kstrdup(name
, GFP_KERNEL
);
132 snprintf(prop_name
, MAX_PROP_SIZE
, "%s-max-microamp", name
);
133 if (of_property_read_u32(np
, prop_name
, &vreg
->max_uA
)) {
134 dev_info(dev
, "%s: unable to find %s\n", __func__
, prop_name
);
144 * ufshcd_parse_regulator_info - get regulator info from device tree
145 * @hba: per adapter instance
147 * Get regulator info from device tree for vcc, vccq, vccq2 power supplies.
148 * If any of the supplies are not defined it is assumed that they are always-on
149 * and hence return zero. If the property is defined but parsing is failed
150 * then return corresponding error.
152 static int ufshcd_parse_regulator_info(struct ufs_hba
*hba
)
155 struct device
*dev
= hba
->dev
;
156 struct ufs_vreg_info
*info
= &hba
->vreg_info
;
158 err
= ufshcd_populate_vreg(dev
, "vdd-hba", &info
->vdd_hba
);
162 err
= ufshcd_populate_vreg(dev
, "vcc", &info
->vcc
);
166 err
= ufshcd_populate_vreg(dev
, "vccq", &info
->vccq
);
170 err
= ufshcd_populate_vreg(dev
, "vccq2", &info
->vccq2
);
177 * ufshcd_pltfrm_suspend - suspend power management function
178 * @dev: pointer to device handle
180 * Returns 0 if successful
181 * Returns non-zero otherwise
183 int ufshcd_pltfrm_suspend(struct device
*dev
)
185 return ufshcd_system_suspend(dev_get_drvdata(dev
));
187 EXPORT_SYMBOL_GPL(ufshcd_pltfrm_suspend
);
190 * ufshcd_pltfrm_resume - resume power management function
191 * @dev: pointer to device handle
193 * Returns 0 if successful
194 * Returns non-zero otherwise
196 int ufshcd_pltfrm_resume(struct device
*dev
)
198 return ufshcd_system_resume(dev_get_drvdata(dev
));
200 EXPORT_SYMBOL_GPL(ufshcd_pltfrm_resume
);
202 int ufshcd_pltfrm_runtime_suspend(struct device
*dev
)
204 return ufshcd_runtime_suspend(dev_get_drvdata(dev
));
206 EXPORT_SYMBOL_GPL(ufshcd_pltfrm_runtime_suspend
);
208 int ufshcd_pltfrm_runtime_resume(struct device
*dev
)
210 return ufshcd_runtime_resume(dev_get_drvdata(dev
));
212 EXPORT_SYMBOL_GPL(ufshcd_pltfrm_runtime_resume
);
214 int ufshcd_pltfrm_runtime_idle(struct device
*dev
)
216 return ufshcd_runtime_idle(dev_get_drvdata(dev
));
218 EXPORT_SYMBOL_GPL(ufshcd_pltfrm_runtime_idle
);
220 #endif /* CONFIG_PM */
222 void ufshcd_pltfrm_shutdown(struct platform_device
*pdev
)
224 ufshcd_shutdown((struct ufs_hba
*)platform_get_drvdata(pdev
));
226 EXPORT_SYMBOL_GPL(ufshcd_pltfrm_shutdown
);
228 static void ufshcd_init_lanes_per_dir(struct ufs_hba
*hba
)
230 struct device
*dev
= hba
->dev
;
233 ret
= of_property_read_u32(dev
->of_node
, "lanes-per-direction",
234 &hba
->lanes_per_direction
);
237 "%s: failed to read lanes-per-direction, ret=%d\n",
239 hba
->lanes_per_direction
= UFSHCD_DEFAULT_LANES_PER_DIRECTION
;
244 * ufshcd_get_pwr_dev_param - get finally agreed attributes for
246 * @pltfrm_param: pointer to platform parameters
247 * @dev_max: pointer to device attributes
248 * @agreed_pwr: returned agreed attributes
250 * Returns 0 on success, non-zero value on failure
252 int ufshcd_get_pwr_dev_param(struct ufs_dev_params
*pltfrm_param
,
253 struct ufs_pa_layer_attr
*dev_max
,
254 struct ufs_pa_layer_attr
*agreed_pwr
)
258 bool is_dev_sup_hs
= false;
259 bool is_pltfrm_max_hs
= false;
261 if (dev_max
->pwr_rx
== FAST_MODE
)
262 is_dev_sup_hs
= true;
264 if (pltfrm_param
->desired_working_mode
== UFS_HS_MODE
) {
265 is_pltfrm_max_hs
= true;
266 min_pltfrm_gear
= min_t(u32
, pltfrm_param
->hs_rx_gear
,
267 pltfrm_param
->hs_tx_gear
);
269 min_pltfrm_gear
= min_t(u32
, pltfrm_param
->pwm_rx_gear
,
270 pltfrm_param
->pwm_tx_gear
);
274 * device doesn't support HS but
275 * pltfrm_param->desired_working_mode is HS,
276 * thus device and pltfrm_param don't agree
278 if (!is_dev_sup_hs
&& is_pltfrm_max_hs
) {
279 pr_info("%s: device doesn't support HS\n",
282 } else if (is_dev_sup_hs
&& is_pltfrm_max_hs
) {
284 * since device supports HS, it supports FAST_MODE.
285 * since pltfrm_param->desired_working_mode is also HS
286 * then final decision (FAST/FASTAUTO) is done according
287 * to pltfrm_params as it is the restricting factor
289 agreed_pwr
->pwr_rx
= pltfrm_param
->rx_pwr_hs
;
290 agreed_pwr
->pwr_tx
= agreed_pwr
->pwr_rx
;
293 * here pltfrm_param->desired_working_mode is PWM.
294 * it doesn't matter whether device supports HS or PWM,
295 * in both cases pltfrm_param->desired_working_mode will
298 agreed_pwr
->pwr_rx
= pltfrm_param
->rx_pwr_pwm
;
299 agreed_pwr
->pwr_tx
= agreed_pwr
->pwr_rx
;
303 * we would like tx to work in the minimum number of lanes
304 * between device capability and vendor preferences.
305 * the same decision will be made for rx
307 agreed_pwr
->lane_tx
= min_t(u32
, dev_max
->lane_tx
,
308 pltfrm_param
->tx_lanes
);
309 agreed_pwr
->lane_rx
= min_t(u32
, dev_max
->lane_rx
,
310 pltfrm_param
->rx_lanes
);
312 /* device maximum gear is the minimum between device rx and tx gears */
313 min_dev_gear
= min_t(u32
, dev_max
->gear_rx
, dev_max
->gear_tx
);
316 * if both device capabilities and vendor pre-defined preferences are
317 * both HS or both PWM then set the minimum gear to be the chosen
319 * if one is PWM and one is HS then the one that is PWM get to decide
320 * what is the gear, as it is the one that also decided previously what
321 * pwr the device will be configured to.
323 if ((is_dev_sup_hs
&& is_pltfrm_max_hs
) ||
324 (!is_dev_sup_hs
&& !is_pltfrm_max_hs
)) {
325 agreed_pwr
->gear_rx
=
326 min_t(u32
, min_dev_gear
, min_pltfrm_gear
);
327 } else if (!is_dev_sup_hs
) {
328 agreed_pwr
->gear_rx
= min_dev_gear
;
330 agreed_pwr
->gear_rx
= min_pltfrm_gear
;
332 agreed_pwr
->gear_tx
= agreed_pwr
->gear_rx
;
334 agreed_pwr
->hs_rate
= pltfrm_param
->hs_rate
;
338 EXPORT_SYMBOL_GPL(ufshcd_get_pwr_dev_param
);
340 void ufshcd_init_pwr_dev_param(struct ufs_dev_params
*dev_param
)
342 dev_param
->tx_lanes
= 2;
343 dev_param
->rx_lanes
= 2;
344 dev_param
->hs_rx_gear
= UFS_HS_G3
;
345 dev_param
->hs_tx_gear
= UFS_HS_G3
;
346 dev_param
->pwm_rx_gear
= UFS_PWM_G4
;
347 dev_param
->pwm_tx_gear
= UFS_PWM_G4
;
348 dev_param
->rx_pwr_pwm
= SLOW_MODE
;
349 dev_param
->tx_pwr_pwm
= SLOW_MODE
;
350 dev_param
->rx_pwr_hs
= FAST_MODE
;
351 dev_param
->tx_pwr_hs
= FAST_MODE
;
352 dev_param
->hs_rate
= PA_HS_MODE_B
;
353 dev_param
->desired_working_mode
= UFS_HS_MODE
;
355 EXPORT_SYMBOL_GPL(ufshcd_init_pwr_dev_param
);
358 * ufshcd_pltfrm_init - probe routine of the driver
359 * @pdev: pointer to Platform device handle
360 * @vops: pointer to variant ops
362 * Returns 0 on success, non-zero value on failure
364 int ufshcd_pltfrm_init(struct platform_device
*pdev
,
365 const struct ufs_hba_variant_ops
*vops
)
368 void __iomem
*mmio_base
;
370 struct device
*dev
= &pdev
->dev
;
372 mmio_base
= devm_platform_ioremap_resource(pdev
, 0);
373 if (IS_ERR(mmio_base
)) {
374 err
= PTR_ERR(mmio_base
);
378 irq
= platform_get_irq(pdev
, 0);
384 err
= ufshcd_alloc_host(dev
, &hba
);
386 dev_err(&pdev
->dev
, "Allocation failed\n");
392 err
= ufshcd_parse_clock_info(hba
);
394 dev_err(&pdev
->dev
, "%s: clock parse failed %d\n",
398 err
= ufshcd_parse_regulator_info(hba
);
400 dev_err(&pdev
->dev
, "%s: regulator init failed %d\n",
405 ufshcd_init_lanes_per_dir(hba
);
407 err
= ufshcd_init(hba
, mmio_base
, irq
);
409 dev_err(dev
, "Initialization failed\n");
413 platform_set_drvdata(pdev
, hba
);
415 pm_runtime_set_active(&pdev
->dev
);
416 pm_runtime_enable(&pdev
->dev
);
421 ufshcd_dealloc_host(hba
);
425 EXPORT_SYMBOL_GPL(ufshcd_pltfrm_init
);
427 MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
428 MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
429 MODULE_DESCRIPTION("UFS host controller Platform bus based glue driver");
430 MODULE_LICENSE("GPL");
431 MODULE_VERSION(UFSHCD_DRIVER_VERSION
);