]>
Commit | Line | Data |
---|---|---|
1f67b599 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
1a6e4b74 VK |
2 | /* |
3 | * ST Microelectronics MFD: stmpe's i2c client specific driver | |
4 | * | |
5 | * Copyright (C) ST-Ericsson SA 2010 | |
6 | * Copyright (C) ST Microelectronics SA 2011 | |
7 | * | |
1a6e4b74 | 8 | * Author: Rabin Vincent <[email protected]> for ST-Ericsson |
da89947b | 9 | * Author: Viresh Kumar <[email protected]> for ST Microelectronics |
1a6e4b74 VK |
10 | */ |
11 | ||
12 | #include <linux/i2c.h> | |
13 | #include <linux/interrupt.h> | |
14 | #include <linux/kernel.h> | |
15 | #include <linux/module.h> | |
16 | #include <linux/types.h> | |
5a826fee | 17 | #include <linux/of_device.h> |
1a6e4b74 VK |
18 | #include "stmpe.h" |
19 | ||
20 | static int i2c_reg_read(struct stmpe *stmpe, u8 reg) | |
21 | { | |
22 | struct i2c_client *i2c = stmpe->client; | |
23 | ||
24 | return i2c_smbus_read_byte_data(i2c, reg); | |
25 | } | |
26 | ||
27 | static int i2c_reg_write(struct stmpe *stmpe, u8 reg, u8 val) | |
28 | { | |
29 | struct i2c_client *i2c = stmpe->client; | |
30 | ||
31 | return i2c_smbus_write_byte_data(i2c, reg, val); | |
32 | } | |
33 | ||
34 | static int i2c_block_read(struct stmpe *stmpe, u8 reg, u8 length, u8 *values) | |
35 | { | |
36 | struct i2c_client *i2c = stmpe->client; | |
37 | ||
38 | return i2c_smbus_read_i2c_block_data(i2c, reg, length, values); | |
39 | } | |
40 | ||
41 | static int i2c_block_write(struct stmpe *stmpe, u8 reg, u8 length, | |
42 | const u8 *values) | |
43 | { | |
44 | struct i2c_client *i2c = stmpe->client; | |
45 | ||
46 | return i2c_smbus_write_i2c_block_data(i2c, reg, length, values); | |
47 | } | |
48 | ||
49 | static struct stmpe_client_info i2c_ci = { | |
50 | .read_byte = i2c_reg_read, | |
51 | .write_byte = i2c_reg_write, | |
52 | .read_block = i2c_block_read, | |
53 | .write_block = i2c_block_write, | |
54 | }; | |
55 | ||
5a826fee LW |
56 | static const struct of_device_id stmpe_of_match[] = { |
57 | { .compatible = "st,stmpe610", .data = (void *)STMPE610, }, | |
58 | { .compatible = "st,stmpe801", .data = (void *)STMPE801, }, | |
59 | { .compatible = "st,stmpe811", .data = (void *)STMPE811, }, | |
6bb9f0d9 | 60 | { .compatible = "st,stmpe1600", .data = (void *)STMPE1600, }, |
5a826fee LW |
61 | { .compatible = "st,stmpe1601", .data = (void *)STMPE1601, }, |
62 | { .compatible = "st,stmpe1801", .data = (void *)STMPE1801, }, | |
63 | { .compatible = "st,stmpe2401", .data = (void *)STMPE2401, }, | |
64 | { .compatible = "st,stmpe2403", .data = (void *)STMPE2403, }, | |
65 | {}, | |
66 | }; | |
67 | MODULE_DEVICE_TABLE(of, stmpe_of_match); | |
68 | ||
f791be49 | 69 | static int |
50b1d5ba | 70 | stmpe_i2c_probe(struct i2c_client *i2c) |
1a6e4b74 | 71 | { |
50b1d5ba | 72 | const struct i2c_device_id *id = i2c_client_get_device_id(i2c); |
c00572bc | 73 | enum stmpe_partnum partnum; |
5a826fee LW |
74 | const struct of_device_id *of_id; |
75 | ||
1a6e4b74 VK |
76 | i2c_ci.data = (void *)id; |
77 | i2c_ci.irq = i2c->irq; | |
78 | i2c_ci.client = i2c; | |
79 | i2c_ci.dev = &i2c->dev; | |
80 | ||
5a826fee LW |
81 | of_id = of_match_device(stmpe_of_match, &i2c->dev); |
82 | if (!of_id) { | |
83 | /* | |
84 | * This happens when the I2C ID matches the node name | |
85 | * but no real compatible string has been given. | |
86 | */ | |
87 | dev_info(&i2c->dev, "matching on node name, compatible is preferred\n"); | |
88 | partnum = id->driver_data; | |
89 | } else | |
4db65f45 | 90 | partnum = (uintptr_t)of_id->data; |
5a826fee LW |
91 | |
92 | return stmpe_probe(&i2c_ci, partnum); | |
1a6e4b74 VK |
93 | } |
94 | ||
ed5c2f5f | 95 | static void stmpe_i2c_remove(struct i2c_client *i2c) |
1a6e4b74 VK |
96 | { |
97 | struct stmpe *stmpe = dev_get_drvdata(&i2c->dev); | |
98 | ||
356bbaba | 99 | stmpe_remove(stmpe); |
1a6e4b74 VK |
100 | } |
101 | ||
102 | static const struct i2c_device_id stmpe_i2c_id[] = { | |
1cda2394 | 103 | { "stmpe610", STMPE610 }, |
7f7f4ea1 | 104 | { "stmpe801", STMPE801 }, |
1a6e4b74 | 105 | { "stmpe811", STMPE811 }, |
6bb9f0d9 | 106 | { "stmpe1600", STMPE1600 }, |
1a6e4b74 | 107 | { "stmpe1601", STMPE1601 }, |
230f13a5 | 108 | { "stmpe1801", STMPE1801 }, |
1a6e4b74 VK |
109 | { "stmpe2401", STMPE2401 }, |
110 | { "stmpe2403", STMPE2403 }, | |
111 | { } | |
112 | }; | |
4700ef32 | 113 | MODULE_DEVICE_TABLE(i2c, stmpe_i2c_id); |
1a6e4b74 VK |
114 | |
115 | static struct i2c_driver stmpe_i2c_driver = { | |
32533983 VK |
116 | .driver = { |
117 | .name = "stmpe-i2c", | |
f7f292fe | 118 | .pm = pm_sleep_ptr(&stmpe_dev_pm_ops), |
5a826fee | 119 | .of_match_table = stmpe_of_match, |
32533983 | 120 | }, |
9816d859 | 121 | .probe = stmpe_i2c_probe, |
84449216 | 122 | .remove = stmpe_i2c_remove, |
1a6e4b74 VK |
123 | .id_table = stmpe_i2c_id, |
124 | }; | |
125 | ||
126 | static int __init stmpe_init(void) | |
127 | { | |
128 | return i2c_add_driver(&stmpe_i2c_driver); | |
129 | } | |
130 | subsys_initcall(stmpe_init); | |
131 | ||
132 | static void __exit stmpe_exit(void) | |
133 | { | |
134 | i2c_del_driver(&stmpe_i2c_driver); | |
135 | } | |
136 | module_exit(stmpe_exit); | |
137 | ||
1a6e4b74 VK |
138 | MODULE_DESCRIPTION("STMPE MFD I2C Interface Driver"); |
139 | MODULE_AUTHOR("Rabin Vincent <[email protected]>"); |