1 // SPDX-License-Identifier: GPL-2.0
3 * Intel Lightning Mountain SoC LED Serial Shift Output Controller driver
5 * Copyright (c) 2020 Intel Corporation.
8 #include <linux/bitfield.h>
10 #include <linux/gpio/consumer.h>
11 #include <linux/gpio/driver.h>
12 #include <linux/init.h>
13 #include <linux/kernel.h>
14 #include <linux/leds.h>
15 #include <linux/mfd/syscon.h>
16 #include <linux/module.h>
17 #include <linux/platform_device.h>
18 #include <linux/property.h>
19 #include <linux/regmap.h>
20 #include <linux/sizes.h>
21 #include <linux/uaccess.h>
23 #define SSO_DEV_NAME "lgm-sso"
25 #define LED_BLINK_H8_0 0x0
26 #define LED_BLINK_H8_1 0x4
27 #define GET_FREQ_OFFSET(pin, src) (((pin) * 6) + ((src) * 2))
28 #define GET_SRC_OFFSET(pinc) (((pin) * 6) + 4)
30 #define DUTY_CYCLE(x) (0x8 + ((x) * 4))
31 #define SSO_CON0 0x2B0
32 #define SSO_CON0_RZFL BIT(26)
33 #define SSO_CON0_BLINK_R BIT(30)
34 #define SSO_CON0_SWU BIT(31)
36 #define SSO_CON1 0x2B4
37 #define SSO_CON1_FCDSC GENMASK(21, 20) /* Fixed Divider Shift Clock */
38 #define SSO_CON1_FPID GENMASK(24, 23)
39 #define SSO_CON1_GPTD GENMASK(26, 25)
40 #define SSO_CON1_US GENMASK(31, 30)
43 #define SSO_CON2 0x2C4
44 #define SSO_CON3 0x2C8
47 #define MAX_PIN_NUM_PER_BANK SZ_32
48 #define MAX_GROUP_NUM SZ_4
49 #define PINS_PER_GROUP SZ_8
50 #define FPID_FREQ_RANK_MAX SZ_4
51 #define SSO_LED_MAX_NUM SZ_32
52 #define MAX_FREQ_RANK 10
53 #define DEF_GPTC_CLK_RATE 200000000
54 #define SSO_DEF_BRIGHTNESS LED_HALF
55 #define DATA_CLK_EDGE 0 /* 0-rising, 1-falling */
57 static const u32 freq_div_tbl
[] = {4000, 2000, 1000, 800};
58 static const int freq_tbl
[] = {2, 4, 8, 10, 50000, 100000, 200000, 250000};
59 static const int shift_clk_freq_tbl
[] = {25000000, 12500000, 6250000, 3125000};
62 * Update Source to update the SOUTs
63 * SW - Software has to update the SWU bit
64 * GPTC - General Purpose timer is used as clock source
65 * FPID - Divided FSC clock (FPID) is used as clock source
74 MAX_FPID_FREQ_RANK
= 5, /* 1 to 4 */
75 MAX_GPTC_FREQ_RANK
= 9, /* 5 to 8 */
76 MAX_GPTC_HS_FREQ_RANK
= 10, /* 9 to 10 */
80 LED_GRP0_PIN_MAX
= 24,
81 LED_GRP1_PIN_MAX
= 29,
82 LED_GRP2_PIN_MAX
= 32,
100 struct sso_led_desc
{
102 const char *default_trigger
;
103 unsigned int brightness
;
104 unsigned int blink_rate
;
105 unsigned int retain_state_suspended
:1;
106 unsigned int retain_state_shutdown
:1;
107 unsigned int panic_indicator
:1;
108 unsigned int hw_blink
:1;
109 unsigned int hw_trig
:1;
110 unsigned int blinking
:1;
116 struct list_head list
;
117 struct led_classdev cdev
;
118 struct gpio_desc
*gpiod
;
119 struct sso_led_desc desc
;
120 struct sso_led_priv
*priv
;
124 struct gpio_chip chip
;
132 struct sso_led_priv
{
135 struct platform_device
*pdev
;
136 struct clk_bulk_data clocks
[2];
139 u32 freq
[MAX_FREQ_RANK
];
140 struct list_head led_list
;
141 struct sso_gpio gpio
;
144 static int sso_get_blink_rate_idx(struct sso_led_priv
*priv
, u32 rate
)
148 for (i
= 0; i
< MAX_FREQ_RANK
; i
++) {
149 if (rate
<= priv
->freq
[i
])
156 static unsigned int sso_led_pin_to_group(u32 pin
)
158 if (pin
< LED_GRP0_PIN_MAX
)
159 return LED_GRP0_0_23
;
160 else if (pin
< LED_GRP1_PIN_MAX
)
161 return LED_GRP1_24_28
;
163 return LED_GRP2_29_31
;
166 static u32
sso_led_get_freq_src(int freq_idx
)
168 if (freq_idx
< MAX_FPID_FREQ_RANK
)
170 else if (freq_idx
< MAX_GPTC_FREQ_RANK
)
173 return CLK_SRC_GPTC_HS
;
176 static u32
sso_led_pin_blink_off(u32 pin
, unsigned int group
)
178 if (group
== LED_GRP2_29_31
)
179 return pin
- LED_GRP1_PIN_MAX
;
180 else if (group
== LED_GRP1_24_28
)
181 return pin
- LED_GRP0_PIN_MAX
;
182 else /* led 0 - 23 in led 32 location */
183 return SSO_LED_MAX_NUM
- LED_GRP1_PIN_MAX
;
186 static struct sso_led
187 *cdev_to_sso_led_data(struct led_classdev
*led_cdev
)
189 return container_of(led_cdev
, struct sso_led
, cdev
);
192 static void sso_led_freq_set(struct sso_led_priv
*priv
, u32 pin
, int freq_idx
)
194 u32 reg
, off
, freq_src
, val_freq
;
201 group
= sso_led_pin_to_group(pin
);
202 freq_src
= sso_led_get_freq_src(freq_idx
);
203 off
= sso_led_pin_blink_off(pin
, group
);
205 if (group
== LED_GRP0_0_23
)
207 else if (group
== LED_GRP1_24_28
)
208 reg
= LED_BLINK_H8_0
;
210 reg
= LED_BLINK_H8_1
;
212 if (freq_src
== CLK_SRC_FPID
)
213 val_freq
= freq_idx
- 1;
214 else if (freq_src
== CLK_SRC_GPTC
)
215 val_freq
= freq_idx
- MAX_FPID_FREQ_RANK
;
217 /* set blink rate idx */
218 if (freq_src
!= CLK_SRC_GPTC_HS
) {
219 low
= GET_FREQ_OFFSET(off
, freq_src
);
221 val
= val_freq
<< high
;
222 regmap_update_bits(priv
->mmap
, reg
, GENMASK(high
, low
), val
);
225 /* select clock source */
226 low
= GET_SRC_OFFSET(off
);
228 val
= freq_src
<< high
;
229 regmap_update_bits(priv
->mmap
, reg
, GENMASK(high
, low
), val
);
232 static void sso_led_brightness_set(struct led_classdev
*led_cdev
,
233 enum led_brightness brightness
)
235 struct sso_led_priv
*priv
;
236 struct sso_led_desc
*desc
;
240 led
= cdev_to_sso_led_data(led_cdev
);
244 desc
->brightness
= brightness
;
245 regmap_write(priv
->mmap
, DUTY_CYCLE(desc
->pin
), brightness
);
247 if (brightness
== LED_OFF
)
253 if (desc
->hw_blink
&& !val
&& desc
->blinking
) {
255 regmap_update_bits(priv
->mmap
, SSO_CON2
, BIT(desc
->pin
), 0);
256 } else if (desc
->hw_blink
&& val
&& !desc
->blinking
) {
258 regmap_update_bits(priv
->mmap
, SSO_CON2
, BIT(desc
->pin
),
263 gpiod_set_value(led
->gpiod
, val
);
266 static enum led_brightness
sso_led_brightness_get(struct led_classdev
*led_cdev
)
268 struct sso_led
*led
= cdev_to_sso_led_data(led_cdev
);
270 return (enum led_brightness
)led
->desc
.brightness
;
274 delay_to_freq_idx(struct sso_led
*led
, unsigned long *delay_on
,
275 unsigned long *delay_off
)
277 struct sso_led_priv
*priv
= led
->priv
;
282 if (!*delay_on
&& !*delay_off
) {
283 *delay_on
= *delay_off
= (1000 / priv
->freq
[0]) / 2;
287 delay
= *delay_on
+ *delay_off
;
290 freq_idx
= sso_get_blink_rate_idx(priv
, freq
);
292 freq_idx
= MAX_FREQ_RANK
- 1;
294 delay
= 1000 / priv
->freq
[freq_idx
];
295 *delay_on
= *delay_off
= delay
/ 2;
298 *delay_on
= *delay_off
= 1;
304 sso_led_blink_set(struct led_classdev
*led_cdev
, unsigned long *delay_on
,
305 unsigned long *delay_off
)
307 struct sso_led_priv
*priv
;
311 led
= cdev_to_sso_led_data(led_cdev
);
313 freq_idx
= delay_to_freq_idx(led
, delay_on
, delay_off
);
315 sso_led_freq_set(priv
, led
->desc
.pin
, freq_idx
);
316 regmap_update_bits(priv
->mmap
, SSO_CON2
, BIT(led
->desc
.pin
),
318 led
->desc
.freq_idx
= freq_idx
;
319 led
->desc
.blink_rate
= priv
->freq
[freq_idx
];
320 led
->desc
.blinking
= 1;
325 static void sso_led_hw_cfg(struct sso_led_priv
*priv
, struct sso_led
*led
)
327 struct sso_led_desc
*desc
= &led
->desc
;
330 if (desc
->hw_blink
) {
331 sso_led_freq_set(priv
, desc
->pin
, desc
->freq_idx
);
332 regmap_update_bits(priv
->mmap
, SSO_CON2
, BIT(desc
->pin
),
337 regmap_update_bits(priv
->mmap
, SSO_CON3
, BIT(desc
->pin
),
341 regmap_write(priv
->mmap
, DUTY_CYCLE(desc
->pin
), desc
->brightness
);
344 if (!desc
->hw_trig
&& desc
->brightness
)
345 gpiod_set_value(led
->gpiod
, 1);
348 static int sso_create_led(struct sso_led_priv
*priv
, struct sso_led
*led
,
349 struct fwnode_handle
*child
)
351 struct sso_led_desc
*desc
= &led
->desc
;
352 struct led_init_data init_data
;
355 init_data
.fwnode
= child
;
356 init_data
.devicename
= SSO_DEV_NAME
;
357 init_data
.default_label
= ":";
359 led
->cdev
.default_trigger
= desc
->default_trigger
;
360 led
->cdev
.brightness_set
= sso_led_brightness_set
;
361 led
->cdev
.brightness_get
= sso_led_brightness_get
;
362 led
->cdev
.brightness
= desc
->brightness
;
363 led
->cdev
.max_brightness
= LED_FULL
;
365 if (desc
->retain_state_shutdown
)
366 led
->cdev
.flags
|= LED_RETAIN_AT_SHUTDOWN
;
367 if (desc
->retain_state_suspended
)
368 led
->cdev
.flags
|= LED_CORE_SUSPENDRESUME
;
369 if (desc
->panic_indicator
)
370 led
->cdev
.flags
|= LED_PANIC_INDICATOR
;
373 led
->cdev
.blink_set
= sso_led_blink_set
;
375 sso_led_hw_cfg(priv
, led
);
377 err
= devm_led_classdev_register_ext(priv
->dev
, &led
->cdev
, &init_data
);
381 list_add(&led
->list
, &priv
->led_list
);
386 static void sso_init_freq(struct sso_led_priv
*priv
)
391 for (i
= 1; i
< MAX_FREQ_RANK
; i
++) {
392 if (i
< MAX_FPID_FREQ_RANK
) {
393 priv
->freq
[i
] = priv
->fpid_clkrate
/ freq_div_tbl
[i
- 1];
394 } else if (i
< MAX_GPTC_FREQ_RANK
) {
395 priv
->freq
[i
] = priv
->gptc_clkrate
/
396 freq_div_tbl
[i
- MAX_FPID_FREQ_RANK
];
397 } else if (i
< MAX_GPTC_HS_FREQ_RANK
) {
398 priv
->freq
[i
] = priv
->gptc_clkrate
;
403 static int sso_gpio_request(struct gpio_chip
*chip
, unsigned int offset
)
405 struct sso_led_priv
*priv
= gpiochip_get_data(chip
);
407 if (priv
->gpio
.alloc_bitmap
& BIT(offset
))
410 priv
->gpio
.alloc_bitmap
|= BIT(offset
);
411 regmap_write(priv
->mmap
, DUTY_CYCLE(offset
), 0xFF);
416 static void sso_gpio_free(struct gpio_chip
*chip
, unsigned int offset
)
418 struct sso_led_priv
*priv
= gpiochip_get_data(chip
);
420 priv
->gpio
.alloc_bitmap
&= ~BIT(offset
);
421 regmap_write(priv
->mmap
, DUTY_CYCLE(offset
), 0x0);
424 static int sso_gpio_get_dir(struct gpio_chip
*chip
, unsigned int offset
)
426 return GPIO_LINE_DIRECTION_OUT
;
430 sso_gpio_dir_out(struct gpio_chip
*chip
, unsigned int offset
, int value
)
432 struct sso_led_priv
*priv
= gpiochip_get_data(chip
);
435 regmap_update_bits(priv
->mmap
, SSO_CPU
, BIT(offset
), bit
<< offset
);
436 if (!priv
->gpio
.freq
)
437 regmap_update_bits(priv
->mmap
, SSO_CON0
, SSO_CON0_SWU
,
443 static int sso_gpio_get(struct gpio_chip
*chip
, unsigned int offset
)
445 struct sso_led_priv
*priv
= gpiochip_get_data(chip
);
448 regmap_read(priv
->mmap
, SSO_CPU
, ®_val
);
450 return !!(reg_val
& BIT(offset
));
453 static void sso_gpio_set(struct gpio_chip
*chip
, unsigned int offset
, int value
)
455 struct sso_led_priv
*priv
= gpiochip_get_data(chip
);
457 regmap_update_bits(priv
->mmap
, SSO_CPU
, BIT(offset
), value
<< offset
);
458 if (!priv
->gpio
.freq
)
459 regmap_update_bits(priv
->mmap
, SSO_CON0
, SSO_CON0_SWU
,
463 static int sso_gpio_gc_init(struct device
*dev
, struct sso_led_priv
*priv
)
465 struct gpio_chip
*gc
= &priv
->gpio
.chip
;
467 gc
->request
= sso_gpio_request
;
468 gc
->free
= sso_gpio_free
;
469 gc
->get_direction
= sso_gpio_get_dir
;
470 gc
->direction_output
= sso_gpio_dir_out
;
471 gc
->get
= sso_gpio_get
;
472 gc
->set
= sso_gpio_set
;
474 gc
->label
= "lgm-sso";
476 /* To exclude pins from control, use "gpio-reserved-ranges" */
477 gc
->ngpio
= priv
->gpio
.pins
;
479 gc
->owner
= THIS_MODULE
;
481 return devm_gpiochip_add_data(dev
, gc
, priv
);
484 static int sso_gpio_get_freq_idx(int freq
)
488 for (idx
= 0; idx
< ARRAY_SIZE(freq_tbl
); idx
++) {
489 if (freq
<= freq_tbl
[idx
])
496 static void sso_register_shift_clk(struct sso_led_priv
*priv
)
498 int idx
, size
= ARRAY_SIZE(shift_clk_freq_tbl
);
501 for (idx
= 0; idx
< size
; idx
++) {
502 if (shift_clk_freq_tbl
[idx
] <= priv
->gpio
.shift_clk_freq
) {
509 dev_warn(priv
->dev
, "%s: Invalid freq %d\n",
510 __func__
, priv
->gpio
.shift_clk_freq
);
512 regmap_update_bits(priv
->mmap
, SSO_CON1
, SSO_CON1_FCDSC
,
513 FIELD_PREP(SSO_CON1_FCDSC
, val
));
516 static int sso_gpio_freq_set(struct sso_led_priv
*priv
)
521 freq_idx
= sso_gpio_get_freq_idx(priv
->gpio
.freq
);
523 freq_idx
= ARRAY_SIZE(freq_tbl
) - 1;
525 val
= freq_idx
% FPID_FREQ_RANK_MAX
;
527 if (!priv
->gpio
.freq
) {
528 regmap_update_bits(priv
->mmap
, SSO_CON0
, SSO_CON0_BLINK_R
, 0);
529 regmap_update_bits(priv
->mmap
, SSO_CON1
, SSO_CON1_US
,
530 FIELD_PREP(SSO_CON1_US
, US_SW
));
531 } else if (freq_idx
< FPID_FREQ_RANK_MAX
) {
532 regmap_update_bits(priv
->mmap
, SSO_CON0
, SSO_CON0_BLINK_R
,
534 regmap_update_bits(priv
->mmap
, SSO_CON1
, SSO_CON1_US
,
535 FIELD_PREP(SSO_CON1_US
, US_FPID
));
536 regmap_update_bits(priv
->mmap
, SSO_CON1
, SSO_CON1_FPID
,
537 FIELD_PREP(SSO_CON1_FPID
, val
));
539 regmap_update_bits(priv
->mmap
, SSO_CON0
, SSO_CON0_BLINK_R
,
541 regmap_update_bits(priv
->mmap
, SSO_CON1
, SSO_CON1_US
,
542 FIELD_PREP(SSO_CON1_US
, US_GPTC
));
543 regmap_update_bits(priv
->mmap
, SSO_CON1
, SSO_CON1_GPTD
,
544 FIELD_PREP(SSO_CON1_GPTD
, val
));
550 static int sso_gpio_hw_init(struct sso_led_priv
*priv
)
555 /* Clear all duty cycles */
556 for (i
= 0; i
< priv
->gpio
.pins
; i
++) {
557 err
= regmap_write(priv
->mmap
, DUTY_CYCLE(i
), 0);
562 /* 4 groups for total 32 pins */
563 for (i
= 1; i
<= MAX_GROUP_NUM
; i
++) {
564 activate
= !!(i
* PINS_PER_GROUP
<= priv
->gpio
.pins
||
565 priv
->gpio
.pins
> (i
- 1) * PINS_PER_GROUP
);
566 err
= regmap_update_bits(priv
->mmap
, SSO_CON1
, BIT(i
- 1),
567 activate
<< (i
- 1));
572 /* NO HW directly controlled pin by default */
573 err
= regmap_write(priv
->mmap
, SSO_CON3
, 0);
577 /* NO BLINK for all pins */
578 err
= regmap_write(priv
->mmap
, SSO_CON2
, 0);
582 /* OUTPUT 0 by default */
583 err
= regmap_write(priv
->mmap
, SSO_CPU
, 0);
588 err
= regmap_update_bits(priv
->mmap
, SSO_CON0
, SSO_CON0_RZFL
,
589 FIELD_PREP(SSO_CON0_RZFL
, priv
->gpio
.edge
));
593 /* Set GPIO update rate */
594 sso_gpio_freq_set(priv
);
596 /* Register shift clock */
597 sso_register_shift_clk(priv
);
602 static void sso_led_shutdown(struct sso_led
*led
)
604 struct sso_led_priv
*priv
= led
->priv
;
607 devm_led_classdev_unregister(priv
->dev
, &led
->cdev
);
609 /* clear HW control bit */
610 if (led
->desc
.hw_trig
)
611 regmap_update_bits(priv
->mmap
, SSO_CON3
, BIT(led
->desc
.pin
), 0);
617 __sso_led_dt_parse(struct sso_led_priv
*priv
, struct fwnode_handle
*fw_ssoled
)
619 struct fwnode_handle
*fwnode_child
;
620 struct device
*dev
= priv
->dev
;
621 struct sso_led_desc
*desc
;
627 fwnode_for_each_child_node(fw_ssoled
, fwnode_child
) {
628 led
= devm_kzalloc(dev
, sizeof(*led
), GFP_KERNEL
);
634 INIT_LIST_HEAD(&led
->list
);
638 led
->gpiod
= devm_fwnode_gpiod_get(dev
, fwnode_child
, NULL
,
640 if (IS_ERR(led
->gpiod
)) {
641 ret
= dev_err_probe(dev
, PTR_ERR(led
->gpiod
), "led: get gpio fail!\n");
645 fwnode_property_read_string(fwnode_child
,
646 "linux,default-trigger",
647 &desc
->default_trigger
);
649 if (fwnode_property_present(fwnode_child
,
650 "retain-state-suspended"))
651 desc
->retain_state_suspended
= 1;
653 if (fwnode_property_present(fwnode_child
,
654 "retain-state-shutdown"))
655 desc
->retain_state_shutdown
= 1;
657 if (fwnode_property_present(fwnode_child
, "panic-indicator"))
658 desc
->panic_indicator
= 1;
660 ret
= fwnode_property_read_u32(fwnode_child
, "reg", &prop
);
663 if (prop
>= SSO_LED_MAX_NUM
) {
664 dev_err(dev
, "invalid LED pin:%u\n", prop
);
670 if (fwnode_property_present(fwnode_child
, "intel,sso-hw-blink"))
673 desc
->hw_trig
= fwnode_property_read_bool(fwnode_child
,
674 "intel,sso-hw-trigger");
676 desc
->default_trigger
= NULL
;
677 desc
->retain_state_shutdown
= 0;
678 desc
->retain_state_suspended
= 0;
679 desc
->panic_indicator
= 0;
683 if (fwnode_property_read_u32(fwnode_child
,
684 "intel,sso-blink-rate-hz", &prop
)) {
685 /* default first freq rate */
687 desc
->blink_rate
= priv
->freq
[desc
->freq_idx
];
689 desc
->freq_idx
= sso_get_blink_rate_idx(priv
, prop
);
690 if (desc
->freq_idx
== -1)
691 desc
->freq_idx
= MAX_FREQ_RANK
- 1;
693 desc
->blink_rate
= priv
->freq
[desc
->freq_idx
];
696 if (!fwnode_property_read_string(fwnode_child
, "default-state", &tmp
)) {
697 if (!strcmp(tmp
, "on"))
698 desc
->brightness
= LED_FULL
;
701 ret
= sso_create_led(priv
, led
, fwnode_child
);
709 fwnode_handle_put(fwnode_child
);
710 /* unregister leds */
711 list_for_each_entry(led
, &priv
->led_list
, list
)
712 sso_led_shutdown(led
);
717 static int sso_led_dt_parse(struct sso_led_priv
*priv
)
719 struct fwnode_handle
*fwnode
= dev_fwnode(priv
->dev
);
720 struct fwnode_handle
*fw_ssoled
;
721 struct device
*dev
= priv
->dev
;
725 count
= device_get_child_node_count(dev
);
729 fw_ssoled
= fwnode_get_named_child_node(fwnode
, "ssoled");
731 ret
= __sso_led_dt_parse(priv
, fw_ssoled
);
732 fwnode_handle_put(fw_ssoled
);
740 static int sso_probe_gpios(struct sso_led_priv
*priv
)
742 struct device
*dev
= priv
->dev
;
745 if (device_property_read_u32(dev
, "ngpios", &priv
->gpio
.pins
))
746 priv
->gpio
.pins
= MAX_PIN_NUM_PER_BANK
;
748 if (priv
->gpio
.pins
> MAX_PIN_NUM_PER_BANK
)
751 if (device_property_read_u32(dev
, "intel,sso-update-rate-hz",
755 priv
->gpio
.edge
= DATA_CLK_EDGE
;
756 priv
->gpio
.shift_clk_freq
= -1;
758 ret
= sso_gpio_hw_init(priv
);
762 return sso_gpio_gc_init(dev
, priv
);
765 static void sso_clock_disable_unprepare(void *data
)
767 struct sso_led_priv
*priv
= data
;
769 clk_bulk_disable_unprepare(ARRAY_SIZE(priv
->clocks
), priv
->clocks
);
772 static int intel_sso_led_probe(struct platform_device
*pdev
)
774 struct device
*dev
= &pdev
->dev
;
775 struct sso_led_priv
*priv
;
778 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
786 priv
->clocks
[0].id
= "sso";
789 priv
->clocks
[1].id
= "fpid";
791 ret
= devm_clk_bulk_get(dev
, ARRAY_SIZE(priv
->clocks
), priv
->clocks
);
793 dev_err(dev
, "Getting clocks failed!\n");
797 ret
= clk_bulk_prepare_enable(ARRAY_SIZE(priv
->clocks
), priv
->clocks
);
799 dev_err(dev
, "Failed to prepare and enable clocks!\n");
803 ret
= devm_add_action_or_reset(dev
, sso_clock_disable_unprepare
, priv
);
807 priv
->fpid_clkrate
= clk_get_rate(priv
->clocks
[1].clk
);
809 priv
->mmap
= syscon_node_to_regmap(dev
->of_node
);
811 priv
->mmap
= syscon_node_to_regmap(dev
->of_node
);
812 if (IS_ERR(priv
->mmap
)) {
813 dev_err(dev
, "Failed to map iomem!\n");
814 return PTR_ERR(priv
->mmap
);
817 ret
= sso_probe_gpios(priv
);
819 regmap_exit(priv
->mmap
);
823 INIT_LIST_HEAD(&priv
->led_list
);
825 platform_set_drvdata(pdev
, priv
);
828 priv
->gptc_clkrate
= DEF_GPTC_CLK_RATE
;
830 ret
= sso_led_dt_parse(priv
);
832 regmap_exit(priv
->mmap
);
835 dev_info(priv
->dev
, "sso LED init success!\n");
840 static void intel_sso_led_remove(struct platform_device
*pdev
)
842 struct sso_led_priv
*priv
;
843 struct sso_led
*led
, *n
;
845 priv
= platform_get_drvdata(pdev
);
847 list_for_each_entry_safe(led
, n
, &priv
->led_list
, list
) {
848 list_del(&led
->list
);
849 sso_led_shutdown(led
);
852 regmap_exit(priv
->mmap
);
855 static const struct of_device_id of_sso_led_match
[] = {
856 { .compatible
= "intel,lgm-ssoled" },
860 MODULE_DEVICE_TABLE(of
, of_sso_led_match
);
862 static struct platform_driver intel_sso_led_driver
= {
863 .probe
= intel_sso_led_probe
,
864 .remove
= intel_sso_led_remove
,
866 .name
= "lgm-ssoled",
867 .of_match_table
= of_sso_led_match
,
871 module_platform_driver(intel_sso_led_driver
);
873 MODULE_DESCRIPTION("Intel SSO LED/GPIO driver");
874 MODULE_LICENSE("GPL v2");