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
= devm_kstrdup(dev
, 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
)
109 char prop_name
[MAX_PROP_SIZE
];
110 struct ufs_vreg
*vreg
= NULL
;
111 struct device_node
*np
= dev
->of_node
;
114 dev_err(dev
, "%s: non DT initialization\n", __func__
);
118 snprintf(prop_name
, MAX_PROP_SIZE
, "%s-supply", name
);
119 if (!of_parse_phandle(np
, prop_name
, 0)) {
120 dev_info(dev
, "%s: Unable to find %s regulator, assuming enabled\n",
121 __func__
, prop_name
);
125 vreg
= devm_kzalloc(dev
, sizeof(*vreg
), GFP_KERNEL
);
129 vreg
->name
= devm_kstrdup(dev
, name
, GFP_KERNEL
);
131 snprintf(prop_name
, MAX_PROP_SIZE
, "%s-max-microamp", name
);
132 if (of_property_read_u32(np
, prop_name
, &vreg
->max_uA
)) {
133 dev_info(dev
, "%s: unable to find %s\n", __func__
, prop_name
);
142 * ufshcd_parse_regulator_info - get regulator info from device tree
143 * @hba: per adapter instance
145 * Get regulator info from device tree for vcc, vccq, vccq2 power supplies.
146 * If any of the supplies are not defined it is assumed that they are always-on
147 * and hence return zero. If the property is defined but parsing is failed
148 * then return corresponding error.
150 static int ufshcd_parse_regulator_info(struct ufs_hba
*hba
)
153 struct device
*dev
= hba
->dev
;
154 struct ufs_vreg_info
*info
= &hba
->vreg_info
;
156 err
= ufshcd_populate_vreg(dev
, "vdd-hba", &info
->vdd_hba
);
160 err
= ufshcd_populate_vreg(dev
, "vcc", &info
->vcc
);
164 err
= ufshcd_populate_vreg(dev
, "vccq", &info
->vccq
);
168 err
= ufshcd_populate_vreg(dev
, "vccq2", &info
->vccq2
);
173 void ufshcd_pltfrm_shutdown(struct platform_device
*pdev
)
175 ufshcd_shutdown((struct ufs_hba
*)platform_get_drvdata(pdev
));
177 EXPORT_SYMBOL_GPL(ufshcd_pltfrm_shutdown
);
179 static void ufshcd_init_lanes_per_dir(struct ufs_hba
*hba
)
181 struct device
*dev
= hba
->dev
;
184 ret
= of_property_read_u32(dev
->of_node
, "lanes-per-direction",
185 &hba
->lanes_per_direction
);
188 "%s: failed to read lanes-per-direction, ret=%d\n",
190 hba
->lanes_per_direction
= UFSHCD_DEFAULT_LANES_PER_DIRECTION
;
195 * ufshcd_get_pwr_dev_param - get finally agreed attributes for
197 * @pltfrm_param: pointer to platform parameters
198 * @dev_max: pointer to device attributes
199 * @agreed_pwr: returned agreed attributes
201 * Returns 0 on success, non-zero value on failure
203 int ufshcd_get_pwr_dev_param(struct ufs_dev_params
*pltfrm_param
,
204 struct ufs_pa_layer_attr
*dev_max
,
205 struct ufs_pa_layer_attr
*agreed_pwr
)
209 bool is_dev_sup_hs
= false;
210 bool is_pltfrm_max_hs
= false;
212 if (dev_max
->pwr_rx
== FAST_MODE
)
213 is_dev_sup_hs
= true;
215 if (pltfrm_param
->desired_working_mode
== UFS_HS_MODE
) {
216 is_pltfrm_max_hs
= true;
217 min_pltfrm_gear
= min_t(u32
, pltfrm_param
->hs_rx_gear
,
218 pltfrm_param
->hs_tx_gear
);
220 min_pltfrm_gear
= min_t(u32
, pltfrm_param
->pwm_rx_gear
,
221 pltfrm_param
->pwm_tx_gear
);
225 * device doesn't support HS but
226 * pltfrm_param->desired_working_mode is HS,
227 * thus device and pltfrm_param don't agree
229 if (!is_dev_sup_hs
&& is_pltfrm_max_hs
) {
230 pr_info("%s: device doesn't support HS\n",
233 } else if (is_dev_sup_hs
&& is_pltfrm_max_hs
) {
235 * since device supports HS, it supports FAST_MODE.
236 * since pltfrm_param->desired_working_mode is also HS
237 * then final decision (FAST/FASTAUTO) is done according
238 * to pltfrm_params as it is the restricting factor
240 agreed_pwr
->pwr_rx
= pltfrm_param
->rx_pwr_hs
;
241 agreed_pwr
->pwr_tx
= agreed_pwr
->pwr_rx
;
244 * here pltfrm_param->desired_working_mode is PWM.
245 * it doesn't matter whether device supports HS or PWM,
246 * in both cases pltfrm_param->desired_working_mode will
249 agreed_pwr
->pwr_rx
= pltfrm_param
->rx_pwr_pwm
;
250 agreed_pwr
->pwr_tx
= agreed_pwr
->pwr_rx
;
254 * we would like tx to work in the minimum number of lanes
255 * between device capability and vendor preferences.
256 * the same decision will be made for rx
258 agreed_pwr
->lane_tx
= min_t(u32
, dev_max
->lane_tx
,
259 pltfrm_param
->tx_lanes
);
260 agreed_pwr
->lane_rx
= min_t(u32
, dev_max
->lane_rx
,
261 pltfrm_param
->rx_lanes
);
263 /* device maximum gear is the minimum between device rx and tx gears */
264 min_dev_gear
= min_t(u32
, dev_max
->gear_rx
, dev_max
->gear_tx
);
267 * if both device capabilities and vendor pre-defined preferences are
268 * both HS or both PWM then set the minimum gear to be the chosen
270 * if one is PWM and one is HS then the one that is PWM get to decide
271 * what is the gear, as it is the one that also decided previously what
272 * pwr the device will be configured to.
274 if ((is_dev_sup_hs
&& is_pltfrm_max_hs
) ||
275 (!is_dev_sup_hs
&& !is_pltfrm_max_hs
)) {
276 agreed_pwr
->gear_rx
=
277 min_t(u32
, min_dev_gear
, min_pltfrm_gear
);
278 } else if (!is_dev_sup_hs
) {
279 agreed_pwr
->gear_rx
= min_dev_gear
;
281 agreed_pwr
->gear_rx
= min_pltfrm_gear
;
283 agreed_pwr
->gear_tx
= agreed_pwr
->gear_rx
;
285 agreed_pwr
->hs_rate
= pltfrm_param
->hs_rate
;
289 EXPORT_SYMBOL_GPL(ufshcd_get_pwr_dev_param
);
291 void ufshcd_init_pwr_dev_param(struct ufs_dev_params
*dev_param
)
293 dev_param
->tx_lanes
= 2;
294 dev_param
->rx_lanes
= 2;
295 dev_param
->hs_rx_gear
= UFS_HS_G3
;
296 dev_param
->hs_tx_gear
= UFS_HS_G3
;
297 dev_param
->pwm_rx_gear
= UFS_PWM_G4
;
298 dev_param
->pwm_tx_gear
= UFS_PWM_G4
;
299 dev_param
->rx_pwr_pwm
= SLOW_MODE
;
300 dev_param
->tx_pwr_pwm
= SLOW_MODE
;
301 dev_param
->rx_pwr_hs
= FAST_MODE
;
302 dev_param
->tx_pwr_hs
= FAST_MODE
;
303 dev_param
->hs_rate
= PA_HS_MODE_B
;
304 dev_param
->desired_working_mode
= UFS_HS_MODE
;
306 EXPORT_SYMBOL_GPL(ufshcd_init_pwr_dev_param
);
309 * ufshcd_pltfrm_init - probe routine of the driver
310 * @pdev: pointer to Platform device handle
311 * @vops: pointer to variant ops
313 * Returns 0 on success, non-zero value on failure
315 int ufshcd_pltfrm_init(struct platform_device
*pdev
,
316 const struct ufs_hba_variant_ops
*vops
)
319 void __iomem
*mmio_base
;
321 struct device
*dev
= &pdev
->dev
;
323 mmio_base
= devm_platform_ioremap_resource(pdev
, 0);
324 if (IS_ERR(mmio_base
)) {
325 err
= PTR_ERR(mmio_base
);
329 irq
= platform_get_irq(pdev
, 0);
335 err
= ufshcd_alloc_host(dev
, &hba
);
337 dev_err(&pdev
->dev
, "Allocation failed\n");
343 err
= ufshcd_parse_clock_info(hba
);
345 dev_err(&pdev
->dev
, "%s: clock parse failed %d\n",
349 err
= ufshcd_parse_regulator_info(hba
);
351 dev_err(&pdev
->dev
, "%s: regulator init failed %d\n",
356 ufshcd_init_lanes_per_dir(hba
);
358 err
= ufshcd_init(hba
, mmio_base
, irq
);
360 dev_err(dev
, "Initialization failed\n");
364 pm_runtime_set_active(&pdev
->dev
);
365 pm_runtime_enable(&pdev
->dev
);
370 ufshcd_dealloc_host(hba
);
374 EXPORT_SYMBOL_GPL(ufshcd_pltfrm_init
);
376 MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
377 MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
378 MODULE_DESCRIPTION("UFS host controller Platform bus based glue driver");
379 MODULE_LICENSE("GPL");
380 MODULE_VERSION(UFSHCD_DRIVER_VERSION
);