Commit 470eca47bded10f2e1a425b44d6f2b1418271a9f
Committed by
Lee Jones
1 parent
0cc59b9d98
mfd: Add LP3943 MFD driver
LP3943 has 16 output pins which can be used as GPIO expander and PWM generator. * Regmap I2C interface for R/W LP3943 registers * Atomic operations for output pin assignment The driver should check whether requested pin is available or not. If the pin is already used, pin request returns as a failure. A driver data, 'pin_used' is checked when gpio_request() and pwm_request() are called. If the pin is available, then pin_used is set. And it is cleared when gpio_free() and pwm_free(). * Device tree support Compatible strings for GPIO and PWM driver. LP3943 platform data is PWM related, so parsing the device tree is implemented in the PWM driver. Signed-off-by: Milo Kim <milo.kim@ti.com> Signed-off-by: Lee Jones <lee.jones@linaro.org>
Showing 4 changed files with 293 additions and 0 deletions Side-by-side Diff
drivers/mfd/Kconfig
... | ... | @@ -738,6 +738,17 @@ |
738 | 738 | boards. MSP430 firmware manages resets and power sequencing, |
739 | 739 | inputs from buttons and the IR remote, LEDs, an RTC, and more. |
740 | 740 | |
741 | +config MFD_LP3943 | |
742 | + tristate "TI/National Semiconductor LP3943 MFD Driver" | |
743 | + depends on I2C | |
744 | + select MFD_CORE | |
745 | + select REGMAP_I2C | |
746 | + help | |
747 | + Support for the TI/National Semiconductor LP3943. | |
748 | + This driver consists of GPIO and PWM drivers. | |
749 | + With these functionalities, it can be used for LED string control or | |
750 | + general usage such like a GPIO controller and a PWM controller. | |
751 | + | |
741 | 752 | config MFD_LP8788 |
742 | 753 | bool "TI LP8788 Power Management Unit Driver" |
743 | 754 | depends on I2C=y |
drivers/mfd/Makefile
drivers/mfd/lp3943.c
1 | +/* | |
2 | + * TI/National Semiconductor LP3943 MFD Core Driver | |
3 | + * | |
4 | + * Copyright 2013 Texas Instruments | |
5 | + * | |
6 | + * Author: Milo Kim <milo.kim@ti.com> | |
7 | + * | |
8 | + * This program is free software; you can redistribute it and/or modify | |
9 | + * it under the terms of the GNU General Public License version 2 as | |
10 | + * published by the Free Software Foundation. | |
11 | + * | |
12 | + * Driver structure: | |
13 | + * LP3943 is an integrated device capable of driving 16 output channels. | |
14 | + * It can be used for a GPIO expander and PWM generators. | |
15 | + * | |
16 | + * LED control General usage for a device | |
17 | + * ___________ ____________________________ | |
18 | + * | |
19 | + * LP3943 MFD ---- GPIO expander leds-gpio eg) HW enable pin | |
20 | + * | | |
21 | + * --- PWM generator leds-pwm eg) PWM input | |
22 | + * | |
23 | + * Internal two PWM channels are used for LED dimming effect. | |
24 | + * And each output pin can be used as a GPIO as well. | |
25 | + * The LED functionality can work with GPIOs or PWMs. | |
26 | + * LEDs can be controlled with legacy leds-gpio(static brightness) or | |
27 | + * leds-pwm drivers(dynamic brightness control). | |
28 | + * Alternatively, it can be used for generic GPIO and PWM controller. | |
29 | + * For example, a GPIO is HW enable pin of a device. | |
30 | + * A PWM is input pin of a backlight device. | |
31 | + */ | |
32 | + | |
33 | +#include <linux/err.h> | |
34 | +#include <linux/gpio.h> | |
35 | +#include <linux/i2c.h> | |
36 | +#include <linux/mfd/core.h> | |
37 | +#include <linux/mfd/lp3943.h> | |
38 | +#include <linux/module.h> | |
39 | +#include <linux/of.h> | |
40 | +#include <linux/slab.h> | |
41 | + | |
42 | +#define LP3943_MAX_REGISTERS 0x09 | |
43 | + | |
44 | +/* Register configuration for pin MUX */ | |
45 | +static const struct lp3943_reg_cfg lp3943_mux_cfg[] = { | |
46 | + /* address, mask, shift */ | |
47 | + { LP3943_REG_MUX0, 0x03, 0 }, | |
48 | + { LP3943_REG_MUX0, 0x0C, 2 }, | |
49 | + { LP3943_REG_MUX0, 0x30, 4 }, | |
50 | + { LP3943_REG_MUX0, 0xC0, 6 }, | |
51 | + { LP3943_REG_MUX1, 0x03, 0 }, | |
52 | + { LP3943_REG_MUX1, 0x0C, 2 }, | |
53 | + { LP3943_REG_MUX1, 0x30, 4 }, | |
54 | + { LP3943_REG_MUX1, 0xC0, 6 }, | |
55 | + { LP3943_REG_MUX2, 0x03, 0 }, | |
56 | + { LP3943_REG_MUX2, 0x0C, 2 }, | |
57 | + { LP3943_REG_MUX2, 0x30, 4 }, | |
58 | + { LP3943_REG_MUX2, 0xC0, 6 }, | |
59 | + { LP3943_REG_MUX3, 0x03, 0 }, | |
60 | + { LP3943_REG_MUX3, 0x0C, 2 }, | |
61 | + { LP3943_REG_MUX3, 0x30, 4 }, | |
62 | + { LP3943_REG_MUX3, 0xC0, 6 }, | |
63 | +}; | |
64 | + | |
65 | +static struct mfd_cell lp3943_devs[] = { | |
66 | + { | |
67 | + .name = "lp3943-pwm", | |
68 | + .of_compatible = "ti,lp3943-pwm", | |
69 | + }, | |
70 | + { | |
71 | + .name = "lp3943-gpio", | |
72 | + .of_compatible = "ti,lp3943-gpio", | |
73 | + }, | |
74 | +}; | |
75 | + | |
76 | +int lp3943_read_byte(struct lp3943 *lp3943, u8 reg, u8 *read) | |
77 | +{ | |
78 | + int ret; | |
79 | + unsigned int val; | |
80 | + | |
81 | + ret = regmap_read(lp3943->regmap, reg, &val); | |
82 | + if (ret < 0) | |
83 | + return ret; | |
84 | + | |
85 | + *read = (u8)val; | |
86 | + return 0; | |
87 | +} | |
88 | +EXPORT_SYMBOL_GPL(lp3943_read_byte); | |
89 | + | |
90 | +int lp3943_write_byte(struct lp3943 *lp3943, u8 reg, u8 data) | |
91 | +{ | |
92 | + return regmap_write(lp3943->regmap, reg, data); | |
93 | +} | |
94 | +EXPORT_SYMBOL_GPL(lp3943_write_byte); | |
95 | + | |
96 | +int lp3943_update_bits(struct lp3943 *lp3943, u8 reg, u8 mask, u8 data) | |
97 | +{ | |
98 | + return regmap_update_bits(lp3943->regmap, reg, mask, data); | |
99 | +} | |
100 | +EXPORT_SYMBOL_GPL(lp3943_update_bits); | |
101 | + | |
102 | +static const struct regmap_config lp3943_regmap_config = { | |
103 | + .reg_bits = 8, | |
104 | + .val_bits = 8, | |
105 | + .max_register = LP3943_MAX_REGISTERS, | |
106 | +}; | |
107 | + | |
108 | +static int lp3943_probe(struct i2c_client *cl, const struct i2c_device_id *id) | |
109 | +{ | |
110 | + struct lp3943 *lp3943; | |
111 | + struct device *dev = &cl->dev; | |
112 | + | |
113 | + lp3943 = devm_kzalloc(dev, sizeof(*lp3943), GFP_KERNEL); | |
114 | + if (!lp3943) | |
115 | + return -ENOMEM; | |
116 | + | |
117 | + lp3943->regmap = devm_regmap_init_i2c(cl, &lp3943_regmap_config); | |
118 | + if (IS_ERR(lp3943->regmap)) | |
119 | + return PTR_ERR(lp3943->regmap); | |
120 | + | |
121 | + lp3943->pdata = dev_get_platdata(dev); | |
122 | + lp3943->dev = dev; | |
123 | + lp3943->mux_cfg = lp3943_mux_cfg; | |
124 | + i2c_set_clientdata(cl, lp3943); | |
125 | + | |
126 | + return mfd_add_devices(dev, -1, lp3943_devs, ARRAY_SIZE(lp3943_devs), | |
127 | + NULL, 0, NULL); | |
128 | +} | |
129 | + | |
130 | +static int lp3943_remove(struct i2c_client *cl) | |
131 | +{ | |
132 | + struct lp3943 *lp3943 = i2c_get_clientdata(cl); | |
133 | + | |
134 | + mfd_remove_devices(lp3943->dev); | |
135 | + return 0; | |
136 | +} | |
137 | + | |
138 | +static const struct i2c_device_id lp3943_ids[] = { | |
139 | + { "lp3943", 0 }, | |
140 | + { } | |
141 | +}; | |
142 | +MODULE_DEVICE_TABLE(i2c, lp3943_ids); | |
143 | + | |
144 | +#ifdef CONFIG_OF | |
145 | +static const struct of_device_id lp3943_of_match[] = { | |
146 | + { .compatible = "ti,lp3943", }, | |
147 | + { } | |
148 | +}; | |
149 | +MODULE_DEVICE_TABLE(of, lp3943_of_match); | |
150 | +#endif | |
151 | + | |
152 | +static struct i2c_driver lp3943_driver = { | |
153 | + .probe = lp3943_probe, | |
154 | + .remove = lp3943_remove, | |
155 | + .driver = { | |
156 | + .name = "lp3943", | |
157 | + .owner = THIS_MODULE, | |
158 | + .of_match_table = of_match_ptr(lp3943_of_match), | |
159 | + }, | |
160 | + .id_table = lp3943_ids, | |
161 | +}; | |
162 | + | |
163 | +module_i2c_driver(lp3943_driver); | |
164 | + | |
165 | +MODULE_DESCRIPTION("LP3943 MFD Core Driver"); | |
166 | +MODULE_AUTHOR("Milo Kim"); | |
167 | +MODULE_LICENSE("GPL"); |
include/linux/mfd/lp3943.h
1 | +/* | |
2 | + * TI/National Semiconductor LP3943 Device | |
3 | + * | |
4 | + * Copyright 2013 Texas Instruments | |
5 | + * | |
6 | + * Author: Milo Kim <milo.kim@ti.com> | |
7 | + * | |
8 | + * This program is free software; you can redistribute it and/or modify | |
9 | + * it under the terms of the GNU General Public License version 2 as | |
10 | + * published by the Free Software Foundation. | |
11 | + * | |
12 | + */ | |
13 | + | |
14 | +#ifndef __MFD_LP3943_H__ | |
15 | +#define __MFD_LP3943_H__ | |
16 | + | |
17 | +#include <linux/gpio.h> | |
18 | +#include <linux/pwm.h> | |
19 | +#include <linux/regmap.h> | |
20 | + | |
21 | +/* Registers */ | |
22 | +#define LP3943_REG_GPIO_A 0x00 | |
23 | +#define LP3943_REG_GPIO_B 0x01 | |
24 | +#define LP3943_REG_PRESCALE0 0x02 | |
25 | +#define LP3943_REG_PWM0 0x03 | |
26 | +#define LP3943_REG_PRESCALE1 0x04 | |
27 | +#define LP3943_REG_PWM1 0x05 | |
28 | +#define LP3943_REG_MUX0 0x06 | |
29 | +#define LP3943_REG_MUX1 0x07 | |
30 | +#define LP3943_REG_MUX2 0x08 | |
31 | +#define LP3943_REG_MUX3 0x09 | |
32 | + | |
33 | +/* Bit description for LP3943_REG_MUX0 ~ 3 */ | |
34 | +#define LP3943_GPIO_IN 0x00 | |
35 | +#define LP3943_GPIO_OUT_HIGH 0x00 | |
36 | +#define LP3943_GPIO_OUT_LOW 0x01 | |
37 | +#define LP3943_DIM_PWM0 0x02 | |
38 | +#define LP3943_DIM_PWM1 0x03 | |
39 | + | |
40 | +#define LP3943_NUM_PWMS 2 | |
41 | + | |
42 | +enum lp3943_pwm_output { | |
43 | + LP3943_PWM_OUT0, | |
44 | + LP3943_PWM_OUT1, | |
45 | + LP3943_PWM_OUT2, | |
46 | + LP3943_PWM_OUT3, | |
47 | + LP3943_PWM_OUT4, | |
48 | + LP3943_PWM_OUT5, | |
49 | + LP3943_PWM_OUT6, | |
50 | + LP3943_PWM_OUT7, | |
51 | + LP3943_PWM_OUT8, | |
52 | + LP3943_PWM_OUT9, | |
53 | + LP3943_PWM_OUT10, | |
54 | + LP3943_PWM_OUT11, | |
55 | + LP3943_PWM_OUT12, | |
56 | + LP3943_PWM_OUT13, | |
57 | + LP3943_PWM_OUT14, | |
58 | + LP3943_PWM_OUT15, | |
59 | +}; | |
60 | + | |
61 | +/* | |
62 | + * struct lp3943_pwm_map | |
63 | + * @output: Output pins which are mapped to each PWM channel | |
64 | + * @num_outputs: Number of outputs | |
65 | + */ | |
66 | +struct lp3943_pwm_map { | |
67 | + enum lp3943_pwm_output *output; | |
68 | + int num_outputs; | |
69 | +}; | |
70 | + | |
71 | +/* | |
72 | + * struct lp3943_platform_data | |
73 | + * @pwms: Output channel definitions for PWM channel 0 and 1 | |
74 | + */ | |
75 | +struct lp3943_platform_data { | |
76 | + struct lp3943_pwm_map *pwms[LP3943_NUM_PWMS]; | |
77 | +}; | |
78 | + | |
79 | +/* | |
80 | + * struct lp3943_reg_cfg | |
81 | + * @reg: Register address | |
82 | + * @mask: Register bit mask to be updated | |
83 | + * @shift: Register bit shift | |
84 | + */ | |
85 | +struct lp3943_reg_cfg { | |
86 | + u8 reg; | |
87 | + u8 mask; | |
88 | + u8 shift; | |
89 | +}; | |
90 | + | |
91 | +/* | |
92 | + * struct lp3943 | |
93 | + * @dev: Parent device pointer | |
94 | + * @regmap: Used for I2C communication on accessing registers | |
95 | + * @pdata: LP3943 platform specific data | |
96 | + * @mux_cfg: Register configuration for pin MUX | |
97 | + * @pin_used: Bit mask for output pin used. | |
98 | + * This bitmask is used for pin assignment management. | |
99 | + * 1 = pin used, 0 = available. | |
100 | + * Only LSB 16 bits are used, but it is unsigned long type | |
101 | + * for atomic bitwise operations. | |
102 | + */ | |
103 | +struct lp3943 { | |
104 | + struct device *dev; | |
105 | + struct regmap *regmap; | |
106 | + struct lp3943_platform_data *pdata; | |
107 | + const struct lp3943_reg_cfg *mux_cfg; | |
108 | + unsigned long pin_used; | |
109 | +}; | |
110 | + | |
111 | +int lp3943_read_byte(struct lp3943 *lp3943, u8 reg, u8 *read); | |
112 | +int lp3943_write_byte(struct lp3943 *lp3943, u8 reg, u8 data); | |
113 | +int lp3943_update_bits(struct lp3943 *lp3943, u8 reg, u8 mask, u8 data); | |
114 | +#endif |