Beispiel #1
0
/*
 * Handle commands from user-space
 */
static int wm8350_rtc_ioctl(struct device *dev, unsigned int cmd,
			    unsigned long arg)
{
	struct wm8350_rtc *wm_rtc = to_wm8350_rtc_device(dev);
	struct wm8350 *wm8350 = to_wm8350_from_rtc(wm_rtc);

	switch (cmd) {
	case RTC_AIE_OFF:	/* alarm off */
		wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_ALM);
		wm_rtc->alarm_enabled = 0;
		break;
	case RTC_AIE_ON:	/* alarm on */
		wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_ALM);
		wm_rtc->alarm_enabled = 1;
		break;
	case RTC_UIE_OFF:	/* update off */
		wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC);
		wm_rtc->update_enabled = 0;
		break;
	case RTC_UIE_ON:	/* update on */
		wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC);
		wm_rtc->update_enabled = 1;
		break;
	case RTC_PIE_ON:
		if (!wm_rtc->pie_enabled) {
			enable_irq(wm_rtc->per_irq);
			wm_rtc->pie_enabled = 1;
		}
		break;
	case RTC_PIE_OFF:
		if (wm_rtc->pie_enabled) {
			disable_irq(wm_rtc->per_irq);
			wm_rtc->pie_enabled = 0;
		}
		break;
	case RTC_IRQP_READ:	/* read periodic alarm frequency */
		return wm_rtc->pie_freq;
	case RTC_IRQP_SET:	/* set periodic alarm frequency */
		return wm8350_rtc_set_pie(wm_rtc, arg);
	default:
		return -ENOIOCTLCMD;
	}

	return 0;
}
static void headphone_detect_handler(struct work_struct *work)
{
	struct imx_3stack_priv *priv = &machine_priv;
	struct platform_device *pdev = priv->pdev;
	struct wm8350 *wm8350 = priv->wm8350;

	sysfs_notify(&pdev->dev.kobj, NULL, "headphone");
	wm8350_unmask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R);
}
static int wm8350_regulator_probe(struct platform_device *pdev)
{
	struct wm8350 *wm8350 = dev_get_drvdata(&pdev->dev);
	struct regulator_dev *rdev;
	int ret;
	u16 val;

	if (pdev->id < WM8350_DCDC_1 || pdev->id > WM8350_ISINK_B)
		return -ENODEV;

	/* do any regulatior specific init */
	switch (pdev->id) {
	case WM8350_DCDC_1:
		val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER);
		wm8350->pmic.dcdc1_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
		break;
	case WM8350_DCDC_3:
		val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER);
		wm8350->pmic.dcdc3_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
		break;
	case WM8350_DCDC_4:
		val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER);
		wm8350->pmic.dcdc4_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
		break;
	case WM8350_DCDC_6:
		val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER);
		wm8350->pmic.dcdc6_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
		break;
	}

	/* register regulator */
	rdev = regulator_register(&wm8350_reg[pdev->id], &pdev->dev,
				  pdev->dev.platform_data,
				  dev_get_drvdata(&pdev->dev));
	if (IS_ERR(rdev)) {
		dev_err(&pdev->dev, "failed to register %s\n",
			wm8350_reg[pdev->id].name);
		return PTR_ERR(rdev);
	}

	/* register regulator IRQ */
	ret = wm8350_register_irq(wm8350, wm8350_reg[pdev->id].irq,
				  pmic_uv_handler, rdev);
	if (ret < 0) {
		regulator_unregister(rdev);
		dev_err(&pdev->dev, "failed to register regulator %s IRQ\n",
			wm8350_reg[pdev->id].name);
		return ret;
	}

	wm8350_unmask_irq(wm8350, wm8350_reg[pdev->id].irq);

	return 0;
}
static int config_gpios(struct wm8350 *wm8350)
{
    /* power on */
    wm8350_gpio_config(wm8350, 0, WM8350_GPIO_DIR_IN,
                       WM8350_GPIO0_PWR_ON_IN, WM8350_GPIO_ACTIVE_LOW,
                       WM8350_GPIO_PULL_UP, WM8350_GPIO_INVERT_OFF,
                       WM8350_GPIO_DEBOUNCE_ON);

    /* Sw3 --> PWR_OFF_GPIO3 */
    /* lg - TODO: GPIO1_0 to be pulled down */
    wm8350_gpio_config(wm8350, 3, WM8350_GPIO_DIR_IN,
                       WM8350_GPIO3_PWR_OFF_IN, WM8350_GPIO_ACTIVE_HIGH,
                       WM8350_GPIO_PULL_DOWN, WM8350_GPIO_INVERT_OFF,
                       WM8350_GPIO_DEBOUNCE_ON);

    /* MR or MEMRST ????? */
    wm8350_gpio_config(wm8350, 4, WM8350_GPIO_DIR_IN,
                       WM8350_GPIO4_MR_IN, WM8350_GPIO_ACTIVE_HIGH,
                       WM8350_GPIO_PULL_DOWN, WM8350_GPIO_INVERT_OFF,
                       WM8350_GPIO_DEBOUNCE_OFF);

    /* Hibernate -- GPIO 7 */
    wm8350_gpio_config(wm8350, 7, WM8350_GPIO_DIR_IN,
                       WM8350_GPIO7_HIBERNATE_IN, WM8350_GPIO_ACTIVE_HIGH,
                       WM8350_GPIO_PULL_DOWN, WM8350_GPIO_INVERT_OFF,
                       WM8350_GPIO_DEBOUNCE_OFF);

    /* SDOUT */
    wm8350_gpio_config(wm8350, 6, WM8350_GPIO_DIR_OUT,
                       WM8350_GPIO6_SDOUT_OUT, WM8350_GPIO_ACTIVE_HIGH,
                       WM8350_GPIO_PULL_NONE, WM8350_GPIO_INVERT_OFF,
                       WM8350_GPIO_DEBOUNCE_OFF);

    /* GPIO switch SW2 */
    wm8350_gpio_config(wm8350, 7, WM8350_GPIO_DIR_IN, WM8350_GPIO7_GPIO_IN,
                       WM8350_GPIO_ACTIVE_HIGH, WM8350_GPIO_PULL_DOWN,
                       WM8350_GPIO_INVERT_OFF, WM8350_GPIO_DEBOUNCE_ON);
    wm8350_register_irq(wm8350, WM8350_IRQ_GPIO(7),
                        imx37_3stack_switch_handler, NULL);
    wm8350_unmask_irq(wm8350, WM8350_IRQ_GPIO(7));

    /* PWR_FAIL */
    wm8350_gpio_config(wm8350, 8, WM8350_GPIO_DIR_OUT,
                       WM8350_GPIO8_VCC_FAULT_OUT, WM8350_GPIO_ACTIVE_LOW,
                       WM8350_GPIO_PULL_NONE, WM8350_GPIO_INVERT_OFF,
                       WM8350_GPIO_DEBOUNCE_OFF);

    /* BATT Fault */
    wm8350_gpio_config(wm8350, 9, WM8350_GPIO_DIR_OUT,
                       WM8350_GPIO9_BATT_FAULT_OUT, WM8350_GPIO_ACTIVE_LOW,
                       WM8350_GPIO_PULL_NONE, WM8350_GPIO_INVERT_OFF,
                       WM8350_GPIO_DEBOUNCE_OFF);
    return 0;
}
static int __devinit imx_3stack_wm8350_probe(struct platform_device *pdev)
{
	struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
	struct imx_3stack_priv *priv = &machine_priv;
	struct wm8350 *wm8350 = plat->priv;
	struct snd_soc_dai *wm8350_cpu_dai;
	int ret = 0;
	u16 reg;

	priv->pdev = pdev;
	priv->wm8350 = wm8350;

	gpio_activate_audio_ports();
	imx_3stack_init_dam(plat->src_port, plat->ext_port);

	if (plat->src_port == 2)
		wm8350_cpu_dai =  imx_ssi_dai[2];
	else
		wm8350_cpu_dai = imx_ssi_dai[0];

	imx_3stack_dai.cpu_dai = wm8350_cpu_dai;

	ret = driver_create_file(pdev->dev.driver, &driver_attr_headphone);
	if (ret < 0) {
		pr_err("%s:failed to create driver_attr_headphone\n", __func__);
		return ret;
	}

	/* enable slow clock gen for jack detect */
	reg = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_4);
	wm8350_reg_write(wm8350, WM8350_POWER_MGMT_4, reg | WM8350_TOCLK_ENA);
	/* enable jack detect */
	reg = wm8350_reg_read(wm8350, WM8350_JACK_DETECT);
	wm8350_reg_write(wm8350, WM8350_JACK_DETECT, reg | WM8350_JDR_ENA);
	wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R,
			    imx_3stack_jack_handler, NULL);
	wm8350_unmask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R);

	wm8350_jack_func = 1;
	wm8350_spk_func = 1;

	return 0;
}
static int wm8350_rtc_update_irq_enable(struct device *dev,
					unsigned int enabled)
{
	struct wm8350 *wm8350 = dev_get_drvdata(dev);

	/* Suppress duplicate changes since genirq nests enable and
	 * disable calls. */
	if (enabled == wm8350->rtc.update_enabled)
		return 0;

	if (enabled)
		wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC);
	else
		wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC);

	wm8350->rtc.update_enabled = enabled;

	return 0;
}
Beispiel #7
0
/**
 * wm8350_hp_jack_detect - Enable headphone jack detection.
 *
 * @codec:  WM8350 codec
 * @which:  left or right jack detect signal
 * @jack:   jack to report detection events on
 * @report: value to report
 *
 * Enables the headphone jack detection of the WM8350.
 */
int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
			  struct snd_soc_jack *jack, int report)
{
	struct wm8350_data *priv = codec->private_data;
	struct wm8350 *wm8350 = codec->control_data;
	int irq;
	int ena;

	switch (which) {
	case WM8350_JDL:
		priv->hpl.jack = jack;
		priv->hpl.report = report;
		irq = WM8350_IRQ_CODEC_JCK_DET_L;
		ena = WM8350_JDL_ENA;
		break;

	case WM8350_JDR:
		priv->hpr.jack = jack;
		priv->hpr.report = report;
		irq = WM8350_IRQ_CODEC_JCK_DET_R;
		ena = WM8350_JDR_ENA;
		break;

	default:
		return -EINVAL;
	}

	wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA);
	wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena);

	/* Sync status */
	wm8350_hp_jack_handler(wm8350, irq, priv);

	wm8350_unmask_irq(wm8350, irq);

	return 0;
}
Beispiel #8
0
/*
 * Handle commands from user-space
 */
static int wm8350_rtc_ioctl(struct device *dev, unsigned int cmd,
			    unsigned long arg)
{
	struct wm8350 *wm8350 = dev_get_drvdata(dev);

	switch (cmd) {
	case RTC_AIE_OFF:
		return wm8350_rtc_stop_alarm(wm8350);
	case RTC_AIE_ON:
		return wm8350_rtc_start_alarm(wm8350);

	case RTC_UIE_OFF:
		wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC);
		break;
	case RTC_UIE_ON:
		wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC);
		break;

	default:
		return -ENOIOCTLCMD;
	}

	return 0;
}
//static int wm8350_init(struct wm8350 *wm8350)
int wm8350_dev_init(struct wm8350 *wm8350)
{
	int i, ret;
	u16 data;

#if 0
	/* dont assert RTS when hibernating */
	wm8350_set_bits(wm8350, WM8350_SYSTEM_HIBERNATE, WM8350_RST_HIB_MODE);
#endif

	wm8350_reg_unlock(wm8350);
	wm8350_set_bits(wm8350, WM8350_SYSTEM_CONTROL_1, WM8350_IRQ_POL);
	wm8350_reg_lock(wm8350);

	s3c2410_gpio_pullup(S3C2410_GPF1, 0);
	s3c2410_gpio_cfgpin(S3C2410_GPF1, S3C2410_GPF1_EINT1);
//	set_irq_type(IRQ_EINT1, IRQT_BOTHEDGE);
	s3c2410_gpio_pullup(S3C2410_GPF2, 0);
	s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_EINT2);

	/* Shutdown threshold value 3.1v off , 3.2v on */
	wm8350_reg_unlock(wm8350);
	data = wm8350_reg_read(wm8350, WM8350_POWER_CHECK_COMPARATOR)
		& ~(WM8350_PCCMP_OFF_THR_MASK | WM8350_PCCMP_ON_THR_MASK);
	wm8350_reg_write(wm8350, WM8350_POWER_CHECK_COMPARATOR, data | 0x23);
	wm8350_reg_lock(wm8350);

	data = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_2);
	wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_2, data | WM8350_AUXADC_CAL);

	config_s3c_wm8350_gpio(wm8350);

#if 0
	/* Sw1 --> PWR_ON */
	wm8350_register_irq(wm8350, WM8350_IRQ_WKUP_ONKEY,
			    imx32ads_switch_handler, NULL);
	wm8350_unmask_irq(wm8350, WM8350_IRQ_WKUP_ONKEY);
#endif

#ifndef CONFIG_MACH_CANOPUS
	for (i = 0; i < ARRAY_SIZE(wm8350_regulator_devices); i++) {
		platform_set_drvdata(&wm8350_regulator_devices[i], wm8350);
		ret = platform_device_register(&wm8350_regulator_devices[i]);
		if (ret < 0)
			goto unwind;
	}
#else	// CONFIG_MACH_CANOPUS
	struct regulator_init_data *reg_data = NULL;

	for (i = 0; i < ARRAY_SIZE(wm8350_regulator_devices); i++) {
		if (wm8350_regulator_devices[i].id == WM8350_DCDC_4) {
			// for LCD
			if (q_hw_ver(7800_ES2)
					|| q_hw_ver(7800_TP)
					|| q_hw_ver(7800_MP)) {
				reg_data = (struct regulator_init_data *)wm8350_regulator_devices[i].dev.platform_data;
				reg_data->constraints.min_uV = 3400000;
				reg_data->constraints.max_uV = 3400000;
				reg_data->constraints.state_mem.uV = 3400000;
			}
		} else if (wm8350_regulator_devices[i].id == WM8350_LDO_3) {
			// for PMIC LDO
			if (q_hw_ver(SWP2000)
					|| q_hw_ver(7800_MP2)
					|| q_hw_ver(KTQOOK_TP2)
					|| q_hw_ver(KTQOOK_MP)
					|| q_hw_ver(SKATM)) {
				reg_data = (struct regulator_init_data *)wm8350_regulator_devices[i].dev.platform_data;

				reg_data->constraints.min_uV = 1200000;
				reg_data->constraints.max_uV = 1200000;
				reg_data->num_consumer_supplies = ARRAY_SIZE(ldo4_consumers);
				reg_data->consumer_supplies = ldo4_consumers;
			}
		} else if (wm8350_regulator_devices[i].id == WM8350_LDO_4) {
			// for PMIC LDO
			if (q_hw_ver(SWP2000)
					|| q_hw_ver(7800_MP2)
					|| q_hw_ver(KTQOOK_TP2)
					|| q_hw_ver(KTQOOK_MP)
					|| q_hw_ver(SKATM)) {
				reg_data = (struct regulator_init_data *)wm8350_regulator_devices[i].dev.platform_data;
				reg_data->constraints.min_uV = 3300000;
				reg_data->constraints.max_uV = 3300000;
				reg_data->num_consumer_supplies = ARRAY_SIZE(ldo3_consumers);
				reg_data->consumer_supplies = ldo3_consumers;
			}
		}

		platform_set_drvdata(&wm8350_regulator_devices[i], wm8350);
		ret = platform_device_register(&wm8350_regulator_devices[i]);
		if (ret < 0)
			goto unwind;
	}
#endif	// CONFIG_MACH_CANOPUS

	/* now register other clients */
	return s3c_wm8350_device_register(wm8350);
unwind:
	for (i--; i >= 0; i--)
		platform_device_unregister(&wm8350_regulator_devices[i]);

	return ret;
}
Beispiel #10
0
static void wm8350_init_charger(struct wm8350 *wm8350)
{
	
	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT,
			    wm8350_charger_handler, NULL);
	wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT);
	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD,
			    wm8350_charger_handler, NULL);
	wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD);
	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL,
			    wm8350_charger_handler, NULL);
	wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL);
	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_TO,
			    wm8350_charger_handler, NULL);
	wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_TO);
	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_END,
			    wm8350_charger_handler, NULL);
	wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_END);
	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_START,
			    wm8350_charger_handler, NULL);
	wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_START);
	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY,
			    wm8350_charger_handler, NULL);
	wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_FAST_RDY);
	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9,
			    wm8350_charger_handler, NULL);
	wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9);
	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1,
			    wm8350_charger_handler, NULL);
	wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1);
	wm8350_register_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85,
			    wm8350_charger_handler, NULL);
	wm8350_unmask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85);

	
	wm8350_register_irq(wm8350, WM8350_IRQ_EXT_USB_FB,
			    wm8350_charger_handler, NULL);
	wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_USB_FB);
	wm8350_register_irq(wm8350, WM8350_IRQ_EXT_WALL_FB,
			    wm8350_charger_handler, NULL);
	wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_WALL_FB);
	wm8350_register_irq(wm8350, WM8350_IRQ_EXT_BAT_FB,
			    wm8350_charger_handler, NULL);
	wm8350_unmask_irq(wm8350, WM8350_IRQ_EXT_BAT_FB);
}
int wm8350_init(struct wm8350 *wm8350)
{
    int ret = 0;

    /* register regulator and set constraints */
    wm8350_device_register_pmic(wm8350);
    set_regulator_constraints(wm8350);
#ifdef NOT_PORTED_TO_IMX37
    wm8350_device_register_rtc(wm8350);
    wm8350_device_register_wdg(wm8350);
    wm8350_device_register_power(wm8350);
#endif
    mxc_init_wm8350();

    /*Note: Needs to be moved into a regulator function. */
    /* Configuring -- GPIO 7 pin */
    if (wm8350_gpio_config(wm8350, 7, WM8350_GPIO_DIR_OUT, 0,
                           WM8350_GPIO_ACTIVE_LOW, WM8350_GPIO_PULL_NONE,
                           WM8350_GPIO_INVERT_OFF,
                           WM8350_GPIO_DEBOUNCE_OFF) == 0)
        wm8350_gpio_set_status(wm8350, 7, 1);
    else
        printk(KERN_ERR "Error in setting Wolfson GPIO pin 7 \n");
    /* enable gpio4:USB_VBUS_EN */
    ret =
        wm8350_gpio_config(wm8350, 4, WM8350_GPIO_DIR_IN,
                           WM8350_GPIO4_MR_IN, WM8350_GPIO_ACTIVE_HIGH,
                           WM8350_GPIO_PULL_UP, WM8350_GPIO_INVERT_OFF,
                           WM8350_GPIO_DEBOUNCE_OFF);
    if (ret)
        printk(KERN_ERR "Error in setting USB VBUS enable pin\n");

    /*PMIC RDY*/
    if (wm8350_gpio_config(wm8350, 9, WM8350_GPIO_DIR_OUT, WM8350_GPIO9_GPIO_OUT,
                           WM8350_GPIO_ACTIVE_LOW, WM8350_GPIO_PULL_NONE,
                           WM8350_GPIO_INVERT_OFF, WM8350_GPIO_DEBOUNCE_OFF) == 0)
        wm8350_gpio_set_status(wm8350, 9, 1);
    else
        printk(KERN_ERR "Error in setting Wolfson GPIO pin 9 \n");

    /* register sound */
    printk("Registering imx37_snd_device");
    imx_snd_device = platform_device_alloc("wm8350-imx-3stack-audio", -1);
    if (!imx_snd_device) {
        ret = -ENOMEM;
        goto err;
    }
    imx_snd_device->dev.platform_data = &imx_3stack_audio_platform_data;
    platform_set_drvdata(imx_snd_device, &wm8350->audio);
    ret = platform_device_add(imx_snd_device);
    if (ret)
        goto snd_err;

    /* set up PMIC IRQ (active high) to i.MX32ADS */
    printk("Registering PMIC INT");
    INIT_WORK(&wm8350->work, wm8350_irq_work);
    wm8350_reg_unlock(wm8350);
    wm8350_set_bits(wm8350, WM8350_SYSTEM_CONTROL_1, WM8350_IRQ_POL);
    wm8350_reg_lock(wm8350);
    set_irq_type(MXC_PMIC_INT_LINE, IRQT_RISING);
    ret = request_irq(MXC_PMIC_INT_LINE, wm8350_irq_handler,
                      IRQF_DISABLED, "wm8350-pmic", wm8350);
    if (ret != 0) {
        printk(KERN_ERR "wm8350: cant request irq %d\n",
               MXC_PMIC_INT_LINE);
        goto err;
    }
    wm8350->nirq = MXC_PMIC_INT_LINE;

    set_irq_wake(MXC_PMIC_INT_LINE, 1);

#ifdef NOT_PORTED_TO_IMX37
    printk("Configuring WM8350 GPIOS");
    config_gpios(wm8350);
    config_hibernate(wm8350);
#endif

    /* Sw1 --> PWR_ON */
    printk("Registering and unmasking the WM8350 wakeup key\n");
    wm8350_register_irq(wm8350, WM8350_IRQ_WKUP_ONKEY,
                        imx37_3stack_switch_handler, NULL);
    wm8350_unmask_irq(wm8350, WM8350_IRQ_WKUP_ONKEY);

    /* unmask all & clear sticky */
    printk("Unmasking WM8350 local interrupts\n");
    wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0x3ffe);
    schedule_work(&wm8350->work);

#if BATTERY
    /* not much use without a battery atm */
    wm8350_init_battery(wm8350);
#endif

    printk("Exiting normally from wm8350_init()");
    return ret;
snd_err:
    platform_device_put(imx_snd_device);

err:
    printk("wm8350_init() FAILED");
    kfree(wm8350->reg_cache);
    return ret;
}
Beispiel #12
0
static int wm8350_rtc_probe(struct platform_device *pdev)
{
	struct wm8350 *wm8350 = platform_get_drvdata(pdev);
	struct wm8350_rtc *wm_rtc = &wm8350->rtc;
	int ret = 0;
	u16 timectl, power5;

	timectl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL);
	if (timectl & WM8350_RTC_BCD) {
		dev_err(&pdev->dev, "RTC BCD mode not supported\n");
		return -EINVAL;
	}
	if (timectl & WM8350_RTC_12HR) {
		dev_err(&pdev->dev, "RTC 12 hour mode not supported\n");
		return -EINVAL;
	}

	/* enable the RTC if it's not already enabled */
	power5 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5);
	if (!(power5 &  WM8350_RTC_TICK_ENA)) {
		dev_info(wm8350->dev, "Starting RTC\n");

		wm8350_reg_unlock(wm8350);

		ret = wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5,
				      WM8350_RTC_TICK_ENA);
		if (ret < 0) {
			dev_err(&pdev->dev, "failed to enable RTC: %d\n", ret);
			return ret;
		}

		wm8350_reg_lock(wm8350);
	}

	if (timectl & WM8350_RTC_STS) {
		int retries;

		ret = wm8350_clear_bits(wm8350, WM8350_RTC_TIME_CONTROL,
					WM8350_RTC_SET);
		if (ret < 0) {
			dev_err(&pdev->dev, "failed to start: %d\n", ret);
			return ret;
		}

		retries = WM8350_SET_TIME_RETRIES;
		do {
			timectl = wm8350_reg_read(wm8350,
						  WM8350_RTC_TIME_CONTROL);
		} while (timectl & WM8350_RTC_STS && retries--);

		if (retries == 0) {
			dev_err(&pdev->dev, "failed to start: timeout\n");
			return -ENODEV;
		}
	}

	device_init_wakeup(&pdev->dev, 1);

	wm_rtc->rtc = rtc_device_register("wm8350", &pdev->dev,
					  &wm8350_rtc_ops, THIS_MODULE);
	if (IS_ERR(wm_rtc->rtc)) {
		ret = PTR_ERR(wm_rtc->rtc);
		dev_err(&pdev->dev, "failed to register RTC: %d\n", ret);
		return ret;
	}

	wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC);
	wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_PER);

	wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC,
			    wm8350_rtc_update_handler, NULL);

	wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM,
			    wm8350_rtc_alarm_handler, NULL);
	wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_ALM);

	return 0;
}