Exemple #1
0
static int mc13783_probe(struct snd_soc_codec *codec)
{
	struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);

	/* these are the reset values */
	mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_RX0, 0x25893);
	mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_RX1, 0x00d35A);
	mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_TX, 0x420000);
	mc13xxx_reg_write(priv->mc13xxx, MC13783_SSI_NETWORK, 0x013060);
	mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_CODEC, 0x180027);
	mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_DAC, 0x0e0004);

	if (priv->adc_ssi_port == MC13783_SSI1_PORT)
		mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_CODEC,
				AUDIO_SSI_SEL, 0);
	else
		mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_CODEC,
				AUDIO_SSI_SEL, AUDIO_SSI_SEL);

	if (priv->dac_ssi_port == MC13783_SSI1_PORT)
		mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_DAC,
				AUDIO_SSI_SEL, 0);
	else
		mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_DAC,
				AUDIO_SSI_SEL, AUDIO_SSI_SEL);

	return 0;
}
Exemple #2
0
static void mc13783_remove(struct snd_soc_component *component)
{
	struct mc13783_priv *priv = snd_soc_component_get_drvdata(component);

	/* Make sure VAUDIOON is off */
	mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_RX0, 0x3, 0);
}
static int mc13xxx_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
		int max_uV, unsigned *selector)
{
	struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
	struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
	int value, id = rdev_get_id(rdev);
	int ret;

	dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n",
		__func__, id, min_uV, max_uV);

	/* Find the best index */
	value = mc13xxx_get_best_voltage_index(rdev, min_uV, max_uV);
	dev_dbg(rdev_get_dev(rdev), "%s best value: %d\n", __func__, value);
	if (value < 0)
		return value;

	mc13xxx_lock(priv->mc13xxx);
	ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].vsel_reg,
			mc13xxx_regulators[id].vsel_mask,
			value << mc13xxx_regulators[id].vsel_shift);
	mc13xxx_unlock(priv->mc13xxx);

	return ret;
}
static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev,
						unsigned selector)
{
	struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
	int volt, mask, id = rdev_get_id(rdev);
	u32 reg_value;
	int ret;

	volt = rdev->desc->volt_table[selector];
	mask = mc13892_regulators[id].vsel_mask;
	reg_value = selector << mc13892_regulators[id].vsel_shift;

	if (volt > 1375000) {
		mask |= MC13892_SWITCHERS0_SWxHI;
		reg_value |= MC13892_SWITCHERS0_SWxHI;
	} else if (volt < 1100000) {
		mask |= MC13892_SWITCHERS0_SWxHI;
		reg_value &= ~MC13892_SWITCHERS0_SWxHI;
	}

	mc13xxx_lock(priv->mc13xxx);
	ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].reg, mask,
			      reg_value);
	mc13xxx_unlock(priv->mc13xxx);

	return ret;
}
Exemple #5
0
static int mc13783_remove(struct snd_soc_codec *codec)
{
	struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);

	/* Make sure VAUDIOON is off */
	mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_RX0, 0x3, 0);

	return 0;
}
static int mc13xxx_regulator_set_voltage_sel(struct regulator_dev *rdev,
					     unsigned selector)
{
	struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
	struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
	int id = rdev_get_id(rdev);

	return mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].vsel_reg,
			       mc13xxx_regulators[id].vsel_mask,
			       selector << mc13xxx_regulators[id].vsel_shift);
}
static int mc13xxx_regulator_disable(struct regulator_dev *rdev)
{
	struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
	struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
	int id = rdev_get_id(rdev);

	dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);

	return mc13xxx_reg_rmw(priv->mc13xxx, mc13xxx_regulators[id].reg,
			       mc13xxx_regulators[id].enable_bit, 0);
}
Exemple #8
0
static void mc13xxx_led_work(struct work_struct *work)
{
	struct mc13xxx_led *led = container_of(work, struct mc13xxx_led, work);
	struct mc13xxx_leds *leds = led->leds;
	unsigned int reg, bank, off, shift;

	switch (led->id) {
	case MC13783_LED_MD:
	case MC13783_LED_AD:
	case MC13783_LED_KP:
		reg = 2;
		shift = 9 + (led->id - MC13783_LED_MD) * 4;
		break;
	case MC13783_LED_R1:
	case MC13783_LED_G1:
	case MC13783_LED_B1:
	case MC13783_LED_R2:
	case MC13783_LED_G2:
	case MC13783_LED_B2:
	case MC13783_LED_R3:
	case MC13783_LED_G3:
	case MC13783_LED_B3:
		off = led->id - MC13783_LED_R1;
		bank = off / 3;
		reg = 3 + bank;
		shift = (off - bank * 3) * 5 + 6;
		break;
	case MC13892_LED_MD:
	case MC13892_LED_AD:
	case MC13892_LED_KP:
		reg = (led->id - MC13892_LED_MD) / 2;
		shift = 3 + (led->id - MC13892_LED_MD) * 12;
		break;
	case MC13892_LED_R:
	case MC13892_LED_G:
	case MC13892_LED_B:
		off = led->id - MC13892_LED_R;
		bank = off / 2;
		reg = 2 + bank;
		shift = (off - bank * 2) * 12 + 3;
		break;
	case MC34708_LED_R:
	case MC34708_LED_G:
		reg = 0;
		shift = 3 + (led->id - MC34708_LED_R) * 12;
		break;
	default:
		BUG();
	}

	mc13xxx_reg_rmw(leds->master, leds->devtype->ledctrl_base + reg,
			mc13xxx_max_brightness(led->id) << shift,
			led->new_brightness << shift);
}
Exemple #9
0
static int mc13783_probe(struct snd_soc_codec *codec)
{
	struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec);
	int ret;

	ret = snd_soc_codec_set_cache_io(codec,
			dev_get_regmap(codec->dev->parent, NULL));
	if (ret != 0) {
		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
		return ret;
	}

	/* these are the reset values */
	mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_RX0, 0x25893);
	mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_RX1, 0x00d35A);
	mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_TX, 0x420000);
	mc13xxx_reg_write(priv->mc13xxx, MC13783_SSI_NETWORK, 0x013060);
	mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_CODEC, 0x180027);
	mc13xxx_reg_write(priv->mc13xxx, MC13783_AUDIO_DAC, 0x0e0004);

	if (priv->adc_ssi_port == MC13783_SSI1_PORT)
		mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_CODEC,
				AUDIO_SSI_SEL, 0);
	else
		mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_CODEC,
				0, AUDIO_SSI_SEL);

	if (priv->dac_ssi_port == MC13783_SSI1_PORT)
		mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_DAC,
				AUDIO_SSI_SEL, 0);
	else
		mc13xxx_reg_rmw(priv->mc13xxx, MC13783_AUDIO_DAC,
				0, AUDIO_SSI_SEL);

	return 0;
}
static int mc13892_vcam_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
	unsigned int en_val = 0;
	struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
	int ret, id = rdev_get_id(rdev);

	if (mode == REGULATOR_MODE_FAST)
		en_val = MC13892_REGULATORMODE1_VCAMCONFIGEN;

	mc13xxx_lock(priv->mc13xxx);
	ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].reg,
		MC13892_REGULATORMODE1_VCAMCONFIGEN, en_val);
	mc13xxx_unlock(priv->mc13xxx);

	return ret;
}
static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev,
						unsigned selector)
{
	struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
	int volt, mask, id = rdev_get_id(rdev);
	u32 reg_value;
	int ret;

	volt = rdev->desc->volt_table[selector];
	mask = mc13892_regulators[id].vsel_mask;
	reg_value = selector;

	/*
	 * Don't mess with the HI bit or support HI voltage offsets for SW1.
	 *
	 * Since the get_voltage_sel callback has given a fudged value for
	 * the selector offset, we need to back out that offset if HI is
	 * to be set so we write the correct value to the register.
	 *
	 * The HI bit addition and selector offset handling COULD be more
	 * complicated by shifting and masking off the voltage selector part
	 * of the register then logical OR it back in, but since the selector
	 * is at bits 4:0 there is very little point. This makes the whole
	 * thing more readable and we do far less work.
	 */

	if (mc13892_regulators[id].vsel_reg != MC13892_SWITCHERS0) {
		mask |= MC13892_SWITCHERS0_SWxHI;

		if (volt > 1375000) {
			reg_value -= MC13892_SWxHI_SEL_OFFSET;
			reg_value |= MC13892_SWITCHERS0_SWxHI;
		} else {
			reg_value &= ~MC13892_SWITCHERS0_SWxHI;
		}
	}

	mc13xxx_lock(priv->mc13xxx);
	ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].vsel_reg, mask,
			      reg_value);
	mc13xxx_unlock(priv->mc13xxx);

	return ret;
}
static int __devinit mc13783_pwrbutton_probe(struct platform_device *pdev)
{
	const struct mc13xxx_buttons_platform_data *pdata;
	struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
	struct input_dev *pwr;
	struct mc13783_pwrb *priv;
	int err = 0;
	int reg = 0;

	pdata = dev_get_platdata(&pdev->dev);
	if (!pdata) {
		dev_err(&pdev->dev, "missing platform data\n");
		return -ENODEV;
	}

	pwr = input_allocate_device();
	if (!pwr) {
		dev_dbg(&pdev->dev, "Can't allocate power button\n");
		return -ENOMEM;
	}

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv) {
		err = -ENOMEM;
		dev_dbg(&pdev->dev, "Can't allocate power button\n");
		goto free_input_dev;
	}

	reg |= (pdata->b1on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON1BDBNC;
	reg |= (pdata->b2on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON2BDBNC;
	reg |= (pdata->b3on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON3BDBNC;

	priv->pwr = pwr;
	priv->mc13783 = mc13783;

	mc13xxx_lock(mc13783);

	if (pdata->b1on_flags & MC13783_BUTTON_ENABLE) {
		priv->keymap[0] = pdata->b1on_key;
		if (pdata->b1on_key != KEY_RESERVED)
			__set_bit(pdata->b1on_key, pwr->keybit);

		if (pdata->b1on_flags & MC13783_BUTTON_POL_INVERT)
			priv->flags |= MC13783_PWRB_B1_POL_INVERT;

		if (pdata->b1on_flags & MC13783_BUTTON_RESET_EN)
			reg |= MC13783_POWER_CONTROL_2_ON1BRSTEN;

		err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD1,
					  button_irq, "b1on", priv);
		if (err) {
			dev_dbg(&pdev->dev, "Can't request irq\n");
			goto free_priv;
		}
	}

	if (pdata->b2on_flags & MC13783_BUTTON_ENABLE) {
		priv->keymap[1] = pdata->b2on_key;
		if (pdata->b2on_key != KEY_RESERVED)
			__set_bit(pdata->b2on_key, pwr->keybit);

		if (pdata->b2on_flags & MC13783_BUTTON_POL_INVERT)
			priv->flags |= MC13783_PWRB_B2_POL_INVERT;

		if (pdata->b2on_flags & MC13783_BUTTON_RESET_EN)
			reg |= MC13783_POWER_CONTROL_2_ON2BRSTEN;

		err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD2,
					  button_irq, "b2on", priv);
		if (err) {
			dev_dbg(&pdev->dev, "Can't request irq\n");
			goto free_irq_b1;
		}
	}

	if (pdata->b3on_flags & MC13783_BUTTON_ENABLE) {
		priv->keymap[2] = pdata->b3on_key;
		if (pdata->b3on_key != KEY_RESERVED)
			__set_bit(pdata->b3on_key, pwr->keybit);

		if (pdata->b3on_flags & MC13783_BUTTON_POL_INVERT)
			priv->flags |= MC13783_PWRB_B3_POL_INVERT;

		if (pdata->b3on_flags & MC13783_BUTTON_RESET_EN)
			reg |= MC13783_POWER_CONTROL_2_ON3BRSTEN;

		err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD3,
					  button_irq, "b3on", priv);
		if (err) {
			dev_dbg(&pdev->dev, "Can't request irq: %d\n", err);
			goto free_irq_b2;
		}
	}

	mc13xxx_reg_rmw(mc13783, MC13783_REG_POWER_CONTROL_2, 0x3FE, reg);

	mc13xxx_unlock(mc13783);

	pwr->name = "mc13783_pwrbutton";
	pwr->phys = "mc13783_pwrbutton/input0";
	pwr->dev.parent = &pdev->dev;

	pwr->keycode = priv->keymap;
	pwr->keycodemax = ARRAY_SIZE(priv->keymap);
	pwr->keycodesize = sizeof(priv->keymap[0]);
	__set_bit(EV_KEY, pwr->evbit);

	err = input_register_device(pwr);
	if (err) {
		dev_dbg(&pdev->dev, "Can't register power button: %d\n", err);
		goto free_irq;
	}

	platform_set_drvdata(pdev, priv);

	return 0;

free_irq:
	mc13xxx_lock(mc13783);

	if (pdata->b3on_flags & MC13783_BUTTON_ENABLE)
		mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD3, priv);

free_irq_b2:
	if (pdata->b2on_flags & MC13783_BUTTON_ENABLE)
		mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD2, priv);

free_irq_b1:
	if (pdata->b1on_flags & MC13783_BUTTON_ENABLE)
		mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD1, priv);

free_priv:
	mc13xxx_unlock(mc13783);
	kfree(priv);

free_input_dev:
	input_free_device(pwr);

	return err;
}
static int mc13892_regulator_probe(struct platform_device *pdev)
{
	struct mc13xxx_regulator_priv *priv;
	struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent);
	struct mc13xxx_regulator_platform_data *pdata =
		dev_get_platdata(&pdev->dev);
	struct mc13xxx_regulator_init_data *mc13xxx_data;
	struct regulator_config config = { };
	int i, ret;
	int num_regulators = 0;
	u32 val;

	num_regulators = mc13xxx_get_num_regulators_dt(pdev);

	if (num_regulators <= 0 && pdata)
		num_regulators = pdata->num_regulators;
	if (num_regulators <= 0)
		return -EINVAL;

	priv = devm_kzalloc(&pdev->dev, sizeof(*priv) +
		num_regulators * sizeof(priv->regulators[0]),
		GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	priv->num_regulators = num_regulators;
	priv->mc13xxx_regulators = mc13892_regulators;
	priv->mc13xxx = mc13892;
	platform_set_drvdata(pdev, priv);

	mc13xxx_lock(mc13892);
	ret = mc13xxx_reg_read(mc13892, MC13892_REVISION, &val);
	if (ret)
		goto err_unlock;

	/* enable switch auto mode (on 2.0A silicon only) */
	if ((val & 0x0000FFFF) == 0x45d0) {
		ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS4,
			MC13892_SWITCHERS4_SW1MODE_M |
			MC13892_SWITCHERS4_SW2MODE_M,
			MC13892_SWITCHERS4_SW1MODE_AUTO |
			MC13892_SWITCHERS4_SW2MODE_AUTO);
		if (ret)
			goto err_unlock;

		ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS5,
			MC13892_SWITCHERS5_SW3MODE_M |
			MC13892_SWITCHERS5_SW4MODE_M,
			MC13892_SWITCHERS5_SW3MODE_AUTO |
			MC13892_SWITCHERS5_SW4MODE_AUTO);
		if (ret)
			goto err_unlock;
	}
	mc13xxx_unlock(mc13892);

	mc13892_regulators[MC13892_VCAM].desc.ops->set_mode
		= mc13892_vcam_set_mode;
	mc13892_regulators[MC13892_VCAM].desc.ops->get_mode
		= mc13892_vcam_get_mode;

	mc13xxx_data = mc13xxx_parse_regulators_dt(pdev, mc13892_regulators,
					ARRAY_SIZE(mc13892_regulators));

	for (i = 0; i < priv->num_regulators; i++) {
		struct regulator_init_data *init_data;
		struct regulator_desc *desc;
		struct device_node *node = NULL;
		int id;

		if (mc13xxx_data) {
			id = mc13xxx_data[i].id;
			init_data = mc13xxx_data[i].init_data;
			node = mc13xxx_data[i].node;
		} else {
			id = pdata->regulators[i].id;
			init_data = pdata->regulators[i].init_data;
		}
		desc = &mc13892_regulators[id].desc;

		config.dev = &pdev->dev;
		config.init_data = init_data;
		config.driver_data = priv;
		config.of_node = node;

		priv->regulators[i] = regulator_register(desc, &config);
		if (IS_ERR(priv->regulators[i])) {
			dev_err(&pdev->dev, "failed to register regulator %s\n",
				mc13892_regulators[i].desc.name);
			ret = PTR_ERR(priv->regulators[i]);
			goto err;
		}
	}

	return 0;
err:
	while (--i >= 0)
		regulator_unregister(priv->regulators[i]);
	return ret;

err_unlock:
	mc13xxx_unlock(mc13892);
	return ret;
}
Exemple #14
0
int mc13xxx_common_init(struct device *dev)
{
	struct mc13xxx_platform_data *pdata = dev_get_platdata(dev);
	struct mc13xxx *mc13xxx = dev_get_drvdata(dev);
	u32 revision;
	int i, ret;

	mc13xxx->dev = dev;

	ret = mc13xxx_reg_read(mc13xxx, MC13XXX_REVISION, &revision);
	if (ret)
		return ret;

	mc13xxx->variant->print_revision(mc13xxx, revision);

	ret = mc13xxx_reg_rmw(mc13xxx, MC13XXX_PWRCTRL,
			MC13XXX_PWRCTRL_WDIRESET, MC13XXX_PWRCTRL_WDIRESET);
	if (ret)
		return ret;

	for (i = 0; i < ARRAY_SIZE(mc13xxx->irqs); i++) {
		mc13xxx->irqs[i].reg_offset = i / MC13XXX_IRQ_PER_REG;
		mc13xxx->irqs[i].mask = BIT(i % MC13XXX_IRQ_PER_REG);
	}

	mc13xxx->irq_chip.name = dev_name(dev);
	mc13xxx->irq_chip.status_base = MC13XXX_IRQSTAT0;
	mc13xxx->irq_chip.mask_base = MC13XXX_IRQMASK0;
	mc13xxx->irq_chip.ack_base = MC13XXX_IRQSTAT0;
	mc13xxx->irq_chip.irq_reg_stride = MC13XXX_IRQSTAT1 - MC13XXX_IRQSTAT0;
	mc13xxx->irq_chip.init_ack_masked = true;
	mc13xxx->irq_chip.use_ack = true;
	mc13xxx->irq_chip.num_regs = MC13XXX_IRQ_REG_CNT;
	mc13xxx->irq_chip.irqs = mc13xxx->irqs;
	mc13xxx->irq_chip.num_irqs = ARRAY_SIZE(mc13xxx->irqs);

	ret = regmap_add_irq_chip(mc13xxx->regmap, mc13xxx->irq, IRQF_ONESHOT,
				  0, &mc13xxx->irq_chip, &mc13xxx->irq_data);
	if (ret)
		return ret;

	mutex_init(&mc13xxx->lock);

	if (mc13xxx_probe_flags_dt(mc13xxx) < 0 && pdata)
		mc13xxx->flags = pdata->flags;

	if (pdata) {
		mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
			&pdata->regulators, sizeof(pdata->regulators));
		mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led",
				pdata->leds, sizeof(*pdata->leds));
		mc13xxx_add_subdevice_pdata(mc13xxx, "%s-pwrbutton",
				pdata->buttons, sizeof(*pdata->buttons));
		if (mc13xxx->flags & MC13XXX_USE_CODEC)
			mc13xxx_add_subdevice_pdata(mc13xxx, "%s-codec",
				pdata->codec, sizeof(*pdata->codec));
		if (mc13xxx->flags & MC13XXX_USE_TOUCHSCREEN)
			mc13xxx_add_subdevice_pdata(mc13xxx, "%s-ts",
				&pdata->touch, sizeof(pdata->touch));
	} else {
		mc13xxx_add_subdevice(mc13xxx, "%s-regulator");
		mc13xxx_add_subdevice(mc13xxx, "%s-led");
		mc13xxx_add_subdevice(mc13xxx, "%s-pwrbutton");
		if (mc13xxx->flags & MC13XXX_USE_CODEC)
			mc13xxx_add_subdevice(mc13xxx, "%s-codec");
		if (mc13xxx->flags & MC13XXX_USE_TOUCHSCREEN)
			mc13xxx_add_subdevice(mc13xxx, "%s-ts");
	}

	if (mc13xxx->flags & MC13XXX_USE_ADC)
		mc13xxx_add_subdevice(mc13xxx, "%s-adc");

	if (mc13xxx->flags & MC13XXX_USE_RTC)
		mc13xxx_add_subdevice(mc13xxx, "%s-rtc");

	return 0;
}
static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
{
	struct mc13xxx_regulator_priv *priv;
	struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent);
	struct mc13xxx_regulator_platform_data *pdata =
		dev_get_platdata(&pdev->dev);
	struct mc13xxx_regulator_init_data *init_data;
	int i, ret;
	u32 val;

	priv = kzalloc(sizeof(*priv) +
		pdata->num_regulators * sizeof(priv->regulators[0]),
		GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	priv->mc13xxx_regulators = mc13892_regulators;
	priv->mc13xxx = mc13892;

	mc13xxx_lock(mc13892);
	ret = mc13xxx_reg_read(mc13892, MC13892_REVISION, &val);
	if (ret)
		goto err_free;

	/* enable switch auto mode */
	if ((val & 0x0000FFFF) == 0x45d0) {
		ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS4,
			MC13892_SWITCHERS4_SW1MODE_M |
			MC13892_SWITCHERS4_SW2MODE_M,
			MC13892_SWITCHERS4_SW1MODE_AUTO |
			MC13892_SWITCHERS4_SW2MODE_AUTO);
		if (ret)
			goto err_free;

		ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS5,
			MC13892_SWITCHERS5_SW3MODE_M |
			MC13892_SWITCHERS5_SW4MODE_M,
			MC13892_SWITCHERS5_SW3MODE_AUTO |
			MC13892_SWITCHERS5_SW4MODE_AUTO);
		if (ret)
			goto err_free;
	}
	mc13xxx_unlock(mc13892);

	pax_open_kernel();
	*(void **)&mc13892_regulators[MC13892_VCAM].desc.ops->set_mode
		= mc13892_vcam_set_mode;
	*(void **)&mc13892_regulators[MC13892_VCAM].desc.ops->get_mode
		= mc13892_vcam_get_mode;
	pax_close_kernel();
	for (i = 0; i < pdata->num_regulators; i++) {
		init_data = &pdata->regulators[i];
		priv->regulators[i] = regulator_register(
			&mc13892_regulators[init_data->id].desc,
			&pdev->dev, init_data->init_data, priv);

		if (IS_ERR(priv->regulators[i])) {
			dev_err(&pdev->dev, "failed to register regulator %s\n",
				mc13892_regulators[i].desc.name);
			ret = PTR_ERR(priv->regulators[i]);
			goto err;
		}
	}

	platform_set_drvdata(pdev, priv);

	return 0;
err:
	while (--i >= 0)
		regulator_unregister(priv->regulators[i]);

err_free:
	mc13xxx_unlock(mc13892);
	kfree(priv);

	return ret;
}