0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/acpi.h>
0010 #include <linux/interrupt.h>
0011 #include <linux/mfd/core.h>
0012 #include <linux/mfd/intel_soc_pmic.h>
0013 #include <linux/mfd/intel_soc_pmic_mrfld.h>
0014 #include <linux/module.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/regmap.h>
0017
0018 #include <asm/intel_scu_ipc.h>
0019
0020
0021
0022
0023
0024
0025
0026
0027 static struct resource irq_level2_resources[] = {
0028 DEFINE_RES_IRQ(0),
0029 DEFINE_RES_IRQ(0),
0030 DEFINE_RES_IRQ(0),
0031 DEFINE_RES_IRQ(0),
0032 DEFINE_RES_IRQ(0),
0033 DEFINE_RES_IRQ(0),
0034 DEFINE_RES_IRQ(0),
0035 };
0036
0037 static const struct mfd_cell bcove_dev[] = {
0038 {
0039 .name = "mrfld_bcove_pwrbtn",
0040 .num_resources = 1,
0041 .resources = &irq_level2_resources[0],
0042 }, {
0043 .name = "mrfld_bcove_tmu",
0044 .num_resources = 1,
0045 .resources = &irq_level2_resources[1],
0046 }, {
0047 .name = "mrfld_bcove_thermal",
0048 .num_resources = 1,
0049 .resources = &irq_level2_resources[2],
0050 }, {
0051 .name = "mrfld_bcove_bcu",
0052 .num_resources = 1,
0053 .resources = &irq_level2_resources[3],
0054 }, {
0055 .name = "mrfld_bcove_adc",
0056 .num_resources = 1,
0057 .resources = &irq_level2_resources[4],
0058 }, {
0059 .name = "mrfld_bcove_charger",
0060 .num_resources = 1,
0061 .resources = &irq_level2_resources[5],
0062 }, {
0063 .name = "mrfld_bcove_pwrsrc",
0064 .num_resources = 1,
0065 .resources = &irq_level2_resources[5],
0066 }, {
0067 .name = "mrfld_bcove_gpio",
0068 .num_resources = 1,
0069 .resources = &irq_level2_resources[6],
0070 },
0071 { .name = "mrfld_bcove_region", },
0072 };
0073
0074 static int bcove_ipc_byte_reg_read(void *context, unsigned int reg,
0075 unsigned int *val)
0076 {
0077 struct intel_soc_pmic *pmic = context;
0078 u8 ipc_out;
0079 int ret;
0080
0081 ret = intel_scu_ipc_dev_ioread8(pmic->scu, reg, &ipc_out);
0082 if (ret)
0083 return ret;
0084
0085 *val = ipc_out;
0086 return 0;
0087 }
0088
0089 static int bcove_ipc_byte_reg_write(void *context, unsigned int reg,
0090 unsigned int val)
0091 {
0092 struct intel_soc_pmic *pmic = context;
0093 u8 ipc_in = val;
0094
0095 return intel_scu_ipc_dev_iowrite8(pmic->scu, reg, ipc_in);
0096 }
0097
0098 static const struct regmap_config bcove_regmap_config = {
0099 .reg_bits = 16,
0100 .val_bits = 8,
0101 .max_register = 0xff,
0102 .reg_write = bcove_ipc_byte_reg_write,
0103 .reg_read = bcove_ipc_byte_reg_read,
0104 };
0105
0106 static int bcove_probe(struct platform_device *pdev)
0107 {
0108 struct device *dev = &pdev->dev;
0109 struct intel_soc_pmic *pmic;
0110 unsigned int i;
0111 int ret;
0112
0113 pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
0114 if (!pmic)
0115 return -ENOMEM;
0116
0117 pmic->scu = devm_intel_scu_ipc_dev_get(dev);
0118 if (!pmic->scu)
0119 return -ENOMEM;
0120
0121 platform_set_drvdata(pdev, pmic);
0122 pmic->dev = &pdev->dev;
0123
0124 pmic->regmap = devm_regmap_init(dev, NULL, pmic, &bcove_regmap_config);
0125 if (IS_ERR(pmic->regmap))
0126 return PTR_ERR(pmic->regmap);
0127
0128 for (i = 0; i < ARRAY_SIZE(irq_level2_resources); i++) {
0129 ret = platform_get_irq(pdev, i);
0130 if (ret < 0)
0131 return ret;
0132
0133 irq_level2_resources[i].start = ret;
0134 irq_level2_resources[i].end = ret;
0135 }
0136
0137 return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
0138 bcove_dev, ARRAY_SIZE(bcove_dev),
0139 NULL, 0, NULL);
0140 }
0141
0142 static const struct acpi_device_id bcove_acpi_ids[] = {
0143 { "INTC100E" },
0144 {}
0145 };
0146 MODULE_DEVICE_TABLE(acpi, bcove_acpi_ids);
0147
0148 static struct platform_driver bcove_driver = {
0149 .driver = {
0150 .name = "intel_soc_pmic_mrfld",
0151 .acpi_match_table = bcove_acpi_ids,
0152 },
0153 .probe = bcove_probe,
0154 };
0155 module_platform_driver(bcove_driver);
0156
0157 MODULE_DESCRIPTION("IPC driver for Intel SoC Basin Cove PMIC");
0158 MODULE_LICENSE("GPL v2");