1 // SPDX-License-Identifier: GPL-2.0+
3 // wm831x-isink.c -- Current sink driver for the WM831x series
5 // Copyright 2009 Wolfson Microelectronics PLC.
7 // Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
9 #include <linux/module.h>
10 #include <linux/moduleparam.h>
11 #include <linux/init.h>
12 #include <linux/bitops.h>
13 #include <linux/err.h>
14 #include <linux/i2c.h>
15 #include <linux/platform_device.h>
16 #include <linux/regulator/driver.h>
17 #include <linux/slab.h>
19 #include <linux/mfd/wm831x/core.h>
20 #include <linux/mfd/wm831x/regulator.h>
21 #include <linux/mfd/wm831x/pdata.h>
23 #define WM831X_ISINK_MAX_NAME 7
26 char name
[WM831X_ISINK_MAX_NAME
];
27 struct regulator_desc desc
;
29 struct wm831x
*wm831x
;
30 struct regulator_dev
*regulator
;
33 static int wm831x_isink_enable(struct regulator_dev
*rdev
)
35 struct wm831x_isink
*isink
= rdev_get_drvdata(rdev
);
36 struct wm831x
*wm831x
= isink
->wm831x
;
39 /* We have a two stage enable: first start the ISINK... */
40 ret
= wm831x_set_bits(wm831x
, isink
->reg
, WM831X_CS1_ENA
,
45 /* ...then enable drive */
46 ret
= wm831x_set_bits(wm831x
, isink
->reg
, WM831X_CS1_DRIVE
,
49 wm831x_set_bits(wm831x
, isink
->reg
, WM831X_CS1_ENA
, 0);
55 static int wm831x_isink_disable(struct regulator_dev
*rdev
)
57 struct wm831x_isink
*isink
= rdev_get_drvdata(rdev
);
58 struct wm831x
*wm831x
= isink
->wm831x
;
61 ret
= wm831x_set_bits(wm831x
, isink
->reg
, WM831X_CS1_DRIVE
, 0);
65 ret
= wm831x_set_bits(wm831x
, isink
->reg
, WM831X_CS1_ENA
, 0);
73 static int wm831x_isink_is_enabled(struct regulator_dev
*rdev
)
75 struct wm831x_isink
*isink
= rdev_get_drvdata(rdev
);
76 struct wm831x
*wm831x
= isink
->wm831x
;
79 ret
= wm831x_reg_read(wm831x
, isink
->reg
);
83 if ((ret
& (WM831X_CS1_ENA
| WM831X_CS1_DRIVE
)) ==
84 (WM831X_CS1_ENA
| WM831X_CS1_DRIVE
))
90 static const struct regulator_ops wm831x_isink_ops
= {
91 .is_enabled
= wm831x_isink_is_enabled
,
92 .enable
= wm831x_isink_enable
,
93 .disable
= wm831x_isink_disable
,
94 .set_current_limit
= regulator_set_current_limit_regmap
,
95 .get_current_limit
= regulator_get_current_limit_regmap
,
98 static irqreturn_t
wm831x_isink_irq(int irq
, void *data
)
100 struct wm831x_isink
*isink
= data
;
102 regulator_notifier_call_chain(isink
->regulator
,
103 REGULATOR_EVENT_OVER_CURRENT
,
110 static int wm831x_isink_probe(struct platform_device
*pdev
)
112 struct wm831x
*wm831x
= dev_get_drvdata(pdev
->dev
.parent
);
113 struct wm831x_pdata
*pdata
= dev_get_platdata(wm831x
->dev
);
114 struct wm831x_isink
*isink
;
115 int id
= pdev
->id
% ARRAY_SIZE(pdata
->isink
);
116 struct regulator_config config
= { };
117 struct resource
*res
;
120 dev_dbg(&pdev
->dev
, "Probing ISINK%d\n", id
+ 1);
122 if (pdata
== NULL
|| pdata
->isink
[id
] == NULL
)
125 isink
= devm_kzalloc(&pdev
->dev
, sizeof(struct wm831x_isink
),
130 isink
->wm831x
= wm831x
;
132 res
= platform_get_resource(pdev
, IORESOURCE_REG
, 0);
134 dev_err(&pdev
->dev
, "No REG resource\n");
138 isink
->reg
= res
->start
;
140 /* For current parts this is correct; probably need to revisit
143 snprintf(isink
->name
, sizeof(isink
->name
), "ISINK%d", id
+ 1);
144 isink
->desc
.name
= isink
->name
;
146 isink
->desc
.ops
= &wm831x_isink_ops
;
147 isink
->desc
.type
= REGULATOR_CURRENT
;
148 isink
->desc
.owner
= THIS_MODULE
;
149 isink
->desc
.curr_table
= wm831x_isinkv_values
,
150 isink
->desc
.n_current_limits
= ARRAY_SIZE(wm831x_isinkv_values
),
151 isink
->desc
.csel_reg
= isink
->reg
,
152 isink
->desc
.csel_mask
= WM831X_CS1_ISEL_MASK
,
154 config
.dev
= pdev
->dev
.parent
;
155 config
.init_data
= pdata
->isink
[id
];
156 config
.driver_data
= isink
;
157 config
.regmap
= wm831x
->regmap
;
159 isink
->regulator
= devm_regulator_register(&pdev
->dev
, &isink
->desc
,
161 if (IS_ERR(isink
->regulator
)) {
162 ret
= PTR_ERR(isink
->regulator
);
163 dev_err(wm831x
->dev
, "Failed to register ISINK%d: %d\n",
168 irq
= wm831x_irq(wm831x
, platform_get_irq(pdev
, 0));
169 ret
= devm_request_threaded_irq(&pdev
->dev
, irq
, NULL
,
171 IRQF_TRIGGER_RISING
| IRQF_ONESHOT
,
175 dev_err(&pdev
->dev
, "Failed to request ISINK IRQ %d: %d\n",
180 platform_set_drvdata(pdev
, isink
);
188 static struct platform_driver wm831x_isink_driver
= {
189 .probe
= wm831x_isink_probe
,
191 .name
= "wm831x-isink",
195 static int __init
wm831x_isink_init(void)
198 ret
= platform_driver_register(&wm831x_isink_driver
);
200 pr_err("Failed to register WM831x ISINK driver: %d\n", ret
);
204 subsys_initcall(wm831x_isink_init
);
206 static void __exit
wm831x_isink_exit(void)
208 platform_driver_unregister(&wm831x_isink_driver
);
210 module_exit(wm831x_isink_exit
);
212 /* Module information */
213 MODULE_AUTHOR("Mark Brown");
214 MODULE_DESCRIPTION("WM831x current sink driver");
215 MODULE_LICENSE("GPL");
216 MODULE_ALIAS("platform:wm831x-isink");