Linux镜像1780是多少,代码阅读 - Linux\kernel\linux-5.0\drivers\iio\light\bh1780.c

/*

* ROHM 1780GLI Ambient Light Sensor Driver

*

* Copyright (C) 2016 Linaro Ltd.

* Author: Linus Walleij * Loosely based on the previous BH1780 ALS misc driver

* Copyright (C) 2010 Texas Instruments

* Author: Hemanth V */

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define BH1780_CMD_BITBIT(7)

#define BH1780_REG_CONTROL0x00

#define BH1780_REG_PARTID0x0A

#define BH1780_REG_MANFID0x0B

#define BH1780_REG_DLOW0x0C

#define BH1780_REG_DHIGH0x0D

#define BH1780_REVMASKGENMASK(3,0)

#define BH1780_POWMASKGENMASK(1,0)

#define BH1780_POFF(0x0)

#define BH1780_PON(0x3)

/* power on settling time in ms */

#define BH1780_PON_DELAY2

/* max time before value available in ms */

#define BH1780_INTERVAL250

struct bh1780_data {

struct i2c_client *client;

};

static int bh1780_write(struct bh1780_data *bh1780, u8 reg, u8 val)

{

int ret = i2c_smbus_write_byte_data(bh1780->client,

BH1780_CMD_BIT | reg,

val);

if (ret < 0)

dev_err(&bh1780->client->dev,

"i2c_smbus_write_byte_data failed error "

"%d, register %01x\n",

ret, reg);

return ret;

}

static int bh1780_read(struct bh1780_data *bh1780, u8 reg)

{

int ret = i2c_smbus_read_byte_data(bh1780->client,

BH1780_CMD_BIT | reg);

if (ret < 0)

dev_err(&bh1780->client->dev,

"i2c_smbus_read_byte_data failed error "

"%d, register %01x\n",

ret, reg);

return ret;

}

static int bh1780_read_word(struct bh1780_data *bh1780, u8 reg)

{

int ret = i2c_smbus_read_word_data(bh1780->client,

BH1780_CMD_BIT | reg);

if (ret < 0)

dev_err(&bh1780->client->dev,

"i2c_smbus_read_word_data failed error "

"%d, register %01x\n",

ret, reg);

return ret;

}

static int bh1780_debugfs_reg_access(struct iio_dev *indio_dev,

unsigned int reg, unsigned int writeval,

unsigned int *readval)

{

struct bh1780_data *bh1780 = iio_priv(indio_dev);

int ret;

if (!readval)

return bh1780_write(bh1780, (u8)reg, (u8)writeval);

ret = bh1780_read(bh1780, (u8)reg);

if (ret < 0)

return ret;

*readval = ret;

return 0;

}

static int bh1780_read_raw(struct iio_dev *indio_dev,

struct iio_chan_spec const *chan,

int *val, int *val2, long mask)

{

struct bh1780_data *bh1780 = iio_priv(indio_dev);

int value;

switch (mask) {

case IIO_CHAN_INFO_RAW:

switch (chan->type) {

case IIO_LIGHT:

pm_runtime_get_sync(&bh1780->client->dev);

value = bh1780_read_word(bh1780, BH1780_REG_DLOW);

if (value < 0)

return value;

pm_runtime_mark_last_busy(&bh1780->client->dev);

pm_runtime_put_autosuspend(&bh1780->client->dev);

*val = value;

return IIO_VAL_INT;

default:

return -EINVAL;

}

case IIO_CHAN_INFO_INT_TIME:

*val = 0;

*val2 = BH1780_INTERVAL * 1000;

return IIO_VAL_INT_PLUS_MICRO;

default:

return -EINVAL;

}

}

static const struct iio_info bh1780_info = {

.read_raw = bh1780_read_raw,

.debugfs_reg_access = bh1780_debugfs_reg_access,

};

static const struct iio_chan_spec bh1780_channels[] = {

{

.type = IIO_LIGHT,

.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |

BIT(IIO_CHAN_INFO_INT_TIME)

}

};

static int bh1780_probe(struct i2c_client *client,

const struct i2c_device_id *id)

{

int ret;

struct bh1780_data *bh1780;

struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);

struct iio_dev *indio_dev;

if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))

return -EIO;

indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*bh1780));

if (!indio_dev)

return -ENOMEM;

bh1780 = iio_priv(indio_dev);

bh1780->client = client;

i2c_set_clientdata(client, indio_dev);

/* Power up the device */

ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_PON);

if (ret < 0)

return ret;

msleep(BH1780_PON_DELAY);

pm_runtime_get_noresume(&client->dev);

pm_runtime_set_active(&client->dev);

pm_runtime_enable(&client->dev);

ret = bh1780_read(bh1780, BH1780_REG_PARTID);

if (ret < 0)

goto out_disable_pm;

dev_info(&client->dev,

"Ambient Light Sensor, Rev : %lu\n",

(ret & BH1780_REVMASK));

/*

* As the device takes 250 ms to even come up with a fresh

* measurement after power-on, do not shut it down unnecessarily.

* Set autosuspend to a five seconds.

*/

pm_runtime_set_autosuspend_delay(&client->dev, 5000);

pm_runtime_use_autosuspend(&client->dev);

pm_runtime_put(&client->dev);

indio_dev->dev.parent = &client->dev;

indio_dev->info = &bh1780_info;

indio_dev->name = "bh1780";

indio_dev->channels = bh1780_channels;

indio_dev->num_channels = ARRAY_SIZE(bh1780_channels);

indio_dev->modes = INDIO_DIRECT_MODE;

ret = iio_device_register(indio_dev);

if (ret)

goto out_disable_pm;

return 0;

out_disable_pm:

pm_runtime_put_noidle(&client->dev);

pm_runtime_disable(&client->dev);

return ret;

}

static int bh1780_remove(struct i2c_client *client)

{

struct iio_dev *indio_dev = i2c_get_clientdata(client);

struct bh1780_data *bh1780 = iio_priv(indio_dev);

int ret;

iio_device_unregister(indio_dev);

pm_runtime_get_sync(&client->dev);

pm_runtime_put_noidle(&client->dev);

pm_runtime_disable(&client->dev);

ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_POFF);

if (ret < 0) {

dev_err(&client->dev, "failed to power off\n");

return ret;

}

return 0;

}

#ifdef CONFIG_PM

static int bh1780_runtime_suspend(struct device *dev)

{

struct i2c_client *client = to_i2c_client(dev);

struct iio_dev *indio_dev = i2c_get_clientdata(client);

struct bh1780_data *bh1780 = iio_priv(indio_dev);

int ret;

ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_POFF);

if (ret < 0) {

dev_err(dev, "failed to runtime suspend\n");

return ret;

}

return 0;

}

static int bh1780_runtime_resume(struct device *dev)

{

struct i2c_client *client = to_i2c_client(dev);

struct iio_dev *indio_dev = i2c_get_clientdata(client);

struct bh1780_data *bh1780 = iio_priv(indio_dev);

int ret;

ret = bh1780_write(bh1780, BH1780_REG_CONTROL, BH1780_PON);

if (ret < 0) {

dev_err(dev, "failed to runtime resume\n");

return ret;

}

/* Wait for power on, then for a value to be available */

msleep(BH1780_PON_DELAY + BH1780_INTERVAL);

return 0;

}

#endif /* CONFIG_PM */

static const struct dev_pm_ops bh1780_dev_pm_ops = {

SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,

pm_runtime_force_resume)

SET_RUNTIME_PM_OPS(bh1780_runtime_suspend,

bh1780_runtime_resume, NULL)

};

static const struct i2c_device_id bh1780_id[] = {

{ "bh1780", 0 },

{ },

};

MODULE_DEVICE_TABLE(i2c, bh1780_id);

#ifdef CONFIG_OF

static const struct of_device_id of_bh1780_match[] = {

{ .compatible = "rohm,bh1780gli", },

{},

};

MODULE_DEVICE_TABLE(of, of_bh1780_match);

#endif

static struct i2c_driver bh1780_driver = {

.probe= bh1780_probe,

.remove= bh1780_remove,

.id_table= bh1780_id,

.driver = {

.name = "bh1780",

.pm = &bh1780_dev_pm_ops,

.of_match_table = of_match_ptr(of_bh1780_match),

},

};

module_i2c_driver(bh1780_driver);

MODULE_DESCRIPTION("ROHM BH1780GLI Ambient Light Sensor Driver");

MODULE_LICENSE("GPL");

MODULE_AUTHOR("Linus Walleij ");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值