1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2a15123c7SMark Brown /*
3a15123c7SMark Brown * arizona-spi.c -- Arizona SPI bus interface
4a15123c7SMark Brown *
5a15123c7SMark Brown * Copyright 2012 Wolfson Microelectronics plc
6a15123c7SMark Brown *
7a15123c7SMark Brown * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
8a15123c7SMark Brown */
9a15123c7SMark Brown
10e9338367SHans de Goede #include <linux/acpi.h>
11a15123c7SMark Brown #include <linux/err.h>
12e9338367SHans de Goede #include <linux/gpio/consumer.h>
13e9338367SHans de Goede #include <linux/gpio/machine.h>
14a15123c7SMark Brown #include <linux/module.h>
15a15123c7SMark Brown #include <linux/pm_runtime.h>
16a15123c7SMark Brown #include <linux/regmap.h>
17a15123c7SMark Brown #include <linux/regulator/consumer.h>
18a15123c7SMark Brown #include <linux/slab.h>
19a15123c7SMark Brown #include <linux/spi/spi.h>
203d6d1d1cSSachin Kamat #include <linux/of.h>
21e9338367SHans de Goede #include <uapi/linux/input-event-codes.h>
22a15123c7SMark Brown
23a15123c7SMark Brown #include <linux/mfd/arizona/core.h>
24a15123c7SMark Brown
25a15123c7SMark Brown #include "arizona.h"
26a15123c7SMark Brown
27e9338367SHans de Goede #ifdef CONFIG_ACPI
28c4d09226SWei Yongjun static const struct acpi_gpio_params reset_gpios = { 1, 0, false };
29c4d09226SWei Yongjun static const struct acpi_gpio_params ldoena_gpios = { 2, 0, false };
30e9338367SHans de Goede
31e9338367SHans de Goede static const struct acpi_gpio_mapping arizona_acpi_gpios[] = {
32e9338367SHans de Goede { "reset-gpios", &reset_gpios, 1, },
33e9338367SHans de Goede { "wlf,ldoena-gpios", &ldoena_gpios, 1 },
34e9338367SHans de Goede { }
35e9338367SHans de Goede };
36e9338367SHans de Goede
37e9338367SHans de Goede /*
38e9338367SHans de Goede * The ACPI resources for the device only describe external GPIO-s. They do
39e9338367SHans de Goede * not provide mappings for the GPIO-s coming from the Arizona codec itself.
40e9338367SHans de Goede */
41e9338367SHans de Goede static const struct gpiod_lookup arizona_soc_gpios[] = {
42e9338367SHans de Goede { "arizona", 2, "wlf,spkvdd-ena", 0, GPIO_ACTIVE_HIGH },
43e9338367SHans de Goede { "arizona", 4, "wlf,micd-pol", 0, GPIO_ACTIVE_LOW },
44e9338367SHans de Goede };
45e9338367SHans de Goede
arizona_spi_acpi_remove_lookup(void * lookup)46e9338367SHans de Goede static void arizona_spi_acpi_remove_lookup(void *lookup)
47e9338367SHans de Goede {
48e9338367SHans de Goede gpiod_remove_lookup_table(lookup);
49e9338367SHans de Goede }
50e9338367SHans de Goede
513cf2b434SHans de Goede /* For ACPI tables from boards which ship with Windows as factory OS */
arizona_spi_acpi_windows_probe(struct arizona * arizona)523cf2b434SHans de Goede static int arizona_spi_acpi_windows_probe(struct arizona *arizona)
53e9338367SHans de Goede {
54e9338367SHans de Goede struct gpiod_lookup_table *lookup;
55e9338367SHans de Goede acpi_status status;
56e9338367SHans de Goede int ret;
57e9338367SHans de Goede
58e9338367SHans de Goede /* Add mappings for the 2 ACPI declared GPIOs used for reset and ldo-ena */
59e9338367SHans de Goede devm_acpi_dev_add_driver_gpios(arizona->dev, arizona_acpi_gpios);
60e9338367SHans de Goede
61e9338367SHans de Goede /* Add lookups for the SoCs own GPIOs used for micdet-polarity and spkVDD-enable */
62e9338367SHans de Goede lookup = devm_kzalloc(arizona->dev,
63e9338367SHans de Goede struct_size(lookup, table, ARRAY_SIZE(arizona_soc_gpios) + 1),
64e9338367SHans de Goede GFP_KERNEL);
65e9338367SHans de Goede if (!lookup)
66e9338367SHans de Goede return -ENOMEM;
67e9338367SHans de Goede
68e9338367SHans de Goede lookup->dev_id = dev_name(arizona->dev);
69e9338367SHans de Goede memcpy(lookup->table, arizona_soc_gpios, sizeof(arizona_soc_gpios));
70e9338367SHans de Goede
71e9338367SHans de Goede gpiod_add_lookup_table(lookup);
72e9338367SHans de Goede ret = devm_add_action_or_reset(arizona->dev, arizona_spi_acpi_remove_lookup, lookup);
73e9338367SHans de Goede if (ret)
74e9338367SHans de Goede return ret;
75e9338367SHans de Goede
76e9338367SHans de Goede /* Enable 32KHz clock from SoC to codec for jack-detect */
77e9338367SHans de Goede status = acpi_evaluate_object(ACPI_HANDLE(arizona->dev), "CLKE", NULL, NULL);
78e9338367SHans de Goede if (ACPI_FAILURE(status))
79e9338367SHans de Goede dev_warn(arizona->dev, "Failed to enable 32KHz clk ACPI error %d\n", status);
80e9338367SHans de Goede
813cf2b434SHans de Goede return 0;
823cf2b434SHans de Goede }
833cf2b434SHans de Goede
849ed55e9aSHans de Goede /* For ACPI tables from boards which ship with Android as factory OS */
arizona_spi_acpi_android_probe(struct arizona * arizona)859ed55e9aSHans de Goede static int arizona_spi_acpi_android_probe(struct arizona *arizona)
869ed55e9aSHans de Goede {
879ed55e9aSHans de Goede int ret;
889ed55e9aSHans de Goede
899ed55e9aSHans de Goede /*
909ed55e9aSHans de Goede * Get the reset GPIO, treating -ENOENT as -EPROBE_DEFER to wait for
919ed55e9aSHans de Goede * the x86-android-tablets module to register the board specific GPIO
929ed55e9aSHans de Goede * lookup table.
939ed55e9aSHans de Goede */
949ed55e9aSHans de Goede arizona->pdata.reset = devm_gpiod_get(arizona->dev, "reset", GPIOD_OUT_LOW);
959ed55e9aSHans de Goede if (IS_ERR(arizona->pdata.reset)) {
969ed55e9aSHans de Goede ret = PTR_ERR(arizona->pdata.reset);
979ed55e9aSHans de Goede if (ret == -ENOENT) {
989ed55e9aSHans de Goede dev_info_once(arizona->dev,
999ed55e9aSHans de Goede "Deferring probe till GPIO lookup is registered\n");
1009ed55e9aSHans de Goede ret = -EPROBE_DEFER;
1019ed55e9aSHans de Goede }
1029ed55e9aSHans de Goede return dev_err_probe(arizona->dev, ret, "getting reset GPIO\n");
1039ed55e9aSHans de Goede }
1049ed55e9aSHans de Goede
1059ed55e9aSHans de Goede return 0;
1069ed55e9aSHans de Goede }
1079ed55e9aSHans de Goede
1083cf2b434SHans de Goede /*
1093cf2b434SHans de Goede * The AOSP 3.5 mm Headset: Accessory Specification gives the following values:
1103cf2b434SHans de Goede * Function A Play/Pause: 0 ohm
1113cf2b434SHans de Goede * Function D Voice assistant: 135 ohm
1123cf2b434SHans de Goede * Function B Volume Up 240 ohm
1133cf2b434SHans de Goede * Function C Volume Down 470 ohm
1143cf2b434SHans de Goede * Minimum Mic DC resistance 1000 ohm
1153cf2b434SHans de Goede * Minimum Ear speaker impedance 16 ohm
1163cf2b434SHans de Goede * Note the first max value below must be less then the min. speaker impedance,
1173cf2b434SHans de Goede * to allow CTIA/OMTP detection to work. The other max values are the closest
1183cf2b434SHans de Goede * value from extcon-arizona.c:arizona_micd_levels halfway 2 button resistances.
1193cf2b434SHans de Goede */
1203cf2b434SHans de Goede static const struct arizona_micd_range arizona_micd_aosp_ranges[] = {
1213cf2b434SHans de Goede { .max = 11, .key = KEY_PLAYPAUSE },
1223cf2b434SHans de Goede { .max = 186, .key = KEY_VOICECOMMAND },
1233cf2b434SHans de Goede { .max = 348, .key = KEY_VOLUMEUP },
1243cf2b434SHans de Goede { .max = 752, .key = KEY_VOLUMEDOWN },
1253cf2b434SHans de Goede };
1263cf2b434SHans de Goede
arizona_spi_acpi_probe(struct arizona * arizona)1273cf2b434SHans de Goede static int arizona_spi_acpi_probe(struct arizona *arizona)
1283cf2b434SHans de Goede {
1299ed55e9aSHans de Goede struct acpi_device *adev = ACPI_COMPANION(arizona->dev);
1303cf2b434SHans de Goede int ret;
1313cf2b434SHans de Goede
1329ed55e9aSHans de Goede if (acpi_dev_hid_uid_match(adev, "10WM5102", NULL))
1339ed55e9aSHans de Goede ret = arizona_spi_acpi_android_probe(arizona);
1349ed55e9aSHans de Goede else
1353cf2b434SHans de Goede ret = arizona_spi_acpi_windows_probe(arizona);
1369ed55e9aSHans de Goede
1373cf2b434SHans de Goede if (ret)
1383cf2b434SHans de Goede return ret;
1393cf2b434SHans de Goede
140e9338367SHans de Goede /*
141e9338367SHans de Goede * Some DSDTs wrongly declare the IRQ trigger-type as IRQF_TRIGGER_FALLING
142e9338367SHans de Goede * The IRQ line will stay low when a new IRQ event happens between reading
143e9338367SHans de Goede * the IRQ status flags and acknowledging them. When the IRQ line stays
144e9338367SHans de Goede * low like this the IRQ will never trigger again when its type is set
145e9338367SHans de Goede * to IRQF_TRIGGER_FALLING. Correct the IRQ trigger-type to fix this.
146e9338367SHans de Goede *
147e9338367SHans de Goede * Note theoretically it is possible that some boards are not capable
148e9338367SHans de Goede * of handling active low level interrupts. In that case setting the
149e9338367SHans de Goede * flag to IRQF_TRIGGER_FALLING would not be a bug (and we would need
150e9338367SHans de Goede * to work around this) but so far all known usages of IRQF_TRIGGER_FALLING
151e9338367SHans de Goede * are a bug in the board's DSDT.
152e9338367SHans de Goede */
153e9338367SHans de Goede arizona->pdata.irq_flags = IRQF_TRIGGER_LOW;
154e9338367SHans de Goede
155e9338367SHans de Goede /* Wait 200 ms after jack insertion */
156e9338367SHans de Goede arizona->pdata.micd_detect_debounce = 200;
157e9338367SHans de Goede
158e9338367SHans de Goede /* Use standard AOSP values for headset-button mappings */
159e9338367SHans de Goede arizona->pdata.micd_ranges = arizona_micd_aosp_ranges;
160e9338367SHans de Goede arizona->pdata.num_micd_ranges = ARRAY_SIZE(arizona_micd_aosp_ranges);
161e9338367SHans de Goede
162*1815d400SHans de Goede /* Use left headphone speaker for HP vs line-out detection */
163*1815d400SHans de Goede arizona->pdata.hpdet_channel = ARIZONA_ACCDET_MODE_HPL;
164*1815d400SHans de Goede
165e9338367SHans de Goede return 0;
166e9338367SHans de Goede }
167e9338367SHans de Goede
168e9338367SHans de Goede static const struct acpi_device_id arizona_acpi_match[] = {
169e9338367SHans de Goede {
170e9338367SHans de Goede .id = "WM510204",
171e9338367SHans de Goede .driver_data = WM5102,
172e9338367SHans de Goede },
173e9338367SHans de Goede {
174e9338367SHans de Goede .id = "WM510205",
175e9338367SHans de Goede .driver_data = WM5102,
176e9338367SHans de Goede },
1779ed55e9aSHans de Goede {
1789ed55e9aSHans de Goede .id = "10WM5102",
1799ed55e9aSHans de Goede .driver_data = WM5102,
1809ed55e9aSHans de Goede },
181e9338367SHans de Goede { }
182e9338367SHans de Goede };
183e9338367SHans de Goede MODULE_DEVICE_TABLE(acpi, arizona_acpi_match);
184e9338367SHans de Goede #else
arizona_spi_acpi_probe(struct arizona * arizona)185e9338367SHans de Goede static int arizona_spi_acpi_probe(struct arizona *arizona)
186e9338367SHans de Goede {
187e9338367SHans de Goede return -ENODEV;
188e9338367SHans de Goede }
189e9338367SHans de Goede #endif
190e9338367SHans de Goede
arizona_spi_probe(struct spi_device * spi)191f791be49SBill Pemberton static int arizona_spi_probe(struct spi_device *spi)
192a15123c7SMark Brown {
193a15123c7SMark Brown const struct spi_device_id *id = spi_get_device_id(spi);
194039da225SHans de Goede const void *match_data;
195a15123c7SMark Brown struct arizona *arizona;
196b61c1ec0SRichard Fitzgerald const struct regmap_config *regmap_config = NULL;
197039da225SHans de Goede unsigned long type = 0;
198942786e6SLee Jones int ret;
199a15123c7SMark Brown
200039da225SHans de Goede match_data = device_get_match_data(&spi->dev);
201039da225SHans de Goede if (match_data)
202039da225SHans de Goede type = (unsigned long)match_data;
203039da225SHans de Goede else if (id)
204d781009cSMark Brown type = id->driver_data;
205d781009cSMark Brown
206d781009cSMark Brown switch (type) {
207a15123c7SMark Brown case WM5102:
208b61c1ec0SRichard Fitzgerald if (IS_ENABLED(CONFIG_MFD_WM5102))
209a15123c7SMark Brown regmap_config = &wm5102_spi_regmap;
210a15123c7SMark Brown break;
211e102befeSMark Brown case WM5110:
212e5d4ef0dSRichard Fitzgerald case WM8280:
213b61c1ec0SRichard Fitzgerald if (IS_ENABLED(CONFIG_MFD_WM5110))
214e102befeSMark Brown regmap_config = &wm5110_spi_regmap;
215e102befeSMark Brown break;
216ea1f3339SRichard Fitzgerald case WM1831:
217ea1f3339SRichard Fitzgerald case CS47L24:
218ea1f3339SRichard Fitzgerald if (IS_ENABLED(CONFIG_MFD_CS47L24))
219ea1f3339SRichard Fitzgerald regmap_config = &cs47l24_spi_regmap;
220ea1f3339SRichard Fitzgerald break;
221a15123c7SMark Brown default:
2222e44e28aSRichard Fitzgerald dev_err(&spi->dev, "Unknown device type %ld\n", type);
223a15123c7SMark Brown return -EINVAL;
224a15123c7SMark Brown }
225a15123c7SMark Brown
226b61c1ec0SRichard Fitzgerald if (!regmap_config) {
227b61c1ec0SRichard Fitzgerald dev_err(&spi->dev,
228b61c1ec0SRichard Fitzgerald "No kernel support for device type %ld\n", type);
229a15123c7SMark Brown return -EINVAL;
230a15123c7SMark Brown }
231a15123c7SMark Brown
232a15123c7SMark Brown arizona = devm_kzalloc(&spi->dev, sizeof(*arizona), GFP_KERNEL);
233a15123c7SMark Brown if (arizona == NULL)
234a15123c7SMark Brown return -ENOMEM;
235a15123c7SMark Brown
236a15123c7SMark Brown arizona->regmap = devm_regmap_init_spi(spi, regmap_config);
237a15123c7SMark Brown if (IS_ERR(arizona->regmap)) {
238a15123c7SMark Brown ret = PTR_ERR(arizona->regmap);
239a15123c7SMark Brown dev_err(&spi->dev, "Failed to allocate register map: %d\n",
240a15123c7SMark Brown ret);
241a15123c7SMark Brown return ret;
242a15123c7SMark Brown }
243a15123c7SMark Brown
2442e44e28aSRichard Fitzgerald arizona->type = type;
245a15123c7SMark Brown arizona->dev = &spi->dev;
246a15123c7SMark Brown arizona->irq = spi->irq;
247a15123c7SMark Brown
248e9338367SHans de Goede if (has_acpi_companion(&spi->dev)) {
249e9338367SHans de Goede ret = arizona_spi_acpi_probe(arizona);
250e9338367SHans de Goede if (ret)
251e9338367SHans de Goede return ret;
252e9338367SHans de Goede }
253e9338367SHans de Goede
254a15123c7SMark Brown return arizona_dev_init(arizona);
255a15123c7SMark Brown }
256a15123c7SMark Brown
arizona_spi_remove(struct spi_device * spi)257a0386bbaSUwe Kleine-König static void arizona_spi_remove(struct spi_device *spi)
258a15123c7SMark Brown {
259e9642d5eSJingoo Han struct arizona *arizona = spi_get_drvdata(spi);
2606f467e5fSWill Sheppard
261a15123c7SMark Brown arizona_dev_exit(arizona);
262a15123c7SMark Brown }
263a15123c7SMark Brown
264a15123c7SMark Brown static const struct spi_device_id arizona_spi_ids[] = {
265a15123c7SMark Brown { "wm5102", WM5102 },
266e102befeSMark Brown { "wm5110", WM5110 },
267e5d4ef0dSRichard Fitzgerald { "wm8280", WM8280 },
268ea1f3339SRichard Fitzgerald { "wm1831", WM1831 },
269ea1f3339SRichard Fitzgerald { "cs47l24", CS47L24 },
270a15123c7SMark Brown { },
271a15123c7SMark Brown };
272a15123c7SMark Brown MODULE_DEVICE_TABLE(spi, arizona_spi_ids);
273a15123c7SMark Brown
2743f65555cSCharles Keepax #ifdef CONFIG_OF
27510377bb2SCharles Keepax static const struct of_device_id arizona_spi_of_match[] = {
2763f65555cSCharles Keepax { .compatible = "wlf,wm5102", .data = (void *)WM5102 },
2773f65555cSCharles Keepax { .compatible = "wlf,wm5110", .data = (void *)WM5110 },
2783f65555cSCharles Keepax { .compatible = "wlf,wm8280", .data = (void *)WM8280 },
2793f65555cSCharles Keepax { .compatible = "wlf,wm1831", .data = (void *)WM1831 },
2803f65555cSCharles Keepax { .compatible = "cirrus,cs47l24", .data = (void *)CS47L24 },
2813f65555cSCharles Keepax {},
2823f65555cSCharles Keepax };
283972c91fdSCharles Keepax MODULE_DEVICE_TABLE(of, arizona_spi_of_match);
2843f65555cSCharles Keepax #endif
2853f65555cSCharles Keepax
286a15123c7SMark Brown static struct spi_driver arizona_spi_driver = {
287a15123c7SMark Brown .driver = {
288a15123c7SMark Brown .name = "arizona",
28950d3ac7dSPaul Cercueil .pm = pm_ptr(&arizona_pm_ops),
2903f65555cSCharles Keepax .of_match_table = of_match_ptr(arizona_spi_of_match),
291e9338367SHans de Goede .acpi_match_table = ACPI_PTR(arizona_acpi_match),
292a15123c7SMark Brown },
293a15123c7SMark Brown .probe = arizona_spi_probe,
29484449216SBill Pemberton .remove = arizona_spi_remove,
295a15123c7SMark Brown .id_table = arizona_spi_ids,
296a15123c7SMark Brown };
297a15123c7SMark Brown
298a15123c7SMark Brown module_spi_driver(arizona_spi_driver);
299a15123c7SMark Brown
30006e577b4SHans de Goede MODULE_SOFTDEP("pre: arizona_ldo1");
301a15123c7SMark Brown MODULE_DESCRIPTION("Arizona SPI bus interface");
302a15123c7SMark Brown MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
303a15123c7SMark Brown MODULE_LICENSE("GPL");
304