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

da9063-core.c (4919B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Device access for Dialog DA9063 modules
      4 *
      5 * Copyright 2012 Dialog Semiconductors Ltd.
      6 * Copyright 2013 Philipp Zabel, Pengutronix
      7 *
      8 * Author: Krystian Garbaciak, Dialog Semiconductor
      9 * Author: Michal Hajduk, Dialog Semiconductor
     10 *
     11 */
     12
     13#include <linux/kernel.h>
     14#include <linux/module.h>
     15#include <linux/init.h>
     16#include <linux/slab.h>
     17#include <linux/device.h>
     18#include <linux/delay.h>
     19#include <linux/interrupt.h>
     20#include <linux/mutex.h>
     21#include <linux/mfd/core.h>
     22#include <linux/regmap.h>
     23
     24#include <linux/mfd/da9063/core.h>
     25#include <linux/mfd/da9063/registers.h>
     26
     27#include <linux/proc_fs.h>
     28#include <linux/kthread.h>
     29#include <linux/uaccess.h>
     30
     31
     32static const struct resource da9063_regulators_resources[] = {
     33	{
     34		.name	= "LDO_LIM",
     35		.start	= DA9063_IRQ_LDO_LIM,
     36		.end	= DA9063_IRQ_LDO_LIM,
     37		.flags	= IORESOURCE_IRQ,
     38	},
     39};
     40
     41static const struct resource da9063_rtc_resources[] = {
     42	{
     43		.name	= "ALARM",
     44		.start	= DA9063_IRQ_ALARM,
     45		.end	= DA9063_IRQ_ALARM,
     46		.flags	= IORESOURCE_IRQ,
     47	},
     48	{
     49		.name	= "TICK",
     50		.start	= DA9063_IRQ_TICK,
     51		.end	= DA9063_IRQ_TICK,
     52		.flags	= IORESOURCE_IRQ,
     53	}
     54};
     55
     56static const struct resource da9063_onkey_resources[] = {
     57	{
     58		.name	= "ONKEY",
     59		.start	= DA9063_IRQ_ONKEY,
     60		.end	= DA9063_IRQ_ONKEY,
     61		.flags	= IORESOURCE_IRQ,
     62	},
     63};
     64
     65static const struct resource da9063_hwmon_resources[] = {
     66	{
     67		.start	= DA9063_IRQ_ADC_RDY,
     68		.end	= DA9063_IRQ_ADC_RDY,
     69		.flags	= IORESOURCE_IRQ,
     70	},
     71};
     72
     73
     74static const struct mfd_cell da9063_common_devs[] = {
     75	{
     76		.name		= DA9063_DRVNAME_REGULATORS,
     77		.num_resources	= ARRAY_SIZE(da9063_regulators_resources),
     78		.resources	= da9063_regulators_resources,
     79	},
     80	{
     81		.name		= DA9063_DRVNAME_LEDS,
     82	},
     83	{
     84		.name		= DA9063_DRVNAME_WATCHDOG,
     85		.of_compatible	= "dlg,da9063-watchdog",
     86	},
     87	{
     88		.name		= DA9063_DRVNAME_HWMON,
     89		.num_resources	= ARRAY_SIZE(da9063_hwmon_resources),
     90		.resources	= da9063_hwmon_resources,
     91	},
     92	{
     93		.name		= DA9063_DRVNAME_ONKEY,
     94		.num_resources	= ARRAY_SIZE(da9063_onkey_resources),
     95		.resources	= da9063_onkey_resources,
     96		.of_compatible = "dlg,da9063-onkey",
     97	},
     98	{
     99		.name		= DA9063_DRVNAME_VIBRATION,
    100	},
    101};
    102
    103/* Only present on DA9063 , not on DA9063L */
    104static const struct mfd_cell da9063_devs[] = {
    105	{
    106		.name		= DA9063_DRVNAME_RTC,
    107		.num_resources	= ARRAY_SIZE(da9063_rtc_resources),
    108		.resources	= da9063_rtc_resources,
    109		.of_compatible	= "dlg,da9063-rtc",
    110	},
    111};
    112
    113static int da9063_clear_fault_log(struct da9063 *da9063)
    114{
    115	int ret = 0;
    116	int fault_log = 0;
    117
    118	ret = regmap_read(da9063->regmap, DA9063_REG_FAULT_LOG, &fault_log);
    119	if (ret < 0) {
    120		dev_err(da9063->dev, "Cannot read FAULT_LOG.\n");
    121		return -EIO;
    122	}
    123
    124	if (fault_log) {
    125		if (fault_log & DA9063_TWD_ERROR)
    126			dev_dbg(da9063->dev,
    127				"Fault log entry detected: DA9063_TWD_ERROR\n");
    128		if (fault_log & DA9063_POR)
    129			dev_dbg(da9063->dev,
    130				"Fault log entry detected: DA9063_POR\n");
    131		if (fault_log & DA9063_VDD_FAULT)
    132			dev_dbg(da9063->dev,
    133				"Fault log entry detected: DA9063_VDD_FAULT\n");
    134		if (fault_log & DA9063_VDD_START)
    135			dev_dbg(da9063->dev,
    136				"Fault log entry detected: DA9063_VDD_START\n");
    137		if (fault_log & DA9063_TEMP_CRIT)
    138			dev_dbg(da9063->dev,
    139				"Fault log entry detected: DA9063_TEMP_CRIT\n");
    140		if (fault_log & DA9063_KEY_RESET)
    141			dev_dbg(da9063->dev,
    142				"Fault log entry detected: DA9063_KEY_RESET\n");
    143		if (fault_log & DA9063_NSHUTDOWN)
    144			dev_dbg(da9063->dev,
    145				"Fault log entry detected: DA9063_NSHUTDOWN\n");
    146		if (fault_log & DA9063_WAIT_SHUT)
    147			dev_dbg(da9063->dev,
    148				"Fault log entry detected: DA9063_WAIT_SHUT\n");
    149	}
    150
    151	ret = regmap_write(da9063->regmap,
    152			   DA9063_REG_FAULT_LOG,
    153			   fault_log);
    154	if (ret < 0)
    155		dev_err(da9063->dev,
    156			"Cannot reset FAULT_LOG values %d\n", ret);
    157
    158	return ret;
    159}
    160
    161int da9063_device_init(struct da9063 *da9063, unsigned int irq)
    162{
    163	int ret;
    164
    165	ret = da9063_clear_fault_log(da9063);
    166	if (ret < 0)
    167		dev_err(da9063->dev, "Cannot clear fault log\n");
    168
    169	da9063->flags = 0;
    170	da9063->irq_base = -1;
    171	da9063->chip_irq = irq;
    172
    173	ret = da9063_irq_init(da9063);
    174	if (ret) {
    175		dev_err(da9063->dev, "Cannot initialize interrupts.\n");
    176		return ret;
    177	}
    178
    179	da9063->irq_base = regmap_irq_chip_get_base(da9063->regmap_irq);
    180
    181	ret = devm_mfd_add_devices(da9063->dev, PLATFORM_DEVID_NONE,
    182				   da9063_common_devs,
    183				   ARRAY_SIZE(da9063_common_devs),
    184				   NULL, da9063->irq_base, NULL);
    185	if (ret) {
    186		dev_err(da9063->dev, "Failed to add child devices\n");
    187		return ret;
    188	}
    189
    190	if (da9063->type == PMIC_TYPE_DA9063) {
    191		ret = devm_mfd_add_devices(da9063->dev, PLATFORM_DEVID_NONE,
    192					   da9063_devs, ARRAY_SIZE(da9063_devs),
    193					   NULL, da9063->irq_base, NULL);
    194		if (ret) {
    195			dev_err(da9063->dev, "Failed to add child devices\n");
    196			return ret;
    197		}
    198	}
    199
    200	return ret;
    201}
    202
    203MODULE_DESCRIPTION("PMIC driver for Dialog DA9063");
    204MODULE_AUTHOR("Krystian Garbaciak");
    205MODULE_AUTHOR("Michal Hajduk");
    206MODULE_LICENSE("GPL");