cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

leds-max77650.c (3690B)


      1// SPDX-License-Identifier: GPL-2.0
      2//
      3// Copyright (C) 2018 BayLibre SAS
      4// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
      5//
      6// LED driver for MAXIM 77650/77651 charger/power-supply.
      7
      8#include <linux/i2c.h>
      9#include <linux/leds.h>
     10#include <linux/mfd/max77650.h>
     11#include <linux/module.h>
     12#include <linux/platform_device.h>
     13#include <linux/regmap.h>
     14
     15#define MAX77650_LED_NUM_LEDS		3
     16
     17#define MAX77650_LED_A_BASE		0x40
     18#define MAX77650_LED_B_BASE		0x43
     19
     20#define MAX77650_LED_BR_MASK		GENMASK(4, 0)
     21#define MAX77650_LED_EN_MASK		GENMASK(7, 6)
     22
     23#define MAX77650_LED_MAX_BRIGHTNESS	MAX77650_LED_BR_MASK
     24
     25/* Enable EN_LED_MSTR. */
     26#define MAX77650_LED_TOP_DEFAULT	BIT(0)
     27
     28#define MAX77650_LED_ENABLE		GENMASK(7, 6)
     29#define MAX77650_LED_DISABLE		0x00
     30
     31#define MAX77650_LED_A_DEFAULT		MAX77650_LED_DISABLE
     32/* 100% on duty */
     33#define MAX77650_LED_B_DEFAULT		GENMASK(3, 0)
     34
     35struct max77650_led {
     36	struct led_classdev cdev;
     37	struct regmap *map;
     38	unsigned int regA;
     39	unsigned int regB;
     40};
     41
     42static struct max77650_led *max77650_to_led(struct led_classdev *cdev)
     43{
     44	return container_of(cdev, struct max77650_led, cdev);
     45}
     46
     47static int max77650_led_brightness_set(struct led_classdev *cdev,
     48				       enum led_brightness brightness)
     49{
     50	struct max77650_led *led = max77650_to_led(cdev);
     51	int val, mask;
     52
     53	mask = MAX77650_LED_BR_MASK | MAX77650_LED_EN_MASK;
     54
     55	if (brightness == LED_OFF)
     56		val = MAX77650_LED_DISABLE;
     57	else
     58		val = MAX77650_LED_ENABLE | brightness;
     59
     60	return regmap_update_bits(led->map, led->regA, mask, val);
     61}
     62
     63static int max77650_led_probe(struct platform_device *pdev)
     64{
     65	struct fwnode_handle *child;
     66	struct max77650_led *leds, *led;
     67	struct device *dev;
     68	struct regmap *map;
     69	int rv, num_leds;
     70	u32 reg;
     71
     72	dev = &pdev->dev;
     73
     74	leds = devm_kcalloc(dev, sizeof(*leds),
     75			    MAX77650_LED_NUM_LEDS, GFP_KERNEL);
     76	if (!leds)
     77		return -ENOMEM;
     78
     79	map = dev_get_regmap(dev->parent, NULL);
     80	if (!map)
     81		return -ENODEV;
     82
     83	num_leds = device_get_child_node_count(dev);
     84	if (!num_leds || num_leds > MAX77650_LED_NUM_LEDS)
     85		return -ENODEV;
     86
     87	device_for_each_child_node(dev, child) {
     88		struct led_init_data init_data = {};
     89
     90		rv = fwnode_property_read_u32(child, "reg", &reg);
     91		if (rv || reg >= MAX77650_LED_NUM_LEDS) {
     92			rv = -EINVAL;
     93			goto err_node_put;
     94		}
     95
     96		led = &leds[reg];
     97		led->map = map;
     98		led->regA = MAX77650_LED_A_BASE + reg;
     99		led->regB = MAX77650_LED_B_BASE + reg;
    100		led->cdev.brightness_set_blocking = max77650_led_brightness_set;
    101		led->cdev.max_brightness = MAX77650_LED_MAX_BRIGHTNESS;
    102
    103		init_data.fwnode = child;
    104		init_data.devicename = "max77650";
    105		/* for backwards compatibility if `label` is not present */
    106		init_data.default_label = ":";
    107
    108		rv = devm_led_classdev_register_ext(dev, &led->cdev,
    109						    &init_data);
    110		if (rv)
    111			goto err_node_put;
    112
    113		rv = regmap_write(map, led->regA, MAX77650_LED_A_DEFAULT);
    114		if (rv)
    115			goto err_node_put;
    116
    117		rv = regmap_write(map, led->regB, MAX77650_LED_B_DEFAULT);
    118		if (rv)
    119			goto err_node_put;
    120	}
    121
    122	return regmap_write(map,
    123			    MAX77650_REG_CNFG_LED_TOP,
    124			    MAX77650_LED_TOP_DEFAULT);
    125err_node_put:
    126	fwnode_handle_put(child);
    127	return rv;
    128}
    129
    130static const struct of_device_id max77650_led_of_match[] = {
    131	{ .compatible = "maxim,max77650-led" },
    132	{ }
    133};
    134MODULE_DEVICE_TABLE(of, max77650_led_of_match);
    135
    136static struct platform_driver max77650_led_driver = {
    137	.driver = {
    138		.name = "max77650-led",
    139		.of_match_table = max77650_led_of_match,
    140	},
    141	.probe = max77650_led_probe,
    142};
    143module_platform_driver(max77650_led_driver);
    144
    145MODULE_DESCRIPTION("MAXIM 77650/77651 LED driver");
    146MODULE_AUTHOR("Bartosz Golaszewski <bgolaszewski@baylibre.com>");
    147MODULE_LICENSE("GPL v2");
    148MODULE_ALIAS("platform:max77650-led");