aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSourav Poddar <sourav.poddar@ti.com>2012-10-01 07:01:22 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-10-01 09:27:48 -0400
commit8284328cd98b9ac9eebf646e6fcb9047bc12bf55 (patch)
tree1c7ab08de0e003d300ab194512cb2847a971b45a
parentc6bed9deb6047179a6c58ace847f8b2129085e37 (diff)
mfd: smsc: Add support for smsc gpio io/keypad driver
smsc ece1099 is a keyboard scan or gpio expansion device. The patch create keypad and gpio expander child for this multi function smsc driver. Cc: Benoit Cousson <b-cousson@ti.com> Cc: Felipe Balbi <balbi@ti.com> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com> Signed-off-by: Sourav Poddar <sourav.poddar@ti.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--Documentation/smsc_ece1099.txt56
-rw-r--r--drivers/mfd/Kconfig12
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/smsc-ece1099.c113
-rw-r--r--include/linux/mfd/smsc.h109
5 files changed, 291 insertions, 0 deletions
diff --git a/Documentation/smsc_ece1099.txt b/Documentation/smsc_ece1099.txt
new file mode 100644
index 000000000000..6b492e82b43d
--- /dev/null
+++ b/Documentation/smsc_ece1099.txt
@@ -0,0 +1,56 @@
1What is smsc-ece1099?
2----------------------
3
4The ECE1099 is a 40-Pin 3.3V Keyboard Scan Expansion
5or GPIO Expansion device. The device supports a keyboard
6scan matrix of 23x8. The device is connected to a Master
7via the SMSC BC-Link interface or via the SMBus.
8Keypad scan Input(KSI) and Keypad Scan Output(KSO) signals
9are multiplexed with GPIOs.
10
11Interrupt generation
12--------------------
13
14Interrupts can be generated by an edge detection on a GPIO
15pin or an edge detection on one of the bus interface pins.
16Interrupts can also be detected on the keyboard scan interface.
17The bus interrupt pin (BC_INT# or SMBUS_INT#) is asserted if
18any bit in one of the Interrupt Status registers is 1 and
19the corresponding Interrupt Mask bit is also 1.
20
21In order for software to determine which device is the source
22of an interrupt, it should first read the Group Interrupt Status Register
23to determine which Status register group is a source for the interrupt.
24Software should read both the Status register and the associated Mask register,
25then AND the two values together. Bits that are 1 in the result of the AND
26are active interrupts. Software clears an interrupt by writing a 1 to the
27corresponding bit in the Status register.
28
29Communication Protocol
30----------------------
31
32- SMbus slave Interface
33 The host processor communicates with the ECE1099 device
34 through a series of read/write registers via the SMBus
35 interface. SMBus is a serial communication protocol between
36 a computer host and its peripheral devices. The SMBus data
37 rate is 10KHz minimum to 400 KHz maximum
38
39- Slave Bus Interface
40 The ECE1099 device SMBus implementation is a subset of the
41 SMBus interface to the host. The device is a slave-only SMBus device.
42 The implementation in the device is a subset of SMBus since it
43 only supports four protocols.
44
45 The Write Byte, Read Byte, Send Byte, and Receive Byte protocols are the
46 only valid SMBus protocols for the device.
47
48- BC-LinkTM Interface
49 The BC-Link is a proprietary bus that allows communication
50 between a Master device and a Companion device. The Master
51 device uses this serial bus to read and write registers
52 located on the Companion device. The bus comprises three signals,
53 BC_CLK, BC_DAT and BC_INT#. The Master device always provides the
54 clock, BC_CLK, and the Companion device is the source for an
55 independent asynchronous interrupt signal, BC_INT#. The ECE1099
56 supports BC-Link speeds up to 24MHz.
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6bfa2a1ec9df..ae511b738441 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -375,6 +375,18 @@ config MFD_T7L66XB
375 help 375 help
376 Support for Toshiba Mobile IO Controller T7L66XB 376 Support for Toshiba Mobile IO Controller T7L66XB
377 377
378config MFD_SMSC
379 bool "Support for the SMSC ECE1099 series chips"
380 depends on I2C=y
381 select MFD_CORE
382 select REGMAP_I2C
383 help
384 If you say yes here you get support for the
385 ece1099 chips from SMSC.
386
387 To compile this driver as a module, choose M here: the
388 module will be called smsc.
389
378config MFD_TC6387XB 390config MFD_TC6387XB
379 bool "Support Toshiba TC6387XB" 391 bool "Support Toshiba TC6387XB"
380 depends on ARM && HAVE_CLK 392 depends on ARM && HAVE_CLK
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 33c0e49f7e60..d8ccb630ddb0 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -76,6 +76,7 @@ obj-$(CONFIG_EZX_PCAP) += ezx-pcap.o
76obj-$(CONFIG_MCP) += mcp-core.o 76obj-$(CONFIG_MCP) += mcp-core.o
77obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o 77obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o
78obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o 78obj-$(CONFIG_MCP_UCB1200) += ucb1x00-core.o
79obj-$(CONFIG_MFD_SMSC) += smsc-ece1099.o
79obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o 80obj-$(CONFIG_MCP_UCB1200_TS) += ucb1x00-ts.o
80 81
81ifeq ($(CONFIG_SA1100_ASSABET),y) 82ifeq ($(CONFIG_SA1100_ASSABET),y)
diff --git a/drivers/mfd/smsc-ece1099.c b/drivers/mfd/smsc-ece1099.c
new file mode 100644
index 000000000000..24ae3d8421c5
--- /dev/null
+++ b/drivers/mfd/smsc-ece1099.c
@@ -0,0 +1,113 @@
1/*
2 * TI SMSC MFD Driver
3 *
4 * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
5 *
6 * Author: Sourav Poddar <sourav.poddar@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; GPL v2.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/init.h>
17#include <linux/slab.h>
18#include <linux/i2c.h>
19#include <linux/gpio.h>
20#include <linux/workqueue.h>
21#include <linux/irq.h>
22#include <linux/regmap.h>
23#include <linux/err.h>
24#include <linux/mfd/core.h>
25#include <linux/mfd/smsc.h>
26#include <linux/of_platform.h>
27
28static struct regmap_config smsc_regmap_config = {
29 .reg_bits = 8,
30 .val_bits = 8,
31 .max_register = SMSC_VEN_ID_H,
32 .cache_type = REGCACHE_RBTREE,
33};
34
35static int smsc_i2c_probe(struct i2c_client *i2c,
36 const struct i2c_device_id *id)
37{
38 struct smsc *smsc;
39 int devid, rev, venid_l, venid_h;
40 int ret = 0;
41
42 smsc = devm_kzalloc(&i2c->dev, sizeof(struct smsc),
43 GFP_KERNEL);
44 if (!smsc) {
45 dev_err(&i2c->dev, "smsc mfd driver memory allocation failed\n");
46 return -ENOMEM;
47 }
48
49 smsc->regmap = devm_regmap_init_i2c(i2c, &smsc_regmap_config);
50 if (IS_ERR(smsc->regmap)) {
51 ret = PTR_ERR(smsc->regmap);
52 goto err;
53 }
54
55 i2c_set_clientdata(i2c, smsc);
56 smsc->dev = &i2c->dev;
57
58#ifdef CONFIG_OF
59 of_property_read_u32(i2c->dev.of_node, "clock", &smsc->clk);
60#endif
61
62 regmap_read(smsc->regmap, SMSC_DEV_ID, &devid);
63 regmap_read(smsc->regmap, SMSC_DEV_REV, &rev);
64 regmap_read(smsc->regmap, SMSC_VEN_ID_L, &venid_l);
65 regmap_read(smsc->regmap, SMSC_VEN_ID_H, &venid_h);
66
67 dev_info(&i2c->dev, "SMSCxxx devid: %02x rev: %02x venid: %02x\n",
68 devid, rev, (venid_h << 8) | venid_l);
69
70 ret = regmap_write(smsc->regmap, SMSC_CLK_CTRL, smsc->clk);
71 if (ret)
72 goto err;
73
74#ifdef CONFIG_OF
75 if (i2c->dev.of_node)
76 ret = of_platform_populate(i2c->dev.of_node,
77 NULL, NULL, &i2c->dev);
78#endif
79
80err:
81 return ret;
82}
83
84static int smsc_i2c_remove(struct i2c_client *i2c)
85{
86 struct smsc *smsc = i2c_get_clientdata(i2c);
87
88 mfd_remove_devices(smsc->dev);
89
90 return 0;
91}
92
93static const struct i2c_device_id smsc_i2c_id[] = {
94 { "smscece1099", 0},
95 {},
96};
97MODULE_DEVICE_TABLE(i2c, smsc_i2c_id);
98
99static struct i2c_driver smsc_i2c_driver = {
100 .driver = {
101 .name = "smsc",
102 .owner = THIS_MODULE,
103 },
104 .probe = smsc_i2c_probe,
105 .remove = smsc_i2c_remove,
106 .id_table = smsc_i2c_id,
107};
108
109module_i2c_driver(smsc_i2c_driver);
110
111MODULE_AUTHOR("Sourav Poddar <sourav.poddar@ti.com>");
112MODULE_DESCRIPTION("SMSC chip multi-function driver");
113MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/smsc.h b/include/linux/mfd/smsc.h
new file mode 100644
index 000000000000..9747b29f356f
--- /dev/null
+++ b/include/linux/mfd/smsc.h
@@ -0,0 +1,109 @@
1/*
2 * SMSC ECE1099
3 *
4 * Copyright 2012 Texas Instruments Inc.
5 *
6 * Author: Sourav Poddar <sourav.poddar@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 */
14
15#ifndef __LINUX_MFD_SMSC_H
16#define __LINUX_MFD_SMSC_H
17
18#include <linux/regmap.h>
19
20#define SMSC_ID_ECE1099 1
21#define SMSC_NUM_CLIENTS 2
22
23#define SMSC_BASE_ADDR 0x38
24#define OMAP_GPIO_SMSC_IRQ 151
25
26#define SMSC_MAXGPIO 32
27#define SMSC_BANK(offs) ((offs) >> 3)
28#define SMSC_BIT(offs) (1u << ((offs) & 0x7))
29
30struct smsc {
31 struct device *dev;
32 struct i2c_client *i2c_clients[SMSC_NUM_CLIENTS];
33 struct regmap *regmap;
34 int clk;
35 /* Stored chip id */
36 int id;
37};
38
39struct smsc_gpio;
40struct smsc_keypad;
41
42static inline int smsc_read(struct device *child, unsigned int reg,
43 unsigned int *dest)
44{
45 struct smsc *smsc = dev_get_drvdata(child->parent);
46
47 return regmap_read(smsc->regmap, reg, dest);
48}
49
50static inline int smsc_write(struct device *child, unsigned int reg,
51 unsigned int value)
52{
53 struct smsc *smsc = dev_get_drvdata(child->parent);
54
55 return regmap_write(smsc->regmap, reg, value);
56}
57
58/* Registers for SMSC */
59#define SMSC_RESET 0xF5
60#define SMSC_GRP_INT 0xF9
61#define SMSC_CLK_CTRL 0xFA
62#define SMSC_WKUP_CTRL 0xFB
63#define SMSC_DEV_ID 0xFC
64#define SMSC_DEV_REV 0xFD
65#define SMSC_VEN_ID_L 0xFE
66#define SMSC_VEN_ID_H 0xFF
67
68/* CLK VALUE */
69#define SMSC_CLK_VALUE 0x13
70
71/* Registers for function GPIO INPUT */
72#define SMSC_GPIO_DATA_IN_START 0x00
73
74/* Registers for function GPIO OUPUT */
75#define SMSC_GPIO_DATA_OUT_START 0x05
76
77/* Definitions for SMSC GPIO CONFIGURATION REGISTER*/
78#define SMSC_GPIO_INPUT_LOW 0x01
79#define SMSC_GPIO_INPUT_RISING 0x09
80#define SMSC_GPIO_INPUT_FALLING 0x11
81#define SMSC_GPIO_INPUT_BOTH_EDGE 0x19
82#define SMSC_GPIO_OUTPUT_PP 0x21
83#define SMSC_GPIO_OUTPUT_OP 0x31
84
85#define GRP_INT_STAT 0xf9
86#define SMSC_GPI_INT 0x0f
87#define SMSC_CFG_START 0x0A
88
89/* Registers for SMSC GPIO INTERRUPT STATUS REGISTER*/
90#define SMSC_GPIO_INT_STAT_START 0x32
91
92/* Registers for SMSC GPIO INTERRUPT MASK REGISTER*/
93#define SMSC_GPIO_INT_MASK_START 0x37
94
95/* Registers for SMSC function KEYPAD*/
96#define SMSC_KP_OUT 0x40
97#define SMSC_KP_IN 0x41
98#define SMSC_KP_INT_STAT 0x42
99#define SMSC_KP_INT_MASK 0x43
100
101/* Definitions for keypad */
102#define SMSC_KP_KSO 0x70
103#define SMSC_KP_KSI 0x51
104#define SMSC_KSO_ALL_LOW 0x20
105#define SMSC_KP_SET_LOW_PWR 0x0B
106#define SMSC_KP_SET_HIGH 0xFF
107#define SMSC_KSO_EVAL 0x00
108
109#endif /* __LINUX_MFD_SMSC_H */