aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform/x86/mlx-platform.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/platform/x86/mlx-platform.c')
-rw-r--r--drivers/platform/x86/mlx-platform.c231
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 */
141static struct mlxreg_hotplug_device mlxplat_mlxcpld_psu[] = { 143static 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
152static struct mlxreg_hotplug_device mlxplat_mlxcpld_pwr[] = { 152static 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
163static struct mlxreg_hotplug_device mlxplat_mlxcpld_fan[] = { 161static 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 */
177static 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
194static 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
211static 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
242static 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
183static 272static
184struct mlxreg_hotplug_platform_data mlxplat_mlxcpld_default_data = { 273struct 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 */
281static 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
205static 293static
206struct mlxreg_hotplug_platform_data mlxplat_mlxcpld_msn21xx_data = { 294struct 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
301struct mlxplat_mlxcpld_regmap_context {
302 void __iomem *base;
303};
304
305static struct mlxplat_mlxcpld_regmap_context mlxplat_mlxcpld_regmap_ctx;
306
307static int
308mlxplat_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
316static int
317mlxplat_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
325static 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
215static struct resource mlxplat_mlxcpld_resources[] = { 333static struct resource mlxplat_mlxcpld_resources[] = {
@@ -217,7 +335,7 @@ static struct resource mlxplat_mlxcpld_resources[] = {
217}; 335};
218 336
219static struct platform_device *mlxplat_dev; 337static struct platform_device *mlxplat_dev;
220static struct mlxreg_hotplug_platform_data *mlxplat_hotplug; 338static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug;
221 339
222static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi) 340static 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,