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_lock(isink
->regulator
);
103 regulator_notifier_call_chain(isink
->regulator
,
104 REGULATOR_EVENT_OVER_CURRENT
,
106 regulator_unlock(isink
->regulator
);
112 static int wm831x_isink_probe(struct platform_device
*pdev
)
114 struct wm831x
*wm831x
= dev_get_drvdata(pdev
->dev
.parent
);
115 struct wm831x_pdata
*pdata
= dev_get_platdata(wm831x
->dev
);
116 struct wm831x_isink
*isink
;
117 int id
= pdev
->id
% ARRAY_SIZE(pdata
->isink
);
118 struct regulator_config config
= { };
119 struct resource
*res
;
122 dev_dbg(&pdev
->dev
, "Probing ISINK%d\n", id
+ 1);
124 if (pdata
== NULL
|| pdata
->isink
[id
] == NULL
)
127 isink
= devm_kzalloc(&pdev
->dev
, sizeof(struct wm831x_isink
),
132 isink
->wm831x
= wm831x
;
134 res
= platform_get_resource(pdev
, IORESOURCE_REG
, 0);
136 dev_err(&pdev
->dev
, "No REG resource\n");
140 isink
->reg
= res
->start
;
142 /* For current parts this is correct; probably need to revisit
145 snprintf(isink
->name
, sizeof(isink
->name
), "ISINK%d", id
+ 1);
146 isink
->desc
.name
= isink
->name
;
148 isink
->desc
.ops
= &wm831x_isink_ops
;
149 isink
->desc
.type
= REGULATOR_CURRENT
;
150 isink
->desc
.owner
= THIS_MODULE
;
151 isink
->desc
.curr_table
= wm831x_isinkv_values
,
152 isink
->desc
.n_current_limits
= ARRAY_SIZE(wm831x_isinkv_values
),
153 isink
->desc
.csel_reg
= isink
->reg
,
154 isink
->desc
.csel_mask
= WM831X_CS1_ISEL_MASK
,
156 config
.dev
= pdev
->dev
.parent
;
157 config
.init_data
= pdata
->isink
[id
];
158 config
.driver_data
= isink
;
159 config
.regmap
= wm831x
->regmap
;
161 isink
->regulator
= devm_regulator_register(&pdev
->dev
, &isink
->desc
,
163 if (IS_ERR(isink
->regulator
)) {
164 ret
= PTR_ERR(isink
->regulator
);
165 dev_err(wm831x
->dev
, "Failed to register ISINK%d: %d\n",
170 irq
= wm831x_irq(wm831x
, platform_get_irq(pdev
, 0));
171 ret
= devm_request_threaded_irq(&pdev
->dev
, irq
, NULL
,
173 IRQF_TRIGGER_RISING
| IRQF_ONESHOT
,
177 dev_err(&pdev
->dev
, "Failed to request ISINK IRQ %d: %d\n",
182 platform_set_drvdata(pdev
, isink
);
190 static struct platform_driver wm831x_isink_driver
= {
191 .probe
= wm831x_isink_probe
,
193 .name
= "wm831x-isink",
197 static int __init
wm831x_isink_init(void)
200 ret
= platform_driver_register(&wm831x_isink_driver
);
202 pr_err("Failed to register WM831x ISINK driver: %d\n", ret
);
206 subsys_initcall(wm831x_isink_init
);
208 static void __exit
wm831x_isink_exit(void)
210 platform_driver_unregister(&wm831x_isink_driver
);
212 module_exit(wm831x_isink_exit
);
214 /* Module information */
215 MODULE_AUTHOR("Mark Brown");
216 MODULE_DESCRIPTION("WM831x current sink driver");
217 MODULE_LICENSE("GPL");
218 MODULE_ALIAS("platform:wm831x-isink");