Path: blob/master/drivers/input/misc/adxl34x-spi.c
15111 views
/*1* ADLX345/346 Three-Axis Digital Accelerometers (SPI Interface)2*3* Enter bugs at http://blackfin.uclinux.org/4*5* Copyright (C) 2009 Michael Hennerich, Analog Devices Inc.6* Licensed under the GPL-2 or later.7*/89#include <linux/input.h> /* BUS_SPI */10#include <linux/module.h>11#include <linux/spi/spi.h>12#include <linux/pm.h>13#include <linux/types.h>14#include "adxl34x.h"1516#define MAX_SPI_FREQ_HZ 500000017#define MAX_FREQ_NO_FIFODELAY 150000018#define ADXL34X_CMD_MULTB (1 << 6)19#define ADXL34X_CMD_READ (1 << 7)20#define ADXL34X_WRITECMD(reg) (reg & 0x3F)21#define ADXL34X_READCMD(reg) (ADXL34X_CMD_READ | (reg & 0x3F))22#define ADXL34X_READMB_CMD(reg) (ADXL34X_CMD_READ | ADXL34X_CMD_MULTB \23| (reg & 0x3F))2425static int adxl34x_spi_read(struct device *dev, unsigned char reg)26{27struct spi_device *spi = to_spi_device(dev);28unsigned char cmd;2930cmd = ADXL34X_READCMD(reg);3132return spi_w8r8(spi, cmd);33}3435static int adxl34x_spi_write(struct device *dev,36unsigned char reg, unsigned char val)37{38struct spi_device *spi = to_spi_device(dev);39unsigned char buf[2];4041buf[0] = ADXL34X_WRITECMD(reg);42buf[1] = val;4344return spi_write(spi, buf, sizeof(buf));45}4647static int adxl34x_spi_read_block(struct device *dev,48unsigned char reg, int count,49void *buf)50{51struct spi_device *spi = to_spi_device(dev);52ssize_t status;5354reg = ADXL34X_READMB_CMD(reg);55status = spi_write_then_read(spi, ®, 1, buf, count);5657return (status < 0) ? status : 0;58}5960static const struct adxl34x_bus_ops adxl34x_spi_bops = {61.bustype = BUS_SPI,62.write = adxl34x_spi_write,63.read = adxl34x_spi_read,64.read_block = adxl34x_spi_read_block,65};6667static int __devinit adxl34x_spi_probe(struct spi_device *spi)68{69struct adxl34x *ac;7071/* don't exceed max specified SPI CLK frequency */72if (spi->max_speed_hz > MAX_SPI_FREQ_HZ) {73dev_err(&spi->dev, "SPI CLK %d Hz too fast\n", spi->max_speed_hz);74return -EINVAL;75}7677ac = adxl34x_probe(&spi->dev, spi->irq,78spi->max_speed_hz > MAX_FREQ_NO_FIFODELAY,79&adxl34x_spi_bops);8081if (IS_ERR(ac))82return PTR_ERR(ac);8384spi_set_drvdata(spi, ac);8586return 0;87}8889static int __devexit adxl34x_spi_remove(struct spi_device *spi)90{91struct adxl34x *ac = dev_get_drvdata(&spi->dev);9293return adxl34x_remove(ac);94}9596#ifdef CONFIG_PM97static int adxl34x_spi_suspend(struct device *dev)98{99struct spi_device *spi = to_spi_device(dev);100struct adxl34x *ac = dev_get_drvdata(&spi->dev);101102adxl34x_suspend(ac);103104return 0;105}106107static int adxl34x_spi_resume(struct device *dev)108{109struct spi_device *spi = to_spi_device(dev);110struct adxl34x *ac = dev_get_drvdata(&spi->dev);111112adxl34x_resume(ac);113114return 0;115}116#endif117118static SIMPLE_DEV_PM_OPS(adxl34x_spi_pm, adxl34x_spi_suspend,119adxl34x_spi_resume);120121static struct spi_driver adxl34x_driver = {122.driver = {123.name = "adxl34x",124.bus = &spi_bus_type,125.owner = THIS_MODULE,126.pm = &adxl34x_spi_pm,127},128.probe = adxl34x_spi_probe,129.remove = __devexit_p(adxl34x_spi_remove),130};131132static int __init adxl34x_spi_init(void)133{134return spi_register_driver(&adxl34x_driver);135}136module_init(adxl34x_spi_init);137138static void __exit adxl34x_spi_exit(void)139{140spi_unregister_driver(&adxl34x_driver);141}142module_exit(adxl34x_spi_exit);143144MODULE_AUTHOR("Michael Hennerich <[email protected]>");145MODULE_DESCRIPTION("ADXL345/346 Three-Axis Digital Accelerometer SPI Bus Driver");146MODULE_LICENSE("GPL");147148149