mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
Char/Misc driver fixes for 6.2-rc7
Here are a number of small char/misc/whatever driver fixes for 6.2-rc7. They include: - IIO driver fixes for some reported problems - nvmem driver fixes - fpga driver fixes - debugfs memory leak fix in the hv_balloon and irqdomain code (irqdomain change was acked by the maintainer.) All have been in linux-next with no reported problems. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCY9+Xkw8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+yl92QCfSTATuad8nUXmtBDsveUyAV3G6pkAoJFMWAIj otmAl9XOGWxdwAURdovs =tSdo -----END PGP SIGNATURE----- Merge tag 'char-misc-6.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc Pull char/misc driver fixes from Greg KH: "Here are a number of small char/misc/whatever driver fixes. They include: - IIO driver fixes for some reported problems - nvmem driver fixes - fpga driver fixes - debugfs memory leak fix in the hv_balloon and irqdomain code (irqdomain change was acked by the maintainer) All have been in linux-next with no reported problems" * tag 'char-misc-6.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (33 commits) kernel/irq/irqdomain.c: fix memory leak with using debugfs_lookup() HV: hv_balloon: fix memory leak with using debugfs_lookup() nvmem: qcom-spmi-sdam: fix module autoloading nvmem: core: fix return value nvmem: core: fix cell removal on error nvmem: core: fix device node refcounting nvmem: core: fix registration vs use race nvmem: core: fix cleanup after dev_set_name() nvmem: core: remove nvmem_config wp_gpio nvmem: core: initialise nvmem->id early nvmem: sunxi_sid: Always use 32-bit MMIO reads nvmem: brcm_nvram: Add check for kzalloc iio: imu: fxos8700: fix MAGN sensor scale and unit iio: imu: fxos8700: remove definition FXOS8700_CTRL_ODR_MIN iio: imu: fxos8700: fix failed initialization ODR mode assignment iio: imu: fxos8700: fix incorrect ODR mode readback iio: light: cm32181: Fix PM support on system with 2 I2C resources iio: hid: fix the retval in gyro_3d_capture_sample iio: hid: fix the retval in accel_3d_capture_sample iio: imu: st_lsm6dsx: fix build when CONFIG_IIO_TRIGGERED_BUFFER=m ...
This commit is contained in:
commit
d3feaff4d9
@ -574,20 +574,27 @@ static int m10bmc_sec_probe(struct platform_device *pdev)
|
||||
len = scnprintf(buf, SEC_UPDATE_LEN_MAX, "secure-update%d",
|
||||
sec->fw_name_id);
|
||||
sec->fw_name = kmemdup_nul(buf, len, GFP_KERNEL);
|
||||
if (!sec->fw_name)
|
||||
return -ENOMEM;
|
||||
if (!sec->fw_name) {
|
||||
ret = -ENOMEM;
|
||||
goto fw_name_fail;
|
||||
}
|
||||
|
||||
fwl = firmware_upload_register(THIS_MODULE, sec->dev, sec->fw_name,
|
||||
&m10bmc_ops, sec);
|
||||
if (IS_ERR(fwl)) {
|
||||
dev_err(sec->dev, "Firmware Upload driver failed to start\n");
|
||||
kfree(sec->fw_name);
|
||||
xa_erase(&fw_upload_xa, sec->fw_name_id);
|
||||
return PTR_ERR(fwl);
|
||||
ret = PTR_ERR(fwl);
|
||||
goto fw_uploader_fail;
|
||||
}
|
||||
|
||||
sec->fwl = fwl;
|
||||
return 0;
|
||||
|
||||
fw_uploader_fail:
|
||||
kfree(sec->fw_name);
|
||||
fw_name_fail:
|
||||
xa_erase(&fw_upload_xa, sec->fw_name_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int m10bmc_sec_remove(struct platform_device *pdev)
|
||||
|
@ -213,9 +213,9 @@ static int s10_ops_write_init(struct fpga_manager *mgr,
|
||||
/* Allocate buffers from the service layer's pool. */
|
||||
for (i = 0; i < NUM_SVC_BUFS; i++) {
|
||||
kbuf = stratix10_svc_allocate_memory(priv->chan, SVC_BUF_SIZE);
|
||||
if (!kbuf) {
|
||||
if (IS_ERR(kbuf)) {
|
||||
s10_free_buffers(mgr);
|
||||
ret = -ENOMEM;
|
||||
ret = PTR_ERR(kbuf);
|
||||
goto init_done;
|
||||
}
|
||||
|
||||
|
@ -1963,7 +1963,7 @@ static void hv_balloon_debugfs_init(struct hv_dynmem_device *b)
|
||||
|
||||
static void hv_balloon_debugfs_exit(struct hv_dynmem_device *b)
|
||||
{
|
||||
debugfs_remove(debugfs_lookup("hv-balloon", NULL));
|
||||
debugfs_lookup_and_remove("hv-balloon", NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -280,6 +280,7 @@ static int accel_3d_capture_sample(struct hid_sensor_hub_device *hsdev,
|
||||
hid_sensor_convert_timestamp(
|
||||
&accel_state->common_attributes,
|
||||
*(int64_t *)raw_data);
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -298,8 +298,10 @@ static int berlin2_adc_probe(struct platform_device *pdev)
|
||||
int ret;
|
||||
|
||||
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
|
||||
if (!indio_dev)
|
||||
if (!indio_dev) {
|
||||
of_node_put(parent_np);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv = iio_priv(indio_dev);
|
||||
|
||||
|
@ -86,6 +86,8 @@
|
||||
|
||||
#define IMX8QXP_ADC_TIMEOUT msecs_to_jiffies(100)
|
||||
|
||||
#define IMX8QXP_ADC_MAX_FIFO_SIZE 16
|
||||
|
||||
struct imx8qxp_adc {
|
||||
struct device *dev;
|
||||
void __iomem *regs;
|
||||
@ -95,6 +97,7 @@ struct imx8qxp_adc {
|
||||
/* Serialise ADC channel reads */
|
||||
struct mutex lock;
|
||||
struct completion completion;
|
||||
u32 fifo[IMX8QXP_ADC_MAX_FIFO_SIZE];
|
||||
};
|
||||
|
||||
#define IMX8QXP_ADC_CHAN(_idx) { \
|
||||
@ -238,8 +241,7 @@ static int imx8qxp_adc_read_raw(struct iio_dev *indio_dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
*val = FIELD_GET(IMX8QXP_ADC_RESFIFO_VAL_MASK,
|
||||
readl(adc->regs + IMX8QXP_ADR_ADC_RESFIFO));
|
||||
*val = adc->fifo[0];
|
||||
|
||||
mutex_unlock(&adc->lock);
|
||||
return IIO_VAL_INT;
|
||||
@ -265,10 +267,15 @@ static irqreturn_t imx8qxp_adc_isr(int irq, void *dev_id)
|
||||
{
|
||||
struct imx8qxp_adc *adc = dev_id;
|
||||
u32 fifo_count;
|
||||
int i;
|
||||
|
||||
fifo_count = FIELD_GET(IMX8QXP_ADC_FCTRL_FCOUNT_MASK,
|
||||
readl(adc->regs + IMX8QXP_ADR_ADC_FCTRL));
|
||||
|
||||
for (i = 0; i < fifo_count; i++)
|
||||
adc->fifo[i] = FIELD_GET(IMX8QXP_ADC_RESFIFO_VAL_MASK,
|
||||
readl_relaxed(adc->regs + IMX8QXP_ADR_ADC_RESFIFO));
|
||||
|
||||
if (fifo_count)
|
||||
complete(&adc->completion);
|
||||
|
||||
|
@ -1520,6 +1520,7 @@ static const struct of_device_id stm32_dfsdm_adc_match[] = {
|
||||
},
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, stm32_dfsdm_adc_match);
|
||||
|
||||
static int stm32_dfsdm_adc_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
@ -57,6 +57,18 @@
|
||||
#define TWL6030_GPADCS BIT(1)
|
||||
#define TWL6030_GPADCR BIT(0)
|
||||
|
||||
#define USB_VBUS_CTRL_SET 0x04
|
||||
#define USB_ID_CTRL_SET 0x06
|
||||
|
||||
#define TWL6030_MISC1 0xE4
|
||||
#define VBUS_MEAS 0x01
|
||||
#define ID_MEAS 0x01
|
||||
|
||||
#define VAC_MEAS 0x04
|
||||
#define VBAT_MEAS 0x02
|
||||
#define BB_MEAS 0x01
|
||||
|
||||
|
||||
/**
|
||||
* struct twl6030_chnl_calib - channel calibration
|
||||
* @gain: slope coefficient for ideal curve
|
||||
@ -927,6 +939,26 @@ static int twl6030_gpadc_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = twl_i2c_write_u8(TWL_MODULE_USB, VBUS_MEAS, USB_VBUS_CTRL_SET);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to wire up inputs\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = twl_i2c_write_u8(TWL_MODULE_USB, ID_MEAS, USB_ID_CTRL_SET);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to wire up inputs\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = twl_i2c_write_u8(TWL6030_MODULE_ID0,
|
||||
VBAT_MEAS | BB_MEAS | VAC_MEAS,
|
||||
TWL6030_MISC1);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to wire up inputs\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
indio_dev->name = DRIVER_NAME;
|
||||
indio_dev->info = &twl6030_gpadc_iio_info;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
@ -1329,7 +1329,7 @@ static int ams_parse_firmware(struct iio_dev *indio_dev)
|
||||
|
||||
dev_channels = devm_krealloc(dev, ams_channels, dev_size, GFP_KERNEL);
|
||||
if (!dev_channels)
|
||||
ret = -ENOMEM;
|
||||
return -ENOMEM;
|
||||
|
||||
indio_dev->channels = dev_channels;
|
||||
indio_dev->num_channels = num_channels;
|
||||
|
@ -231,6 +231,7 @@ static int gyro_3d_capture_sample(struct hid_sensor_hub_device *hsdev,
|
||||
gyro_state->timestamp =
|
||||
hid_sensor_convert_timestamp(&gyro_state->common_attributes,
|
||||
*(s64 *)raw_data);
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/bitfield.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
@ -144,9 +145,8 @@
|
||||
#define FXOS8700_NVM_DATA_BNK0 0xa7
|
||||
|
||||
/* Bit definitions for FXOS8700_CTRL_REG1 */
|
||||
#define FXOS8700_CTRL_ODR_MSK 0x38
|
||||
#define FXOS8700_CTRL_ODR_MAX 0x00
|
||||
#define FXOS8700_CTRL_ODR_MIN GENMASK(4, 3)
|
||||
#define FXOS8700_CTRL_ODR_MSK GENMASK(5, 3)
|
||||
|
||||
/* Bit definitions for FXOS8700_M_CTRL_REG1 */
|
||||
#define FXOS8700_HMS_MASK GENMASK(1, 0)
|
||||
@ -320,7 +320,7 @@ static enum fxos8700_sensor fxos8700_to_sensor(enum iio_chan_type iio_type)
|
||||
switch (iio_type) {
|
||||
case IIO_ACCEL:
|
||||
return FXOS8700_ACCEL;
|
||||
case IIO_ANGL_VEL:
|
||||
case IIO_MAGN:
|
||||
return FXOS8700_MAGN;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -345,15 +345,35 @@ static int fxos8700_set_active_mode(struct fxos8700_data *data,
|
||||
static int fxos8700_set_scale(struct fxos8700_data *data,
|
||||
enum fxos8700_sensor t, int uscale)
|
||||
{
|
||||
int i;
|
||||
int i, ret, val;
|
||||
bool active_mode;
|
||||
static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);
|
||||
struct device *dev = regmap_get_device(data->regmap);
|
||||
|
||||
if (t == FXOS8700_MAGN) {
|
||||
dev_err(dev, "Magnetometer scale is locked at 1200uT\n");
|
||||
dev_err(dev, "Magnetometer scale is locked at 0.001Gs\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* When device is in active mode, it failed to set an ACCEL
|
||||
* full-scale range(2g/4g/8g) in FXOS8700_XYZ_DATA_CFG.
|
||||
* This is not align with the datasheet, but it is a fxos8700
|
||||
* chip behavier. Set the device in standby mode before setting
|
||||
* an ACCEL full-scale range.
|
||||
*/
|
||||
ret = regmap_read(data->regmap, FXOS8700_CTRL_REG1, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
active_mode = val & FXOS8700_ACTIVE;
|
||||
if (active_mode) {
|
||||
ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,
|
||||
val & ~FXOS8700_ACTIVE);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < scale_num; i++)
|
||||
if (fxos8700_accel_scale[i].uscale == uscale)
|
||||
break;
|
||||
@ -361,8 +381,12 @@ static int fxos8700_set_scale(struct fxos8700_data *data,
|
||||
if (i == scale_num)
|
||||
return -EINVAL;
|
||||
|
||||
return regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG,
|
||||
ret = regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG,
|
||||
fxos8700_accel_scale[i].bits);
|
||||
if (ret)
|
||||
return ret;
|
||||
return regmap_write(data->regmap, FXOS8700_CTRL_REG1,
|
||||
active_mode);
|
||||
}
|
||||
|
||||
static int fxos8700_get_scale(struct fxos8700_data *data,
|
||||
@ -372,7 +396,7 @@ static int fxos8700_get_scale(struct fxos8700_data *data,
|
||||
static const int scale_num = ARRAY_SIZE(fxos8700_accel_scale);
|
||||
|
||||
if (t == FXOS8700_MAGN) {
|
||||
*uscale = 1200; /* Magnetometer is locked at 1200uT */
|
||||
*uscale = 1000; /* Magnetometer is locked at 0.001Gs */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -394,22 +418,61 @@ static int fxos8700_get_data(struct fxos8700_data *data, int chan_type,
|
||||
int axis, int *val)
|
||||
{
|
||||
u8 base, reg;
|
||||
s16 tmp;
|
||||
int ret;
|
||||
enum fxos8700_sensor type = fxos8700_to_sensor(chan_type);
|
||||
|
||||
base = type ? FXOS8700_OUT_X_MSB : FXOS8700_M_OUT_X_MSB;
|
||||
/*
|
||||
* Different register base addresses varies with channel types.
|
||||
* This bug hasn't been noticed before because using an enum is
|
||||
* really hard to read. Use an a switch statement to take over that.
|
||||
*/
|
||||
switch (chan_type) {
|
||||
case IIO_ACCEL:
|
||||
base = FXOS8700_OUT_X_MSB;
|
||||
break;
|
||||
case IIO_MAGN:
|
||||
base = FXOS8700_M_OUT_X_MSB;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Block read 6 bytes of device output registers to avoid data loss */
|
||||
ret = regmap_bulk_read(data->regmap, base, data->buf,
|
||||
FXOS8700_DATA_BUF_SIZE);
|
||||
sizeof(data->buf));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Convert axis to buffer index */
|
||||
reg = axis - IIO_MOD_X;
|
||||
|
||||
/*
|
||||
* Convert to native endianness. The accel data and magn data
|
||||
* are signed, so a forced type conversion is needed.
|
||||
*/
|
||||
tmp = be16_to_cpu(data->buf[reg]);
|
||||
|
||||
/*
|
||||
* ACCEL output data registers contain the X-axis, Y-axis, and Z-axis
|
||||
* 14-bit left-justified sample data and MAGN output data registers
|
||||
* contain the X-axis, Y-axis, and Z-axis 16-bit sample data. Apply
|
||||
* a signed 2 bits right shift to the readback raw data from ACCEL
|
||||
* output data register and keep that from MAGN sensor as the origin.
|
||||
* Value should be extended to 32 bit.
|
||||
*/
|
||||
switch (chan_type) {
|
||||
case IIO_ACCEL:
|
||||
tmp = tmp >> 2;
|
||||
break;
|
||||
case IIO_MAGN:
|
||||
/* Nothing to do */
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Convert to native endianness */
|
||||
*val = sign_extend32(be16_to_cpu(data->buf[reg]), 15);
|
||||
*val = sign_extend32(tmp, 15);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -445,10 +508,9 @@ static int fxos8700_set_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
|
||||
if (i >= odr_num)
|
||||
return -EINVAL;
|
||||
|
||||
return regmap_update_bits(data->regmap,
|
||||
FXOS8700_CTRL_REG1,
|
||||
FXOS8700_CTRL_ODR_MSK + FXOS8700_ACTIVE,
|
||||
fxos8700_odr[i].bits << 3 | active_mode);
|
||||
val &= ~FXOS8700_CTRL_ODR_MSK;
|
||||
val |= FIELD_PREP(FXOS8700_CTRL_ODR_MSK, fxos8700_odr[i].bits) | FXOS8700_ACTIVE;
|
||||
return regmap_write(data->regmap, FXOS8700_CTRL_REG1, val);
|
||||
}
|
||||
|
||||
static int fxos8700_get_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
|
||||
@ -461,7 +523,7 @@ static int fxos8700_get_odr(struct fxos8700_data *data, enum fxos8700_sensor t,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val &= FXOS8700_CTRL_ODR_MSK;
|
||||
val = FIELD_GET(FXOS8700_CTRL_ODR_MSK, val);
|
||||
|
||||
for (i = 0; i < odr_num; i++)
|
||||
if (val == fxos8700_odr[i].bits)
|
||||
@ -526,7 +588,7 @@ static IIO_CONST_ATTR(in_accel_sampling_frequency_available,
|
||||
static IIO_CONST_ATTR(in_magn_sampling_frequency_available,
|
||||
"1.5625 6.25 12.5 50 100 200 400 800");
|
||||
static IIO_CONST_ATTR(in_accel_scale_available, "0.000244 0.000488 0.000976");
|
||||
static IIO_CONST_ATTR(in_magn_scale_available, "0.000001200");
|
||||
static IIO_CONST_ATTR(in_magn_scale_available, "0.001000");
|
||||
|
||||
static struct attribute *fxos8700_attrs[] = {
|
||||
&iio_const_attr_in_accel_sampling_frequency_available.dev_attr.attr,
|
||||
@ -592,14 +654,19 @@ static int fxos8700_chip_init(struct fxos8700_data *data, bool use_spi)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Max ODR (800Hz individual or 400Hz hybrid), active mode */
|
||||
ret = regmap_write(data->regmap, FXOS8700_CTRL_REG1,
|
||||
FXOS8700_CTRL_ODR_MAX | FXOS8700_ACTIVE);
|
||||
/*
|
||||
* Set max full-scale range (+/-8G) for ACCEL sensor in chip
|
||||
* initialization then activate the device.
|
||||
*/
|
||||
ret = regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, MODE_8G);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Set for max full-scale range (+/-8G) */
|
||||
return regmap_write(data->regmap, FXOS8700_XYZ_DATA_CFG, MODE_8G);
|
||||
/* Max ODR (800Hz individual or 400Hz hybrid), active mode */
|
||||
return regmap_update_bits(data->regmap, FXOS8700_CTRL_REG1,
|
||||
FXOS8700_CTRL_ODR_MSK | FXOS8700_ACTIVE,
|
||||
FIELD_PREP(FXOS8700_CTRL_ODR_MSK, FXOS8700_CTRL_ODR_MAX) |
|
||||
FXOS8700_ACTIVE);
|
||||
}
|
||||
|
||||
static void fxos8700_chip_uninit(void *data)
|
||||
|
@ -4,6 +4,7 @@ config IIO_ST_LSM6DSX
|
||||
tristate "ST_LSM6DSx driver for STM 6-axis IMU MEMS sensors"
|
||||
depends on (I2C || SPI || I3C)
|
||||
select IIO_BUFFER
|
||||
select IIO_TRIGGERED_BUFFER
|
||||
select IIO_KFIFO_BUF
|
||||
select IIO_ST_LSM6DSX_I2C if (I2C)
|
||||
select IIO_ST_LSM6DSX_SPI if (SPI_MASTER)
|
||||
|
@ -440,6 +440,8 @@ static int cm32181_probe(struct i2c_client *client)
|
||||
if (!indio_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
|
||||
/*
|
||||
* Some ACPI systems list 2 I2C resources for the CM3218 sensor, the
|
||||
* SMBus Alert Response Address (ARA, 0x0c) and the actual I2C address.
|
||||
@ -460,8 +462,6 @@ static int cm32181_probe(struct i2c_client *client)
|
||||
return PTR_ERR(client);
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, indio_dev);
|
||||
|
||||
cm32181 = iio_priv(indio_dev);
|
||||
cm32181->client = client;
|
||||
cm32181->dev = dev;
|
||||
@ -490,7 +490,8 @@ static int cm32181_probe(struct i2c_client *client)
|
||||
|
||||
static int cm32181_suspend(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cm32181_chip *cm32181 = iio_priv(dev_get_drvdata(dev));
|
||||
struct i2c_client *client = cm32181->client;
|
||||
|
||||
return i2c_smbus_write_word_data(client, CM32181_REG_ADDR_CMD,
|
||||
CM32181_CMD_ALS_DISABLE);
|
||||
@ -498,8 +499,8 @@ static int cm32181_suspend(struct device *dev)
|
||||
|
||||
static int cm32181_resume(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cm32181_chip *cm32181 = iio_priv(dev_get_drvdata(dev));
|
||||
struct i2c_client *client = cm32181->client;
|
||||
|
||||
return i2c_smbus_write_word_data(client, CM32181_REG_ADDR_CMD,
|
||||
cm32181->conf_regs[CM32181_REG_ADDR_CMD]);
|
||||
|
@ -98,6 +98,9 @@ static int brcm_nvram_parse(struct brcm_nvram *priv)
|
||||
len = le32_to_cpu(header.len);
|
||||
|
||||
data = kzalloc(len, GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy_fromio(data, priv->base, len);
|
||||
data[len - 1] = '\0';
|
||||
|
||||
|
@ -770,31 +770,32 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
|
||||
return ERR_PTR(rval);
|
||||
}
|
||||
|
||||
if (config->wp_gpio)
|
||||
nvmem->wp_gpio = config->wp_gpio;
|
||||
else if (!config->ignore_wp)
|
||||
nvmem->id = rval;
|
||||
|
||||
nvmem->dev.type = &nvmem_provider_type;
|
||||
nvmem->dev.bus = &nvmem_bus_type;
|
||||
nvmem->dev.parent = config->dev;
|
||||
|
||||
device_initialize(&nvmem->dev);
|
||||
|
||||
if (!config->ignore_wp)
|
||||
nvmem->wp_gpio = gpiod_get_optional(config->dev, "wp",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(nvmem->wp_gpio)) {
|
||||
ida_free(&nvmem_ida, nvmem->id);
|
||||
rval = PTR_ERR(nvmem->wp_gpio);
|
||||
kfree(nvmem);
|
||||
return ERR_PTR(rval);
|
||||
nvmem->wp_gpio = NULL;
|
||||
goto err_put_device;
|
||||
}
|
||||
|
||||
kref_init(&nvmem->refcnt);
|
||||
INIT_LIST_HEAD(&nvmem->cells);
|
||||
|
||||
nvmem->id = rval;
|
||||
nvmem->owner = config->owner;
|
||||
if (!nvmem->owner && config->dev->driver)
|
||||
nvmem->owner = config->dev->driver->owner;
|
||||
nvmem->stride = config->stride ?: 1;
|
||||
nvmem->word_size = config->word_size ?: 1;
|
||||
nvmem->size = config->size;
|
||||
nvmem->dev.type = &nvmem_provider_type;
|
||||
nvmem->dev.bus = &nvmem_bus_type;
|
||||
nvmem->dev.parent = config->dev;
|
||||
nvmem->root_only = config->root_only;
|
||||
nvmem->priv = config->priv;
|
||||
nvmem->type = config->type;
|
||||
@ -822,11 +823,8 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
|
||||
break;
|
||||
}
|
||||
|
||||
if (rval) {
|
||||
ida_free(&nvmem_ida, nvmem->id);
|
||||
kfree(nvmem);
|
||||
return ERR_PTR(rval);
|
||||
}
|
||||
if (rval)
|
||||
goto err_put_device;
|
||||
|
||||
nvmem->read_only = device_property_present(config->dev, "read-only") ||
|
||||
config->read_only || !nvmem->reg_write;
|
||||
@ -835,28 +833,22 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
|
||||
nvmem->dev.groups = nvmem_dev_groups;
|
||||
#endif
|
||||
|
||||
dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
|
||||
|
||||
rval = device_register(&nvmem->dev);
|
||||
if (rval)
|
||||
goto err_put_device;
|
||||
|
||||
if (nvmem->nkeepout) {
|
||||
rval = nvmem_validate_keepouts(nvmem);
|
||||
if (rval)
|
||||
goto err_device_del;
|
||||
goto err_put_device;
|
||||
}
|
||||
|
||||
if (config->compat) {
|
||||
rval = nvmem_sysfs_setup_compat(nvmem, config);
|
||||
if (rval)
|
||||
goto err_device_del;
|
||||
goto err_put_device;
|
||||
}
|
||||
|
||||
if (config->cells) {
|
||||
rval = nvmem_add_cells(nvmem, config->cells, config->ncells);
|
||||
if (rval)
|
||||
goto err_teardown_compat;
|
||||
goto err_remove_cells;
|
||||
}
|
||||
|
||||
rval = nvmem_add_cells_from_table(nvmem);
|
||||
@ -867,17 +859,20 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
|
||||
if (rval)
|
||||
goto err_remove_cells;
|
||||
|
||||
dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
|
||||
|
||||
rval = device_add(&nvmem->dev);
|
||||
if (rval)
|
||||
goto err_remove_cells;
|
||||
|
||||
blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem);
|
||||
|
||||
return nvmem;
|
||||
|
||||
err_remove_cells:
|
||||
nvmem_device_remove_all_cells(nvmem);
|
||||
err_teardown_compat:
|
||||
if (config->compat)
|
||||
nvmem_sysfs_remove_compat(nvmem, config);
|
||||
err_device_del:
|
||||
device_del(&nvmem->dev);
|
||||
err_put_device:
|
||||
put_device(&nvmem->dev);
|
||||
|
||||
@ -1242,16 +1237,21 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id)
|
||||
if (!cell_np)
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
nvmem_np = of_get_next_parent(cell_np);
|
||||
if (!nvmem_np)
|
||||
nvmem_np = of_get_parent(cell_np);
|
||||
if (!nvmem_np) {
|
||||
of_node_put(cell_np);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
nvmem = __nvmem_device_get(nvmem_np, device_match_of_node);
|
||||
of_node_put(nvmem_np);
|
||||
if (IS_ERR(nvmem))
|
||||
if (IS_ERR(nvmem)) {
|
||||
of_node_put(cell_np);
|
||||
return ERR_CAST(nvmem);
|
||||
}
|
||||
|
||||
cell_entry = nvmem_find_cell_entry_by_node(nvmem, cell_np);
|
||||
of_node_put(cell_np);
|
||||
if (!cell_entry) {
|
||||
__nvmem_device_put(nvmem);
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
@ -166,6 +166,7 @@ static const struct of_device_id sdam_match_table[] = {
|
||||
{ .compatible = "qcom,spmi-sdam" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sdam_match_table);
|
||||
|
||||
static struct platform_driver sdam_driver = {
|
||||
.driver = {
|
||||
|
@ -41,8 +41,21 @@ static int sunxi_sid_read(void *context, unsigned int offset,
|
||||
void *val, size_t bytes)
|
||||
{
|
||||
struct sunxi_sid *sid = context;
|
||||
u32 word;
|
||||
|
||||
memcpy_fromio(val, sid->base + sid->value_offset + offset, bytes);
|
||||
/* .stride = 4 so offset is guaranteed to be aligned */
|
||||
__ioread32_copy(val, sid->base + sid->value_offset + offset, bytes / 4);
|
||||
|
||||
val += round_down(bytes, 4);
|
||||
offset += round_down(bytes, 4);
|
||||
bytes = bytes % 4;
|
||||
|
||||
if (!bytes)
|
||||
return 0;
|
||||
|
||||
/* Handle any trailing bytes */
|
||||
word = readl_relaxed(sid->base + sid->value_offset + offset);
|
||||
memcpy(val, &word, bytes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -70,7 +70,6 @@ struct nvmem_keepout {
|
||||
* @word_size: Minimum read/write access granularity.
|
||||
* @stride: Minimum read/write access stride.
|
||||
* @priv: User context passed to read/write callbacks.
|
||||
* @wp-gpio: Write protect pin
|
||||
* @ignore_wp: Write Protect pin is managed by the provider.
|
||||
*
|
||||
* Note: A default "nvmem<id>" name will be assigned to the device if
|
||||
@ -85,7 +84,6 @@ struct nvmem_config {
|
||||
const char *name;
|
||||
int id;
|
||||
struct module *owner;
|
||||
struct gpio_desc *wp_gpio;
|
||||
const struct nvmem_cell_info *cells;
|
||||
int ncells;
|
||||
const struct nvmem_keepout *keepout;
|
||||
|
@ -1915,7 +1915,7 @@ static void debugfs_add_domain_dir(struct irq_domain *d)
|
||||
|
||||
static void debugfs_remove_domain_dir(struct irq_domain *d)
|
||||
{
|
||||
debugfs_remove(debugfs_lookup(d->name, domain_dir));
|
||||
debugfs_lookup_and_remove(d->name, domain_dir);
|
||||
}
|
||||
|
||||
void __init irq_domain_debugfs_init(struct dentry *root)
|
||||
|
Loading…
Reference in New Issue
Block a user