brintos

brintos / linux-shallow public Read only

0
0
Text · 5.0 KiB · 970d86f Raw
202 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * linux/drivers/regulator/aat2870-regulator.c4 *5 * Copyright (c) 2011, NVIDIA Corporation.6 * Author: Jin Park <jinyoungp@nvidia.com>7 */8 9#include <linux/kernel.h>10#include <linux/init.h>11#include <linux/err.h>12#include <linux/module.h>13#include <linux/slab.h>14#include <linux/platform_device.h>15#include <linux/regulator/driver.h>16#include <linux/regulator/machine.h>17#include <linux/mfd/aat2870.h>18 19struct aat2870_regulator {20	struct aat2870_data *aat2870;21	struct regulator_desc desc;22 23	u8 enable_addr;24	u8 enable_shift;25	u8 enable_mask;26 27	u8 voltage_addr;28	u8 voltage_shift;29	u8 voltage_mask;30};31 32static int aat2870_ldo_set_voltage_sel(struct regulator_dev *rdev,33				       unsigned selector)34{35	struct aat2870_regulator *ri = rdev_get_drvdata(rdev);36	struct aat2870_data *aat2870 = ri->aat2870;37 38	return aat2870->update(aat2870, ri->voltage_addr, ri->voltage_mask,39			       selector << ri->voltage_shift);40}41 42static int aat2870_ldo_get_voltage_sel(struct regulator_dev *rdev)43{44	struct aat2870_regulator *ri = rdev_get_drvdata(rdev);45	struct aat2870_data *aat2870 = ri->aat2870;46	u8 val;47	int ret;48 49	ret = aat2870->read(aat2870, ri->voltage_addr, &val);50	if (ret)51		return ret;52 53	return (val & ri->voltage_mask) >> ri->voltage_shift;54}55 56static int aat2870_ldo_enable(struct regulator_dev *rdev)57{58	struct aat2870_regulator *ri = rdev_get_drvdata(rdev);59	struct aat2870_data *aat2870 = ri->aat2870;60 61	return aat2870->update(aat2870, ri->enable_addr, ri->enable_mask,62			       ri->enable_mask);63}64 65static int aat2870_ldo_disable(struct regulator_dev *rdev)66{67	struct aat2870_regulator *ri = rdev_get_drvdata(rdev);68	struct aat2870_data *aat2870 = ri->aat2870;69 70	return aat2870->update(aat2870, ri->enable_addr, ri->enable_mask, 0);71}72 73static int aat2870_ldo_is_enabled(struct regulator_dev *rdev)74{75	struct aat2870_regulator *ri = rdev_get_drvdata(rdev);76	struct aat2870_data *aat2870 = ri->aat2870;77	u8 val;78	int ret;79 80	ret = aat2870->read(aat2870, ri->enable_addr, &val);81	if (ret)82		return ret;83 84	return val & ri->enable_mask ? 1 : 0;85}86 87static const struct regulator_ops aat2870_ldo_ops = {88	.list_voltage = regulator_list_voltage_table,89	.map_voltage = regulator_map_voltage_ascend,90	.set_voltage_sel = aat2870_ldo_set_voltage_sel,91	.get_voltage_sel = aat2870_ldo_get_voltage_sel,92	.enable = aat2870_ldo_enable,93	.disable = aat2870_ldo_disable,94	.is_enabled = aat2870_ldo_is_enabled,95};96 97static const unsigned int aat2870_ldo_voltages[] = {98	1200000, 1300000, 1500000, 1600000,99	1800000, 2000000, 2200000, 2500000,100	2600000, 2700000, 2800000, 2900000,101	3000000, 3100000, 3200000, 3300000,102};103 104#define AAT2870_LDO(ids)				\105	{						\106		.desc = {				\107			.name = #ids,			\108			.id = AAT2870_ID_##ids,		\109			.n_voltages = ARRAY_SIZE(aat2870_ldo_voltages),	\110			.volt_table = aat2870_ldo_voltages, \111			.ops = &aat2870_ldo_ops,	\112			.type = REGULATOR_VOLTAGE,	\113			.owner = THIS_MODULE,		\114		},					\115	}116 117static struct aat2870_regulator aat2870_regulators[] = {118	AAT2870_LDO(LDOA),119	AAT2870_LDO(LDOB),120	AAT2870_LDO(LDOC),121	AAT2870_LDO(LDOD),122};123 124static struct aat2870_regulator *aat2870_get_regulator(int id)125{126	struct aat2870_regulator *ri = NULL;127	int i;128 129	for (i = 0; i < ARRAY_SIZE(aat2870_regulators); i++) {130		ri = &aat2870_regulators[i];131		if (ri->desc.id == id)132			break;133	}134 135	if (i == ARRAY_SIZE(aat2870_regulators))136		return NULL;137 138	ri->enable_addr = AAT2870_LDO_EN;139	ri->enable_shift = id - AAT2870_ID_LDOA;140	ri->enable_mask = 0x1 << ri->enable_shift;141 142	ri->voltage_addr = (id - AAT2870_ID_LDOA) / 2 ?143			   AAT2870_LDO_CD : AAT2870_LDO_AB;144	ri->voltage_shift = (id - AAT2870_ID_LDOA) % 2 ? 0 : 4;145	ri->voltage_mask = 0xF << ri->voltage_shift;146 147	return ri;148}149 150static int aat2870_regulator_probe(struct platform_device *pdev)151{152	struct aat2870_regulator *ri;153	struct regulator_config config = { };154	struct regulator_dev *rdev;155 156	ri = aat2870_get_regulator(pdev->id);157	if (!ri) {158		dev_err(&pdev->dev, "Invalid device ID, %d\n", pdev->id);159		return -EINVAL;160	}161	ri->aat2870 = dev_get_drvdata(pdev->dev.parent);162 163	config.dev = &pdev->dev;164	config.driver_data = ri;165	config.init_data = dev_get_platdata(&pdev->dev);166 167	rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);168	if (IS_ERR(rdev)) {169		dev_err(&pdev->dev, "Failed to register regulator %s\n",170			ri->desc.name);171		return PTR_ERR(rdev);172	}173	platform_set_drvdata(pdev, rdev);174 175	return 0;176}177 178static struct platform_driver aat2870_regulator_driver = {179	.driver = {180		.name	= "aat2870-regulator",181		.probe_type = PROBE_PREFER_ASYNCHRONOUS,182	},183	.probe	= aat2870_regulator_probe,184};185 186static int __init aat2870_regulator_init(void)187{188	return platform_driver_register(&aat2870_regulator_driver);189}190subsys_initcall(aat2870_regulator_init);191 192static void __exit aat2870_regulator_exit(void)193{194	platform_driver_unregister(&aat2870_regulator_driver);195}196module_exit(aat2870_regulator_exit);197 198MODULE_DESCRIPTION("AnalogicTech AAT2870 Regulator");199MODULE_LICENSE("GPL");200MODULE_AUTHOR("Jin Park <jinyoungp@nvidia.com>");201MODULE_ALIAS("platform:aat2870-regulator");202