1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // |
3 | // cs35l41-spi.c -- CS35l41 SPI driver |
4 | // |
5 | // Copyright 2017-2021 Cirrus Logic, Inc. |
6 | // |
7 | // Author: David Rhodes <david.rhodes@cirrus.com> |
8 | |
9 | #include <linux/acpi.h> |
10 | #include <linux/delay.h> |
11 | #include <linux/init.h> |
12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> |
14 | #include <linux/moduleparam.h> |
15 | #include <linux/platform_device.h> |
16 | #include <linux/spi/spi.h> |
17 | |
18 | #include "cs35l41.h" |
19 | |
20 | static const struct spi_device_id cs35l41_id_spi[] = { |
21 | { "cs35l40" , 0 }, |
22 | { "cs35l41" , 0 }, |
23 | { "cs35l51" , 0 }, |
24 | { "cs35l53" , 0 }, |
25 | {} |
26 | }; |
27 | |
28 | MODULE_DEVICE_TABLE(spi, cs35l41_id_spi); |
29 | |
30 | static int cs35l41_spi_probe(struct spi_device *spi) |
31 | { |
32 | const struct regmap_config *regmap_config = &cs35l41_regmap_spi; |
33 | struct cs35l41_hw_cfg *hw_cfg = dev_get_platdata(dev: &spi->dev); |
34 | struct cs35l41_private *cs35l41; |
35 | |
36 | cs35l41 = devm_kzalloc(dev: &spi->dev, size: sizeof(struct cs35l41_private), GFP_KERNEL); |
37 | if (!cs35l41) |
38 | return -ENOMEM; |
39 | |
40 | spi->max_speed_hz = CS35L41_SPI_MAX_FREQ; |
41 | spi_setup(spi); |
42 | |
43 | spi_set_drvdata(spi, data: cs35l41); |
44 | cs35l41->regmap = devm_regmap_init_spi(spi, regmap_config); |
45 | if (IS_ERR(ptr: cs35l41->regmap)) |
46 | return dev_err_probe(dev: cs35l41->dev, err: PTR_ERR(ptr: cs35l41->regmap), |
47 | fmt: "Failed to allocate register map\n" ); |
48 | |
49 | cs35l41->dev = &spi->dev; |
50 | cs35l41->irq = spi->irq; |
51 | |
52 | return cs35l41_probe(cs35l41, hw_cfg); |
53 | } |
54 | |
55 | static void cs35l41_spi_remove(struct spi_device *spi) |
56 | { |
57 | struct cs35l41_private *cs35l41 = spi_get_drvdata(spi); |
58 | |
59 | cs35l41_remove(cs35l41); |
60 | } |
61 | |
62 | #ifdef CONFIG_OF |
63 | static const struct of_device_id cs35l41_of_match[] = { |
64 | { .compatible = "cirrus,cs35l40" }, |
65 | { .compatible = "cirrus,cs35l41" }, |
66 | {}, |
67 | }; |
68 | MODULE_DEVICE_TABLE(of, cs35l41_of_match); |
69 | #endif |
70 | |
71 | #ifdef CONFIG_ACPI |
72 | static const struct acpi_device_id cs35l41_acpi_match[] = { |
73 | { "CSC3541" , 0 }, /* Cirrus Logic PnP ID + part ID */ |
74 | { "CLSA3541" , 0 }, /* Cirrus Logic PnP ID + part ID */ |
75 | {}, |
76 | }; |
77 | MODULE_DEVICE_TABLE(acpi, cs35l41_acpi_match); |
78 | #endif |
79 | |
80 | static struct spi_driver cs35l41_spi_driver = { |
81 | .driver = { |
82 | .name = "cs35l41" , |
83 | .pm = pm_ptr(&cs35l41_pm_ops), |
84 | .of_match_table = of_match_ptr(cs35l41_of_match), |
85 | .acpi_match_table = ACPI_PTR(cs35l41_acpi_match), |
86 | }, |
87 | .id_table = cs35l41_id_spi, |
88 | .probe = cs35l41_spi_probe, |
89 | .remove = cs35l41_spi_remove, |
90 | }; |
91 | |
92 | module_spi_driver(cs35l41_spi_driver); |
93 | |
94 | MODULE_DESCRIPTION("SPI CS35L41 driver" ); |
95 | MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <david.rhodes@cirrus.com>" ); |
96 | MODULE_LICENSE("GPL" ); |
97 | |