Files
ubports_kernel_google_msm/include/linux/spmi.h
Michael Bohan 317a4316b4 of: of_spmi: Add support for spmi-dev-container binding
The spmi-dev-container binding is intended for SPMI
configurations that have multiple device nodes associated with
only one spmi_device. By default, if this flag is not specified,
each device node will create a new spmi_device.

Sometimes having multiple spmi_devices for SPMI device nodes is
superfluous. One example of this is gpios. In some architectures,
a single gpio is treated as a unique device. But from a gpio_chip
perspective, the chip is comprised of many gpios. Beyond wasting
memory allocating a unique spmi_device per gpio, the implication
of not coalescing spmi_devices is that the clients probe() routine
would be called N number of times. But this sort of behavior makes
it difficult to realize when a gpio_chip starts and stops. If we
assume that one gpio_chip represents one call to probe(), then
this problem is solved, since all gpios in that chip will be
passed as resources.

In order to support multiple device nodes per spmi_device, we
also need to extend the data structures for spmi_resources.

This change also makes an effort to cleanup some of the error
handling for illegal combinations of device bindings, as well as
adding some additional documentation.

Change-Id: If3ce2aaaa07bdf79e0d9fdedf16419e74a00fbec
Signed-off-by: Michael Bohan <mbohan@codeaurora.org>
Signed-off-by: David Brown <davidb@codeaurora.org>
2013-02-25 11:33:02 -08:00

421 lines
13 KiB
C

/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _LINUX_SPMI_H
#define _LINUX_SPMI_H
#include <linux/types.h>
#include <linux/device.h>
#include <linux/mod_devicetable.h>
/* Maximum slave identifier */
#define SPMI_MAX_SLAVE_ID 16
/* SPMI Commands */
enum spmi_commands {
SPMI_CMD_EXT_WRITE = 0x00,
SPMI_CMD_RESET = 0x10,
SPMI_CMD_SLEEP = 0x11,
SPMI_CMD_SHUTDOWN = 0x12,
SPMI_CMD_WAKEUP = 0x13,
SPMI_CMD_AUTHENTICATE = 0x14,
SPMI_CMD_MSTR_READ = 0x15,
SPMI_CMD_MSTR_WRITE = 0x16,
SPMI_CMD_TRANSFER_BUS_OWNERSHIP = 0x1A,
SPMI_CMD_DDB_MASTER_READ = 0x1B,
SPMI_CMD_DDB_SLAVE_READ = 0x1C,
SPMI_CMD_EXT_READ = 0x20,
SPMI_CMD_EXT_WRITEL = 0x30,
SPMI_CMD_EXT_READL = 0x38,
SPMI_CMD_WRITE = 0x40,
SPMI_CMD_READ = 0x60,
SPMI_CMD_ZERO_WRITE = 0x80,
};
struct spmi_device;
/**
* struct spmi_controller: interface to the SPMI master controller
* @nr: board-specific number identifier for this controller/bus
* @name: name for this controller
* @cmd: sends a non-data command sequence on the SPMI bus.
* @read_cmd: sends a register read command sequence on the SPMI bus.
* @write_cmd: sends a register write command sequence on the SPMI bus.
*/
struct spmi_controller {
struct device dev;
unsigned int nr;
struct list_head list;
int (*cmd)(struct spmi_controller *, u8 opcode, u8 sid);
int (*read_cmd)(struct spmi_controller *,
u8 opcode, u8 sid, u16 addr, u8 bc, u8 *buf);
int (*write_cmd)(struct spmi_controller *,
u8 opcode, u8 sid, u16 addr, u8 bc, u8 *buf);
};
#define to_spmi_controller(d) container_of(d, struct spmi_controller, dev)
/**
* struct spmi_driver: Manage SPMI generic/slave device driver
* @probe: binds this driver to a SPMI device.
* @remove: unbinds this driver from the SPMI device.
* @shutdown: standard shutdown callback used during powerdown/halt.
* @suspend: standard suspend callback used during system suspend
* @resume: standard resume callback used during system resume
* @driver: SPMI device drivers should initialize name and owner field of
* this structure
* @id_table: list of SPMI devices supported by this driver
*/
struct spmi_driver {
int (*probe)(struct spmi_device *dev);
int (*remove)(struct spmi_device *dev);
void (*shutdown)(struct spmi_device *dev);
int (*suspend)(struct spmi_device *dev,
pm_message_t pmesg);
int (*resume)(struct spmi_device *dev);
struct device_driver driver;
const struct spmi_device_id *id_table;
};
#define to_spmi_driver(d) container_of(d, struct spmi_driver, driver)
/**
* struct spmi_resource: spmi_resource for one device_node
* @num_resources: number of resources for this device node
* @resources: array of resources for this device_node
* @of_node: device_node of the resource in question
*/
struct spmi_resource {
struct resource *resource;
u32 num_resources;
struct device_node *of_node;
};
/**
* Client/device handle (struct spmi_device):
* ------------------------------------------
* This is the client/device handle returned when a SPMI device
* is registered with a controller.
* Pointer to this structure is used by client-driver as a handle.
* @dev: Driver model representation of the device.
* @name: Name of driver to use with this device.
* @ctrl: SPMI controller managing the bus hosting this device.
* @dev_node: array of SPMI resources - one entry per device_node.
* @num_dev_node: number of device_node structures.
* @sid: Slave Identifier.
*/
struct spmi_device {
struct device dev;
const char *name;
struct spmi_controller *ctrl;
struct spmi_resource *dev_node;
u32 num_dev_node;
u8 sid;
};
#define to_spmi_device(d) container_of(d, struct spmi_device, dev)
/**
* struct spmi_boardinfo: Declare board info for SPMI device bringup.
* @slave_id: slave identifier.
* @spmi_device: device to be registered with the SPMI framework.
* @of_node: pointer to the OpenFirmware device node.
* @dev_node: one spmi_resource for each device_node.
* @num_dev_node: number of device_node structures.
* @platform_data: goes to spmi_device.dev.platform_data
*/
struct spmi_boardinfo {
char name[SPMI_NAME_SIZE];
uint8_t slave_id;
struct device_node *of_node;
struct spmi_resource *dev_node;
u32 num_dev_node;
const void *platform_data;
};
/**
* spmi_driver_register: Client driver registration with SPMI framework.
* @drv: client driver to be associated with client-device.
*
* This API will register the client driver with the SPMI framework.
* It is called from the driver's module-init function.
*/
extern int spmi_driver_register(struct spmi_driver *drv);
/**
* spmi_driver_unregister - reverse effect of spmi_driver_register
* @sdrv: the driver to unregister
* Context: can sleep
*/
static inline void spmi_driver_unregister(struct spmi_driver *sdrv)
{
if (sdrv)
driver_unregister(&sdrv->driver);
}
/**
* spmi_add_controller: Controller bring-up.
* @ctrl: controller to be registered.
*
* A controller is registered with the framework using this API. ctrl->nr is the
* desired number with which SPMI framework registers the controller.
* Function will return -EBUSY if the number is in use.
*/
extern int spmi_add_controller(struct spmi_controller *ctrl);
/**
* spmi_del_controller: Controller tear-down.
* Controller added with the above API is teared down using this API.
*/
extern int spmi_del_controller(struct spmi_controller *ctrl);
/**
* spmi_busnum_to_ctrl: Map bus number to controller
* @busnum: bus number
*
* Returns controller device representing this bus number
*/
extern struct spmi_controller *spmi_busnum_to_ctrl(u32 bus_num);
/**
* spmi_alloc_device: Allocate a new SPMI devices.
* @ctrl: controller to which this device is to be added to.
* Context: can sleep
*
* Allows a driver to allocate and initialize a SPMI device without
* registering it immediately. This allows a driver to directly fill
* the spmi_device structure before calling spmi_add_device().
*
* Caller is responsible to call spmi_add_device() on the returned
* spmi_device. If the caller needs to discard the spmi_device without
* adding it, then spmi_dev_put() should be called.
*/
extern struct spmi_device *spmi_alloc_device(struct spmi_controller *ctrl);
/**
* spmi_add_device: Add spmi_device allocated with spmi_alloc_device().
* @spmi_dev: spmi_device to be added (registered).
*/
extern int spmi_add_device(struct spmi_device *spmi_dev);
/**
* spmi_new_device: Instantiates a new SPMI device
* @ctrl: controller to which this device is to be added to.
* @info: board information for this device.
*
* Returns the new device or NULL.
*/
extern struct spmi_device *spmi_new_device(struct spmi_controller *ctrl,
struct spmi_boardinfo const *info);
/* spmi_remove_device: Remove the effect of spmi_add_device() */
extern void spmi_remove_device(struct spmi_device *spmi_dev);
#ifdef CONFIG_SPMI
/**
* spmi_register_board_info: Board-initialization routine.
* @bus_num: controller number (bus) on which this device will sit.
* @info: list of all devices on all controllers present on the board.
* @n: number of entries.
*
* API enumerates respective devices on corresponding controller.
* Called from board-init function.
*/
extern int spmi_register_board_info(int busnum,
struct spmi_boardinfo const *info, unsigned n);
#else
static inline int spmi_register_board_info(int busnum,
struct spmi_boardinfo const *info, unsigned n)
{
return 0;
}
#endif
static inline void *spmi_get_ctrldata(const struct spmi_controller *ctrl)
{
return dev_get_drvdata(&ctrl->dev);
}
static inline void spmi_set_ctrldata(struct spmi_controller *ctrl, void *data)
{
dev_set_drvdata(&ctrl->dev, data);
}
static inline void *spmi_get_devicedata(const struct spmi_device *dev)
{
return dev_get_drvdata(&dev->dev);
}
static inline void spmi_set_devicedata(struct spmi_device *dev, void *data)
{
dev_set_drvdata(&dev->dev, data);
}
static inline void spmi_dev_put(struct spmi_device *spmidev)
{
if (spmidev)
put_device(&spmidev->dev);
}
/**
* spmi_register_read() - register read
* @ctrl: SPMI controller.
* @sid: slave identifier.
* @ad: slave register address (5-bit address).
* @buf: buffer to be populated with data from the Slave.
*
* Reads 1 byte of data from a Slave device register.
*/
extern int spmi_register_read(struct spmi_controller *ctrl,
u8 sid, u8 ad, u8 *buf);
/**
* spmi_ext_register_read() - extended register read
* @ctrl: SPMI controller.
* @sid: slave identifier.
* @ad: slave register address (8-bit address).
* @len: the request number of bytes to read (up to 16 bytes).
* @buf: buffer to be populated with data from the Slave.
*
* Reads up to 16 bytes of data from the extended register space on a
* Slave device.
*/
extern int spmi_ext_register_read(struct spmi_controller *ctrl,
u8 sid, u8 ad, u8 *buf, int len);
/**
* spmi_ext_register_readl() - extended register read long
* @ctrl: SPMI controller.
* @sid: slave identifier.
* @ad: slave register address (16-bit address).
* @len: the request number of bytes to read (up to 8 bytes).
* @buf: buffer to be populated with data from the Slave.
*
* Reads up to 8 bytes of data from the extended register space on a
* Slave device using 16-bit address.
*/
extern int spmi_ext_register_readl(struct spmi_controller *ctrl,
u8 sid, u16 ad, u8 *buf, int len);
/**
* spmi_register_write() - register write
* @ctrl: SPMI controller.
* @sid: slave identifier.
* @ad: slave register address (5-bit address).
* @buf: buffer containing the data to be transferred to the Slave.
*
* Writes 1 byte of data to a Slave device register.
*/
extern int spmi_register_write(struct spmi_controller *ctrl,
u8 sid, u8 ad, u8 *buf);
/**
* spmi_register_zero_write() - register zero write
* @ctrl: SPMI controller.
* @sid: slave identifier.
* @data: the data to be written to register 0 (7-bits).
*
* Writes data to register 0 of the Slave device.
*/
extern int spmi_register_zero_write(struct spmi_controller *ctrl,
u8 sid, u8 data);
/**
* spmi_ext_register_write() - extended register write
* @ctrl: SPMI controller.
* @sid: slave identifier.
* @ad: slave register address (8-bit address).
* @buf: buffer containing the data to be transferred to the Slave.
* @len: the request number of bytes to read (up to 16 bytes).
*
* Writes up to 16 bytes of data to the extended register space of a
* Slave device.
*/
extern int spmi_ext_register_write(struct spmi_controller *ctrl,
u8 sid, u8 ad, u8 *buf, int len);
/**
* spmi_ext_register_writel() - extended register write long
* @ctrl: SPMI controller.
* @sid: slave identifier.
* @ad: slave register address (16-bit address).
* @buf: buffer containing the data to be transferred to the Slave.
* @len: the request number of bytes to read (up to 8 bytes).
*
* Writes up to 8 bytes of data to the extended register space of a
* Slave device using 16-bit address.
*/
extern int spmi_ext_register_writel(struct spmi_controller *ctrl,
u8 sid, u16 ad, u8 *buf, int len);
/**
* spmi_command_reset() - sends RESET command to the specified slave
* @ctrl: SPMI controller.
* @sid: slave identifier.
*
* The Reset command initializes the Slave and forces all registers to
* their reset values. The Slave shall enter the STARTUP state after
* receiving a Reset command.
*
* Returns
* -EINVAL for invalid slave identifier.
* -EPERM if the SPMI transaction is denied due to permission issues.
* -EIO if the SPMI transaction fails (parity errors, etc).
* -ETIMEDOUT if the SPMI transaction times out.
*/
extern int spmi_command_reset(struct spmi_controller *ctrl, u8 sid);
/**
* spmi_command_sleep() - sends SLEEP command to the specified slave
* @ctrl: SPMI controller.
* @sid: slave identifier.
*
* The Sleep command causes the Slave to enter the user defined SLEEP state.
*
* Returns
* -EINVAL for invalid slave identifier.
* -EPERM if the SPMI transaction is denied due to permission issues.
* -EIO if the SPMI transaction fails (parity errors, etc).
* -ETIMEDOUT if the SPMI transaction times out.
*/
extern int spmi_command_sleep(struct spmi_controller *ctrl, u8 sid);
/**
* spmi_command_wakeup() - sends WAKEUP command to the specified slave
* @ctrl: SPMI controller.
* @sid: slave identifier.
*
* The Wakeup command causes the Slave to move from the SLEEP state to
* the ACTIVE state.
*
* Returns
* -EINVAL for invalid slave identifier.
* -EPERM if the SPMI transaction is denied due to permission issues.
* -EIO if the SPMI transaction fails (parity errors, etc).
* -ETIMEDOUT if the SPMI transaction times out.
*/
extern int spmi_command_wakeup(struct spmi_controller *ctrl, u8 sid);
/**
* spmi_command_shutdown() - sends SHUTDOWN command to the specified slave
* @ctrl: SPMI controller.
* @sid: slave identifier.
*
* The Shutdown command causes the Slave to enter the SHUTDOWN state.
*
* Returns
* -EINVAL for invalid slave identifier.
* -EPERM if the SPMI transaction is denied due to permission issues.
* -EIO if the SPMI transaction fails (parity errors, etc).
* -ETIMEDOUT if the SPMI transaction times out.
*/
extern int spmi_command_shutdown(struct spmi_controller *ctrl, u8 sid);
#endif