xref: /linux/drivers/mfd/sec-acpm.c (revision 69352bd52b2667e5c6e8ebb14143528c28f5e37d)
1*53387090SAndré Draszik // SPDX-License-Identifier: GPL-2.0-only
2*53387090SAndré Draszik /*
3*53387090SAndré Draszik  * Copyright 2020 Google Inc
4*53387090SAndré Draszik  * Copyright 2025 Linaro Ltd.
5*53387090SAndré Draszik  *
6*53387090SAndré Draszik  * Samsung S2MPG1x ACPM driver
7*53387090SAndré Draszik  */
8*53387090SAndré Draszik 
9*53387090SAndré Draszik #include <linux/array_size.h>
10*53387090SAndré Draszik #include <linux/bitops.h>
11*53387090SAndré Draszik #include <linux/device.h>
12*53387090SAndré Draszik #include <linux/firmware/samsung/exynos-acpm-protocol.h>
13*53387090SAndré Draszik #include <linux/mfd/samsung/core.h>
14*53387090SAndré Draszik #include <linux/mfd/samsung/rtc.h>
15*53387090SAndré Draszik #include <linux/mfd/samsung/s2mpg10.h>
16*53387090SAndré Draszik #include <linux/mod_devicetable.h>
17*53387090SAndré Draszik #include <linux/module.h>
18*53387090SAndré Draszik #include <linux/of.h>
19*53387090SAndré Draszik #include <linux/platform_device.h>
20*53387090SAndré Draszik #include <linux/pm.h>
21*53387090SAndré Draszik #include <linux/property.h>
22*53387090SAndré Draszik #include <linux/regmap.h>
23*53387090SAndré Draszik #include "sec-core.h"
24*53387090SAndré Draszik 
25*53387090SAndré Draszik #define ACPM_ADDR_BITS       8
26*53387090SAndré Draszik #define ACPM_MAX_BULK_DATA   8
27*53387090SAndré Draszik 
28*53387090SAndré Draszik struct sec_pmic_acpm_platform_data {
29*53387090SAndré Draszik 	int device_type;
30*53387090SAndré Draszik 
31*53387090SAndré Draszik 	unsigned int acpm_chan_id;
32*53387090SAndré Draszik 	u8 speedy_channel;
33*53387090SAndré Draszik 
34*53387090SAndré Draszik 	const struct regmap_config *regmap_cfg_common;
35*53387090SAndré Draszik 	const struct regmap_config *regmap_cfg_pmic;
36*53387090SAndré Draszik 	const struct regmap_config *regmap_cfg_rtc;
37*53387090SAndré Draszik 	const struct regmap_config *regmap_cfg_meter;
38*53387090SAndré Draszik };
39*53387090SAndré Draszik 
40*53387090SAndré Draszik static const struct regmap_range s2mpg10_common_registers[] = {
41*53387090SAndré Draszik 	regmap_reg_range(0x00, 0x02), /* CHIP_ID_M, INT, INT_MASK */
42*53387090SAndré Draszik 	regmap_reg_range(0x0a, 0x0c), /* Speedy control */
43*53387090SAndré Draszik 	regmap_reg_range(0x1a, 0x2a), /* Debug */
44*53387090SAndré Draszik };
45*53387090SAndré Draszik 
46*53387090SAndré Draszik static const struct regmap_range s2mpg10_common_ro_registers[] = {
47*53387090SAndré Draszik 	regmap_reg_range(0x00, 0x01), /* CHIP_ID_M, INT */
48*53387090SAndré Draszik 	regmap_reg_range(0x28, 0x2a), /* Debug */
49*53387090SAndré Draszik };
50*53387090SAndré Draszik 
51*53387090SAndré Draszik static const struct regmap_range s2mpg10_common_nonvolatile_registers[] = {
52*53387090SAndré Draszik 	regmap_reg_range(0x00, 0x00), /* CHIP_ID_M */
53*53387090SAndré Draszik 	regmap_reg_range(0x02, 0x02), /* INT_MASK */
54*53387090SAndré Draszik 	regmap_reg_range(0x0a, 0x0c), /* Speedy control */
55*53387090SAndré Draszik };
56*53387090SAndré Draszik 
57*53387090SAndré Draszik static const struct regmap_range s2mpg10_common_precious_registers[] = {
58*53387090SAndré Draszik 	regmap_reg_range(0x01, 0x01), /* INT */
59*53387090SAndré Draszik };
60*53387090SAndré Draszik 
61*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_common_wr_table = {
62*53387090SAndré Draszik 	.yes_ranges = s2mpg10_common_registers,
63*53387090SAndré Draszik 	.n_yes_ranges = ARRAY_SIZE(s2mpg10_common_registers),
64*53387090SAndré Draszik 	.no_ranges = s2mpg10_common_ro_registers,
65*53387090SAndré Draszik 	.n_no_ranges = ARRAY_SIZE(s2mpg10_common_ro_registers),
66*53387090SAndré Draszik };
67*53387090SAndré Draszik 
68*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_common_rd_table = {
69*53387090SAndré Draszik 	.yes_ranges = s2mpg10_common_registers,
70*53387090SAndré Draszik 	.n_yes_ranges = ARRAY_SIZE(s2mpg10_common_registers),
71*53387090SAndré Draszik };
72*53387090SAndré Draszik 
73*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_common_volatile_table = {
74*53387090SAndré Draszik 	.no_ranges = s2mpg10_common_nonvolatile_registers,
75*53387090SAndré Draszik 	.n_no_ranges = ARRAY_SIZE(s2mpg10_common_nonvolatile_registers),
76*53387090SAndré Draszik };
77*53387090SAndré Draszik 
78*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_common_precious_table = {
79*53387090SAndré Draszik 	.yes_ranges = s2mpg10_common_precious_registers,
80*53387090SAndré Draszik 	.n_yes_ranges = ARRAY_SIZE(s2mpg10_common_precious_registers),
81*53387090SAndré Draszik };
82*53387090SAndré Draszik 
83*53387090SAndré Draszik static const struct regmap_config s2mpg10_regmap_config_common = {
84*53387090SAndré Draszik 	.name = "common",
85*53387090SAndré Draszik 	.reg_bits = ACPM_ADDR_BITS,
86*53387090SAndré Draszik 	.val_bits = 8,
87*53387090SAndré Draszik 	.max_register = S2MPG10_COMMON_SPD_DEBUG4,
88*53387090SAndré Draszik 	.wr_table = &s2mpg10_common_wr_table,
89*53387090SAndré Draszik 	.rd_table = &s2mpg10_common_rd_table,
90*53387090SAndré Draszik 	.volatile_table = &s2mpg10_common_volatile_table,
91*53387090SAndré Draszik 	.precious_table = &s2mpg10_common_precious_table,
92*53387090SAndré Draszik 	.num_reg_defaults_raw = S2MPG10_COMMON_SPD_DEBUG4 + 1,
93*53387090SAndré Draszik 	.cache_type = REGCACHE_FLAT,
94*53387090SAndré Draszik };
95*53387090SAndré Draszik 
96*53387090SAndré Draszik static const struct regmap_range s2mpg10_pmic_registers[] = {
97*53387090SAndré Draszik 	regmap_reg_range(0x00, 0xf6), /* All PMIC registers */
98*53387090SAndré Draszik };
99*53387090SAndré Draszik 
100*53387090SAndré Draszik static const struct regmap_range s2mpg10_pmic_ro_registers[] = {
101*53387090SAndré Draszik 	regmap_reg_range(0x00, 0x05), /* INTx */
102*53387090SAndré Draszik 	regmap_reg_range(0x0c, 0x0f), /* STATUSx PWRONSRC OFFSRC */
103*53387090SAndré Draszik 	regmap_reg_range(0xc7, 0xc7), /* GPIO input */
104*53387090SAndré Draszik };
105*53387090SAndré Draszik 
106*53387090SAndré Draszik static const struct regmap_range s2mpg10_pmic_nonvolatile_registers[] = {
107*53387090SAndré Draszik 	regmap_reg_range(0x06, 0x0b), /* INTxM */
108*53387090SAndré Draszik };
109*53387090SAndré Draszik 
110*53387090SAndré Draszik static const struct regmap_range s2mpg10_pmic_precious_registers[] = {
111*53387090SAndré Draszik 	regmap_reg_range(0x00, 0x05), /* INTx */
112*53387090SAndré Draszik };
113*53387090SAndré Draszik 
114*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_pmic_wr_table = {
115*53387090SAndré Draszik 	.yes_ranges = s2mpg10_pmic_registers,
116*53387090SAndré Draszik 	.n_yes_ranges = ARRAY_SIZE(s2mpg10_pmic_registers),
117*53387090SAndré Draszik 	.no_ranges = s2mpg10_pmic_ro_registers,
118*53387090SAndré Draszik 	.n_no_ranges = ARRAY_SIZE(s2mpg10_pmic_ro_registers),
119*53387090SAndré Draszik };
120*53387090SAndré Draszik 
121*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_pmic_rd_table = {
122*53387090SAndré Draszik 	.yes_ranges = s2mpg10_pmic_registers,
123*53387090SAndré Draszik 	.n_yes_ranges = ARRAY_SIZE(s2mpg10_pmic_registers),
124*53387090SAndré Draszik };
125*53387090SAndré Draszik 
126*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_pmic_volatile_table = {
127*53387090SAndré Draszik 	.no_ranges = s2mpg10_pmic_nonvolatile_registers,
128*53387090SAndré Draszik 	.n_no_ranges = ARRAY_SIZE(s2mpg10_pmic_nonvolatile_registers),
129*53387090SAndré Draszik };
130*53387090SAndré Draszik 
131*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_pmic_precious_table = {
132*53387090SAndré Draszik 	.yes_ranges = s2mpg10_pmic_precious_registers,
133*53387090SAndré Draszik 	.n_yes_ranges = ARRAY_SIZE(s2mpg10_pmic_precious_registers),
134*53387090SAndré Draszik };
135*53387090SAndré Draszik 
136*53387090SAndré Draszik static const struct regmap_config s2mpg10_regmap_config_pmic = {
137*53387090SAndré Draszik 	.name = "pmic",
138*53387090SAndré Draszik 	.reg_bits = ACPM_ADDR_BITS,
139*53387090SAndré Draszik 	.val_bits = 8,
140*53387090SAndré Draszik 	.max_register = S2MPG10_PMIC_LDO_SENSE4,
141*53387090SAndré Draszik 	.wr_table = &s2mpg10_pmic_wr_table,
142*53387090SAndré Draszik 	.rd_table = &s2mpg10_pmic_rd_table,
143*53387090SAndré Draszik 	.volatile_table = &s2mpg10_pmic_volatile_table,
144*53387090SAndré Draszik 	.precious_table = &s2mpg10_pmic_precious_table,
145*53387090SAndré Draszik 	.num_reg_defaults_raw = S2MPG10_PMIC_LDO_SENSE4 + 1,
146*53387090SAndré Draszik 	.cache_type = REGCACHE_FLAT,
147*53387090SAndré Draszik };
148*53387090SAndré Draszik 
149*53387090SAndré Draszik static const struct regmap_range s2mpg10_rtc_registers[] = {
150*53387090SAndré Draszik 	regmap_reg_range(0x00, 0x2b), /* All RTC registers */
151*53387090SAndré Draszik };
152*53387090SAndré Draszik 
153*53387090SAndré Draszik static const struct regmap_range s2mpg10_rtc_volatile_registers[] = {
154*53387090SAndré Draszik 	regmap_reg_range(0x01, 0x01), /* RTC_UPDATE */
155*53387090SAndré Draszik 	regmap_reg_range(0x05, 0x0c), /* Time / date */
156*53387090SAndré Draszik };
157*53387090SAndré Draszik 
158*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_rtc_rd_table = {
159*53387090SAndré Draszik 	.yes_ranges = s2mpg10_rtc_registers,
160*53387090SAndré Draszik 	.n_yes_ranges = ARRAY_SIZE(s2mpg10_rtc_registers),
161*53387090SAndré Draszik };
162*53387090SAndré Draszik 
163*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_rtc_volatile_table = {
164*53387090SAndré Draszik 	.yes_ranges = s2mpg10_rtc_volatile_registers,
165*53387090SAndré Draszik 	.n_yes_ranges = ARRAY_SIZE(s2mpg10_rtc_volatile_registers),
166*53387090SAndré Draszik };
167*53387090SAndré Draszik 
168*53387090SAndré Draszik static const struct regmap_config s2mpg10_regmap_config_rtc = {
169*53387090SAndré Draszik 	.name = "rtc",
170*53387090SAndré Draszik 	.reg_bits = ACPM_ADDR_BITS,
171*53387090SAndré Draszik 	.val_bits = 8,
172*53387090SAndré Draszik 	.max_register = S2MPG10_RTC_OSC_CTRL,
173*53387090SAndré Draszik 	.rd_table = &s2mpg10_rtc_rd_table,
174*53387090SAndré Draszik 	.volatile_table = &s2mpg10_rtc_volatile_table,
175*53387090SAndré Draszik 	.num_reg_defaults_raw = S2MPG10_RTC_OSC_CTRL + 1,
176*53387090SAndré Draszik 	.cache_type = REGCACHE_FLAT,
177*53387090SAndré Draszik };
178*53387090SAndré Draszik 
179*53387090SAndré Draszik static const struct regmap_range s2mpg10_meter_registers[] = {
180*53387090SAndré Draszik 	regmap_reg_range(0x00, 0x21), /* Meter config */
181*53387090SAndré Draszik 	regmap_reg_range(0x40, 0x8a), /* Meter data */
182*53387090SAndré Draszik 	regmap_reg_range(0xee, 0xee), /* Offset */
183*53387090SAndré Draszik 	regmap_reg_range(0xf1, 0xf1), /* Trim */
184*53387090SAndré Draszik };
185*53387090SAndré Draszik 
186*53387090SAndré Draszik static const struct regmap_range s2mpg10_meter_ro_registers[] = {
187*53387090SAndré Draszik 	regmap_reg_range(0x40, 0x8a), /* Meter data */
188*53387090SAndré Draszik };
189*53387090SAndré Draszik 
190*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_meter_wr_table = {
191*53387090SAndré Draszik 	.yes_ranges = s2mpg10_meter_registers,
192*53387090SAndré Draszik 	.n_yes_ranges = ARRAY_SIZE(s2mpg10_meter_registers),
193*53387090SAndré Draszik 	.no_ranges = s2mpg10_meter_ro_registers,
194*53387090SAndré Draszik 	.n_no_ranges = ARRAY_SIZE(s2mpg10_meter_ro_registers),
195*53387090SAndré Draszik };
196*53387090SAndré Draszik 
197*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_meter_rd_table = {
198*53387090SAndré Draszik 	.yes_ranges = s2mpg10_meter_registers,
199*53387090SAndré Draszik 	.n_yes_ranges = ARRAY_SIZE(s2mpg10_meter_registers),
200*53387090SAndré Draszik };
201*53387090SAndré Draszik 
202*53387090SAndré Draszik static const struct regmap_access_table s2mpg10_meter_volatile_table = {
203*53387090SAndré Draszik 	.yes_ranges = s2mpg10_meter_ro_registers,
204*53387090SAndré Draszik 	.n_yes_ranges = ARRAY_SIZE(s2mpg10_meter_ro_registers),
205*53387090SAndré Draszik };
206*53387090SAndré Draszik 
207*53387090SAndré Draszik static const struct regmap_config s2mpg10_regmap_config_meter = {
208*53387090SAndré Draszik 	.name = "meter",
209*53387090SAndré Draszik 	.reg_bits = ACPM_ADDR_BITS,
210*53387090SAndré Draszik 	.val_bits = 8,
211*53387090SAndré Draszik 	.max_register = S2MPG10_METER_BUCK_METER_TRIM3,
212*53387090SAndré Draszik 	.wr_table = &s2mpg10_meter_wr_table,
213*53387090SAndré Draszik 	.rd_table = &s2mpg10_meter_rd_table,
214*53387090SAndré Draszik 	.volatile_table = &s2mpg10_meter_volatile_table,
215*53387090SAndré Draszik 	.num_reg_defaults_raw = S2MPG10_METER_BUCK_METER_TRIM3 + 1,
216*53387090SAndré Draszik 	.cache_type = REGCACHE_FLAT,
217*53387090SAndré Draszik };
218*53387090SAndré Draszik 
219*53387090SAndré Draszik struct sec_pmic_acpm_shared_bus_context {
220*53387090SAndré Draszik 	const struct acpm_handle *acpm;
221*53387090SAndré Draszik 	unsigned int acpm_chan_id;
222*53387090SAndré Draszik 	u8 speedy_channel;
223*53387090SAndré Draszik };
224*53387090SAndré Draszik 
225*53387090SAndré Draszik enum sec_pmic_acpm_accesstype {
226*53387090SAndré Draszik 	SEC_PMIC_ACPM_ACCESSTYPE_COMMON = 0x00,
227*53387090SAndré Draszik 	SEC_PMIC_ACPM_ACCESSTYPE_PMIC = 0x01,
228*53387090SAndré Draszik 	SEC_PMIC_ACPM_ACCESSTYPE_RTC = 0x02,
229*53387090SAndré Draszik 	SEC_PMIC_ACPM_ACCESSTYPE_METER = 0x0a,
230*53387090SAndré Draszik 	SEC_PMIC_ACPM_ACCESSTYPE_WLWP = 0x0b,
231*53387090SAndré Draszik 	SEC_PMIC_ACPM_ACCESSTYPE_TRIM = 0x0f,
232*53387090SAndré Draszik };
233*53387090SAndré Draszik 
234*53387090SAndré Draszik struct sec_pmic_acpm_bus_context {
235*53387090SAndré Draszik 	struct sec_pmic_acpm_shared_bus_context *shared;
236*53387090SAndré Draszik 	enum sec_pmic_acpm_accesstype type;
237*53387090SAndré Draszik };
238*53387090SAndré Draszik 
239*53387090SAndré Draszik static int sec_pmic_acpm_bus_write(void *context, const void *data,
240*53387090SAndré Draszik 				   size_t count)
241*53387090SAndré Draszik {
242*53387090SAndré Draszik 	struct sec_pmic_acpm_bus_context *ctx = context;
243*53387090SAndré Draszik 	const struct acpm_handle *acpm = ctx->shared->acpm;
244*53387090SAndré Draszik 	const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops;
245*53387090SAndré Draszik 	size_t val_count = count - BITS_TO_BYTES(ACPM_ADDR_BITS);
246*53387090SAndré Draszik 	const u8 *d = data;
247*53387090SAndré Draszik 	const u8 *vals = &d[BITS_TO_BYTES(ACPM_ADDR_BITS)];
248*53387090SAndré Draszik 	u8 reg;
249*53387090SAndré Draszik 
250*53387090SAndré Draszik 	if (val_count < 1 || val_count > ACPM_MAX_BULK_DATA)
251*53387090SAndré Draszik 		return -EINVAL;
252*53387090SAndré Draszik 
253*53387090SAndré Draszik 	reg = d[0];
254*53387090SAndré Draszik 
255*53387090SAndré Draszik 	return pmic_ops->bulk_write(acpm, ctx->shared->acpm_chan_id, ctx->type, reg,
256*53387090SAndré Draszik 				    ctx->shared->speedy_channel, val_count, vals);
257*53387090SAndré Draszik }
258*53387090SAndré Draszik 
259*53387090SAndré Draszik static int sec_pmic_acpm_bus_read(void *context, const void *reg_buf, size_t reg_size,
260*53387090SAndré Draszik 				  void *val_buf, size_t val_size)
261*53387090SAndré Draszik {
262*53387090SAndré Draszik 	struct sec_pmic_acpm_bus_context *ctx = context;
263*53387090SAndré Draszik 	const struct acpm_handle *acpm = ctx->shared->acpm;
264*53387090SAndré Draszik 	const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops;
265*53387090SAndré Draszik 	const u8 *r = reg_buf;
266*53387090SAndré Draszik 	u8 reg;
267*53387090SAndré Draszik 
268*53387090SAndré Draszik 	if (reg_size != BITS_TO_BYTES(ACPM_ADDR_BITS) || !val_size ||
269*53387090SAndré Draszik 	    val_size > ACPM_MAX_BULK_DATA)
270*53387090SAndré Draszik 		return -EINVAL;
271*53387090SAndré Draszik 
272*53387090SAndré Draszik 	reg = r[0];
273*53387090SAndré Draszik 
274*53387090SAndré Draszik 	return pmic_ops->bulk_read(acpm, ctx->shared->acpm_chan_id, ctx->type, reg,
275*53387090SAndré Draszik 				   ctx->shared->speedy_channel, val_size, val_buf);
276*53387090SAndré Draszik }
277*53387090SAndré Draszik 
278*53387090SAndré Draszik static int sec_pmic_acpm_bus_reg_update_bits(void *context, unsigned int reg, unsigned int mask,
279*53387090SAndré Draszik 					     unsigned int val)
280*53387090SAndré Draszik {
281*53387090SAndré Draszik 	struct sec_pmic_acpm_bus_context *ctx = context;
282*53387090SAndré Draszik 	const struct acpm_handle *acpm = ctx->shared->acpm;
283*53387090SAndré Draszik 	const struct acpm_pmic_ops *pmic_ops = &acpm->ops.pmic_ops;
284*53387090SAndré Draszik 
285*53387090SAndré Draszik 	return pmic_ops->update_reg(acpm, ctx->shared->acpm_chan_id, ctx->type, reg & 0xff,
286*53387090SAndré Draszik 				    ctx->shared->speedy_channel, val, mask);
287*53387090SAndré Draszik }
288*53387090SAndré Draszik 
289*53387090SAndré Draszik static const struct regmap_bus sec_pmic_acpm_regmap_bus = {
290*53387090SAndré Draszik 	.write = sec_pmic_acpm_bus_write,
291*53387090SAndré Draszik 	.read = sec_pmic_acpm_bus_read,
292*53387090SAndré Draszik 	.reg_update_bits = sec_pmic_acpm_bus_reg_update_bits,
293*53387090SAndré Draszik 	.max_raw_read = ACPM_MAX_BULK_DATA,
294*53387090SAndré Draszik 	.max_raw_write = ACPM_MAX_BULK_DATA,
295*53387090SAndré Draszik };
296*53387090SAndré Draszik 
297*53387090SAndré Draszik static struct regmap *sec_pmic_acpm_regmap_init(struct device *dev,
298*53387090SAndré Draszik 						struct sec_pmic_acpm_shared_bus_context *shared_ctx,
299*53387090SAndré Draszik 						enum sec_pmic_acpm_accesstype type,
300*53387090SAndré Draszik 						const struct regmap_config *cfg, bool do_attach)
301*53387090SAndré Draszik {
302*53387090SAndré Draszik 	struct sec_pmic_acpm_bus_context *ctx;
303*53387090SAndré Draszik 	struct regmap *regmap;
304*53387090SAndré Draszik 
305*53387090SAndré Draszik 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
306*53387090SAndré Draszik 	if (!ctx)
307*53387090SAndré Draszik 		return ERR_PTR(-ENOMEM);
308*53387090SAndré Draszik 
309*53387090SAndré Draszik 	ctx->shared = shared_ctx;
310*53387090SAndré Draszik 	ctx->type = type;
311*53387090SAndré Draszik 
312*53387090SAndré Draszik 	regmap = devm_regmap_init(dev, &sec_pmic_acpm_regmap_bus, ctx, cfg);
313*53387090SAndré Draszik 	if (IS_ERR(regmap))
314*53387090SAndré Draszik 		return dev_err_cast_probe(dev, regmap, "regmap init (%s) failed\n", cfg->name);
315*53387090SAndré Draszik 
316*53387090SAndré Draszik 	if (do_attach) {
317*53387090SAndré Draszik 		int ret;
318*53387090SAndré Draszik 
319*53387090SAndré Draszik 		ret = regmap_attach_dev(dev, regmap, cfg);
320*53387090SAndré Draszik 		if (ret)
321*53387090SAndré Draszik 			return dev_err_ptr_probe(dev, ret, "regmap attach (%s) failed\n",
322*53387090SAndré Draszik 						 cfg->name);
323*53387090SAndré Draszik 	}
324*53387090SAndré Draszik 
325*53387090SAndré Draszik 	return regmap;
326*53387090SAndré Draszik }
327*53387090SAndré Draszik 
328*53387090SAndré Draszik static void sec_pmic_acpm_mask_common_irqs(void *regmap_common)
329*53387090SAndré Draszik {
330*53387090SAndré Draszik 	regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK, S2MPG10_COMMON_INT_SRC);
331*53387090SAndré Draszik }
332*53387090SAndré Draszik 
333*53387090SAndré Draszik static int sec_pmic_acpm_probe(struct platform_device *pdev)
334*53387090SAndré Draszik {
335*53387090SAndré Draszik 	struct regmap *regmap_common, *regmap_pmic, *regmap;
336*53387090SAndré Draszik 	const struct sec_pmic_acpm_platform_data *pdata;
337*53387090SAndré Draszik 	struct sec_pmic_acpm_shared_bus_context *shared_ctx;
338*53387090SAndré Draszik 	const struct acpm_handle *acpm;
339*53387090SAndré Draszik 	struct device *dev = &pdev->dev;
340*53387090SAndré Draszik 	int ret, irq;
341*53387090SAndré Draszik 
342*53387090SAndré Draszik 	pdata = device_get_match_data(dev);
343*53387090SAndré Draszik 	if (!pdata)
344*53387090SAndré Draszik 		return dev_err_probe(dev, -ENODEV, "unsupported device type\n");
345*53387090SAndré Draszik 
346*53387090SAndré Draszik 	acpm = devm_acpm_get_by_node(dev, dev->parent->of_node);
347*53387090SAndré Draszik 	if (IS_ERR(acpm))
348*53387090SAndré Draszik 		return dev_err_probe(dev, PTR_ERR(acpm), "failed to get acpm\n");
349*53387090SAndré Draszik 
350*53387090SAndré Draszik 	irq = platform_get_irq(pdev, 0);
351*53387090SAndré Draszik 	if (irq < 0)
352*53387090SAndré Draszik 		return irq;
353*53387090SAndré Draszik 
354*53387090SAndré Draszik 	shared_ctx = devm_kzalloc(dev, sizeof(*shared_ctx), GFP_KERNEL);
355*53387090SAndré Draszik 	if (!shared_ctx)
356*53387090SAndré Draszik 		return -ENOMEM;
357*53387090SAndré Draszik 
358*53387090SAndré Draszik 	shared_ctx->acpm = acpm;
359*53387090SAndré Draszik 	shared_ctx->acpm_chan_id = pdata->acpm_chan_id;
360*53387090SAndré Draszik 	shared_ctx->speedy_channel = pdata->speedy_channel;
361*53387090SAndré Draszik 
362*53387090SAndré Draszik 	regmap_common = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_COMMON,
363*53387090SAndré Draszik 						  pdata->regmap_cfg_common, false);
364*53387090SAndré Draszik 	if (IS_ERR(regmap_common))
365*53387090SAndré Draszik 		return PTR_ERR(regmap_common);
366*53387090SAndré Draszik 
367*53387090SAndré Draszik 	/* Mask all interrupts from 'common' block, until successful init */
368*53387090SAndré Draszik 	ret = regmap_write(regmap_common, S2MPG10_COMMON_INT_MASK, S2MPG10_COMMON_INT_SRC);
369*53387090SAndré Draszik 	if (ret)
370*53387090SAndré Draszik 		return dev_err_probe(dev, ret, "failed to mask common block interrupts\n");
371*53387090SAndré Draszik 
372*53387090SAndré Draszik 	regmap_pmic = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_PMIC,
373*53387090SAndré Draszik 						pdata->regmap_cfg_pmic, false);
374*53387090SAndré Draszik 	if (IS_ERR(regmap_pmic))
375*53387090SAndré Draszik 		return PTR_ERR(regmap_pmic);
376*53387090SAndré Draszik 
377*53387090SAndré Draszik 	regmap = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_RTC,
378*53387090SAndré Draszik 					   pdata->regmap_cfg_rtc, true);
379*53387090SAndré Draszik 	if (IS_ERR(regmap))
380*53387090SAndré Draszik 		return PTR_ERR(regmap);
381*53387090SAndré Draszik 
382*53387090SAndré Draszik 	regmap = sec_pmic_acpm_regmap_init(dev, shared_ctx, SEC_PMIC_ACPM_ACCESSTYPE_METER,
383*53387090SAndré Draszik 					   pdata->regmap_cfg_meter, true);
384*53387090SAndré Draszik 	if (IS_ERR(regmap))
385*53387090SAndré Draszik 		return PTR_ERR(regmap);
386*53387090SAndré Draszik 
387*53387090SAndré Draszik 	ret = sec_pmic_probe(dev, pdata->device_type, irq, regmap_pmic, NULL);
388*53387090SAndré Draszik 	if (ret)
389*53387090SAndré Draszik 		return ret;
390*53387090SAndré Draszik 
391*53387090SAndré Draszik 	if (device_property_read_bool(dev, "wakeup-source"))
392*53387090SAndré Draszik 		devm_device_init_wakeup(dev);
393*53387090SAndré Draszik 
394*53387090SAndré Draszik 	/* Unmask PMIC interrupt from 'common' block, now that everything is in place. */
395*53387090SAndré Draszik 	ret = regmap_clear_bits(regmap_common, S2MPG10_COMMON_INT_MASK,
396*53387090SAndré Draszik 				S2MPG10_COMMON_INT_SRC_PMIC);
397*53387090SAndré Draszik 	if (ret)
398*53387090SAndré Draszik 		return dev_err_probe(dev, ret, "failed to unmask PMIC interrupt\n");
399*53387090SAndré Draszik 
400*53387090SAndré Draszik 	/* Mask all interrupts from 'common' block on shutdown */
401*53387090SAndré Draszik 	ret = devm_add_action_or_reset(dev, sec_pmic_acpm_mask_common_irqs, regmap_common);
402*53387090SAndré Draszik 	if (ret)
403*53387090SAndré Draszik 		return ret;
404*53387090SAndré Draszik 
405*53387090SAndré Draszik 	return 0;
406*53387090SAndré Draszik }
407*53387090SAndré Draszik 
408*53387090SAndré Draszik static void sec_pmic_acpm_shutdown(struct platform_device *pdev)
409*53387090SAndré Draszik {
410*53387090SAndré Draszik 	sec_pmic_shutdown(&pdev->dev);
411*53387090SAndré Draszik }
412*53387090SAndré Draszik 
413*53387090SAndré Draszik static const struct sec_pmic_acpm_platform_data s2mpg10_data = {
414*53387090SAndré Draszik 	.device_type = S2MPG10,
415*53387090SAndré Draszik 	.acpm_chan_id = 2,
416*53387090SAndré Draszik 	.speedy_channel = 0,
417*53387090SAndré Draszik 	.regmap_cfg_common = &s2mpg10_regmap_config_common,
418*53387090SAndré Draszik 	.regmap_cfg_pmic = &s2mpg10_regmap_config_pmic,
419*53387090SAndré Draszik 	.regmap_cfg_rtc = &s2mpg10_regmap_config_rtc,
420*53387090SAndré Draszik 	.regmap_cfg_meter = &s2mpg10_regmap_config_meter,
421*53387090SAndré Draszik };
422*53387090SAndré Draszik 
423*53387090SAndré Draszik static const struct of_device_id sec_pmic_acpm_of_match[] = {
424*53387090SAndré Draszik 	{ .compatible = "samsung,s2mpg10-pmic", .data = &s2mpg10_data, },
425*53387090SAndré Draszik 	{ },
426*53387090SAndré Draszik };
427*53387090SAndré Draszik MODULE_DEVICE_TABLE(of, sec_pmic_acpm_of_match);
428*53387090SAndré Draszik 
429*53387090SAndré Draszik static struct platform_driver sec_pmic_acpm_driver = {
430*53387090SAndré Draszik 	.driver = {
431*53387090SAndré Draszik 		.name = "sec-pmic-acpm",
432*53387090SAndré Draszik 		.pm = pm_sleep_ptr(&sec_pmic_pm_ops),
433*53387090SAndré Draszik 		.of_match_table = sec_pmic_acpm_of_match,
434*53387090SAndré Draszik 	},
435*53387090SAndré Draszik 	.probe = sec_pmic_acpm_probe,
436*53387090SAndré Draszik 	.shutdown = sec_pmic_acpm_shutdown,
437*53387090SAndré Draszik };
438*53387090SAndré Draszik module_platform_driver(sec_pmic_acpm_driver);
439*53387090SAndré Draszik 
440*53387090SAndré Draszik MODULE_AUTHOR("André Draszik <andre.draszik@linaro.org>");
441*53387090SAndré Draszik MODULE_DESCRIPTION("ACPM driver for the Samsung S2MPG1x");
442*53387090SAndré Draszik MODULE_LICENSE("GPL");
443