mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 08:14:15 +08:00
37613fa5b7
There were a few files in the regmap code that did not have SPDX identifiers on them, so fix that up. At the same time, remove the "free form" text that specified the license of the file, as that is impossible for any tool to properly parse. Also, as Mark loves // comment markers, convert all of the headers to be the same to make things look consistent :) Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Mark Brown <broonie@kernel.org>
226 lines
5.0 KiB
C
226 lines
5.0 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
//
|
|
// Register map access API - SPMI support
|
|
//
|
|
// Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
|
|
//
|
|
// Based on regmap-i2c.c:
|
|
// Copyright 2011 Wolfson Microelectronics plc
|
|
// Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
|
|
|
|
#include <linux/regmap.h>
|
|
#include <linux/spmi.h>
|
|
#include <linux/module.h>
|
|
#include <linux/init.h>
|
|
|
|
static int regmap_spmi_base_read(void *context,
|
|
const void *reg, size_t reg_size,
|
|
void *val, size_t val_size)
|
|
{
|
|
u8 addr = *(u8 *)reg;
|
|
int err = 0;
|
|
|
|
BUG_ON(reg_size != 1);
|
|
|
|
while (val_size-- && !err)
|
|
err = spmi_register_read(context, addr++, val++);
|
|
|
|
return err;
|
|
}
|
|
|
|
static int regmap_spmi_base_gather_write(void *context,
|
|
const void *reg, size_t reg_size,
|
|
const void *val, size_t val_size)
|
|
{
|
|
const u8 *data = val;
|
|
u8 addr = *(u8 *)reg;
|
|
int err = 0;
|
|
|
|
BUG_ON(reg_size != 1);
|
|
|
|
/*
|
|
* SPMI defines a more bandwidth-efficient 'Register 0 Write' sequence,
|
|
* use it when possible.
|
|
*/
|
|
if (addr == 0 && val_size) {
|
|
err = spmi_register_zero_write(context, *data);
|
|
if (err)
|
|
goto err_out;
|
|
|
|
data++;
|
|
addr++;
|
|
val_size--;
|
|
}
|
|
|
|
while (val_size) {
|
|
err = spmi_register_write(context, addr, *data);
|
|
if (err)
|
|
goto err_out;
|
|
|
|
data++;
|
|
addr++;
|
|
val_size--;
|
|
}
|
|
|
|
err_out:
|
|
return err;
|
|
}
|
|
|
|
static int regmap_spmi_base_write(void *context, const void *data,
|
|
size_t count)
|
|
{
|
|
BUG_ON(count < 1);
|
|
return regmap_spmi_base_gather_write(context, data, 1, data + 1,
|
|
count - 1);
|
|
}
|
|
|
|
static const struct regmap_bus regmap_spmi_base = {
|
|
.read = regmap_spmi_base_read,
|
|
.write = regmap_spmi_base_write,
|
|
.gather_write = regmap_spmi_base_gather_write,
|
|
.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
|
|
.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
|
|
};
|
|
|
|
struct regmap *__regmap_init_spmi_base(struct spmi_device *sdev,
|
|
const struct regmap_config *config,
|
|
struct lock_class_key *lock_key,
|
|
const char *lock_name)
|
|
{
|
|
return __regmap_init(&sdev->dev, ®map_spmi_base, sdev, config,
|
|
lock_key, lock_name);
|
|
}
|
|
EXPORT_SYMBOL_GPL(__regmap_init_spmi_base);
|
|
|
|
struct regmap *__devm_regmap_init_spmi_base(struct spmi_device *sdev,
|
|
const struct regmap_config *config,
|
|
struct lock_class_key *lock_key,
|
|
const char *lock_name)
|
|
{
|
|
return __devm_regmap_init(&sdev->dev, ®map_spmi_base, sdev, config,
|
|
lock_key, lock_name);
|
|
}
|
|
EXPORT_SYMBOL_GPL(__devm_regmap_init_spmi_base);
|
|
|
|
static int regmap_spmi_ext_read(void *context,
|
|
const void *reg, size_t reg_size,
|
|
void *val, size_t val_size)
|
|
{
|
|
int err = 0;
|
|
size_t len;
|
|
u16 addr;
|
|
|
|
BUG_ON(reg_size != 2);
|
|
|
|
addr = *(u16 *)reg;
|
|
|
|
/*
|
|
* Split accesses into two to take advantage of the more
|
|
* bandwidth-efficient 'Extended Register Read' command when possible
|
|
*/
|
|
while (addr <= 0xFF && val_size) {
|
|
len = min_t(size_t, val_size, 16);
|
|
|
|
err = spmi_ext_register_read(context, addr, val, len);
|
|
if (err)
|
|
goto err_out;
|
|
|
|
addr += len;
|
|
val += len;
|
|
val_size -= len;
|
|
}
|
|
|
|
while (val_size) {
|
|
len = min_t(size_t, val_size, 8);
|
|
|
|
err = spmi_ext_register_readl(context, addr, val, len);
|
|
if (err)
|
|
goto err_out;
|
|
|
|
addr += len;
|
|
val += len;
|
|
val_size -= len;
|
|
}
|
|
|
|
err_out:
|
|
return err;
|
|
}
|
|
|
|
static int regmap_spmi_ext_gather_write(void *context,
|
|
const void *reg, size_t reg_size,
|
|
const void *val, size_t val_size)
|
|
{
|
|
int err = 0;
|
|
size_t len;
|
|
u16 addr;
|
|
|
|
BUG_ON(reg_size != 2);
|
|
|
|
addr = *(u16 *)reg;
|
|
|
|
while (addr <= 0xFF && val_size) {
|
|
len = min_t(size_t, val_size, 16);
|
|
|
|
err = spmi_ext_register_write(context, addr, val, len);
|
|
if (err)
|
|
goto err_out;
|
|
|
|
addr += len;
|
|
val += len;
|
|
val_size -= len;
|
|
}
|
|
|
|
while (val_size) {
|
|
len = min_t(size_t, val_size, 8);
|
|
|
|
err = spmi_ext_register_writel(context, addr, val, len);
|
|
if (err)
|
|
goto err_out;
|
|
|
|
addr += len;
|
|
val += len;
|
|
val_size -= len;
|
|
}
|
|
|
|
err_out:
|
|
return err;
|
|
}
|
|
|
|
static int regmap_spmi_ext_write(void *context, const void *data,
|
|
size_t count)
|
|
{
|
|
BUG_ON(count < 2);
|
|
return regmap_spmi_ext_gather_write(context, data, 2, data + 2,
|
|
count - 2);
|
|
}
|
|
|
|
static const struct regmap_bus regmap_spmi_ext = {
|
|
.read = regmap_spmi_ext_read,
|
|
.write = regmap_spmi_ext_write,
|
|
.gather_write = regmap_spmi_ext_gather_write,
|
|
.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
|
|
.val_format_endian_default = REGMAP_ENDIAN_NATIVE,
|
|
};
|
|
|
|
struct regmap *__regmap_init_spmi_ext(struct spmi_device *sdev,
|
|
const struct regmap_config *config,
|
|
struct lock_class_key *lock_key,
|
|
const char *lock_name)
|
|
{
|
|
return __regmap_init(&sdev->dev, ®map_spmi_ext, sdev, config,
|
|
lock_key, lock_name);
|
|
}
|
|
EXPORT_SYMBOL_GPL(__regmap_init_spmi_ext);
|
|
|
|
struct regmap *__devm_regmap_init_spmi_ext(struct spmi_device *sdev,
|
|
const struct regmap_config *config,
|
|
struct lock_class_key *lock_key,
|
|
const char *lock_name)
|
|
{
|
|
return __devm_regmap_init(&sdev->dev, ®map_spmi_ext, sdev, config,
|
|
lock_key, lock_name);
|
|
}
|
|
EXPORT_SYMBOL_GPL(__devm_regmap_init_spmi_ext);
|
|
|
|
MODULE_LICENSE("GPL");
|