mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-05 18:14:07 +08:00
2874c5fd28
Based on 1 normalized pattern(s): this program is free software you can redistribute it and or modify it under the terms of the gnu general public license as published by the free software foundation either version 2 of the license or at your option any later version extracted by the scancode license scanner the SPDX license identifier GPL-2.0-or-later has been chosen to replace the boilerplate/reference in 3029 file(s). Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Allison Randal <allison@lohutok.net> Cc: linux-spdx@vger.kernel.org Link: https://lkml.kernel.org/r/20190527070032.746973796@linutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
120 lines
2.6 KiB
C
120 lines
2.6 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* wm831x-spi.c -- SPI access for Wolfson WM831x PMICs
|
|
*
|
|
* Copyright 2009,2010 Wolfson Microelectronics PLC.
|
|
*
|
|
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_device.h>
|
|
#include <linux/pm.h>
|
|
#include <linux/spi/spi.h>
|
|
#include <linux/regmap.h>
|
|
#include <linux/err.h>
|
|
|
|
#include <linux/mfd/wm831x/core.h>
|
|
|
|
static int wm831x_spi_probe(struct spi_device *spi)
|
|
{
|
|
struct wm831x_pdata *pdata = dev_get_platdata(&spi->dev);
|
|
const struct spi_device_id *id = spi_get_device_id(spi);
|
|
const struct of_device_id *of_id;
|
|
struct wm831x *wm831x;
|
|
enum wm831x_parent type;
|
|
int ret;
|
|
|
|
if (spi->dev.of_node) {
|
|
of_id = of_match_device(wm831x_of_match, &spi->dev);
|
|
if (!of_id) {
|
|
dev_err(&spi->dev, "Failed to match device\n");
|
|
return -ENODEV;
|
|
}
|
|
type = (enum wm831x_parent)of_id->data;
|
|
} else {
|
|
type = (enum wm831x_parent)id->driver_data;
|
|
}
|
|
|
|
wm831x = devm_kzalloc(&spi->dev, sizeof(struct wm831x), GFP_KERNEL);
|
|
if (wm831x == NULL)
|
|
return -ENOMEM;
|
|
|
|
spi->mode = SPI_MODE_0;
|
|
|
|
spi_set_drvdata(spi, wm831x);
|
|
wm831x->dev = &spi->dev;
|
|
wm831x->type = type;
|
|
|
|
wm831x->regmap = devm_regmap_init_spi(spi, &wm831x_regmap_config);
|
|
if (IS_ERR(wm831x->regmap)) {
|
|
ret = PTR_ERR(wm831x->regmap);
|
|
dev_err(wm831x->dev, "Failed to allocate register map: %d\n",
|
|
ret);
|
|
return ret;
|
|
}
|
|
|
|
if (pdata)
|
|
memcpy(&wm831x->pdata, pdata, sizeof(*pdata));
|
|
|
|
return wm831x_device_init(wm831x, spi->irq);
|
|
}
|
|
|
|
static int wm831x_spi_suspend(struct device *dev)
|
|
{
|
|
struct wm831x *wm831x = dev_get_drvdata(dev);
|
|
|
|
return wm831x_device_suspend(wm831x);
|
|
}
|
|
|
|
static int wm831x_spi_poweroff(struct device *dev)
|
|
{
|
|
struct wm831x *wm831x = dev_get_drvdata(dev);
|
|
|
|
wm831x_device_shutdown(wm831x);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct dev_pm_ops wm831x_spi_pm = {
|
|
.freeze = wm831x_spi_suspend,
|
|
.suspend = wm831x_spi_suspend,
|
|
.poweroff = wm831x_spi_poweroff,
|
|
};
|
|
|
|
static const struct spi_device_id wm831x_spi_ids[] = {
|
|
{ "wm8310", WM8310 },
|
|
{ "wm8311", WM8311 },
|
|
{ "wm8312", WM8312 },
|
|
{ "wm8320", WM8320 },
|
|
{ "wm8321", WM8321 },
|
|
{ "wm8325", WM8325 },
|
|
{ "wm8326", WM8326 },
|
|
{ },
|
|
};
|
|
|
|
static struct spi_driver wm831x_spi_driver = {
|
|
.driver = {
|
|
.name = "wm831x",
|
|
.pm = &wm831x_spi_pm,
|
|
.of_match_table = of_match_ptr(wm831x_of_match),
|
|
.suppress_bind_attrs = true,
|
|
},
|
|
.id_table = wm831x_spi_ids,
|
|
.probe = wm831x_spi_probe,
|
|
};
|
|
|
|
static int __init wm831x_spi_init(void)
|
|
{
|
|
int ret;
|
|
|
|
ret = spi_register_driver(&wm831x_spi_driver);
|
|
if (ret != 0)
|
|
pr_err("Failed to register WM831x SPI driver: %d\n", ret);
|
|
|
|
return 0;
|
|
}
|
|
subsys_initcall(wm831x_spi_init);
|