#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
*/
int wm8350_reg_lock(struct wm8350 *wm8350)
{
- u16 key = WM8350_LOCK_KEY;
int ret;
+ mutex_lock(®_lock_mutex);
+
ldbg(__func__);
- mutex_lock(&io_mutex);
- ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key);
+
+ ret = wm8350_reg_write(wm8350, WM8350_SECURITY, WM8350_LOCK_KEY);
if (ret)
dev_err(wm8350->dev, "lock failed\n");
- mutex_unlock(&io_mutex);
+
+ wm8350->unlocked = false;
+
+ mutex_unlock(®_lock_mutex);
+
return ret;
}
EXPORT_SYMBOL_GPL(wm8350_reg_lock);
*/
int wm8350_reg_unlock(struct wm8350 *wm8350)
{
- u16 key = WM8350_UNLOCK_KEY;
int ret;
+ mutex_lock(®_lock_mutex);
+
ldbg(__func__);
- mutex_lock(&io_mutex);
- ret = wm8350_write(wm8350, WM8350_SECURITY, 1, &key);
+
+ ret = wm8350_reg_write(wm8350, WM8350_SECURITY, WM8350_UNLOCK_KEY);
if (ret)
dev_err(wm8350->dev, "unlock failed\n");
- mutex_unlock(&io_mutex);
+
+ wm8350->unlocked = true;
+
+ mutex_unlock(®_lock_mutex);
+
return ret;
}
EXPORT_SYMBOL_GPL(wm8350_reg_unlock);
#include <linux/regmap.h>
#include <linux/slab.h>
-static const struct regmap_config wm8350_regmap = {
- .reg_bits = 8,
- .val_bits = 16,
-};
-
static int wm8350_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
{ 0x0000, 0x0000, 0x0000 }, /* R254 */
{ 0x0000, 0x0000, 0x0000 }, /* R255 */
};
+
+static bool wm8350_readable(struct device *dev, unsigned int reg)
+{
+ return wm8350_reg_io_map[reg].readable;
+}
+
+static bool wm8350_writeable(struct device *dev, unsigned int reg)
+{
+ struct wm8350 *wm8350 = dev_get_drvdata(dev);
+
+ if (!wm8350->unlocked) {
+ if ((reg >= WM8350_GPIO_FUNCTION_SELECT_1 &&
+ reg <= WM8350_GPIO_FUNCTION_SELECT_4) ||
+ (reg >= WM8350_BATTERY_CHARGER_CONTROL_1 &&
+ reg <= WM8350_BATTERY_CHARGER_CONTROL_3))
+ return false;
+ }
+
+ return wm8350_reg_io_map[reg].writable;
+}
+
+static bool wm8350_volatile(struct device *dev, unsigned int reg)
+{
+ return wm8350_reg_io_map[reg].vol;
+}
+
+static bool wm8350_precious(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8350_SYSTEM_INTERRUPTS:
+ case WM8350_INT_STATUS_1:
+ case WM8350_INT_STATUS_2:
+ case WM8350_POWER_UP_INT_STATUS:
+ case WM8350_UNDER_VOLTAGE_INT_STATUS:
+ case WM8350_OVER_CURRENT_INT_STATUS:
+ case WM8350_GPIO_INT_STATUS:
+ case WM8350_COMPARATOR_INT_STATUS:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+const struct regmap_config wm8350_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+
+ .cache_type = REGCACHE_RBTREE,
+
+ .max_register = WM8350_MAX_REGISTER,
+ .readable_reg = wm8350_readable,
+ .writeable_reg = wm8350_writeable,
+ .volatile_reg = wm8350_volatile,
+ .precious_reg = wm8350_precious,
+};
#include <linux/mutex.h>
#include <linux/interrupt.h>
#include <linux/completion.h>
+#include <linux/regmap.h>
#include <linux/mfd/wm8350/audio.h>
#include <linux/mfd/wm8350/gpio.h>
#define WM8350_MAX_REGISTER 0xFF
+#define WM8350_UNLOCK_KEY 0x0013
+#define WM8350_LOCK_KEY 0x0000
+
/*
* Field Definitions.
*/
#define WM8350_NUM_IRQ_REGS 7
+extern const struct regmap_config wm8350_regmap;
struct wm8350_reg_access {
u16 readable; /* Mask of readable bits */
u16 writable; /* Mask of writable bits */
extern const u16 wm8352_mode3_defaults[];
struct wm8350;
-struct regmap;
struct wm8350_hwmon {
struct platform_device *pdev;
/* device IO */
struct regmap *regmap;
u16 *reg_cache;
+ bool unlocked;
struct mutex auxadc_mutex;
struct completion auxadc_done;