]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
platform/x86: mlx-platform: Add mlxreg-fan platform driver activation
authorVadim Pasternak <vadimp@mellanox.com>
Thu, 26 Jul 2018 22:40:57 +0000 (22:40 +0000)
committerDarren Hart (VMware) <dvhart@infradead.org>
Thu, 2 Aug 2018 00:41:31 +0000 (17:41 -0700)
Add mlxreg-fan platform driver activation. FAN driver uses the same regmap
infrastructure as others Mellanox platform drivers. Specific registers
description for default FAN platform data configuration are added to
mlx-platform. There are the registers for tachometers reading, PWM
control and FAN ownership control. The last one has a default value,
which is set at initialization time through the regmap infrastructure,
which is necessary for moving FAN control ownership from hardware to
software.

Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
Signed-off-by: Darren Hart (VMware) <dvhart@infradead.org>
drivers/platform/x86/mlx-platform.c

index 3a227509c7acc62e0fbaf170225daa209d5a7f1a..deea6a6339af009a65770c06392e6ce6d306fce8 100644 (file)
@@ -59,6 +59,7 @@
 #define MLXPLAT_CPLD_LPC_REG_WP1_OFFSET                0x31
 #define MLXPLAT_CPLD_LPC_REG_GP2_OFFSET                0x32
 #define MLXPLAT_CPLD_LPC_REG_WP2_OFFSET                0x33
+#define MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET        0x37
 #define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET       0x3a
 #define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET  0x3b
 #define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET     0x40
 #define MLXPLAT_CPLD_LPC_REG_FAN_OFFSET                0x88
 #define MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET  0x89
 #define MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET   0x8a
+#define MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET       0xe3
+#define MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET     0xe4
+#define MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET     0xe5
+#define MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET     0xe6
+#define MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET     0xe7
+#define MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET     0xe8
+#define MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET     0xe9
+#define MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET     0xea
+#define MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET     0xeb
+#define MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET     0xec
+#define MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET    0xed
+#define MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET    0xee
+#define MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET    0xef
 #define MLXPLAT_CPLD_LPC_IO_RANGE              0x100
 #define MLXPLAT_CPLD_LPC_I2C_CH1_OFF           0xdb
 #define MLXPLAT_CPLD_LPC_I2C_CH2_OFF           0xda
+
 #define MLXPLAT_CPLD_LPC_PIO_OFFSET            0x10000UL
 #define MLXPLAT_CPLD_LPC_REG1  ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \
                                  MLXPLAT_CPLD_LPC_I2C_CH1_OFF) | \
  * @pdev_hotplug - hotplug platform devices
  * @pdev_led - led platform devices
  * @pdev_io_regs - register access platform devices
+ * @pdev_fan - FAN platform devices
  */
 struct mlxplat_priv {
        struct platform_device *pdev_i2c;
@@ -138,6 +154,7 @@ struct mlxplat_priv {
        struct platform_device *pdev_hotplug;
        struct platform_device *pdev_led;
        struct platform_device *pdev_io_regs;
+       struct platform_device *pdev_fan;
 };
 
 /* Regions for LPC I2C controller and LPC base register space */
@@ -929,6 +946,79 @@ static struct mlxreg_core_platform_data mlxplat_default_regs_io_data = {
                .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_regs_io_data),
 };
 
+/* Platform FAN default */
+static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = {
+       {
+               .label = "pwm1",
+               .reg = MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET,
+       },
+       {
+               .label = "tacho1",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho2",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho3",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho4",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho5",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho6",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho7",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho8",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho9",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho10",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho11",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+       {
+               .label = "tacho12",
+               .reg = MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET,
+               .mask = GENMASK(7, 0),
+       },
+};
+
+static struct mlxreg_core_platform_data mlxplat_default_fan_data = {
+               .data = mlxplat_mlxcpld_default_fan_data,
+               .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_fan_data),
+};
+
 static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
 {
        switch (reg) {
@@ -949,6 +1039,8 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
        case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
                return true;
        }
        return false;
@@ -983,6 +1075,20 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
        case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
                return true;
        }
        return false;
@@ -1015,6 +1121,20 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
        case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET:
        case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET:
+       case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET:
                return true;
        }
        return false;
@@ -1023,6 +1143,7 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
 static const struct reg_default mlxplat_mlxcpld_regmap_default[] = {
        { MLXPLAT_CPLD_LPC_REG_WP1_OFFSET, 0x00 },
        { MLXPLAT_CPLD_LPC_REG_WP2_OFFSET, 0x00 },
+       { MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, 0x00 },
 };
 
 struct mlxplat_mlxcpld_regmap_context {
@@ -1071,6 +1192,7 @@ static struct platform_device *mlxplat_dev;
 static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug;
 static struct mlxreg_core_platform_data *mlxplat_led;
 static struct mlxreg_core_platform_data *mlxplat_regs_io;
+static struct mlxreg_core_platform_data *mlxplat_fan;
 
 static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
 {
@@ -1155,6 +1277,7 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi)
        mlxplat_hotplug->deferred_nr =
                mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
        mlxplat_led = &mlxplat_msn21xx_led_data;
+       mlxplat_fan = &mlxplat_default_fan_data;
 
        return 1;
 };
@@ -1410,14 +1533,31 @@ static int __init mlxplat_init(void)
                }
        }
 
+       /* Add FAN driver. */
+       if (mlxplat_fan) {
+               mlxplat_fan->regmap = mlxplat_hotplug->regmap;
+               priv->pdev_fan = platform_device_register_resndata(
+                                       &mlxplat_dev->dev, "mlxreg-fan",
+                                       PLATFORM_DEVID_NONE, NULL, 0,
+                                       mlxplat_fan,
+                                       sizeof(*mlxplat_fan));
+               if (IS_ERR(priv->pdev_io_regs)) {
+                       err = PTR_ERR(priv->pdev_io_regs);
+                       goto fail_platform_io_regs_register;
+               }
+       }
+
        /* Sync registers with hardware. */
        regcache_mark_dirty(mlxplat_hotplug->regmap);
        err = regcache_sync(mlxplat_hotplug->regmap);
        if (err)
-               goto fail_platform_io_regs_register;
+               goto fail_platform_fan_register;
 
        return 0;
 
+fail_platform_fan_register:
+       if (mlxplat_fan)
+               platform_device_unregister(priv->pdev_fan);
 fail_platform_io_regs_register:
        if (mlxplat_regs_io)
                platform_device_unregister(priv->pdev_io_regs);
@@ -1441,6 +1581,8 @@ static void __exit mlxplat_exit(void)
        struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
        int i;
 
+       if (priv->pdev_fan)
+               platform_device_unregister(priv->pdev_fan);
        if (priv->pdev_io_regs)
                platform_device_unregister(priv->pdev_io_regs);
        platform_device_unregister(priv->pdev_led);