xref: /openbmc/linux/drivers/mfd/twl4030-power.c (revision b0fc1da4)
1 /*
2  * linux/drivers/i2c/chips/twl4030-power.c
3  *
4  * Handle TWL4030 Power initialization
5  *
6  * Copyright (C) 2008 Nokia Corporation
7  * Copyright (C) 2006 Texas Instruments, Inc
8  *
9  * Written by 	Kalle Jokiniemi
10  *		Peter De Schrijver <peter.de-schrijver@nokia.com>
11  * Several fixes by Amit Kucheria <amit.kucheria@verdurent.com>
12  *
13  * This file is subject to the terms and conditions of the GNU General
14  * Public License. See the file "COPYING" in the main directory of this
15  * archive for more details.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25  */
26 
27 #include <linux/module.h>
28 #include <linux/pm.h>
29 #include <linux/i2c/twl.h>
30 #include <linux/platform_device.h>
31 #include <linux/of.h>
32 
33 #include <asm/mach-types.h>
34 
35 static u8 twl4030_start_script_address = 0x2b;
36 
37 #define PWR_P1_SW_EVENTS	0x10
38 #define PWR_DEVOFF		(1 << 0)
39 #define SEQ_OFFSYNC		(1 << 0)
40 
41 #define PHY_TO_OFF_PM_MASTER(p)		(p - 0x36)
42 #define PHY_TO_OFF_PM_RECEIVER(p)	(p - 0x5b)
43 
44 /* resource - hfclk */
45 #define R_HFCLKOUT_DEV_GRP 	PHY_TO_OFF_PM_RECEIVER(0xe6)
46 
47 /* PM events */
48 #define R_P1_SW_EVENTS		PHY_TO_OFF_PM_MASTER(0x46)
49 #define R_P2_SW_EVENTS		PHY_TO_OFF_PM_MASTER(0x47)
50 #define R_P3_SW_EVENTS		PHY_TO_OFF_PM_MASTER(0x48)
51 #define R_CFG_P1_TRANSITION	PHY_TO_OFF_PM_MASTER(0x36)
52 #define R_CFG_P2_TRANSITION	PHY_TO_OFF_PM_MASTER(0x37)
53 #define R_CFG_P3_TRANSITION	PHY_TO_OFF_PM_MASTER(0x38)
54 
55 #define LVL_WAKEUP	0x08
56 
57 #define ENABLE_WARMRESET (1<<4)
58 
59 #define END_OF_SCRIPT		0x3f
60 
61 #define R_SEQ_ADD_A2S		PHY_TO_OFF_PM_MASTER(0x55)
62 #define R_SEQ_ADD_S2A12		PHY_TO_OFF_PM_MASTER(0x56)
63 #define	R_SEQ_ADD_S2A3		PHY_TO_OFF_PM_MASTER(0x57)
64 #define	R_SEQ_ADD_WARM		PHY_TO_OFF_PM_MASTER(0x58)
65 #define R_MEMORY_ADDRESS	PHY_TO_OFF_PM_MASTER(0x59)
66 #define R_MEMORY_DATA		PHY_TO_OFF_PM_MASTER(0x5a)
67 
68 /* resource configuration registers
69    <RESOURCE>_DEV_GRP   at address 'n+0'
70    <RESOURCE>_TYPE      at address 'n+1'
71    <RESOURCE>_REMAP     at address 'n+2'
72    <RESOURCE>_DEDICATED at address 'n+3'
73 */
74 #define DEV_GRP_OFFSET		0
75 #define TYPE_OFFSET		1
76 #define REMAP_OFFSET		2
77 #define DEDICATED_OFFSET	3
78 
79 /* Bit positions in the registers */
80 
81 /* <RESOURCE>_DEV_GRP */
82 #define DEV_GRP_SHIFT		5
83 #define DEV_GRP_MASK		(7 << DEV_GRP_SHIFT)
84 
85 /* <RESOURCE>_TYPE */
86 #define TYPE_SHIFT		0
87 #define TYPE_MASK		(7 << TYPE_SHIFT)
88 #define TYPE2_SHIFT		3
89 #define TYPE2_MASK		(3 << TYPE2_SHIFT)
90 
91 /* <RESOURCE>_REMAP */
92 #define SLEEP_STATE_SHIFT	0
93 #define SLEEP_STATE_MASK	(0xf << SLEEP_STATE_SHIFT)
94 #define OFF_STATE_SHIFT		4
95 #define OFF_STATE_MASK		(0xf << OFF_STATE_SHIFT)
96 
97 static u8 res_config_addrs[] = {
98 	[RES_VAUX1]	= 0x17,
99 	[RES_VAUX2]	= 0x1b,
100 	[RES_VAUX3]	= 0x1f,
101 	[RES_VAUX4]	= 0x23,
102 	[RES_VMMC1]	= 0x27,
103 	[RES_VMMC2]	= 0x2b,
104 	[RES_VPLL1]	= 0x2f,
105 	[RES_VPLL2]	= 0x33,
106 	[RES_VSIM]	= 0x37,
107 	[RES_VDAC]	= 0x3b,
108 	[RES_VINTANA1]	= 0x3f,
109 	[RES_VINTANA2]	= 0x43,
110 	[RES_VINTDIG]	= 0x47,
111 	[RES_VIO]	= 0x4b,
112 	[RES_VDD1]	= 0x55,
113 	[RES_VDD2]	= 0x63,
114 	[RES_VUSB_1V5]	= 0x71,
115 	[RES_VUSB_1V8]	= 0x74,
116 	[RES_VUSB_3V1]	= 0x77,
117 	[RES_VUSBCP]	= 0x7a,
118 	[RES_REGEN]	= 0x7f,
119 	[RES_NRES_PWRON] = 0x82,
120 	[RES_CLKEN]	= 0x85,
121 	[RES_SYSEN]	= 0x88,
122 	[RES_HFCLKOUT]	= 0x8b,
123 	[RES_32KCLKOUT]	= 0x8e,
124 	[RES_RESET]	= 0x91,
125 	[RES_MAIN_REF]	= 0x94,
126 };
127 
128 static int twl4030_write_script_byte(u8 address, u8 byte)
129 {
130 	int err;
131 
132 	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_MEMORY_ADDRESS);
133 	if (err)
134 		goto out;
135 	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, byte, R_MEMORY_DATA);
136 out:
137 	return err;
138 }
139 
140 static int twl4030_write_script_ins(u8 address, u16 pmb_message,
141 					   u8 delay, u8 next)
142 {
143 	int err;
144 
145 	address *= 4;
146 	err = twl4030_write_script_byte(address++, pmb_message >> 8);
147 	if (err)
148 		goto out;
149 	err = twl4030_write_script_byte(address++, pmb_message & 0xff);
150 	if (err)
151 		goto out;
152 	err = twl4030_write_script_byte(address++, delay);
153 	if (err)
154 		goto out;
155 	err = twl4030_write_script_byte(address++, next);
156 out:
157 	return err;
158 }
159 
160 static int twl4030_write_script(u8 address, struct twl4030_ins *script,
161 				       int len)
162 {
163 	int err = -EINVAL;
164 
165 	for (; len; len--, address++, script++) {
166 		if (len == 1) {
167 			err = twl4030_write_script_ins(address,
168 						script->pmb_message,
169 						script->delay,
170 						END_OF_SCRIPT);
171 			if (err)
172 				break;
173 		} else {
174 			err = twl4030_write_script_ins(address,
175 						script->pmb_message,
176 						script->delay,
177 						address + 1);
178 			if (err)
179 				break;
180 		}
181 	}
182 	return err;
183 }
184 
185 static int twl4030_config_wakeup3_sequence(u8 address)
186 {
187 	int err;
188 	u8 data;
189 
190 	/* Set SLEEP to ACTIVE SEQ address for P3 */
191 	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_S2A3);
192 	if (err)
193 		goto out;
194 
195 	/* P3 LVL_WAKEUP should be on LEVEL */
196 	err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P3_SW_EVENTS);
197 	if (err)
198 		goto out;
199 	data |= LVL_WAKEUP;
200 	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P3_SW_EVENTS);
201 out:
202 	if (err)
203 		pr_err("TWL4030 wakeup sequence for P3 config error\n");
204 	return err;
205 }
206 
207 static int twl4030_config_wakeup12_sequence(u8 address)
208 {
209 	int err = 0;
210 	u8 data;
211 
212 	/* Set SLEEP to ACTIVE SEQ address for P1 and P2 */
213 	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_S2A12);
214 	if (err)
215 		goto out;
216 
217 	/* P1/P2 LVL_WAKEUP should be on LEVEL */
218 	err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P1_SW_EVENTS);
219 	if (err)
220 		goto out;
221 
222 	data |= LVL_WAKEUP;
223 	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P1_SW_EVENTS);
224 	if (err)
225 		goto out;
226 
227 	err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P2_SW_EVENTS);
228 	if (err)
229 		goto out;
230 
231 	data |= LVL_WAKEUP;
232 	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P2_SW_EVENTS);
233 	if (err)
234 		goto out;
235 
236 	if (machine_is_omap_3430sdp() || machine_is_omap_ldp()) {
237 		/* Disabling AC charger effect on sleep-active transitions */
238 		err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data,
239 				      R_CFG_P1_TRANSITION);
240 		if (err)
241 			goto out;
242 		data &= ~(1<<1);
243 		err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data,
244 				       R_CFG_P1_TRANSITION);
245 		if (err)
246 			goto out;
247 	}
248 
249 out:
250 	if (err)
251 		pr_err("TWL4030 wakeup sequence for P1 and P2" \
252 			"config error\n");
253 	return err;
254 }
255 
256 static int twl4030_config_sleep_sequence(u8 address)
257 {
258 	int err;
259 
260 	/* Set ACTIVE to SLEEP SEQ address in T2 memory*/
261 	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_A2S);
262 
263 	if (err)
264 		pr_err("TWL4030 sleep sequence config error\n");
265 
266 	return err;
267 }
268 
269 static int twl4030_config_warmreset_sequence(u8 address)
270 {
271 	int err;
272 	u8 rd_data;
273 
274 	/* Set WARM RESET SEQ address for P1 */
275 	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_WARM);
276 	if (err)
277 		goto out;
278 
279 	/* P1/P2/P3 enable WARMRESET */
280 	err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P1_SW_EVENTS);
281 	if (err)
282 		goto out;
283 
284 	rd_data |= ENABLE_WARMRESET;
285 	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P1_SW_EVENTS);
286 	if (err)
287 		goto out;
288 
289 	err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P2_SW_EVENTS);
290 	if (err)
291 		goto out;
292 
293 	rd_data |= ENABLE_WARMRESET;
294 	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P2_SW_EVENTS);
295 	if (err)
296 		goto out;
297 
298 	err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P3_SW_EVENTS);
299 	if (err)
300 		goto out;
301 
302 	rd_data |= ENABLE_WARMRESET;
303 	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P3_SW_EVENTS);
304 out:
305 	if (err)
306 		pr_err("TWL4030 warmreset seq config error\n");
307 	return err;
308 }
309 
310 static int twl4030_configure_resource(struct twl4030_resconfig *rconfig)
311 {
312 	int rconfig_addr;
313 	int err;
314 	u8 type;
315 	u8 grp;
316 	u8 remap;
317 
318 	if (rconfig->resource > TOTAL_RESOURCES) {
319 		pr_err("TWL4030 Resource %d does not exist\n",
320 			rconfig->resource);
321 		return -EINVAL;
322 	}
323 
324 	rconfig_addr = res_config_addrs[rconfig->resource];
325 
326 	/* Set resource group */
327 	err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &grp,
328 			      rconfig_addr + DEV_GRP_OFFSET);
329 	if (err) {
330 		pr_err("TWL4030 Resource %d group could not be read\n",
331 			rconfig->resource);
332 		return err;
333 	}
334 
335 	if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) {
336 		grp &= ~DEV_GRP_MASK;
337 		grp |= rconfig->devgroup << DEV_GRP_SHIFT;
338 		err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER,
339 				       grp, rconfig_addr + DEV_GRP_OFFSET);
340 		if (err < 0) {
341 			pr_err("TWL4030 failed to program devgroup\n");
342 			return err;
343 		}
344 	}
345 
346 	/* Set resource types */
347 	err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &type,
348 				rconfig_addr + TYPE_OFFSET);
349 	if (err < 0) {
350 		pr_err("TWL4030 Resource %d type could not be read\n",
351 			rconfig->resource);
352 		return err;
353 	}
354 
355 	if (rconfig->type != TWL4030_RESCONFIG_UNDEF) {
356 		type &= ~TYPE_MASK;
357 		type |= rconfig->type << TYPE_SHIFT;
358 	}
359 
360 	if (rconfig->type2 != TWL4030_RESCONFIG_UNDEF) {
361 		type &= ~TYPE2_MASK;
362 		type |= rconfig->type2 << TYPE2_SHIFT;
363 	}
364 
365 	err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER,
366 				type, rconfig_addr + TYPE_OFFSET);
367 	if (err < 0) {
368 		pr_err("TWL4030 failed to program resource type\n");
369 		return err;
370 	}
371 
372 	/* Set remap states */
373 	err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &remap,
374 			      rconfig_addr + REMAP_OFFSET);
375 	if (err < 0) {
376 		pr_err("TWL4030 Resource %d remap could not be read\n",
377 			rconfig->resource);
378 		return err;
379 	}
380 
381 	if (rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) {
382 		remap &= ~OFF_STATE_MASK;
383 		remap |= rconfig->remap_off << OFF_STATE_SHIFT;
384 	}
385 
386 	if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) {
387 		remap &= ~SLEEP_STATE_MASK;
388 		remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT;
389 	}
390 
391 	err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER,
392 			       remap,
393 			       rconfig_addr + REMAP_OFFSET);
394 	if (err < 0) {
395 		pr_err("TWL4030 failed to program remap\n");
396 		return err;
397 	}
398 
399 	return 0;
400 }
401 
402 static int load_twl4030_script(struct twl4030_script *tscript,
403 	       u8 address)
404 {
405 	int err;
406 	static int order;
407 
408 	/* Make sure the script isn't going beyond last valid address (0x3f) */
409 	if ((address + tscript->size) > END_OF_SCRIPT) {
410 		pr_err("TWL4030 scripts too big error\n");
411 		return -EINVAL;
412 	}
413 
414 	err = twl4030_write_script(address, tscript->script, tscript->size);
415 	if (err)
416 		goto out;
417 
418 	if (tscript->flags & TWL4030_WRST_SCRIPT) {
419 		err = twl4030_config_warmreset_sequence(address);
420 		if (err)
421 			goto out;
422 	}
423 	if (tscript->flags & TWL4030_WAKEUP12_SCRIPT) {
424 		err = twl4030_config_wakeup12_sequence(address);
425 		if (err)
426 			goto out;
427 		order = 1;
428 	}
429 	if (tscript->flags & TWL4030_WAKEUP3_SCRIPT) {
430 		err = twl4030_config_wakeup3_sequence(address);
431 		if (err)
432 			goto out;
433 	}
434 	if (tscript->flags & TWL4030_SLEEP_SCRIPT) {
435 		if (!order)
436 			pr_warning("TWL4030: Bad order of scripts (sleep "\
437 					"script before wakeup) Leads to boot"\
438 					"failure on some boards\n");
439 		err = twl4030_config_sleep_sequence(address);
440 	}
441 out:
442 	return err;
443 }
444 
445 int twl4030_remove_script(u8 flags)
446 {
447 	int err = 0;
448 
449 	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
450 			       TWL4030_PM_MASTER_PROTECT_KEY);
451 	if (err) {
452 		pr_err("twl4030: unable to unlock PROTECT_KEY\n");
453 		return err;
454 	}
455 
456 	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
457 			       TWL4030_PM_MASTER_PROTECT_KEY);
458 	if (err) {
459 		pr_err("twl4030: unable to unlock PROTECT_KEY\n");
460 		return err;
461 	}
462 
463 	if (flags & TWL4030_WRST_SCRIPT) {
464 		err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
465 				       R_SEQ_ADD_WARM);
466 		if (err)
467 			return err;
468 	}
469 	if (flags & TWL4030_WAKEUP12_SCRIPT) {
470 		err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
471 				       R_SEQ_ADD_S2A12);
472 		if (err)
473 			return err;
474 	}
475 	if (flags & TWL4030_WAKEUP3_SCRIPT) {
476 		err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
477 				       R_SEQ_ADD_S2A3);
478 		if (err)
479 			return err;
480 	}
481 	if (flags & TWL4030_SLEEP_SCRIPT) {
482 		err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
483 				       R_SEQ_ADD_A2S);
484 		if (err)
485 			return err;
486 	}
487 
488 	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
489 			       TWL4030_PM_MASTER_PROTECT_KEY);
490 	if (err)
491 		pr_err("TWL4030 Unable to relock registers\n");
492 
493 	return err;
494 }
495 
496 int twl4030_power_configure_scripts(struct twl4030_power_data *pdata)
497 {
498 	int err;
499 	int i;
500 	u8 address = twl4030_start_script_address;
501 
502 	for (i = 0; i < pdata->num; i++) {
503 		err = load_twl4030_script(pdata->scripts[i], address);
504 		if (err)
505 			return err;
506 		address += pdata->scripts[i]->size;
507 	}
508 
509 	return 0;
510 }
511 
512 int twl4030_power_configure_resources(struct twl4030_power_data *pdata)
513 {
514 	struct twl4030_resconfig *resconfig = pdata->resource_config;
515 	int err;
516 
517 	if (resconfig) {
518 		while (resconfig->resource) {
519 			err = twl4030_configure_resource(resconfig);
520 			if (err)
521 				return err;
522 			resconfig++;
523 		}
524 	}
525 
526 	return 0;
527 }
528 
529 /*
530  * In master mode, start the power off sequence.
531  * After a successful execution, TWL shuts down the power to the SoC
532  * and all peripherals connected to it.
533  */
534 void twl4030_power_off(void)
535 {
536 	int err;
537 
538 	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, PWR_DEVOFF,
539 			       TWL4030_PM_MASTER_P1_SW_EVENTS);
540 	if (err)
541 		pr_err("TWL4030 Unable to power off\n");
542 }
543 
544 static bool twl4030_power_use_poweroff(struct twl4030_power_data *pdata,
545 					struct device_node *node)
546 {
547 	if (pdata && pdata->use_poweroff)
548 		return true;
549 
550 	if (of_property_read_bool(node, "ti,use_poweroff"))
551 		return true;
552 
553 	return false;
554 }
555 
556 int twl4030_power_probe(struct platform_device *pdev)
557 {
558 	struct twl4030_power_data *pdata = pdev->dev.platform_data;
559 	struct device_node *node = pdev->dev.of_node;
560 	int err = 0;
561 	u8 val;
562 
563 	if (!pdata && !node) {
564 		dev_err(&pdev->dev, "Platform data is missing\n");
565 		return -EINVAL;
566 	}
567 
568 	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
569 			       TWL4030_PM_MASTER_PROTECT_KEY);
570 	if (err)
571 		goto unlock;
572 
573 	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
574 			       TWL4030_PM_MASTER_PROTECT_KEY);
575 	if (err)
576 		goto unlock;
577 
578 	if (pdata) {
579 		/* TODO: convert to device tree */
580 		err = twl4030_power_configure_scripts(pdata);
581 		if (err)
582 			goto load;
583 		err = twl4030_power_configure_resources(pdata);
584 		if (err)
585 			goto resource;
586 	}
587 
588 	/* Board has to be wired properly to use this feature */
589 	if (twl4030_power_use_poweroff(pdata, node) && !pm_power_off) {
590 		/* Default for SEQ_OFFSYNC is set, lets ensure this */
591 		err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val,
592 				      TWL4030_PM_MASTER_CFG_P123_TRANSITION);
593 		if (err) {
594 			pr_warning("TWL4030 Unable to read registers\n");
595 
596 		} else if (!(val & SEQ_OFFSYNC)) {
597 			val |= SEQ_OFFSYNC;
598 			err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, val,
599 					TWL4030_PM_MASTER_CFG_P123_TRANSITION);
600 			if (err) {
601 				pr_err("TWL4030 Unable to setup SEQ_OFFSYNC\n");
602 				goto relock;
603 			}
604 		}
605 
606 		pm_power_off = twl4030_power_off;
607 	}
608 
609 relock:
610 	err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
611 			       TWL4030_PM_MASTER_PROTECT_KEY);
612 	if (err)
613 		pr_err("TWL4030 Unable to relock registers\n");
614 	return err;
615 
616 unlock:
617 	if (err)
618 		pr_err("TWL4030 Unable to unlock registers\n");
619 	return err;
620 load:
621 	if (err)
622 		pr_err("TWL4030 failed to load scripts\n");
623 	return err;
624 resource:
625 	if (err)
626 		pr_err("TWL4030 failed to configure resource\n");
627 	return err;
628 }
629 
630 static int twl4030_power_remove(struct platform_device *pdev)
631 {
632 	return 0;
633 }
634 
635 #ifdef CONFIG_OF
636 static const struct of_device_id twl4030_power_of_match[] = {
637 	{.compatible = "ti,twl4030-power", },
638 	{ },
639 };
640 MODULE_DEVICE_TABLE(of, twl4030_power_of_match);
641 #endif
642 
643 static struct platform_driver twl4030_power_driver = {
644 	.driver = {
645 		.name	= "twl4030_power",
646 		.owner	= THIS_MODULE,
647 		.of_match_table = of_match_ptr(twl4030_power_of_match),
648 	},
649 	.probe		= twl4030_power_probe,
650 	.remove		= twl4030_power_remove,
651 };
652 
653 module_platform_driver(twl4030_power_driver);
654 
655 MODULE_AUTHOR("Nokia Corporation");
656 MODULE_AUTHOR("Texas Instruments, Inc.");
657 MODULE_DESCRIPTION("Power management for TWL4030");
658 MODULE_LICENSE("GPL");
659 MODULE_ALIAS("platform:twl4030_power");
660