/* * RSB (Reduced Serial Bus) driver. * * Author: Chen-Yu Tsai * * This file is licensed under the terms of the GNU General Public License * version 2. This program is licensed "as is" without any warranty of any * kind, whether express or implied. * * The RSB controller looks like an SMBus controller which only supports * byte and word data transfers. But, it differs from standard SMBus * protocol on several aspects: * - it uses addresses set at runtime to address slaves. Runtime addresses * are sent to slaves using their 12bit hardware addresses. Up to 15 * runtime addresses are available. * - it adds a parity bit every 8bits of data and address for read and * write accesses; this replaces the ack bit * - only one read access is required to read a byte (instead of a write * followed by a read access in standard SMBus protocol) * - there's no Ack bit after each read access * * This means this bus cannot be used to interface with standard SMBus * devices. Devices known to support this interface include the AXP223, * AXP809, and AXP806 PMICs, and the AC100 audio codec, all from X-Powers. * * A description of the operation and wire protocol can be found in the * RSB section of Allwinner's A80 user manual, which can be found at * * https://github.com/allwinner-zh/documents/tree/master/A80 * * This document is officially released by Allwinner. * * This driver is based on i2c-sun6i-p2wi.c, the P2WI bus driver. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* RSB registers */ #define RSB_CTRL 0x0 /* Global control */ #define RSB_CCR 0x4 /* Clock control */ #define RSB_INTE 0x8 /* Interrupt controls */ #define RSB_INTS 0xc /* Interrupt status */ #define RSB_ADDR 0x10 /* Address to send with read/write command */ #define RSB_DATA 0x1c /* Data to read/write */ #define RSB_LCR 0x24 /* Line control */ #define RSB_DMCR 0x28 /* Device mode (init) control */ #define RSB_CMD 0x2c /* RSB Command */ #define RSB_DAR 0x30 /* Device address / runtime address */ /* CTRL fields */ #define RSB_CTRL_START_TRANS BIT(7) #define RSB_CTRL_ABORT_TRANS BIT(6) #define RSB_CTRL_GLOBAL_INT_ENB BIT(1) #define RSB_CTRL_SOFT_RST BIT(0) /* CLK CTRL fields */ #define RSB_CCR_SDA_OUT_DELAY(v) (((v) & 0x7) << 8) #define RSB_CCR_MAX_CLK_DIV 0xff #define RSB_CCR_CLK_DIV(v) ((v) & RSB_CCR_MAX_CLK_DIV) /* STATUS fields */ #define RSB_INTS_TRANS_ERR_ACK BIT(16) #define RSB_INTS_TRANS_ERR_DATA_BIT(v) (((v) >> 8) & 0xf) #define RSB_INTS_TRANS_ERR_DATA GENMASK(11, 8) #define RSB_INTS_LOAD_BSY BIT(2) #define RSB_INTS_TRANS_ERR BIT(1) #define RSB_INTS_TRANS_OVER BIT(0) /* LINE CTRL fields*/ #define RSB_LCR_SCL_STATE BIT(5) #define RSB_LCR_SDA_STATE BIT(4) #define RSB_LCR_SCL_CTL BIT(3) #define RSB_LCR_SCL_CTL_EN BIT(2) #define RSB_LCR_SDA_CTL BIT(1) #define RSB_LCR_SDA_CTL_EN BIT(0) /* DEVICE MODE CTRL field values */ #define RSB_DMCR_DEVICE_START BIT(31) #define RSB_DMCR_MODE_DATA (0x7c << 16) #define RSB_DMCR_MODE_REG (0x3e << 8) #define RSB_DMCR_DEV_ADDR 0x00 /* CMD values */ #define RSB_CMD_RD8 0x8b #define RSB_CMD_RD16 0x9c #define RSB_CMD_RD32 0xa6 #define RSB_CMD_WR8 0x4e #define RSB_CMD_WR16 0x59 #define RSB_CMD_WR32 0x63 #define RSB_CMD_STRA 0xe8 /* DAR fields */ #define RSB_DAR_RTA(v) (((v) & 0xff) << 16) #define RSB_DAR_DA(v) ((v) & 0xffff) #define RSB_MAX_FREQ 20000000 #define RSB_CTRL_NAME "sunxi-rsb" struct sunxi_rsb_addr_map { u16 hwaddr; u8 rtaddr; }; struct sunxi_rsb { struct device *dev; void __iomem *regs; struct clk *clk; struct reset_control *rstc; struct completion complete; struct mutex lock; unsigned int status; }; /* bus / slave device related functions */ static struct bus_type sunxi_rsb_bus; static int sunxi_rsb_device_match(struct device *dev, struct device_driver *drv) { return of_driver_match_device(dev, drv); } static int sunxi_rsb_device_probe(struct device *dev) { const struct sunxi_rsb_driver *drv = to_sunxi_rsb_driver(dev->driver); struct sunxi_rsb_device *rdev = to_sunxi_rsb_device(dev); int ret; if (!drv->probe) return -ENODEV; if (!rdev->irq) { int irq = -ENOENT; if (dev->of_node) irq = of_irq_get(dev->of_node, 0); if (irq == -EPROBE_DEFER) return irq; if (irq < 0) irq = 0; rdev->irq = irq; } ret = of_clk_set_defaults(dev->of_node, false); if (ret < 0) return ret; return drv->probe(rdev); } static int sunxi_rsb_device_remove(struct device *dev) { const struct sunxi_rsb_driver *drv = to_sunxi_rsb_driver(dev->driver); return drv->remove(to_sunxi_rsb_device(dev)); } static struct bus_type sunxi_rsb_bus = { .name = RSB_CTRL_NAME, .match = sunxi_rsb_device_match, .probe = sunxi_rsb_device_probe, .remove = sunxi_rsb_device_remove, .uevent = of_device_uevent_modalias, }; static void sunxi_rsb_dev_release(struct device *dev) { struct sunxi_rsb_device *rdev = to_sunxi_rsb_device(dev); kfree(rdev); } /** * sunxi_rsb_device_create() - allocate and add an RSB device * @rsb: RSB controller * @node: RSB slave device node * @hwaddr: RSB slave hardw
/*
 * internal.h  --  Voltage/Current Regulator framework internal code
 *
 * Copyright 2007, 2008 Wolfson Microelectronics PLC.
 * Copyright 2008 SlimLogic Ltd.
 *
 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
 *
 *  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.
 *
 */

#ifndef __REGULATOR_INTERNAL_H
#define __REGULATOR_INTERNAL_H

/*
 * struct regulator
 *
 * One for each consumer device.
 */
struct regulator {
	struct device *dev;
	struct list_head list;
	unsigned int always_on:1;
	unsigned int bypass:1;
	int uA_load;
	int min_uV;
	int max_uV;
	char *supply_name;
	struct device_attribute dev_attr;
	struct regulator_dev *rdev;
	struct dentry *debugfs;
};

#ifdef CONFIG_OF
struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
			         const struct regulator_desc *desc,
				 struct device_node **node);
#else
static inline struct regulator_init_data *
regulator_of_get_init_data(struct device *dev,
			   const struct regulator_desc *desc,
			   struct device_node **node)
{
	return NULL;
}
#endif

#endif
match_table, }, }; static int __init sunxi_rsb_init(void) { int ret; ret = bus_register(&sunxi_rsb_bus); if (ret) { pr_err("failed to register sunxi sunxi_rsb bus: %d\n", ret); return ret; } return platform_driver_register(&sunxi_rsb_driver); } module_init(sunxi_rsb_init); static void __exit sunxi_rsb_exit(void) { platform_driver_unregister(&sunxi_rsb_driver); bus_unregister(&sunxi_rsb_bus); } module_exit(sunxi_rsb_exit); MODULE_AUTHOR("Chen-Yu Tsai "); MODULE_DESCRIPTION("Allwinner sunXi Reduced Serial Bus controller driver"); MODULE_LICENSE("GPL v2");