Squashed backup commit (no shallow-clone history issues) of xiaomi-mt6833-dev/kernel_xiaomi_mt6833 (lineage-23.2 branch, upstream commit 9eece662e) plus all fixes applied to get everpal_defconfig building clean against a modern (GCC 15.2.0) toolchain -- see the previous commit message on the lineage-23.2 branch (also in this repo history is not available here since this is a squashed snapshot; full incremental history lives in the local DL380 checkout and the upstream GitHub remote). Upstream: https://github.com/xiaomi-mt6833-dev/kernel_xiaomi_mt6833 (lineage-23.2)
176 lines
4.5 KiB
C
176 lines
4.5 KiB
C
/*
|
|
* Copyright (C) 2017 MediaTek Inc.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/init.h>
|
|
#include <linux/version.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/mfd/core.h>
|
|
#include <linux/of_irq.h>
|
|
|
|
#include "inc/mt6370_pmu.h"
|
|
|
|
static struct mfd_cell mt6370_pmu_subdev_cells[MT6370_PMU_DEV_MAX] = {
|
|
{
|
|
.name = "mt6370_pmu_core",
|
|
.of_compatible = "mediatek,mt6370_pmu_core",
|
|
.pm_runtime_no_callbacks = true,
|
|
},
|
|
{
|
|
.name = "mt6370_pmu_charger",
|
|
.of_compatible = "mediatek,mt6370_pmu_charger",
|
|
.pm_runtime_no_callbacks = true,
|
|
},
|
|
{
|
|
.name = "mt6370_pmu_fled",
|
|
.of_compatible = "mediatek,mt6370_pmu_fled1",
|
|
.pm_runtime_no_callbacks = true,
|
|
.id = 1,
|
|
},
|
|
{
|
|
.name = "mt6370_pmu_fled",
|
|
.of_compatible = "mediatek,mt6370_pmu_fled2",
|
|
.pm_runtime_no_callbacks = true,
|
|
.id = 2,
|
|
},
|
|
{
|
|
.name = "mt6370_pmu_ldo",
|
|
.of_compatible = "mediatek,mt6370_pmu_ldo",
|
|
.pm_runtime_no_callbacks = true,
|
|
},
|
|
{
|
|
.name = "mt6370_pmu_rgbled",
|
|
.of_compatible = "mediatek,mt6370_pmu_rgbled",
|
|
.pm_runtime_no_callbacks = true,
|
|
},
|
|
{
|
|
.name = "mt6370_pmu_bled",
|
|
.of_compatible = "mediatek,mt6370_pmu_bled",
|
|
.pm_runtime_no_callbacks = true,
|
|
},
|
|
{
|
|
.name = "mt6370_pmu_dsv",
|
|
.of_compatible = "mediatek,mt6370_pmu_dsv",
|
|
.pm_runtime_no_callbacks = true,
|
|
},
|
|
};
|
|
|
|
static inline int mt6370_pmu_init_of_subdevs(struct mt6370_pmu_chip *chip)
|
|
{
|
|
struct resource *res;
|
|
struct mfd_cell *cell;
|
|
struct device_node *np;
|
|
int i, j, irq_cnt, ret = 0;
|
|
|
|
for (i = 0; i < MT6370_PMU_DEV_MAX; i++) {
|
|
cell = mt6370_pmu_subdev_cells + i;
|
|
np = NULL;
|
|
for_each_child_of_node(chip->dev->of_node, np) {
|
|
if (of_device_is_compatible(np, cell->of_compatible))
|
|
break;
|
|
}
|
|
if (!np)
|
|
continue;
|
|
irq_cnt = 0;
|
|
while (true) {
|
|
const char *name = NULL;
|
|
|
|
ret = of_property_read_string_index(np,
|
|
"interrupt-names",
|
|
irq_cnt, &name);
|
|
if (ret < 0)
|
|
break;
|
|
irq_cnt++;
|
|
}
|
|
if (!irq_cnt)
|
|
continue;
|
|
res = devm_kzalloc(chip->dev,
|
|
sizeof(*res) * irq_cnt, GFP_KERNEL);
|
|
if (!res)
|
|
return -ENOMEM;
|
|
for (j = 0; j < irq_cnt; j++) {
|
|
const char *name = NULL;
|
|
|
|
of_property_read_string_index(np, "interrupt-names",
|
|
j, &name);
|
|
res[j].name = name;
|
|
ret = mt6370_pmu_get_virq_number(chip, name);
|
|
res[j].start = res[j].end = ret;
|
|
if (ret < 0)
|
|
continue;
|
|
res[j].flags = IORESOURCE_IRQ;
|
|
}
|
|
/* store to original platform data */
|
|
cell->num_resources = irq_cnt;
|
|
cell->resources = res;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static inline int mt6370_pmu_init_nonof_subdevs(struct mt6370_pmu_chip *chip)
|
|
{
|
|
struct mt6370_pmu_platform_data *pdata = dev_get_platdata(chip->dev);
|
|
struct mfd_cell *cell;
|
|
struct resource *res;
|
|
int i, j, ret = 0;
|
|
|
|
for (i = 0; i < MT6370_PMU_DEV_MAX; i++) {
|
|
cell = mt6370_pmu_subdev_cells + i;
|
|
res = devm_kzalloc(chip->dev,
|
|
pdata->num_irq_enable[i] * sizeof(*res),
|
|
GFP_KERNEL);
|
|
if (!res)
|
|
return -ENOMEM;
|
|
for (j = 0; j < pdata->num_irq_enable[i]; j++) {
|
|
ret = mt6370_pmu_get_virq_number(chip,
|
|
pdata->irq_enable[i][j]);
|
|
res[j].name = pdata->irq_enable[i][j];
|
|
res[j].start = res[j].end = ret;
|
|
}
|
|
cell->num_resources = pdata->num_irq_enable[i];
|
|
cell->resources = res;
|
|
cell->platform_data = pdata->platform_data[i];
|
|
cell->pdata_size = pdata->pdata_size[i];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static inline int mt6370_pmu_init_subdevs(struct mt6370_pmu_chip *chip)
|
|
{
|
|
return (chip->dev->of_node ? mt6370_pmu_init_of_subdevs(chip) :
|
|
mt6370_pmu_init_nonof_subdevs(chip));
|
|
}
|
|
|
|
int mt6370_pmu_subdevs_register(struct mt6370_pmu_chip *chip)
|
|
{
|
|
int ret = 0;
|
|
|
|
ret = mt6370_pmu_init_subdevs(chip);
|
|
if (ret < 0)
|
|
return ret;
|
|
#if 1 /*(LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) */
|
|
return mfd_add_devices(chip->dev, -1, mt6370_pmu_subdev_cells,
|
|
MT6370_PMU_DEV_MAX, NULL, 0, NULL);
|
|
#else
|
|
return mfd_add_devices(chip->dev, -1, mt6370_pmu_subdev_cells,
|
|
MT6370_PMU_DEV_MAX, NULL, 0);
|
|
#endif /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) */
|
|
}
|
|
EXPORT_SYMBOL(mt6370_pmu_subdevs_register);
|
|
|
|
void mt6370_pmu_subdevs_unregister(struct mt6370_pmu_chip *chip)
|
|
{
|
|
mfd_remove_devices(chip->dev);
|
|
}
|
|
EXPORT_SYMBOL(mt6370_pmu_subdevs_unregister);
|