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

rt4831.c (3172B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Copyright (c) 2021 Richtek Technology Corp.
      4 *
      5 * Author: ChiYuan Huang <cy_huang@richtek.com>
      6 */
      7
      8#include <linux/gpio/consumer.h>
      9#include <linux/i2c.h>
     10#include <linux/kernel.h>
     11#include <linux/mfd/core.h>
     12#include <linux/module.h>
     13#include <linux/regmap.h>
     14
     15#define RT4831_REG_REVISION	0x01
     16#define RT4831_REG_ENABLE	0x08
     17#define RT4831_REG_I2CPROT	0x15
     18
     19#define RICHTEK_VENDOR_ID	0x03
     20#define RT4831_VID_MASK		GENMASK(1, 0)
     21#define RT4831_RESET_MASK	BIT(7)
     22#define RT4831_I2CSAFETMR_MASK	BIT(0)
     23
     24static const struct mfd_cell rt4831_subdevs[] = {
     25	MFD_CELL_OF("rt4831-backlight", NULL, NULL, 0, 0, "richtek,rt4831-backlight"),
     26	MFD_CELL_NAME("rt4831-regulator")
     27};
     28
     29static bool rt4831_is_accessible_reg(struct device *dev, unsigned int reg)
     30{
     31	if (reg >= RT4831_REG_REVISION && reg <= RT4831_REG_I2CPROT)
     32		return true;
     33	return false;
     34}
     35
     36static const struct regmap_config rt4831_regmap_config = {
     37	.reg_bits = 8,
     38	.val_bits = 8,
     39	.max_register = RT4831_REG_I2CPROT,
     40
     41	.readable_reg = rt4831_is_accessible_reg,
     42	.writeable_reg = rt4831_is_accessible_reg,
     43};
     44
     45static int rt4831_probe(struct i2c_client *client)
     46{
     47	struct gpio_desc *enable_gpio;
     48	struct regmap *regmap;
     49	unsigned int chip_id;
     50	int ret;
     51
     52	enable_gpio = devm_gpiod_get_optional(&client->dev, "enable", GPIOD_OUT_HIGH);
     53	if (IS_ERR(enable_gpio)) {
     54		dev_err(&client->dev, "Failed to get 'enable' GPIO\n");
     55		return PTR_ERR(enable_gpio);
     56	}
     57
     58	regmap = devm_regmap_init_i2c(client, &rt4831_regmap_config);
     59	if (IS_ERR(regmap)) {
     60		dev_err(&client->dev, "Failed to initialize regmap\n");
     61		return PTR_ERR(regmap);
     62	}
     63
     64	ret = regmap_read(regmap, RT4831_REG_REVISION, &chip_id);
     65	if (ret) {
     66		dev_err(&client->dev, "Failed to get H/W revision\n");
     67		return ret;
     68	}
     69
     70	if ((chip_id & RT4831_VID_MASK) != RICHTEK_VENDOR_ID) {
     71		dev_err(&client->dev, "Chip vendor ID 0x%02x not matched\n", chip_id);
     72		return -ENODEV;
     73	}
     74
     75	/*
     76	 * Used to prevent the abnormal shutdown.
     77	 * If SCL/SDA both keep low for one second to reset HW.
     78	 */
     79	ret = regmap_update_bits(regmap, RT4831_REG_I2CPROT, RT4831_I2CSAFETMR_MASK,
     80				 RT4831_I2CSAFETMR_MASK);
     81	if (ret) {
     82		dev_err(&client->dev, "Failed to enable I2C safety timer\n");
     83		return ret;
     84	}
     85
     86	return devm_mfd_add_devices(&client->dev, PLATFORM_DEVID_AUTO, rt4831_subdevs,
     87				    ARRAY_SIZE(rt4831_subdevs), NULL, 0, NULL);
     88}
     89
     90static int rt4831_remove(struct i2c_client *client)
     91{
     92	struct regmap *regmap = dev_get_regmap(&client->dev, NULL);
     93	int ret;
     94
     95	/* Disable WLED and DSV outputs */
     96	ret = regmap_update_bits(regmap, RT4831_REG_ENABLE, RT4831_RESET_MASK, RT4831_RESET_MASK);
     97	if (ret)
     98		dev_warn(&client->dev, "Failed to disable outputs (%pe)\n", ERR_PTR(ret));
     99
    100	return 0;
    101}
    102
    103static const struct of_device_id __maybe_unused rt4831_of_match[] = {
    104	{ .compatible = "richtek,rt4831", },
    105	{}
    106};
    107MODULE_DEVICE_TABLE(of, rt4831_of_match);
    108
    109static struct i2c_driver rt4831_driver = {
    110	.driver = {
    111		.name = "rt4831",
    112		.of_match_table = rt4831_of_match,
    113	},
    114	.probe_new = rt4831_probe,
    115	.remove = rt4831_remove,
    116};
    117module_i2c_driver(rt4831_driver);
    118
    119MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
    120MODULE_LICENSE("GPL v2");