Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mfd: Add support for Merrifield Basin Cove PMIC

Add an MFD driver for Intel Merrifield Basin Cove PMIC.

Firmware on the platforms which are using Basin Cove PMIC is "smarter"
than on the rest supported by vanilla kernel. It handles first level
of interrupt itself, while others do it on OS level.

The driver is done in the same way as the rest of Intel PMIC MFD drivers
in the kernel to support the initial design. The design allows to use
one driver among few PMICs without knowing implementation details of
the each hardware version or generation.

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>

authored by

Andy Shevchenko and committed by
Lee Jones
b9a801df b65dc4f6

+250
+11
drivers/mfd/Kconfig
··· 597 597 Select this option for supporting Dollar Cove (TI version) PMIC 598 598 device that is found on some Intel Cherry Trail systems. 599 599 600 + config INTEL_SOC_PMIC_MRFLD 601 + tristate "Support for Intel Merrifield Basin Cove PMIC" 602 + depends on GPIOLIB 603 + depends on ACPI 604 + depends on INTEL_SCU_IPC 605 + select MFD_CORE 606 + select REGMAP_IRQ 607 + help 608 + Select this option for supporting Basin Cove PMIC device 609 + that is found on Intel Merrifield systems. 610 + 600 611 config MFD_INTEL_LPSS 601 612 tristate 602 613 select COMMON_CLK
+1
drivers/mfd/Makefile
··· 242 242 obj-$(CONFIG_INTEL_SOC_PMIC_CHTDC_TI) += intel_soc_pmic_chtdc_ti.o 243 243 mt6397-objs := mt6397-core.o mt6397-irq.o 244 244 obj-$(CONFIG_MFD_MT6397) += mt6397.o 245 + obj-$(CONFIG_INTEL_SOC_PMIC_MRFLD) += intel_soc_pmic_mrfld.o 245 246 246 247 obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o 247 248 obj-$(CONFIG_MFD_ALTERA_SYSMGR) += altera-sysmgr.o
+157
drivers/mfd/intel_soc_pmic_mrfld.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Device access for Basin Cove PMIC 4 + * 5 + * Copyright (c) 2019, Intel Corporation. 6 + * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> 7 + */ 8 + 9 + #include <linux/acpi.h> 10 + #include <linux/interrupt.h> 11 + #include <linux/mfd/core.h> 12 + #include <linux/mfd/intel_soc_pmic.h> 13 + #include <linux/mfd/intel_soc_pmic_mrfld.h> 14 + #include <linux/module.h> 15 + #include <linux/platform_device.h> 16 + #include <linux/regmap.h> 17 + 18 + #include <asm/intel_scu_ipc.h> 19 + 20 + /* 21 + * Level 2 IRQs 22 + * 23 + * Firmware on the systems with Basin Cove PMIC services Level 1 IRQs 24 + * without an assistance. Thus, each of the Level 1 IRQ is represented 25 + * as a separate RTE in IOAPIC. 26 + */ 27 + static struct resource irq_level2_resources[] = { 28 + DEFINE_RES_IRQ(0), /* power button */ 29 + DEFINE_RES_IRQ(0), /* TMU */ 30 + DEFINE_RES_IRQ(0), /* thermal */ 31 + DEFINE_RES_IRQ(0), /* BCU */ 32 + DEFINE_RES_IRQ(0), /* ADC */ 33 + DEFINE_RES_IRQ(0), /* charger */ 34 + DEFINE_RES_IRQ(0), /* GPIO */ 35 + }; 36 + 37 + static const struct mfd_cell bcove_dev[] = { 38 + { 39 + .name = "mrfld_bcove_pwrbtn", 40 + .num_resources = 1, 41 + .resources = &irq_level2_resources[0], 42 + }, { 43 + .name = "mrfld_bcove_tmu", 44 + .num_resources = 1, 45 + .resources = &irq_level2_resources[1], 46 + }, { 47 + .name = "mrfld_bcove_thermal", 48 + .num_resources = 1, 49 + .resources = &irq_level2_resources[2], 50 + }, { 51 + .name = "mrfld_bcove_bcu", 52 + .num_resources = 1, 53 + .resources = &irq_level2_resources[3], 54 + }, { 55 + .name = "mrfld_bcove_adc", 56 + .num_resources = 1, 57 + .resources = &irq_level2_resources[4], 58 + }, { 59 + .name = "mrfld_bcove_charger", 60 + .num_resources = 1, 61 + .resources = &irq_level2_resources[5], 62 + }, { 63 + .name = "mrfld_bcove_pwrsrc", 64 + .num_resources = 1, 65 + .resources = &irq_level2_resources[5], 66 + }, { 67 + .name = "mrfld_bcove_gpio", 68 + .num_resources = 1, 69 + .resources = &irq_level2_resources[6], 70 + }, 71 + { .name = "mrfld_bcove_region", }, 72 + }; 73 + 74 + static int bcove_ipc_byte_reg_read(void *context, unsigned int reg, 75 + unsigned int *val) 76 + { 77 + u8 ipc_out; 78 + int ret; 79 + 80 + ret = intel_scu_ipc_ioread8(reg, &ipc_out); 81 + if (ret) 82 + return ret; 83 + 84 + *val = ipc_out; 85 + return 0; 86 + } 87 + 88 + static int bcove_ipc_byte_reg_write(void *context, unsigned int reg, 89 + unsigned int val) 90 + { 91 + u8 ipc_in = val; 92 + int ret; 93 + 94 + ret = intel_scu_ipc_iowrite8(reg, ipc_in); 95 + if (ret) 96 + return ret; 97 + 98 + return 0; 99 + } 100 + 101 + static const struct regmap_config bcove_regmap_config = { 102 + .reg_bits = 16, 103 + .val_bits = 8, 104 + .max_register = 0xff, 105 + .reg_write = bcove_ipc_byte_reg_write, 106 + .reg_read = bcove_ipc_byte_reg_read, 107 + }; 108 + 109 + static int bcove_probe(struct platform_device *pdev) 110 + { 111 + struct device *dev = &pdev->dev; 112 + struct intel_soc_pmic *pmic; 113 + unsigned int i; 114 + int ret; 115 + 116 + pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL); 117 + if (!pmic) 118 + return -ENOMEM; 119 + 120 + platform_set_drvdata(pdev, pmic); 121 + pmic->dev = &pdev->dev; 122 + 123 + pmic->regmap = devm_regmap_init(dev, NULL, pmic, &bcove_regmap_config); 124 + if (IS_ERR(pmic->regmap)) 125 + return PTR_ERR(pmic->regmap); 126 + 127 + for (i = 0; i < ARRAY_SIZE(irq_level2_resources); i++) { 128 + ret = platform_get_irq(pdev, i); 129 + if (ret < 0) 130 + return ret; 131 + 132 + irq_level2_resources[i].start = ret; 133 + irq_level2_resources[i].end = ret; 134 + } 135 + 136 + return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, 137 + bcove_dev, ARRAY_SIZE(bcove_dev), 138 + NULL, 0, NULL); 139 + } 140 + 141 + static const struct acpi_device_id bcove_acpi_ids[] = { 142 + { "INTC100E" }, 143 + {} 144 + }; 145 + MODULE_DEVICE_TABLE(acpi, bcove_acpi_ids); 146 + 147 + static struct platform_driver bcove_driver = { 148 + .driver = { 149 + .name = "intel_soc_pmic_mrfld", 150 + .acpi_match_table = bcove_acpi_ids, 151 + }, 152 + .probe = bcove_probe, 153 + }; 154 + module_platform_driver(bcove_driver); 155 + 156 + MODULE_DESCRIPTION("IPC driver for Intel SoC Basin Cove PMIC"); 157 + MODULE_LICENSE("GPL v2");
+81
include/linux/mfd/intel_soc_pmic_mrfld.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Header file for Intel Merrifield Basin Cove PMIC 4 + * 5 + * Copyright (C) 2019 Intel Corporation. All rights reserved. 6 + */ 7 + 8 + #ifndef __INTEL_SOC_PMIC_MRFLD_H__ 9 + #define __INTEL_SOC_PMIC_MRFLD_H__ 10 + 11 + #include <linux/bits.h> 12 + 13 + #define BCOVE_ID 0x00 14 + 15 + #define BCOVE_ID_MINREV0 GENMASK(2, 0) 16 + #define BCOVE_ID_MAJREV0 GENMASK(5, 3) 17 + #define BCOVE_ID_VENDID0 GENMASK(7, 6) 18 + 19 + #define BCOVE_MINOR(x) (unsigned int)(((x) & BCOVE_ID_MINREV0) >> 0) 20 + #define BCOVE_MAJOR(x) (unsigned int)(((x) & BCOVE_ID_MAJREV0) >> 3) 21 + #define BCOVE_VENDOR(x) (unsigned int)(((x) & BCOVE_ID_VENDID0) >> 6) 22 + 23 + #define BCOVE_IRQLVL1 0x01 24 + 25 + #define BCOVE_PBIRQ 0x02 26 + #define BCOVE_TMUIRQ 0x03 27 + #define BCOVE_THRMIRQ 0x04 28 + #define BCOVE_BCUIRQ 0x05 29 + #define BCOVE_ADCIRQ 0x06 30 + #define BCOVE_CHGRIRQ0 0x07 31 + #define BCOVE_CHGRIRQ1 0x08 32 + #define BCOVE_GPIOIRQ 0x09 33 + #define BCOVE_CRITIRQ 0x0B 34 + 35 + #define BCOVE_MIRQLVL1 0x0C 36 + 37 + #define BCOVE_MPBIRQ 0x0D 38 + #define BCOVE_MTMUIRQ 0x0E 39 + #define BCOVE_MTHRMIRQ 0x0F 40 + #define BCOVE_MBCUIRQ 0x10 41 + #define BCOVE_MADCIRQ 0x11 42 + #define BCOVE_MCHGRIRQ0 0x12 43 + #define BCOVE_MCHGRIRQ1 0x13 44 + #define BCOVE_MGPIOIRQ 0x14 45 + #define BCOVE_MCRITIRQ 0x16 46 + 47 + #define BCOVE_SCHGRIRQ0 0x4E 48 + #define BCOVE_SCHGRIRQ1 0x4F 49 + 50 + /* Level 1 IRQs */ 51 + #define BCOVE_LVL1_PWRBTN BIT(0) /* power button */ 52 + #define BCOVE_LVL1_TMU BIT(1) /* time management unit */ 53 + #define BCOVE_LVL1_THRM BIT(2) /* thermal */ 54 + #define BCOVE_LVL1_BCU BIT(3) /* burst control unit */ 55 + #define BCOVE_LVL1_ADC BIT(4) /* ADC */ 56 + #define BCOVE_LVL1_CHGR BIT(5) /* charger */ 57 + #define BCOVE_LVL1_GPIO BIT(6) /* GPIO */ 58 + #define BCOVE_LVL1_CRIT BIT(7) /* critical event */ 59 + 60 + /* Level 2 IRQs: power button */ 61 + #define BCOVE_PBIRQ_PBTN BIT(0) 62 + #define BCOVE_PBIRQ_UBTN BIT(1) 63 + 64 + /* Level 2 IRQs: ADC */ 65 + #define BCOVE_ADCIRQ_BATTEMP BIT(2) 66 + #define BCOVE_ADCIRQ_SYSTEMP BIT(3) 67 + #define BCOVE_ADCIRQ_BATTID BIT(4) 68 + #define BCOVE_ADCIRQ_VIBATT BIT(5) 69 + #define BCOVE_ADCIRQ_CCTICK BIT(7) 70 + 71 + /* Level 2 IRQs: charger */ 72 + #define BCOVE_CHGRIRQ_BAT0ALRT BIT(4) 73 + #define BCOVE_CHGRIRQ_BAT1ALRT BIT(5) 74 + #define BCOVE_CHGRIRQ_BATCRIT BIT(6) 75 + 76 + #define BCOVE_CHGRIRQ_VBUSDET BIT(0) 77 + #define BCOVE_CHGRIRQ_DCDET BIT(1) 78 + #define BCOVE_CHGRIRQ_BATTDET BIT(2) 79 + #define BCOVE_CHGRIRQ_USBIDDET BIT(3) 80 + 81 + #endif /* __INTEL_SOC_PMIC_MRFLD_H__ */