Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp755884imm; Tue, 5 Jun 2018 04:04:45 -0700 (PDT) X-Google-Smtp-Source: ADUXVKKVv46bPAaOj3l4C+hVe/ASyxo31EqHngJKGJ3DNeJJvXll2bmtKxFSlGWE/zWG70I8iwbc X-Received: by 2002:a17:902:8a94:: with SMTP id p20-v6mr25854424plo.258.1528196685780; Tue, 05 Jun 2018 04:04:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1528196685; cv=none; d=google.com; s=arc-20160816; b=YJBU+GgWLWCR1MalHCfjL6b53CC+QKo1x52fz+i5USO++p6uUE2FbfchxwrL1YGRL7 j756ASx5zzgZTC1I11lfTckB0vt6ph/1ghT6VGw2+l4c/u+ev5h/cMgONrRlZ6ggaK0p krVlVGzsklY3nibaVwYTR2Pyw6lUugfASOlmS4tNugUy79hNbG0PiWR9I6I4zbQ6C1N2 QdvsJFMK6F5ev1JeOK5w1gr7gGaMVgI3yFnyp+fa8AqfN1dfT3QW8uCWJG8QodwWsgyw 71eyrPGW424kkmtXFqNd93j45y7hKztpCkwOxu3u7dDmQlCmLeNUsCjucy+YAcwBgRZb bzXg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=prYbkkdyRr4dapXMaAfrZP6neG1G92nx7HrCo98Gkf0=; b=Qn/ENwBF9+ZKu2vr46wG/3B29AnuCgWUy28RPdhvvWGWLCAMaqRJUJ9gj6WHHIq7v6 UtwDNkfU42b+9i14uzS4pz7gDMnRlSsdSoNt6Vt42H9ARpZCCFwEWHdkiqljHeKoeJ4p Ouvuqd/OhjK+u4jW1empb/phvD220ug+JpVwrp+3TL5IWmrfADn1G4nLeRfWEVvsJlHX ki675YAKaAImdW3ttyQAFo4ZlKCM+1Qfhneun32gW91qQYHiQ+hWh/aqAUSAD5y3Gx1n bSH2XePiDEeiUX3UJx5lBik5rSiB1hiVUHnzoeFMkyDLO/0OGZEqm+r/PSDDYZGDbziB EgBQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mellanox.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d4-v6si4756324pfa.263.2018.06.05.04.04.30; Tue, 05 Jun 2018 04:04:45 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mellanox.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751895AbeFELCq (ORCPT + 99 others); Tue, 5 Jun 2018 07:02:46 -0400 Received: from mail-il-dmz.mellanox.com ([193.47.165.129]:51236 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751640AbeFELCl (ORCPT ); Tue, 5 Jun 2018 07:02:41 -0400 Received: from Internal Mail-Server by MTLPINE1 (envelope-from vadimp@mellanox.com) with ESMTPS (AES256-SHA encrypted); 5 Jun 2018 14:04:49 +0300 Received: from r-mgtswh-226.mtr.labs.mlnx. (r-mgtswh-226.mtr.labs.mlnx [10.209.1.51]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id w55B2YsN019101; Tue, 5 Jun 2018 14:02:36 +0300 From: Vadim Pasternak To: dvhart@infradead.org, andy.shevchenko@gmail.com, gregkh@linuxfoundation.org Cc: linux-kernel@vger.kernel.org, platform-driver-x86@vger.kernel.org, jiri@resnulli.us, michaelsh@mellanox.com, ivecera@redhat.com, Vadim Pasternak Subject: [PATCH v5 7/8] platform/x86: mlx-platform: Add mlxreg-io platform driver activation Date: Tue, 5 Jun 2018 12:58:20 +0000 Message-Id: <1528203501-129092-2-git-send-email-vadimp@mellanox.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1528203501-129092-1-git-send-email-vadimp@mellanox.com> References: <1528203501-129092-1-git-send-email-vadimp@mellanox.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add mlxreg-io platform driver activation. Access driver uses the same regmap infrastructure as others Mellanox platform drivers. Specific registers description for default platform data configuration are added to mlx-platform. There are the registers for resets control, reset causes monitoring, programmable devices version reading and mux select control. This platform data is passed to mlxreg-io driver. Also some default values for the register are set at initialization time through the regmap infrastructure, which are necessary for moving write protection from the general purpose registers, which are used by mlxreg-io for write access. Signed-off-by: Vadim Pasternak v4-v5: Changes added by Vadim: - Add two new attributes for ASIC health and main power domain shutdown. --- drivers/platform/x86/mlx-platform.c | 175 +++++++++++++++++++++++++++++++++++- 1 file changed, 173 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c index a0fd9aa..3a22750 100644 --- a/drivers/platform/x86/mlx-platform.c +++ b/drivers/platform/x86/mlx-platform.c @@ -47,15 +47,23 @@ /* LPC bus IO offsets */ #define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR 0x2000 #define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500 +#define MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET 0x00 +#define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET 0x01 +#define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET 0x1d #define MLXPLAT_CPLD_LPC_REG_LED1_OFFSET 0x20 #define MLXPLAT_CPLD_LPC_REG_LED2_OFFSET 0x21 #define MLXPLAT_CPLD_LPC_REG_LED3_OFFSET 0x22 #define MLXPLAT_CPLD_LPC_REG_LED4_OFFSET 0x23 #define MLXPLAT_CPLD_LPC_REG_LED5_OFFSET 0x24 +#define MLXPLAT_CPLD_LPC_REG_GP1_OFFSET 0x30 +#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_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_AGGRLO_MASK_OFFSET 0x41 +#define MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET 0x50 #define MLXPLAT_CPLD_LPC_REG_PSU_OFFSET 0x58 #define MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET 0x59 #define MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET 0x5a @@ -122,12 +130,14 @@ * @pdev_mux - array of mux platform devices * @pdev_hotplug - hotplug platform devices * @pdev_led - led platform devices + * @pdev_io_regs - register access platform devices */ struct mlxplat_priv { struct platform_device *pdev_i2c; struct platform_device *pdev_mux[MLXPLAT_CPLD_LPC_MUX_DEVS]; struct platform_device *pdev_hotplug; struct platform_device *pdev_led; + struct platform_device *pdev_io_regs; }; /* Regions for LPC I2C controller and LPC base register space */ @@ -813,6 +823,111 @@ static struct mlxreg_core_platform_data mlxplat_default_ng_led_data = { .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_led_data), }; +/* Platform register access default */ +static struct mlxreg_core_data mlxplat_mlxcpld_default_regs_io_data[] = { + { + .label = "cpld1_version", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET, + .bit = GENMASK(7, 0), + .mode = 0444, + }, + { + .label = "cpld2_version", + .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET, + .bit = GENMASK(7, 0), + .mode = 0444, + }, + { + .label = "reset_long_pb", + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(0), + .mode = 0444, + }, + { + .label = "reset_short_pb", + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(1), + .mode = 0444, + }, + { + .label = "reset_aux_pwr_or_ref", + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(2), + .mode = 0444, + }, + { + .label = "reset_main_pwr_fail", + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(3), + .mode = 0444, + }, + { + .label = "reset_sw_reset", + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(4), + .mode = 0444, + }, + { + .label = "reset_fw_reset", + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(5), + .mode = 0444, + }, + { + .label = "reset_hotswap_or_wd", + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(6), + .mode = 0444, + }, + { + .label = "reset_asic_thermal", + .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(7), + .mode = 0444, + }, + { + .label = "psu1_on", + .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(0), + .mode = 0200, + }, + { + .label = "psu2_on", + .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(1), + .mode = 0200, + }, + { + .label = "pwr_cycle", + .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(2), + .mode = 0200, + }, + { + .label = "pwr_down", + .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(3), + .mode = 0200, + }, + { + .label = "select_iio", + .reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET, + .mask = GENMASK(7, 0) & ~BIT(6), + .mode = 0644, + }, + { + .label = "asic_health", + .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, + .mask = GENMASK(1, 0), + .bit = 1, + .mode = 0444, + }, +}; + +static struct mlxreg_core_platform_data mlxplat_default_regs_io_data = { + .data = mlxplat_mlxcpld_default_regs_io_data, + .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_regs_io_data), +}; static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) { @@ -822,6 +937,10 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET: case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET: case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET: @@ -838,15 +957,23 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) { switch (reg) { + case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET: + case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET: case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET: case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET: case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET: case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET: case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET: case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET: @@ -864,15 +991,21 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { + case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: + case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET: case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET: + case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET: case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET: case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET: case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET: + case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET: case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET: case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET: case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET: @@ -887,6 +1020,11 @@ static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) return false; } +static const struct reg_default mlxplat_mlxcpld_regmap_default[] = { + { MLXPLAT_CPLD_LPC_REG_WP1_OFFSET, 0x00 }, + { MLXPLAT_CPLD_LPC_REG_WP2_OFFSET, 0x00 }, +}; + struct mlxplat_mlxcpld_regmap_context { void __iomem *base; }; @@ -919,6 +1057,8 @@ static const struct regmap_config mlxplat_mlxcpld_regmap_config = { .writeable_reg = mlxplat_mlxcpld_writeable_reg, .readable_reg = mlxplat_mlxcpld_readable_reg, .volatile_reg = mlxplat_mlxcpld_volatile_reg, + .reg_defaults = mlxplat_mlxcpld_regmap_default, + .num_reg_defaults = ARRAY_SIZE(mlxplat_mlxcpld_regmap_default), .reg_read = mlxplat_mlxcpld_reg_read, .reg_write = mlxplat_mlxcpld_reg_write, }; @@ -930,6 +1070,7 @@ static struct resource mlxplat_mlxcpld_resources[] = { 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 int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi) { @@ -944,6 +1085,7 @@ static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi) mlxplat_hotplug->deferred_nr = mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; mlxplat_led = &mlxplat_default_led_data; + mlxplat_regs_io = &mlxplat_default_regs_io_data; return 1; }; @@ -978,6 +1120,7 @@ static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi) mlxplat_hotplug->deferred_nr = mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; mlxplat_led = &mlxplat_default_led_data; + mlxplat_regs_io = &mlxplat_default_regs_io_data; return 1; }; @@ -1163,7 +1306,7 @@ static int mlxplat_mlxcpld_verify_bus_topology(int *nr) static int __init mlxplat_init(void) { struct mlxplat_priv *priv; - int i, nr, err; + int i, j, nr, err; if (!dmi_check_system(mlxplat_dmi_table)) return -ENODEV; @@ -1233,6 +1376,15 @@ static int __init mlxplat_init(void) goto fail_platform_mux_register; } + /* Set default registers. */ + for (j = 0; j < mlxplat_mlxcpld_regmap_config.num_reg_defaults; j++) { + err = regmap_write(mlxplat_hotplug->regmap, + mlxplat_mlxcpld_regmap_default[j].reg, + mlxplat_mlxcpld_regmap_default[j].def); + if (err) + goto fail_platform_mux_register; + } + /* Add LED driver. */ mlxplat_led->regmap = mlxplat_hotplug->regmap; priv->pdev_led = platform_device_register_resndata( @@ -1244,14 +1396,31 @@ static int __init mlxplat_init(void) goto fail_platform_hotplug_register; } + /* Add registers io access driver. */ + if (mlxplat_regs_io) { + mlxplat_regs_io->regmap = mlxplat_hotplug->regmap; + priv->pdev_io_regs = platform_device_register_resndata( + &mlxplat_dev->dev, "mlxreg-io", + PLATFORM_DEVID_NONE, NULL, 0, + mlxplat_regs_io, + sizeof(*mlxplat_regs_io)); + if (IS_ERR(priv->pdev_io_regs)) { + err = PTR_ERR(priv->pdev_io_regs); + goto fail_platform_led_register; + } + } + /* Sync registers with hardware. */ regcache_mark_dirty(mlxplat_hotplug->regmap); err = regcache_sync(mlxplat_hotplug->regmap); if (err) - goto fail_platform_led_register; + goto fail_platform_io_regs_register; return 0; +fail_platform_io_regs_register: + if (mlxplat_regs_io) + platform_device_unregister(priv->pdev_io_regs); fail_platform_led_register: platform_device_unregister(priv->pdev_led); fail_platform_hotplug_register: @@ -1272,6 +1441,8 @@ static void __exit mlxplat_exit(void) struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev); int i; + if (priv->pdev_io_regs) + platform_device_unregister(priv->pdev_io_regs); platform_device_unregister(priv->pdev_led); platform_device_unregister(priv->pdev_hotplug); -- 2.1.4