// SPDX-License-Identifier: GPL-2.0 /* * Device access for Basin Cove PMIC * * Copyright (c) 2019, Intel Corporation. * Author: Andy Shevchenko */ #include #include #include #include #include #include #include #include #include /* * Level 2 IRQs * * Firmware on the systems with Basin Cove PMIC services Level 1 IRQs * without an assistance. Thus, each of the Level 1 IRQ is represented * as a separate RTE in IOAPIC. */ static struct resource irq_level2_resources[] = { DEFINE_RES_IRQ(0), /* power button */ DEFINE_RES_IRQ(0), /* TMU */ DEFINE_RES_IRQ(0), /* thermal */ DEFINE_RES_IRQ(0), /* BCU */ DEFINE_RES_IRQ(0), /* ADC */ DEFINE_RES_IRQ(0), /* charger */ DEFINE_RES_IRQ(0), /* GPIO */ }; static const struct mfd_cell bcove_dev[] = { { .name = "mrfld_bcove_pwrbtn", .num_resources = 1, .resources = &irq_level2_resources[0], }, { .name = "mrfld_bcove_tmu", .num_resources = 1, .resources = &irq_level2_resources[1], }, { .name = "mrfld_bcove_thermal", .num_resources = 1, .resources = &irq_level2_resources[2], }, { .name = "mrfld_bcove_bcu", .num_resources = 1, .resources = &irq_level2_resources[3], }, { .name = "mrfld_bcove_adc", .num_resources = 1, .resources = &irq_level2_resources[4], }, { .name = "mrfld_bcove_charger", .num_resources = 1, .resources = &irq_level2_resources[5], }, { .name = "mrfld_bcove_pwrsrc", .num_resources = 1, .resources = &irq_level2_resources[5], }, { .name = "mrfld_bcove_gpio", .num_resources = 1, .resources = &irq_level2_resources[6], }, { .name = "mrfld_bcove_region", }, }; static int bcove_ipc_byte_reg_read(void *context, unsigned int reg, unsigned int *val) { struct intel_soc_pmic *pmic = context; u8 ipc_out; int ret; ret = intel_scu_ipc_dev_ioread8(pmic->scu, reg, &ipc_out); if (ret) return ret; *val = ipc_out; return 0; } static int bcove_ipc_byte_reg_write(void *context, unsigned int reg, unsigned int val) { struct intel_soc_pmic *pmic = context; u8 ipc_in = val; return intel_scu_ipc_dev_iowrite8(pmic->scu, reg, ipc_in); } static const struct regmap_config bcove_regmap_config = { .reg_bits = 16, .val_bits = 8, .max_register = 0xff, .reg_write = bcove_ipc_byte_reg_write, .reg_read = bcove_ipc_byte_reg_read, }; static int bcove_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct intel_soc_pmic *pmic; unsigned int i; int ret; pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL); if (!pmic) return -ENOMEM; pmic->scu = devm_intel_scu_ipc_dev_get(dev); if (!pmic->scu) return -ENOMEM; platform_set_drvdata(pdev, pmic); pmic->dev = &pdev->dev; pmic->regmap = devm_regmap_init(dev, NULL, pmic, &bcove_regmap_config); if (IS_ERR(pmic->regmap)) return PTR_ERR(pmic->regmap); for (i = 0; i < ARRAY_SIZE(irq_level2_resources); i++) { ret = platform_get_irq(pdev, i); if (ret < 0) return ret; irq_level2_resources[i].start = ret; irq_level2_resources[i].end = ret; } return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE, bcove_dev, ARRAY_SIZE(bcove_dev), NULL, 0, NULL); } static const struct acpi_device_id bcove_acpi_ids[] = { { "INTC100E" }, {} }; MODULE_DEVICE_TABLE(acpi, bcove_acpi_ids); static struct platform_driver bcove_driver = { .driver = { .name = "intel_soc_pmic_mrfld", .acpi_match_table = bcove_acpi_ids, }, .probe = bcove_probe, }; module_platform_driver(bcove_driver); MODULE_DESCRIPTION("IPC driver for Intel SoC Basin Cove PMIC"); MODULE_LICENSE("GPL v2");