Exemplo n.º 1
0
/**
 * wm831x_reg_unlock: Unlock user keyed registers
 *
 * The WM831x has a user key preventing writes to particularly
 * critical registers.  This function locks those registers,
 * preventing spurious writes.
 */
int wm831x_reg_unlock(struct wm831x *wm831x)
{
	int ret;

	/* 0x9716 is the value required to unlock the registers */
	ret = wm831x_reg_write(wm831x, WM831X_SECURITY_KEY, 0x9716);
	if (ret == 0) {
		dev_vdbg(wm831x->dev, "Registers unlocked\n");

		mutex_lock(&wm831x->io_lock);
		WARN_ON(!wm831x->locked);
		wm831x->locked = 0;
		mutex_unlock(&wm831x->io_lock);
	}

	return ret;
}
Exemplo n.º 2
0
/**
 * wm831x_reg_unlock: Unlock user keyed registers
 *
 * The WM831x has a user key preventing writes to particularly
 * critical registers.  This function locks those registers,
 * allowing writes to them.
 */
void wm831x_reg_lock(struct wm831x *wm831x)
{
	int ret;

	ret = wm831x_reg_write(wm831x, WM831X_SECURITY_KEY, 0);
	if (ret == 0) {
		dev_vdbg(wm831x->dev, "Registers locked\n");

		mutex_lock(&wm831x->io_lock);
		WARN_ON(wm831x->locked);
		wm831x->locked = 1;
		mutex_unlock(&wm831x->io_lock);
	} else {
		dev_err(wm831x->dev, "Failed to lock registers: %d\n", ret);
	}

}
Exemplo n.º 3
0
static int wm831x_mask_interrupt(struct wm831x *Wm831x)
{
	/**************************clear interrupt********************/
	wm831x_reg_write(Wm831x,WM831X_INTERRUPT_STATUS_1,0xffff);
	wm831x_reg_write(Wm831x,WM831X_INTERRUPT_STATUS_2,0xffff);
	wm831x_reg_write(Wm831x,WM831X_INTERRUPT_STATUS_3,0xffff);
	wm831x_reg_write(Wm831x,WM831X_INTERRUPT_STATUS_4,0xffff);
	wm831x_reg_write(Wm831x,WM831X_INTERRUPT_STATUS_5,0xffff);
	
	wm831x_reg_write(Wm831x,WM831X_SYSTEM_INTERRUPTS_MASK,0xbedc); //mask interrupt which not used
	return 0;
	/*****************************************************************/
}
Exemplo n.º 4
0
static int wm831x_i2c_resume(struct i2c_client *i2c)
{
	struct wm831x *wm831x = i2c_get_clientdata(i2c);
	int i;
	//set some intterupt again while resume 
	for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) {
		//printk("irq_masks_cur[%d]=0x%x\n",i,wm831x->irq_masks_cur[i]);

		if (wm831x->irq_masks_cur[i] != wm831x->irq_masks_cache[i]) {
			wm831x->irq_masks_cache[i] = wm831x->irq_masks_cur[i];
			wm831x_reg_write(wm831x,
					 WM831X_INTERRUPT_STATUS_1_MASK + i,
					 wm831x->irq_masks_cur[i]);
		}
	
	}

	return 0;
}
Exemplo n.º 5
0
static int wm831x_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(dev);
	struct wm831x *wm831x = wm831x_rtc->wm831x;
	int ret;
	unsigned long time;

	ret = rtc_tm_to_time(&alrm->time, &time);
	if (ret < 0) {
		dev_err(dev, "Failed to convert time: %d\n", ret);
		return ret;
	}

	ret = wm831x_rtc_stop_alarm(wm831x_rtc);
	if (ret < 0) {
		dev_err(dev, "Failed to stop alarm: %d\n", ret);
		return ret;
	}

	ret = wm831x_reg_write(wm831x, WM831X_RTC_ALARM_1,
			       (time >> 16) & 0xffff);
	if (ret < 0) {
		dev_err(dev, "Failed to write ALARM_1: %d\n", ret);
		return ret;
	}

	ret = wm831x_reg_write(wm831x, WM831X_RTC_ALARM_2, time & 0xffff);
	if (ret < 0) {
		dev_err(dev, "Failed to write ALARM_2: %d\n", ret);
		return ret;
	}

	if (alrm->enabled) {
		ret = wm831x_rtc_start_alarm(wm831x_rtc);
		if (ret < 0) {
			dev_err(dev, "Failed to start alarm: %d\n", ret);
			return ret;
		}
	}

	return 0;
}
static int wm831x_wdt_ping(struct watchdog_device *wdt_dev)
{
	struct wm831x_wdt_drvdata *driver_data = watchdog_get_drvdata(wdt_dev);
	struct wm831x *wm831x = driver_data->wm831x;
	int ret;
	u16 reg;

	mutex_lock(&driver_data->lock);

	if (driver_data->update_gpio) {
		gpio_set_value_cansleep(driver_data->update_gpio,
					driver_data->update_state);
		driver_data->update_state = !driver_data->update_state;
		ret = 0;
		goto out;
	}

	reg = wm831x_reg_read(wm831x, WM831X_WATCHDOG);

	if (!(reg & WM831X_WDOG_RST_SRC)) {
		dev_err(wm831x->dev, "Hardware watchdog update unsupported\n");
		ret = -EINVAL;
		goto out;
	}

	reg |= WM831X_WDOG_RESET;

	ret = wm831x_reg_unlock(wm831x);
	if (ret == 0) {
		ret = wm831x_reg_write(wm831x, WM831X_WATCHDOG, reg);
		wm831x_reg_lock(wm831x);
	} else {
		dev_err(wm831x->dev, "Failed to unlock security key: %d\n",
			ret);
	}

out:
	mutex_unlock(&driver_data->lock);

	return ret;
}
Exemplo n.º 7
0
static int wm831x_wdt_kick(struct wm831x *wm831x)
{
    int ret;
    u16 reg;

    mutex_lock(&wdt_mutex);

    if (update_gpio) {
        gpio_set_value_cansleep(update_gpio, update_state);
        update_state = !update_state;
        ret = 0;
        goto out;
    }


    reg = wm831x_reg_read(wm831x, WM831X_WATCHDOG);

    if (!(reg & WM831X_WDOG_RST_SRC)) {
        dev_err(wm831x->dev, "Hardware watchdog update unsupported\n");
        ret = -EINVAL;
        goto out;
    }

    reg |= WM831X_WDOG_RESET;

    ret = wm831x_reg_unlock(wm831x);
    if (ret == 0) {
        ret = wm831x_reg_write(wm831x, WM831X_WATCHDOG, reg);
        wm831x_reg_lock(wm831x);
    } else {
        dev_err(wm831x->dev, "Failed to unlock security key: %d\n",
                ret);
    }

out:
    mutex_unlock(&wdt_mutex);

    return ret;
}
static int wm831x_low_power_detection(struct wm831x *wm831x)
{
	wm831x_reg_write(wm831x,WM831X_AUXADC_CONTROL,0x803f);     //open adc 
	wm831x_reg_write(wm831x,WM831X_AUXADC_CONTROL,0xd03f);
	wm831x_reg_write(wm831x,WM831X_AUXADC_SOURCE,0x0001);
	
	wm831x_reg_write(wm831x,WM831X_COMPARATOR_CONTROL,0x0001);
	wm831x_reg_write(wm831x,WM831X_COMPARATOR_1,0x2910);   //set the low power is 3.4v
	
	wm831x_reg_write(wm831x,WM831X_INTERRUPT_STATUS_1_MASK,0x99ee);
	wm831x_set_bits(wm831x,WM831X_SYSTEM_INTERRUPTS_MASK,0x0100,0x0000);
	if (wm831x_reg_read(wm831x,WM831X_AUXADC_DATA)< 0x1900){
		printk("The vbat is too low.\n");
		wm831x_device_shutdown(wm831x);
	}
	return 0;
}
Exemplo n.º 9
0
static int wm831x_low_power_detection(struct wm831x *wm831x)
{
	#ifdef CONFIG_BATTERY_RK30_VOL3V8
	wm831x_reg_write(wm831x,WM831X_SYSTEM_INTERRUPTS_MASK,0xbe5c); 	
	wm831x_set_bits(wm831x,WM831X_INTERRUPT_STATUS_1_MASK,0x8000,0x0000);	
	wm831x_set_bits(wm831x,WM831X_SYSVDD_CONTROL ,0xc077,0x0035);		//set pvdd low voltage is 3.1v hi voltage is 3.3v 
	#else
	wm831x_reg_write(wm831x,WM831X_AUXADC_CONTROL,0x803f);     //open adc 
	wm831x_reg_write(wm831x,WM831X_AUXADC_CONTROL,0xd03f);
	wm831x_reg_write(wm831x,WM831X_AUXADC_SOURCE,0x0001);
	
	wm831x_reg_write(wm831x,WM831X_COMPARATOR_CONTROL,0x0001);
	wm831x_reg_write(wm831x,WM831X_COMPARATOR_1,0x2844);   //set the low power is 3.1v
	
	wm831x_reg_write(wm831x,WM831X_INTERRUPT_STATUS_1_MASK,0x99ee);
	wm831x_set_bits(wm831x,WM831X_SYSTEM_INTERRUPTS_MASK,0x0100,0x0000);
	if (wm831x_reg_read(wm831x,WM831X_AUXADC_DATA)< 0x1844){
		printk("The vbat is too low.\n");
		wm831x_device_shutdown(wm831x);
	}
	#endif
	return 0;	
}
Exemplo n.º 10
0
static int __devinit wm831x_spi_probe(struct spi_device *spi)
{
	struct wm831x *wm831x;
	enum wm831x_parent type;
	int ret,gpio,irq;
	
	/* Currently SPI support for ID tables is unmerged, we're faking it */
	if (strcmp(spi->modalias, "wm8310") == 0)
		type = WM8310;
	else if (strcmp(spi->modalias, "wm8311") == 0)
		type = WM8311;
	else if (strcmp(spi->modalias, "wm8312") == 0)
		type = WM8312;
	else if (strcmp(spi->modalias, "wm8320") == 0)
		type = WM8320;
	else if (strcmp(spi->modalias, "wm8321") == 0)
		type = WM8321;
	else if (strcmp(spi->modalias, "wm8325") == 0)
		type = WM8325;
	else {
		dev_err(&spi->dev, "Unknown device type\n");
		return -EINVAL;
	}

	wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
	if (wm831x == NULL)
		return -ENOMEM;

	spi->bits_per_word = 16;
	spi->mode = SPI_MODE_0;

	gpio = spi->irq;
	ret = gpio_request(gpio, "wm831x");
	if (ret) {
		printk( "failed to request rk gpio irq for wm831x \n");
		return ret;
	}
	gpio_pull_updown(gpio, GPIOPullUp);
	if (ret) {
	    printk("failed to pull up gpio irq for wm831x \n");
		return ret;
	}	
	irq = gpio_to_irq(gpio);

	dev_set_drvdata(&spi->dev, wm831x);
	wm831x->dev = &spi->dev;
	wm831x->control_data = spi;
	wm831x->read_dev = wm831x_spi_read_device;
	wm831x->write_dev = wm831x_spi_write_device;
	gwm831x = wm831x;
	mutex_init(&wm831x->io_lock);
	
	wm831x_init(wm831x);
	
	wm831x->irq_wq = create_singlethread_workqueue("wm831x-irq");
	if (!wm831x->irq_wq) {
		dev_err(wm831x->dev, "Failed to allocate IRQ worker\n");
		return -ESRCH;
	}
	
	INIT_WORK(&wm831x->irq_work, wm831x_irq_worker);
	wake_lock_init(&wm831x->irq_wake, WAKE_LOCK_SUSPEND, "wm831x_irq_wake");

	ret = request_threaded_irq(irq, wm831x_irq_thread, NULL, 
				 IRQF_TRIGGER_LOW,
				   "wm831x", wm831x);
	if (ret != 0) {
		dev_err(wm831x->dev, "Failed to request IRQ %d: %d\n",
			wm831x->irq, ret);
		return ret;
	}
	wm831x->irq = irq;
	enable_irq_wake(irq); // so wm831x irq can wake up system
	/* only support on intterupt */
	wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0xefff);
	wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1_MASK, 0xefff);

	setup_timer(&irq_timer, wm831x_irq_timer, (unsigned long)wm831x);
	irq_timer.expires  = jiffies+2000;
	add_timer(&irq_timer);

	return 0;
	//return wm831x_device_init(wm831x, type, irq);
}
Exemplo n.º 11
0
void wm831x_power_off(void)
{
	wm831x_reg_write(gwm831x, WM831X_POWER_STATE, 0);//power off
}
Exemplo n.º 12
0
static int wm831x_init(struct wm831x *wm831x)
{

/*wm831x_pre_init*/
	wm831x_reg_write(wm831x, WM831X_POWER_STATE, 0x8804);	//900ma
	
/*wm831x_irq_init:irq=252,180 mask irq*/
	wm831x_reg_write(wm831x, 0x4019, 0xffff);	
	wm831x_reg_write(wm831x, 0x401a, 0xffff);	
	wm831x_reg_write(wm831x, 0x401b, 0xffff);	
	wm831x_reg_write(wm831x, 0x401c, 0xffff);	
	wm831x_reg_write(wm831x, 0x401d, 0xffff);	
	wm831x_reg_write(wm831x, 0x4018, 0xffff);//wm831x_reg_write(wm831x, 0x4018, 0x0);	
	wm831x_reg_write(wm831x, 0x4019, 0xffff);	

/*regulator: DCDC1: 600 <--> 1800 mV */
	//wm831x_reg_write(wm831x, 0x401c, 0xfffe);
	//wm831x_reg_write(wm831x, 0x401c, 0xfefe);

/*regulator: DCDC2: 600 <--> 1800 mV*/ 
	//wm831x_reg_write(wm831x, 0x401c, 0xfefc);
	//wm831x_reg_write(wm831x, 0x401c, 0xfcfc);

/* regulator: DCDC3: 850 <--> 3400 mV */
	//wm831x_reg_write(wm831x, 0x401c, 0xfcf8);

/*regulator: DCDC4: 0 <--> 30000 mV */
	//wm831x_reg_write(wm831x, 0x401c, 0xfcf0);

/*wm831x_isink_enable*/
	wm831x_reg_write(wm831x, 0x404e, 0x8500);
	wm831x_reg_write(wm831x, 0x404e, 0xc500);

/*wm831x_isink_probe:line=203,irq=220*/
	//wm831x_reg_write(wm831x, 0x401a, 0xffbf);
	//wm831x_reg_write(wm831x, 0x401a, 0xff3f);


/*regulator: LDO1: 900 <--> 3300 mV */
	//wm831x_reg_write(wm831x, 0x401b, 0xfffe);

/*regulator: LDO2: 900 <--> 3300 mV*/ 
	//wm831x_reg_write(wm831x, 0x401b, 0xfffc);

/*regulator: LDO3: 900 <--> 3300 mV */
	//wm831x_reg_write(wm831x, 0x401b, 0xfff8);

/*regulator: LDO4: 900 <--> 3300 mV */
	//wm831x_reg_write(wm831x, 0x401b, 0xfff0);

/* regulator: LDO5: 900 <--> 3300 mV */
	//wm831x_reg_write(wm831x, 0x401b, 0xffe0);

/*regulator: LDO6: 900 <--> 3300 mV */
	//wm831x_reg_write(wm831x, 0x401b, 0xffc0);

/*regulator: LDO7: 1000 <--> 3500 mV */
	//wm831x_reg_write(wm831x, 0x401b, 0xff80);

/*regulator: LDO8: 1000 <--> 3500 mV */
	//wm831x_reg_write(wm831x, 0x401b, 0xff00);

/*regulator: LDO9: 1000 <--> 3500 mV */
	//wm831x_reg_write(wm831x, 0x401b, 0xfe00);

/*regulator: LDO10: 1000 <--> 3500 mV */
	//wm831x_reg_write(wm831x, 0x401b, 0xfc00);

/*regulator: LDO11: 1200 <--> 1550 mV */
	wm831x_reg_write(wm831x, 0x4008, 0x9716);
	wm831x_reg_write(wm831x, 0x4006, 0x8463);

/*wm831x_post_init set dcdc3=3000000mV end*/
	wm831x_reg_write(wm831x, 0x4051, 0xfa49);
	wm831x_reg_write(wm831x, 0x4062, 0x2156);
	

/*wm831x_post_init set ldo10=3000000mV end*/
	wm831x_reg_write(wm831x, 0x4084, 0x201a);

/*wm831x_post_init set dcdc2=1300000mV end8*/
	wm831x_reg_write(wm831x, 0x405d, 0x4140);

/* wm831x_post_init set dcdc1=1800000mV end*/
	wm831x_reg_write(wm831x, 0x4058, 0x6168);

/*wm831x_post_init set ldo1=1800000mV end*/
	wm831x_reg_write(wm831x, 0x4069, 0x6010);

/*wm831x_post_init set ldo4=2500000mV end*/
	wm831x_reg_write(wm831x, 0x4072, 0x8017);

/*wm831x_post_init set ldo7=3300000mV end*/
	wm831x_reg_write(wm831x, 0x407b, 0xa01d);

/*wm831x_post_init set dcdc4=-22mV end*/
	wm831x_reg_write(wm831x, 0x4050, 0xf);

/*wm831x_post_init set ldo2=3000000mV end*/
	wm831x_reg_write(wm831x, 0x406c, 0x1c);
	wm831x_reg_write(wm831x, 0x4051, 0x24b);

/*wm831x_post_init set ldo3=1800000mV end*/
	wm831x_reg_write(wm831x, 0x406f, 0x10);
	wm831x_reg_write(wm831x, 0x4051, 0x24f);

/*wm831x_post_init set ldo5=3000000mV end*/
	wm831x_reg_write(wm831x, 0x4075, 0x1c);
	wm831x_reg_write(wm831x, 0x4051, 0x25f);

/*wm831x_post_init set ldo6=2800000mV end*/
	wm831x_reg_write(wm831x, 0x4078, 0x1a);
	wm831x_reg_write(wm831x, 0x4051, 0x27f);

/*wm831x_post_init set ldo8=1200000mV end*/
	wm831x_reg_write(wm831x, 0x407e, 0x4);
	wm831x_reg_write(wm831x, 0x4051, 0x2ff);

/*wm831x_post_init set ldo9=3000000mV end*/
	wm831x_reg_write(wm831x, 0x4081, 0x1a);
	wm831x_reg_write(wm831x, 0x4051, 0x3ff);

	wm831x_reg_write(wm831x, 0x4008, 0x0);

	wm831x_reg_write(wm831x, 0x4008, 0x9716);
	wm831x_reg_write(wm831x, 0x4064, 0x104);
	wm831x_reg_write(wm831x, 0x4008, 0x0);
	wm831x_reg_write(wm831x, 0x4050, 0x7);

/* backlight brightness=255*/
	wm831x_reg_write(wm831x, 0x404e, 0xc500);
	wm831x_reg_write(wm831x, 0x4050, 0xf);
	wm831x_reg_write(wm831x, 0x404e, 0xc535);
	wm831x_reg_write(wm831x, 0x404e, 0xc535);


/*wm831x-rtc wm831x-rtc: rtc core: registered wm831x as rtc0*/
	//wm831x_reg_write(wm831x, 0x4019, 0xeef7);
	//wm831x_reg_write(wm831x, 0x4019, 0xeef3);
	
/*wm831x_power_probe:wm831x_power initialized*/
	wm831x_reg_write(wm831x, 0x4008, 0x9716);
	wm831x_reg_write(wm831x, 0x404b, 0x8812);

	wm831x_reg_write(wm831x, 0x4008, 0x0);
	wm831x_reg_write(wm831x, 0x4008, 0x9716);
	wm831x_reg_write(wm831x, 0x4048, 0x9c21);

	wm831x_reg_write(wm831x, 0x4048, 0x9c21);

	wm831x_reg_write(wm831x, 0x4049, 0x44ff);
	wm831x_reg_write(wm831x, 0x4001, 0x57);
	wm831x_reg_write(wm831x, 0x4008, 0x0);	
	//wm831x_reg_write(wm831x, 0x4019, 0x6ef3);
	//wm831x_reg_write(wm831x, 0x4019, 0x2ef3);	
	
/*device-mapper: uevent: version 1.0.3*/
	wm831x_reg_write(wm831x, 0x402e, 0x8000);
	wm831x_reg_write(wm831x, 0x4014, 0x8);
	wm831x_reg_write(wm831x, 0x402f, 0x400);
	wm831x_reg_write(wm831x, 0x402e, 0xc000);

/*gpu: power on... done!*/
	wm831x_reg_write(wm831x, 0x402e, 0x0);
	wm831x_reg_write(wm831x, 0x4011, 0x2100);
	wm831x_reg_write(wm831x, 0x402e, 0x8000);
	wm831x_reg_write(wm831x, 0x402f, 0x200);
	wm831x_reg_write(wm831x, 0x402e, 0xc000);


/*wm831x_isink_is_enabled:line=85*/
/*wm831x-rtc wm831x-rtc: setting system clock to 1970-01-02 04:18:35 UTC (101915)*/
	wm831x_reg_write(wm831x, 0x402e, 0x0);
	wm831x_reg_write(wm831x, 0x4011, 0x100);

	wm831x_reg_write(wm831x, 0x402e, 0x8000);
	wm831x_reg_write(wm831x, 0x402f, 0x100);
	wm831x_reg_write(wm831x, 0x402e, 0xc000);
	wm831x_reg_write(wm831x, 0x4011, 0x100);
	wm831x_reg_write(wm831x, 0x402e, 0x0);

	printk("%s\n",__FUNCTION__);
	
}
Exemplo n.º 13
0
static int wm831x_wdt_probe(struct platform_device *pdev)
{
	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
	struct wm831x_pdata *chip_pdata;
	struct wm831x_watchdog_pdata *pdata;
	struct wm831x_wdt_drvdata *driver_data;
	struct watchdog_device *wm831x_wdt;
	int reg, ret, i;

	ret = wm831x_reg_read(wm831x, WM831X_WATCHDOG);
	if (ret < 0) {
		dev_err(wm831x->dev, "Failed to read watchdog status: %d\n",
			ret);
		goto err;
	}
	reg = ret;

	if (reg & WM831X_WDOG_DEBUG)
		dev_warn(wm831x->dev, "Watchdog is paused\n");

	driver_data = devm_kzalloc(&pdev->dev, sizeof(*driver_data),
				   GFP_KERNEL);
	if (!driver_data) {
		dev_err(wm831x->dev, "Unable to alloacate watchdog device\n");
		ret = -ENOMEM;
		goto err;
	}

	mutex_init(&driver_data->lock);
	driver_data->wm831x = wm831x;

	wm831x_wdt = &driver_data->wdt;

	wm831x_wdt->info = &wm831x_wdt_info;
	wm831x_wdt->ops = &wm831x_wdt_ops;
	watchdog_set_nowayout(wm831x_wdt, nowayout);
	watchdog_set_drvdata(wm831x_wdt, driver_data);

	reg = wm831x_reg_read(wm831x, WM831X_WATCHDOG);
	reg &= WM831X_WDOG_TO_MASK;
	for (i = 0; i < ARRAY_SIZE(wm831x_wdt_cfgs); i++)
		if (wm831x_wdt_cfgs[i].val == reg)
			break;
	if (i == ARRAY_SIZE(wm831x_wdt_cfgs))
		dev_warn(wm831x->dev,
			 "Unknown watchdog timeout: %x\n", reg);
	else
		wm831x_wdt->timeout = wm831x_wdt_cfgs[i].time;

	/* Apply any configuration */
	if (pdev->dev.parent->platform_data) {
		chip_pdata = pdev->dev.parent->platform_data;
		pdata = chip_pdata->watchdog;
	} else {
		pdata = NULL;
	}

	if (pdata) {
		reg &= ~(WM831X_WDOG_SECACT_MASK | WM831X_WDOG_PRIMACT_MASK |
			 WM831X_WDOG_RST_SRC);

		reg |= pdata->primary << WM831X_WDOG_PRIMACT_SHIFT;
		reg |= pdata->secondary << WM831X_WDOG_SECACT_SHIFT;
		reg |= pdata->software << WM831X_WDOG_RST_SRC_SHIFT;

		if (pdata->update_gpio) {
			ret = gpio_request_one(pdata->update_gpio,
					       GPIOF_DIR_OUT | GPIOF_INIT_LOW,
					       "Watchdog update");
			if (ret < 0) {
				dev_err(wm831x->dev,
					"Failed to request update GPIO: %d\n",
					ret);
				goto err;
			}

			driver_data->update_gpio = pdata->update_gpio;

			/* Make sure the watchdog takes hardware updates */
			reg |= WM831X_WDOG_RST_SRC;
		}

		ret = wm831x_reg_unlock(wm831x);
		if (ret == 0) {
			ret = wm831x_reg_write(wm831x, WM831X_WATCHDOG, reg);
			wm831x_reg_lock(wm831x);
		} else {
			dev_err(wm831x->dev,
				"Failed to unlock security key: %d\n", ret);
			goto err_gpio;
		}
	}

	ret = watchdog_register_device(&driver_data->wdt);
	if (ret != 0) {
		dev_err(wm831x->dev, "watchdog_register_device() failed: %d\n",
			ret);
		goto err_gpio;
	}

	dev_set_drvdata(&pdev->dev, driver_data);

	return 0;

err_gpio:
	if (driver_data->update_gpio)
		gpio_free(driver_data->update_gpio);
err:
	return ret;
}
Exemplo n.º 14
0
static int wm8325_post_init(struct wm831x *wm831x)
{
	int ret;

	/* Set GPIO1 as input ,active high, Hardware Enable1 Function */
	ret = wm831x_reg_write(wm831x, WM831X_GPIO1_CONTROL, \
			WM8325_GPIO1_CONFIG_VAL);
	if (0 > ret) {
		printk("func:%s, write wm831x gpio1 ctrl reg error.\n", __func__);
		goto out;
	}

	/* Set GPIO2 as input ,active high, Hardware Control1 Function */
	ret = wm831x_reg_write(wm831x, WM831X_GPIO2_CONTROL, \
			WM8325_GPIO2_CONFIG_VAL);
	if (0 > ret) {
		printk("func:%s, write wm831x gpio2 ctrl reg error.\n", __func__);
		goto out;
	}

	/* Set GPIO3 as input ,active high, DVS1 Function */
	ret = wm831x_reg_write(wm831x, WM831X_GPIO3_CONTROL, \
			WM8325_GPIO3_CONFIG_VAL);
	if (0 > ret) {
		printk("func:%s, write wm831x gpio3 ctrl reg error.\n", __func__);
		goto out;
	}

	/* Set DCDC1 hardware controlled by Hardware Control1 */
	ret = wm831x_reg_write(wm831x, WM831X_DC1_CONTROL_2, \
			WM831X_DC1_CONTROL_2_VAL);
	if (0 > ret) {
		printk("func:%s, write wm831x dc1 ctrl2 reg error.\n", __func__);
		goto out;
	}

	/* Set DCDC2 hardware controlled by Hardware Control1 */
	ret = wm831x_reg_write(wm831x, WM831X_DC2_CONTROL_2, \
			WM831X_DC2_CONTROL_2_VAL);
	if (0 > ret) {
		printk("func:%s, write wm831x dc2 ctrl2 reg error.\n", __func__);
		goto out;
	}

	/* Set DCDC1 controlled by DVS1, DC1_DVS_VSEL=0.95V */
	ret = wm831x_reg_write(wm831x, WM831X_DC1_DVS_CONTROL, \
			WM831X_DC1_DVS_CONTROL_VAL);
	if (0 > ret) {
		printk("func:%s, write wm831x dc1 dvs reg error.\n", __func__);
		goto out;
	}

	/* Set DCDC2 controlled by DVS1, DC2_DVS_VSEL=0.85V */
	ret = wm831x_reg_write(wm831x, WM831X_DC2_DVS_CONTROL, \
			WM831X_DC2_DVS_CONTROL_VAL);
	if (0 > ret) {
		printk("func:%s, write wm831x dc2 dvs reg error.\n", __func__);
		goto out;
	}

	/* Set other LDOs hardware controlled by Hardware Control1,
	   and set other LDOs hardware enable function, accroding to board design
	*/
	/* Set LDO1 hardware controlled by Hardware Control1:low-pwr mode */
	ret = wm831x_reg_write(wm831x, WM831X_LDO1_CONTROL, \
			WM831X_LDO1_CONTROL_VAL);
	if (0 > ret) {
		printk("func:%s, write wm831x ldo1 ctrl reg error.\n", __func__);
		goto out;
	}

	/* Set LDO9 to 3.0V */
	ret = wm831x_reg_write(wm831x, WM831X_LDO9_ON_CONTROL, 0x1A);
	if (0 > ret) {
		printk("func:%s, write wm831x ldo9 ctrl reg error.\n", __func__);
		goto out;
	}
	return 0;

out:
	return ret;
}
Exemplo n.º 15
0
/*
 * Instantiate the generic non-control parts of the device.
 */
int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
{
	struct wm831x_pdata *pdata = wm831x->dev->platform_data;
	int rev, wm831x_num;
	enum wm831x_parent parent;
	int ret, i;

	mutex_init(&wm831x->io_lock);
	mutex_init(&wm831x->key_lock);
	dev_set_drvdata(wm831x->dev, wm831x);

	ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
	if (ret < 0) {
		dev_err(wm831x->dev, "Failed to read parent ID: %d\n", ret);
		goto err;
	}
	switch (ret) {
	case 0x6204:
	case 0x6246:
		break;
	default:
		dev_err(wm831x->dev, "Device is not a WM831x: ID %x\n", ret);
		ret = -EINVAL;
		goto err;
	}

	ret = wm831x_reg_read(wm831x, WM831X_REVISION);
	if (ret < 0) {
		dev_err(wm831x->dev, "Failed to read revision: %d\n", ret);
		goto err;
	}
	rev = (ret & WM831X_PARENT_REV_MASK) >> WM831X_PARENT_REV_SHIFT;

	ret = wm831x_reg_read(wm831x, WM831X_RESET_ID);
	if (ret < 0) {
		dev_err(wm831x->dev, "Failed to read device ID: %d\n", ret);
		goto err;
	}

	/* Some engineering samples do not have the ID set, rely on
	 * the device being registered correctly.
	 */
	if (ret == 0) {
		dev_info(wm831x->dev, "Device is an engineering sample\n");
		ret = id;
	}

	switch (ret) {
	case WM8310:
		parent = WM8310;
		wm831x->num_gpio = 16;
		wm831x->charger_irq_wake = 1;
		if (rev > 0) {
			wm831x->has_gpio_ena = 1;
			wm831x->has_cs_sts = 1;
		}

		dev_info(wm831x->dev, "WM8310 revision %c\n", 'A' + rev);
		break;

	case WM8311:
		parent = WM8311;
		wm831x->num_gpio = 16;
		wm831x->charger_irq_wake = 1;
		if (rev > 0) {
			wm831x->has_gpio_ena = 1;
			wm831x->has_cs_sts = 1;
		}

		dev_info(wm831x->dev, "WM8311 revision %c\n", 'A' + rev);
		break;

	case WM8312:
		parent = WM8312;
		wm831x->num_gpio = 16;
		wm831x->charger_irq_wake = 1;
		if (rev > 0) {
			wm831x->has_gpio_ena = 1;
			wm831x->has_cs_sts = 1;
		}

		dev_info(wm831x->dev, "WM8312 revision %c\n", 'A' + rev);
		break;

	case WM8320:
		parent = WM8320;
		wm831x->num_gpio = 12;
		dev_info(wm831x->dev, "WM8320 revision %c\n", 'A' + rev);
		break;

	case WM8321:
		parent = WM8321;
		wm831x->num_gpio = 12;
		dev_info(wm831x->dev, "WM8321 revision %c\n", 'A' + rev);
		break;

	case WM8325:
		parent = WM8325;
		wm831x->num_gpio = 12;
		dev_info(wm831x->dev, "WM8325 revision %c\n", 'A' + rev);
		break;

	case WM8326:
		parent = WM8326;
		wm831x->num_gpio = 12;
		dev_info(wm831x->dev, "WM8326 revision %c\n", 'A' + rev);
		break;

	default:
		dev_err(wm831x->dev, "Unknown WM831x device %04x\n", ret);
		ret = -EINVAL;
		goto err;
	}

	/* This will need revisiting in future but is OK for all
	 * current parts.
	 */
	if (parent != id)
		dev_warn(wm831x->dev, "Device was registered as a WM%lx\n",
			 id);

	/* Bootstrap the user key */
	ret = wm831x_reg_read(wm831x, WM831X_SECURITY_KEY);
	if (ret < 0) {
		dev_err(wm831x->dev, "Failed to read security key: %d\n", ret);
		goto err;
	}
	if (ret != 0) {
		dev_warn(wm831x->dev, "Security key had non-zero value %x\n",
			 ret);
		wm831x_reg_write(wm831x, WM831X_SECURITY_KEY, 0);
	}
	wm831x->locked = 1;

	if (pdata && pdata->pre_init) {
		ret = pdata->pre_init(wm831x);
		if (ret != 0) {
			dev_err(wm831x->dev, "pre_init() failed: %d\n", ret);
			goto err;
		}
	}

	if (pdata) {
		for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) {
			if (!pdata->gpio_defaults[i])
				continue;

			wm831x_reg_write(wm831x,
					 WM831X_GPIO1_CONTROL + i,
					 pdata->gpio_defaults[i] & 0xffff);
		}
	}

	/* Multiply by 10 as we have many subdevices of the same type */
	if (pdata && pdata->wm831x_num)
		wm831x_num = pdata->wm831x_num * 10;
	else
		wm831x_num = -1;

	ret = wm831x_irq_init(wm831x, irq);
	if (ret != 0)
		goto err;

	wm831x_auxadc_init(wm831x);

	/* The core device is up, instantiate the subdevices. */
	switch (parent) {
	case WM8310:
		ret = mfd_add_devices(wm831x->dev, wm831x_num,
				      wm8310_devs, ARRAY_SIZE(wm8310_devs),
				      NULL, wm831x->irq_base);
		break;

	case WM8311:
		ret = mfd_add_devices(wm831x->dev, wm831x_num,
				      wm8311_devs, ARRAY_SIZE(wm8311_devs),
				      NULL, wm831x->irq_base);
		if (!pdata || !pdata->disable_touch)
			mfd_add_devices(wm831x->dev, wm831x_num,
					touch_devs, ARRAY_SIZE(touch_devs),
					NULL, wm831x->irq_base);
		break;

	case WM8312:
		ret = mfd_add_devices(wm831x->dev, wm831x_num,
				      wm8312_devs, ARRAY_SIZE(wm8312_devs),
				      NULL, wm831x->irq_base);
		if (!pdata || !pdata->disable_touch)
			mfd_add_devices(wm831x->dev, wm831x_num,
					touch_devs, ARRAY_SIZE(touch_devs),
					NULL, wm831x->irq_base);
		break;

	case WM8320:
	case WM8321:
	case WM8325:
	case WM8326:
		ret = mfd_add_devices(wm831x->dev, wm831x_num,
				      wm8320_devs, ARRAY_SIZE(wm8320_devs),
				      NULL, wm831x->irq_base);
		break;

	default:
		/* If this happens the bus probe function is buggy */
		BUG();
	}

	if (ret != 0) {
		dev_err(wm831x->dev, "Failed to add children\n");
		goto err_irq;
	}

	/* The RTC can only be used if the 32.768kHz crystal is
	 * enabled; this can't be controlled by software at runtime.
	 */
	ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
	if (ret < 0) {
		dev_err(wm831x->dev, "Failed to read clock status: %d\n", ret);
		goto err_irq;
	}

	if (ret & WM831X_XTAL_ENA) {
		ret = mfd_add_devices(wm831x->dev, wm831x_num,
				      rtc_devs, ARRAY_SIZE(rtc_devs),
				      NULL, wm831x->irq_base);
		if (ret != 0) {
			dev_err(wm831x->dev, "Failed to add RTC: %d\n", ret);
			goto err_irq;
		}
	} else {
		dev_info(wm831x->dev, "32.768kHz clock disabled, no RTC\n");
	}

	if (pdata && pdata->backlight) {
		/* Treat errors as non-critical */
		ret = mfd_add_devices(wm831x->dev, wm831x_num, backlight_devs,
				      ARRAY_SIZE(backlight_devs), NULL,
				      wm831x->irq_base);
		if (ret < 0)
			dev_err(wm831x->dev, "Failed to add backlight: %d\n",
				ret);
	}

	wm831x_otp_init(wm831x);

	if (pdata && pdata->post_init) {
		ret = pdata->post_init(wm831x);
		if (ret != 0) {
			dev_err(wm831x->dev, "post_init() failed: %d\n", ret);
			goto err_irq;
		}
	}

	return 0;

err_irq:
	wm831x_irq_exit(wm831x);
err:
	mfd_remove_devices(wm831x->dev);
	kfree(wm831x);
	return ret;
}
Exemplo n.º 16
0
static int wm831x_pre_init(struct wm831x *parm)
{
	int ret;
	Wm831x = parm;
	printk("%s\n", __func__);

	#ifdef CONFIG_RK_CONFIG
	if(sram_gpio_init(get_port_config(pmic_slp).gpio, &pmic_sleep) < 0){
		printk(KERN_ERR "sram_gpio_init failed\n");
		return -EINVAL;
	}
	if(port_output_init(pmic_slp, 0, "pmic_slp") < 0){
		printk(KERN_ERR "port_output_init failed\n");
		return -EINVAL;
	}
	#else
	if(sram_gpio_init(PMU_POWER_SLEEP, &pmic_sleep) < 0){
		printk(KERN_ERR "sram_gpio_init failed\n");
		return -EINVAL;
	}

	gpio_request(PMU_POWER_SLEEP, "NULL");
	gpio_direction_output(PMU_POWER_SLEEP, GPIO_LOW);
	#endif

	#ifdef CONFIG_WM8326_VBAT_LOW_DETECTION
	#ifdef CONFIG_BATTERY_RK30_VOL3V8
	wm831x_set_bits(parm,WM831X_SYSVDD_CONTROL ,0xc077,0xc035);	  //pvdd power on dect vbat voltage
	printk("+++The vbat is too low+++\n");	
	#endif
	#endif
	
	ret = wm831x_reg_read(parm, WM831X_POWER_STATE) & 0xffff;
	wm831x_reg_write(parm, WM831X_POWER_STATE, (ret & 0xfff8) | 0x04);

	wm831x_set_bits(parm, WM831X_RTC_CONTROL, WM831X_RTC_ALAM_ENA_MASK, 0x0400);//enable rtc alam
	//BATT_FET_ENA = 1
	wm831x_reg_write(parm, WM831X_SECURITY_KEY, 0x9716);	// unlock security key
	wm831x_set_bits(parm, WM831X_RESET_CONTROL, 0x1003, 0x1001);
	ret = wm831x_reg_read(parm, WM831X_RESET_CONTROL) & 0xffff & UNLOCK_SECURITY_KEY;	// enternal reset active in sleep
//	printk("%s:WM831X_RESET_CONTROL=0x%x\n", __func__, ret);
	wm831x_reg_write(parm, WM831X_RESET_CONTROL, ret);

	wm831x_set_bits(parm,WM831X_DC1_ON_CONFIG ,0x0300,0x0000); //set dcdc mode is FCCM
	wm831x_set_bits(parm,WM831X_DC2_ON_CONFIG ,0x0300,0x0000);
	wm831x_set_bits(parm,WM831X_DC3_ON_CONFIG ,0x0300,0x0000);
	wm831x_set_bits(parm,0x4066,0x0300,0x0000);

#ifndef CONFIG_MACH_RK3066_SDK
	wm831x_set_bits(parm,WM831X_LDO10_CONTROL ,0x0040,0x0040);// set ldo10 in switch mode
#endif
	wm831x_set_bits(parm,WM831X_STATUS_LED_1 ,0xc300,0xc100);// set led1 on(in manual mode)
	wm831x_set_bits(parm,WM831X_STATUS_LED_2 ,0xc300,0xc000);//set led2 off(in manual mode)

	wm831x_set_bits(parm,WM831X_LDO5_SLEEP_CONTROL ,0xe000,0x2000);// set ldo5 is disable in sleep mode 
	wm831x_set_bits(parm,WM831X_LDO1_SLEEP_CONTROL ,0xe000,0x2000);// set ldo1 is disable in sleep mode 
	
	wm831x_reg_write(parm, WM831X_SECURITY_KEY, LOCK_SECURITY_KEY);	// lock security key

	return 0;
}
Exemplo n.º 17
0
static int __devinit wm831x_wdt_probe(struct platform_device *pdev)
{
    struct wm831x_pdata *chip_pdata;
    struct wm831x_watchdog_pdata *pdata;
    int reg, ret;

    if (wm831x) {
        dev_err(&pdev->dev, "wm831x watchdog already registered\n");
        return -EBUSY;
    }

    wm831x = dev_get_drvdata(pdev->dev.parent);

    ret = wm831x_reg_read(wm831x, WM831X_WATCHDOG);
    if (ret < 0) {
        dev_err(wm831x->dev, "Failed to read watchdog status: %d\n",
                ret);
        goto err;
    }
    reg = ret;

    if (reg & WM831X_WDOG_DEBUG)
        dev_warn(wm831x->dev, "Watchdog is paused\n");

    /* Apply any configuration */
    if (pdev->dev.parent->platform_data) {
        chip_pdata = pdev->dev.parent->platform_data;
        pdata = chip_pdata->watchdog;
    } else {
        pdata = NULL;
    }

    if (pdata) {
        reg &= ~(WM831X_WDOG_SECACT_MASK | WM831X_WDOG_PRIMACT_MASK |
                 WM831X_WDOG_RST_SRC);

        reg |= pdata->primary << WM831X_WDOG_PRIMACT_SHIFT;
        reg |= pdata->secondary << WM831X_WDOG_SECACT_SHIFT;
        reg |= pdata->software << WM831X_WDOG_RST_SRC_SHIFT;

        if (pdata->update_gpio) {
            ret = gpio_request(pdata->update_gpio,
                               "Watchdog update");
            if (ret < 0) {
                dev_err(wm831x->dev,
                        "Failed to request update GPIO: %d\n",
                        ret);
                goto err;
            }

            ret = gpio_direction_output(pdata->update_gpio, 0);
            if (ret != 0) {
                dev_err(wm831x->dev,
                        "gpio_direction_output returned: %d\n",
                        ret);
                goto err_gpio;
            }

            update_gpio = pdata->update_gpio;

            /* Make sure the watchdog takes hardware updates */
            reg |= WM831X_WDOG_RST_SRC;
        }

        ret = wm831x_reg_unlock(wm831x);
        if (ret == 0) {
            ret = wm831x_reg_write(wm831x, WM831X_WATCHDOG, reg);
            wm831x_reg_lock(wm831x);
        } else {
            dev_err(wm831x->dev,
                    "Failed to unlock security key: %d\n", ret);
            goto err_gpio;
        }
    }

    wm831x_wdt_miscdev.parent = &pdev->dev;

    ret = misc_register(&wm831x_wdt_miscdev);
    if (ret != 0) {
        dev_err(wm831x->dev, "Failed to register miscdev: %d\n", ret);
        goto err_gpio;
    }

    return 0;

err_gpio:
    if (update_gpio) {
        gpio_free(update_gpio);
        update_gpio = 0;
    }
err:
    return ret;
}