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 10a15123c7SMark Brown #include <linux/err.h> 11a15123c7SMark Brown #include <linux/module.h> 12a15123c7SMark Brown #include <linux/pm_runtime.h> 13a15123c7SMark Brown #include <linux/regmap.h> 14a15123c7SMark Brown #include <linux/regulator/consumer.h> 15a15123c7SMark Brown #include <linux/slab.h> 16a15123c7SMark Brown #include <linux/spi/spi.h> 173d6d1d1cSSachin Kamat #include <linux/of.h> 18a15123c7SMark Brown 19a15123c7SMark Brown #include <linux/mfd/arizona/core.h> 20a15123c7SMark Brown 21a15123c7SMark Brown #include "arizona.h" 22a15123c7SMark Brown 23f791be49SBill Pemberton static int arizona_spi_probe(struct spi_device *spi) 24a15123c7SMark Brown { 25a15123c7SMark Brown const struct spi_device_id *id = spi_get_device_id(spi); 26*039da225SHans de Goede const void *match_data; 27a15123c7SMark Brown struct arizona *arizona; 28b61c1ec0SRichard Fitzgerald const struct regmap_config *regmap_config = NULL; 29*039da225SHans de Goede unsigned long type = 0; 30942786e6SLee Jones int ret; 31a15123c7SMark Brown 32*039da225SHans de Goede match_data = device_get_match_data(&spi->dev); 33*039da225SHans de Goede if (match_data) 34*039da225SHans de Goede type = (unsigned long)match_data; 35*039da225SHans de Goede else if (id) 36d781009cSMark Brown type = id->driver_data; 37d781009cSMark Brown 38d781009cSMark Brown switch (type) { 39a15123c7SMark Brown case WM5102: 40b61c1ec0SRichard Fitzgerald if (IS_ENABLED(CONFIG_MFD_WM5102)) 41a15123c7SMark Brown regmap_config = &wm5102_spi_regmap; 42a15123c7SMark Brown break; 43e102befeSMark Brown case WM5110: 44e5d4ef0dSRichard Fitzgerald case WM8280: 45b61c1ec0SRichard Fitzgerald if (IS_ENABLED(CONFIG_MFD_WM5110)) 46e102befeSMark Brown regmap_config = &wm5110_spi_regmap; 47e102befeSMark Brown break; 48ea1f3339SRichard Fitzgerald case WM1831: 49ea1f3339SRichard Fitzgerald case CS47L24: 50ea1f3339SRichard Fitzgerald if (IS_ENABLED(CONFIG_MFD_CS47L24)) 51ea1f3339SRichard Fitzgerald regmap_config = &cs47l24_spi_regmap; 52ea1f3339SRichard Fitzgerald break; 53a15123c7SMark Brown default: 542e44e28aSRichard Fitzgerald dev_err(&spi->dev, "Unknown device type %ld\n", type); 55a15123c7SMark Brown return -EINVAL; 56a15123c7SMark Brown } 57a15123c7SMark Brown 58b61c1ec0SRichard Fitzgerald if (!regmap_config) { 59b61c1ec0SRichard Fitzgerald dev_err(&spi->dev, 60b61c1ec0SRichard Fitzgerald "No kernel support for device type %ld\n", type); 61a15123c7SMark Brown return -EINVAL; 62a15123c7SMark Brown } 63a15123c7SMark Brown 64a15123c7SMark Brown arizona = devm_kzalloc(&spi->dev, sizeof(*arizona), GFP_KERNEL); 65a15123c7SMark Brown if (arizona == NULL) 66a15123c7SMark Brown return -ENOMEM; 67a15123c7SMark Brown 68a15123c7SMark Brown arizona->regmap = devm_regmap_init_spi(spi, regmap_config); 69a15123c7SMark Brown if (IS_ERR(arizona->regmap)) { 70a15123c7SMark Brown ret = PTR_ERR(arizona->regmap); 71a15123c7SMark Brown dev_err(&spi->dev, "Failed to allocate register map: %d\n", 72a15123c7SMark Brown ret); 73a15123c7SMark Brown return ret; 74a15123c7SMark Brown } 75a15123c7SMark Brown 762e44e28aSRichard Fitzgerald arizona->type = type; 77a15123c7SMark Brown arizona->dev = &spi->dev; 78a15123c7SMark Brown arizona->irq = spi->irq; 79a15123c7SMark Brown 80a15123c7SMark Brown return arizona_dev_init(arizona); 81a15123c7SMark Brown } 82a15123c7SMark Brown 834740f73fSBill Pemberton static int arizona_spi_remove(struct spi_device *spi) 84a15123c7SMark Brown { 85e9642d5eSJingoo Han struct arizona *arizona = spi_get_drvdata(spi); 866f467e5fSWill Sheppard 87a15123c7SMark Brown arizona_dev_exit(arizona); 886f467e5fSWill Sheppard 89a15123c7SMark Brown return 0; 90a15123c7SMark Brown } 91a15123c7SMark Brown 92a15123c7SMark Brown static const struct spi_device_id arizona_spi_ids[] = { 93a15123c7SMark Brown { "wm5102", WM5102 }, 94e102befeSMark Brown { "wm5110", WM5110 }, 95e5d4ef0dSRichard Fitzgerald { "wm8280", WM8280 }, 96ea1f3339SRichard Fitzgerald { "wm1831", WM1831 }, 97ea1f3339SRichard Fitzgerald { "cs47l24", CS47L24 }, 98a15123c7SMark Brown { }, 99a15123c7SMark Brown }; 100a15123c7SMark Brown MODULE_DEVICE_TABLE(spi, arizona_spi_ids); 101a15123c7SMark Brown 102a15123c7SMark Brown static struct spi_driver arizona_spi_driver = { 103a15123c7SMark Brown .driver = { 104a15123c7SMark Brown .name = "arizona", 105a15123c7SMark Brown .pm = &arizona_pm_ops, 106d781009cSMark Brown .of_match_table = of_match_ptr(arizona_of_match), 107a15123c7SMark Brown }, 108a15123c7SMark Brown .probe = arizona_spi_probe, 10984449216SBill Pemberton .remove = arizona_spi_remove, 110a15123c7SMark Brown .id_table = arizona_spi_ids, 111a15123c7SMark Brown }; 112a15123c7SMark Brown 113a15123c7SMark Brown module_spi_driver(arizona_spi_driver); 114a15123c7SMark Brown 11506e577b4SHans de Goede MODULE_SOFTDEP("pre: arizona_ldo1"); 116a15123c7SMark Brown MODULE_DESCRIPTION("Arizona SPI bus interface"); 117a15123c7SMark Brown MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 118a15123c7SMark Brown MODULE_LICENSE("GPL"); 119