]>
Commit | Line | Data |
---|---|---|
56ca9db8 PC |
1 | /* |
2 | * AD5593R Digital <-> Analog converters driver | |
3 | * | |
4 | * Copyright 2015-2016 Analog Devices Inc. | |
5 | * Author: Paul Cercueil <[email protected]> | |
6 | * | |
7 | * Licensed under the GPL-2. | |
8 | */ | |
9 | ||
10 | #include "ad5592r-base.h" | |
11 | ||
12 | #include <linux/bitops.h> | |
13 | #include <linux/i2c.h> | |
14 | #include <linux/module.h> | |
15 | #include <linux/of.h> | |
2cc5b0df | 16 | #include <linux/acpi.h> |
56ca9db8 PC |
17 | |
18 | #define AD5593R_MODE_CONF (0 << 4) | |
19 | #define AD5593R_MODE_DAC_WRITE (1 << 4) | |
20 | #define AD5593R_MODE_ADC_READBACK (4 << 4) | |
21 | #define AD5593R_MODE_DAC_READBACK (5 << 4) | |
22 | #define AD5593R_MODE_GPIO_READBACK (6 << 4) | |
23 | #define AD5593R_MODE_REG_READBACK (7 << 4) | |
24 | ||
25 | static int ad5593r_write_dac(struct ad5592r_state *st, unsigned chan, u16 value) | |
26 | { | |
27 | struct i2c_client *i2c = to_i2c_client(st->dev); | |
28 | ||
29 | return i2c_smbus_write_word_swapped(i2c, | |
30 | AD5593R_MODE_DAC_WRITE | chan, value); | |
31 | } | |
32 | ||
33 | static int ad5593r_read_adc(struct ad5592r_state *st, unsigned chan, u16 *value) | |
34 | { | |
35 | struct i2c_client *i2c = to_i2c_client(st->dev); | |
36 | s32 val; | |
37 | ||
38 | val = i2c_smbus_write_word_swapped(i2c, | |
39 | AD5593R_MODE_CONF | AD5592R_REG_ADC_SEQ, BIT(chan)); | |
40 | if (val < 0) | |
41 | return (int) val; | |
42 | ||
43 | val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_ADC_READBACK); | |
44 | if (val < 0) | |
45 | return (int) val; | |
46 | ||
47 | *value = (u16) val; | |
48 | ||
49 | return 0; | |
50 | } | |
51 | ||
52 | static int ad5593r_reg_write(struct ad5592r_state *st, u8 reg, u16 value) | |
53 | { | |
54 | struct i2c_client *i2c = to_i2c_client(st->dev); | |
55 | ||
56 | return i2c_smbus_write_word_swapped(i2c, | |
57 | AD5593R_MODE_CONF | reg, value); | |
58 | } | |
59 | ||
60 | static int ad5593r_reg_read(struct ad5592r_state *st, u8 reg, u16 *value) | |
61 | { | |
62 | struct i2c_client *i2c = to_i2c_client(st->dev); | |
63 | s32 val; | |
64 | ||
65 | val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_REG_READBACK | reg); | |
66 | if (val < 0) | |
67 | return (int) val; | |
68 | ||
69 | *value = (u16) val; | |
70 | ||
71 | return 0; | |
72 | } | |
73 | ||
74 | static int ad5593r_gpio_read(struct ad5592r_state *st, u8 *value) | |
75 | { | |
76 | struct i2c_client *i2c = to_i2c_client(st->dev); | |
77 | s32 val; | |
78 | ||
79 | val = i2c_smbus_read_word_swapped(i2c, AD5593R_MODE_GPIO_READBACK); | |
80 | if (val < 0) | |
81 | return (int) val; | |
82 | ||
83 | *value = (u8) val; | |
84 | ||
85 | return 0; | |
86 | } | |
87 | ||
88 | static const struct ad5592r_rw_ops ad5593r_rw_ops = { | |
89 | .write_dac = ad5593r_write_dac, | |
90 | .read_adc = ad5593r_read_adc, | |
91 | .reg_write = ad5593r_reg_write, | |
92 | .reg_read = ad5593r_reg_read, | |
93 | .gpio_read = ad5593r_gpio_read, | |
94 | }; | |
95 | ||
96 | static int ad5593r_i2c_probe(struct i2c_client *i2c, | |
97 | const struct i2c_device_id *id) | |
98 | { | |
99 | return ad5592r_probe(&i2c->dev, id->name, &ad5593r_rw_ops); | |
100 | } | |
101 | ||
102 | static int ad5593r_i2c_remove(struct i2c_client *i2c) | |
103 | { | |
104 | return ad5592r_remove(&i2c->dev); | |
105 | } | |
106 | ||
107 | static const struct i2c_device_id ad5593r_i2c_ids[] = { | |
108 | { .name = "ad5593r", }, | |
109 | {}, | |
110 | }; | |
111 | MODULE_DEVICE_TABLE(i2c, ad5593r_i2c_ids); | |
112 | ||
113 | static const struct of_device_id ad5593r_of_match[] = { | |
114 | { .compatible = "adi,ad5593r", }, | |
115 | {}, | |
116 | }; | |
117 | MODULE_DEVICE_TABLE(of, ad5593r_of_match); | |
118 | ||
2cc5b0df MH |
119 | static const struct acpi_device_id ad5593r_acpi_match[] = { |
120 | {"ADS5593", }, | |
121 | { }, | |
122 | }; | |
123 | MODULE_DEVICE_TABLE(acpi, ad5593r_acpi_match); | |
124 | ||
56ca9db8 PC |
125 | static struct i2c_driver ad5593r_driver = { |
126 | .driver = { | |
127 | .name = "ad5593r", | |
128 | .of_match_table = of_match_ptr(ad5593r_of_match), | |
2cc5b0df | 129 | .acpi_match_table = ACPI_PTR(ad5593r_acpi_match), |
56ca9db8 PC |
130 | }, |
131 | .probe = ad5593r_i2c_probe, | |
132 | .remove = ad5593r_i2c_remove, | |
133 | .id_table = ad5593r_i2c_ids, | |
134 | }; | |
135 | module_i2c_driver(ad5593r_driver); | |
136 | ||
137 | MODULE_AUTHOR("Paul Cercueil <[email protected]>"); | |
138 | MODULE_DESCRIPTION("Analog Devices AD5592R multi-channel converters"); | |
139 | MODULE_LICENSE("GPL v2"); |