/** * 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; }
/** * 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); } }
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; /*****************************************************************/ }
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; }
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; }
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; }
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; }
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); }
void wm831x_power_off(void) { wm831x_reg_write(gwm831x, WM831X_POWER_STATE, 0);//power off }
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__); }
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; }
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; }
/* * 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; }
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; }
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; }