Commit | Line | Data |
---|---|---|
1c743ad5 MV |
1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | // | |
3 | // Copyright (C) 2019 ROHM Semiconductors | |
4 | // | |
4dcdcfd5 | 5 | // ROHM BD71828/BD71815 PMIC driver |
1c743ad5 | 6 | |
e795bf72 | 7 | #include <linux/gpio_keys.h> |
1c743ad5 | 8 | #include <linux/i2c.h> |
e795bf72 | 9 | #include <linux/input.h> |
1c743ad5 MV |
10 | #include <linux/interrupt.h> |
11 | #include <linux/ioport.h> | |
12 | #include <linux/irq.h> | |
13 | #include <linux/mfd/core.h> | |
4dcdcfd5 | 14 | #include <linux/mfd/rohm-bd71815.h> |
1c743ad5 | 15 | #include <linux/mfd/rohm-bd71828.h> |
4dcdcfd5 | 16 | #include <linux/mfd/rohm-generic.h> |
1c743ad5 MV |
17 | #include <linux/module.h> |
18 | #include <linux/of_device.h> | |
19 | #include <linux/regmap.h> | |
20 | #include <linux/types.h> | |
21 | ||
e795bf72 MV |
22 | static struct gpio_keys_button button = { |
23 | .code = KEY_POWER, | |
24 | .gpio = -1, | |
25 | .type = EV_KEY, | |
26 | }; | |
27 | ||
28 | static struct gpio_keys_platform_data bd71828_powerkey_data = { | |
29 | .buttons = &button, | |
30 | .nbuttons = 1, | |
31 | .name = "bd71828-pwrkey", | |
32 | }; | |
33 | ||
4dcdcfd5 MV |
34 | static const struct resource bd71815_rtc_irqs[] = { |
35 | DEFINE_RES_IRQ_NAMED(BD71815_INT_RTC0, "bd71815-rtc-alm-0"), | |
36 | DEFINE_RES_IRQ_NAMED(BD71815_INT_RTC1, "bd71815-rtc-alm-1"), | |
37 | DEFINE_RES_IRQ_NAMED(BD71815_INT_RTC2, "bd71815-rtc-alm-2"), | |
38 | }; | |
39 | ||
40 | static const struct resource bd71828_rtc_irqs[] = { | |
1c743ad5 MV |
41 | DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC0, "bd71828-rtc-alm-0"), |
42 | DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC1, "bd71828-rtc-alm-1"), | |
43 | DEFINE_RES_IRQ_NAMED(BD71828_INT_RTC2, "bd71828-rtc-alm-2"), | |
44 | }; | |
45 | ||
4dcdcfd5 MV |
46 | static struct resource bd71815_power_irqs[] = { |
47 | DEFINE_RES_IRQ_NAMED(BD71815_INT_DCIN_RMV, "bd71815-dcin-rmv"), | |
48 | DEFINE_RES_IRQ_NAMED(BD71815_INT_CLPS_OUT, "bd71815-clps-out"), | |
49 | DEFINE_RES_IRQ_NAMED(BD71815_INT_CLPS_IN, "bd71815-clps-in"), | |
50 | DEFINE_RES_IRQ_NAMED(BD71815_INT_DCIN_OVP_RES, "bd71815-dcin-ovp-res"), | |
51 | DEFINE_RES_IRQ_NAMED(BD71815_INT_DCIN_OVP_DET, "bd71815-dcin-ovp-det"), | |
52 | DEFINE_RES_IRQ_NAMED(BD71815_INT_DCIN_MON_RES, "bd71815-dcin-mon-res"), | |
53 | DEFINE_RES_IRQ_NAMED(BD71815_INT_DCIN_MON_DET, "bd71815-dcin-mon-det"), | |
54 | DEFINE_RES_IRQ_NAMED(BD71815_INT_VSYS_UV_RES, "bd71815-vsys-uv-res"), | |
55 | DEFINE_RES_IRQ_NAMED(BD71815_INT_VSYS_UV_DET, "bd71815-vsys-uv-det"), | |
56 | DEFINE_RES_IRQ_NAMED(BD71815_INT_VSYS_LOW_RES, "bd71815-vsys-low-res"), | |
57 | DEFINE_RES_IRQ_NAMED(BD71815_INT_VSYS_LOW_DET, "bd71815-vsys-low-det"), | |
58 | DEFINE_RES_IRQ_NAMED(BD71815_INT_VSYS_MON_RES, "bd71815-vsys-mon-res"), | |
59 | DEFINE_RES_IRQ_NAMED(BD71815_INT_VSYS_MON_RES, "bd71815-vsys-mon-det"), | |
60 | DEFINE_RES_IRQ_NAMED(BD71815_INT_CHG_WDG_TEMP, "bd71815-chg-wdg-temp"), | |
61 | DEFINE_RES_IRQ_NAMED(BD71815_INT_CHG_WDG_TIME, "bd71815-chg-wdg"), | |
62 | DEFINE_RES_IRQ_NAMED(BD71815_INT_CHG_RECHARGE_RES, "bd71815-rechg-res"), | |
63 | DEFINE_RES_IRQ_NAMED(BD71815_INT_CHG_RECHARGE_DET, "bd71815-rechg-det"), | |
64 | DEFINE_RES_IRQ_NAMED(BD71815_INT_CHG_RANGED_TEMP_TRANSITION, "bd71815-ranged-temp-transit"), | |
65 | DEFINE_RES_IRQ_NAMED(BD71815_INT_CHG_STATE_TRANSITION, "bd71815-chg-state-change"), | |
66 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_TEMP_NORMAL, "bd71815-bat-temp-normal"), | |
67 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_TEMP_ERANGE, "bd71815-bat-temp-erange"), | |
68 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_REMOVED, "bd71815-bat-rmv"), | |
69 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_DETECTED, "bd71815-bat-det"), | |
70 | DEFINE_RES_IRQ_NAMED(BD71815_INT_THERM_REMOVED, "bd71815-therm-rmv"), | |
71 | DEFINE_RES_IRQ_NAMED(BD71815_INT_THERM_DETECTED, "bd71815-therm-det"), | |
72 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_DEAD, "bd71815-bat-dead"), | |
73 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_SHORTC_RES, "bd71815-bat-short-res"), | |
74 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_SHORTC_DET, "bd71815-bat-short-det"), | |
75 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_LOW_VOLT_RES, "bd71815-bat-low-res"), | |
76 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_LOW_VOLT_DET, "bd71815-bat-low-det"), | |
77 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_OVER_VOLT_RES, "bd71815-bat-over-res"), | |
78 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_OVER_VOLT_DET, "bd71815-bat-over-det"), | |
79 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_MON_RES, "bd71815-bat-mon-res"), | |
80 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_MON_DET, "bd71815-bat-mon-det"), | |
81 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_CC_MON1, "bd71815-bat-cc-mon1"), | |
82 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_CC_MON2, "bd71815-bat-cc-mon2"), | |
83 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_CC_MON3, "bd71815-bat-cc-mon3"), | |
84 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_OVER_CURR_1_RES, "bd71815-bat-oc1-res"), | |
85 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_OVER_CURR_1_DET, "bd71815-bat-oc1-det"), | |
86 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_OVER_CURR_2_RES, "bd71815-bat-oc2-res"), | |
87 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_OVER_CURR_2_DET, "bd71815-bat-oc2-det"), | |
88 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_OVER_CURR_3_RES, "bd71815-bat-oc3-res"), | |
89 | DEFINE_RES_IRQ_NAMED(BD71815_INT_BAT_OVER_CURR_3_DET, "bd71815-bat-oc3-det"), | |
90 | DEFINE_RES_IRQ_NAMED(BD71815_INT_TEMP_BAT_LOW_RES, "bd71815-bat-low-res"), | |
91 | DEFINE_RES_IRQ_NAMED(BD71815_INT_TEMP_BAT_LOW_DET, "bd71815-bat-low-det"), | |
92 | DEFINE_RES_IRQ_NAMED(BD71815_INT_TEMP_BAT_HI_RES, "bd71815-bat-hi-res"), | |
93 | DEFINE_RES_IRQ_NAMED(BD71815_INT_TEMP_BAT_HI_DET, "bd71815-bat-hi-det"), | |
94 | }; | |
95 | ||
96 | static struct mfd_cell bd71815_mfd_cells[] = { | |
97 | { .name = "bd71815-pmic", }, | |
98 | { .name = "bd71815-clk", }, | |
99 | { .name = "bd71815-gpo", }, | |
100 | { | |
101 | .name = "bd71815-power", | |
102 | .num_resources = ARRAY_SIZE(bd71815_power_irqs), | |
103 | .resources = &bd71815_power_irqs[0], | |
104 | }, | |
105 | { | |
106 | .name = "bd71815-rtc", | |
107 | .num_resources = ARRAY_SIZE(bd71815_rtc_irqs), | |
108 | .resources = &bd71815_rtc_irqs[0], | |
109 | }, | |
110 | }; | |
111 | ||
1c743ad5 MV |
112 | static struct mfd_cell bd71828_mfd_cells[] = { |
113 | { .name = "bd71828-pmic", }, | |
114 | { .name = "bd71828-gpio", }, | |
115 | { .name = "bd71828-led", .of_compatible = "rohm,bd71828-leds" }, | |
116 | /* | |
117 | * We use BD71837 driver to drive the clock block. Only differences to | |
118 | * BD70528 clock gate are the register address and mask. | |
119 | */ | |
120 | { .name = "bd71828-clk", }, | |
121 | { .name = "bd71827-power", }, | |
122 | { | |
123 | .name = "bd71828-rtc", | |
4dcdcfd5 MV |
124 | .resources = bd71828_rtc_irqs, |
125 | .num_resources = ARRAY_SIZE(bd71828_rtc_irqs), | |
e795bf72 MV |
126 | }, { |
127 | .name = "gpio-keys", | |
128 | .platform_data = &bd71828_powerkey_data, | |
129 | .pdata_size = sizeof(bd71828_powerkey_data), | |
1c743ad5 MV |
130 | }, |
131 | }; | |
132 | ||
4dcdcfd5 MV |
133 | static const struct regmap_range bd71815_volatile_ranges[] = { |
134 | { | |
135 | .range_min = BD71815_REG_SEC, | |
136 | .range_max = BD71815_REG_YEAR, | |
137 | }, { | |
138 | .range_min = BD71815_REG_CONF, | |
139 | .range_max = BD71815_REG_BAT_TEMP, | |
140 | }, { | |
141 | .range_min = BD71815_REG_VM_IBAT_U, | |
142 | .range_max = BD71815_REG_CC_CTRL, | |
143 | }, { | |
144 | .range_min = BD71815_REG_CC_STAT, | |
145 | .range_max = BD71815_REG_CC_CURCD_L, | |
146 | }, { | |
147 | .range_min = BD71815_REG_VM_BTMP_MON, | |
148 | .range_max = BD71815_REG_VM_BTMP_MON, | |
149 | }, { | |
150 | .range_min = BD71815_REG_INT_STAT, | |
151 | .range_max = BD71815_REG_INT_UPDATE, | |
152 | }, { | |
153 | .range_min = BD71815_REG_VM_VSYS_U, | |
154 | .range_max = BD71815_REG_REX_CTRL_1, | |
155 | }, { | |
156 | .range_min = BD71815_REG_FULL_CCNTD_3, | |
157 | .range_max = BD71815_REG_CCNTD_CHG_2, | |
158 | }, | |
159 | }; | |
160 | ||
161 | static const struct regmap_range bd71828_volatile_ranges[] = { | |
1c743ad5 MV |
162 | { |
163 | .range_min = BD71828_REG_PS_CTRL_1, | |
164 | .range_max = BD71828_REG_PS_CTRL_1, | |
165 | }, { | |
166 | .range_min = BD71828_REG_PS_CTRL_3, | |
167 | .range_max = BD71828_REG_PS_CTRL_3, | |
168 | }, { | |
169 | .range_min = BD71828_REG_RTC_SEC, | |
170 | .range_max = BD71828_REG_RTC_YEAR, | |
171 | }, { | |
172 | /* | |
173 | * For now make all charger registers volatile because many | |
174 | * needs to be and because the charger block is not that | |
175 | * performance critical. | |
176 | */ | |
177 | .range_min = BD71828_REG_CHG_STATE, | |
178 | .range_max = BD71828_REG_CHG_FULL, | |
179 | }, { | |
180 | .range_min = BD71828_REG_INT_MAIN, | |
181 | .range_max = BD71828_REG_IO_STAT, | |
182 | }, | |
183 | }; | |
184 | ||
4dcdcfd5 MV |
185 | static const struct regmap_access_table bd71815_volatile_regs = { |
186 | .yes_ranges = &bd71815_volatile_ranges[0], | |
187 | .n_yes_ranges = ARRAY_SIZE(bd71815_volatile_ranges), | |
188 | }; | |
189 | ||
190 | static const struct regmap_access_table bd71828_volatile_regs = { | |
191 | .yes_ranges = &bd71828_volatile_ranges[0], | |
192 | .n_yes_ranges = ARRAY_SIZE(bd71828_volatile_ranges), | |
193 | }; | |
194 | ||
195 | static const struct regmap_config bd71815_regmap = { | |
196 | .reg_bits = 8, | |
197 | .val_bits = 8, | |
198 | .volatile_table = &bd71815_volatile_regs, | |
199 | .max_register = BD71815_MAX_REGISTER - 1, | |
200 | .cache_type = REGCACHE_RBTREE, | |
1c743ad5 MV |
201 | }; |
202 | ||
4dcdcfd5 | 203 | static const struct regmap_config bd71828_regmap = { |
1c743ad5 MV |
204 | .reg_bits = 8, |
205 | .val_bits = 8, | |
4dcdcfd5 | 206 | .volatile_table = &bd71828_volatile_regs, |
1c743ad5 MV |
207 | .max_register = BD71828_MAX_REGISTER, |
208 | .cache_type = REGCACHE_RBTREE, | |
209 | }; | |
210 | ||
211 | /* | |
212 | * Mapping of main IRQ register bits to sub-IRQ register offsets so that we can | |
213 | * access corect sub-IRQ registers based on bits that are set in main IRQ | |
4dcdcfd5 | 214 | * register. BD71815 and BD71828 have same sub-register-block offests. |
1c743ad5 MV |
215 | */ |
216 | ||
217 | static unsigned int bit0_offsets[] = {11}; /* RTC IRQ */ | |
218 | static unsigned int bit1_offsets[] = {10}; /* TEMP IRQ */ | |
219 | static unsigned int bit2_offsets[] = {6, 7, 8, 9}; /* BAT MON IRQ */ | |
220 | static unsigned int bit3_offsets[] = {5}; /* BAT IRQ */ | |
221 | static unsigned int bit4_offsets[] = {4}; /* CHG IRQ */ | |
222 | static unsigned int bit5_offsets[] = {3}; /* VSYS IRQ */ | |
223 | static unsigned int bit6_offsets[] = {1, 2}; /* DCIN IRQ */ | |
224 | static unsigned int bit7_offsets[] = {0}; /* BUCK IRQ */ | |
225 | ||
4dcdcfd5 | 226 | static struct regmap_irq_sub_irq_map bd718xx_sub_irq_offsets[] = { |
1c743ad5 MV |
227 | REGMAP_IRQ_MAIN_REG_OFFSET(bit0_offsets), |
228 | REGMAP_IRQ_MAIN_REG_OFFSET(bit1_offsets), | |
229 | REGMAP_IRQ_MAIN_REG_OFFSET(bit2_offsets), | |
230 | REGMAP_IRQ_MAIN_REG_OFFSET(bit3_offsets), | |
231 | REGMAP_IRQ_MAIN_REG_OFFSET(bit4_offsets), | |
232 | REGMAP_IRQ_MAIN_REG_OFFSET(bit5_offsets), | |
233 | REGMAP_IRQ_MAIN_REG_OFFSET(bit6_offsets), | |
234 | REGMAP_IRQ_MAIN_REG_OFFSET(bit7_offsets), | |
235 | }; | |
236 | ||
4dcdcfd5 MV |
237 | static const struct regmap_irq bd71815_irqs[] = { |
238 | REGMAP_IRQ_REG(BD71815_INT_BUCK1_OCP, 0, BD71815_INT_BUCK1_OCP_MASK), | |
239 | REGMAP_IRQ_REG(BD71815_INT_BUCK2_OCP, 0, BD71815_INT_BUCK2_OCP_MASK), | |
240 | REGMAP_IRQ_REG(BD71815_INT_BUCK3_OCP, 0, BD71815_INT_BUCK3_OCP_MASK), | |
241 | REGMAP_IRQ_REG(BD71815_INT_BUCK4_OCP, 0, BD71815_INT_BUCK4_OCP_MASK), | |
242 | REGMAP_IRQ_REG(BD71815_INT_BUCK5_OCP, 0, BD71815_INT_BUCK5_OCP_MASK), | |
243 | REGMAP_IRQ_REG(BD71815_INT_LED_OVP, 0, BD71815_INT_LED_OVP_MASK), | |
244 | REGMAP_IRQ_REG(BD71815_INT_LED_OCP, 0, BD71815_INT_LED_OCP_MASK), | |
245 | REGMAP_IRQ_REG(BD71815_INT_LED_SCP, 0, BD71815_INT_LED_SCP_MASK), | |
246 | /* DCIN1 interrupts */ | |
247 | REGMAP_IRQ_REG(BD71815_INT_DCIN_RMV, 1, BD71815_INT_DCIN_RMV_MASK), | |
248 | REGMAP_IRQ_REG(BD71815_INT_CLPS_OUT, 1, BD71815_INT_CLPS_OUT_MASK), | |
249 | REGMAP_IRQ_REG(BD71815_INT_CLPS_IN, 1, BD71815_INT_CLPS_IN_MASK), | |
250 | REGMAP_IRQ_REG(BD71815_INT_DCIN_OVP_RES, 1, BD71815_INT_DCIN_OVP_RES_MASK), | |
251 | REGMAP_IRQ_REG(BD71815_INT_DCIN_OVP_DET, 1, BD71815_INT_DCIN_OVP_DET_MASK), | |
252 | /* DCIN2 interrupts */ | |
253 | REGMAP_IRQ_REG(BD71815_INT_DCIN_MON_RES, 2, BD71815_INT_DCIN_MON_RES_MASK), | |
254 | REGMAP_IRQ_REG(BD71815_INT_DCIN_MON_DET, 2, BD71815_INT_DCIN_MON_DET_MASK), | |
255 | REGMAP_IRQ_REG(BD71815_INT_WDOG, 2, BD71815_INT_WDOG_MASK), | |
256 | /* Vsys */ | |
257 | REGMAP_IRQ_REG(BD71815_INT_VSYS_UV_RES, 3, BD71815_INT_VSYS_UV_RES_MASK), | |
258 | REGMAP_IRQ_REG(BD71815_INT_VSYS_UV_DET, 3, BD71815_INT_VSYS_UV_DET_MASK), | |
259 | REGMAP_IRQ_REG(BD71815_INT_VSYS_LOW_RES, 3, BD71815_INT_VSYS_LOW_RES_MASK), | |
260 | REGMAP_IRQ_REG(BD71815_INT_VSYS_LOW_DET, 3, BD71815_INT_VSYS_LOW_DET_MASK), | |
261 | REGMAP_IRQ_REG(BD71815_INT_VSYS_MON_RES, 3, BD71815_INT_VSYS_MON_RES_MASK), | |
262 | REGMAP_IRQ_REG(BD71815_INT_VSYS_MON_DET, 3, BD71815_INT_VSYS_MON_DET_MASK), | |
263 | /* Charger */ | |
264 | REGMAP_IRQ_REG(BD71815_INT_CHG_WDG_TEMP, 4, BD71815_INT_CHG_WDG_TEMP_MASK), | |
265 | REGMAP_IRQ_REG(BD71815_INT_CHG_WDG_TIME, 4, BD71815_INT_CHG_WDG_TIME_MASK), | |
266 | REGMAP_IRQ_REG(BD71815_INT_CHG_RECHARGE_RES, 4, BD71815_INT_CHG_RECHARGE_RES_MASK), | |
267 | REGMAP_IRQ_REG(BD71815_INT_CHG_RECHARGE_DET, 4, BD71815_INT_CHG_RECHARGE_DET_MASK), | |
268 | REGMAP_IRQ_REG(BD71815_INT_CHG_RANGED_TEMP_TRANSITION, 4, | |
269 | BD71815_INT_CHG_RANGED_TEMP_TRANSITION_MASK), | |
270 | REGMAP_IRQ_REG(BD71815_INT_CHG_STATE_TRANSITION, 4, BD71815_INT_CHG_STATE_TRANSITION_MASK), | |
271 | /* Battery */ | |
272 | REGMAP_IRQ_REG(BD71815_INT_BAT_TEMP_NORMAL, 5, BD71815_INT_BAT_TEMP_NORMAL_MASK), | |
273 | REGMAP_IRQ_REG(BD71815_INT_BAT_TEMP_ERANGE, 5, BD71815_INT_BAT_TEMP_ERANGE_MASK), | |
274 | REGMAP_IRQ_REG(BD71815_INT_BAT_REMOVED, 5, BD71815_INT_BAT_REMOVED_MASK), | |
275 | REGMAP_IRQ_REG(BD71815_INT_BAT_DETECTED, 5, BD71815_INT_BAT_DETECTED_MASK), | |
276 | REGMAP_IRQ_REG(BD71815_INT_THERM_REMOVED, 5, BD71815_INT_THERM_REMOVED_MASK), | |
277 | REGMAP_IRQ_REG(BD71815_INT_THERM_DETECTED, 5, BD71815_INT_THERM_DETECTED_MASK), | |
278 | /* Battery Mon 1 */ | |
279 | REGMAP_IRQ_REG(BD71815_INT_BAT_DEAD, 6, BD71815_INT_BAT_DEAD_MASK), | |
280 | REGMAP_IRQ_REG(BD71815_INT_BAT_SHORTC_RES, 6, BD71815_INT_BAT_SHORTC_RES_MASK), | |
281 | REGMAP_IRQ_REG(BD71815_INT_BAT_SHORTC_DET, 6, BD71815_INT_BAT_SHORTC_DET_MASK), | |
282 | REGMAP_IRQ_REG(BD71815_INT_BAT_LOW_VOLT_RES, 6, BD71815_INT_BAT_LOW_VOLT_RES_MASK), | |
283 | REGMAP_IRQ_REG(BD71815_INT_BAT_LOW_VOLT_DET, 6, BD71815_INT_BAT_LOW_VOLT_DET_MASK), | |
284 | REGMAP_IRQ_REG(BD71815_INT_BAT_OVER_VOLT_RES, 6, BD71815_INT_BAT_OVER_VOLT_RES_MASK), | |
285 | REGMAP_IRQ_REG(BD71815_INT_BAT_OVER_VOLT_DET, 6, BD71815_INT_BAT_OVER_VOLT_DET_MASK), | |
286 | /* Battery Mon 2 */ | |
287 | REGMAP_IRQ_REG(BD71815_INT_BAT_MON_RES, 7, BD71815_INT_BAT_MON_RES_MASK), | |
288 | REGMAP_IRQ_REG(BD71815_INT_BAT_MON_DET, 7, BD71815_INT_BAT_MON_DET_MASK), | |
289 | /* Battery Mon 3 (Coulomb counter) */ | |
290 | REGMAP_IRQ_REG(BD71815_INT_BAT_CC_MON1, 8, BD71815_INT_BAT_CC_MON1_MASK), | |
291 | REGMAP_IRQ_REG(BD71815_INT_BAT_CC_MON2, 8, BD71815_INT_BAT_CC_MON2_MASK), | |
292 | REGMAP_IRQ_REG(BD71815_INT_BAT_CC_MON3, 8, BD71815_INT_BAT_CC_MON3_MASK), | |
293 | /* Battery Mon 4 */ | |
294 | REGMAP_IRQ_REG(BD71815_INT_BAT_OVER_CURR_1_RES, 9, BD71815_INT_BAT_OVER_CURR_1_RES_MASK), | |
295 | REGMAP_IRQ_REG(BD71815_INT_BAT_OVER_CURR_1_DET, 9, BD71815_INT_BAT_OVER_CURR_1_DET_MASK), | |
296 | REGMAP_IRQ_REG(BD71815_INT_BAT_OVER_CURR_2_RES, 9, BD71815_INT_BAT_OVER_CURR_2_RES_MASK), | |
297 | REGMAP_IRQ_REG(BD71815_INT_BAT_OVER_CURR_2_DET, 9, BD71815_INT_BAT_OVER_CURR_2_DET_MASK), | |
298 | REGMAP_IRQ_REG(BD71815_INT_BAT_OVER_CURR_3_RES, 9, BD71815_INT_BAT_OVER_CURR_3_RES_MASK), | |
299 | REGMAP_IRQ_REG(BD71815_INT_BAT_OVER_CURR_3_DET, 9, BD71815_INT_BAT_OVER_CURR_3_DET_MASK), | |
300 | /* Temperature */ | |
301 | REGMAP_IRQ_REG(BD71815_INT_TEMP_BAT_LOW_RES, 10, BD71815_INT_TEMP_BAT_LOW_RES_MASK), | |
302 | REGMAP_IRQ_REG(BD71815_INT_TEMP_BAT_LOW_DET, 10, BD71815_INT_TEMP_BAT_LOW_DET_MASK), | |
303 | REGMAP_IRQ_REG(BD71815_INT_TEMP_BAT_HI_RES, 10, BD71815_INT_TEMP_BAT_HI_RES_MASK), | |
304 | REGMAP_IRQ_REG(BD71815_INT_TEMP_BAT_HI_DET, 10, BD71815_INT_TEMP_BAT_HI_DET_MASK), | |
305 | REGMAP_IRQ_REG(BD71815_INT_TEMP_CHIP_OVER_125_RES, 10, | |
306 | BD71815_INT_TEMP_CHIP_OVER_125_RES_MASK), | |
307 | REGMAP_IRQ_REG(BD71815_INT_TEMP_CHIP_OVER_125_DET, 10, | |
308 | BD71815_INT_TEMP_CHIP_OVER_125_DET_MASK), | |
309 | REGMAP_IRQ_REG(BD71815_INT_TEMP_CHIP_OVER_VF_RES, 10, | |
310 | BD71815_INT_TEMP_CHIP_OVER_VF_RES_MASK), | |
311 | REGMAP_IRQ_REG(BD71815_INT_TEMP_CHIP_OVER_VF_DET, 10, | |
312 | BD71815_INT_TEMP_CHIP_OVER_VF_DET_MASK), | |
313 | /* RTC Alarm */ | |
314 | REGMAP_IRQ_REG(BD71815_INT_RTC0, 11, BD71815_INT_RTC0_MASK), | |
315 | REGMAP_IRQ_REG(BD71815_INT_RTC1, 11, BD71815_INT_RTC1_MASK), | |
316 | REGMAP_IRQ_REG(BD71815_INT_RTC2, 11, BD71815_INT_RTC2_MASK), | |
317 | }; | |
318 | ||
1c743ad5 MV |
319 | static struct regmap_irq bd71828_irqs[] = { |
320 | REGMAP_IRQ_REG(BD71828_INT_BUCK1_OCP, 0, BD71828_INT_BUCK1_OCP_MASK), | |
321 | REGMAP_IRQ_REG(BD71828_INT_BUCK2_OCP, 0, BD71828_INT_BUCK2_OCP_MASK), | |
322 | REGMAP_IRQ_REG(BD71828_INT_BUCK3_OCP, 0, BD71828_INT_BUCK3_OCP_MASK), | |
323 | REGMAP_IRQ_REG(BD71828_INT_BUCK4_OCP, 0, BD71828_INT_BUCK4_OCP_MASK), | |
324 | REGMAP_IRQ_REG(BD71828_INT_BUCK5_OCP, 0, BD71828_INT_BUCK5_OCP_MASK), | |
325 | REGMAP_IRQ_REG(BD71828_INT_BUCK6_OCP, 0, BD71828_INT_BUCK6_OCP_MASK), | |
326 | REGMAP_IRQ_REG(BD71828_INT_BUCK7_OCP, 0, BD71828_INT_BUCK7_OCP_MASK), | |
327 | REGMAP_IRQ_REG(BD71828_INT_PGFAULT, 0, BD71828_INT_PGFAULT_MASK), | |
328 | /* DCIN1 interrupts */ | |
329 | REGMAP_IRQ_REG(BD71828_INT_DCIN_DET, 1, BD71828_INT_DCIN_DET_MASK), | |
330 | REGMAP_IRQ_REG(BD71828_INT_DCIN_RMV, 1, BD71828_INT_DCIN_RMV_MASK), | |
331 | REGMAP_IRQ_REG(BD71828_INT_CLPS_OUT, 1, BD71828_INT_CLPS_OUT_MASK), | |
332 | REGMAP_IRQ_REG(BD71828_INT_CLPS_IN, 1, BD71828_INT_CLPS_IN_MASK), | |
333 | /* DCIN2 interrupts */ | |
4dcdcfd5 MV |
334 | REGMAP_IRQ_REG(BD71828_INT_DCIN_MON_RES, 2, BD71828_INT_DCIN_MON_RES_MASK), |
335 | REGMAP_IRQ_REG(BD71828_INT_DCIN_MON_DET, 2, BD71828_INT_DCIN_MON_DET_MASK), | |
1c743ad5 MV |
336 | REGMAP_IRQ_REG(BD71828_INT_LONGPUSH, 2, BD71828_INT_LONGPUSH_MASK), |
337 | REGMAP_IRQ_REG(BD71828_INT_MIDPUSH, 2, BD71828_INT_MIDPUSH_MASK), | |
338 | REGMAP_IRQ_REG(BD71828_INT_SHORTPUSH, 2, BD71828_INT_SHORTPUSH_MASK), | |
339 | REGMAP_IRQ_REG(BD71828_INT_PUSH, 2, BD71828_INT_PUSH_MASK), | |
340 | REGMAP_IRQ_REG(BD71828_INT_WDOG, 2, BD71828_INT_WDOG_MASK), | |
341 | REGMAP_IRQ_REG(BD71828_INT_SWRESET, 2, BD71828_INT_SWRESET_MASK), | |
342 | /* Vsys */ | |
4dcdcfd5 MV |
343 | REGMAP_IRQ_REG(BD71828_INT_VSYS_UV_RES, 3, BD71828_INT_VSYS_UV_RES_MASK), |
344 | REGMAP_IRQ_REG(BD71828_INT_VSYS_UV_DET, 3, BD71828_INT_VSYS_UV_DET_MASK), | |
345 | REGMAP_IRQ_REG(BD71828_INT_VSYS_LOW_RES, 3, BD71828_INT_VSYS_LOW_RES_MASK), | |
346 | REGMAP_IRQ_REG(BD71828_INT_VSYS_LOW_DET, 3, BD71828_INT_VSYS_LOW_DET_MASK), | |
347 | REGMAP_IRQ_REG(BD71828_INT_VSYS_HALL_IN, 3, BD71828_INT_VSYS_HALL_IN_MASK), | |
348 | REGMAP_IRQ_REG(BD71828_INT_VSYS_HALL_TOGGLE, 3, BD71828_INT_VSYS_HALL_TOGGLE_MASK), | |
349 | REGMAP_IRQ_REG(BD71828_INT_VSYS_MON_RES, 3, BD71828_INT_VSYS_MON_RES_MASK), | |
350 | REGMAP_IRQ_REG(BD71828_INT_VSYS_MON_DET, 3, BD71828_INT_VSYS_MON_DET_MASK), | |
1c743ad5 | 351 | /* Charger */ |
4dcdcfd5 MV |
352 | REGMAP_IRQ_REG(BD71828_INT_CHG_DCIN_ILIM, 4, BD71828_INT_CHG_DCIN_ILIM_MASK), |
353 | REGMAP_IRQ_REG(BD71828_INT_CHG_TOPOFF_TO_DONE, 4, BD71828_INT_CHG_TOPOFF_TO_DONE_MASK), | |
354 | REGMAP_IRQ_REG(BD71828_INT_CHG_WDG_TEMP, 4, BD71828_INT_CHG_WDG_TEMP_MASK), | |
355 | REGMAP_IRQ_REG(BD71828_INT_CHG_WDG_TIME, 4, BD71828_INT_CHG_WDG_TIME_MASK), | |
356 | REGMAP_IRQ_REG(BD71828_INT_CHG_RECHARGE_RES, 4, BD71828_INT_CHG_RECHARGE_RES_MASK), | |
357 | REGMAP_IRQ_REG(BD71828_INT_CHG_RECHARGE_DET, 4, BD71828_INT_CHG_RECHARGE_DET_MASK), | |
1c743ad5 MV |
358 | REGMAP_IRQ_REG(BD71828_INT_CHG_RANGED_TEMP_TRANSITION, 4, |
359 | BD71828_INT_CHG_RANGED_TEMP_TRANSITION_MASK), | |
4dcdcfd5 | 360 | REGMAP_IRQ_REG(BD71828_INT_CHG_STATE_TRANSITION, 4, BD71828_INT_CHG_STATE_TRANSITION_MASK), |
1c743ad5 | 361 | /* Battery */ |
4dcdcfd5 MV |
362 | REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_NORMAL, 5, BD71828_INT_BAT_TEMP_NORMAL_MASK), |
363 | REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_ERANGE, 5, BD71828_INT_BAT_TEMP_ERANGE_MASK), | |
364 | REGMAP_IRQ_REG(BD71828_INT_BAT_TEMP_WARN, 5, BD71828_INT_BAT_TEMP_WARN_MASK), | |
365 | REGMAP_IRQ_REG(BD71828_INT_BAT_REMOVED, 5, BD71828_INT_BAT_REMOVED_MASK), | |
366 | REGMAP_IRQ_REG(BD71828_INT_BAT_DETECTED, 5, BD71828_INT_BAT_DETECTED_MASK), | |
367 | REGMAP_IRQ_REG(BD71828_INT_THERM_REMOVED, 5, BD71828_INT_THERM_REMOVED_MASK), | |
368 | REGMAP_IRQ_REG(BD71828_INT_THERM_DETECTED, 5, BD71828_INT_THERM_DETECTED_MASK), | |
1c743ad5 MV |
369 | /* Battery Mon 1 */ |
370 | REGMAP_IRQ_REG(BD71828_INT_BAT_DEAD, 6, BD71828_INT_BAT_DEAD_MASK), | |
4dcdcfd5 MV |
371 | REGMAP_IRQ_REG(BD71828_INT_BAT_SHORTC_RES, 6, BD71828_INT_BAT_SHORTC_RES_MASK), |
372 | REGMAP_IRQ_REG(BD71828_INT_BAT_SHORTC_DET, 6, BD71828_INT_BAT_SHORTC_DET_MASK), | |
373 | REGMAP_IRQ_REG(BD71828_INT_BAT_LOW_VOLT_RES, 6, BD71828_INT_BAT_LOW_VOLT_RES_MASK), | |
374 | REGMAP_IRQ_REG(BD71828_INT_BAT_LOW_VOLT_DET, 6, BD71828_INT_BAT_LOW_VOLT_DET_MASK), | |
375 | REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_VOLT_RES, 6, BD71828_INT_BAT_OVER_VOLT_RES_MASK), | |
376 | REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_VOLT_DET, 6, BD71828_INT_BAT_OVER_VOLT_DET_MASK), | |
1c743ad5 | 377 | /* Battery Mon 2 */ |
4dcdcfd5 MV |
378 | REGMAP_IRQ_REG(BD71828_INT_BAT_MON_RES, 7, BD71828_INT_BAT_MON_RES_MASK), |
379 | REGMAP_IRQ_REG(BD71828_INT_BAT_MON_DET, 7, BD71828_INT_BAT_MON_DET_MASK), | |
1c743ad5 | 380 | /* Battery Mon 3 (Coulomb counter) */ |
4dcdcfd5 MV |
381 | REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON1, 8, BD71828_INT_BAT_CC_MON1_MASK), |
382 | REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON2, 8, BD71828_INT_BAT_CC_MON2_MASK), | |
383 | REGMAP_IRQ_REG(BD71828_INT_BAT_CC_MON3, 8, BD71828_INT_BAT_CC_MON3_MASK), | |
1c743ad5 | 384 | /* Battery Mon 4 */ |
4dcdcfd5 MV |
385 | REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_1_RES, 9, BD71828_INT_BAT_OVER_CURR_1_RES_MASK), |
386 | REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_1_DET, 9, BD71828_INT_BAT_OVER_CURR_1_DET_MASK), | |
387 | REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_2_RES, 9, BD71828_INT_BAT_OVER_CURR_2_RES_MASK), | |
388 | REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_2_DET, 9, BD71828_INT_BAT_OVER_CURR_2_DET_MASK), | |
389 | REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_3_RES, 9, BD71828_INT_BAT_OVER_CURR_3_RES_MASK), | |
390 | REGMAP_IRQ_REG(BD71828_INT_BAT_OVER_CURR_3_DET, 9, BD71828_INT_BAT_OVER_CURR_3_DET_MASK), | |
1c743ad5 | 391 | /* Temperature */ |
4dcdcfd5 MV |
392 | REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_LOW_RES, 10, BD71828_INT_TEMP_BAT_LOW_RES_MASK), |
393 | REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_LOW_DET, 10, BD71828_INT_TEMP_BAT_LOW_DET_MASK), | |
394 | REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_HI_RES, 10, BD71828_INT_TEMP_BAT_HI_RES_MASK), | |
395 | REGMAP_IRQ_REG(BD71828_INT_TEMP_BAT_HI_DET, 10, BD71828_INT_TEMP_BAT_HI_DET_MASK), | |
1c743ad5 MV |
396 | REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_125_RES, 10, |
397 | BD71828_INT_TEMP_CHIP_OVER_125_RES_MASK), | |
398 | REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_125_DET, 10, | |
399 | BD71828_INT_TEMP_CHIP_OVER_125_DET_MASK), | |
400 | REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_VF_DET, 10, | |
401 | BD71828_INT_TEMP_CHIP_OVER_VF_DET_MASK), | |
402 | REGMAP_IRQ_REG(BD71828_INT_TEMP_CHIP_OVER_VF_RES, 10, | |
403 | BD71828_INT_TEMP_CHIP_OVER_VF_RES_MASK), | |
404 | /* RTC Alarm */ | |
405 | REGMAP_IRQ_REG(BD71828_INT_RTC0, 11, BD71828_INT_RTC0_MASK), | |
406 | REGMAP_IRQ_REG(BD71828_INT_RTC1, 11, BD71828_INT_RTC1_MASK), | |
407 | REGMAP_IRQ_REG(BD71828_INT_RTC2, 11, BD71828_INT_RTC2_MASK), | |
408 | }; | |
409 | ||
410 | static struct regmap_irq_chip bd71828_irq_chip = { | |
411 | .name = "bd71828_irq", | |
412 | .main_status = BD71828_REG_INT_MAIN, | |
413 | .irqs = &bd71828_irqs[0], | |
414 | .num_irqs = ARRAY_SIZE(bd71828_irqs), | |
415 | .status_base = BD71828_REG_INT_BUCK, | |
416 | .mask_base = BD71828_REG_INT_MASK_BUCK, | |
417 | .ack_base = BD71828_REG_INT_BUCK, | |
418 | .mask_invert = true, | |
419 | .init_ack_masked = true, | |
420 | .num_regs = 12, | |
421 | .num_main_regs = 1, | |
4dcdcfd5 MV |
422 | .sub_reg_offsets = &bd718xx_sub_irq_offsets[0], |
423 | .num_main_status_bits = 8, | |
424 | .irq_reg_stride = 1, | |
425 | }; | |
426 | ||
427 | static struct regmap_irq_chip bd71815_irq_chip = { | |
428 | .name = "bd71815_irq", | |
429 | .main_status = BD71815_REG_INT_STAT, | |
430 | .irqs = &bd71815_irqs[0], | |
431 | .num_irqs = ARRAY_SIZE(bd71815_irqs), | |
432 | .status_base = BD71815_REG_INT_STAT_01, | |
433 | .mask_base = BD71815_REG_INT_EN_01, | |
434 | .ack_base = BD71815_REG_INT_STAT_01, | |
435 | .mask_invert = true, | |
436 | .init_ack_masked = true, | |
437 | .num_regs = 12, | |
438 | .num_main_regs = 1, | |
439 | .sub_reg_offsets = &bd718xx_sub_irq_offsets[0], | |
1c743ad5 MV |
440 | .num_main_status_bits = 8, |
441 | .irq_reg_stride = 1, | |
442 | }; | |
443 | ||
4dcdcfd5 MV |
444 | static int set_clk_mode(struct device *dev, struct regmap *regmap, |
445 | int clkmode_reg) | |
446 | { | |
447 | int ret; | |
448 | unsigned int open_drain; | |
449 | ||
450 | ret = of_property_read_u32(dev->of_node, "rohm,clkout-open-drain", &open_drain); | |
451 | if (ret) { | |
452 | if (ret == -EINVAL) | |
453 | return 0; | |
454 | return ret; | |
455 | } | |
456 | if (open_drain > 1) { | |
457 | dev_err(dev, "bad clk32kout mode configuration"); | |
458 | return -EINVAL; | |
459 | } | |
460 | ||
461 | if (open_drain) | |
462 | return regmap_update_bits(regmap, clkmode_reg, OUT32K_MODE, | |
463 | OUT32K_MODE_OPEN_DRAIN); | |
464 | ||
465 | return regmap_update_bits(regmap, clkmode_reg, OUT32K_MODE, | |
466 | OUT32K_MODE_CMOS); | |
467 | } | |
468 | ||
1c743ad5 MV |
469 | static int bd71828_i2c_probe(struct i2c_client *i2c) |
470 | { | |
1c743ad5 MV |
471 | struct regmap_irq_chip_data *irq_data; |
472 | int ret; | |
4dcdcfd5 MV |
473 | struct regmap *regmap; |
474 | const struct regmap_config *regmap_config; | |
475 | struct regmap_irq_chip *irqchip; | |
476 | unsigned int chip_type; | |
477 | struct mfd_cell *mfd; | |
478 | int cells; | |
479 | int button_irq; | |
480 | int clkmode_reg; | |
1c743ad5 MV |
481 | |
482 | if (!i2c->irq) { | |
483 | dev_err(&i2c->dev, "No IRQ configured\n"); | |
484 | return -EINVAL; | |
485 | } | |
486 | ||
4dcdcfd5 MV |
487 | chip_type = (unsigned int)(uintptr_t) |
488 | of_device_get_match_data(&i2c->dev); | |
489 | switch (chip_type) { | |
490 | case ROHM_CHIP_TYPE_BD71828: | |
491 | mfd = bd71828_mfd_cells; | |
492 | cells = ARRAY_SIZE(bd71828_mfd_cells); | |
493 | regmap_config = &bd71828_regmap; | |
494 | irqchip = &bd71828_irq_chip; | |
495 | clkmode_reg = BD71828_REG_OUT32K; | |
496 | button_irq = BD71828_INT_SHORTPUSH; | |
497 | break; | |
498 | case ROHM_CHIP_TYPE_BD71815: | |
499 | mfd = bd71815_mfd_cells; | |
500 | cells = ARRAY_SIZE(bd71815_mfd_cells); | |
501 | regmap_config = &bd71815_regmap; | |
502 | irqchip = &bd71815_irq_chip; | |
503 | clkmode_reg = BD71815_REG_OUT32K; | |
504 | /* | |
505 | * If BD71817 support is needed we should be able to handle it | |
506 | * with proper DT configs + BD71815 drivers + power-button. | |
507 | * BD71815 data-sheet does not list the power-button IRQ so we | |
508 | * don't use it. | |
509 | */ | |
510 | button_irq = 0; | |
511 | break; | |
512 | default: | |
513 | dev_err(&i2c->dev, "Unknown device type"); | |
514 | return -EINVAL; | |
515 | } | |
1c743ad5 | 516 | |
4dcdcfd5 MV |
517 | regmap = devm_regmap_init_i2c(i2c, regmap_config); |
518 | if (IS_ERR(regmap)) { | |
1c743ad5 | 519 | dev_err(&i2c->dev, "Failed to initialize Regmap\n"); |
4dcdcfd5 | 520 | return PTR_ERR(regmap); |
1c743ad5 MV |
521 | } |
522 | ||
4dcdcfd5 MV |
523 | ret = devm_regmap_add_irq_chip(&i2c->dev, regmap, i2c->irq, |
524 | IRQF_ONESHOT, 0, irqchip, &irq_data); | |
1c743ad5 MV |
525 | if (ret) { |
526 | dev_err(&i2c->dev, "Failed to add IRQ chip\n"); | |
527 | return ret; | |
528 | } | |
529 | ||
530 | dev_dbg(&i2c->dev, "Registered %d IRQs for chip\n", | |
4dcdcfd5 | 531 | irqchip->num_irqs); |
1c743ad5 | 532 | |
4dcdcfd5 MV |
533 | if (button_irq) { |
534 | ret = regmap_irq_get_virq(irq_data, button_irq); | |
535 | if (ret < 0) { | |
536 | dev_err(&i2c->dev, "Failed to get the power-key IRQ\n"); | |
537 | return ret; | |
538 | } | |
539 | ||
540 | button.irq = ret; | |
e795bf72 MV |
541 | } |
542 | ||
4dcdcfd5 MV |
543 | ret = set_clk_mode(&i2c->dev, regmap, clkmode_reg); |
544 | if (ret) | |
545 | return ret; | |
e795bf72 | 546 | |
4dcdcfd5 MV |
547 | ret = devm_mfd_add_devices(&i2c->dev, PLATFORM_DEVID_AUTO, mfd, cells, |
548 | NULL, 0, regmap_irq_get_domain(irq_data)); | |
1c743ad5 MV |
549 | if (ret) |
550 | dev_err(&i2c->dev, "Failed to create subdevices\n"); | |
551 | ||
552 | return ret; | |
553 | } | |
554 | ||
555 | static const struct of_device_id bd71828_of_match[] = { | |
4dcdcfd5 MV |
556 | { |
557 | .compatible = "rohm,bd71828", | |
558 | .data = (void *)ROHM_CHIP_TYPE_BD71828, | |
559 | }, { | |
560 | .compatible = "rohm,bd71815", | |
561 | .data = (void *)ROHM_CHIP_TYPE_BD71815, | |
562 | }, | |
1c743ad5 MV |
563 | { }, |
564 | }; | |
565 | MODULE_DEVICE_TABLE(of, bd71828_of_match); | |
566 | ||
567 | static struct i2c_driver bd71828_drv = { | |
568 | .driver = { | |
569 | .name = "rohm-bd71828", | |
570 | .of_match_table = bd71828_of_match, | |
571 | }, | |
572 | .probe_new = &bd71828_i2c_probe, | |
573 | }; | |
574 | module_i2c_driver(bd71828_drv); | |
575 | ||
576 | MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>"); | |
577 | MODULE_DESCRIPTION("ROHM BD71828 Power Management IC driver"); | |
578 | MODULE_LICENSE("GPL"); |