leds: aat1290: Add missing of_node_put
[sfrench/cifs-2.6.git] / drivers / leds / leds-bcm6328.c
index 1793727bc9ae5f6c64467a68b4646b92e0963e1b..0329dee4687b2b48942e462f625a44fd94660335 100644 (file)
 #define BCM6328_SERIAL_LED_SHIFT_DIR   BIT(16)
 #define BCM6328_LED_SHIFT_TEST         BIT(30)
 #define BCM6328_LED_TEST               BIT(31)
+#define BCM6328_INIT_MASK              (BCM6328_SERIAL_LED_EN | \
+                                        BCM6328_SERIAL_LED_MUX  | \
+                                        BCM6328_SERIAL_LED_CLK_NPOL | \
+                                        BCM6328_SERIAL_LED_DATA_PPOL | \
+                                        BCM6328_SERIAL_LED_SHIFT_DIR)
 
 #define BCM6328_LED_MODE_MASK          3
-#define BCM6328_LED_MODE_OFF           0
+#define BCM6328_LED_MODE_O           0
 #define BCM6328_LED_MODE_FAST          1
 #define BCM6328_LED_MODE_BLINK         2
-#define BCM6328_LED_MODE_O           3
+#define BCM6328_LED_MODE_OFF           3
 #define BCM6328_LED_SHIFT(X)           ((X) << 1)
 
 /**
@@ -121,9 +126,9 @@ static void bcm6328_led_set(struct led_classdev *led_cdev,
        *(led->blink_leds) &= ~BIT(led->pin);
        if ((led->active_low && value == LED_OFF) ||
            (!led->active_low && value != LED_OFF))
-               bcm6328_led_mode(led, BCM6328_LED_MODE_OFF);
-       else
                bcm6328_led_mode(led, BCM6328_LED_MODE_ON);
+       else
+               bcm6328_led_mode(led, BCM6328_LED_MODE_OFF);
        spin_unlock_irqrestore(led->lock, flags);
 }
 
@@ -281,11 +286,10 @@ static int bcm6328_led(struct device *dev, struct device_node *nc, u32 reg,
                                                    "linux,default-trigger",
                                                    NULL);
 
+       spin_lock_irqsave(lock, flags);
        if (!of_property_read_string(nc, "default-state", &state)) {
-               spin_lock_irqsave(lock, flags);
                if (!strcmp(state, "on")) {
                        led->cdev.brightness = LED_FULL;
-                       bcm6328_led_mode(led, BCM6328_LED_MODE_ON);
                } else if (!strcmp(state, "keep")) {
                        void __iomem *mode;
                        unsigned long val, shift;
@@ -296,20 +300,23 @@ static int bcm6328_led(struct device *dev, struct device_node *nc, u32 reg,
                        else
                                mode = mem + BCM6328_REG_MODE_LO;
 
-                       val = bcm6328_led_read(mode) >> (shift % 16);
+                       val = bcm6328_led_read(mode) >>
+                             BCM6328_LED_SHIFT(shift % 16);
                        val &= BCM6328_LED_MODE_MASK;
-                       if (val == BCM6328_LED_MODE_ON)
+                       if ((led->active_low && val == BCM6328_LED_MODE_OFF) ||
+                           (!led->active_low && val == BCM6328_LED_MODE_ON))
                                led->cdev.brightness = LED_FULL;
-                       else {
+                       else
                                led->cdev.brightness = LED_OFF;
-                               bcm6328_led_mode(led, BCM6328_LED_MODE_OFF);
-                       }
                } else {
                        led->cdev.brightness = LED_OFF;
-                       bcm6328_led_mode(led, BCM6328_LED_MODE_OFF);
                }
-               spin_unlock_irqrestore(lock, flags);
+       } else {
+               led->cdev.brightness = LED_OFF;
        }
+       spin_unlock_irqrestore(lock, flags);
+
+       bcm6328_led_set(&led->cdev, led->cdev.brightness);
 
        led->cdev.brightness_set = bcm6328_led_set;
        led->cdev.blink_set = bcm6328_blink_set;
@@ -360,9 +367,17 @@ static int bcm6328_leds_probe(struct platform_device *pdev)
        bcm6328_led_write(mem + BCM6328_REG_LNKACTSEL_LO, 0);
 
        val = bcm6328_led_read(mem + BCM6328_REG_INIT);
-       val &= ~BCM6328_SERIAL_LED_EN;
+       val &= ~(BCM6328_INIT_MASK);
        if (of_property_read_bool(np, "brcm,serial-leds"))
                val |= BCM6328_SERIAL_LED_EN;
+       if (of_property_read_bool(np, "brcm,serial-mux"))
+               val |= BCM6328_SERIAL_LED_MUX;
+       if (of_property_read_bool(np, "brcm,serial-clk-low"))
+               val |= BCM6328_SERIAL_LED_CLK_NPOL;
+       if (!of_property_read_bool(np, "brcm,serial-dat-low"))
+               val |= BCM6328_SERIAL_LED_DATA_PPOL;
+       if (!of_property_read_bool(np, "brcm,serial-shift-inv"))
+               val |= BCM6328_SERIAL_LED_SHIFT_DIR;
        bcm6328_led_write(mem + BCM6328_REG_INIT, val);
 
        for_each_available_child_of_node(np, child) {
@@ -373,7 +388,7 @@ static int bcm6328_leds_probe(struct platform_device *pdev)
                        continue;
 
                if (reg >= BCM6328_LED_MAX_COUNT) {
-                       dev_err(dev, "invalid LED (>= %d)\n",
+                       dev_err(dev, "invalid LED (%u >= %d)\n", reg,
                                BCM6328_LED_MAX_COUNT);
                        continue;
                }
@@ -384,8 +399,10 @@ static int bcm6328_leds_probe(struct platform_device *pdev)
                        rc = bcm6328_led(dev, child, reg, mem, lock,
                                         blink_leds, blink_delay);
 
-               if (rc < 0)
+               if (rc < 0) {
+                       of_node_put(child);
                        return rc;
+               }
        }
 
        return 0;