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

da9055-core.c (9432B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Device access for Dialog DA9055 PMICs.
      4 *
      5 * Copyright(c) 2012 Dialog Semiconductor Ltd.
      6 *
      7 * Author: David Dajun Chen <dchen@diasemi.com>
      8 */
      9
     10#include <linux/module.h>
     11#include <linux/device.h>
     12#include <linux/input.h>
     13#include <linux/irq.h>
     14#include <linux/mutex.h>
     15
     16#include <linux/mfd/core.h>
     17#include <linux/mfd/da9055/core.h>
     18#include <linux/mfd/da9055/pdata.h>
     19#include <linux/mfd/da9055/reg.h>
     20
     21#define DA9055_IRQ_NONKEY_MASK		0x01
     22#define DA9055_IRQ_ALM_MASK		0x02
     23#define DA9055_IRQ_TICK_MASK		0x04
     24#define DA9055_IRQ_ADC_MASK		0x08
     25#define DA9055_IRQ_BUCK_ILIM_MASK	0x08
     26
     27static bool da9055_register_readable(struct device *dev, unsigned int reg)
     28{
     29	switch (reg) {
     30	case DA9055_REG_STATUS_A:
     31	case DA9055_REG_STATUS_B:
     32	case DA9055_REG_EVENT_A:
     33	case DA9055_REG_EVENT_B:
     34	case DA9055_REG_EVENT_C:
     35	case DA9055_REG_IRQ_MASK_A:
     36	case DA9055_REG_IRQ_MASK_B:
     37	case DA9055_REG_IRQ_MASK_C:
     38
     39	case DA9055_REG_CONTROL_A:
     40	case DA9055_REG_CONTROL_B:
     41	case DA9055_REG_CONTROL_C:
     42	case DA9055_REG_CONTROL_D:
     43	case DA9055_REG_CONTROL_E:
     44
     45	case DA9055_REG_ADC_MAN:
     46	case DA9055_REG_ADC_CONT:
     47	case DA9055_REG_VSYS_MON:
     48	case DA9055_REG_ADC_RES_L:
     49	case DA9055_REG_ADC_RES_H:
     50	case DA9055_REG_VSYS_RES:
     51	case DA9055_REG_ADCIN1_RES:
     52	case DA9055_REG_ADCIN2_RES:
     53	case DA9055_REG_ADCIN3_RES:
     54
     55	case DA9055_REG_COUNT_S:
     56	case DA9055_REG_COUNT_MI:
     57	case DA9055_REG_COUNT_H:
     58	case DA9055_REG_COUNT_D:
     59	case DA9055_REG_COUNT_MO:
     60	case DA9055_REG_COUNT_Y:
     61	case DA9055_REG_ALARM_H:
     62	case DA9055_REG_ALARM_D:
     63	case DA9055_REG_ALARM_MI:
     64	case DA9055_REG_ALARM_MO:
     65	case DA9055_REG_ALARM_Y:
     66
     67	case DA9055_REG_GPIO0_1:
     68	case DA9055_REG_GPIO2:
     69	case DA9055_REG_GPIO_MODE0_2:
     70
     71	case DA9055_REG_BCORE_CONT:
     72	case DA9055_REG_BMEM_CONT:
     73	case DA9055_REG_LDO1_CONT:
     74	case DA9055_REG_LDO2_CONT:
     75	case DA9055_REG_LDO3_CONT:
     76	case DA9055_REG_LDO4_CONT:
     77	case DA9055_REG_LDO5_CONT:
     78	case DA9055_REG_LDO6_CONT:
     79	case DA9055_REG_BUCK_LIM:
     80	case DA9055_REG_BCORE_MODE:
     81	case DA9055_REG_VBCORE_A:
     82	case DA9055_REG_VBMEM_A:
     83	case DA9055_REG_VLDO1_A:
     84	case DA9055_REG_VLDO2_A:
     85	case DA9055_REG_VLDO3_A:
     86	case DA9055_REG_VLDO4_A:
     87	case DA9055_REG_VLDO5_A:
     88	case DA9055_REG_VLDO6_A:
     89	case DA9055_REG_VBCORE_B:
     90	case DA9055_REG_VBMEM_B:
     91	case DA9055_REG_VLDO1_B:
     92	case DA9055_REG_VLDO2_B:
     93	case DA9055_REG_VLDO3_B:
     94	case DA9055_REG_VLDO4_B:
     95	case DA9055_REG_VLDO5_B:
     96	case DA9055_REG_VLDO6_B:
     97		return true;
     98	default:
     99		return false;
    100	}
    101}
    102
    103static bool da9055_register_writeable(struct device *dev, unsigned int reg)
    104{
    105	switch (reg) {
    106	case DA9055_REG_STATUS_A:
    107	case DA9055_REG_STATUS_B:
    108	case DA9055_REG_EVENT_A:
    109	case DA9055_REG_EVENT_B:
    110	case DA9055_REG_EVENT_C:
    111	case DA9055_REG_IRQ_MASK_A:
    112	case DA9055_REG_IRQ_MASK_B:
    113	case DA9055_REG_IRQ_MASK_C:
    114
    115	case DA9055_REG_CONTROL_A:
    116	case DA9055_REG_CONTROL_B:
    117	case DA9055_REG_CONTROL_C:
    118	case DA9055_REG_CONTROL_D:
    119	case DA9055_REG_CONTROL_E:
    120
    121	case DA9055_REG_ADC_MAN:
    122	case DA9055_REG_ADC_CONT:
    123	case DA9055_REG_VSYS_MON:
    124	case DA9055_REG_ADC_RES_L:
    125	case DA9055_REG_ADC_RES_H:
    126	case DA9055_REG_VSYS_RES:
    127	case DA9055_REG_ADCIN1_RES:
    128	case DA9055_REG_ADCIN2_RES:
    129	case DA9055_REG_ADCIN3_RES:
    130
    131	case DA9055_REG_COUNT_S:
    132	case DA9055_REG_COUNT_MI:
    133	case DA9055_REG_COUNT_H:
    134	case DA9055_REG_COUNT_D:
    135	case DA9055_REG_COUNT_MO:
    136	case DA9055_REG_COUNT_Y:
    137	case DA9055_REG_ALARM_H:
    138	case DA9055_REG_ALARM_D:
    139	case DA9055_REG_ALARM_MI:
    140	case DA9055_REG_ALARM_MO:
    141	case DA9055_REG_ALARM_Y:
    142
    143	case DA9055_REG_GPIO0_1:
    144	case DA9055_REG_GPIO2:
    145	case DA9055_REG_GPIO_MODE0_2:
    146
    147	case DA9055_REG_BCORE_CONT:
    148	case DA9055_REG_BMEM_CONT:
    149	case DA9055_REG_LDO1_CONT:
    150	case DA9055_REG_LDO2_CONT:
    151	case DA9055_REG_LDO3_CONT:
    152	case DA9055_REG_LDO4_CONT:
    153	case DA9055_REG_LDO5_CONT:
    154	case DA9055_REG_LDO6_CONT:
    155	case DA9055_REG_BUCK_LIM:
    156	case DA9055_REG_BCORE_MODE:
    157	case DA9055_REG_VBCORE_A:
    158	case DA9055_REG_VBMEM_A:
    159	case DA9055_REG_VLDO1_A:
    160	case DA9055_REG_VLDO2_A:
    161	case DA9055_REG_VLDO3_A:
    162	case DA9055_REG_VLDO4_A:
    163	case DA9055_REG_VLDO5_A:
    164	case DA9055_REG_VLDO6_A:
    165	case DA9055_REG_VBCORE_B:
    166	case DA9055_REG_VBMEM_B:
    167	case DA9055_REG_VLDO1_B:
    168	case DA9055_REG_VLDO2_B:
    169	case DA9055_REG_VLDO3_B:
    170	case DA9055_REG_VLDO4_B:
    171	case DA9055_REG_VLDO5_B:
    172	case DA9055_REG_VLDO6_B:
    173		return true;
    174	default:
    175		return false;
    176	}
    177}
    178
    179static bool da9055_register_volatile(struct device *dev, unsigned int reg)
    180{
    181	switch (reg) {
    182	case DA9055_REG_STATUS_A:
    183	case DA9055_REG_STATUS_B:
    184	case DA9055_REG_EVENT_A:
    185	case DA9055_REG_EVENT_B:
    186	case DA9055_REG_EVENT_C:
    187
    188	case DA9055_REG_CONTROL_A:
    189	case DA9055_REG_CONTROL_E:
    190
    191	case DA9055_REG_ADC_MAN:
    192	case DA9055_REG_ADC_RES_L:
    193	case DA9055_REG_ADC_RES_H:
    194	case DA9055_REG_VSYS_RES:
    195	case DA9055_REG_ADCIN1_RES:
    196	case DA9055_REG_ADCIN2_RES:
    197	case DA9055_REG_ADCIN3_RES:
    198
    199	case DA9055_REG_COUNT_S:
    200	case DA9055_REG_COUNT_MI:
    201	case DA9055_REG_COUNT_H:
    202	case DA9055_REG_COUNT_D:
    203	case DA9055_REG_COUNT_MO:
    204	case DA9055_REG_COUNT_Y:
    205	case DA9055_REG_ALARM_MI:
    206
    207	case DA9055_REG_BCORE_CONT:
    208	case DA9055_REG_BMEM_CONT:
    209	case DA9055_REG_LDO1_CONT:
    210	case DA9055_REG_LDO2_CONT:
    211	case DA9055_REG_LDO3_CONT:
    212	case DA9055_REG_LDO4_CONT:
    213	case DA9055_REG_LDO5_CONT:
    214	case DA9055_REG_LDO6_CONT:
    215		return true;
    216	default:
    217		return false;
    218	}
    219}
    220
    221static const struct regmap_irq da9055_irqs[] = {
    222	[DA9055_IRQ_NONKEY] = {
    223		.reg_offset = 0,
    224		.mask = DA9055_IRQ_NONKEY_MASK,
    225	},
    226	[DA9055_IRQ_ALARM] = {
    227		.reg_offset = 0,
    228		.mask = DA9055_IRQ_ALM_MASK,
    229	},
    230	[DA9055_IRQ_TICK] = {
    231		.reg_offset = 0,
    232		.mask = DA9055_IRQ_TICK_MASK,
    233	},
    234	[DA9055_IRQ_HWMON] = {
    235		.reg_offset = 0,
    236		.mask = DA9055_IRQ_ADC_MASK,
    237	},
    238	[DA9055_IRQ_REGULATOR] = {
    239		.reg_offset = 1,
    240		.mask = DA9055_IRQ_BUCK_ILIM_MASK,
    241	},
    242};
    243
    244const struct regmap_config da9055_regmap_config = {
    245	.reg_bits = 8,
    246	.val_bits = 8,
    247
    248	.cache_type = REGCACHE_RBTREE,
    249
    250	.max_register = DA9055_MAX_REGISTER_CNT,
    251	.readable_reg = da9055_register_readable,
    252	.writeable_reg = da9055_register_writeable,
    253	.volatile_reg = da9055_register_volatile,
    254};
    255EXPORT_SYMBOL_GPL(da9055_regmap_config);
    256
    257static const struct resource da9055_onkey_resource =
    258	DEFINE_RES_IRQ_NAMED(DA9055_IRQ_NONKEY, "ONKEY");
    259
    260static const struct resource da9055_rtc_resource[] = {
    261	DEFINE_RES_IRQ_NAMED(DA9055_IRQ_ALARM, "ALM"),
    262	DEFINE_RES_IRQ_NAMED(DA9055_IRQ_TICK, "TICK"),
    263};
    264
    265static const struct resource da9055_hwmon_resource =
    266	DEFINE_RES_IRQ_NAMED(DA9055_IRQ_HWMON, "HWMON");
    267
    268static const struct resource da9055_ld05_6_resource =
    269	DEFINE_RES_IRQ_NAMED(DA9055_IRQ_REGULATOR, "REGULATOR");
    270
    271static const struct mfd_cell da9055_devs[] = {
    272	{
    273		.of_compatible = "dlg,da9055-gpio",
    274		.name = "da9055-gpio",
    275	},
    276	{
    277		.of_compatible = "dlg,da9055-regulator",
    278		.name = "da9055-regulator",
    279		.id = 1,
    280	},
    281	{
    282		.of_compatible = "dlg,da9055-regulator",
    283		.name = "da9055-regulator",
    284		.id = 2,
    285	},
    286	{
    287		.of_compatible = "dlg,da9055-regulator",
    288		.name = "da9055-regulator",
    289		.id = 3,
    290	},
    291	{
    292		.of_compatible = "dlg,da9055-regulator",
    293		.name = "da9055-regulator",
    294		.id = 4,
    295	},
    296	{
    297		.of_compatible = "dlg,da9055-regulator",
    298		.name = "da9055-regulator",
    299		.id = 5,
    300	},
    301	{
    302		.of_compatible = "dlg,da9055-regulator",
    303		.name = "da9055-regulator",
    304		.id = 6,
    305	},
    306	{
    307		.of_compatible = "dlg,da9055-regulator",
    308		.name = "da9055-regulator",
    309		.id = 7,
    310		.resources = &da9055_ld05_6_resource,
    311		.num_resources = 1,
    312	},
    313	{
    314		.of_compatible = "dlg,da9055-regulator",
    315		.name = "da9055-regulator",
    316		.resources = &da9055_ld05_6_resource,
    317		.num_resources = 1,
    318		.id = 8,
    319	},
    320	{
    321		.of_compatible = "dlg,da9055-onkey",
    322		.name = "da9055-onkey",
    323		.resources = &da9055_onkey_resource,
    324		.num_resources = 1,
    325	},
    326	{
    327		.of_compatible = "dlg,da9055-rtc",
    328		.name = "da9055-rtc",
    329		.resources = da9055_rtc_resource,
    330		.num_resources = ARRAY_SIZE(da9055_rtc_resource),
    331	},
    332	{
    333		.of_compatible = "dlg,da9055-hwmon",
    334		.name = "da9055-hwmon",
    335		.resources = &da9055_hwmon_resource,
    336		.num_resources = 1,
    337	},
    338	{
    339		.of_compatible = "dlg,da9055-watchdog",
    340		.name = "da9055-watchdog",
    341	},
    342};
    343
    344static const struct regmap_irq_chip da9055_regmap_irq_chip = {
    345	.name = "da9055_irq",
    346	.status_base = DA9055_REG_EVENT_A,
    347	.mask_base = DA9055_REG_IRQ_MASK_A,
    348	.ack_base = DA9055_REG_EVENT_A,
    349	.num_regs = 3,
    350	.irqs = da9055_irqs,
    351	.num_irqs = ARRAY_SIZE(da9055_irqs),
    352};
    353
    354int da9055_device_init(struct da9055 *da9055)
    355{
    356	struct da9055_pdata *pdata = dev_get_platdata(da9055->dev);
    357	int ret;
    358	uint8_t clear_events[3] = {0xFF, 0xFF, 0xFF};
    359
    360	if (pdata && pdata->init != NULL)
    361		pdata->init(da9055);
    362
    363	if (!pdata || !pdata->irq_base)
    364		da9055->irq_base = -1;
    365	else
    366		da9055->irq_base = pdata->irq_base;
    367
    368	ret = da9055_group_write(da9055, DA9055_REG_EVENT_A, 3, clear_events);
    369	if (ret < 0)
    370		return ret;
    371
    372	ret = regmap_add_irq_chip(da9055->regmap, da9055->chip_irq,
    373				  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
    374				  da9055->irq_base, &da9055_regmap_irq_chip,
    375				  &da9055->irq_data);
    376	if (ret < 0)
    377		return ret;
    378
    379	da9055->irq_base = regmap_irq_chip_get_base(da9055->irq_data);
    380
    381	ret = mfd_add_devices(da9055->dev, -1,
    382			      da9055_devs, ARRAY_SIZE(da9055_devs),
    383			      NULL, da9055->irq_base, NULL);
    384	if (ret)
    385		goto err;
    386
    387	return 0;
    388
    389err:
    390	mfd_remove_devices(da9055->dev);
    391	return ret;
    392}
    393
    394void da9055_device_exit(struct da9055 *da9055)
    395{
    396	regmap_del_irq_chip(da9055->chip_irq, da9055->irq_data);
    397	mfd_remove_devices(da9055->dev);
    398}
    399
    400MODULE_DESCRIPTION("Core support for the DA9055 PMIC");
    401MODULE_LICENSE("GPL");
    402MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");