1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2019, Linaro Limited
5 #include <linux/gpio.h>
6 #include <linux/interrupt.h>
7 #include <linux/kernel.h>
8 #include <linux/mfd/core.h>
9 #include <linux/mfd/wcd934x/registers.h>
10 #include <linux/mfd/wcd934x/wcd934x.h>
11 #include <linux/module.h>
12 #include <linux/of_gpio.h>
14 #include <linux/of_irq.h>
15 #include <linux/platform_device.h>
16 #include <linux/regmap.h>
17 #include <linux/regulator/consumer.h>
18 #include <linux/slimbus.h>
20 static const struct mfd_cell wcd934x_devices
[] = {
22 .name
= "wcd934x-codec",
24 .name
= "wcd934x-gpio",
25 .of_compatible
= "qcom,wcd9340-gpio",
27 .name
= "wcd934x-soundwire",
28 .of_compatible
= "qcom,soundwire-v1.3.0",
32 static const struct regmap_irq wcd934x_irqs
[] = {
33 [WCD934X_IRQ_SLIMBUS
] = {
38 .types_supported
= IRQ_TYPE_EDGE_BOTH
,
39 .type_reg_mask
= BIT(0),
40 .type_level_low_val
= BIT(0),
41 .type_level_high_val
= BIT(0),
42 .type_falling_val
= 0,
46 [WCD934X_IRQ_SOUNDWIRE
] = {
51 .types_supported
= IRQ_TYPE_EDGE_BOTH
,
52 .type_reg_mask
= BIT(4),
53 .type_level_low_val
= BIT(4),
54 .type_level_high_val
= BIT(4),
55 .type_falling_val
= 0,
61 static const struct regmap_irq_chip wcd934x_regmap_irq_chip
= {
62 .name
= "wcd934x_irq",
63 .status_base
= WCD934X_INTR_PIN1_STATUS0
,
64 .mask_base
= WCD934X_INTR_PIN1_MASK0
,
65 .ack_base
= WCD934X_INTR_PIN1_CLEAR0
,
66 .type_base
= WCD934X_INTR_LEVEL0
,
68 .type_in_mask
= false,
71 .num_irqs
= ARRAY_SIZE(wcd934x_irqs
),
74 static bool wcd934x_is_volatile_register(struct device
*dev
, unsigned int reg
)
77 case WCD934X_INTR_PIN1_STATUS0
...WCD934X_INTR_PIN2_CLEAR3
:
78 case WCD934X_SWR_AHB_BRIDGE_RD_DATA_0
:
79 case WCD934X_SWR_AHB_BRIDGE_RD_DATA_1
:
80 case WCD934X_SWR_AHB_BRIDGE_RD_DATA_2
:
81 case WCD934X_SWR_AHB_BRIDGE_RD_DATA_3
:
82 case WCD934X_SWR_AHB_BRIDGE_ACCESS_STATUS
:
83 case WCD934X_ANA_MBHC_RESULT_3
:
84 case WCD934X_ANA_MBHC_RESULT_2
:
85 case WCD934X_ANA_MBHC_RESULT_1
:
86 case WCD934X_ANA_MBHC_MECH
:
87 case WCD934X_ANA_MBHC_ELECT
:
88 case WCD934X_ANA_MBHC_ZDET
:
89 case WCD934X_ANA_MICB2
:
91 case WCD934X_ANA_BIAS
:
98 static const struct regmap_range_cfg wcd934x_ranges
[] = {
101 .range_max
= WCD934X_MAX_REGISTER
,
102 .selector_reg
= WCD934X_SEL_REGISTER
,
103 .selector_mask
= WCD934X_SEL_MASK
,
104 .selector_shift
= WCD934X_SEL_SHIFT
,
105 .window_start
= WCD934X_WINDOW_START
,
106 .window_len
= WCD934X_WINDOW_LENGTH
,
110 static struct regmap_config wcd934x_regmap_config
= {
113 .cache_type
= REGCACHE_RBTREE
,
114 .max_register
= 0xffff,
115 .can_multi_write
= true,
116 .ranges
= wcd934x_ranges
,
117 .num_ranges
= ARRAY_SIZE(wcd934x_ranges
),
118 .volatile_reg
= wcd934x_is_volatile_register
,
121 static int wcd934x_bring_up(struct wcd934x_ddata
*ddata
)
123 struct regmap
*regmap
= ddata
->regmap
;
124 u16 id_minor
, id_major
;
127 ret
= regmap_bulk_read(regmap
, WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE0
,
128 (u8
*)&id_minor
, sizeof(u16
));
132 ret
= regmap_bulk_read(regmap
, WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE2
,
133 (u8
*)&id_major
, sizeof(u16
));
137 dev_info(ddata
->dev
, "WCD934x chip id major 0x%x, minor 0x%x\n",
140 regmap_write(regmap
, WCD934X_CODEC_RPM_RST_CTL
, 0x01);
141 regmap_write(regmap
, WCD934X_SIDO_NEW_VOUT_A_STARTUP
, 0x19);
142 regmap_write(regmap
, WCD934X_SIDO_NEW_VOUT_D_STARTUP
, 0x15);
143 /* Add 1msec delay for VOUT to settle */
144 usleep_range(1000, 1100);
145 regmap_write(regmap
, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL
, 0x5);
146 regmap_write(regmap
, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL
, 0x7);
147 regmap_write(regmap
, WCD934X_CODEC_RPM_RST_CTL
, 0x3);
148 regmap_write(regmap
, WCD934X_CODEC_RPM_RST_CTL
, 0x7);
149 regmap_write(regmap
, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL
, 0x3);
154 static int wcd934x_slim_status_up(struct slim_device
*sdev
)
156 struct device
*dev
= &sdev
->dev
;
157 struct wcd934x_ddata
*ddata
;
160 ddata
= dev_get_drvdata(dev
);
162 ddata
->regmap
= regmap_init_slimbus(sdev
, &wcd934x_regmap_config
);
163 if (IS_ERR(ddata
->regmap
)) {
164 dev_err(dev
, "Error allocating slim regmap\n");
165 return PTR_ERR(ddata
->regmap
);
168 ret
= wcd934x_bring_up(ddata
);
170 dev_err(dev
, "Failed to bring up WCD934X: err = %d\n", ret
);
174 ret
= devm_regmap_add_irq_chip(dev
, ddata
->regmap
, ddata
->irq
,
175 IRQF_TRIGGER_HIGH
, 0,
176 &wcd934x_regmap_irq_chip
,
179 dev_err(dev
, "Failed to add IRQ chip: err = %d\n", ret
);
183 ret
= mfd_add_devices(dev
, PLATFORM_DEVID_AUTO
, wcd934x_devices
,
184 ARRAY_SIZE(wcd934x_devices
), NULL
, 0, NULL
);
186 dev_err(dev
, "Failed to add child devices: err = %d\n",
194 static int wcd934x_slim_status(struct slim_device
*sdev
,
195 enum slim_device_status status
)
198 case SLIM_DEVICE_STATUS_UP
:
199 return wcd934x_slim_status_up(sdev
);
200 case SLIM_DEVICE_STATUS_DOWN
:
201 mfd_remove_devices(&sdev
->dev
);
210 static int wcd934x_slim_probe(struct slim_device
*sdev
)
212 struct device
*dev
= &sdev
->dev
;
213 struct device_node
*np
= dev
->of_node
;
214 struct wcd934x_ddata
*ddata
;
217 ddata
= devm_kzalloc(dev
, sizeof(*ddata
), GFP_KERNEL
);
221 ddata
->irq
= of_irq_get(np
, 0);
222 if (ddata
->irq
< 0) {
223 if (ddata
->irq
!= -EPROBE_DEFER
)
224 dev_err(ddata
->dev
, "Failed to get IRQ: err = %d\n",
229 reset_gpio
= of_get_named_gpio(np
, "reset-gpios", 0);
230 if (reset_gpio
< 0) {
231 dev_err(dev
, "Failed to get reset gpio: err = %d\n",
236 ddata
->extclk
= devm_clk_get(dev
, "extclk");
237 if (IS_ERR(ddata
->extclk
)) {
238 dev_err(dev
, "Failed to get extclk");
239 return PTR_ERR(ddata
->extclk
);
242 ddata
->supplies
[0].supply
= "vdd-buck";
243 ddata
->supplies
[1].supply
= "vdd-buck-sido";
244 ddata
->supplies
[2].supply
= "vdd-tx";
245 ddata
->supplies
[3].supply
= "vdd-rx";
246 ddata
->supplies
[4].supply
= "vdd-io";
248 ret
= regulator_bulk_get(dev
, WCD934X_MAX_SUPPLY
, ddata
->supplies
);
250 dev_err(dev
, "Failed to get supplies: err = %d\n", ret
);
254 ret
= regulator_bulk_enable(WCD934X_MAX_SUPPLY
, ddata
->supplies
);
256 dev_err(dev
, "Failed to enable supplies: err = %d\n", ret
);
261 * For WCD934X, it takes about 600us for the Vout_A and
262 * Vout_D to be ready after BUCK_SIDO is powered up.
263 * SYS_RST_N shouldn't be pulled high during this time
265 usleep_range(600, 650);
266 gpio_direction_output(reset_gpio
, 0);
268 gpio_set_value(reset_gpio
, 1);
272 dev_set_drvdata(dev
, ddata
);
277 static void wcd934x_slim_remove(struct slim_device
*sdev
)
279 struct wcd934x_ddata
*ddata
= dev_get_drvdata(&sdev
->dev
);
281 regulator_bulk_disable(WCD934X_MAX_SUPPLY
, ddata
->supplies
);
282 mfd_remove_devices(&sdev
->dev
);
286 static const struct slim_device_id wcd934x_slim_id
[] = {
287 { SLIM_MANF_ID_QCOM
, SLIM_PROD_CODE_WCD9340
,
288 SLIM_DEV_IDX_WCD9340
, SLIM_DEV_INSTANCE_ID_WCD9340
},
292 static struct slim_driver wcd934x_slim_driver
= {
294 .name
= "wcd934x-slim",
296 .probe
= wcd934x_slim_probe
,
297 .remove
= wcd934x_slim_remove
,
298 .device_status
= wcd934x_slim_status
,
299 .id_table
= wcd934x_slim_id
,
302 module_slim_driver(wcd934x_slim_driver
);
303 MODULE_DESCRIPTION("WCD934X slim driver");
304 MODULE_LICENSE("GPL v2");
305 MODULE_ALIAS("slim:217:250:*");
306 MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org>");