0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/i2c.h>
0009 #include <linux/leds.h>
0010 #include <linux/mfd/max77650.h>
0011 #include <linux/module.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/regmap.h>
0014
0015 #define MAX77650_LED_NUM_LEDS 3
0016
0017 #define MAX77650_LED_A_BASE 0x40
0018 #define MAX77650_LED_B_BASE 0x43
0019
0020 #define MAX77650_LED_BR_MASK GENMASK(4, 0)
0021 #define MAX77650_LED_EN_MASK GENMASK(7, 6)
0022
0023 #define MAX77650_LED_MAX_BRIGHTNESS MAX77650_LED_BR_MASK
0024
0025
0026 #define MAX77650_LED_TOP_DEFAULT BIT(0)
0027
0028 #define MAX77650_LED_ENABLE GENMASK(7, 6)
0029 #define MAX77650_LED_DISABLE 0x00
0030
0031 #define MAX77650_LED_A_DEFAULT MAX77650_LED_DISABLE
0032
0033 #define MAX77650_LED_B_DEFAULT GENMASK(3, 0)
0034
0035 struct max77650_led {
0036 struct led_classdev cdev;
0037 struct regmap *map;
0038 unsigned int regA;
0039 unsigned int regB;
0040 };
0041
0042 static struct max77650_led *max77650_to_led(struct led_classdev *cdev)
0043 {
0044 return container_of(cdev, struct max77650_led, cdev);
0045 }
0046
0047 static int max77650_led_brightness_set(struct led_classdev *cdev,
0048 enum led_brightness brightness)
0049 {
0050 struct max77650_led *led = max77650_to_led(cdev);
0051 int val, mask;
0052
0053 mask = MAX77650_LED_BR_MASK | MAX77650_LED_EN_MASK;
0054
0055 if (brightness == LED_OFF)
0056 val = MAX77650_LED_DISABLE;
0057 else
0058 val = MAX77650_LED_ENABLE | brightness;
0059
0060 return regmap_update_bits(led->map, led->regA, mask, val);
0061 }
0062
0063 static int max77650_led_probe(struct platform_device *pdev)
0064 {
0065 struct fwnode_handle *child;
0066 struct max77650_led *leds, *led;
0067 struct device *dev;
0068 struct regmap *map;
0069 int rv, num_leds;
0070 u32 reg;
0071
0072 dev = &pdev->dev;
0073
0074 leds = devm_kcalloc(dev, sizeof(*leds),
0075 MAX77650_LED_NUM_LEDS, GFP_KERNEL);
0076 if (!leds)
0077 return -ENOMEM;
0078
0079 map = dev_get_regmap(dev->parent, NULL);
0080 if (!map)
0081 return -ENODEV;
0082
0083 num_leds = device_get_child_node_count(dev);
0084 if (!num_leds || num_leds > MAX77650_LED_NUM_LEDS)
0085 return -ENODEV;
0086
0087 device_for_each_child_node(dev, child) {
0088 struct led_init_data init_data = {};
0089
0090 rv = fwnode_property_read_u32(child, "reg", ®);
0091 if (rv || reg >= MAX77650_LED_NUM_LEDS) {
0092 rv = -EINVAL;
0093 goto err_node_put;
0094 }
0095
0096 led = &leds[reg];
0097 led->map = map;
0098 led->regA = MAX77650_LED_A_BASE + reg;
0099 led->regB = MAX77650_LED_B_BASE + reg;
0100 led->cdev.brightness_set_blocking = max77650_led_brightness_set;
0101 led->cdev.max_brightness = MAX77650_LED_MAX_BRIGHTNESS;
0102
0103 init_data.fwnode = child;
0104 init_data.devicename = "max77650";
0105
0106 init_data.default_label = ":";
0107
0108 rv = devm_led_classdev_register_ext(dev, &led->cdev,
0109 &init_data);
0110 if (rv)
0111 goto err_node_put;
0112
0113 rv = regmap_write(map, led->regA, MAX77650_LED_A_DEFAULT);
0114 if (rv)
0115 goto err_node_put;
0116
0117 rv = regmap_write(map, led->regB, MAX77650_LED_B_DEFAULT);
0118 if (rv)
0119 goto err_node_put;
0120 }
0121
0122 return regmap_write(map,
0123 MAX77650_REG_CNFG_LED_TOP,
0124 MAX77650_LED_TOP_DEFAULT);
0125 err_node_put:
0126 fwnode_handle_put(child);
0127 return rv;
0128 }
0129
0130 static const struct of_device_id max77650_led_of_match[] = {
0131 { .compatible = "maxim,max77650-led" },
0132 { }
0133 };
0134 MODULE_DEVICE_TABLE(of, max77650_led_of_match);
0135
0136 static struct platform_driver max77650_led_driver = {
0137 .driver = {
0138 .name = "max77650-led",
0139 .of_match_table = max77650_led_of_match,
0140 },
0141 .probe = max77650_led_probe,
0142 };
0143 module_platform_driver(max77650_led_driver);
0144
0145 MODULE_DESCRIPTION("MAXIM 77650/77651 LED driver");
0146 MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
0147 MODULE_LICENSE("GPL v2");
0148 MODULE_ALIAS("platform:max77650-led");