diff options
Diffstat (limited to 'drivers/platform/x86/mlx-platform.c')
-rw-r--r-- | drivers/platform/x86/mlx-platform.c | 231 |
1 files changed, 182 insertions, 49 deletions
diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c index 56017143d6a9..03c9e7a76d89 100644 --- a/drivers/platform/x86/mlx-platform.c +++ b/drivers/platform/x86/mlx-platform.c | |||
@@ -35,20 +35,22 @@ | |||
35 | #include <linux/dmi.h> | 35 | #include <linux/dmi.h> |
36 | #include <linux/i2c.h> | 36 | #include <linux/i2c.h> |
37 | #include <linux/i2c-mux.h> | 37 | #include <linux/i2c-mux.h> |
38 | #include <linux/io.h> | ||
38 | #include <linux/module.h> | 39 | #include <linux/module.h> |
39 | #include <linux/platform_device.h> | 40 | #include <linux/platform_device.h> |
40 | #include <linux/platform_data/i2c-mux-reg.h> | 41 | #include <linux/platform_data/i2c-mux-reg.h> |
41 | #include <linux/platform_data/mlxreg.h> | 42 | #include <linux/platform_data/mlxreg.h> |
43 | #include <linux/regmap.h> | ||
42 | 44 | ||
43 | #define MLX_PLAT_DEVICE_NAME "mlxplat" | 45 | #define MLX_PLAT_DEVICE_NAME "mlxplat" |
44 | 46 | ||
45 | /* LPC bus IO offsets */ | 47 | /* LPC bus IO offsets */ |
46 | #define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR 0x2000 | 48 | #define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR 0x2000 |
47 | #define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500 | 49 | #define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500 |
48 | #define MLXPLAT_CPLD_LPC_REG_AGGR_ADRR 0x253a | 50 | #define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a |
49 | #define MLXPLAT_CPLD_LPC_REG_PSU_ADRR 0x2558 | 51 | #define MLXPLAT_CPLD_LPC_REG_PSU_OFFSET 0x58 |
50 | #define MLXPLAT_CPLD_LPC_REG_PWR_ADRR 0x2564 | 52 | #define MLXPLAT_CPLD_LPC_REG_PWR_OFFSET 0x64 |
51 | #define MLXPLAT_CPLD_LPC_REG_FAN_ADRR 0x2588 | 53 | #define MLXPLAT_CPLD_LPC_REG_FAN_OFFSET 0x88 |
52 | #define MLXPLAT_CPLD_LPC_IO_RANGE 0x100 | 54 | #define MLXPLAT_CPLD_LPC_IO_RANGE 0x100 |
53 | #define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb | 55 | #define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb |
54 | #define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda | 56 | #define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda |
@@ -138,78 +140,194 @@ static struct i2c_mux_reg_platform_data mlxplat_mux_data[] = { | |||
138 | }; | 140 | }; |
139 | 141 | ||
140 | /* Platform hotplug devices */ | 142 | /* Platform hotplug devices */ |
141 | static struct mlxreg_hotplug_device mlxplat_mlxcpld_psu[] = { | 143 | static struct i2c_board_info mlxplat_mlxcpld_psu[] = { |
142 | { | 144 | { |
143 | .brdinfo = { I2C_BOARD_INFO("24c02", 0x51) }, | 145 | I2C_BOARD_INFO("24c02", 0x51), |
144 | .nr = 10, | ||
145 | }, | 146 | }, |
146 | { | 147 | { |
147 | .brdinfo = { I2C_BOARD_INFO("24c02", 0x50) }, | 148 | I2C_BOARD_INFO("24c02", 0x50), |
148 | .nr = 10, | ||
149 | }, | 149 | }, |
150 | }; | 150 | }; |
151 | 151 | ||
152 | static struct mlxreg_hotplug_device mlxplat_mlxcpld_pwr[] = { | 152 | static struct i2c_board_info mlxplat_mlxcpld_pwr[] = { |
153 | { | 153 | { |
154 | .brdinfo = { I2C_BOARD_INFO("dps460", 0x59) }, | 154 | I2C_BOARD_INFO("dps460", 0x59), |
155 | .nr = 10, | ||
156 | }, | 155 | }, |
157 | { | 156 | { |
158 | .brdinfo = { I2C_BOARD_INFO("dps460", 0x58) }, | 157 | I2C_BOARD_INFO("dps460", 0x58), |
159 | .nr = 10, | ||
160 | }, | 158 | }, |
161 | }; | 159 | }; |
162 | 160 | ||
163 | static struct mlxreg_hotplug_device mlxplat_mlxcpld_fan[] = { | 161 | static struct i2c_board_info mlxplat_mlxcpld_fan[] = { |
164 | { | 162 | { |
165 | .brdinfo = { I2C_BOARD_INFO("24c32", 0x50) }, | 163 | I2C_BOARD_INFO("24c32", 0x50), |
166 | .nr = 11, | ||
167 | }, | 164 | }, |
168 | { | 165 | { |
169 | .brdinfo = { I2C_BOARD_INFO("24c32", 0x50) }, | 166 | I2C_BOARD_INFO("24c32", 0x50), |
170 | .nr = 12, | ||
171 | }, | 167 | }, |
172 | { | 168 | { |
173 | .brdinfo = { I2C_BOARD_INFO("24c32", 0x50) }, | 169 | I2C_BOARD_INFO("24c32", 0x50), |
174 | .nr = 13, | ||
175 | }, | 170 | }, |
176 | { | 171 | { |
177 | .brdinfo = { I2C_BOARD_INFO("24c32", 0x50) }, | 172 | I2C_BOARD_INFO("24c32", 0x50), |
178 | .nr = 14, | ||
179 | }, | 173 | }, |
180 | }; | 174 | }; |
181 | 175 | ||
182 | /* Platform hotplug default data */ | 176 | /* Platform hotplug default data */ |
177 | static struct mlxreg_core_data mlxplat_mlxcpld_default_psu_items_data[] = { | ||
178 | { | ||
179 | .label = "psu1", | ||
180 | .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, | ||
181 | .mask = BIT(0), | ||
182 | .hpdev.brdinfo = &mlxplat_mlxcpld_psu[0], | ||
183 | .hpdev.nr = 10, | ||
184 | }, | ||
185 | { | ||
186 | .label = "psu2", | ||
187 | .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, | ||
188 | .mask = BIT(1), | ||
189 | .hpdev.brdinfo = &mlxplat_mlxcpld_psu[1], | ||
190 | .hpdev.nr = 10, | ||
191 | }, | ||
192 | }; | ||
193 | |||
194 | static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_items_data[] = { | ||
195 | { | ||
196 | .label = "pwr1", | ||
197 | .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, | ||
198 | .mask = BIT(0), | ||
199 | .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0], | ||
200 | .hpdev.nr = 10, | ||
201 | }, | ||
202 | { | ||
203 | .label = "pwr2", | ||
204 | .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, | ||
205 | .mask = BIT(1), | ||
206 | .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1], | ||
207 | .hpdev.nr = 10, | ||
208 | }, | ||
209 | }; | ||
210 | |||
211 | static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_items_data[] = { | ||
212 | { | ||
213 | .label = "fan1", | ||
214 | .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, | ||
215 | .mask = BIT(0), | ||
216 | .hpdev.brdinfo = &mlxplat_mlxcpld_fan[0], | ||
217 | .hpdev.nr = 11, | ||
218 | }, | ||
219 | { | ||
220 | .label = "fan2", | ||
221 | .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, | ||
222 | .mask = BIT(1), | ||
223 | .hpdev.brdinfo = &mlxplat_mlxcpld_fan[1], | ||
224 | .hpdev.nr = 12, | ||
225 | }, | ||
226 | { | ||
227 | .label = "fan3", | ||
228 | .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, | ||
229 | .mask = BIT(2), | ||
230 | .hpdev.brdinfo = &mlxplat_mlxcpld_fan[2], | ||
231 | .hpdev.nr = 13, | ||
232 | }, | ||
233 | { | ||
234 | .label = "fan4", | ||
235 | .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, | ||
236 | .mask = BIT(3), | ||
237 | .hpdev.brdinfo = &mlxplat_mlxcpld_fan[3], | ||
238 | .hpdev.nr = 14, | ||
239 | }, | ||
240 | }; | ||
241 | |||
242 | static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = { | ||
243 | { | ||
244 | .data = mlxplat_mlxcpld_default_psu_items_data, | ||
245 | .aggr_mask = MLXPLAT_CPLD_AGGR_PSU_MASK_DEF, | ||
246 | .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, | ||
247 | .mask = MLXPLAT_CPLD_PSU_MASK, | ||
248 | .count = ARRAY_SIZE(mlxplat_mlxcpld_psu), | ||
249 | .inversed = 1, | ||
250 | .health = false, | ||
251 | }, | ||
252 | { | ||
253 | .data = mlxplat_mlxcpld_default_pwr_items_data, | ||
254 | .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF, | ||
255 | .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, | ||
256 | .mask = MLXPLAT_CPLD_PWR_MASK, | ||
257 | .count = ARRAY_SIZE(mlxplat_mlxcpld_pwr), | ||
258 | .inversed = 0, | ||
259 | .health = false, | ||
260 | }, | ||
261 | { | ||
262 | .data = mlxplat_mlxcpld_default_fan_items_data, | ||
263 | .aggr_mask = MLXPLAT_CPLD_AGGR_FAN_MASK_DEF, | ||
264 | .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, | ||
265 | .mask = MLXPLAT_CPLD_FAN_MASK, | ||
266 | .count = ARRAY_SIZE(mlxplat_mlxcpld_fan), | ||
267 | .inversed = 1, | ||
268 | .health = false, | ||
269 | }, | ||
270 | }; | ||
271 | |||
183 | static | 272 | static |
184 | struct mlxreg_hotplug_platform_data mlxplat_mlxcpld_default_data = { | 273 | struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_data = { |
185 | .top_aggr_offset = MLXPLAT_CPLD_LPC_REG_AGGR_ADRR, | 274 | .items = mlxplat_mlxcpld_default_items, |
186 | .top_aggr_mask = MLXPLAT_CPLD_AGGR_MASK_DEF, | 275 | .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_items), |
187 | .top_aggr_psu_mask = MLXPLAT_CPLD_AGGR_PSU_MASK_DEF, | 276 | .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, |
188 | .psu_reg_offset = MLXPLAT_CPLD_LPC_REG_PSU_ADRR, | 277 | .mask = MLXPLAT_CPLD_AGGR_MASK_DEF, |
189 | .psu_mask = MLXPLAT_CPLD_PSU_MASK, | ||
190 | .psu_count = ARRAY_SIZE(mlxplat_mlxcpld_psu), | ||
191 | .psu = mlxplat_mlxcpld_psu, | ||
192 | .top_aggr_pwr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF, | ||
193 | .pwr_reg_offset = MLXPLAT_CPLD_LPC_REG_PWR_ADRR, | ||
194 | .pwr_mask = MLXPLAT_CPLD_PWR_MASK, | ||
195 | .pwr_count = ARRAY_SIZE(mlxplat_mlxcpld_pwr), | ||
196 | .pwr = mlxplat_mlxcpld_pwr, | ||
197 | .top_aggr_fan_mask = MLXPLAT_CPLD_AGGR_FAN_MASK_DEF, | ||
198 | .fan_reg_offset = MLXPLAT_CPLD_LPC_REG_FAN_ADRR, | ||
199 | .fan_mask = MLXPLAT_CPLD_FAN_MASK, | ||
200 | .fan_count = ARRAY_SIZE(mlxplat_mlxcpld_fan), | ||
201 | .fan = mlxplat_mlxcpld_fan, | ||
202 | }; | 278 | }; |
203 | 279 | ||
204 | /* Platform hotplug MSN21xx system family data */ | 280 | /* Platform hotplug MSN21xx system family data */ |
281 | static struct mlxreg_core_item mlxplat_mlxcpld_msn21xx_items[] = { | ||
282 | { | ||
283 | .data = mlxplat_mlxcpld_default_pwr_items_data, | ||
284 | .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF, | ||
285 | .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, | ||
286 | .mask = MLXPLAT_CPLD_PWR_MASK, | ||
287 | .count = ARRAY_SIZE(mlxplat_mlxcpld_pwr), | ||
288 | .inversed = 0, | ||
289 | .health = false, | ||
290 | }, | ||
291 | }; | ||
292 | |||
205 | static | 293 | static |
206 | struct mlxreg_hotplug_platform_data mlxplat_mlxcpld_msn21xx_data = { | 294 | struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn21xx_data = { |
207 | .top_aggr_offset = MLXPLAT_CPLD_LPC_REG_AGGR_ADRR, | 295 | .items = mlxplat_mlxcpld_msn21xx_items, |
208 | .top_aggr_mask = MLXPLAT_CPLD_AGGR_MASK_MSN21XX, | 296 | .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_items), |
209 | .top_aggr_pwr_mask = MLXPLAT_CPLD_AGGR_MASK_MSN21XX, | 297 | .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, |
210 | .pwr_reg_offset = MLXPLAT_CPLD_LPC_REG_PWR_ADRR, | 298 | .mask = MLXPLAT_CPLD_AGGR_MASK_DEF, |
211 | .pwr_mask = MLXPLAT_CPLD_PWR_MASK, | 299 | }; |
212 | .pwr_count = ARRAY_SIZE(mlxplat_mlxcpld_pwr), | 300 | |
301 | struct mlxplat_mlxcpld_regmap_context { | ||
302 | void __iomem *base; | ||
303 | }; | ||
304 | |||
305 | static struct mlxplat_mlxcpld_regmap_context mlxplat_mlxcpld_regmap_ctx; | ||
306 | |||
307 | static int | ||
308 | mlxplat_mlxcpld_reg_read(void *context, unsigned int reg, unsigned int *val) | ||
309 | { | ||
310 | struct mlxplat_mlxcpld_regmap_context *ctx = context; | ||
311 | |||
312 | *val = ioread8(ctx->base + reg); | ||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | static int | ||
317 | mlxplat_mlxcpld_reg_write(void *context, unsigned int reg, unsigned int val) | ||
318 | { | ||
319 | struct mlxplat_mlxcpld_regmap_context *ctx = context; | ||
320 | |||
321 | iowrite8(val, ctx->base + reg); | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static const struct regmap_config mlxplat_mlxcpld_regmap_config = { | ||
326 | .reg_bits = 8, | ||
327 | .val_bits = 8, | ||
328 | .max_register = 255, | ||
329 | .reg_read = mlxplat_mlxcpld_reg_read, | ||
330 | .reg_write = mlxplat_mlxcpld_reg_write, | ||
213 | }; | 331 | }; |
214 | 332 | ||
215 | static struct resource mlxplat_mlxcpld_resources[] = { | 333 | static struct resource mlxplat_mlxcpld_resources[] = { |
@@ -217,7 +335,7 @@ static struct resource mlxplat_mlxcpld_resources[] = { | |||
217 | }; | 335 | }; |
218 | 336 | ||
219 | static struct platform_device *mlxplat_dev; | 337 | static struct platform_device *mlxplat_dev; |
220 | static struct mlxreg_hotplug_platform_data *mlxplat_hotplug; | 338 | static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug; |
221 | 339 | ||
222 | static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi) | 340 | static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi) |
223 | { | 341 | { |
@@ -328,6 +446,21 @@ static int __init mlxplat_init(void) | |||
328 | } | 446 | } |
329 | } | 447 | } |
330 | 448 | ||
449 | mlxplat_mlxcpld_regmap_ctx.base = devm_ioport_map(&mlxplat_dev->dev, | ||
450 | mlxplat_lpc_resources[1].start, 1); | ||
451 | if (IS_ERR(mlxplat_mlxcpld_regmap_ctx.base)) { | ||
452 | err = PTR_ERR(mlxplat_mlxcpld_regmap_ctx.base); | ||
453 | goto fail_platform_mux_register; | ||
454 | } | ||
455 | |||
456 | mlxplat_hotplug->regmap = devm_regmap_init(&mlxplat_dev->dev, NULL, | ||
457 | &mlxplat_mlxcpld_regmap_ctx, | ||
458 | &mlxplat_mlxcpld_regmap_config); | ||
459 | if (IS_ERR(mlxplat_hotplug->regmap)) { | ||
460 | err = PTR_ERR(mlxplat_hotplug->regmap); | ||
461 | goto fail_platform_mux_register; | ||
462 | } | ||
463 | |||
331 | priv->pdev_hotplug = platform_device_register_resndata( | 464 | priv->pdev_hotplug = platform_device_register_resndata( |
332 | &mlxplat_dev->dev, "mlxreg-hotplug", | 465 | &mlxplat_dev->dev, "mlxreg-hotplug", |
333 | PLATFORM_DEVID_NONE, | 466 | PLATFORM_DEVID_NONE, |