Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mfd: menf21bmc: Introduce MEN 14F021P00 BMC MFD Core driver

The MEN 14F021P00 Board Management Controller provides an
I2C interface to the host to access the feature implemented in the BMC.
The BMC is a PIC Microntroller assembled on CPCI Card from MEN Mikroelektronik
and on a few Box/Display Computer.

Added MFD Core driver, supporting the I2C communication to the device.

The MFD driver currently supports the following features:
- Watchdog
- LEDs
- Hwmon (voltage monitoring)

Signed-off-by: Andreas Werner <andreas.werner@men.de>
Signed-off-by: Lee Jones <lee.jones@linaro.org>

authored by

Andreas Werner and committed by
Lee Jones
dfbdcd7c 52addcf9

+148
+15
drivers/mfd/Kconfig
··· 454 454 additional drivers must be enabled in order to use the functionality 455 455 of the device. 456 456 457 + config MFD_MENF21BMC 458 + tristate "MEN 14F021P00 Board Management Controller Support" 459 + depends on I2C 460 + select MFD_CORE 461 + help 462 + Say yes here to add support for the MEN 14F021P00 BMC 463 + which is a Board Management Controller connected to the I2C bus. 464 + The device supports multiple sub-devices like LED, HWMON and WDT. 465 + This driver provides common support for accessing the devices; 466 + additional drivers must be enabled in order to use the 467 + functionality of the BMC device. 468 + 469 + This driver can also be built as a module. If so the module 470 + will be called menf21bmc. 471 + 457 472 config EZX_PCAP 458 473 bool "Motorola EZXPCAP Support" 459 474 depends on SPI_MASTER
+1
drivers/mfd/Makefile
··· 169 169 obj-$(CONFIG_MFD_AS3722) += as3722.o 170 170 obj-$(CONFIG_MFD_STW481X) += stw481x.o 171 171 obj-$(CONFIG_MFD_IPAQ_MICRO) += ipaq-micro.o 172 + obj-$(CONFIG_MFD_MENF21BMC) += menf21bmc.o 172 173 173 174 intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o 174 175 obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
+132
drivers/mfd/menf21bmc.c
··· 1 + /* 2 + * MEN 14F021P00 Board Management Controller (BMC) MFD Core Driver. 3 + * 4 + * Copyright (C) 2014 MEN Mikro Elektronik Nuernberg GmbH 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms of the GNU General Public License as published by the 8 + * Free Software Foundation; either version 2 of the License, or (at your 9 + * option) any later version. 10 + */ 11 + 12 + #include <linux/kernel.h> 13 + #include <linux/device.h> 14 + #include <linux/module.h> 15 + #include <linux/i2c.h> 16 + #include <linux/mfd/core.h> 17 + 18 + #define BMC_CMD_WDT_EXIT_PROD 0x18 19 + #define BMC_CMD_WDT_PROD_STAT 0x19 20 + #define BMC_CMD_REV_MAJOR 0x80 21 + #define BMC_CMD_REV_MINOR 0x81 22 + #define BMC_CMD_REV_MAIN 0x82 23 + 24 + static struct mfd_cell menf21bmc_cell[] = { 25 + { .name = "menf21bmc_wdt", }, 26 + { .name = "menf21bmc_led", }, 27 + { .name = "menf21bmc_hwmon", } 28 + }; 29 + 30 + static int menf21bmc_wdt_exit_prod_mode(struct i2c_client *client) 31 + { 32 + int val, ret; 33 + 34 + val = i2c_smbus_read_byte_data(client, BMC_CMD_WDT_PROD_STAT); 35 + if (val < 0) 36 + return val; 37 + 38 + /* 39 + * Production mode should be not active after delivery of the Board. 40 + * To be sure we check it, inform the user and exit the mode 41 + * if active. 42 + */ 43 + if (val == 0x00) { 44 + dev_info(&client->dev, 45 + "BMC in production mode. Exit production mode\n"); 46 + 47 + ret = i2c_smbus_write_byte(client, BMC_CMD_WDT_EXIT_PROD); 48 + if (ret < 0) 49 + return ret; 50 + } 51 + 52 + return 0; 53 + } 54 + 55 + static int 56 + menf21bmc_probe(struct i2c_client *client, const struct i2c_device_id *ids) 57 + { 58 + int rev_major, rev_minor, rev_main; 59 + int ret; 60 + 61 + ret = i2c_check_functionality(client->adapter, 62 + I2C_FUNC_SMBUS_BYTE_DATA | 63 + I2C_FUNC_SMBUS_WORD_DATA | 64 + I2C_FUNC_SMBUS_BYTE); 65 + if (!ret) 66 + return -ENODEV; 67 + 68 + rev_major = i2c_smbus_read_word_data(client, BMC_CMD_REV_MAJOR); 69 + if (rev_major < 0) { 70 + dev_err(&client->dev, "failed to get BMC major revision\n"); 71 + return rev_major; 72 + } 73 + 74 + rev_minor = i2c_smbus_read_word_data(client, BMC_CMD_REV_MINOR); 75 + if (rev_minor < 0) { 76 + dev_err(&client->dev, "failed to get BMC minor revision\n"); 77 + return rev_minor; 78 + } 79 + 80 + rev_main = i2c_smbus_read_word_data(client, BMC_CMD_REV_MAIN); 81 + if (rev_main < 0) { 82 + dev_err(&client->dev, "failed to get BMC main revision\n"); 83 + return rev_main; 84 + } 85 + 86 + dev_info(&client->dev, "FW Revision: %02d.%02d.%02d\n", 87 + rev_major, rev_minor, rev_main); 88 + 89 + /* 90 + * We have to exit the Production Mode of the BMC to activate the 91 + * Watchdog functionality and the BIOS life sign monitoring. 92 + */ 93 + ret = menf21bmc_wdt_exit_prod_mode(client); 94 + if (ret < 0) { 95 + dev_err(&client->dev, "failed to leave production mode\n"); 96 + return ret; 97 + } 98 + 99 + ret = mfd_add_devices(&client->dev, 0, menf21bmc_cell, 100 + ARRAY_SIZE(menf21bmc_cell), NULL, 0, NULL); 101 + if (ret < 0) { 102 + dev_err(&client->dev, "failed to add BMC sub-devices\n"); 103 + return ret; 104 + } 105 + 106 + return 0; 107 + } 108 + 109 + static int menf21bmc_remove(struct i2c_client *client) 110 + { 111 + mfd_remove_devices(&client->dev); 112 + return 0; 113 + } 114 + 115 + static const struct i2c_device_id menf21bmc_id_table[] = { 116 + { "menf21bmc" }, 117 + { } 118 + }; 119 + MODULE_DEVICE_TABLE(i2c, menf21bmc_id_table); 120 + 121 + static struct i2c_driver menf21bmc_driver = { 122 + .driver.name = "menf21bmc", 123 + .id_table = menf21bmc_id_table, 124 + .probe = menf21bmc_probe, 125 + .remove = menf21bmc_remove, 126 + }; 127 + 128 + module_i2c_driver(menf21bmc_driver); 129 + 130 + MODULE_DESCRIPTION("MEN 14F021P00 BMC mfd core driver"); 131 + MODULE_AUTHOR("Andreas Werner <andreas.werner@men.de>"); 132 + MODULE_LICENSE("GPL v2");