brintos

brintos / linux-shallow public Read only

0
0
Text · 26.0 KiB · d25cd81 Raw
1008 lines · c
1// SPDX-License-Identifier: GPL-2.0+2//3// Copyright (c) 2011 Samsung Electronics Co., Ltd4//              http://www.samsung.com5 6#include <linux/cleanup.h>7#include <linux/err.h>8#include <linux/of_gpio.h>9#include <linux/gpio/consumer.h>10#include <linux/module.h>11#include <linux/platform_device.h>12#include <linux/regulator/driver.h>13#include <linux/regulator/machine.h>14#include <linux/mfd/samsung/core.h>15#include <linux/mfd/samsung/s5m8767.h>16#include <linux/regulator/of_regulator.h>17#include <linux/regmap.h>18 19#define S5M8767_OPMODE_NORMAL_MODE 0x120 21struct s5m8767_info {22	struct device *dev;23	struct sec_pmic_dev *iodev;24	int num_regulators;25	struct sec_opmode_data *opmode;26 27	int ramp_delay;28	bool buck2_ramp;29	bool buck3_ramp;30	bool buck4_ramp;31 32	bool buck2_gpiodvs;33	bool buck3_gpiodvs;34	bool buck4_gpiodvs;35	u8 buck2_vol[8];36	u8 buck3_vol[8];37	u8 buck4_vol[8];38	int buck_gpios[3];39	int buck_ds[3];40	int buck_gpioindex;41};42 43struct sec_voltage_desc {44	int max;45	int min;46	int step;47};48 49static const struct sec_voltage_desc buck_voltage_val1 = {50	.max = 2225000,51	.min =  650000,52	.step =   6250,53};54 55static const struct sec_voltage_desc buck_voltage_val2 = {56	.max = 1600000,57	.min =  600000,58	.step =   6250,59};60 61static const struct sec_voltage_desc buck_voltage_val3 = {62	.max = 3000000,63	.min =  750000,64	.step =  12500,65};66 67static const struct sec_voltage_desc ldo_voltage_val1 = {68	.max = 3950000,69	.min =  800000,70	.step =  50000,71};72 73static const struct sec_voltage_desc ldo_voltage_val2 = {74	.max = 2375000,75	.min =  800000,76	.step =  25000,77};78 79static const struct sec_voltage_desc *reg_voltage_map[] = {80	[S5M8767_LDO1] = &ldo_voltage_val2,81	[S5M8767_LDO2] = &ldo_voltage_val2,82	[S5M8767_LDO3] = &ldo_voltage_val1,83	[S5M8767_LDO4] = &ldo_voltage_val1,84	[S5M8767_LDO5] = &ldo_voltage_val1,85	[S5M8767_LDO6] = &ldo_voltage_val2,86	[S5M8767_LDO7] = &ldo_voltage_val2,87	[S5M8767_LDO8] = &ldo_voltage_val2,88	[S5M8767_LDO9] = &ldo_voltage_val1,89	[S5M8767_LDO10] = &ldo_voltage_val1,90	[S5M8767_LDO11] = &ldo_voltage_val1,91	[S5M8767_LDO12] = &ldo_voltage_val1,92	[S5M8767_LDO13] = &ldo_voltage_val1,93	[S5M8767_LDO14] = &ldo_voltage_val1,94	[S5M8767_LDO15] = &ldo_voltage_val2,95	[S5M8767_LDO16] = &ldo_voltage_val1,96	[S5M8767_LDO17] = &ldo_voltage_val1,97	[S5M8767_LDO18] = &ldo_voltage_val1,98	[S5M8767_LDO19] = &ldo_voltage_val1,99	[S5M8767_LDO20] = &ldo_voltage_val1,100	[S5M8767_LDO21] = &ldo_voltage_val1,101	[S5M8767_LDO22] = &ldo_voltage_val1,102	[S5M8767_LDO23] = &ldo_voltage_val1,103	[S5M8767_LDO24] = &ldo_voltage_val1,104	[S5M8767_LDO25] = &ldo_voltage_val1,105	[S5M8767_LDO26] = &ldo_voltage_val1,106	[S5M8767_LDO27] = &ldo_voltage_val1,107	[S5M8767_LDO28] = &ldo_voltage_val1,108	[S5M8767_BUCK1] = &buck_voltage_val1,109	[S5M8767_BUCK2] = &buck_voltage_val2,110	[S5M8767_BUCK3] = &buck_voltage_val2,111	[S5M8767_BUCK4] = &buck_voltage_val2,112	[S5M8767_BUCK5] = &buck_voltage_val1,113	[S5M8767_BUCK6] = &buck_voltage_val1,114	[S5M8767_BUCK7] = &buck_voltage_val3,115	[S5M8767_BUCK8] = &buck_voltage_val3,116	[S5M8767_BUCK9] = &buck_voltage_val3,117};118 119static const unsigned int s5m8767_opmode_reg[][4] = {120	/* {OFF, ON, LOWPOWER, SUSPEND} */121	/* LDO1 ... LDO28 */122	{0x0, 0x3, 0x2, 0x1}, /* LDO1 */123	{0x0, 0x3, 0x2, 0x1},124	{0x0, 0x3, 0x2, 0x1},125	{0x0, 0x0, 0x0, 0x0},126	{0x0, 0x3, 0x2, 0x1}, /* LDO5 */127	{0x0, 0x3, 0x2, 0x1},128	{0x0, 0x3, 0x2, 0x1},129	{0x0, 0x3, 0x2, 0x1},130	{0x0, 0x3, 0x2, 0x1},131	{0x0, 0x3, 0x2, 0x1}, /* LDO10 */132	{0x0, 0x3, 0x2, 0x1},133	{0x0, 0x3, 0x2, 0x1},134	{0x0, 0x3, 0x2, 0x1},135	{0x0, 0x3, 0x2, 0x1},136	{0x0, 0x3, 0x2, 0x1}, /* LDO15 */137	{0x0, 0x3, 0x2, 0x1},138	{0x0, 0x3, 0x2, 0x1},139	{0x0, 0x0, 0x0, 0x0},140	{0x0, 0x3, 0x2, 0x1},141	{0x0, 0x3, 0x2, 0x1}, /* LDO20 */142	{0x0, 0x3, 0x2, 0x1},143	{0x0, 0x3, 0x2, 0x1},144	{0x0, 0x0, 0x0, 0x0},145	{0x0, 0x3, 0x2, 0x1},146	{0x0, 0x3, 0x2, 0x1}, /* LDO25 */147	{0x0, 0x3, 0x2, 0x1},148	{0x0, 0x3, 0x2, 0x1},149	{0x0, 0x3, 0x2, 0x1}, /* LDO28 */150 151	/* BUCK1 ... BUCK9 */152	{0x0, 0x3, 0x1, 0x1}, /* BUCK1 */153	{0x0, 0x3, 0x1, 0x1},154	{0x0, 0x3, 0x1, 0x1},155	{0x0, 0x3, 0x1, 0x1},156	{0x0, 0x3, 0x2, 0x1}, /* BUCK5 */157	{0x0, 0x3, 0x1, 0x1},158	{0x0, 0x3, 0x1, 0x1},159	{0x0, 0x3, 0x1, 0x1},160	{0x0, 0x3, 0x1, 0x1}, /* BUCK9 */161};162 163static int s5m8767_get_register(struct s5m8767_info *s5m8767, int reg_id,164				int *reg, int *enable_ctrl)165{166	int i;167	unsigned int mode;168 169	switch (reg_id) {170	case S5M8767_LDO1 ... S5M8767_LDO2:171		*reg = S5M8767_REG_LDO1CTRL + (reg_id - S5M8767_LDO1);172		break;173	case S5M8767_LDO3 ... S5M8767_LDO28:174		*reg = S5M8767_REG_LDO3CTRL + (reg_id - S5M8767_LDO3);175		break;176	case S5M8767_BUCK1:177		*reg = S5M8767_REG_BUCK1CTRL1;178		break;179	case S5M8767_BUCK2 ... S5M8767_BUCK4:180		*reg = S5M8767_REG_BUCK2CTRL + (reg_id - S5M8767_BUCK2) * 9;181		break;182	case S5M8767_BUCK5:183		*reg = S5M8767_REG_BUCK5CTRL1;184		break;185	case S5M8767_BUCK6 ... S5M8767_BUCK9:186		*reg = S5M8767_REG_BUCK6CTRL1 + (reg_id - S5M8767_BUCK6) * 2;187		break;188	default:189		return -EINVAL;190	}191 192	for (i = 0; i < s5m8767->num_regulators; i++) {193		if (s5m8767->opmode[i].id == reg_id) {194			mode = s5m8767->opmode[i].mode;195			break;196		}197	}198 199	if (i >= s5m8767->num_regulators)200		return -EINVAL;201 202	*enable_ctrl = s5m8767_opmode_reg[reg_id][mode] << S5M8767_ENCTRL_SHIFT;203 204	return 0;205}206 207static int s5m8767_get_vsel_reg(int reg_id, struct s5m8767_info *s5m8767)208{209	int reg;210 211	switch (reg_id) {212	case S5M8767_LDO1 ... S5M8767_LDO2:213		reg = S5M8767_REG_LDO1CTRL + (reg_id - S5M8767_LDO1);214		break;215	case S5M8767_LDO3 ... S5M8767_LDO28:216		reg = S5M8767_REG_LDO3CTRL + (reg_id - S5M8767_LDO3);217		break;218	case S5M8767_BUCK1:219		reg = S5M8767_REG_BUCK1CTRL2;220		break;221	case S5M8767_BUCK2:222		reg = S5M8767_REG_BUCK2DVS1;223		if (s5m8767->buck2_gpiodvs)224			reg += s5m8767->buck_gpioindex;225		break;226	case S5M8767_BUCK3:227		reg = S5M8767_REG_BUCK3DVS1;228		if (s5m8767->buck3_gpiodvs)229			reg += s5m8767->buck_gpioindex;230		break;231	case S5M8767_BUCK4:232		reg = S5M8767_REG_BUCK4DVS1;233		if (s5m8767->buck4_gpiodvs)234			reg += s5m8767->buck_gpioindex;235		break;236	case S5M8767_BUCK5:237		reg = S5M8767_REG_BUCK5CTRL2;238		break;239	case S5M8767_BUCK6 ... S5M8767_BUCK9:240		reg = S5M8767_REG_BUCK6CTRL2 + (reg_id - S5M8767_BUCK6) * 2;241		break;242	default:243		return -EINVAL;244	}245 246	return reg;247}248 249static int s5m8767_convert_voltage_to_sel(const struct sec_voltage_desc *desc,250					  int min_vol)251{252	int selector = 0;253 254	if (desc == NULL)255		return -EINVAL;256 257	if (min_vol > desc->max)258		return -EINVAL;259 260	if (min_vol < desc->min)261		min_vol = desc->min;262 263	selector = DIV_ROUND_UP(min_vol - desc->min, desc->step);264 265	if (desc->min + desc->step * selector > desc->max)266		return -EINVAL;267 268	return selector;269}270 271static inline int s5m8767_set_high(struct s5m8767_info *s5m8767)272{273	int temp_index = s5m8767->buck_gpioindex;274 275	gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);276	gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);277	gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);278 279	return 0;280}281 282static inline int s5m8767_set_low(struct s5m8767_info *s5m8767)283{284	int temp_index = s5m8767->buck_gpioindex;285 286	gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);287	gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);288	gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);289 290	return 0;291}292 293static int s5m8767_set_voltage_sel(struct regulator_dev *rdev,294				   unsigned selector)295{296	struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);297	int reg_id = rdev_get_id(rdev);298	int old_index, index = 0;299	u8 *buck234_vol = NULL;300 301	switch (reg_id) {302	case S5M8767_LDO1 ... S5M8767_LDO28:303		break;304	case S5M8767_BUCK1 ... S5M8767_BUCK6:305		if (reg_id == S5M8767_BUCK2 && s5m8767->buck2_gpiodvs)306			buck234_vol = &s5m8767->buck2_vol[0];307		else if (reg_id == S5M8767_BUCK3 && s5m8767->buck3_gpiodvs)308			buck234_vol = &s5m8767->buck3_vol[0];309		else if (reg_id == S5M8767_BUCK4 && s5m8767->buck4_gpiodvs)310			buck234_vol = &s5m8767->buck4_vol[0];311		break;312	case S5M8767_BUCK7 ... S5M8767_BUCK8:313		return -EINVAL;314	case S5M8767_BUCK9:315		break;316	default:317		return -EINVAL;318	}319 320	/* buck234_vol != NULL means to control buck234 voltage via DVS GPIO */321	if (buck234_vol) {322		while (*buck234_vol != selector) {323			buck234_vol++;324			index++;325		}326		old_index = s5m8767->buck_gpioindex;327		s5m8767->buck_gpioindex = index;328 329		if (index > old_index)330			return s5m8767_set_high(s5m8767);331		else332			return s5m8767_set_low(s5m8767);333	} else {334		return regulator_set_voltage_sel_regmap(rdev, selector);335	}336}337 338static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev,339					     unsigned int old_sel,340					     unsigned int new_sel)341{342	struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);343 344	if ((old_sel < new_sel) && s5m8767->ramp_delay)345		return DIV_ROUND_UP(rdev->desc->uV_step * (new_sel - old_sel),346					s5m8767->ramp_delay * 1000);347	return 0;348}349 350static const struct regulator_ops s5m8767_ops = {351	.list_voltage		= regulator_list_voltage_linear,352	.is_enabled		= regulator_is_enabled_regmap,353	.enable			= regulator_enable_regmap,354	.disable		= regulator_disable_regmap,355	.get_voltage_sel	= regulator_get_voltage_sel_regmap,356	.set_voltage_sel	= s5m8767_set_voltage_sel,357	.set_voltage_time_sel	= s5m8767_set_voltage_time_sel,358};359 360static const struct regulator_ops s5m8767_buck78_ops = {361	.list_voltage		= regulator_list_voltage_linear,362	.is_enabled		= regulator_is_enabled_regmap,363	.enable			= regulator_enable_regmap,364	.disable		= regulator_disable_regmap,365	.get_voltage_sel	= regulator_get_voltage_sel_regmap,366	.set_voltage_sel	= regulator_set_voltage_sel_regmap,367};368 369#define s5m8767_regulator_desc(_name) {		\370	.name		= #_name,		\371	.id		= S5M8767_##_name,	\372	.ops		= &s5m8767_ops,		\373	.type		= REGULATOR_VOLTAGE,	\374	.owner		= THIS_MODULE,		\375}376 377#define s5m8767_regulator_buck78_desc(_name) {	\378	.name		= #_name,		\379	.id		= S5M8767_##_name,	\380	.ops		= &s5m8767_buck78_ops,	\381	.type		= REGULATOR_VOLTAGE,	\382	.owner		= THIS_MODULE,		\383}384 385static struct regulator_desc regulators[] = {386	s5m8767_regulator_desc(LDO1),387	s5m8767_regulator_desc(LDO2),388	s5m8767_regulator_desc(LDO3),389	s5m8767_regulator_desc(LDO4),390	s5m8767_regulator_desc(LDO5),391	s5m8767_regulator_desc(LDO6),392	s5m8767_regulator_desc(LDO7),393	s5m8767_regulator_desc(LDO8),394	s5m8767_regulator_desc(LDO9),395	s5m8767_regulator_desc(LDO10),396	s5m8767_regulator_desc(LDO11),397	s5m8767_regulator_desc(LDO12),398	s5m8767_regulator_desc(LDO13),399	s5m8767_regulator_desc(LDO14),400	s5m8767_regulator_desc(LDO15),401	s5m8767_regulator_desc(LDO16),402	s5m8767_regulator_desc(LDO17),403	s5m8767_regulator_desc(LDO18),404	s5m8767_regulator_desc(LDO19),405	s5m8767_regulator_desc(LDO20),406	s5m8767_regulator_desc(LDO21),407	s5m8767_regulator_desc(LDO22),408	s5m8767_regulator_desc(LDO23),409	s5m8767_regulator_desc(LDO24),410	s5m8767_regulator_desc(LDO25),411	s5m8767_regulator_desc(LDO26),412	s5m8767_regulator_desc(LDO27),413	s5m8767_regulator_desc(LDO28),414	s5m8767_regulator_desc(BUCK1),415	s5m8767_regulator_desc(BUCK2),416	s5m8767_regulator_desc(BUCK3),417	s5m8767_regulator_desc(BUCK4),418	s5m8767_regulator_desc(BUCK5),419	s5m8767_regulator_desc(BUCK6),420	s5m8767_regulator_buck78_desc(BUCK7),421	s5m8767_regulator_buck78_desc(BUCK8),422	s5m8767_regulator_desc(BUCK9),423};424 425/*426 * Enable GPIO control over BUCK9 in regulator_config for that regulator.427 */428static void s5m8767_regulator_config_ext_control(struct s5m8767_info *s5m8767,429		struct sec_regulator_data *rdata,430		struct regulator_config *config)431{432	int i, mode = 0;433 434	if (rdata->id != S5M8767_BUCK9)435		return;436 437	/* Check if opmode for regulator matches S5M8767_ENCTRL_USE_GPIO */438	for (i = 0; i < s5m8767->num_regulators; i++) {439		const struct sec_opmode_data *opmode = &s5m8767->opmode[i];440		if (opmode->id == rdata->id) {441			mode = s5m8767_opmode_reg[rdata->id][opmode->mode];442			break;443		}444	}445	if (mode != S5M8767_ENCTRL_USE_GPIO) {446		dev_warn(s5m8767->dev,447				"ext-control for %pOFn: mismatched op_mode (%x), ignoring\n",448				rdata->reg_node, mode);449		return;450	}451 452	if (!rdata->ext_control_gpiod) {453		dev_warn(s5m8767->dev,454				"ext-control for %pOFn: GPIO not valid, ignoring\n",455			 rdata->reg_node);456		return;457	}458 459	config->ena_gpiod = rdata->ext_control_gpiod;460}461 462/*463 * Turn on GPIO control over BUCK9.464 */465static int s5m8767_enable_ext_control(struct s5m8767_info *s5m8767,466		struct regulator_dev *rdev)467{468	int id = rdev_get_id(rdev);469	int ret, reg, enable_ctrl;470 471	if (id != S5M8767_BUCK9)472		return -EINVAL;473 474	ret = s5m8767_get_register(s5m8767, id, &reg, &enable_ctrl);475	if (ret)476		return ret;477 478	return regmap_update_bits(s5m8767->iodev->regmap_pmic,479			reg, S5M8767_ENCTRL_MASK,480			S5M8767_ENCTRL_USE_GPIO << S5M8767_ENCTRL_SHIFT);481}482 483 484#ifdef CONFIG_OF485static int s5m8767_pmic_dt_parse_dvs_gpio(struct sec_pmic_dev *iodev,486			struct sec_platform_data *pdata,487			struct device_node *pmic_np)488{489	int i, gpio;490 491	for (i = 0; i < 3; i++) {492		gpio = of_get_named_gpio(pmic_np,493					"s5m8767,pmic-buck-dvs-gpios", i);494		if (!gpio_is_valid(gpio)) {495			dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio);496			return -EINVAL;497		}498		pdata->buck_gpios[i] = gpio;499	}500	return 0;501}502 503static int s5m8767_pmic_dt_parse_ds_gpio(struct sec_pmic_dev *iodev,504			struct sec_platform_data *pdata,505			struct device_node *pmic_np)506{507	int i, gpio;508 509	for (i = 0; i < 3; i++) {510		gpio = of_get_named_gpio(pmic_np,511					"s5m8767,pmic-buck-ds-gpios", i);512		if (!gpio_is_valid(gpio)) {513			dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio);514			return -EINVAL;515		}516		pdata->buck_ds[i] = gpio;517	}518	return 0;519}520 521static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,522					struct sec_platform_data *pdata)523{524	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);525	struct device_node *pmic_np, *reg_np;526	struct sec_regulator_data *rdata;527	struct sec_opmode_data *rmode;528	unsigned int i, dvs_voltage_nr = 8, ret;529 530	pmic_np = iodev->dev->of_node;531	if (!pmic_np) {532		dev_err(iodev->dev, "could not find pmic sub-node\n");533		return -ENODEV;534	}535 536	struct device_node *regulators_np __free(device_node) = of_get_child_by_name(pmic_np,537										     "regulators");538	if (!regulators_np) {539		dev_err(iodev->dev, "could not find regulators sub-node\n");540		return -EINVAL;541	}542 543	/* count the number of regulators to be supported in pmic */544	pdata->num_regulators = of_get_child_count(regulators_np);545 546	rdata = devm_kcalloc(&pdev->dev,547			     pdata->num_regulators, sizeof(*rdata),548			     GFP_KERNEL);549	if (!rdata)550		return -ENOMEM;551 552	rmode = devm_kcalloc(&pdev->dev,553			     pdata->num_regulators, sizeof(*rmode),554			     GFP_KERNEL);555	if (!rmode)556		return -ENOMEM;557 558	pdata->regulators = rdata;559	pdata->opmode = rmode;560	for_each_child_of_node(regulators_np, reg_np) {561		for (i = 0; i < ARRAY_SIZE(regulators); i++)562			if (of_node_name_eq(reg_np, regulators[i].name))563				break;564 565		if (i == ARRAY_SIZE(regulators)) {566			dev_warn(iodev->dev,567			"don't know how to configure regulator %pOFn\n",568			reg_np);569			continue;570		}571 572		rdata->ext_control_gpiod = devm_fwnode_gpiod_get(573			&pdev->dev,574			of_fwnode_handle(reg_np),575			"s5m8767,pmic-ext-control",576			GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,577			"s5m8767");578		if (PTR_ERR(rdata->ext_control_gpiod) == -ENOENT) {579			rdata->ext_control_gpiod = NULL;580		} else if (IS_ERR(rdata->ext_control_gpiod)) {581			of_node_put(reg_np);582			return PTR_ERR(rdata->ext_control_gpiod);583		}584 585		rdata->id = i;586		rdata->initdata = of_get_regulator_init_data(587						&pdev->dev, reg_np,588						&regulators[i]);589		rdata->reg_node = reg_np;590		rdata++;591		rmode->id = i;592		if (of_property_read_u32(reg_np, "op_mode",593				&rmode->mode)) {594			dev_warn(iodev->dev,595				"no op_mode property at %pOF\n",596				reg_np);597 598			rmode->mode = S5M8767_OPMODE_NORMAL_MODE;599		}600		rmode++;601	}602 603	if (of_property_read_bool(pmic_np, "s5m8767,pmic-buck2-uses-gpio-dvs")) {604		pdata->buck2_gpiodvs = true;605 606		if (of_property_read_u32_array(pmic_np,607				"s5m8767,pmic-buck2-dvs-voltage",608				pdata->buck2_voltage, dvs_voltage_nr)) {609			dev_err(iodev->dev, "buck2 voltages not specified\n");610			return -EINVAL;611		}612	}613 614	if (of_property_read_bool(pmic_np, "s5m8767,pmic-buck3-uses-gpio-dvs")) {615		pdata->buck3_gpiodvs = true;616 617		if (of_property_read_u32_array(pmic_np,618				"s5m8767,pmic-buck3-dvs-voltage",619				pdata->buck3_voltage, dvs_voltage_nr)) {620			dev_err(iodev->dev, "buck3 voltages not specified\n");621			return -EINVAL;622		}623	}624 625	if (of_property_read_bool(pmic_np, "s5m8767,pmic-buck4-uses-gpio-dvs")) {626		pdata->buck4_gpiodvs = true;627 628		if (of_property_read_u32_array(pmic_np,629				"s5m8767,pmic-buck4-dvs-voltage",630				pdata->buck4_voltage, dvs_voltage_nr)) {631			dev_err(iodev->dev, "buck4 voltages not specified\n");632			return -EINVAL;633		}634	}635 636	if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||637						pdata->buck4_gpiodvs) {638		ret = s5m8767_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np);639		if (ret)640			return -EINVAL;641 642		if (of_property_read_u32(pmic_np,643				"s5m8767,pmic-buck-default-dvs-idx",644				&pdata->buck_default_idx)) {645			pdata->buck_default_idx = 0;646		} else {647			if (pdata->buck_default_idx >= 8) {648				pdata->buck_default_idx = 0;649				dev_info(iodev->dev,650				"invalid value for default dvs index, use 0\n");651			}652		}653	}654 655	ret = s5m8767_pmic_dt_parse_ds_gpio(iodev, pdata, pmic_np);656	if (ret)657		return -EINVAL;658 659	pdata->buck2_ramp_enable = of_property_read_bool(pmic_np, "s5m8767,pmic-buck2-ramp-enable");660	pdata->buck3_ramp_enable = of_property_read_bool(pmic_np, "s5m8767,pmic-buck3-ramp-enable");661	pdata->buck4_ramp_enable = of_property_read_bool(pmic_np, "s5m8767,pmic-buck4-ramp-enable");662 663	if (pdata->buck2_ramp_enable || pdata->buck3_ramp_enable664			|| pdata->buck4_ramp_enable) {665		if (of_property_read_u32(pmic_np, "s5m8767,pmic-buck-ramp-delay",666				&pdata->buck_ramp_delay))667			pdata->buck_ramp_delay = 0;668	}669 670	return 0;671}672#else673static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,674					struct sec_platform_data *pdata)675{676	return 0;677}678#endif /* CONFIG_OF */679 680static int s5m8767_pmic_probe(struct platform_device *pdev)681{682	struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);683	struct sec_platform_data *pdata = iodev->pdata;684	struct regulator_config config = { };685	struct s5m8767_info *s5m8767;686	int i, ret, buck_init;687 688	if (!pdata) {689		dev_err(pdev->dev.parent, "Platform data not supplied\n");690		return -ENODEV;691	}692 693	if (iodev->dev->of_node) {694		ret = s5m8767_pmic_dt_parse_pdata(pdev, pdata);695		if (ret)696			return ret;697	}698 699	if (pdata->buck2_gpiodvs) {700		if (pdata->buck3_gpiodvs || pdata->buck4_gpiodvs) {701			dev_err(&pdev->dev, "S5M8767 GPIO DVS NOT VALID\n");702			return -EINVAL;703		}704	}705 706	if (pdata->buck3_gpiodvs) {707		if (pdata->buck2_gpiodvs || pdata->buck4_gpiodvs) {708			dev_err(&pdev->dev, "S5M8767 GPIO DVS NOT VALID\n");709			return -EINVAL;710		}711	}712 713	if (pdata->buck4_gpiodvs) {714		if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs) {715			dev_err(&pdev->dev, "S5M8767 GPIO DVS NOT VALID\n");716			return -EINVAL;717		}718	}719 720	s5m8767 = devm_kzalloc(&pdev->dev, sizeof(struct s5m8767_info),721				GFP_KERNEL);722	if (!s5m8767)723		return -ENOMEM;724 725	s5m8767->dev = &pdev->dev;726	s5m8767->iodev = iodev;727	s5m8767->num_regulators = pdata->num_regulators;728	platform_set_drvdata(pdev, s5m8767);729 730	s5m8767->buck_gpioindex = pdata->buck_default_idx;731	s5m8767->buck2_gpiodvs = pdata->buck2_gpiodvs;732	s5m8767->buck3_gpiodvs = pdata->buck3_gpiodvs;733	s5m8767->buck4_gpiodvs = pdata->buck4_gpiodvs;734	s5m8767->buck_gpios[0] = pdata->buck_gpios[0];735	s5m8767->buck_gpios[1] = pdata->buck_gpios[1];736	s5m8767->buck_gpios[2] = pdata->buck_gpios[2];737	s5m8767->buck_ds[0] = pdata->buck_ds[0];738	s5m8767->buck_ds[1] = pdata->buck_ds[1];739	s5m8767->buck_ds[2] = pdata->buck_ds[2];740 741	s5m8767->ramp_delay = pdata->buck_ramp_delay;742	s5m8767->buck2_ramp = pdata->buck2_ramp_enable;743	s5m8767->buck3_ramp = pdata->buck3_ramp_enable;744	s5m8767->buck4_ramp = pdata->buck4_ramp_enable;745	s5m8767->opmode = pdata->opmode;746 747	buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,748						   pdata->buck2_init);749 750	regmap_write(s5m8767->iodev->regmap_pmic, S5M8767_REG_BUCK2DVS2,751			buck_init);752 753	buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,754						   pdata->buck3_init);755 756	regmap_write(s5m8767->iodev->regmap_pmic, S5M8767_REG_BUCK3DVS2,757			buck_init);758 759	buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,760						   pdata->buck4_init);761 762	regmap_write(s5m8767->iodev->regmap_pmic, S5M8767_REG_BUCK4DVS2,763			buck_init);764 765	for (i = 0; i < 8; i++) {766		if (s5m8767->buck2_gpiodvs) {767			s5m8767->buck2_vol[i] =768				s5m8767_convert_voltage_to_sel(769						&buck_voltage_val2,770						pdata->buck2_voltage[i]);771		}772 773		if (s5m8767->buck3_gpiodvs) {774			s5m8767->buck3_vol[i] =775				s5m8767_convert_voltage_to_sel(776						&buck_voltage_val2,777						pdata->buck3_voltage[i]);778		}779 780		if (s5m8767->buck4_gpiodvs) {781			s5m8767->buck4_vol[i] =782				s5m8767_convert_voltage_to_sel(783						&buck_voltage_val2,784						pdata->buck4_voltage[i]);785		}786	}787 788	if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||789						pdata->buck4_gpiodvs) {790 791		if (!gpio_is_valid(pdata->buck_gpios[0]) ||792			!gpio_is_valid(pdata->buck_gpios[1]) ||793			!gpio_is_valid(pdata->buck_gpios[2])) {794			dev_err(&pdev->dev, "GPIO NOT VALID\n");795			return -EINVAL;796		}797 798		ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[0],799					"S5M8767 SET1");800		if (ret)801			return ret;802 803		ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[1],804					"S5M8767 SET2");805		if (ret)806			return ret;807 808		ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[2],809					"S5M8767 SET3");810		if (ret)811			return ret;812 813		/* SET1 GPIO */814		gpio_direction_output(pdata->buck_gpios[0],815				(s5m8767->buck_gpioindex >> 2) & 0x1);816		/* SET2 GPIO */817		gpio_direction_output(pdata->buck_gpios[1],818				(s5m8767->buck_gpioindex >> 1) & 0x1);819		/* SET3 GPIO */820		gpio_direction_output(pdata->buck_gpios[2],821				(s5m8767->buck_gpioindex >> 0) & 0x1);822	}823 824	ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[0], "S5M8767 DS2");825	if (ret)826		return ret;827 828	ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[1], "S5M8767 DS3");829	if (ret)830		return ret;831 832	ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[2], "S5M8767 DS4");833	if (ret)834		return ret;835 836	/* DS2 GPIO */837	gpio_direction_output(pdata->buck_ds[0], 0x0);838	/* DS3 GPIO */839	gpio_direction_output(pdata->buck_ds[1], 0x0);840	/* DS4 GPIO */841	gpio_direction_output(pdata->buck_ds[2], 0x0);842 843	regmap_update_bits(s5m8767->iodev->regmap_pmic,844			   S5M8767_REG_BUCK2CTRL, 1 << 1,845			   (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1));846	regmap_update_bits(s5m8767->iodev->regmap_pmic,847			   S5M8767_REG_BUCK3CTRL, 1 << 1,848			   (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1));849	regmap_update_bits(s5m8767->iodev->regmap_pmic,850			   S5M8767_REG_BUCK4CTRL, 1 << 1,851			   (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1));852 853	/* Initialize GPIO DVS registers */854	for (i = 0; i < 8; i++) {855		if (s5m8767->buck2_gpiodvs) {856			regmap_write(s5m8767->iodev->regmap_pmic,857					S5M8767_REG_BUCK2DVS1 + i,858					s5m8767->buck2_vol[i]);859		}860 861		if (s5m8767->buck3_gpiodvs) {862			regmap_write(s5m8767->iodev->regmap_pmic,863					S5M8767_REG_BUCK3DVS1 + i,864					s5m8767->buck3_vol[i]);865		}866 867		if (s5m8767->buck4_gpiodvs) {868			regmap_write(s5m8767->iodev->regmap_pmic,869					S5M8767_REG_BUCK4DVS1 + i,870					s5m8767->buck4_vol[i]);871		}872	}873 874	if (s5m8767->buck2_ramp)875		regmap_update_bits(s5m8767->iodev->regmap_pmic,876				S5M8767_REG_DVSRAMP, 0x08, 0x08);877 878	if (s5m8767->buck3_ramp)879		regmap_update_bits(s5m8767->iodev->regmap_pmic,880				S5M8767_REG_DVSRAMP, 0x04, 0x04);881 882	if (s5m8767->buck4_ramp)883		regmap_update_bits(s5m8767->iodev->regmap_pmic,884				S5M8767_REG_DVSRAMP, 0x02, 0x02);885 886	if (s5m8767->buck2_ramp || s5m8767->buck3_ramp887		|| s5m8767->buck4_ramp) {888		unsigned int val;889		switch (s5m8767->ramp_delay) {890		case 5:891			val = S5M8767_DVS_BUCK_RAMP_5;892			break;893		case 10:894			val = S5M8767_DVS_BUCK_RAMP_10;895			break;896		case 25:897			val = S5M8767_DVS_BUCK_RAMP_25;898			break;899		case 50:900			val = S5M8767_DVS_BUCK_RAMP_50;901			break;902		case 100:903			val = S5M8767_DVS_BUCK_RAMP_100;904			break;905		default:906			val = S5M8767_DVS_BUCK_RAMP_10;907		}908		regmap_update_bits(s5m8767->iodev->regmap_pmic,909					S5M8767_REG_DVSRAMP,910					S5M8767_DVS_BUCK_RAMP_MASK,911					val << S5M8767_DVS_BUCK_RAMP_SHIFT);912	}913 914	for (i = 0; i < pdata->num_regulators; i++) {915		const struct sec_voltage_desc *desc;916		unsigned int id = pdata->regulators[i].id;917		int enable_reg, enable_val;918		struct regulator_dev *rdev;919 920		BUILD_BUG_ON(ARRAY_SIZE(regulators) != ARRAY_SIZE(reg_voltage_map));921		if (WARN_ON_ONCE(id >= ARRAY_SIZE(regulators)))922			continue;923 924		desc = reg_voltage_map[id];925		if (desc) {926			regulators[id].n_voltages =927				(desc->max - desc->min) / desc->step + 1;928			regulators[id].min_uV = desc->min;929			regulators[id].uV_step = desc->step;930			regulators[id].vsel_reg =931				s5m8767_get_vsel_reg(id, s5m8767);932			if (id < S5M8767_BUCK1)933				regulators[id].vsel_mask = 0x3f;934			else935				regulators[id].vsel_mask = 0xff;936 937			ret = s5m8767_get_register(s5m8767, id, &enable_reg,938					     &enable_val);939			if (ret) {940				dev_err(s5m8767->dev, "error reading registers\n");941				return ret;942			}943			regulators[id].enable_reg = enable_reg;944			regulators[id].enable_mask = S5M8767_ENCTRL_MASK;945			regulators[id].enable_val = enable_val;946		}947 948		config.dev = s5m8767->dev;949		config.init_data = pdata->regulators[i].initdata;950		config.driver_data = s5m8767;951		config.regmap = iodev->regmap_pmic;952		config.of_node = pdata->regulators[i].reg_node;953		config.ena_gpiod = NULL;954		if (pdata->regulators[i].ext_control_gpiod) {955			/* Assigns config.ena_gpiod */956			s5m8767_regulator_config_ext_control(s5m8767,957					&pdata->regulators[i], &config);958 959			/*960			 * Hand the GPIO descriptor management over to the961			 * regulator core, remove it from devres management.962			 */963			devm_gpiod_unhinge(s5m8767->dev, config.ena_gpiod);964		}965		rdev = devm_regulator_register(&pdev->dev, &regulators[id],966						  &config);967		if (IS_ERR(rdev)) {968			ret = PTR_ERR(rdev);969			dev_err(s5m8767->dev, "regulator init failed for %d\n",970					id);971			return ret;972		}973 974		if (pdata->regulators[i].ext_control_gpiod) {975			ret = s5m8767_enable_ext_control(s5m8767, rdev);976			if (ret < 0) {977				dev_err(s5m8767->dev,978						"failed to enable gpio control over %s: %d\n",979						rdev->desc->name, ret);980				return ret;981			}982		}983	}984 985	return 0;986}987 988static const struct platform_device_id s5m8767_pmic_id[] = {989	{ "s5m8767-pmic", 0},990	{ },991};992MODULE_DEVICE_TABLE(platform, s5m8767_pmic_id);993 994static struct platform_driver s5m8767_pmic_driver = {995	.driver = {996		.name = "s5m8767-pmic",997		.probe_type = PROBE_PREFER_ASYNCHRONOUS,998	},999	.probe = s5m8767_pmic_probe,1000	.id_table = s5m8767_pmic_id,1001};1002module_platform_driver(s5m8767_pmic_driver);1003 1004/* Module information */1005MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");1006MODULE_DESCRIPTION("Samsung S5M8767 Regulator Driver");1007MODULE_LICENSE("GPL");1008