Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * lis3lv02d_spi - SPI glue layer for lis3lv02d
0004  *
0005  * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/kernel.h>
0010 #include <linux/err.h>
0011 #include <linux/input.h>
0012 #include <linux/interrupt.h>
0013 #include <linux/workqueue.h>
0014 #include <linux/spi/spi.h>
0015 #include <linux/pm.h>
0016 #include <linux/of.h>
0017 #include <linux/of_platform.h>
0018 #include <linux/of_device.h>
0019 
0020 #include "lis3lv02d.h"
0021 
0022 #define DRV_NAME    "lis3lv02d_spi"
0023 #define LIS3_SPI_READ   0x80
0024 
0025 static int lis3_spi_read(struct lis3lv02d *lis3, int reg, u8 *v)
0026 {
0027     struct spi_device *spi = lis3->bus_priv;
0028     int ret = spi_w8r8(spi, reg | LIS3_SPI_READ);
0029     if (ret < 0)
0030         return -EINVAL;
0031 
0032     *v = (u8) ret;
0033     return 0;
0034 }
0035 
0036 static int lis3_spi_write(struct lis3lv02d *lis3, int reg, u8 val)
0037 {
0038     u8 tmp[2] = { reg, val };
0039     struct spi_device *spi = lis3->bus_priv;
0040     return spi_write(spi, tmp, sizeof(tmp));
0041 }
0042 
0043 static int lis3_spi_init(struct lis3lv02d *lis3)
0044 {
0045     u8 reg;
0046     int ret;
0047 
0048     /* power up the device */
0049     ret = lis3->read(lis3, CTRL_REG1, &reg);
0050     if (ret < 0)
0051         return ret;
0052 
0053     reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
0054     return lis3->write(lis3, CTRL_REG1, reg);
0055 }
0056 
0057 static union axis_conversion lis3lv02d_axis_normal =
0058     { .as_array = { 1, 2, 3 } };
0059 
0060 #ifdef CONFIG_OF
0061 static const struct of_device_id lis302dl_spi_dt_ids[] = {
0062     { .compatible = "st,lis302dl-spi" },
0063     {}
0064 };
0065 MODULE_DEVICE_TABLE(of, lis302dl_spi_dt_ids);
0066 #endif
0067 
0068 static int lis302dl_spi_probe(struct spi_device *spi)
0069 {
0070     int ret;
0071 
0072     spi->bits_per_word = 8;
0073     spi->mode = SPI_MODE_0;
0074     ret = spi_setup(spi);
0075     if (ret < 0)
0076         return ret;
0077 
0078     lis3_dev.bus_priv   = spi;
0079     lis3_dev.init       = lis3_spi_init;
0080     lis3_dev.read       = lis3_spi_read;
0081     lis3_dev.write      = lis3_spi_write;
0082     lis3_dev.irq        = spi->irq;
0083     lis3_dev.ac     = lis3lv02d_axis_normal;
0084     lis3_dev.pdata      = spi->dev.platform_data;
0085 
0086 #ifdef CONFIG_OF
0087     if (of_match_device(lis302dl_spi_dt_ids, &spi->dev)) {
0088         lis3_dev.of_node = spi->dev.of_node;
0089         ret = lis3lv02d_init_dt(&lis3_dev);
0090         if (ret)
0091             return ret;
0092     }
0093 #endif
0094     spi_set_drvdata(spi, &lis3_dev);
0095 
0096     return lis3lv02d_init_device(&lis3_dev);
0097 }
0098 
0099 static void lis302dl_spi_remove(struct spi_device *spi)
0100 {
0101     struct lis3lv02d *lis3 = spi_get_drvdata(spi);
0102     lis3lv02d_joystick_disable(lis3);
0103     lis3lv02d_poweroff(lis3);
0104 
0105     lis3lv02d_remove_fs(&lis3_dev);
0106 }
0107 
0108 #ifdef CONFIG_PM_SLEEP
0109 static int lis3lv02d_spi_suspend(struct device *dev)
0110 {
0111     struct spi_device *spi = to_spi_device(dev);
0112     struct lis3lv02d *lis3 = spi_get_drvdata(spi);
0113 
0114     if (!lis3->pdata || !lis3->pdata->wakeup_flags)
0115         lis3lv02d_poweroff(&lis3_dev);
0116 
0117     return 0;
0118 }
0119 
0120 static int lis3lv02d_spi_resume(struct device *dev)
0121 {
0122     struct spi_device *spi = to_spi_device(dev);
0123     struct lis3lv02d *lis3 = spi_get_drvdata(spi);
0124 
0125     if (!lis3->pdata || !lis3->pdata->wakeup_flags)
0126         lis3lv02d_poweron(lis3);
0127 
0128     return 0;
0129 }
0130 #endif
0131 
0132 static SIMPLE_DEV_PM_OPS(lis3lv02d_spi_pm, lis3lv02d_spi_suspend,
0133              lis3lv02d_spi_resume);
0134 
0135 static struct spi_driver lis302dl_spi_driver = {
0136     .driver  = {
0137         .name   = DRV_NAME,
0138         .pm = &lis3lv02d_spi_pm,
0139         .of_match_table = of_match_ptr(lis302dl_spi_dt_ids),
0140     },
0141     .probe  = lis302dl_spi_probe,
0142     .remove = lis302dl_spi_remove,
0143 };
0144 
0145 module_spi_driver(lis302dl_spi_driver);
0146 
0147 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
0148 MODULE_DESCRIPTION("lis3lv02d SPI glue layer");
0149 MODULE_LICENSE("GPL");
0150 MODULE_ALIAS("spi:" DRV_NAME);