/*
* wm8350-core.c -- Device access for Wolfson WM8350
*
* Copyright 2007, 2008 Wolfson Microelectronics PLC.
*
* Author: Liam Girdwood, Mark Brown
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/bug.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/mfd/wm8350/core.h>
#include <linux/mfd/wm8350/audio.h>
#include <linux/mfd/wm8350/comparator.h>
#include <linux/mfd/wm8350/gpio.h>
#include <linux/mfd/wm8350/pmic.h>
#include <linux/mfd/wm8350/rtc.h>
#include <linux/mfd/wm8350/supply.h>
#include <linux/mfd/wm8350/wdt.h>
#define WM8350_UNLOCK_KEY 0x0013
#define WM8350_LOCK_KEY 0x0000
#define WM8350_CLOCK_CONTROL_1 0x28
#define WM8350_AIF_TEST 0x74
/* debug */
#define WM8350_BUS_DEBUG 0
#if WM8350_BUS_DEBUG
#define dump(regs, src) do { \
int i_; \
u16 *src_ = src; \
printk(KERN_DEBUG); \
for (i_ = 0; i_ < regs; i_++) \
printk(" 0x%4.4x", *src_++); \
printk("\n"); \
} while (0);
#else
#define dump(bytes, src)
#endif
#define WM8350_LOCK_DEBUG 0
#if WM8350_LOCK_DEBUG
#define ldbg(format, arg...) printk(format, ## arg)
#else
#define ldbg(format, arg...)
#endif
/*
* WM8350 Device IO
*/
static DEFINE_MUTEX(io_mutex);
static DEFINE_MUTEX(reg_lock_mutex);
static DEFINE_MUTEX(auxadc_mutex);
/* Perform a physical read from the device.
*/
static int wm8350_phys_read(struct wm8350 *wm8350, u8 reg, int num_regs,
u16 *dest)
{
int i, ret;
int bytes = num_regs * 2;
dev_dbg(wm8350->dev, "volatile read\n");
ret = wm8350->read_dev(wm8350, reg, bytes, (char *)dest);
for (i = reg; i < reg + num_regs; i++) {
/* Cache is CPU endian */
dest[i - reg] = be16_to_cpu(dest[i - reg]);
/* Satisfy non-volatile bits from cache */
dest[i - reg] &= wm8350_reg_io_map[i].vol;
dest[i - reg] |= wm8350->reg_cache[i];
/* Mask out non-readable bits */
dest[i - reg] &= wm8350_reg_io_map[i].readable;
}
dump(num_regs, dest);
return ret;
}
static int wm8350_read(struct wm8350 *wm8350, u8 reg, int num_regs, u16 *dest)
{
int i;
int end = reg + num_regs;
int ret = 0;
int bytes = num_regs * 2;
if (wm8350->read_dev == NULL)
return -ENODEV;
if ((reg + num_regs - 1) > WM8350_MAX_REGISTER) {
dev_err(wm8350->dev, "invalid reg %x\n",
reg + num_regs - 1);
return -EINVAL;
}
dev_dbg(wm83