Commit | Line | Data |
---|---|---|
e4a70e3e LB |
1 | /* |
2 | * STMicroelectronics hts221 i2c driver | |
3 | * | |
4 | * Copyright 2016 STMicroelectronics Inc. | |
5 | * | |
6 | * Lorenzo Bianconi <lorenzo.bianconi@st.com> | |
7 | * | |
8 | * Licensed under the GPL-2. | |
9 | */ | |
10 | ||
11 | #include <linux/kernel.h> | |
12 | #include <linux/module.h> | |
25fc503e | 13 | #include <linux/acpi.h> |
e4a70e3e LB |
14 | #include <linux/i2c.h> |
15 | #include <linux/slab.h> | |
16 | #include "hts221.h" | |
17 | ||
18 | #define I2C_AUTO_INCREMENT 0x80 | |
19 | ||
20 | static int hts221_i2c_read(struct device *dev, u8 addr, int len, u8 *data) | |
21 | { | |
22 | struct i2c_msg msg[2]; | |
23 | struct i2c_client *client = to_i2c_client(dev); | |
24 | ||
25 | if (len > 1) | |
26 | addr |= I2C_AUTO_INCREMENT; | |
27 | ||
28 | msg[0].addr = client->addr; | |
29 | msg[0].flags = client->flags; | |
30 | msg[0].len = 1; | |
31 | msg[0].buf = &addr; | |
32 | ||
33 | msg[1].addr = client->addr; | |
34 | msg[1].flags = client->flags | I2C_M_RD; | |
35 | msg[1].len = len; | |
36 | msg[1].buf = data; | |
37 | ||
38 | return i2c_transfer(client->adapter, msg, 2); | |
39 | } | |
40 | ||
41 | static int hts221_i2c_write(struct device *dev, u8 addr, int len, u8 *data) | |
42 | { | |
43 | u8 send[len + 1]; | |
44 | struct i2c_msg msg; | |
45 | struct i2c_client *client = to_i2c_client(dev); | |
46 | ||
47 | if (len > 1) | |
48 | addr |= I2C_AUTO_INCREMENT; | |
49 | ||
50 | send[0] = addr; | |
51 | memcpy(&send[1], data, len * sizeof(u8)); | |
52 | ||
53 | msg.addr = client->addr; | |
54 | msg.flags = client->flags; | |
55 | msg.len = len + 1; | |
56 | msg.buf = send; | |
57 | ||
58 | return i2c_transfer(client->adapter, &msg, 1); | |
59 | } | |
60 | ||
61 | static const struct hts221_transfer_function hts221_transfer_fn = { | |
62 | .read = hts221_i2c_read, | |
63 | .write = hts221_i2c_write, | |
64 | }; | |
65 | ||
66 | static int hts221_i2c_probe(struct i2c_client *client, | |
67 | const struct i2c_device_id *id) | |
68 | { | |
69 | struct hts221_hw *hw; | |
70 | struct iio_dev *iio_dev; | |
71 | ||
72 | iio_dev = devm_iio_device_alloc(&client->dev, sizeof(*hw)); | |
73 | if (!iio_dev) | |
74 | return -ENOMEM; | |
75 | ||
76 | i2c_set_clientdata(client, iio_dev); | |
77 | ||
78 | hw = iio_priv(iio_dev); | |
79 | hw->name = client->name; | |
80 | hw->dev = &client->dev; | |
81 | hw->irq = client->irq; | |
82 | hw->tf = &hts221_transfer_fn; | |
83 | ||
84 | return hts221_probe(iio_dev); | |
85 | } | |
86 | ||
25fc503e SB |
87 | static const struct acpi_device_id hts221_acpi_match[] = { |
88 | {"SMO9100", 0}, | |
89 | { }, | |
90 | }; | |
91 | MODULE_DEVICE_TABLE(acpi, hts221_acpi_match); | |
92 | ||
e4a70e3e LB |
93 | static const struct of_device_id hts221_i2c_of_match[] = { |
94 | { .compatible = "st,hts221", }, | |
95 | {}, | |
96 | }; | |
97 | MODULE_DEVICE_TABLE(of, hts221_i2c_of_match); | |
98 | ||
99 | static const struct i2c_device_id hts221_i2c_id_table[] = { | |
100 | { HTS221_DEV_NAME }, | |
101 | {}, | |
102 | }; | |
103 | MODULE_DEVICE_TABLE(i2c, hts221_i2c_id_table); | |
104 | ||
105 | static struct i2c_driver hts221_driver = { | |
106 | .driver = { | |
107 | .name = "hts221_i2c", | |
b7079eea | 108 | .pm = &hts221_pm_ops, |
e4a70e3e | 109 | .of_match_table = of_match_ptr(hts221_i2c_of_match), |
25fc503e | 110 | .acpi_match_table = ACPI_PTR(hts221_acpi_match), |
e4a70e3e LB |
111 | }, |
112 | .probe = hts221_i2c_probe, | |
113 | .id_table = hts221_i2c_id_table, | |
114 | }; | |
115 | module_i2c_driver(hts221_driver); | |
116 | ||
117 | MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>"); | |
118 | MODULE_DESCRIPTION("STMicroelectronics hts221 i2c driver"); | |
119 | MODULE_LICENSE("GPL v2"); |