Skip to content

Commit 3ec0b29

Browse files
AngeloGioacchino Del Regnolag-linaro
authored andcommitted
leds: leds-mt6323: Specify registers and specs in platform data
In order to enhance the flexibility of this driver and let it support more than just one MediaTek LEDs IP for more than just one PMIC, add platform data structure specifying the register offsets and data that commonly varies between different IPs. This commit brings no functional changes. Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Reviewed-by: Alexandre Mergnat <amergnat@baylibre.com> Acked-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: Lee Jones <lee@kernel.org> Link: https://lore.kernel.org/r/20230601110813.2373764-5-angelogioacchino.delregno@collabora.com
1 parent 0642b7e commit 3ec0b29

1 file changed

Lines changed: 115 additions & 38 deletions

File tree

drivers/leds/leds-mt6323.c

Lines changed: 115 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,18 @@
3333
*/
3434
#define MT6323_RG_ISINK_CK_SEL_MASK(i) (BIT(10) << (i))
3535

36-
/*
37-
* Register for MT6323_ISINK_CON0 to setup the
38-
* duty cycle of the blink.
39-
*/
40-
#define MT6323_ISINK_CON0(i) (MT6323_ISINK0_CON0 + 0x8 * (i))
36+
#define MT6323_ISINK_CON(r, i) (r + 0x8 * (i))
37+
38+
/* ISINK_CON0: Register to setup the duty cycle of the blink. */
4139
#define MT6323_ISINK_DIM_DUTY_MASK (0x1f << 8)
4240
#define MT6323_ISINK_DIM_DUTY(i) (((i) << 8) & \
43-
MT6323_ISINK_DIM_DUTY_MASK)
41+
MT6323_ISINK_DIM_DUTY_MASK)
4442

45-
/* Register to setup the period of the blink. */
46-
#define MT6323_ISINK_CON1(i) (MT6323_ISINK0_CON1 + 0x8 * (i))
43+
/* ISINK_CON1: Register to setup the period of the blink. */
4744
#define MT6323_ISINK_DIM_FSEL_MASK (0xffff)
4845
#define MT6323_ISINK_DIM_FSEL(i) ((i) & MT6323_ISINK_DIM_FSEL_MASK)
4946

50-
/* Register to control the brightness. */
51-
#define MT6323_ISINK_CON2(i) (MT6323_ISINK0_CON2 + 0x8 * (i))
47+
/* ISINK_CON2: Register to control the brightness. */
5248
#define MT6323_ISINK_CH_STEP_SHIFT 12
5349
#define MT6323_ISINK_CH_STEP_MASK (0x7 << 12)
5450
#define MT6323_ISINK_CH_STEP(i) (((i) << 12) & \
@@ -63,12 +59,9 @@
6359
#define MT6323_ISINK_CH_EN_MASK(i) BIT(i)
6460
#define MT6323_ISINK_CH_EN(i) BIT(i)
6561

66-
#define MT6323_MAX_PERIOD 10000
67-
#define MT6323_MAX_LEDS 4
68-
#define MT6323_MAX_BRIGHTNESS 6
69-
#define MT6323_UNIT_DUTY 3125
70-
#define MT6323_CAL_HW_DUTY(o, p) DIV_ROUND_CLOSEST((o) * 100000ul,\
71-
(p) * MT6323_UNIT_DUTY)
62+
#define MAX_SUPPORTED_LEDS 8
63+
#define MT6323_CAL_HW_DUTY(o, p, u) DIV_ROUND_CLOSEST((o) * 100000ul,\
64+
(p) * (u))
7265

7366
struct mt6323_leds;
7467

@@ -86,29 +79,78 @@ struct mt6323_led {
8679
enum led_brightness current_brightness;
8780
};
8881

82+
/**
83+
* struct mt6323_regs - register spec for the LED device
84+
* @top_ckpdn: Offset to ISINK_CKPDN[0..x] registers
85+
* @num_top_ckpdn: Number of ISINK_CKPDN registers
86+
* @top_ckcon: Offset to ISINK_CKCON[0..x] registers
87+
* @num_top_ckcon: Number of ISINK_CKCON registers
88+
* @isink_con: Offset to ISINKx_CON[0..x] registers
89+
* @num_isink_con: Number of ISINKx_CON registers
90+
* @isink_max_regs: Number of ISINK[0..x] registers
91+
* @isink_en_ctrl: Offset to ISINK_EN_CTRL register
92+
*/
93+
struct mt6323_regs {
94+
const u16 *top_ckpdn;
95+
u8 num_top_ckpdn;
96+
const u16 *top_ckcon;
97+
u8 num_top_ckcon;
98+
const u16 *isink_con;
99+
u8 num_isink_con;
100+
u8 isink_max_regs;
101+
u16 isink_en_ctrl;
102+
};
103+
104+
/**
105+
* struct mt6323_hwspec - hardware specific parameters
106+
* @max_period: Maximum period for all LEDs
107+
* @max_leds: Maximum number of supported LEDs
108+
* @max_brightness: Maximum brightness for all LEDs
109+
* @unit_duty: Steps of duty per period
110+
*/
111+
struct mt6323_hwspec {
112+
u16 max_period;
113+
u8 max_leds;
114+
u16 max_brightness;
115+
u16 unit_duty;
116+
};
117+
118+
/**
119+
* struct mt6323_data - device specific data
120+
* @regs: Register spec for this device
121+
* @spec: Hardware specific parameters
122+
*/
123+
struct mt6323_data {
124+
const struct mt6323_regs *regs;
125+
const struct mt6323_hwspec *spec;
126+
};
127+
89128
/**
90129
* struct mt6323_leds - state container for holding LED controller
91130
* of the driver
92131
* @dev: the device pointer
93132
* @hw: the underlying hardware providing shared
94133
* bus for the register operations
134+
* @pdata: device specific data
95135
* @lock: the lock among process context
96136
* @led: the array that contains the state of individual
97137
* LED device
98138
*/
99139
struct mt6323_leds {
100140
struct device *dev;
101141
struct mt6397_chip *hw;
142+
const struct mt6323_data *pdata;
102143
/* protect among process context */
103144
struct mutex lock;
104-
struct mt6323_led *led[MT6323_MAX_LEDS];
145+
struct mt6323_led *led[MAX_SUPPORTED_LEDS];
105146
};
106147

107148
static int mt6323_led_hw_brightness(struct led_classdev *cdev,
108149
enum led_brightness brightness)
109150
{
110151
struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
111152
struct mt6323_leds *leds = led->parent;
153+
const struct mt6323_regs *regs = leds->pdata->regs;
112154
struct regmap *regmap = leds->hw->regmap;
113155
u32 con2_mask = 0, con2_val = 0;
114156
int ret;
@@ -124,7 +166,7 @@ static int mt6323_led_hw_brightness(struct led_classdev *cdev,
124166
MT6323_ISINK_SFSTR0_TC(2) |
125167
MT6323_ISINK_SFSTR0_EN;
126168

127-
ret = regmap_update_bits(regmap, MT6323_ISINK_CON2(led->id),
169+
ret = regmap_update_bits(regmap, MT6323_ISINK_CON(regs->isink_con[2], led->id),
128170
con2_mask, con2_val);
129171
return ret;
130172
}
@@ -133,18 +175,19 @@ static int mt6323_led_hw_off(struct led_classdev *cdev)
133175
{
134176
struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
135177
struct mt6323_leds *leds = led->parent;
178+
const struct mt6323_regs *regs = leds->pdata->regs;
136179
struct regmap *regmap = leds->hw->regmap;
137180
unsigned int status;
138181
int ret;
139182

140183
status = MT6323_ISINK_CH_EN(led->id);
141-
ret = regmap_update_bits(regmap, MT6323_ISINK_EN_CTRL,
184+
ret = regmap_update_bits(regmap, regs->isink_en_ctrl,
142185
MT6323_ISINK_CH_EN_MASK(led->id), ~status);
143186
if (ret < 0)
144187
return ret;
145188

146189
usleep_range(100, 300);
147-
ret = regmap_update_bits(regmap, MT6323_TOP_CKPDN2,
190+
ret = regmap_update_bits(regmap, regs->top_ckpdn[2],
148191
MT6323_RG_ISINK_CK_PDN_MASK(led->id),
149192
MT6323_RG_ISINK_CK_PDN(led->id));
150193
if (ret < 0)
@@ -158,25 +201,26 @@ mt6323_get_led_hw_brightness(struct led_classdev *cdev)
158201
{
159202
struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
160203
struct mt6323_leds *leds = led->parent;
204+
const struct mt6323_regs *regs = leds->pdata->regs;
161205
struct regmap *regmap = leds->hw->regmap;
162206
unsigned int status;
163207
int ret;
164208

165-
ret = regmap_read(regmap, MT6323_TOP_CKPDN2, &status);
209+
ret = regmap_read(regmap, regs->top_ckpdn[2], &status);
166210
if (ret < 0)
167211
return ret;
168212

169213
if (status & MT6323_RG_ISINK_CK_PDN_MASK(led->id))
170214
return 0;
171215

172-
ret = regmap_read(regmap, MT6323_ISINK_EN_CTRL, &status);
216+
ret = regmap_read(regmap, regs->isink_en_ctrl, &status);
173217
if (ret < 0)
174218
return ret;
175219

176220
if (!(status & MT6323_ISINK_CH_EN(led->id)))
177221
return 0;
178222

179-
ret = regmap_read(regmap, MT6323_ISINK_CON2(led->id), &status);
223+
ret = regmap_read(regmap, MT6323_ISINK_CON(regs->isink_con[2], led->id), &status);
180224
if (ret < 0)
181225
return ret;
182226

@@ -189,6 +233,7 @@ static int mt6323_led_hw_on(struct led_classdev *cdev,
189233
{
190234
struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
191235
struct mt6323_leds *leds = led->parent;
236+
const struct mt6323_regs *regs = leds->pdata->regs;
192237
struct regmap *regmap = leds->hw->regmap;
193238
unsigned int status;
194239
int ret;
@@ -198,21 +243,21 @@ static int mt6323_led_hw_on(struct led_classdev *cdev,
198243
* clock and channel and let work with continuous blink as
199244
* the default.
200245
*/
201-
ret = regmap_update_bits(regmap, MT6323_TOP_CKCON1,
246+
ret = regmap_update_bits(regmap, regs->top_ckcon[1],
202247
MT6323_RG_ISINK_CK_SEL_MASK(led->id), 0);
203248
if (ret < 0)
204249
return ret;
205250

206251
status = MT6323_RG_ISINK_CK_PDN(led->id);
207-
ret = regmap_update_bits(regmap, MT6323_TOP_CKPDN2,
252+
ret = regmap_update_bits(regmap, regs->top_ckpdn[2],
208253
MT6323_RG_ISINK_CK_PDN_MASK(led->id),
209254
~status);
210255
if (ret < 0)
211256
return ret;
212257

213258
usleep_range(100, 300);
214259

215-
ret = regmap_update_bits(regmap, MT6323_ISINK_EN_CTRL,
260+
ret = regmap_update_bits(regmap, regs->isink_en_ctrl,
216261
MT6323_ISINK_CH_EN_MASK(led->id),
217262
MT6323_ISINK_CH_EN(led->id));
218263
if (ret < 0)
@@ -222,13 +267,13 @@ static int mt6323_led_hw_on(struct led_classdev *cdev,
222267
if (ret < 0)
223268
return ret;
224269

225-
ret = regmap_update_bits(regmap, MT6323_ISINK_CON0(led->id),
270+
ret = regmap_update_bits(regmap, MT6323_ISINK_CON(regs->isink_con[0], led->id),
226271
MT6323_ISINK_DIM_DUTY_MASK,
227272
MT6323_ISINK_DIM_DUTY(31));
228273
if (ret < 0)
229274
return ret;
230275

231-
ret = regmap_update_bits(regmap, MT6323_ISINK_CON1(led->id),
276+
ret = regmap_update_bits(regmap, MT6323_ISINK_CON(regs->isink_con[1], led->id),
232277
MT6323_ISINK_DIM_FSEL_MASK,
233278
MT6323_ISINK_DIM_FSEL(1000));
234279
if (ret < 0)
@@ -243,6 +288,8 @@ static int mt6323_led_set_blink(struct led_classdev *cdev,
243288
{
244289
struct mt6323_led *led = container_of(cdev, struct mt6323_led, cdev);
245290
struct mt6323_leds *leds = led->parent;
291+
const struct mt6323_regs *regs = leds->pdata->regs;
292+
const struct mt6323_hwspec *spec = leds->pdata->spec;
246293
struct regmap *regmap = leds->hw->regmap;
247294
unsigned long period;
248295
u8 duty_hw;
@@ -265,14 +312,14 @@ static int mt6323_led_set_blink(struct led_classdev *cdev,
265312
*/
266313
period = *delay_on + *delay_off;
267314

268-
if (period > MT6323_MAX_PERIOD)
315+
if (period > spec->max_period)
269316
return -EINVAL;
270317

271318
/*
272319
* Calculate duty_hw based on the percentage of period during
273320
* which the led is ON.
274321
*/
275-
duty_hw = MT6323_CAL_HW_DUTY(*delay_on, period);
322+
duty_hw = MT6323_CAL_HW_DUTY(*delay_on, period, spec->unit_duty);
276323

277324
/* hardware doesn't support zero duty cycle. */
278325
if (!duty_hw)
@@ -290,13 +337,13 @@ static int mt6323_led_set_blink(struct led_classdev *cdev,
290337
led->current_brightness = cdev->max_brightness;
291338
}
292339

293-
ret = regmap_update_bits(regmap, MT6323_ISINK_CON0(led->id),
340+
ret = regmap_update_bits(regmap, MT6323_ISINK_CON(regs->isink_con[0], led->id),
294341
MT6323_ISINK_DIM_DUTY_MASK,
295342
MT6323_ISINK_DIM_DUTY(duty_hw - 1));
296343
if (ret < 0)
297344
goto out;
298345

299-
ret = regmap_update_bits(regmap, MT6323_ISINK_CON1(led->id),
346+
ret = regmap_update_bits(regmap, MT6323_ISINK_CON(regs->isink_con[1], led->id),
300347
MT6323_ISINK_DIM_FSEL_MASK,
301348
MT6323_ISINK_DIM_FSEL(period - 1));
302349
out:
@@ -369,6 +416,8 @@ static int mt6323_led_probe(struct platform_device *pdev)
369416
struct mt6397_chip *hw = dev_get_drvdata(dev->parent);
370417
struct mt6323_leds *leds;
371418
struct mt6323_led *led;
419+
const struct mt6323_regs *regs;
420+
const struct mt6323_hwspec *spec;
372421
int ret;
373422
unsigned int status;
374423
u32 reg;
@@ -379,6 +428,9 @@ static int mt6323_led_probe(struct platform_device *pdev)
379428

380429
platform_set_drvdata(pdev, leds);
381430
leds->dev = dev;
431+
leds->pdata = device_get_match_data(dev);
432+
regs = leds->pdata->regs;
433+
spec = leds->pdata->spec;
382434

383435
/*
384436
* leds->hw points to the underlying bus for the register
@@ -388,11 +440,11 @@ static int mt6323_led_probe(struct platform_device *pdev)
388440
mutex_init(&leds->lock);
389441

390442
status = MT6323_RG_DRV_32K_CK_PDN;
391-
ret = regmap_update_bits(leds->hw->regmap, MT6323_TOP_CKPDN0,
443+
ret = regmap_update_bits(leds->hw->regmap, regs->top_ckpdn[0],
392444
MT6323_RG_DRV_32K_CK_PDN_MASK, ~status);
393445
if (ret < 0) {
394446
dev_err(leds->dev,
395-
"Failed to update MT6323_TOP_CKPDN0 Register\n");
447+
"Failed to update TOP_CKPDN0 Register\n");
396448
return ret;
397449
}
398450

@@ -405,7 +457,8 @@ static int mt6323_led_probe(struct platform_device *pdev)
405457
goto put_child_node;
406458
}
407459

408-
if (reg >= MT6323_MAX_LEDS || leds->led[reg]) {
460+
if (reg >= spec->max_leds || reg >= MAX_SUPPORTED_LEDS ||
461+
leds->led[reg]) {
409462
dev_err(dev, "Invalid led reg %u\n", reg);
410463
ret = -EINVAL;
411464
goto put_child_node;
@@ -419,7 +472,7 @@ static int mt6323_led_probe(struct platform_device *pdev)
419472

420473
leds->led[reg] = led;
421474
leds->led[reg]->id = reg;
422-
leds->led[reg]->cdev.max_brightness = MT6323_MAX_BRIGHTNESS;
475+
leds->led[reg]->cdev.max_brightness = spec->max_brightness;
423476
leds->led[reg]->cdev.brightness_set_blocking =
424477
mt6323_led_set_brightness;
425478
leds->led[reg]->cdev.blink_set = mt6323_led_set_blink;
@@ -454,13 +507,14 @@ static int mt6323_led_probe(struct platform_device *pdev)
454507
static int mt6323_led_remove(struct platform_device *pdev)
455508
{
456509
struct mt6323_leds *leds = platform_get_drvdata(pdev);
510+
const struct mt6323_regs *regs = leds->pdata->regs;
457511
int i;
458512

459513
/* Turn the LEDs off on driver removal. */
460514
for (i = 0 ; leds->led[i] ; i++)
461515
mt6323_led_hw_off(&leds->led[i]->cdev);
462516

463-
regmap_update_bits(leds->hw->regmap, MT6323_TOP_CKPDN0,
517+
regmap_update_bits(leds->hw->regmap, regs->top_ckpdn[0],
464518
MT6323_RG_DRV_32K_CK_PDN_MASK,
465519
MT6323_RG_DRV_32K_CK_PDN);
466520

@@ -469,8 +523,31 @@ static int mt6323_led_remove(struct platform_device *pdev)
469523
return 0;
470524
}
471525

526+
static const struct mt6323_regs mt6323_registers = {
527+
.top_ckpdn = (const u16[]){ 0x102, 0x106, 0x10e },
528+
.num_top_ckpdn = 3,
529+
.top_ckcon = (const u16[]){ 0x120, 0x126 },
530+
.num_top_ckcon = 2,
531+
.isink_con = (const u16[]){ 0x330, 0x332, 0x334 },
532+
.num_isink_con = 3,
533+
.isink_max_regs = 4, /* ISINK[0..3] */
534+
.isink_en_ctrl = 0x356,
535+
};
536+
537+
static const struct mt6323_hwspec mt6323_spec = {
538+
.max_period = 10000,
539+
.max_leds = 4,
540+
.max_brightness = 6,
541+
.unit_duty = 3125,
542+
};
543+
544+
static const struct mt6323_data mt6323_pdata = {
545+
.regs = &mt6323_registers,
546+
.spec = &mt6323_spec,
547+
};
548+
472549
static const struct of_device_id mt6323_led_dt_match[] = {
473-
{ .compatible = "mediatek,mt6323-led" },
550+
{ .compatible = "mediatek,mt6323-led", .data = &mt6323_pdata},
474551
{},
475552
};
476553
MODULE_DEVICE_TABLE(of, mt6323_led_dt_match);

0 commit comments

Comments
 (0)