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) & \
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
7366struct 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 */
99139struct 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
107148static 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 ));
302349out :
@@ -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)
454507static 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+
472549static const struct of_device_id mt6323_led_dt_match [] = {
473- { .compatible = "mediatek,mt6323-led" },
550+ { .compatible = "mediatek,mt6323-led" , . data = & mt6323_pdata },
474551 {},
475552};
476553MODULE_DEVICE_TABLE (of , mt6323_led_dt_match );
0 commit comments