mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-23 09:56:00 +00:00
eeprom: at24: add basic regmap_i2c support
This patch adds basic regmap support to be used by subsequent patches of this series. Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
This commit is contained in:
parent
30a7acd573
commit
5c01525847
@ -4,6 +4,7 @@ config EEPROM_AT24
|
|||||||
tristate "I2C EEPROMs / RAMs / ROMs from most vendors"
|
tristate "I2C EEPROMs / RAMs / ROMs from most vendors"
|
||||||
depends on I2C && SYSFS
|
depends on I2C && SYSFS
|
||||||
select NVMEM
|
select NVMEM
|
||||||
|
select REGMAP_I2C
|
||||||
help
|
help
|
||||||
Enable this driver to get read/write support to most I2C EEPROMs
|
Enable this driver to get read/write support to most I2C EEPROMs
|
||||||
and compatible devices like FRAMs, SRAMs, ROMs etc. After you
|
and compatible devices like FRAMs, SRAMs, ROMs etc. After you
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/nvmem-provider.h>
|
#include <linux/nvmem-provider.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
#include <linux/platform_data/at24.h>
|
#include <linux/platform_data/at24.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
|
||||||
@ -55,6 +56,11 @@
|
|||||||
* which won't work on pure SMBus systems.
|
* which won't work on pure SMBus systems.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct at24_client {
|
||||||
|
struct i2c_client *client;
|
||||||
|
struct regmap *regmap;
|
||||||
|
};
|
||||||
|
|
||||||
struct at24_data {
|
struct at24_data {
|
||||||
struct at24_platform_data chip;
|
struct at24_platform_data chip;
|
||||||
int use_smbus;
|
int use_smbus;
|
||||||
@ -81,7 +87,7 @@ struct at24_data {
|
|||||||
* Some chips tie up multiple I2C addresses; dummy devices reserve
|
* Some chips tie up multiple I2C addresses; dummy devices reserve
|
||||||
* them for us, and we'll use them with SMBus calls.
|
* them for us, and we'll use them with SMBus calls.
|
||||||
*/
|
*/
|
||||||
struct i2c_client *client[];
|
struct at24_client client[];
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -274,7 +280,7 @@ static struct i2c_client *at24_translate_offset(struct at24_data *at24,
|
|||||||
*offset &= 0xff;
|
*offset &= 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
return at24->client[i];
|
return at24->client[i].client;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t at24_eeprom_read_smbus(struct at24_data *at24, char *buf,
|
static ssize_t at24_eeprom_read_smbus(struct at24_data *at24, char *buf,
|
||||||
@ -562,7 +568,7 @@ static ssize_t at24_eeprom_write_i2c(struct at24_data *at24, const char *buf,
|
|||||||
static int at24_read(void *priv, unsigned int off, void *val, size_t count)
|
static int at24_read(void *priv, unsigned int off, void *val, size_t count)
|
||||||
{
|
{
|
||||||
struct at24_data *at24 = priv;
|
struct at24_data *at24 = priv;
|
||||||
struct device *dev = &at24->client[0]->dev;
|
struct device *dev = &at24->client[0].client->dev;
|
||||||
char *buf = val;
|
char *buf = val;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -608,7 +614,7 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count)
|
|||||||
static int at24_write(void *priv, unsigned int off, void *val, size_t count)
|
static int at24_write(void *priv, unsigned int off, void *val, size_t count)
|
||||||
{
|
{
|
||||||
struct at24_data *at24 = priv;
|
struct at24_data *at24 = priv;
|
||||||
struct device *dev = &at24->client[0]->dev;
|
struct device *dev = &at24->client[0].client->dev;
|
||||||
char *buf = val;
|
char *buf = val;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -676,6 +682,16 @@ static void at24_get_pdata(struct device *dev, struct at24_platform_data *chip)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct regmap_config regmap_config_8 = {
|
||||||
|
.reg_bits = 8,
|
||||||
|
.val_bits = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct regmap_config regmap_config_16 = {
|
||||||
|
.reg_bits = 16,
|
||||||
|
.val_bits = 8,
|
||||||
|
};
|
||||||
|
|
||||||
static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
struct at24_platform_data chip;
|
struct at24_platform_data chip;
|
||||||
@ -686,6 +702,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||||||
struct at24_data *at24;
|
struct at24_data *at24;
|
||||||
int err;
|
int err;
|
||||||
unsigned i, num_addresses;
|
unsigned i, num_addresses;
|
||||||
|
const struct regmap_config *config;
|
||||||
u8 test_byte;
|
u8 test_byte;
|
||||||
|
|
||||||
if (client->dev.platform_data) {
|
if (client->dev.platform_data) {
|
||||||
@ -777,8 +794,13 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||||||
num_addresses = DIV_ROUND_UP(chip.byte_len,
|
num_addresses = DIV_ROUND_UP(chip.byte_len,
|
||||||
(chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256);
|
(chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256);
|
||||||
|
|
||||||
|
if (chip.flags & AT24_FLAG_ADDR16)
|
||||||
|
config = ®map_config_16;
|
||||||
|
else
|
||||||
|
config = ®map_config_8;
|
||||||
|
|
||||||
at24 = devm_kzalloc(&client->dev, sizeof(struct at24_data) +
|
at24 = devm_kzalloc(&client->dev, sizeof(struct at24_data) +
|
||||||
num_addresses * sizeof(struct i2c_client *), GFP_KERNEL);
|
num_addresses * sizeof(struct at24_client), GFP_KERNEL);
|
||||||
if (!at24)
|
if (!at24)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -788,6 +810,11 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||||||
at24->chip = chip;
|
at24->chip = chip;
|
||||||
at24->num_addresses = num_addresses;
|
at24->num_addresses = num_addresses;
|
||||||
|
|
||||||
|
at24->client[0].client = client;
|
||||||
|
at24->client[0].regmap = devm_regmap_init_i2c(client, config);
|
||||||
|
if (IS_ERR(at24->client[0].regmap))
|
||||||
|
return PTR_ERR(at24->client[0].regmap);
|
||||||
|
|
||||||
if ((chip.flags & AT24_FLAG_SERIAL) && (chip.flags & AT24_FLAG_MAC)) {
|
if ((chip.flags & AT24_FLAG_SERIAL) && (chip.flags & AT24_FLAG_MAC)) {
|
||||||
dev_err(&client->dev,
|
dev_err(&client->dev,
|
||||||
"invalid device data - cannot have both AT24_FLAG_SERIAL & AT24_FLAG_MAC.");
|
"invalid device data - cannot have both AT24_FLAG_SERIAL & AT24_FLAG_MAC.");
|
||||||
@ -835,18 +862,22 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
at24->client[0] = client;
|
|
||||||
|
|
||||||
/* use dummy devices for multiple-address chips */
|
/* use dummy devices for multiple-address chips */
|
||||||
for (i = 1; i < num_addresses; i++) {
|
for (i = 1; i < num_addresses; i++) {
|
||||||
at24->client[i] = i2c_new_dummy(client->adapter,
|
at24->client[i].client = i2c_new_dummy(client->adapter,
|
||||||
client->addr + i);
|
client->addr + i);
|
||||||
if (!at24->client[i]) {
|
if (!at24->client[i].client) {
|
||||||
dev_err(&client->dev, "address 0x%02x unavailable\n",
|
dev_err(&client->dev, "address 0x%02x unavailable\n",
|
||||||
client->addr + i);
|
client->addr + i);
|
||||||
err = -EADDRINUSE;
|
err = -EADDRINUSE;
|
||||||
goto err_clients;
|
goto err_clients;
|
||||||
}
|
}
|
||||||
|
at24->client[i].regmap = devm_regmap_init_i2c(
|
||||||
|
at24->client[i].client, config);
|
||||||
|
if (IS_ERR(at24->client[i].regmap)) {
|
||||||
|
err = PTR_ERR(at24->client[i].regmap);
|
||||||
|
goto err_clients;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c_set_clientdata(client, at24);
|
i2c_set_clientdata(client, at24);
|
||||||
@ -905,8 +936,8 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||||||
|
|
||||||
err_clients:
|
err_clients:
|
||||||
for (i = 1; i < num_addresses; i++)
|
for (i = 1; i < num_addresses; i++)
|
||||||
if (at24->client[i])
|
if (at24->client[i].client)
|
||||||
i2c_unregister_device(at24->client[i]);
|
i2c_unregister_device(at24->client[i].client);
|
||||||
|
|
||||||
pm_runtime_disable(&client->dev);
|
pm_runtime_disable(&client->dev);
|
||||||
|
|
||||||
@ -923,7 +954,7 @@ static int at24_remove(struct i2c_client *client)
|
|||||||
nvmem_unregister(at24->nvmem);
|
nvmem_unregister(at24->nvmem);
|
||||||
|
|
||||||
for (i = 1; i < at24->num_addresses; i++)
|
for (i = 1; i < at24->num_addresses; i++)
|
||||||
i2c_unregister_device(at24->client[i]);
|
i2c_unregister_device(at24->client[i].client);
|
||||||
|
|
||||||
pm_runtime_disable(&client->dev);
|
pm_runtime_disable(&client->dev);
|
||||||
pm_runtime_set_suspended(&client->dev);
|
pm_runtime_set_suspended(&client->dev);
|
||||||
|
Loading…
Reference in New Issue
Block a user