HELLCREEK_OVERFLOW_PERIOD);
 }
 
+static enum led_brightness hellcreek_get_brightness(struct hellcreek *hellcreek,
+                                                   int led)
+{
+       return (hellcreek->status_out & led) ? 1 : 0;
+}
+
+static void hellcreek_set_brightness(struct hellcreek *hellcreek, int led,
+                                    enum led_brightness b)
+{
+       mutex_lock(&hellcreek->ptp_lock);
+
+       if (b)
+               hellcreek->status_out |= led;
+       else
+               hellcreek->status_out &= ~led;
+
+       hellcreek_ptp_write(hellcreek, hellcreek->status_out, STATUS_OUT);
+
+       mutex_unlock(&hellcreek->ptp_lock);
+}
+
+static void hellcreek_led_sync_good_set(struct led_classdev *ldev,
+                                       enum led_brightness b)
+{
+       struct hellcreek *hellcreek = led_to_hellcreek(ldev, led_sync_good);
+
+       hellcreek_set_brightness(hellcreek, STATUS_OUT_SYNC_GOOD, b);
+}
+
+static enum led_brightness hellcreek_led_sync_good_get(struct led_classdev *ldev)
+{
+       struct hellcreek *hellcreek = led_to_hellcreek(ldev, led_sync_good);
+
+       return hellcreek_get_brightness(hellcreek, STATUS_OUT_SYNC_GOOD);
+}
+
+static void hellcreek_led_is_gm_set(struct led_classdev *ldev,
+                                   enum led_brightness b)
+{
+       struct hellcreek *hellcreek = led_to_hellcreek(ldev, led_is_gm);
+
+       hellcreek_set_brightness(hellcreek, STATUS_OUT_IS_GM, b);
+}
+
+static enum led_brightness hellcreek_led_is_gm_get(struct led_classdev *ldev)
+{
+       struct hellcreek *hellcreek = led_to_hellcreek(ldev, led_is_gm);
+
+       return hellcreek_get_brightness(hellcreek, STATUS_OUT_IS_GM);
+}
+
+/* There two available LEDs internally called sync_good and is_gm. However, the
+ * user might want to use a different label and specify the default state. Take
+ * those properties from device tree.
+ */
+static int hellcreek_led_setup(struct hellcreek *hellcreek)
+{
+       struct device_node *leds, *led = NULL;
+       const char *label, *state;
+       int ret = -EINVAL;
+
+       leds = of_find_node_by_name(hellcreek->dev->of_node, "leds");
+       if (!leds) {
+               dev_err(hellcreek->dev, "No LEDs specified in device tree!\n");
+               return ret;
+       }
+
+       hellcreek->status_out = 0;
+
+       led = of_get_next_available_child(leds, led);
+       if (!led) {
+               dev_err(hellcreek->dev, "First LED not specified!\n");
+               goto out;
+       }
+
+       ret = of_property_read_string(led, "label", &label);
+       hellcreek->led_sync_good.name = ret ? "sync_good" : label;
+
+       ret = of_property_read_string(led, "default-state", &state);
+       if (!ret) {
+               if (!strcmp(state, "on"))
+                       hellcreek->led_sync_good.brightness = 1;
+               else if (!strcmp(state, "off"))
+                       hellcreek->led_sync_good.brightness = 0;
+               else if (!strcmp(state, "keep"))
+                       hellcreek->led_sync_good.brightness =
+                               hellcreek_get_brightness(hellcreek,
+                                                        STATUS_OUT_SYNC_GOOD);
+       }
+
+       hellcreek->led_sync_good.max_brightness = 1;
+       hellcreek->led_sync_good.brightness_set = hellcreek_led_sync_good_set;
+       hellcreek->led_sync_good.brightness_get = hellcreek_led_sync_good_get;
+
+       led = of_get_next_available_child(leds, led);
+       if (!led) {
+               dev_err(hellcreek->dev, "Second LED not specified!\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       ret = of_property_read_string(led, "label", &label);
+       hellcreek->led_is_gm.name = ret ? "is_gm" : label;
+
+       ret = of_property_read_string(led, "default-state", &state);
+       if (!ret) {
+               if (!strcmp(state, "on"))
+                       hellcreek->led_is_gm.brightness = 1;
+               else if (!strcmp(state, "off"))
+                       hellcreek->led_is_gm.brightness = 0;
+               else if (!strcmp(state, "keep"))
+                       hellcreek->led_is_gm.brightness =
+                               hellcreek_get_brightness(hellcreek,
+                                                        STATUS_OUT_IS_GM);
+       }
+
+       hellcreek->led_is_gm.max_brightness = 1;
+       hellcreek->led_is_gm.brightness_set = hellcreek_led_is_gm_set;
+       hellcreek->led_is_gm.brightness_get = hellcreek_led_is_gm_get;
+
+       /* Set initial state */
+       if (hellcreek->led_sync_good.brightness == 1)
+               hellcreek_set_brightness(hellcreek, STATUS_OUT_SYNC_GOOD, 1);
+       if (hellcreek->led_is_gm.brightness == 1)
+               hellcreek_set_brightness(hellcreek, STATUS_OUT_IS_GM, 1);
+
+       /* Register both leds */
+       led_classdev_register(hellcreek->dev, &hellcreek->led_sync_good);
+       led_classdev_register(hellcreek->dev, &hellcreek->led_is_gm);
+
+       ret = 0;
+
+out:
+       of_node_put(leds);
+
+       return ret;
+}
+
 int hellcreek_ptp_setup(struct hellcreek *hellcreek)
 {
        u16 status;
+       int ret;
 
        /* Set up the overflow work */
        INIT_DELAYED_WORK(&hellcreek->overflow_work,
        hellcreek_ptp_write(hellcreek, status | PR_CLOCK_STATUS_C_ENA_DRIFT,
                            PR_CLOCK_STATUS_C);
 
+       /* LED setup */
+       ret = hellcreek_led_setup(hellcreek);
+       if (ret) {
+               if (hellcreek->ptp_clock)
+                       ptp_clock_unregister(hellcreek->ptp_clock);
+               return ret;
+       }
+
        schedule_delayed_work(&hellcreek->overflow_work,
                              HELLCREEK_OVERFLOW_PERIOD);
 
 
 void hellcreek_ptp_free(struct hellcreek *hellcreek)
 {
+       led_classdev_unregister(&hellcreek->led_is_gm);
+       led_classdev_unregister(&hellcreek->led_sync_good);
        cancel_delayed_work_sync(&hellcreek->overflow_work);
        if (hellcreek->ptp_clock)
                ptp_clock_unregister(hellcreek->ptp_clock);