~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/arm/mach-s3c/mach-crag6410-module.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 //
  3 // Speyside modules for Cragganmore - board data probing
  4 //
  5 // Copyright 2011 Wolfson Microelectronics plc
  6 //      Mark Brown <broonie@opensource.wolfsonmicro.com>
  7 
  8 #include <linux/export.h>
  9 #include <linux/interrupt.h>
 10 #include <linux/i2c.h>
 11 #include <linux/spi/spi.h>
 12 #include <linux/gpio/machine.h>
 13 
 14 #include <linux/mfd/wm831x/irq.h>
 15 #include <linux/mfd/wm831x/gpio.h>
 16 #include <linux/mfd/wm8994/pdata.h>
 17 #include <linux/mfd/arizona/pdata.h>
 18 
 19 #include <linux/regulator/machine.h>
 20 
 21 #include <sound/wm0010.h>
 22 #include <sound/wm2200.h>
 23 #include <sound/wm5100.h>
 24 #include <sound/wm8996.h>
 25 #include <sound/wm8962.h>
 26 #include <sound/wm9081.h>
 27 
 28 #include <linux/platform_data/spi-s3c64xx.h>
 29 
 30 #include "cpu.h"
 31 #include "irqs.h"
 32 
 33 #include "crag6410.h"
 34 
 35 static struct gpiod_lookup_table wm0010_gpiod_table = {
 36         .dev_id = "spi0.0", /* SPI device name */
 37         .table = {
 38                 /* Active high for Glenfarclas Rev 2 */
 39                 GPIO_LOOKUP("GPION", 6,
 40                             "reset", GPIO_ACTIVE_HIGH),
 41                 { },
 42         },
 43 };
 44 
 45 static struct wm0010_pdata wm0010_pdata = {
 46         /* Intentionally left blank */
 47 };
 48 
 49 static struct spi_board_info wm1253_devs[] = {
 50         [0] = {
 51                 .modalias       = "wm0010",
 52                 .max_speed_hz   = 26 * 1000 * 1000,
 53                 .bus_num        = 0,
 54                 .chip_select    = 0,
 55                 .mode           = SPI_MODE_0,
 56                 .irq            = S3C_EINT(4),
 57                 .platform_data = &wm0010_pdata,
 58         },
 59 };
 60 
 61 static struct spi_board_info balblair_devs[] = {
 62         [0] = {
 63                 .modalias       = "wm0010",
 64                 .max_speed_hz   = 26 * 1000 * 1000,
 65                 .bus_num        = 0,
 66                 .chip_select    = 0,
 67                 .mode           = SPI_MODE_0,
 68                 .irq            = S3C_EINT(4),
 69                 .platform_data = &wm0010_pdata,
 70         },
 71 };
 72 
 73 static struct gpiod_lookup_table wm5100_gpiod_table = {
 74         .dev_id = "1-001a", /* Device 001a on I2C bus 1 */
 75         .table = {
 76                 GPIO_LOOKUP("GPION", 7,
 77                             "wlf,ldo1ena", GPIO_ACTIVE_HIGH),
 78                 GPIO_LOOKUP("wm5100", 3,
 79                             "hp-pol", GPIO_ACTIVE_HIGH),
 80                 { },
 81         },
 82 };
 83 
 84 static struct wm5100_pdata wm5100_pdata = {
 85         .irq_flags = IRQF_TRIGGER_HIGH,
 86 
 87         .in_mode = {
 88                 WM5100_IN_DIFF,
 89                 WM5100_IN_DIFF,
 90                 WM5100_IN_DIFF,
 91                 WM5100_IN_SE,
 92         },
 93 
 94         .jack_modes = {
 95                 { WM5100_MICDET_MICBIAS3, 0, 0 },
 96                 { WM5100_MICDET_MICBIAS2, 1, 1 },
 97         },
 98 
 99         .gpio_defaults = {
100                 0,
101                 0,
102                 0,
103                 0,
104                 0x2, /* IRQ: CMOS output */
105                 0x3, /* CLKOUT: CMOS output */
106         },
107 };
108 
109 static struct wm8996_retune_mobile_config wm8996_retune[] = {
110         {
111                 .name = "Sub LPF",
112                 .rate = 48000,
113                 .regs = {
114                         0x6318, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
115                         0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
116                         0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
117                 },
118         },
119         {
120                 .name = "Sub HPF",
121                 .rate = 48000,
122                 .regs = {
123                         0x000A, 0x6300, 0x1000, 0x0000, 0x0004, 0x2000, 0xF000,
124                         0x0000, 0x0004, 0x2000, 0xF000, 0x0000, 0x0004, 0x2000,
125                         0xF000, 0x0000, 0x0004, 0x1000, 0x0800, 0x4000
126                 },
127         },
128 };
129 
130 static struct gpiod_lookup_table wm8996_gpiod_table = {
131         .dev_id = "1-001a", /* Device 001a on I2C bus 1 */
132         .table = {
133                 GPIO_LOOKUP("GPION", 7,
134                             "wlf,ldo1ena", GPIO_ACTIVE_HIGH),
135                 { },
136         },
137 };
138 
139 static struct wm8996_pdata wm8996_pdata __initdata = {
140         .micdet_def = 1,
141         .inl_mode = WM8996_DIFFERRENTIAL_1,
142         .inr_mode = WM8996_DIFFERRENTIAL_1,
143 
144         .irq_flags = IRQF_TRIGGER_RISING,
145 
146         .gpio_default = {
147                 0x8001, /* GPIO1 == ADCLRCLK1 */
148                 0x8001, /* GPIO2 == ADCLRCLK2, input due to CPU */
149                 0x0141, /* GPIO3 == HP_SEL */
150                 0x0002, /* GPIO4 == IRQ */
151                 0x020e, /* GPIO5 == CLKOUT */
152         },
153 
154         .retune_mobile_cfgs = wm8996_retune,
155         .num_retune_mobile_cfgs = ARRAY_SIZE(wm8996_retune),
156 };
157 
158 static struct wm8962_pdata wm8962_pdata __initdata = {
159         .gpio_init = {
160                 0,
161                 WM8962_GPIO_FN_OPCLK,
162                 WM8962_GPIO_FN_DMICCLK,
163                 0,
164                 0x8000 | WM8962_GPIO_FN_DMICDAT,
165                 WM8962_GPIO_FN_IRQ,    /* Open drain mode */
166         },
167         .in4_dc_measure = true,
168 };
169 
170 static struct wm9081_pdata wm9081_pdata __initdata = {
171         .irq_high = false,
172         .irq_cmos = false,
173 };
174 
175 static const struct i2c_board_info wm1254_devs[] = {
176         { I2C_BOARD_INFO("wm8996", 0x1a),
177           .platform_data = &wm8996_pdata,
178           .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
179         },
180         { I2C_BOARD_INFO("wm9081", 0x6c),
181           .platform_data = &wm9081_pdata, },
182 };
183 
184 static const struct i2c_board_info wm1255_devs[] = {
185         { I2C_BOARD_INFO("wm5100", 0x1a),
186           .platform_data = &wm5100_pdata,
187           .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
188         },
189         { I2C_BOARD_INFO("wm9081", 0x6c),
190           .platform_data = &wm9081_pdata, },
191 };
192 
193 static const struct i2c_board_info wm1259_devs[] = {
194         { I2C_BOARD_INFO("wm8962", 0x1a),
195           .platform_data = &wm8962_pdata,
196           .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
197         },
198 };
199 
200 static struct regulator_init_data wm8994_ldo1 = {
201         .supply_regulator = "WALLVDD",
202 };
203 
204 static struct regulator_init_data wm8994_ldo2 = {
205         .supply_regulator = "WALLVDD",
206 };
207 
208 static struct wm8994_pdata wm8994_pdata = {
209         .gpio_base = CODEC_GPIO_BASE,
210         .micb2_delay = 150,
211         .gpio_defaults = {
212                 0x3,          /* IRQ out, active high, CMOS */
213         },
214         .ldo = {
215                  { .init_data = &wm8994_ldo1, },
216                  { .init_data = &wm8994_ldo2, },
217         },
218 };
219 
220 static const struct i2c_board_info wm1277_devs[] = {
221         { I2C_BOARD_INFO("wm8958", 0x1a),  /* WM8958 is the superset */
222           .platform_data = &wm8994_pdata,
223           .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
224           .dev_name = "wm8958",
225         },
226 };
227 
228 static struct gpiod_lookup_table wm8994_gpiod_table = {
229         .dev_id = "i2c-wm8958", /* I2C device name */
230         .table = {
231                 GPIO_LOOKUP("GPION", 6,
232                             "wlf,ldo1ena", GPIO_ACTIVE_HIGH),
233                 GPIO_LOOKUP("GPION", 4,
234                             "wlf,ldo2ena", GPIO_ACTIVE_HIGH),
235                 { },
236         },
237 };
238 
239 static struct arizona_pdata wm5102_reva_pdata = {
240         .gpio_base = CODEC_GPIO_BASE,
241         .irq_flags = IRQF_TRIGGER_HIGH,
242         .micd_pol_gpio = CODEC_GPIO_BASE + 4,
243         .micd_rate = 6,
244         .gpio_defaults = {
245                 [2] = 0x10000, /* AIF3TXLRCLK */
246                 [3] = 0x4,     /* OPCLK */
247         },
248 };
249 
250 static struct spi_board_info wm5102_reva_spi_devs[] = {
251         [0] = {
252                 .modalias       = "wm5102",
253                 .max_speed_hz   = 10 * 1000 * 1000,
254                 .bus_num        = 0,
255                 .chip_select    = 1,
256                 .mode           = SPI_MODE_0,
257                 .irq            = GLENFARCLAS_PMIC_IRQ_BASE +
258                                   WM831X_IRQ_GPIO_2,
259                 .platform_data = &wm5102_reva_pdata,
260         },
261 };
262 
263 static struct gpiod_lookup_table wm5102_reva_gpiod_table = {
264         .dev_id = "spi0.1", /* SPI device name */
265         .table = {
266                 GPIO_LOOKUP("GPION", 7,
267                             "wlf,ldoena", GPIO_ACTIVE_HIGH),
268                 { },
269         },
270 };
271 
272 static struct arizona_pdata wm5102_pdata = {
273         .gpio_base = CODEC_GPIO_BASE,
274         .irq_flags = IRQF_TRIGGER_HIGH,
275         .micd_pol_gpio = CODEC_GPIO_BASE + 2,
276         .gpio_defaults = {
277                 [2] = 0x10000, /* AIF3TXLRCLK */
278                 [3] = 0x4,     /* OPCLK */
279         },
280 };
281 
282 static struct spi_board_info wm5102_spi_devs[] = {
283         [0] = {
284                 .modalias       = "wm5102",
285                 .max_speed_hz   = 10 * 1000 * 1000,
286                 .bus_num        = 0,
287                 .chip_select    = 1,
288                 .mode           = SPI_MODE_0,
289                 .irq            = GLENFARCLAS_PMIC_IRQ_BASE +
290                                   WM831X_IRQ_GPIO_2,
291                 .platform_data = &wm5102_pdata,
292         },
293 };
294 
295 static struct gpiod_lookup_table wm5102_gpiod_table = {
296         .dev_id = "spi0.1", /* SPI device name */
297         .table = {
298                 GPIO_LOOKUP("GPION", 7,
299                             "wlf,ldo1ena", GPIO_ACTIVE_HIGH),
300                 { },
301         },
302 };
303 
304 static struct spi_board_info wm5110_spi_devs[] = {
305         [0] = {
306                 .modalias       = "wm5110",
307                 .max_speed_hz   = 10 * 1000 * 1000,
308                 .bus_num        = 0,
309                 .chip_select    = 1,
310                 .mode           = SPI_MODE_0,
311                 .irq            = GLENFARCLAS_PMIC_IRQ_BASE +
312                                   WM831X_IRQ_GPIO_2,
313                 .platform_data = &wm5102_reva_pdata,
314         },
315 };
316 
317 static const struct i2c_board_info wm6230_i2c_devs[] = {
318         { I2C_BOARD_INFO("wm9081", 0x6c),
319           .platform_data = &wm9081_pdata, },
320 };
321 
322 static struct wm2200_pdata wm2200_pdata = {
323         .gpio_defaults = {
324                 [2] = 0x0005,  /* GPIO3 24.576MHz output clock */
325         },
326 };
327 
328 static struct gpiod_lookup_table wm2200_gpiod_table = {
329         .dev_id = "1-003a", /* Device 003a on I2C bus 1 */
330         .table = {
331                 GPIO_LOOKUP("GPION", 7,
332                             "wlf,ldo1ena", GPIO_ACTIVE_HIGH),
333                 { },
334         },
335 };
336 
337 static const struct i2c_board_info wm2200_i2c[] = {
338         { I2C_BOARD_INFO("wm2200", 0x3a),
339           .platform_data = &wm2200_pdata, },
340 };
341 
342 static const struct {
343         u8 id;
344         u8 rev;
345         const char *name;
346         const struct i2c_board_info *i2c_devs;
347         int num_i2c_devs;
348         const struct spi_board_info *spi_devs;
349         int num_spi_devs;
350 
351         struct gpiod_lookup_table *gpiod_table;
352 } gf_mods[] = {
353         { .id = 0x01, .rev = 0xff, .name = "1250-EV1 Springbank" },
354         { .id = 0x02, .rev = 0xff, .name = "1251-EV1 Jura" },
355         { .id = 0x03, .rev = 0xff, .name = "1252-EV1 Glenlivet" },
356         { .id = 0x06, .rev = 0xff, .name = "WM8997-6721-CS96-EV1 Lapraoig" },
357         { .id = 0x07, .rev = 0xff, .name = "WM5110-6271 Deanston",
358           .spi_devs = wm5110_spi_devs,
359           .num_spi_devs = ARRAY_SIZE(wm5110_spi_devs) },
360         { .id = 0x08, .rev = 0xff, .name = "WM8903-6102 Tamdhu" },
361         { .id = 0x09, .rev = 0xff, .name = "WM1811A-6305 Adelphi" },
362         { .id = 0x0a, .rev = 0xff, .name = "WM8996-6272 Blackadder" },
363         { .id = 0x0b, .rev = 0xff, .name = "WM8994-6235 Benromach" },
364         { .id = 0x11, .rev = 0xff, .name = "6249-EV2 Glenfarclas", },
365         { .id = 0x14, .rev = 0xff, .name = "6271-EV1 Lochnagar" },
366         { .id = 0x15, .rev = 0xff, .name = "6320-EV1 Bells",
367           .i2c_devs = wm6230_i2c_devs,
368           .num_i2c_devs = ARRAY_SIZE(wm6230_i2c_devs) },
369         { .id = 0x21, .rev = 0xff, .name = "1275-EV1 Mortlach" },
370         { .id = 0x25, .rev = 0xff, .name = "1274-EV1 Glencadam" },
371         { .id = 0x31, .rev = 0xff, .name = "1253-EV1 Tomatin",
372           .spi_devs = wm1253_devs, .num_spi_devs = ARRAY_SIZE(wm1253_devs),
373           .gpiod_table = &wm0010_gpiod_table },
374         { .id = 0x32, .rev = 0xff, .name = "XXXX-EV1 Caol Illa" },
375         { .id = 0x33, .rev = 0xff, .name = "XXXX-EV1 Oban" },
376         { .id = 0x34, .rev = 0xff, .name = "WM0010-6320-CS42 Balblair",
377           .spi_devs = balblair_devs,
378           .num_spi_devs = ARRAY_SIZE(balblair_devs) },
379         { .id = 0x39, .rev = 0xff, .name = "1254-EV1 Dallas Dhu",
380           .i2c_devs = wm1254_devs, .num_i2c_devs = ARRAY_SIZE(wm1254_devs),
381           .gpiod_table = &wm8996_gpiod_table },
382         { .id = 0x3a, .rev = 0xff, .name = "1259-EV1 Tobermory",
383           .i2c_devs = wm1259_devs, .num_i2c_devs = ARRAY_SIZE(wm1259_devs) },
384         { .id = 0x3b, .rev = 0xff, .name = "1255-EV1 Kilchoman",
385           .i2c_devs = wm1255_devs, .num_i2c_devs = ARRAY_SIZE(wm1255_devs),
386           .gpiod_table = &wm5100_gpiod_table },
387         { .id = 0x3c, .rev = 0xff, .name = "1273-EV1 Longmorn" },
388         { .id = 0x3d, .rev = 0xff, .name = "1277-EV1 Littlemill",
389           .i2c_devs = wm1277_devs, .num_i2c_devs = ARRAY_SIZE(wm1277_devs),
390           .gpiod_table = &wm8994_gpiod_table },
391         { .id = 0x3e, .rev = 0, .name = "WM5102-6271-EV1-CS127 Amrut",
392           .spi_devs = wm5102_reva_spi_devs,
393           .num_spi_devs = ARRAY_SIZE(wm5102_reva_spi_devs),
394           .gpiod_table = &wm5102_reva_gpiod_table },
395         { .id = 0x3e, .rev = -1, .name = "WM5102-6271-EV1-CS127 Amrut",
396           .spi_devs = wm5102_spi_devs,
397           .num_spi_devs = ARRAY_SIZE(wm5102_spi_devs),
398           .gpiod_table = &wm5102_gpiod_table },
399         { .id = 0x3f, .rev = -1, .name = "WM2200-6271-CS90-M-REV1",
400           .i2c_devs = wm2200_i2c, .num_i2c_devs = ARRAY_SIZE(wm2200_i2c),
401           .gpiod_table = &wm2200_gpiod_table },
402 };
403 
404 static int wlf_gf_module_probe(struct i2c_client *i2c)
405 {
406         int ret, i, j, id, rev;
407 
408         ret = i2c_smbus_read_byte_data(i2c, 0);
409         if (ret < 0) {
410                 dev_err(&i2c->dev, "Failed to read ID: %d\n", ret);
411                 return ret;
412         }
413 
414         id = (ret & 0xfe) >> 2;
415         rev = ret & 0x3;
416         for (i = 0; i < ARRAY_SIZE(gf_mods); i++)
417                 if (id == gf_mods[i].id && (gf_mods[i].rev == 0xff ||
418                                             rev == gf_mods[i].rev))
419                         break;
420 
421         gpiod_add_lookup_table(&wm5102_reva_gpiod_table);
422         gpiod_add_lookup_table(&wm5102_gpiod_table);
423         gpiod_add_lookup_table(&wm8994_gpiod_table);
424 
425         if (i < ARRAY_SIZE(gf_mods)) {
426                 dev_info(&i2c->dev, "%s revision %d\n",
427                          gf_mods[i].name, rev + 1);
428 
429                 for (j = 0; j < gf_mods[i].num_i2c_devs; j++) {
430                         if (IS_ERR(i2c_new_client_device(i2c->adapter,
431                                                          &(gf_mods[i].i2c_devs[j]))))
432                                 dev_err(&i2c->dev, "Failed to register\n");
433                 }
434 
435                 spi_register_board_info(gf_mods[i].spi_devs,
436                                         gf_mods[i].num_spi_devs);
437 
438                 if (gf_mods[i].gpiod_table)
439                         gpiod_add_lookup_table(gf_mods[i].gpiod_table);
440         } else {
441                 dev_warn(&i2c->dev, "Unknown module ID 0x%x revision %d\n",
442                          id, rev + 1);
443         }
444 
445         return 0;
446 }
447 
448 static const struct i2c_device_id wlf_gf_module_id[] = {
449         { "wlf-gf-module", 0 },
450         { }
451 };
452 
453 static struct i2c_driver wlf_gf_module_driver = {
454         .driver = {
455                 .name = "wlf-gf-module"
456         },
457         .probe = wlf_gf_module_probe,
458         .id_table = wlf_gf_module_id,
459 };
460 
461 static int __init wlf_gf_module_register(void)
462 {
463         if (!soc_is_s3c64xx())
464                 return 0;
465 
466         return i2c_add_driver(&wlf_gf_module_driver);
467 }
468 device_initcall(wlf_gf_module_register);
469 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php