xref: /openbmc/linux/drivers/mfd/arizona-spi.c (revision 039da225)
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