blob: ea4d8f575ac6524676550789e93beb143cdb7cff [file] [log] [blame]
Ashish Jangam08bf1c02011-12-09 19:48:20 +05301/*
2* da9052-regulator.c: Regulator driver for DA9052
3*
4* Copyright(c) 2011 Dialog Semiconductor Ltd.
5*
6* Author: David Dajun Chen <dchen@diasemi.com>
7*
8* This program is free software; you can redistribute it and/or modify
9* it under the terms of the GNU General Public License as published by
10* the Free Software Foundation; either version 2 of the License, or
11* (at your option) any later version.
12*
13*/
14
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/init.h>
18#include <linux/err.h>
19#include <linux/platform_device.h>
20#include <linux/regulator/driver.h>
21#include <linux/regulator/machine.h>
22
23#include <linux/mfd/da9052/da9052.h>
24#include <linux/mfd/da9052/reg.h>
25#include <linux/mfd/da9052/pdata.h>
26
27/* Buck step size */
28#define DA9052_BUCK_PERI_3uV_STEP 100000
29#define DA9052_BUCK_PERI_REG_MAP_UPTO_3uV 24
30#define DA9052_CONST_3uV 3000000
31
32#define DA9052_MIN_UA 0
33#define DA9052_MAX_UA 3
34#define DA9052_CURRENT_RANGE 4
35
36/* Bit masks */
37#define DA9052_BUCK_ILIM_MASK_EVEN 0x0c
38#define DA9052_BUCK_ILIM_MASK_ODD 0xc0
39
40static const u32 da9052_current_limits[3][4] = {
41 {700000, 800000, 1000000, 1200000}, /* DA9052-BC BUCKs */
42 {1600000, 2000000, 2400000, 3000000}, /* DA9053-AA/Bx BUCK-CORE */
43 {800000, 1000000, 1200000, 1500000}, /* DA9053-AA/Bx BUCK-PRO,
44 * BUCK-MEM and BUCK-PERI
45 */
46};
47
48struct da9052_regulator_info {
49 struct regulator_desc reg_desc;
50 int step_uV;
51 int min_uV;
52 int max_uV;
53 unsigned char volt_shift;
54 unsigned char en_bit;
55 unsigned char activate_bit;
56};
57
58struct da9052_regulator {
59 struct da9052 *da9052;
60 struct da9052_regulator_info *info;
61 struct regulator_dev *rdev;
62};
63
64static int verify_range(struct da9052_regulator_info *info,
65 int min_uV, int max_uV)
66{
67 if (min_uV > info->max_uV || max_uV < info->min_uV)
68 return -EINVAL;
69
70 return 0;
71}
72
73static int da9052_regulator_enable(struct regulator_dev *rdev)
74{
75 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
76 struct da9052_regulator_info *info = regulator->info;
77 int offset = rdev_get_id(rdev);
78
79 return da9052_reg_update(regulator->da9052,
80 DA9052_BUCKCORE_REG + offset,
81 1 << info->en_bit, 1 << info->en_bit);
82}
83
84static int da9052_regulator_disable(struct regulator_dev *rdev)
85{
86 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
87 struct da9052_regulator_info *info = regulator->info;
88 int offset = rdev_get_id(rdev);
89
90 return da9052_reg_update(regulator->da9052,
91 DA9052_BUCKCORE_REG + offset,
92 1 << info->en_bit, 0);
93}
94
95static int da9052_regulator_is_enabled(struct regulator_dev *rdev)
96{
97 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
98 struct da9052_regulator_info *info = regulator->info;
99 int offset = rdev_get_id(rdev);
100 int ret;
101
102 ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset);
103 if (ret < 0)
104 return ret;
105
106 return ret & (1 << info->en_bit);
107}
108
109static int da9052_dcdc_get_current_limit(struct regulator_dev *rdev)
110{
111 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
112 int offset = rdev_get_id(rdev);
113 int ret, row = 2;
114
115 ret = da9052_reg_read(regulator->da9052, DA9052_BUCKA_REG + offset/2);
116 if (ret < 0)
117 return ret;
118
119 /* Determine the even or odd position of the buck current limit
120 * register field
121 */
122 if (offset % 2 == 0)
123 ret = (ret & DA9052_BUCK_ILIM_MASK_EVEN) >> 2;
124 else
125 ret = (ret & DA9052_BUCK_ILIM_MASK_ODD) >> 6;
126
127 /* Select the appropriate current limit range */
128 if (regulator->da9052->chip_id == DA9052)
129 row = 0;
130 else if (offset == 0)
131 row = 1;
132
133 return da9052_current_limits[row][ret];
134}
135
136static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA,
137 int max_uA)
138{
139 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
140 int offset = rdev_get_id(rdev);
141 int reg_val = 0;
142 int i, row = 2;
143
144 /* Select the appropriate current limit range */
145 if (regulator->da9052->chip_id == DA9052)
146 row = 0;
147 else if (offset == 0)
148 row = 1;
149
150 if (min_uA > da9052_current_limits[row][DA9052_MAX_UA] ||
151 max_uA < da9052_current_limits[row][DA9052_MIN_UA])
152 return -EINVAL;
153
154 for (i = 0; i < DA9052_CURRENT_RANGE; i++) {
155 if (min_uA <= da9052_current_limits[row][i]) {
156 reg_val = i;
157 break;
158 }
159 }
160
161 /* Determine the even or odd position of the buck current limit
162 * register field
163 */
164 if (offset % 2 == 0)
165 return da9052_reg_update(regulator->da9052,
166 DA9052_BUCKA_REG + offset/2,
167 DA9052_BUCK_ILIM_MASK_EVEN,
168 reg_val << 2);
169 else
170 return da9052_reg_update(regulator->da9052,
171 DA9052_BUCKA_REG + offset/2,
172 DA9052_BUCK_ILIM_MASK_ODD,
173 reg_val << 6);
174}
175
176static int da9052_list_buckperi_voltage(struct regulator_dev *rdev,
177 unsigned int selector)
178{
179 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
180 struct da9052_regulator_info *info = regulator->info;
181 int volt_uV;
182
183 if ((regulator->da9052->chip_id == DA9052) &&
184 (selector >= DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)) {
185 volt_uV = ((DA9052_BUCK_PERI_REG_MAP_UPTO_3uV * info->step_uV)
186 + info->min_uV);
187 volt_uV += (selector - DA9052_BUCK_PERI_REG_MAP_UPTO_3uV)
188 * (DA9052_BUCK_PERI_3uV_STEP);
189 } else
190 volt_uV = (selector * info->step_uV) + info->min_uV;
191
192 if (volt_uV > info->max_uV)
193 return -EINVAL;
194
195 return volt_uV;
196}
197
198static int da9052_list_voltage(struct regulator_dev *rdev,
199 unsigned int selector)
200{
201 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
202 struct da9052_regulator_info *info = regulator->info;
203 int volt_uV;
204
205 volt_uV = info->min_uV + info->step_uV * selector;
206
207 if (volt_uV > info->max_uV)
208 return -EINVAL;
209
210 return volt_uV;
211}
212
213static int da9052_regulator_set_voltage_int(struct regulator_dev *rdev,
214 int min_uV, int max_uV,
215 unsigned int *selector)
216{
217 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
218 struct da9052_regulator_info *info = regulator->info;
219 int offset = rdev_get_id(rdev);
220 int ret;
221
222 ret = verify_range(info, min_uV, max_uV);
223 if (ret < 0)
224 return ret;
225
226 if (min_uV < info->min_uV)
227 min_uV = info->min_uV;
228
229 *selector = (min_uV - info->min_uV) / info->step_uV;
230
231 ret = da9052_list_voltage(rdev, *selector);
232 if (ret < 0)
233 return ret;
234
235 return da9052_reg_update(regulator->da9052,
236 DA9052_BUCKCORE_REG + offset,
237 (1 << info->volt_shift) - 1, *selector);
238}
239
240static int da9052_set_ldo_voltage(struct regulator_dev *rdev,
241 int min_uV, int max_uV,
242 unsigned int *selector)
243{
244 return da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector);
245}
246
247static int da9052_set_ldo5_6_voltage(struct regulator_dev *rdev,
248 int min_uV, int max_uV,
249 unsigned int *selector)
250{
251 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
252 struct da9052_regulator_info *info = regulator->info;
253 int ret;
254
255 ret = da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector);
256 if (ret < 0)
257 return ret;
258
259 /* Some LDOs are DVC controlled which requires enabling of
260 * the LDO activate bit to implment the changes on the
261 * LDO output.
262 */
Axel Lin4adf9be2012-03-02 18:07:21 +0800263 return da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG,
264 info->activate_bit, info->activate_bit);
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530265}
266
267static int da9052_set_dcdc_voltage(struct regulator_dev *rdev,
268 int min_uV, int max_uV,
269 unsigned int *selector)
270{
271 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
272 struct da9052_regulator_info *info = regulator->info;
273 int ret;
274
275 ret = da9052_regulator_set_voltage_int(rdev, min_uV, max_uV, selector);
276 if (ret < 0)
277 return ret;
278
279 /* Some DCDCs are DVC controlled which requires enabling of
280 * the DCDC activate bit to implment the changes on the
281 * DCDC output.
282 */
Axel Lin4adf9be2012-03-02 18:07:21 +0800283 return da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG,
284 info->activate_bit, info->activate_bit);
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530285}
286
287static int da9052_get_regulator_voltage_sel(struct regulator_dev *rdev)
288{
289 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
290 struct da9052_regulator_info *info = regulator->info;
291 int offset = rdev_get_id(rdev);
292 int ret;
293
294 ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset);
295 if (ret < 0)
296 return ret;
297
298 ret &= ((1 << info->volt_shift) - 1);
299
300 return ret;
301}
302
303static int da9052_set_buckperi_voltage(struct regulator_dev *rdev, int min_uV,
304 int max_uV, unsigned int *selector)
305{
306 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
307 struct da9052_regulator_info *info = regulator->info;
308 int offset = rdev_get_id(rdev);
309 int ret;
310
311 ret = verify_range(info, min_uV, max_uV);
312 if (ret < 0)
313 return ret;
314
315 if (min_uV < info->min_uV)
316 min_uV = info->min_uV;
317
318 if ((regulator->da9052->chip_id == DA9052) &&
319 (min_uV >= DA9052_CONST_3uV))
320 *selector = DA9052_BUCK_PERI_REG_MAP_UPTO_3uV +
321 ((min_uV - DA9052_CONST_3uV) /
322 (DA9052_BUCK_PERI_3uV_STEP));
323 else
324 *selector = (min_uV - info->min_uV) / info->step_uV;
325
326 ret = da9052_list_buckperi_voltage(rdev, *selector);
327 if (ret < 0)
328 return ret;
329
330 return da9052_reg_update(regulator->da9052,
331 DA9052_BUCKCORE_REG + offset,
332 (1 << info->volt_shift) - 1, *selector);
333}
334
335static int da9052_get_buckperi_voltage_sel(struct regulator_dev *rdev)
336{
337 struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
338 struct da9052_regulator_info *info = regulator->info;
339 int offset = rdev_get_id(rdev);
340 int ret;
341
342 ret = da9052_reg_read(regulator->da9052, DA9052_BUCKCORE_REG + offset);
343 if (ret < 0)
344 return ret;
345
346 ret &= ((1 << info->volt_shift) - 1);
347
348 return ret;
349}
350
351static struct regulator_ops da9052_buckperi_ops = {
352 .list_voltage = da9052_list_buckperi_voltage,
353 .get_voltage_sel = da9052_get_buckperi_voltage_sel,
354 .set_voltage = da9052_set_buckperi_voltage,
355
356 .get_current_limit = da9052_dcdc_get_current_limit,
357 .set_current_limit = da9052_dcdc_set_current_limit,
358
359 .is_enabled = da9052_regulator_is_enabled,
360 .enable = da9052_regulator_enable,
361 .disable = da9052_regulator_disable,
362};
363
364static struct regulator_ops da9052_dcdc_ops = {
365 .set_voltage = da9052_set_dcdc_voltage,
366 .get_current_limit = da9052_dcdc_get_current_limit,
367 .set_current_limit = da9052_dcdc_set_current_limit,
368
369 .list_voltage = da9052_list_voltage,
370 .get_voltage_sel = da9052_get_regulator_voltage_sel,
371 .is_enabled = da9052_regulator_is_enabled,
372 .enable = da9052_regulator_enable,
373 .disable = da9052_regulator_disable,
374};
375
376static struct regulator_ops da9052_ldo5_6_ops = {
377 .set_voltage = da9052_set_ldo5_6_voltage,
378
379 .list_voltage = da9052_list_voltage,
380 .get_voltage_sel = da9052_get_regulator_voltage_sel,
381 .is_enabled = da9052_regulator_is_enabled,
382 .enable = da9052_regulator_enable,
383 .disable = da9052_regulator_disable,
384};
385
386static struct regulator_ops da9052_ldo_ops = {
387 .set_voltage = da9052_set_ldo_voltage,
388
389 .list_voltage = da9052_list_voltage,
390 .get_voltage_sel = da9052_get_regulator_voltage_sel,
391 .is_enabled = da9052_regulator_is_enabled,
392 .enable = da9052_regulator_enable,
393 .disable = da9052_regulator_disable,
394};
395
396#define DA9052_LDO5_6(_id, step, min, max, sbits, ebits, abits) \
397{\
398 .reg_desc = {\
399 .name = "LDO" #_id,\
400 .ops = &da9052_ldo5_6_ops,\
401 .type = REGULATOR_VOLTAGE,\
402 .id = _id,\
403 .owner = THIS_MODULE,\
404 },\
405 .min_uV = (min) * 1000,\
406 .max_uV = (max) * 1000,\
407 .step_uV = (step) * 1000,\
408 .volt_shift = (sbits),\
409 .en_bit = (ebits),\
410 .activate_bit = (abits),\
411}
412
413#define DA9052_LDO(_id, step, min, max, sbits, ebits, abits) \
414{\
415 .reg_desc = {\
416 .name = "LDO" #_id,\
417 .ops = &da9052_ldo_ops,\
418 .type = REGULATOR_VOLTAGE,\
419 .id = _id,\
420 .owner = THIS_MODULE,\
421 },\
422 .min_uV = (min) * 1000,\
423 .max_uV = (max) * 1000,\
424 .step_uV = (step) * 1000,\
425 .volt_shift = (sbits),\
426 .en_bit = (ebits),\
427 .activate_bit = (abits),\
428}
429
430#define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \
431{\
432 .reg_desc = {\
433 .name = "BUCK" #_id,\
434 .ops = &da9052_dcdc_ops,\
435 .type = REGULATOR_VOLTAGE,\
436 .id = _id,\
437 .owner = THIS_MODULE,\
438 },\
439 .min_uV = (min) * 1000,\
440 .max_uV = (max) * 1000,\
441 .step_uV = (step) * 1000,\
442 .volt_shift = (sbits),\
443 .en_bit = (ebits),\
444 .activate_bit = (abits),\
445}
446
447#define DA9052_BUCKPERI(_id, step, min, max, sbits, ebits, abits) \
448{\
449 .reg_desc = {\
450 .name = "BUCK" #_id,\
451 .ops = &da9052_buckperi_ops,\
452 .type = REGULATOR_VOLTAGE,\
453 .id = _id,\
454 .owner = THIS_MODULE,\
455 },\
456 .min_uV = (min) * 1000,\
457 .max_uV = (max) * 1000,\
458 .step_uV = (step) * 1000,\
459 .volt_shift = (sbits),\
460 .en_bit = (ebits),\
461 .activate_bit = (abits),\
462}
463
Axel Lin6242eae2011-12-20 17:12:00 +0800464static struct da9052_regulator_info da9052_regulator_info[] = {
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530465 /* Buck1 - 4 */
466 DA9052_DCDC(0, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
467 DA9052_DCDC(1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
468 DA9052_DCDC(2, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO),
469 DA9052_BUCKPERI(3, 50, 1800, 3600, 5, 6, 0),
470 /* LD01 - LDO10 */
471 DA9052_LDO(4, 50, 600, 1800, 5, 6, 0),
472 DA9052_LDO5_6(5, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
473 DA9052_LDO5_6(6, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
474 DA9052_LDO(7, 25, 1725, 3300, 6, 6, 0),
475 DA9052_LDO(8, 50, 1200, 3600, 6, 6, 0),
476 DA9052_LDO(9, 50, 1200, 3600, 6, 6, 0),
477 DA9052_LDO(10, 50, 1200, 3600, 6, 6, 0),
478 DA9052_LDO(11, 50, 1200, 3600, 6, 6, 0),
479 DA9052_LDO(12, 50, 1250, 3650, 6, 6, 0),
480 DA9052_LDO(13, 50, 1200, 3600, 6, 6, 0),
481};
482
Axel Lin6242eae2011-12-20 17:12:00 +0800483static struct da9052_regulator_info da9053_regulator_info[] = {
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530484 /* Buck1 - 4 */
485 DA9052_DCDC(0, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBCOREGO),
486 DA9052_DCDC(1, 25, 500, 2075, 6, 6, DA9052_SUPPLY_VBPROGO),
487 DA9052_DCDC(2, 25, 925, 2500, 6, 6, DA9052_SUPPLY_VBMEMGO),
488 DA9052_BUCKPERI(3, 25, 925, 2500, 6, 6, 0),
489 /* LD01 - LDO10 */
490 DA9052_LDO(4, 50, 600, 1800, 5, 6, 0),
491 DA9052_LDO5_6(5, 25, 600, 1800, 6, 6, DA9052_SUPPLY_VLDO2GO),
492 DA9052_LDO5_6(6, 25, 1725, 3300, 6, 6, DA9052_SUPPLY_VLDO3GO),
493 DA9052_LDO(7, 25, 1725, 3300, 6, 6, 0),
494 DA9052_LDO(8, 50, 1200, 3600, 6, 6, 0),
495 DA9052_LDO(9, 50, 1200, 3600, 6, 6, 0),
496 DA9052_LDO(10, 50, 1200, 3600, 6, 6, 0),
497 DA9052_LDO(11, 50, 1200, 3600, 6, 6, 0),
498 DA9052_LDO(12, 50, 1250, 3650, 6, 6, 0),
499 DA9052_LDO(13, 50, 1200, 3600, 6, 6, 0),
500};
501
502static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id,
503 int id)
504{
505 struct da9052_regulator_info *info;
506 int i;
507
Ashish Jangam984b5a62011-12-15 18:59:53 +0530508 switch (chip_id) {
509 case DA9052:
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530510 for (i = 0; i < ARRAY_SIZE(da9052_regulator_info); i++) {
511 info = &da9052_regulator_info[i];
512 if (info->reg_desc.id == id)
513 return info;
514 }
Ashish Jangam984b5a62011-12-15 18:59:53 +0530515 break;
516 case DA9053_AA:
517 case DA9053_BA:
518 case DA9053_BB:
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530519 for (i = 0; i < ARRAY_SIZE(da9053_regulator_info); i++) {
520 info = &da9053_regulator_info[i];
521 if (info->reg_desc.id == id)
522 return info;
523 }
Ashish Jangam984b5a62011-12-15 18:59:53 +0530524 break;
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530525 }
526
527 return NULL;
528}
529
530static int __devinit da9052_regulator_probe(struct platform_device *pdev)
531{
532 struct da9052_regulator *regulator;
533 struct da9052 *da9052;
534 struct da9052_pdata *pdata;
535 int ret;
536
Ashish Jangam984b5a62011-12-15 18:59:53 +0530537 regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9052_regulator),
538 GFP_KERNEL);
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530539 if (!regulator)
540 return -ENOMEM;
541
542 da9052 = dev_get_drvdata(pdev->dev.parent);
543 pdata = da9052->dev->platform_data;
544 regulator->da9052 = da9052;
545
546 regulator->info = find_regulator_info(regulator->da9052->chip_id,
547 pdev->id);
548 if (regulator->info == NULL) {
549 dev_err(&pdev->dev, "invalid regulator ID specified\n");
550 ret = -EINVAL;
551 goto err;
552 }
553 regulator->rdev = regulator_register(&regulator->info->reg_desc,
554 &pdev->dev,
555 pdata->regulators[pdev->id],
Mark Brown47aed922011-12-15 15:03:38 +0800556 regulator, NULL);
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530557 if (IS_ERR(regulator->rdev)) {
558 dev_err(&pdev->dev, "failed to register regulator %s\n",
559 regulator->info->reg_desc.name);
560 ret = PTR_ERR(regulator->rdev);
561 goto err;
562 }
563
564 platform_set_drvdata(pdev, regulator);
565
566 return 0;
567err:
Ashish Jangam984b5a62011-12-15 18:59:53 +0530568 devm_kfree(&pdev->dev, regulator);
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530569 return ret;
570}
571
572static int __devexit da9052_regulator_remove(struct platform_device *pdev)
573{
574 struct da9052_regulator *regulator = platform_get_drvdata(pdev);
575
576 regulator_unregister(regulator->rdev);
Ashish Jangam984b5a62011-12-15 18:59:53 +0530577 devm_kfree(&pdev->dev, regulator);
Ashish Jangam08bf1c02011-12-09 19:48:20 +0530578
579 return 0;
580}
581
582static struct platform_driver da9052_regulator_driver = {
583 .probe = da9052_regulator_probe,
584 .remove = __devexit_p(da9052_regulator_remove),
585 .driver = {
586 .name = "da9052-regulator",
587 .owner = THIS_MODULE,
588 },
589};
590
591static int __init da9052_regulator_init(void)
592{
593 return platform_driver_register(&da9052_regulator_driver);
594}
595subsys_initcall(da9052_regulator_init);
596
597static void __exit da9052_regulator_exit(void)
598{
599 platform_driver_unregister(&da9052_regulator_driver);
600}
601module_exit(da9052_regulator_exit);
602
603MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
604MODULE_DESCRIPTION("Power Regulator driver for Dialog DA9052 PMIC");
605MODULE_LICENSE("GPL");
606MODULE_ALIAS("platform:da9052-regulator");