Commit | Line | Data |
---|---|---|
bbd51b1f HZ |
1 | /* |
2 | * Base driver for Marvell 88PM8607 | |
3 | * | |
4 | * Copyright (C) 2009 Marvell International Ltd. | |
5 | * Haojian Zhuang <haojian.zhuang@marvell.com> | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License version 2 as | |
9 | * published by the Free Software Foundation. | |
10 | */ | |
11 | ||
12 | #include <linux/kernel.h> | |
13 | #include <linux/module.h> | |
14 | #include <linux/interrupt.h> | |
15 | #include <linux/platform_device.h> | |
16 | #include <linux/mfd/core.h> | |
53dbab7a | 17 | #include <linux/mfd/88pm860x.h> |
bbd51b1f HZ |
18 | |
19 | ||
20 | #define PM8607_REG_RESOURCE(_start, _end) \ | |
21 | { \ | |
22 | .start = PM8607_##_start, \ | |
23 | .end = PM8607_##_end, \ | |
24 | .flags = IORESOURCE_IO, \ | |
25 | } | |
26 | ||
27 | static struct resource pm8607_regulator_resources[] = { | |
28 | PM8607_REG_RESOURCE(BUCK1, BUCK1), | |
29 | PM8607_REG_RESOURCE(BUCK2, BUCK2), | |
30 | PM8607_REG_RESOURCE(BUCK3, BUCK3), | |
31 | PM8607_REG_RESOURCE(LDO1, LDO1), | |
32 | PM8607_REG_RESOURCE(LDO2, LDO2), | |
33 | PM8607_REG_RESOURCE(LDO3, LDO3), | |
34 | PM8607_REG_RESOURCE(LDO4, LDO4), | |
35 | PM8607_REG_RESOURCE(LDO5, LDO5), | |
36 | PM8607_REG_RESOURCE(LDO6, LDO6), | |
37 | PM8607_REG_RESOURCE(LDO7, LDO7), | |
38 | PM8607_REG_RESOURCE(LDO8, LDO8), | |
39 | PM8607_REG_RESOURCE(LDO9, LDO9), | |
40 | PM8607_REG_RESOURCE(LDO10, LDO10), | |
41 | PM8607_REG_RESOURCE(LDO12, LDO12), | |
42 | PM8607_REG_RESOURCE(LDO14, LDO14), | |
43 | }; | |
44 | ||
45 | #define PM8607_REG_DEVS(_name, _id) \ | |
46 | { \ | |
47 | .name = "88pm8607-" #_name, \ | |
48 | .num_resources = 1, \ | |
49 | .resources = &pm8607_regulator_resources[PM8607_ID_##_id], \ | |
50 | } | |
51 | ||
52 | static struct mfd_cell pm8607_devs[] = { | |
53 | PM8607_REG_DEVS(buck1, BUCK1), | |
54 | PM8607_REG_DEVS(buck2, BUCK2), | |
55 | PM8607_REG_DEVS(buck3, BUCK3), | |
56 | PM8607_REG_DEVS(ldo1, LDO1), | |
57 | PM8607_REG_DEVS(ldo2, LDO2), | |
58 | PM8607_REG_DEVS(ldo3, LDO3), | |
59 | PM8607_REG_DEVS(ldo4, LDO4), | |
60 | PM8607_REG_DEVS(ldo5, LDO5), | |
61 | PM8607_REG_DEVS(ldo6, LDO6), | |
62 | PM8607_REG_DEVS(ldo7, LDO7), | |
63 | PM8607_REG_DEVS(ldo8, LDO8), | |
64 | PM8607_REG_DEVS(ldo9, LDO9), | |
65 | PM8607_REG_DEVS(ldo10, LDO10), | |
66 | PM8607_REG_DEVS(ldo12, LDO12), | |
67 | PM8607_REG_DEVS(ldo14, LDO14), | |
68 | }; | |
69 | ||
53dbab7a HZ |
70 | static void device_8606_init(struct pm860x_chip *chip, struct i2c_client *i2c, |
71 | struct pm860x_platform_data *pdata) | |
72 | { | |
73 | } | |
74 | ||
75 | static void device_8607_init(struct pm860x_chip *chip, struct i2c_client *i2c, | |
76 | struct pm860x_platform_data *pdata) | |
bbd51b1f HZ |
77 | { |
78 | int i, count; | |
79 | int ret; | |
80 | ||
53dbab7a | 81 | ret = pm860x_reg_read(i2c, PM8607_CHIP_ID); |
bbd51b1f HZ |
82 | if (ret < 0) { |
83 | dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); | |
84 | goto out; | |
85 | } | |
53dbab7a | 86 | if ((ret & PM8607_VERSION_MASK) == PM8607_VERSION) |
bbd51b1f HZ |
87 | dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n", |
88 | ret); | |
89 | else { | |
90 | dev_err(chip->dev, "Failed to detect Marvell 88PM8607. " | |
91 | "Chip ID: %02x\n", ret); | |
92 | goto out; | |
93 | } | |
53dbab7a | 94 | chip->chip_version = ret; |
bbd51b1f | 95 | |
53dbab7a | 96 | ret = pm860x_reg_read(i2c, PM8607_BUCK3); |
bbd51b1f HZ |
97 | if (ret < 0) { |
98 | dev_err(chip->dev, "Failed to read BUCK3 register: %d\n", ret); | |
99 | goto out; | |
100 | } | |
101 | if (ret & PM8607_BUCK3_DOUBLE) | |
102 | chip->buck3_double = 1; | |
103 | ||
53dbab7a | 104 | ret = pm860x_reg_read(i2c, PM8607_MISC1); |
bbd51b1f HZ |
105 | if (ret < 0) { |
106 | dev_err(chip->dev, "Failed to read MISC1 register: %d\n", ret); | |
107 | goto out; | |
108 | } | |
bbd51b1f HZ |
109 | |
110 | count = ARRAY_SIZE(pm8607_devs); | |
111 | for (i = 0; i < count; i++) { | |
112 | ret = mfd_add_devices(chip->dev, i, &pm8607_devs[i], | |
113 | 1, NULL, 0); | |
114 | if (ret != 0) { | |
115 | dev_err(chip->dev, "Failed to add subdevs\n"); | |
116 | goto out; | |
117 | } | |
118 | } | |
119 | out: | |
53dbab7a HZ |
120 | return; |
121 | } | |
122 | ||
123 | int pm860x_device_init(struct pm860x_chip *chip, | |
124 | struct pm860x_platform_data *pdata) | |
125 | { | |
126 | switch (chip->id) { | |
127 | case CHIP_PM8606: | |
128 | device_8606_init(chip, chip->client, pdata); | |
129 | break; | |
130 | case CHIP_PM8607: | |
131 | device_8607_init(chip, chip->client, pdata); | |
132 | break; | |
133 | } | |
134 | ||
135 | if (chip->companion) { | |
136 | switch (chip->id) { | |
137 | case CHIP_PM8607: | |
138 | device_8606_init(chip, chip->companion, pdata); | |
139 | break; | |
140 | case CHIP_PM8606: | |
141 | device_8607_init(chip, chip->companion, pdata); | |
142 | break; | |
143 | } | |
144 | } | |
145 | return 0; | |
bbd51b1f HZ |
146 | } |
147 | ||
53dbab7a | 148 | void pm860x_device_exit(struct pm860x_chip *chip) |
bbd51b1f HZ |
149 | { |
150 | mfd_remove_devices(chip->dev); | |
151 | } | |
152 | ||
53dbab7a | 153 | MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x"); |
bbd51b1f HZ |
154 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); |
155 | MODULE_LICENSE("GPL"); |