forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-01-04 1543e317f1da31b75942316931e8f491a8920811
kernel/drivers/scsi/ufs/ufshcd-pltfrm.c
....@@ -1,36 +1,11 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Universal Flash Storage Host controller Platform bus based glue driver
3
- *
4
- * This code is based on drivers/scsi/ufs/ufshcd-pltfrm.c
54 * Copyright (C) 2011-2013 Samsung India Software Operations
65 *
76 * Authors:
87 * Santosh Yaraganavi <santosh.sy@samsung.com>
98 * Vinayak Holikatti <h.vinayak@samsung.com>
10
- *
11
- * This program is free software; you can redistribute it and/or
12
- * modify it under the terms of the GNU General Public License
13
- * as published by the Free Software Foundation; either version 2
14
- * of the License, or (at your option) any later version.
15
- * See the COPYING file in the top-level directory or visit
16
- * <http://www.gnu.org/licenses/gpl-2.0.html>
17
- *
18
- * This program is distributed in the hope that it will be useful,
19
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
- * GNU General Public License for more details.
22
- *
23
- * This program is provided "AS IS" and "WITH ALL FAULTS" and
24
- * without warranty of any kind. You are solely responsible for
25
- * determining the appropriateness of using and distributing
26
- * the program and assume all risks associated with your exercise
27
- * of rights with respect to the program, including but not limited
28
- * to infringement of third party rights, the risks and costs of
29
- * program errors, damage to or loss of data, programs or equipment,
30
- * and unavailability or interruption of operations. Under no
31
- * circumstances will the contributor of this Program be liable for
32
- * any damages of any kind arising from your use or distribution of
33
- * this program.
349 */
3510
3611 #include <linux/platform_device.h>
....@@ -39,6 +14,7 @@
3914
4015 #include "ufshcd.h"
4116 #include "ufshcd-pltfrm.h"
17
+#include "unipro.h"
4218
4319 #define UFSHCD_DEFAULT_LANES_PER_DIRECTION 2
4420
....@@ -115,7 +91,14 @@
11591
11692 clki->min_freq = clkfreq[i];
11793 clki->max_freq = clkfreq[i+1];
118
- clki->name = kstrdup(name, GFP_KERNEL);
94
+ clki->name = devm_kstrdup(dev, name, GFP_KERNEL);
95
+ if (!clki->name) {
96
+ ret = -ENOMEM;
97
+ goto out;
98
+ }
99
+
100
+ if (!strcmp(name, "ref_clk"))
101
+ clki->keep_link_active = true;
119102 dev_dbg(dev, "%s: min %u max %u name %s\n", "freq-table-hz",
120103 clki->min_freq, clki->max_freq, clki->name);
121104 list_add_tail(&clki->list, &hba->clk_list_head);
....@@ -124,9 +107,20 @@
124107 return ret;
125108 }
126109
110
+static bool phandle_exists(const struct device_node *np,
111
+ const char *phandle_name, int index)
112
+{
113
+ struct device_node *parse_np = of_parse_phandle(np, phandle_name, index);
114
+
115
+ if (parse_np)
116
+ of_node_put(parse_np);
117
+
118
+ return parse_np != NULL;
119
+}
120
+
127121 #define MAX_PROP_SIZE 32
128122 static int ufshcd_populate_vreg(struct device *dev, const char *name,
129
- struct ufs_vreg **out_vreg)
123
+ struct ufs_vreg **out_vreg)
130124 {
131125 int ret = 0;
132126 char prop_name[MAX_PROP_SIZE];
....@@ -139,7 +133,7 @@
139133 }
140134
141135 snprintf(prop_name, MAX_PROP_SIZE, "%s-supply", name);
142
- if (!of_parse_phandle(np, prop_name, 0)) {
136
+ if (!phandle_exists(np, prop_name, 0)) {
143137 dev_info(dev, "%s: Unable to find %s regulator, assuming enabled\n",
144138 __func__, prop_name);
145139 goto out;
....@@ -149,40 +143,15 @@
149143 if (!vreg)
150144 return -ENOMEM;
151145
152
- vreg->name = kstrdup(name, GFP_KERNEL);
153
-
154
- /* if fixed regulator no need further initialization */
155
- snprintf(prop_name, MAX_PROP_SIZE, "%s-fixed-regulator", name);
156
- if (of_property_read_bool(np, prop_name))
157
- goto out;
146
+ vreg->name = devm_kstrdup(dev, name, GFP_KERNEL);
147
+ if (!vreg->name)
148
+ return -ENOMEM;
158149
159150 snprintf(prop_name, MAX_PROP_SIZE, "%s-max-microamp", name);
160
- ret = of_property_read_u32(np, prop_name, &vreg->max_uA);
161
- if (ret) {
162
- dev_err(dev, "%s: unable to find %s err %d\n",
163
- __func__, prop_name, ret);
164
- goto out;
151
+ if (of_property_read_u32(np, prop_name, &vreg->max_uA)) {
152
+ dev_info(dev, "%s: unable to find %s\n", __func__, prop_name);
153
+ vreg->max_uA = 0;
165154 }
166
-
167
- vreg->min_uA = 0;
168
- if (!strcmp(name, "vcc")) {
169
- if (of_property_read_bool(np, "vcc-supply-1p8")) {
170
- vreg->min_uV = UFS_VREG_VCC_1P8_MIN_UV;
171
- vreg->max_uV = UFS_VREG_VCC_1P8_MAX_UV;
172
- } else {
173
- vreg->min_uV = UFS_VREG_VCC_MIN_UV;
174
- vreg->max_uV = UFS_VREG_VCC_MAX_UV;
175
- }
176
- } else if (!strcmp(name, "vccq")) {
177
- vreg->min_uV = UFS_VREG_VCCQ_MIN_UV;
178
- vreg->max_uV = UFS_VREG_VCCQ_MAX_UV;
179
- } else if (!strcmp(name, "vccq2")) {
180
- vreg->min_uV = UFS_VREG_VCCQ2_MIN_UV;
181
- vreg->max_uV = UFS_VREG_VCCQ2_MAX_UV;
182
- }
183
-
184
- goto out;
185
-
186155 out:
187156 if (!ret)
188157 *out_vreg = vreg;
....@@ -290,6 +259,103 @@
290259 }
291260
292261 /**
262
+ * ufshcd_get_pwr_dev_param - get finally agreed attributes for
263
+ * power mode change
264
+ * @pltfrm_param: pointer to platform parameters
265
+ * @dev_max: pointer to device attributes
266
+ * @agreed_pwr: returned agreed attributes
267
+ *
268
+ * Returns 0 on success, non-zero value on failure
269
+ */
270
+int ufshcd_get_pwr_dev_param(struct ufs_dev_params *pltfrm_param,
271
+ struct ufs_pa_layer_attr *dev_max,
272
+ struct ufs_pa_layer_attr *agreed_pwr)
273
+{
274
+ int min_pltfrm_gear;
275
+ int min_dev_gear;
276
+ bool is_dev_sup_hs = false;
277
+ bool is_pltfrm_max_hs = false;
278
+
279
+ if (dev_max->pwr_rx == FAST_MODE)
280
+ is_dev_sup_hs = true;
281
+
282
+ if (pltfrm_param->desired_working_mode == UFS_HS_MODE) {
283
+ is_pltfrm_max_hs = true;
284
+ min_pltfrm_gear = min_t(u32, pltfrm_param->hs_rx_gear,
285
+ pltfrm_param->hs_tx_gear);
286
+ } else {
287
+ min_pltfrm_gear = min_t(u32, pltfrm_param->pwm_rx_gear,
288
+ pltfrm_param->pwm_tx_gear);
289
+ }
290
+
291
+ /*
292
+ * device doesn't support HS but
293
+ * pltfrm_param->desired_working_mode is HS,
294
+ * thus device and pltfrm_param don't agree
295
+ */
296
+ if (!is_dev_sup_hs && is_pltfrm_max_hs) {
297
+ pr_info("%s: device doesn't support HS\n",
298
+ __func__);
299
+ return -ENOTSUPP;
300
+ } else if (is_dev_sup_hs && is_pltfrm_max_hs) {
301
+ /*
302
+ * since device supports HS, it supports FAST_MODE.
303
+ * since pltfrm_param->desired_working_mode is also HS
304
+ * then final decision (FAST/FASTAUTO) is done according
305
+ * to pltfrm_params as it is the restricting factor
306
+ */
307
+ agreed_pwr->pwr_rx = pltfrm_param->rx_pwr_hs;
308
+ agreed_pwr->pwr_tx = agreed_pwr->pwr_rx;
309
+ } else {
310
+ /*
311
+ * here pltfrm_param->desired_working_mode is PWM.
312
+ * it doesn't matter whether device supports HS or PWM,
313
+ * in both cases pltfrm_param->desired_working_mode will
314
+ * determine the mode
315
+ */
316
+ agreed_pwr->pwr_rx = pltfrm_param->rx_pwr_pwm;
317
+ agreed_pwr->pwr_tx = agreed_pwr->pwr_rx;
318
+ }
319
+
320
+ /*
321
+ * we would like tx to work in the minimum number of lanes
322
+ * between device capability and vendor preferences.
323
+ * the same decision will be made for rx
324
+ */
325
+ agreed_pwr->lane_tx = min_t(u32, dev_max->lane_tx,
326
+ pltfrm_param->tx_lanes);
327
+ agreed_pwr->lane_rx = min_t(u32, dev_max->lane_rx,
328
+ pltfrm_param->rx_lanes);
329
+
330
+ /* device maximum gear is the minimum between device rx and tx gears */
331
+ min_dev_gear = min_t(u32, dev_max->gear_rx, dev_max->gear_tx);
332
+
333
+ /*
334
+ * if both device capabilities and vendor pre-defined preferences are
335
+ * both HS or both PWM then set the minimum gear to be the chosen
336
+ * working gear.
337
+ * if one is PWM and one is HS then the one that is PWM get to decide
338
+ * what is the gear, as it is the one that also decided previously what
339
+ * pwr the device will be configured to.
340
+ */
341
+ if ((is_dev_sup_hs && is_pltfrm_max_hs) ||
342
+ (!is_dev_sup_hs && !is_pltfrm_max_hs)) {
343
+ agreed_pwr->gear_rx =
344
+ min_t(u32, min_dev_gear, min_pltfrm_gear);
345
+ } else if (!is_dev_sup_hs) {
346
+ agreed_pwr->gear_rx = min_dev_gear;
347
+ } else {
348
+ agreed_pwr->gear_rx = min_pltfrm_gear;
349
+ }
350
+ agreed_pwr->gear_tx = agreed_pwr->gear_rx;
351
+
352
+ agreed_pwr->hs_rate = pltfrm_param->hs_rate;
353
+
354
+ return 0;
355
+}
356
+EXPORT_SYMBOL_GPL(ufshcd_get_pwr_dev_param);
357
+
358
+/**
293359 * ufshcd_pltfrm_init - probe routine of the driver
294360 * @pdev: pointer to Platform device handle
295361 * @vops: pointer to variant ops
....@@ -297,16 +363,14 @@
297363 * Returns 0 on success, non-zero value on failure
298364 */
299365 int ufshcd_pltfrm_init(struct platform_device *pdev,
300
- struct ufs_hba_variant_ops *vops)
366
+ const struct ufs_hba_variant_ops *vops)
301367 {
302368 struct ufs_hba *hba;
303369 void __iomem *mmio_base;
304
- struct resource *mem_res;
305370 int irq, err;
306371 struct device *dev = &pdev->dev;
307372
308
- mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
309
- mmio_base = devm_ioremap_resource(dev, mem_res);
373
+ mmio_base = devm_platform_ioremap_resource(pdev, 0);
310374 if (IS_ERR(mmio_base)) {
311375 err = PTR_ERR(mmio_base);
312376 goto out;
....@@ -314,8 +378,7 @@
314378
315379 irq = platform_get_irq(pdev, 0);
316380 if (irq < 0) {
317
- dev_err(dev, "IRQ resource not available\n");
318
- err = -ENODEV;
381
+ err = irq;
319382 goto out;
320383 }
321384