aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorAndreas Werner <andreas.werner@men.de>2014-08-27 13:51:45 -0400
committerLee Jones <lee.jones@linaro.org>2014-09-24 08:30:16 -0400
commitdfbdcd7cefcaba306fc1ad36aa8bc1352149e730 (patch)
tree67830569dcf9a0fcd79369f1e940fdde644f119e /drivers/mfd
parent52addcf9d6669fa439387610bc65c92fa0980cef (diff)
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>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/Kconfig15
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/menf21bmc.c132
3 files changed, 148 insertions, 0 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index de5abf244746..cf66ef1ffaf3 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -454,6 +454,21 @@ config MFD_MAX8998
454 additional drivers must be enabled in order to use the functionality 454 additional drivers must be enabled in order to use the functionality
455 of the device. 455 of the device.
456 456
457config 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
457config EZX_PCAP 472config EZX_PCAP
458 bool "Motorola EZXPCAP Support" 473 bool "Motorola EZXPCAP Support"
459 depends on SPI_MASTER 474 depends on SPI_MASTER
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index f00148782d9b..d58068aa8aa9 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -169,6 +169,7 @@ obj-$(CONFIG_MFD_AS3711) += as3711.o
169obj-$(CONFIG_MFD_AS3722) += as3722.o 169obj-$(CONFIG_MFD_AS3722) += as3722.o
170obj-$(CONFIG_MFD_STW481X) += stw481x.o 170obj-$(CONFIG_MFD_STW481X) += stw481x.o
171obj-$(CONFIG_MFD_IPAQ_MICRO) += ipaq-micro.o 171obj-$(CONFIG_MFD_IPAQ_MICRO) += ipaq-micro.o
172obj-$(CONFIG_MFD_MENF21BMC) += menf21bmc.o
172 173
173intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o 174intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o
174obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o 175obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o
diff --git a/drivers/mfd/menf21bmc.c b/drivers/mfd/menf21bmc.c
new file mode 100644
index 000000000000..1c274345820c
--- /dev/null
+++ b/drivers/mfd/menf21bmc.c
@@ -0,0 +1,132 @@
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
24static struct mfd_cell menf21bmc_cell[] = {
25 { .name = "menf21bmc_wdt", },
26 { .name = "menf21bmc_led", },
27 { .name = "menf21bmc_hwmon", }
28};
29
30static 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
55static int
56menf21bmc_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
109static int menf21bmc_remove(struct i2c_client *client)
110{
111 mfd_remove_devices(&client->dev);
112 return 0;
113}
114
115static const struct i2c_device_id menf21bmc_id_table[] = {
116 { "menf21bmc" },
117 { }
118};
119MODULE_DEVICE_TABLE(i2c, menf21bmc_id_table);
120
121static 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
128module_i2c_driver(menf21bmc_driver);
129
130MODULE_DESCRIPTION("MEN 14F021P00 BMC mfd core driver");
131MODULE_AUTHOR("Andreas Werner <andreas.werner@men.de>");
132MODULE_LICENSE("GPL v2");