1
0
Fork 0

Merge branch 'i2c/for-4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c updates from Wolfram Sang:

 - new drivers for Spreadtrum I2C, Intel Cherry Trail Whiskey Cove SMBUS

 - quite some driver updates

 - cleanups for the i2c-mux subsystem

 - some subsystem-wide constification

 - further cleanup of include/linux/i2c

* 'i2c/for-4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (50 commits)
  i2c: sprd: Fix undefined reference errors
  i2c: nomadik: constify amba_id
  i2c: versatile: Make i2c_algo_bit_data const
  i2c: busses: make i2c_adapter_quirks const
  i2c: busses: make i2c_adapter const
  i2c: busses: make i2c_algorithm const
  i2c: Add Spreadtrum I2C controller driver
  dt-bindings: i2c: Add Spreadtrum I2C controller documentation
  i2c-cht-wc: make cht_wc_i2c_adap_driver static
  MAINTAINERS: Add entry for drivers/i2c/busses/i2c-cht-wc.c
  i2c: aspeed: Retain delay/setup/hold values when configuring bus frequency
  dt-bindings: i2c: eeprom: Document vendor to be used and deprecated ones
  i2c: i801: Restore the presence state of P2SB PCI device after reading BAR
  MAINTAINERS: drop entry for Blackfin I2C and Sonic's email
  blackfin: merge the two TWI header files
  i2c: davinci: Preserve return value of devm_clk_get
  i2c: mediatek: Add i2c compatible for MediaTek MT7622
  dt-bindings: i2c: Add MediaTek MT7622 i2c binding
  dt-bindings: i2c: modify information formats
  i2c: mux: i2c-arb-gpio-challenge: allow compiling w/o OF support
  ...
zero-colors
Linus Torvalds 2017-09-09 14:18:40 -07:00
commit d2d8f51e28
71 changed files with 1594 additions and 531 deletions

View File

@ -16,8 +16,12 @@ Required properties:
"renesas,r1ex24002"
The following manufacturers values have been deprecated:
"at", "at24"
If there is no specific driver for <manufacturer>, a generic
driver based on <type> is selected. Possible types are:
device with <type> and manufacturer "atmel" should be used.
Possible types are:
"24c00", "24c01", "24c02", "24c04", "24c08", "24c16", "24c32", "24c64",
"24c128", "24c256", "24c512", "24c1024", "spd"

View File

@ -1,14 +1,15 @@
* Mediatek's I2C controller
* MediaTek's I2C controller
The Mediatek's I2C controller is used to interface with I2C devices.
The MediaTek's I2C controller is used to interface with I2C devices.
Required properties:
- compatible: value should be either of the following.
"mediatek,mt2701-i2c", "mediatek,mt6577-i2c": for Mediatek mt2701
"mediatek,mt6577-i2c": for i2c compatible with mt6577.
"mediatek,mt6589-i2c": for i2c compatible with mt6589.
"mediatek,mt7623-i2c", "mediatek,mt6577-i2c": for i2c compatible with mt7623.
"mediatek,mt8173-i2c": for i2c compatible with mt8173.
"mediatek,mt2701-i2c", "mediatek,mt6577-i2c": for MediaTek MT2701
"mediatek,mt6577-i2c": for MediaTek MT6577
"mediatek,mt6589-i2c": for MediaTek MT6589
"mediatek,mt7622-i2c": for MediaTek MT7622
"mediatek,mt7623-i2c", "mediatek,mt6577-i2c": for MediaTek MT7623
"mediatek,mt8173-i2c": for MediaTek MT8173
- reg: physical base address of the controller and dma base, length of memory
mapped region.
- interrupts: interrupt number to the cpu.

View File

@ -2,6 +2,8 @@ I2C for R-Car platforms
Required properties:
- compatible:
"renesas,i2c-r8a7743" if the device is a part of a R8A7743 SoC.
"renesas,i2c-r8a7745" if the device is a part of a R8A7745 SoC.
"renesas,i2c-r8a7778" if the device is a part of a R8A7778 SoC.
"renesas,i2c-r8a7779" if the device is a part of a R8A7779 SoC.
"renesas,i2c-r8a7790" if the device is a part of a R8A7790 SoC.
@ -12,7 +14,8 @@ Required properties:
"renesas,i2c-r8a7795" if the device is a part of a R8A7795 SoC.
"renesas,i2c-r8a7796" if the device is a part of a R8A7796 SoC.
"renesas,rcar-gen1-i2c" for a generic R-Car Gen1 compatible device.
"renesas,rcar-gen2-i2c" for a generic R-Car Gen2 compatible device.
"renesas,rcar-gen2-i2c" for a generic R-Car Gen2 or RZ/G1 compatible
device.
"renesas,rcar-gen3-i2c" for a generic R-Car Gen3 compatible device.
"renesas,i2c-rcar" (deprecated)

View File

@ -7,6 +7,7 @@ Required properties :
- reg : Offset and length of the register set for the device
- compatible: should be one of the following:
- "rockchip,rv1108-i2c": for rv1108
- "rockchip,rk3066-i2c": for rk3066
- "rockchip,rk3188-i2c": for rk3188
- "rockchip,rk3228-i2c": for rk3228

View File

@ -4,6 +4,8 @@ Required properties:
- compatible :
- "renesas,iic-r8a73a4" (R-Mobile APE6)
- "renesas,iic-r8a7740" (R-Mobile A1)
- "renesas,iic-r8a7743" (RZ/G1M)
- "renesas,iic-r8a7745" (RZ/G1E)
- "renesas,iic-r8a7790" (R-Car H2)
- "renesas,iic-r8a7791" (R-Car M2-W)
- "renesas,iic-r8a7792" (R-Car V2H)
@ -12,7 +14,8 @@ Required properties:
- "renesas,iic-r8a7795" (R-Car H3)
- "renesas,iic-r8a7796" (R-Car M3-W)
- "renesas,iic-sh73a0" (SH-Mobile AG5)
- "renesas,rcar-gen2-iic" (generic R-Car Gen2 compatible device)
- "renesas,rcar-gen2-iic" (generic R-Car Gen2 or RZ/G1
compatible device)
- "renesas,rcar-gen3-iic" (generic R-Car Gen3 compatible device)
- "renesas,rmobile-iic" (generic device)

View File

@ -0,0 +1,31 @@
I2C for Spreadtrum platforms
Required properties:
- compatible: Should be "sprd,sc9860-i2c".
- reg: Specify the physical base address of the controller and length
of memory mapped region.
- interrupts: Should contain I2C interrupt.
- clock-names: Should contain following entries:
"i2c" for I2C clock,
"source" for I2C source (parent) clock,
"enable" for I2C module enable clock.
- clocks: Should contain a clock specifier for each entry in clock-names.
- clock-frequency: Constains desired I2C bus clock frequency in Hz.
- #address-cells: Should be 1 to describe address cells for I2C device address.
- #size-cells: Should be 0 means no size cell for I2C device address.
Optional properties:
- Child nodes conforming to I2C bus binding
Examples:
i2c0: i2c@70500000 {
compatible = "sprd,sc9860-i2c";
reg = <0 0x70500000 0 0x1000>;
interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "i2c", "source", "enable";
clocks = <&clk_i2c3>, <&ext_26m>, <&clk_ap_apb_gates 11>;
clock-frequency = <400000>;
#address-cells = <1>;
#size-cells = <0>;
};

View File

@ -42,6 +42,10 @@ i2c-arb-gpio-challenge Parent-locked
i2c-mux-gpio Normally parent-locked, mux-locked iff
all involved gpio pins are controlled by the
same i2c root adapter that they mux.
i2c-mux-gpmux Normally parent-locked, mux-locked iff
specified in device-tree.
i2c-mux-ltc4306 Mux-locked
i2c-mux-mlxcpld Parent-locked
i2c-mux-pca9541 Parent-locked
i2c-mux-pca954x Parent-locked
i2c-mux-pinctrl Normally parent-locked, mux-locked iff
@ -50,9 +54,11 @@ i2c-mux-pinctrl Normally parent-locked, mux-locked iff
i2c-mux-reg Parent-locked
In drivers/iio/
gyro/mpu3050 Mux-locked
imu/inv_mpu6050/ Mux-locked
In drivers/media/
dvb-frontends/lgdt3306a Mux-locked
dvb-frontends/m88ds3103 Parent-locked
dvb-frontends/rtl2830 Parent-locked
dvb-frontends/rtl2832 Mux-locked

View File

@ -2575,13 +2575,6 @@ W: http://blackfin.uclinux.org
S: Supported
F: drivers/net/ethernet/adi/
BLACKFIN I2C TWI DRIVER
M: Sonic Zhang <sonic.zhang@analog.com>
L: adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers)
W: http://blackfin.uclinux.org/
S: Supported
F: drivers/i2c/busses/i2c-bfin-twi.c
BLACKFIN MEDIA DRIVER
M: Scott Jiang <scott.jiang.linux@gmail.com>
L: adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers)
@ -2598,14 +2591,12 @@ S: Supported
F: drivers/rtc/rtc-bfin.c
BLACKFIN SDH DRIVER
M: Sonic Zhang <sonic.zhang@analog.com>
L: adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers)
W: http://blackfin.uclinux.org
S: Supported
F: drivers/mmc/host/bfin_sdh.c
BLACKFIN SERIAL DRIVER
M: Sonic Zhang <sonic.zhang@analog.com>
L: adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers)
W: http://blackfin.uclinux.org
S: Supported
@ -6441,6 +6432,12 @@ F: drivers/i2c/busses/i2c-sis96x.c
F: drivers/i2c/busses/i2c-via.c
F: drivers/i2c/busses/i2c-viapro.c
I2C/SMBUS INTEL CHT WHISKEY COVE PMIC DRIVER
M: Hans de Goede <hdegoede@redhat.com>
L: linux-i2c@vger.kernel.org
S: Maintained
F: drivers/i2c/busses/i2c-cht-wc.c
I2C/SMBUS ISMT DRIVER
M: Seth Heasley <seth.heasley@intel.com>
M: Neil Horman <nhorman@tuxdriver.com>

View File

@ -1,7 +1,7 @@
/*
* bfin_twi.h - interface to Blackfin TWIs
*
* Copyright 2005-2010 Analog Devices Inc.
* Copyright 2005-2014 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
@ -10,6 +10,138 @@
#define __ASM_BFIN_TWI_H__
#include <asm/blackfin.h>
#include <linux/types.h>
#include <linux/i2c.h>
/*
* ADI twi registers layout
*/
struct bfin_twi_regs {
u16 clkdiv;
u16 dummy1;
u16 control;
u16 dummy2;
u16 slave_ctl;
u16 dummy3;
u16 slave_stat;
u16 dummy4;
u16 slave_addr;
u16 dummy5;
u16 master_ctl;
u16 dummy6;
u16 master_stat;
u16 dummy7;
u16 master_addr;
u16 dummy8;
u16 int_stat;
u16 dummy9;
u16 int_mask;
u16 dummy10;
u16 fifo_ctl;
u16 dummy11;
u16 fifo_stat;
u16 dummy12;
u32 __pad[20];
u16 xmt_data8;
u16 dummy13;
u16 xmt_data16;
u16 dummy14;
u16 rcv_data8;
u16 dummy15;
u16 rcv_data16;
u16 dummy16;
};
struct bfin_twi_iface {
int irq;
spinlock_t lock;
char read_write;
u8 command;
u8 *transPtr;
int readNum;
int writeNum;
int cur_mode;
int manual_stop;
int result;
struct i2c_adapter adap;
struct completion complete;
struct i2c_msg *pmsg;
int msg_num;
int cur_msg;
u16 saved_clkdiv;
u16 saved_control;
struct bfin_twi_regs __iomem *regs_base;
};
/* ******************** TWO-WIRE INTERFACE (TWI) MASKS ********************/
/* TWI_CLKDIV Macros (Use: *pTWI_CLKDIV = CLKLOW(x)|CLKHI(y); ) */
#define CLKLOW(x) ((x) & 0xFF) /* Periods Clock Is Held Low */
#define CLKHI(y) (((y)&0xFF)<<0x8) /* Periods Before New Clock Low */
/* TWI_PRESCALE Masks */
#define PRESCALE 0x007F /* SCLKs Per Internal Time Reference (10MHz) */
#define TWI_ENA 0x0080 /* TWI Enable */
#define SCCB 0x0200 /* SCCB Compatibility Enable */
/* TWI_SLAVE_CTL Masks */
#define SEN 0x0001 /* Slave Enable */
#define SADD_LEN 0x0002 /* Slave Address Length */
#define STDVAL 0x0004 /* Slave Transmit Data Valid */
#define NAK 0x0008 /* NAK Generated At Conclusion Of Transfer */
#define GEN 0x0010 /* General Call Address Matching Enabled */
/* TWI_SLAVE_STAT Masks */
#define SDIR 0x0001 /* Slave Transfer Direction (RX/TX*) */
#define GCALL 0x0002 /* General Call Indicator */
/* TWI_MASTER_CTL Masks */
#define MEN 0x0001 /* Master Mode Enable */
#define MADD_LEN 0x0002 /* Master Address Length */
#define MDIR 0x0004 /* Master Transmit Direction (RX/TX*) */
#define FAST 0x0008 /* Use Fast Mode Timing Specs */
#define STOP 0x0010 /* Issue Stop Condition */
#define RSTART 0x0020 /* Repeat Start or Stop* At End Of Transfer */
#define DCNT 0x3FC0 /* Data Bytes To Transfer */
#define SDAOVR 0x4000 /* Serial Data Override */
#define SCLOVR 0x8000 /* Serial Clock Override */
/* TWI_MASTER_STAT Masks */
#define MPROG 0x0001 /* Master Transfer In Progress */
#define LOSTARB 0x0002 /* Lost Arbitration Indicator (Xfer Aborted) */
#define ANAK 0x0004 /* Address Not Acknowledged */
#define DNAK 0x0008 /* Data Not Acknowledged */
#define BUFRDERR 0x0010 /* Buffer Read Error */
#define BUFWRERR 0x0020 /* Buffer Write Error */
#define SDASEN 0x0040 /* Serial Data Sense */
#define SCLSEN 0x0080 /* Serial Clock Sense */
#define BUSBUSY 0x0100 /* Bus Busy Indicator */
/* TWI_INT_SRC and TWI_INT_ENABLE Masks */
#define SINIT 0x0001 /* Slave Transfer Initiated */
#define SCOMP 0x0002 /* Slave Transfer Complete */
#define SERR 0x0004 /* Slave Transfer Error */
#define SOVF 0x0008 /* Slave Overflow */
#define MCOMP 0x0010 /* Master Transfer Complete */
#define MERR 0x0020 /* Master Transfer Error */
#define XMTSERV 0x0040 /* Transmit FIFO Service */
#define RCVSERV 0x0080 /* Receive FIFO Service */
/* TWI_FIFO_CTRL Masks */
#define XMTFLUSH 0x0001 /* Transmit Buffer Flush */
#define RCVFLUSH 0x0002 /* Receive Buffer Flush */
#define XMTINTLEN 0x0004 /* Transmit Buffer Interrupt Length */
#define RCVINTLEN 0x0008 /* Receive Buffer Interrupt Length */
/* TWI_FIFO_STAT Masks */
#define XMTSTAT 0x0003 /* Transmit FIFO Status */
#define XMT_EMPTY 0x0000 /* Transmit FIFO Empty */
#define XMT_HALF 0x0001 /* Transmit FIFO Has 1 Byte To Write */
#define XMT_FULL 0x0003 /* Transmit FIFO Full (2 Bytes To Write) */
#define RCVSTAT 0x000C /* Receive FIFO Status */
#define RCV_EMPTY 0x0000 /* Receive FIFO Empty */
#define RCV_HALF 0x0004 /* Receive FIFO Has 1 Byte To Read */
#define RCV_FULL 0x000C /* Receive FIFO Full (2 Bytes To Read) */
#define DEFINE_TWI_REG(reg_name, reg) \
static inline u16 read_##reg_name(struct bfin_twi_iface *iface) \

View File

@ -10,7 +10,6 @@
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i2c/bfin_twi.h>
#include <linux/gpio.h>
#include <asm/blackfin.h>

View File

@ -11,7 +11,7 @@
*/
#include <linux/gpio.h>
#include <linux/i2c/tc35876x.h>
#include <linux/platform_data/tc35876x.h>
#include <asm/intel-mid.h>
/*tc35876x DSI_LVDS bridge chip and panel platform data*/

View File

@ -26,7 +26,7 @@
#include "mdfld_output.h"
#include "mdfld_dsi_pkg_sender.h"
#include "tc35876x-dsi-lvds.h"
#include <linux/i2c/tc35876x.h>
#include <linux/platform_data/tc35876x.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/intel_scu_ipc.h>

View File

@ -189,6 +189,14 @@ config I2C_PIIX4
This driver can also be built as a module. If so, the module
will be called i2c-piix4.
config I2C_CHT_WC
tristate "Intel Cherry Trail Whiskey Cove PMIC smbus controller"
depends on INTEL_SOC_PMIC_CHTWC
help
If you say yes to this option, support will be included for the
SMBus controller found in the Intel Cherry Trail Whiskey Cove PMIC
found on some Intel Cherry Trail systems.
config I2C_NFORCE2
tristate "Nvidia nForce2, nForce3 and nForce4"
depends on PCI
@ -900,6 +908,13 @@ config I2C_SIRF
This driver can also be built as a module. If so, the module
will be called i2c-sirf.
config I2C_SPRD
bool "Spreadtrum I2C interface"
depends on I2C=y && ARCH_SPRD
help
If you say yes to this option, support will be included for the
Spreadtrum I2C interface.
config I2C_ST
tristate "STMicroelectronics SSC I2C support"
depends on ARCH_STI

View File

@ -12,6 +12,7 @@ obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o
obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o
obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o
obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o
obj-$(CONFIG_I2C_CHT_WC) += i2c-cht-wc.o
obj-$(CONFIG_I2C_I801) += i2c-i801.o
obj-$(CONFIG_I2C_ISCH) += i2c-isch.o
obj-$(CONFIG_I2C_ISMT) += i2c-ismt.o
@ -89,6 +90,7 @@ obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o
obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o
obj-$(CONFIG_I2C_SIRF) += i2c-sirf.o
obj-$(CONFIG_I2C_SPRD) += i2c-sprd.o
obj-$(CONFIG_I2C_ST) += i2c-st.o
obj-$(CONFIG_I2C_STM32F4) += i2c-stm32f4.o
obj-$(CONFIG_I2C_STU300) += i2c-stu300.o

View File

@ -53,6 +53,9 @@
#define ASPEED_I2CD_MASTER_EN BIT(0)
/* 0x04 : I2CD Clock and AC Timing Control Register #1 */
#define ASPEED_I2CD_TIME_TBUF_MASK GENMASK(31, 28)
#define ASPEED_I2CD_TIME_THDSTA_MASK GENMASK(27, 24)
#define ASPEED_I2CD_TIME_TACST_MASK GENMASK(23, 20)
#define ASPEED_I2CD_TIME_SCL_HIGH_SHIFT 16
#define ASPEED_I2CD_TIME_SCL_HIGH_MASK GENMASK(19, 16)
#define ASPEED_I2CD_TIME_SCL_LOW_SHIFT 12
@ -132,6 +135,7 @@ struct aspeed_i2c_bus {
/* Synchronizes I/O mem access to base. */
spinlock_t lock;
struct completion cmd_complete;
u32 (*get_clk_reg_val)(u32 divisor);
unsigned long parent_clk_frequency;
u32 bus_frequency;
/* Transaction state. */
@ -675,7 +679,7 @@ static const struct i2c_algorithm aspeed_i2c_algo = {
#endif /* CONFIG_I2C_SLAVE */
};
static u32 aspeed_i2c_get_clk_reg_val(u32 divisor)
static u32 aspeed_i2c_get_clk_reg_val(u32 clk_high_low_max, u32 divisor)
{
u32 base_clk, clk_high, clk_low, tmp;
@ -695,16 +699,22 @@ static u32 aspeed_i2c_get_clk_reg_val(u32 divisor)
* Thus,
* SCL_freq = APB_freq /
* ((1 << base_clk) * (clk_high + 1 + clk_low + 1))
* The documentation recommends clk_high >= 8 and clk_low >= 7 when
* possible; this last constraint gives us the following solution:
* The documentation recommends clk_high >= clk_high_max / 2 and
* clk_low >= clk_low_max / 2 - 1 when possible; this last constraint
* gives us the following solution:
*/
base_clk = divisor > 33 ? ilog2((divisor - 1) / 32) + 1 : 0;
tmp = divisor / (1 << base_clk);
clk_high = tmp / 2 + tmp % 2;
clk_low = tmp - clk_high;
base_clk = divisor > clk_high_low_max ?
ilog2((divisor - 1) / clk_high_low_max) + 1 : 0;
tmp = (divisor + (1 << base_clk) - 1) >> base_clk;
clk_low = tmp / 2;
clk_high = tmp - clk_low;
if (clk_high)
clk_high--;
if (clk_low)
clk_low--;
clk_high -= 1;
clk_low -= 1;
return ((clk_high << ASPEED_I2CD_TIME_SCL_HIGH_SHIFT)
& ASPEED_I2CD_TIME_SCL_HIGH_MASK)
@ -713,13 +723,35 @@ static u32 aspeed_i2c_get_clk_reg_val(u32 divisor)
| (base_clk & ASPEED_I2CD_TIME_BASE_DIVISOR_MASK);
}
static u32 aspeed_i2c_24xx_get_clk_reg_val(u32 divisor)
{
/*
* clk_high and clk_low are each 3 bits wide, so each can hold a max
* value of 8 giving a clk_high_low_max of 16.
*/
return aspeed_i2c_get_clk_reg_val(16, divisor);
}
static u32 aspeed_i2c_25xx_get_clk_reg_val(u32 divisor)
{
/*
* clk_high and clk_low are each 4 bits wide, so each can hold a max
* value of 16 giving a clk_high_low_max of 32.
*/
return aspeed_i2c_get_clk_reg_val(32, divisor);
}
/* precondition: bus.lock has been acquired. */
static int aspeed_i2c_init_clk(struct aspeed_i2c_bus *bus)
{
u32 divisor, clk_reg_val;
divisor = bus->parent_clk_frequency / bus->bus_frequency;
clk_reg_val = aspeed_i2c_get_clk_reg_val(divisor);
divisor = DIV_ROUND_UP(bus->parent_clk_frequency, bus->bus_frequency);
clk_reg_val = readl(bus->base + ASPEED_I2C_AC_TIMING_REG1);
clk_reg_val &= (ASPEED_I2CD_TIME_TBUF_MASK |
ASPEED_I2CD_TIME_THDSTA_MASK |
ASPEED_I2CD_TIME_TACST_MASK);
clk_reg_val |= bus->get_clk_reg_val(divisor);
writel(clk_reg_val, bus->base + ASPEED_I2C_AC_TIMING_REG1);
writel(ASPEED_NO_TIMEOUT_CTRL, bus->base + ASPEED_I2C_AC_TIMING_REG2);
@ -778,8 +810,22 @@ static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus)
return ret;
}
static const struct of_device_id aspeed_i2c_bus_of_table[] = {
{
.compatible = "aspeed,ast2400-i2c-bus",
.data = aspeed_i2c_24xx_get_clk_reg_val,
},
{
.compatible = "aspeed,ast2500-i2c-bus",
.data = aspeed_i2c_25xx_get_clk_reg_val,
},
{ },
};
MODULE_DEVICE_TABLE(of, aspeed_i2c_bus_of_table);
static int aspeed_i2c_probe_bus(struct platform_device *pdev)
{
const struct of_device_id *match;
struct aspeed_i2c_bus *bus;
struct clk *parent_clk;
struct resource *res;
@ -809,6 +855,12 @@ static int aspeed_i2c_probe_bus(struct platform_device *pdev)
bus->bus_frequency = 100000;
}
match = of_match_node(aspeed_i2c_bus_of_table, pdev->dev.of_node);
if (!match)
bus->get_clk_reg_val = aspeed_i2c_24xx_get_clk_reg_val;
else
bus->get_clk_reg_val = match->data;
/* Initialize the I2C adapter */
spin_lock_init(&bus->lock);
init_completion(&bus->cmd_complete);
@ -870,13 +922,6 @@ static int aspeed_i2c_remove_bus(struct platform_device *pdev)
return 0;
}
static const struct of_device_id aspeed_i2c_bus_of_table[] = {
{ .compatible = "aspeed,ast2400-i2c-bus", },
{ .compatible = "aspeed,ast2500-i2c-bus", },
{ },
};
MODULE_DEVICE_TABLE(of, aspeed_i2c_bus_of_table);
static struct platform_driver aspeed_i2c_bus_driver = {
.probe = aspeed_i2c_probe_bus,
.remove = aspeed_i2c_remove_bus,

View File

@ -809,7 +809,7 @@ out:
* The hardware can handle at most two messages concatenated by a
* repeated start via it's internal address feature.
*/
static struct i2c_adapter_quirks at91_twi_quirks = {
static const struct i2c_adapter_quirks at91_twi_quirks = {
.flags = I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST | I2C_AQ_COMB_SAME_ADDR,
.max_comb_1st_msg_len = 3,
};

View File

@ -510,8 +510,7 @@ static int bcm_iproc_i2c_remove(struct platform_device *pdev)
static int bcm_iproc_i2c_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct bcm_iproc_i2c_dev *iproc_i2c = platform_get_drvdata(pdev);
struct bcm_iproc_i2c_dev *iproc_i2c = dev_get_drvdata(dev);
/* make sure there's no pending interrupt when we go into suspend */
writel(0, iproc_i2c->base + IE_OFFSET);
@ -526,8 +525,7 @@ static int bcm_iproc_i2c_suspend(struct device *dev)
static int bcm_iproc_i2c_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct bcm_iproc_i2c_dev *iproc_i2c = platform_get_drvdata(pdev);
struct bcm_iproc_i2c_dev *iproc_i2c = dev_get_drvdata(dev);
int ret;
u32 val;

View File

@ -21,7 +21,6 @@
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/i2c/bfin_twi.h>
#include <asm/irq.h>
#include <asm/portmux.h>

View File

@ -826,8 +826,7 @@ static int cdns_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long
*/
static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct cdns_i2c *xi2c = platform_get_drvdata(pdev);
struct cdns_i2c *xi2c = dev_get_drvdata(dev);
clk_disable(xi2c->clk);
@ -844,8 +843,7 @@ static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev)
*/
static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct cdns_i2c *xi2c = platform_get_drvdata(pdev);
struct cdns_i2c *xi2c = dev_get_drvdata(dev);
int ret;
ret = clk_enable(xi2c->clk);

View File

@ -0,0 +1,363 @@
/*
* Intel CHT Whiskey Cove PMIC I2C Master driver
* Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
*
* Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
* Copyright (C) 2011 - 2014 Intel Corporation. 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 as published by the Free Software Foundation, or (at your option)
* any later version.
*
* 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.
*/
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/mfd/intel_soc_pmic.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#define CHT_WC_I2C_CTRL 0x5e24
#define CHT_WC_I2C_CTRL_WR BIT(0)
#define CHT_WC_I2C_CTRL_RD BIT(1)
#define CHT_WC_I2C_CLIENT_ADDR 0x5e25
#define CHT_WC_I2C_REG_OFFSET 0x5e26
#define CHT_WC_I2C_WRDATA 0x5e27
#define CHT_WC_I2C_RDDATA 0x5e28
#define CHT_WC_EXTCHGRIRQ 0x6e0a
#define CHT_WC_EXTCHGRIRQ_CLIENT_IRQ BIT(0)
#define CHT_WC_EXTCHGRIRQ_WRITE_IRQ BIT(1)
#define CHT_WC_EXTCHGRIRQ_READ_IRQ BIT(2)
#define CHT_WC_EXTCHGRIRQ_NACK_IRQ BIT(3)
#define CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK ((u8)GENMASK(3, 1))
#define CHT_WC_EXTCHGRIRQ_MSK 0x6e17
struct cht_wc_i2c_adap {
struct i2c_adapter adapter;
wait_queue_head_t wait;
struct irq_chip irqchip;
struct mutex adap_lock;
struct mutex irqchip_lock;
struct regmap *regmap;
struct irq_domain *irq_domain;
struct i2c_client *client;
int client_irq;
u8 irq_mask;
u8 old_irq_mask;
int read_data;
bool io_error;
bool done;
};
static irqreturn_t cht_wc_i2c_adap_thread_handler(int id, void *data)
{
struct cht_wc_i2c_adap *adap = data;
int ret, reg;
mutex_lock(&adap->adap_lock);
/* Read IRQs */
ret = regmap_read(adap->regmap, CHT_WC_EXTCHGRIRQ, &reg);
if (ret) {
dev_err(&adap->adapter.dev, "Error reading extchgrirq reg\n");
mutex_unlock(&adap->adap_lock);
return IRQ_NONE;
}
reg &= ~adap->irq_mask;
/* Reads must be acked after reading the received data. */
ret = regmap_read(adap->regmap, CHT_WC_I2C_RDDATA, &adap->read_data);
if (ret)
adap->io_error = true;
/*
* Immediately ack IRQs, so that if new IRQs arrives while we're
* handling the previous ones our irq will re-trigger when we're done.
*/
ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ, reg);
if (ret)
dev_err(&adap->adapter.dev, "Error writing extchgrirq reg\n");
if (reg & CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK) {
adap->io_error |= !!(reg & CHT_WC_EXTCHGRIRQ_NACK_IRQ);
adap->done = true;
}
mutex_unlock(&adap->adap_lock);
if (reg & CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK)
wake_up(&adap->wait);
/*
* Do NOT use handle_nested_irq here, the client irq handler will
* likely want to do i2c transfers and the i2c controller uses this
* interrupt handler as well, so running the client irq handler from
* this thread will cause things to lock up.
*/
if (reg & CHT_WC_EXTCHGRIRQ_CLIENT_IRQ) {
/*
* generic_handle_irq expects local IRQs to be disabled
* as normally it is called from interrupt context.
*/
local_irq_disable();
generic_handle_irq(adap->client_irq);
local_irq_enable();
}
return IRQ_HANDLED;
}
static u32 cht_wc_i2c_adap_master_func(struct i2c_adapter *adap)
{
/* This i2c adapter only supports SMBUS byte transfers */
return I2C_FUNC_SMBUS_BYTE_DATA;
}
static int cht_wc_i2c_adap_smbus_xfer(struct i2c_adapter *_adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size,
union i2c_smbus_data *data)
{
struct cht_wc_i2c_adap *adap = i2c_get_adapdata(_adap);
int ret;
mutex_lock(&adap->adap_lock);
adap->io_error = false;
adap->done = false;
mutex_unlock(&adap->adap_lock);
ret = regmap_write(adap->regmap, CHT_WC_I2C_CLIENT_ADDR, addr);
if (ret)
return ret;
if (read_write == I2C_SMBUS_WRITE) {
ret = regmap_write(adap->regmap, CHT_WC_I2C_WRDATA, data->byte);
if (ret)
return ret;
}
ret = regmap_write(adap->regmap, CHT_WC_I2C_REG_OFFSET, command);
if (ret)
return ret;
ret = regmap_write(adap->regmap, CHT_WC_I2C_CTRL,
(read_write == I2C_SMBUS_WRITE) ?
CHT_WC_I2C_CTRL_WR : CHT_WC_I2C_CTRL_RD);
if (ret)
return ret;
ret = wait_event_timeout(adap->wait, adap->done, msecs_to_jiffies(30));
if (ret == 0) {
/*
* The CHT GPIO controller serializes all IRQs, sometimes
* causing significant delays, check status manually.
*/
cht_wc_i2c_adap_thread_handler(0, adap);
if (!adap->done)
return -ETIMEDOUT;
}
ret = 0;
mutex_lock(&adap->adap_lock);
if (adap->io_error)
ret = -EIO;
else if (read_write == I2C_SMBUS_READ)
data->byte = adap->read_data;
mutex_unlock(&adap->adap_lock);
return ret;
}
static const struct i2c_algorithm cht_wc_i2c_adap_algo = {
.functionality = cht_wc_i2c_adap_master_func,
.smbus_xfer = cht_wc_i2c_adap_smbus_xfer,
};
/**** irqchip for the client connected to the extchgr i2c adapter ****/
static void cht_wc_i2c_irq_lock(struct irq_data *data)
{
struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
mutex_lock(&adap->irqchip_lock);
}
static void cht_wc_i2c_irq_sync_unlock(struct irq_data *data)
{
struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
int ret;
if (adap->irq_mask != adap->old_irq_mask) {
ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ_MSK,
adap->irq_mask);
if (ret == 0)
adap->old_irq_mask = adap->irq_mask;
else
dev_err(&adap->adapter.dev, "Error writing EXTCHGRIRQ_MSK\n");
}
mutex_unlock(&adap->irqchip_lock);
}
static void cht_wc_i2c_irq_enable(struct irq_data *data)
{
struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
adap->irq_mask &= ~CHT_WC_EXTCHGRIRQ_CLIENT_IRQ;
}
static void cht_wc_i2c_irq_disable(struct irq_data *data)
{
struct cht_wc_i2c_adap *adap = irq_data_get_irq_chip_data(data);
adap->irq_mask |= CHT_WC_EXTCHGRIRQ_CLIENT_IRQ;
}
static const struct irq_chip cht_wc_i2c_irq_chip = {
.irq_bus_lock = cht_wc_i2c_irq_lock,
.irq_bus_sync_unlock = cht_wc_i2c_irq_sync_unlock,
.irq_disable = cht_wc_i2c_irq_disable,
.irq_enable = cht_wc_i2c_irq_enable,
.name = "cht_wc_ext_chrg_irq_chip",
};
static const struct property_entry bq24190_props[] = {
PROPERTY_ENTRY_STRING("extcon-name", "cht_wcove_pwrsrc"),
PROPERTY_ENTRY_BOOL("omit-battery-class"),
PROPERTY_ENTRY_BOOL("disable-reset"),
{ }
};
static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev)
{
struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
struct cht_wc_i2c_adap *adap;
struct i2c_board_info board_info = {
.type = "bq24190",
.addr = 0x6b,
.properties = bq24190_props,
};
int ret, reg, irq;
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "Error missing irq resource\n");
return -EINVAL;
}
adap = devm_kzalloc(&pdev->dev, sizeof(*adap), GFP_KERNEL);
if (!adap)
return -ENOMEM;
init_waitqueue_head(&adap->wait);
mutex_init(&adap->adap_lock);
mutex_init(&adap->irqchip_lock);
adap->irqchip = cht_wc_i2c_irq_chip;
adap->regmap = pmic->regmap;
adap->adapter.owner = THIS_MODULE;
adap->adapter.class = I2C_CLASS_HWMON;
adap->adapter.algo = &cht_wc_i2c_adap_algo;
strlcpy(adap->adapter.name, "PMIC I2C Adapter",
sizeof(adap->adapter.name));
adap->adapter.dev.parent = &pdev->dev;
/* Clear and activate i2c-adapter interrupts, disable client IRQ */
adap->old_irq_mask = adap->irq_mask = ~CHT_WC_EXTCHGRIRQ_ADAP_IRQMASK;
ret = regmap_read(adap->regmap, CHT_WC_I2C_RDDATA, &reg);
if (ret)
return ret;
ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ, ~adap->irq_mask);
if (ret)
return ret;
ret = regmap_write(adap->regmap, CHT_WC_EXTCHGRIRQ_MSK, adap->irq_mask);
if (ret)
return ret;
/* Alloc and register client IRQ */
adap->irq_domain = irq_domain_add_linear(pdev->dev.of_node, 1,
&irq_domain_simple_ops, NULL);
if (!adap->irq_domain)
return -ENOMEM;
adap->client_irq = irq_create_mapping(adap->irq_domain, 0);
if (!adap->client_irq) {
ret = -ENOMEM;
goto remove_irq_domain;
}
irq_set_chip_data(adap->client_irq, adap);
irq_set_chip_and_handler(adap->client_irq, &adap->irqchip,
handle_simple_irq);
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
cht_wc_i2c_adap_thread_handler,
IRQF_ONESHOT, "PMIC I2C Adapter", adap);
if (ret)
goto remove_irq_domain;
i2c_set_adapdata(&adap->adapter, adap);
ret = i2c_add_adapter(&adap->adapter);
if (ret)
goto remove_irq_domain;
board_info.irq = adap->client_irq;
adap->client = i2c_new_device(&adap->adapter, &board_info);
if (!adap->client) {
ret = -ENOMEM;
goto del_adapter;
}
platform_set_drvdata(pdev, adap);
return 0;
del_adapter:
i2c_del_adapter(&adap->adapter);
remove_irq_domain:
irq_domain_remove(adap->irq_domain);
return ret;
}
static int cht_wc_i2c_adap_i2c_remove(struct platform_device *pdev)
{
struct cht_wc_i2c_adap *adap = platform_get_drvdata(pdev);
i2c_unregister_device(adap->client);
i2c_del_adapter(&adap->adapter);
irq_domain_remove(adap->irq_domain);
return 0;
}
static struct platform_device_id cht_wc_i2c_adap_id_table[] = {
{ .name = "cht_wcove_ext_chgr" },
{},
};
MODULE_DEVICE_TABLE(platform, cht_wc_i2c_adap_id_table);
static struct platform_driver cht_wc_i2c_adap_driver = {
.probe = cht_wc_i2c_adap_i2c_probe,
.remove = cht_wc_i2c_adap_i2c_remove,
.driver = {
.name = "cht_wcove_ext_chgr",
},
.id_table = cht_wc_i2c_adap_id_table,
};
module_platform_driver(cht_wc_i2c_adap_driver);
MODULE_DESCRIPTION("Intel CHT Whiskey Cove PMIC I2C Master driver");
MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
MODULE_LICENSE("GPL");

View File

@ -413,7 +413,7 @@ static const struct i2c_algorithm cpm_i2c_algo = {
};
/* CPM_MAX_READ is also limiting writes according to the code! */
static struct i2c_adapter_quirks cpm_i2c_quirks = {
static const struct i2c_adapter_quirks cpm_i2c_quirks = {
.max_num_msgs = CPM_MAXBD,
.max_read_len = CPM_MAX_READ,
.max_write_len = CPM_MAX_READ,

View File

@ -733,7 +733,7 @@ static inline void i2c_davinci_cpufreq_deregister(struct davinci_i2c_dev *dev)
}
#endif
static struct i2c_algorithm i2c_davinci_algo = {
static const struct i2c_algorithm i2c_davinci_algo = {
.master_xfer = i2c_davinci_xfer,
.functionality = i2c_davinci_func,
};
@ -801,7 +801,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
dev->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(dev->clk))
return -ENODEV;
return PTR_ERR(dev->clk);
clk_prepare_enable(dev->clk);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@ -876,8 +876,7 @@ static int davinci_i2c_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
static int davinci_i2c_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct davinci_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
struct davinci_i2c_dev *i2c_dev = dev_get_drvdata(dev);
/* put I2C into reset */
davinci_i2c_reset_ctrl(i2c_dev, 0);
@ -888,8 +887,7 @@ static int davinci_i2c_suspend(struct device *dev)
static int davinci_i2c_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct davinci_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
struct davinci_i2c_dev *i2c_dev = dev_get_drvdata(dev);
clk_prepare_enable(i2c_dev->clk);
/* take I2C out of reset */

View File

@ -439,8 +439,7 @@ static void dw_i2c_plat_complete(struct device *dev)
#ifdef CONFIG_PM
static int dw_i2c_plat_runtime_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
struct dw_i2c_dev *i_dev = dev_get_drvdata(dev);
i_dev->disable(i_dev);
i2c_dw_plat_prepare_clk(i_dev, false);
@ -450,8 +449,7 @@ static int dw_i2c_plat_runtime_suspend(struct device *dev)
static int dw_i2c_plat_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
struct dw_i2c_dev *i_dev = dev_get_drvdata(dev);
i2c_dw_plat_prepare_clk(i_dev, true);
i_dev->init(i_dev);

View File

@ -346,7 +346,7 @@ static irqreturn_t i2c_dw_isr_slave(int this_irq, void *dev_id)
return IRQ_RETVAL(ret);
}
static struct i2c_algorithm i2c_dw_algo = {
static const struct i2c_algorithm i2c_dw_algo = {
.functionality = i2c_dw_func,
.reg_slave = i2c_dw_reg_slave,
.unreg_slave = i2c_dw_unreg_slave,

View File

@ -803,8 +803,7 @@ static int exynos5_i2c_remove(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static int exynos5_i2c_suspend_noirq(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct exynos5_i2c *i2c = platform_get_drvdata(pdev);
struct exynos5_i2c *i2c = dev_get_drvdata(dev);
i2c->suspended = 1;
@ -815,8 +814,7 @@ static int exynos5_i2c_suspend_noirq(struct device *dev)
static int exynos5_i2c_resume_noirq(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct exynos5_i2c *i2c = platform_get_drvdata(pdev);
struct exynos5_i2c *i2c = dev_get_drvdata(dev);
int ret = 0;
ret = clk_prepare_enable(i2c->clk);

View File

@ -98,8 +98,8 @@ static int of_i2c_gpio_get_pins(struct device_node *np,
return -EPROBE_DEFER;
if (!gpio_is_valid(*sda_pin) || !gpio_is_valid(*scl_pin)) {
pr_err("%s: invalid GPIO pins, sda=%d/scl=%d\n",
np->full_name, *sda_pin, *scl_pin);
pr_err("%pOF: invalid GPIO pins, sda=%d/scl=%d\n",
np, *sda_pin, *scl_pin);
return -ENODEV;
}

View File

@ -505,8 +505,7 @@ static int hix5hd2_i2c_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
static int hix5hd2_i2c_runtime_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct hix5hd2_i2c_priv *priv = platform_get_drvdata(pdev);
struct hix5hd2_i2c_priv *priv = dev_get_drvdata(dev);
clk_disable_unprepare(priv->clk);
@ -515,8 +514,7 @@ static int hix5hd2_i2c_runtime_suspend(struct device *dev)
static int hix5hd2_i2c_runtime_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct hix5hd2_i2c_priv *priv = platform_get_drvdata(pdev);
struct hix5hd2_i2c_priv *priv = dev_get_drvdata(dev);
clk_prepare_enable(priv->clk);
hix5hd2_i2c_init(priv);

View File

@ -1332,6 +1332,7 @@ static void i801_add_tco(struct i801_priv *priv)
u32 tco_base, tco_ctl;
u32 base_addr, ctrl_val;
u64 base64_addr;
u8 hidden;
if (!(priv->features & FEATURE_TCO))
return;
@ -1376,8 +1377,10 @@ static void i801_add_tco(struct i801_priv *priv)
devfn = PCI_DEVFN(PCI_SLOT(pci_dev->devfn), 1);
/* Unhide the P2SB device */
pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, 0x0);
/* Unhide the P2SB device, if it is hidden */
pci_bus_read_config_byte(pci_dev->bus, devfn, 0xe1, &hidden);
if (hidden)
pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, 0x0);
pci_bus_read_config_dword(pci_dev->bus, devfn, SBREG_BAR, &base_addr);
base64_addr = base_addr & 0xfffffff0;
@ -1385,8 +1388,9 @@ static void i801_add_tco(struct i801_priv *priv)
pci_bus_read_config_dword(pci_dev->bus, devfn, SBREG_BAR + 0x4, &base_addr);
base64_addr |= (u64)base_addr << 32;
/* Hide the P2SB device */
pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, 0x1);
/* Hide the P2SB device, if it was hidden before */
if (hidden)
pci_bus_write_config_byte(pci_dev->bus, devfn, 0xe1, hidden);
spin_unlock(&p2sb_spinlock);
res = &tco_res[ICH_RES_MEM_OFF];

View File

@ -289,7 +289,7 @@ static const struct i2c_algorithm kempld_i2c_algorithm = {
.functionality = kempld_i2c_func,
};
static struct i2c_adapter kempld_i2c_adapter = {
static const struct i2c_adapter kempld_i2c_adapter = {
.owner = THIS_MODULE,
.name = "i2c-kempld",
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,

View File

@ -457,8 +457,7 @@ static int i2c_lpc2k_remove(struct platform_device *dev)
#ifdef CONFIG_PM
static int i2c_lpc2k_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct lpc2k_i2c *i2c = platform_get_drvdata(pdev);
struct lpc2k_i2c *i2c = dev_get_drvdata(dev);
clk_disable(i2c->clk);
@ -467,8 +466,7 @@ static int i2c_lpc2k_suspend(struct device *dev)
static int i2c_lpc2k_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct lpc2k_i2c *i2c = platform_get_drvdata(pdev);
struct lpc2k_i2c *i2c = dev_get_drvdata(dev);
clk_enable(i2c->clk);
i2c_lpc2k_reset(i2c);

View File

@ -433,7 +433,7 @@ static const struct i2c_algorithm mlxcpld_i2c_algo = {
.functionality = mlxcpld_i2c_func
};
static struct i2c_adapter_quirks mlxcpld_i2c_quirks = {
static const struct i2c_adapter_quirks mlxcpld_i2c_quirks = {
.flags = I2C_AQ_COMB_WRITE_THEN_READ,
.max_read_len = MLXCPLD_I2C_DATA_REG_SZ - MLXCPLD_I2C_MAX_ADDR_LEN,
.max_write_len = MLXCPLD_I2C_DATA_REG_SZ,

View File

@ -50,7 +50,6 @@
#define I2C_FS_START_CON 0x1800
#define I2C_TIME_CLR_VALUE 0x0000
#define I2C_TIME_DEFAULT_VALUE 0x0003
#define I2C_FS_TIME_INIT_VALUE 0x1303
#define I2C_WRRD_TRANAC_VALUE 0x0002
#define I2C_RD_TRANAC_VALUE 0x0001
@ -154,6 +153,7 @@ struct mtk_i2c {
bool use_push_pull; /* IO config push-pull mode */
u16 irq_stat; /* interrupt status */
unsigned int clk_src_div;
unsigned int speed_hz; /* The speed in transfer */
enum mtk_trans_op op;
u16 timing_reg;
@ -172,6 +172,10 @@ static const struct i2c_adapter_quirks mt6577_i2c_quirks = {
.max_comb_2nd_msg_len = 31,
};
static const struct i2c_adapter_quirks mt7622_i2c_quirks = {
.max_num_msgs = 255,
};
static const struct mtk_i2c_compatible mt6577_compat = {
.quirks = &mt6577_i2c_quirks,
.pmic_i2c = 0,
@ -190,6 +194,15 @@ static const struct mtk_i2c_compatible mt6589_compat = {
.support_33bits = 0,
};
static const struct mtk_i2c_compatible mt7622_compat = {
.quirks = &mt7622_i2c_quirks,
.pmic_i2c = 0,
.dcm = 1,
.auto_restart = 1,
.aux_len_reg = 1,
.support_33bits = 0,
};
static const struct mtk_i2c_compatible mt8173_compat = {
.pmic_i2c = 0,
.dcm = 1,
@ -201,6 +214,7 @@ static const struct mtk_i2c_compatible mt8173_compat = {
static const struct of_device_id mtk_i2c_of_match[] = {
{ .compatible = "mediatek,mt6577-i2c", .data = &mt6577_compat },
{ .compatible = "mediatek,mt6589-i2c", .data = &mt6589_compat },
{ .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat },
{ .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
{}
};
@ -285,23 +299,20 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
* less than or equal to i2c->speed_hz. The calculation try to get
* sample_cnt and step_cn
*/
static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk,
unsigned int clock_div)
static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src,
unsigned int target_speed,
unsigned int *timing_step_cnt,
unsigned int *timing_sample_cnt)
{
unsigned int clk_src;
unsigned int step_cnt;
unsigned int sample_cnt;
unsigned int max_step_cnt;
unsigned int target_speed;
unsigned int base_sample_cnt = MAX_SAMPLE_CNT_DIV;
unsigned int base_step_cnt;
unsigned int opt_div;
unsigned int best_mul;
unsigned int cnt_mul;
clk_src = parent_clk / clock_div;
target_speed = i2c->speed_hz;
if (target_speed > MAX_HS_MODE_SPEED)
target_speed = MAX_HS_MODE_SPEED;
@ -347,16 +358,48 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk,
return -EINVAL;
}
step_cnt--;
sample_cnt--;
*timing_step_cnt = step_cnt - 1;
*timing_sample_cnt = sample_cnt - 1;
return 0;
}
static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk)
{
unsigned int clk_src;
unsigned int step_cnt;
unsigned int sample_cnt;
unsigned int target_speed;
int ret;
clk_src = parent_clk / i2c->clk_src_div;
target_speed = i2c->speed_hz;
if (target_speed > MAX_FS_MODE_SPEED) {
/* Set master code speed register */
ret = mtk_i2c_calculate_speed(i2c, clk_src, MAX_FS_MODE_SPEED,
&step_cnt, &sample_cnt);
if (ret < 0)
return ret;
i2c->timing_reg = (sample_cnt << 8) | step_cnt;
/* Set the high speed mode register */
i2c->timing_reg = I2C_FS_TIME_INIT_VALUE;
ret = mtk_i2c_calculate_speed(i2c, clk_src, target_speed,
&step_cnt, &sample_cnt);
if (ret < 0)
return ret;
i2c->high_speed_reg = I2C_TIME_DEFAULT_VALUE |
(sample_cnt << 12) | (step_cnt << 8);
} else {
i2c->timing_reg = (sample_cnt << 8) | (step_cnt << 0);
ret = mtk_i2c_calculate_speed(i2c, clk_src, target_speed,
&step_cnt, &sample_cnt);
if (ret < 0)
return ret;
i2c->timing_reg = (sample_cnt << 8) | step_cnt;
/* Disable the high speed transaction */
i2c->high_speed_reg = I2C_TIME_CLR_VALUE;
}
@ -647,8 +690,7 @@ static const struct i2c_algorithm mtk_i2c_algorithm = {
.functionality = mtk_i2c_functionality,
};
static int mtk_i2c_parse_dt(struct device_node *np, struct mtk_i2c *i2c,
unsigned int *clk_src_div)
static int mtk_i2c_parse_dt(struct device_node *np, struct mtk_i2c *i2c)
{
int ret;
@ -656,11 +698,11 @@ static int mtk_i2c_parse_dt(struct device_node *np, struct mtk_i2c *i2c,
if (ret < 0)
i2c->speed_hz = I2C_DEFAULT_SPEED;
ret = of_property_read_u32(np, "clock-div", clk_src_div);
ret = of_property_read_u32(np, "clock-div", &i2c->clk_src_div);
if (ret < 0)
return ret;
if (*clk_src_div == 0)
if (i2c->clk_src_div == 0)
return -EINVAL;
i2c->have_pmic = of_property_read_bool(np, "mediatek,have-pmic");
@ -676,7 +718,6 @@ static int mtk_i2c_probe(struct platform_device *pdev)
int ret = 0;
struct mtk_i2c *i2c;
struct clk *clk;
unsigned int clk_src_div;
struct resource *res;
int irq;
@ -684,7 +725,7 @@ static int mtk_i2c_probe(struct platform_device *pdev)
if (!i2c)
return -ENOMEM;
ret = mtk_i2c_parse_dt(pdev->dev.of_node, i2c, &clk_src_div);
ret = mtk_i2c_parse_dt(pdev->dev.of_node, i2c);
if (ret)
return -EINVAL;
@ -745,7 +786,7 @@ static int mtk_i2c_probe(struct platform_device *pdev)
strlcpy(i2c->adap.name, I2C_DRV_NAME, sizeof(i2c->adap.name));
ret = mtk_i2c_set_speed(i2c, clk_get_rate(clk), clk_src_div);
ret = mtk_i2c_set_speed(i2c, clk_get_rate(clk));
if (ret) {
dev_err(&pdev->dev, "Failed to set the speed.\n");
return -EINVAL;

View File

@ -820,7 +820,7 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
goto out;
}
drv_data->rstc = devm_reset_control_get_optional(dev, NULL);
drv_data->rstc = devm_reset_control_get_optional_exclusive(dev, NULL);
if (IS_ERR(drv_data->rstc)) {
rc = PTR_ERR(drv_data->rstc);
goto out;
@ -975,8 +975,7 @@ mv64xxx_i2c_remove(struct platform_device *dev)
#ifdef CONFIG_PM
static int mv64xxx_i2c_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct mv64xxx_i2c_data *drv_data = platform_get_drvdata(pdev);
struct mv64xxx_i2c_data *drv_data = dev_get_drvdata(dev);
mv64xxx_i2c_hw_init(drv_data);

View File

@ -1088,7 +1088,7 @@ static struct i2c_vendor_data vendor_db8500 = {
.fifodepth = 32, /* Guessed from TFTR/RFTR = 15 */
};
static struct amba_id nmk_i2c_ids[] = {
static const struct amba_id nmk_i2c_ids[] = {
{
.id = 0x00180024,
.mask = 0x00ffffff,

View File

@ -276,7 +276,7 @@ static const struct i2c_algorithm ocores_algorithm = {
.functionality = ocores_func,
};
static struct i2c_adapter ocores_adapter = {
static const struct i2c_adapter ocores_adapter = {
.owner = THIS_MODULE,
.name = "i2c-ocores",
.class = I2C_CLASS_DEPRECATED,

View File

@ -126,7 +126,7 @@ static const struct i2c_algorithm octeon_i2c_algo = {
.functionality = octeon_i2c_functionality,
};
static struct i2c_adapter octeon_i2c_ops = {
static const struct i2c_adapter octeon_i2c_ops = {
.owner = THIS_MODULE,
.name = "OCTEON adapter",
.algo = &octeon_i2c_algo,

View File

@ -204,7 +204,7 @@ static const struct i2c_algorithm i2c_opal_algo = {
* For two messages, we basically support simple smbus transactions of a
* write-then-anything.
*/
static struct i2c_adapter_quirks i2c_opal_quirks = {
static const struct i2c_adapter_quirks i2c_opal_quirks = {
.flags = I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST | I2C_AQ_COMB_SAME_ADDR,
.max_comb_1st_msg_len = 4,
};

View File

@ -577,7 +577,7 @@ static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter)
I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL;
}
static struct i2c_adapter_quirks pmcmsptwi_i2c_quirks = {
static const struct i2c_adapter_quirks pmcmsptwi_i2c_quirks = {
.flags = I2C_AQ_COMB_WRITE_THEN_READ,
.max_write_len = MSP_MAX_BYTES_PER_RW,
.max_read_len = MSP_MAX_BYTES_PER_RW,
@ -587,7 +587,7 @@ static struct i2c_adapter_quirks pmcmsptwi_i2c_quirks = {
/* -- Initialization -- */
static struct i2c_algorithm pmcmsptwi_algo = {
static const struct i2c_algorithm pmcmsptwi_algo = {
.master_xfer = pmcmsptwi_master_xfer,
.functionality = pmcmsptwi_i2c_func,
};

View File

@ -590,7 +590,7 @@ static u32 i2c_pnx_func(struct i2c_adapter *adapter)
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static struct i2c_algorithm pnx_algorithm = {
static const struct i2c_algorithm pnx_algorithm = {
.master_xfer = i2c_pnx_xfer,
.functionality = i2c_pnx_func,
};

View File

@ -197,7 +197,7 @@ static const struct i2c_algorithm i2c_powermac_algorithm = {
.functionality = i2c_powermac_func,
};
static struct i2c_adapter_quirks i2c_powermac_quirks = {
static const struct i2c_adapter_quirks i2c_powermac_quirks = {
.max_num_msgs = 1,
};
@ -234,7 +234,7 @@ static u32 i2c_powermac_get_addr(struct i2c_adapter *adap,
else if (!strcmp(node->name, "deq"))
return 0x34;
dev_warn(&adap->dev, "No i2c address for %s\n", node->full_name);
dev_warn(&adap->dev, "No i2c address for %pOF\n", node);
return 0xffffffff;
}
@ -315,8 +315,7 @@ static bool i2c_powermac_get_type(struct i2c_adapter *adap,
}
}
dev_err(&adap->dev, "i2c-powermac: modalias failure"
" on %s\n", node->full_name);
dev_err(&adap->dev, "i2c-powermac: modalias failure on %pOF\n", node);
return false;
}
@ -348,8 +347,7 @@ static void i2c_powermac_register_devices(struct i2c_adapter *adap,
if (!pmac_i2c_match_adapter(node, adap))
continue;
dev_dbg(&adap->dev, "i2c-powermac: register %s\n",
node->full_name);
dev_dbg(&adap->dev, "i2c-powermac: register %pOF\n", node);
/*
* Keep track of some device existence to handle
@ -372,7 +370,7 @@ static void i2c_powermac_register_devices(struct i2c_adapter *adap,
newdev = i2c_new_device(adap, &info);
if (!newdev) {
dev_err(&adap->dev, "i2c-powermac: Failure to register"
" %s\n", node->full_name);
" %pOF\n", node);
of_node_put(node);
/* We do not dispose of the interrupt mapping on
* purpose. It's not necessary (interrupt cannot be

View File

@ -175,7 +175,7 @@ static u32 puv3_i2c_func(struct i2c_adapter *adapter)
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static struct i2c_algorithm puv3_i2c_algorithm = {
static const struct i2c_algorithm puv3_i2c_algorithm = {
.master_xfer = puv3_i2c_xfer,
.functionality = puv3_i2c_func,
};

View File

@ -1346,8 +1346,7 @@ static int i2c_pxa_remove(struct platform_device *dev)
#ifdef CONFIG_PM
static int i2c_pxa_suspend_noirq(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct pxa_i2c *i2c = platform_get_drvdata(pdev);
struct pxa_i2c *i2c = dev_get_drvdata(dev);
clk_disable(i2c->clk);
@ -1356,8 +1355,7 @@ static int i2c_pxa_suspend_noirq(struct device *dev)
static int i2c_pxa_resume_noirq(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct pxa_i2c *i2c = platform_get_drvdata(pdev);
struct pxa_i2c *i2c = dev_get_drvdata(dev);
clk_enable(i2c->clk);
i2c_pxa_reset(i2c);

View File

@ -1396,7 +1396,7 @@ static const struct i2c_algorithm qup_i2c_algo_v2 = {
* the end of the read, the length of the read is specified as one byte
* which limits the possible read to 256 (QUP_READ_LIMIT) bytes.
*/
static struct i2c_adapter_quirks qup_i2c_quirks = {
static const struct i2c_adapter_quirks qup_i2c_quirks = {
.max_read_len = QUP_READ_LIMIT,
};

View File

@ -625,9 +625,8 @@ static struct dma_chan *rcar_i2c_request_dma_chan(struct device *dev,
chan = dma_request_chan(dev, chan_name);
if (IS_ERR(chan)) {
ret = PTR_ERR(chan);
dev_dbg(dev, "request_channel failed for %s (%d)\n",
chan_name, ret);
dev_dbg(dev, "request_channel failed for %s (%ld)\n",
chan_name, PTR_ERR(chan));
return chan;
}

View File

@ -1131,6 +1131,11 @@ static const struct i2c_algorithm rk3x_i2c_algorithm = {
.functionality = rk3x_i2c_func,
};
static const struct rk3x_i2c_soc_data rv1108_soc_data = {
.grf_offset = -1,
.calc_timings = rk3x_i2c_v1_calc_timings,
};
static const struct rk3x_i2c_soc_data rk3066_soc_data = {
.grf_offset = 0x154,
.calc_timings = rk3x_i2c_v0_calc_timings,
@ -1157,6 +1162,10 @@ static const struct rk3x_i2c_soc_data rk3399_soc_data = {
};
static const struct of_device_id rk3x_i2c_match[] = {
{
.compatible = "rockchip,rv1108-i2c",
.data = (void *)&rv1108_soc_data
},
{
.compatible = "rockchip,rk3066-i2c",
.data = (void *)&rk3066_soc_data

View File

@ -1246,8 +1246,7 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static int s3c24xx_i2c_suspend_noirq(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
struct s3c24xx_i2c *i2c = dev_get_drvdata(dev);
i2c->suspended = 1;
@ -1259,8 +1258,7 @@ static int s3c24xx_i2c_suspend_noirq(struct device *dev)
static int s3c24xx_i2c_resume_noirq(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
struct s3c24xx_i2c *i2c = dev_get_drvdata(dev);
int ret;
if (!IS_ERR(i2c->sysreg))

View File

@ -561,8 +561,8 @@ static struct dma_chan *sh_mobile_i2c_request_dma_chan(struct device *dev,
chan = dma_request_slave_channel_reason(dev, chan_name);
if (IS_ERR(chan)) {
ret = PTR_ERR(chan);
dev_dbg(dev, "request_channel failed for %s (%d)\n", chan_name, ret);
dev_dbg(dev, "request_channel failed for %s (%ld)\n", chan_name,
PTR_ERR(chan));
return chan;
}

View File

@ -421,8 +421,7 @@ static int i2c_sirfsoc_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
static int i2c_sirfsoc_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct i2c_adapter *adapter = platform_get_drvdata(pdev);
struct i2c_adapter *adapter = dev_get_drvdata(dev);
struct sirfsoc_i2c *siic = adapter->algo_data;
clk_enable(siic->clk);
@ -434,8 +433,7 @@ static int i2c_sirfsoc_suspend(struct device *dev)
static int i2c_sirfsoc_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct i2c_adapter *adapter = platform_get_drvdata(pdev);
struct i2c_adapter *adapter = dev_get_drvdata(dev);
struct sirfsoc_i2c *siic = adapter->algo_data;
clk_enable(siic->clk);

View File

@ -0,0 +1,646 @@
/*
* Copyright (C) 2017 Spreadtrum Communications Inc.
*
* SPDX-License-Identifier: (GPL-2.0+ OR MIT)
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#define I2C_CTL 0x00
#define I2C_ADDR_CFG 0x04
#define I2C_COUNT 0x08
#define I2C_RX 0x0c
#define I2C_TX 0x10
#define I2C_STATUS 0x14
#define I2C_HSMODE_CFG 0x18
#define I2C_VERSION 0x1c
#define ADDR_DVD0 0x20
#define ADDR_DVD1 0x24
#define ADDR_STA0_DVD 0x28
#define ADDR_RST 0x2c
/* I2C_CTL */
#define STP_EN BIT(20)
#define FIFO_AF_LVL_MASK GENMASK(19, 16)
#define FIFO_AF_LVL 16
#define FIFO_AE_LVL_MASK GENMASK(15, 12)
#define FIFO_AE_LVL 12
#define I2C_DMA_EN BIT(11)
#define FULL_INTEN BIT(10)
#define EMPTY_INTEN BIT(9)
#define I2C_DVD_OPT BIT(8)
#define I2C_OUT_OPT BIT(7)
#define I2C_TRIM_OPT BIT(6)
#define I2C_HS_MODE BIT(4)
#define I2C_MODE BIT(3)
#define I2C_EN BIT(2)
#define I2C_INT_EN BIT(1)
#define I2C_START BIT(0)
/* I2C_STATUS */
#define SDA_IN BIT(21)
#define SCL_IN BIT(20)
#define FIFO_FULL BIT(4)
#define FIFO_EMPTY BIT(3)
#define I2C_INT BIT(2)
#define I2C_RX_ACK BIT(1)
#define I2C_BUSY BIT(0)
/* ADDR_RST */
#define I2C_RST BIT(0)
#define I2C_FIFO_DEEP 12
#define I2C_FIFO_FULL_THLD 15
#define I2C_FIFO_EMPTY_THLD 4
#define I2C_DATA_STEP 8
#define I2C_ADDR_DVD0_CALC(high, low) \
((((high) & GENMASK(15, 0)) << 16) | ((low) & GENMASK(15, 0)))
#define I2C_ADDR_DVD1_CALC(high, low) \
(((high) & GENMASK(31, 16)) | (((low) & GENMASK(31, 16)) >> 16))
/* timeout (ms) for pm runtime autosuspend */
#define SPRD_I2C_PM_TIMEOUT 1000
/* SPRD i2c data structure */
struct sprd_i2c {
struct i2c_adapter adap;
struct device *dev;
void __iomem *base;
struct i2c_msg *msg;
struct clk *clk;
u32 src_clk;
u32 bus_freq;
struct completion complete;
u8 *buf;
u32 count;
int irq;
int err;
};
static void sprd_i2c_set_count(struct sprd_i2c *i2c_dev, u32 count)
{
writel(count, i2c_dev->base + I2C_COUNT);
}
static void sprd_i2c_send_stop(struct sprd_i2c *i2c_dev, int stop)
{
u32 tmp = readl(i2c_dev->base + I2C_CTL);
if (stop)
writel(tmp & ~STP_EN, i2c_dev->base + I2C_CTL);
else
writel(tmp | STP_EN, i2c_dev->base + I2C_CTL);
}
static void sprd_i2c_clear_start(struct sprd_i2c *i2c_dev)
{
u32 tmp = readl(i2c_dev->base + I2C_CTL);
writel(tmp & ~I2C_START, i2c_dev->base + I2C_CTL);
}
static void sprd_i2c_clear_ack(struct sprd_i2c *i2c_dev)
{
u32 tmp = readl(i2c_dev->base + I2C_STATUS);
writel(tmp & ~I2C_RX_ACK, i2c_dev->base + I2C_STATUS);
}
static void sprd_i2c_clear_irq(struct sprd_i2c *i2c_dev)
{
u32 tmp = readl(i2c_dev->base + I2C_STATUS);
writel(tmp & ~I2C_INT, i2c_dev->base + I2C_STATUS);
}
static void sprd_i2c_reset_fifo(struct sprd_i2c *i2c_dev)
{
writel(I2C_RST, i2c_dev->base + ADDR_RST);
}
static void sprd_i2c_set_devaddr(struct sprd_i2c *i2c_dev, struct i2c_msg *m)
{
writel(m->addr << 1, i2c_dev->base + I2C_ADDR_CFG);
}
static void sprd_i2c_write_bytes(struct sprd_i2c *i2c_dev, u8 *buf, u32 len)
{
u32 i;
for (i = 0; i < len; i++)
writeb(buf[i], i2c_dev->base + I2C_TX);
}
static void sprd_i2c_read_bytes(struct sprd_i2c *i2c_dev, u8 *buf, u32 len)
{
u32 i;
for (i = 0; i < len; i++)
buf[i] = readb(i2c_dev->base + I2C_RX);
}
static void sprd_i2c_set_full_thld(struct sprd_i2c *i2c_dev, u32 full_thld)
{
u32 tmp = readl(i2c_dev->base + I2C_CTL);
tmp &= ~FIFO_AF_LVL_MASK;
tmp |= full_thld << FIFO_AF_LVL;
writel(tmp, i2c_dev->base + I2C_CTL);
};
static void sprd_i2c_set_empty_thld(struct sprd_i2c *i2c_dev, u32 empty_thld)
{
u32 tmp = readl(i2c_dev->base + I2C_CTL);
tmp &= ~FIFO_AE_LVL_MASK;
tmp |= empty_thld << FIFO_AE_LVL;
writel(tmp, i2c_dev->base + I2C_CTL);
};
static void sprd_i2c_set_fifo_full_int(struct sprd_i2c *i2c_dev, int enable)
{
u32 tmp = readl(i2c_dev->base + I2C_CTL);
if (enable)
tmp |= FULL_INTEN;
else
tmp &= ~FULL_INTEN;
writel(tmp, i2c_dev->base + I2C_CTL);
};
static void sprd_i2c_set_fifo_empty_int(struct sprd_i2c *i2c_dev, int enable)
{
u32 tmp = readl(i2c_dev->base + I2C_CTL);
if (enable)
tmp |= EMPTY_INTEN;
else
tmp &= ~EMPTY_INTEN;
writel(tmp, i2c_dev->base + I2C_CTL);
};
static void sprd_i2c_opt_start(struct sprd_i2c *i2c_dev)
{
u32 tmp = readl(i2c_dev->base + I2C_CTL);
writel(tmp | I2C_START, i2c_dev->base + I2C_CTL);
}
static void sprd_i2c_opt_mode(struct sprd_i2c *i2c_dev, int rw)
{
u32 cmd = readl(i2c_dev->base + I2C_CTL) & ~I2C_MODE;
writel(cmd | rw << 3, i2c_dev->base + I2C_CTL);
}
static void sprd_i2c_data_transfer(struct sprd_i2c *i2c_dev)
{
u32 i2c_count = i2c_dev->count;
u32 need_tran = i2c_count <= I2C_FIFO_DEEP ? i2c_count : I2C_FIFO_DEEP;
struct i2c_msg *msg = i2c_dev->msg;
if (msg->flags & I2C_M_RD) {
sprd_i2c_read_bytes(i2c_dev, i2c_dev->buf, I2C_FIFO_FULL_THLD);
i2c_dev->count -= I2C_FIFO_FULL_THLD;
i2c_dev->buf += I2C_FIFO_FULL_THLD;
/*
* If the read data count is larger than rx fifo full threshold,
* we should enable the rx fifo full interrupt to read data
* again.
*/
if (i2c_dev->count >= I2C_FIFO_FULL_THLD)
sprd_i2c_set_fifo_full_int(i2c_dev, 1);
} else {
sprd_i2c_write_bytes(i2c_dev, i2c_dev->buf, need_tran);
i2c_dev->buf += need_tran;
i2c_dev->count -= need_tran;
/*
* If the write data count is arger than tx fifo depth which
* means we can not write all data in one time, then we should
* enable the tx fifo empty interrupt to write again.
*/
if (i2c_count > I2C_FIFO_DEEP)
sprd_i2c_set_fifo_empty_int(i2c_dev, 1);
}
}
static int sprd_i2c_handle_msg(struct i2c_adapter *i2c_adap,
struct i2c_msg *msg, bool is_last_msg)
{
struct sprd_i2c *i2c_dev = i2c_adap->algo_data;
i2c_dev->msg = msg;
i2c_dev->buf = msg->buf;
i2c_dev->count = msg->len;
reinit_completion(&i2c_dev->complete);
sprd_i2c_reset_fifo(i2c_dev);
sprd_i2c_set_devaddr(i2c_dev, msg);
sprd_i2c_set_count(i2c_dev, msg->len);
if (msg->flags & I2C_M_RD) {
sprd_i2c_opt_mode(i2c_dev, 1);
sprd_i2c_send_stop(i2c_dev, 1);
} else {
sprd_i2c_opt_mode(i2c_dev, 0);
sprd_i2c_send_stop(i2c_dev, !!is_last_msg);
}
/*
* We should enable rx fifo full interrupt to get data when receiving
* full data.
*/
if (msg->flags & I2C_M_RD)
sprd_i2c_set_fifo_full_int(i2c_dev, 1);
else
sprd_i2c_data_transfer(i2c_dev);
sprd_i2c_opt_start(i2c_dev);
wait_for_completion(&i2c_dev->complete);
return i2c_dev->err;
}
static int sprd_i2c_master_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg *msgs, int num)
{
struct sprd_i2c *i2c_dev = i2c_adap->algo_data;
int im, ret;
ret = pm_runtime_get_sync(i2c_dev->dev);
if (ret < 0)
return ret;
for (im = 0; im < num - 1; im++) {
ret = sprd_i2c_handle_msg(i2c_adap, &msgs[im], 0);
if (ret)
goto err_msg;
}
ret = sprd_i2c_handle_msg(i2c_adap, &msgs[im++], 1);
err_msg:
pm_runtime_mark_last_busy(i2c_dev->dev);
pm_runtime_put_autosuspend(i2c_dev->dev);
return ret < 0 ? ret : im;
}
static u32 sprd_i2c_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static const struct i2c_algorithm sprd_i2c_algo = {
.master_xfer = sprd_i2c_master_xfer,
.functionality = sprd_i2c_func,
};
static void sprd_i2c_set_clk(struct sprd_i2c *i2c_dev, u32 freq)
{
u32 apb_clk = i2c_dev->src_clk;
/*
* From I2C databook, the prescale calculation formula:
* prescale = freq_i2c / (4 * freq_scl) - 1;
*/
u32 i2c_dvd = apb_clk / (4 * freq) - 1;
/*
* From I2C databook, the high period of SCL clock is recommended as
* 40% (2/5), and the low period of SCL clock is recommended as 60%
* (3/5), then the formula should be:
* high = (prescale * 2 * 2) / 5
* low = (prescale * 2 * 3) / 5
*/
u32 high = ((i2c_dvd << 1) * 2) / 5;
u32 low = ((i2c_dvd << 1) * 3) / 5;
u32 div0 = I2C_ADDR_DVD0_CALC(high, low);
u32 div1 = I2C_ADDR_DVD1_CALC(high, low);
writel(div0, i2c_dev->base + ADDR_DVD0);
writel(div1, i2c_dev->base + ADDR_DVD1);
/* Start hold timing = hold time(us) * source clock */
if (freq == 400000)
writel((6 * apb_clk) / 10000000, i2c_dev->base + ADDR_STA0_DVD);
else if (freq == 100000)
writel((4 * apb_clk) / 1000000, i2c_dev->base + ADDR_STA0_DVD);
}
static void sprd_i2c_enable(struct sprd_i2c *i2c_dev)
{
u32 tmp = I2C_DVD_OPT;
writel(tmp, i2c_dev->base + I2C_CTL);
sprd_i2c_set_full_thld(i2c_dev, I2C_FIFO_FULL_THLD);
sprd_i2c_set_empty_thld(i2c_dev, I2C_FIFO_EMPTY_THLD);
sprd_i2c_set_clk(i2c_dev, i2c_dev->bus_freq);
sprd_i2c_reset_fifo(i2c_dev);
sprd_i2c_clear_irq(i2c_dev);
tmp = readl(i2c_dev->base + I2C_CTL);
writel(tmp | I2C_EN | I2C_INT_EN, i2c_dev->base + I2C_CTL);
}
static irqreturn_t sprd_i2c_isr_thread(int irq, void *dev_id)
{
struct sprd_i2c *i2c_dev = dev_id;
struct i2c_msg *msg = i2c_dev->msg;
bool ack = !(readl(i2c_dev->base + I2C_STATUS) & I2C_RX_ACK);
u32 i2c_count = readl(i2c_dev->base + I2C_COUNT);
u32 i2c_tran;
if (msg->flags & I2C_M_RD)
i2c_tran = i2c_dev->count >= I2C_FIFO_FULL_THLD;
else
i2c_tran = i2c_count;
/*
* If we got one ACK from slave when writing data, and we did not
* finish this transmission (i2c_tran is not zero), then we should
* continue to write data.
*
* For reading data, ack is always true, if i2c_tran is not 0 which
* means we still need to contine to read data from slave.
*/
if (i2c_tran && ack) {
sprd_i2c_data_transfer(i2c_dev);
return IRQ_HANDLED;
}
i2c_dev->err = 0;
/*
* If we did not get one ACK from slave when writing data, we should
* return -EIO to notify users.
*/
if (!ack)
i2c_dev->err = -EIO;
else if (msg->flags & I2C_M_RD && i2c_dev->count)
sprd_i2c_read_bytes(i2c_dev, i2c_dev->buf, i2c_dev->count);
/* Transmission is done and clear ack and start operation */
sprd_i2c_clear_ack(i2c_dev);
sprd_i2c_clear_start(i2c_dev);
complete(&i2c_dev->complete);
return IRQ_HANDLED;
}
static irqreturn_t sprd_i2c_isr(int irq, void *dev_id)
{
struct sprd_i2c *i2c_dev = dev_id;
struct i2c_msg *msg = i2c_dev->msg;
u32 i2c_count = readl(i2c_dev->base + I2C_COUNT);
bool ack = !(readl(i2c_dev->base + I2C_STATUS) & I2C_RX_ACK);
u32 i2c_tran;
if (msg->flags & I2C_M_RD)
i2c_tran = i2c_dev->count >= I2C_FIFO_FULL_THLD;
else
i2c_tran = i2c_count;
/*
* If we did not get one ACK from slave when writing data, then we
* should finish this transmission since we got some errors.
*
* When writing data, if i2c_tran == 0 which means we have writen
* done all data, then we can finish this transmission.
*
* When reading data, if conut < rx fifo full threshold, which
* means we can read all data in one time, then we can finish this
* transmission too.
*/
if (!i2c_tran || !ack) {
sprd_i2c_clear_start(i2c_dev);
sprd_i2c_clear_irq(i2c_dev);
}
sprd_i2c_set_fifo_empty_int(i2c_dev, 0);
sprd_i2c_set_fifo_full_int(i2c_dev, 0);
return IRQ_WAKE_THREAD;
}
static int sprd_i2c_clk_init(struct sprd_i2c *i2c_dev)
{
struct clk *clk_i2c, *clk_parent;
clk_i2c = devm_clk_get(i2c_dev->dev, "i2c");
if (IS_ERR(clk_i2c)) {
dev_warn(i2c_dev->dev, "i2c%d can't get the i2c clock\n",
i2c_dev->adap.nr);
clk_i2c = NULL;
}
clk_parent = devm_clk_get(i2c_dev->dev, "source");
if (IS_ERR(clk_parent)) {
dev_warn(i2c_dev->dev, "i2c%d can't get the source clock\n",
i2c_dev->adap.nr);
clk_parent = NULL;
}
if (clk_set_parent(clk_i2c, clk_parent))
i2c_dev->src_clk = clk_get_rate(clk_i2c);
else
i2c_dev->src_clk = 26000000;
dev_dbg(i2c_dev->dev, "i2c%d set source clock is %d\n",
i2c_dev->adap.nr, i2c_dev->src_clk);
i2c_dev->clk = devm_clk_get(i2c_dev->dev, "enable");
if (IS_ERR(i2c_dev->clk)) {
dev_warn(i2c_dev->dev, "i2c%d can't get the enable clock\n",
i2c_dev->adap.nr);
i2c_dev->clk = NULL;
}
return 0;
}
static int sprd_i2c_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct sprd_i2c *i2c_dev;
struct resource *res;
u32 prop;
int ret;
pdev->id = of_alias_get_id(dev->of_node, "i2c");
i2c_dev = devm_kzalloc(dev, sizeof(struct sprd_i2c), GFP_KERNEL);
if (!i2c_dev)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
i2c_dev->base = devm_ioremap_resource(dev, res);
if (IS_ERR(i2c_dev->base))
return PTR_ERR(i2c_dev->base);
i2c_dev->irq = platform_get_irq(pdev, 0);
if (i2c_dev->irq < 0) {
dev_err(&pdev->dev, "failed to get irq resource\n");
return i2c_dev->irq;
}
i2c_set_adapdata(&i2c_dev->adap, i2c_dev);
init_completion(&i2c_dev->complete);
snprintf(i2c_dev->adap.name, sizeof(i2c_dev->adap.name),
"%s", "sprd-i2c");
i2c_dev->bus_freq = 100000;
i2c_dev->adap.owner = THIS_MODULE;
i2c_dev->dev = dev;
i2c_dev->adap.retries = 3;
i2c_dev->adap.algo = &sprd_i2c_algo;
i2c_dev->adap.algo_data = i2c_dev;
i2c_dev->adap.dev.parent = dev;
i2c_dev->adap.nr = pdev->id;
i2c_dev->adap.dev.of_node = dev->of_node;
if (!of_property_read_u32(dev->of_node, "clock-frequency", &prop))
i2c_dev->bus_freq = prop;
/* We only support 100k and 400k now, otherwise will return error. */
if (i2c_dev->bus_freq != 100000 && i2c_dev->bus_freq != 400000)
return -EINVAL;
sprd_i2c_clk_init(i2c_dev);
platform_set_drvdata(pdev, i2c_dev);
ret = clk_prepare_enable(i2c_dev->clk);
if (ret)
return ret;
sprd_i2c_enable(i2c_dev);
pm_runtime_set_autosuspend_delay(i2c_dev->dev, SPRD_I2C_PM_TIMEOUT);
pm_runtime_use_autosuspend(i2c_dev->dev);
pm_runtime_set_active(i2c_dev->dev);
pm_runtime_enable(i2c_dev->dev);
ret = pm_runtime_get_sync(i2c_dev->dev);
if (ret < 0)
goto err_rpm_put;
ret = devm_request_threaded_irq(dev, i2c_dev->irq,
sprd_i2c_isr, sprd_i2c_isr_thread,
IRQF_NO_SUSPEND | IRQF_ONESHOT,
pdev->name, i2c_dev);
if (ret) {
dev_err(&pdev->dev, "failed to request irq %d\n", i2c_dev->irq);
goto err_rpm_put;
}
ret = i2c_add_numbered_adapter(&i2c_dev->adap);
if (ret) {
dev_err(&pdev->dev, "add adapter failed\n");
goto err_rpm_put;
}
pm_runtime_mark_last_busy(i2c_dev->dev);
pm_runtime_put_autosuspend(i2c_dev->dev);
return 0;
err_rpm_put:
pm_runtime_put_noidle(i2c_dev->dev);
pm_runtime_disable(i2c_dev->dev);
clk_disable_unprepare(i2c_dev->clk);
return ret;
}
static int sprd_i2c_remove(struct platform_device *pdev)
{
struct sprd_i2c *i2c_dev = platform_get_drvdata(pdev);
int ret;
ret = pm_runtime_get_sync(i2c_dev->dev);
if (ret < 0)
return ret;
i2c_del_adapter(&i2c_dev->adap);
clk_disable_unprepare(i2c_dev->clk);
pm_runtime_put_noidle(i2c_dev->dev);
pm_runtime_disable(i2c_dev->dev);
return 0;
}
static int __maybe_unused sprd_i2c_suspend_noirq(struct device *pdev)
{
return pm_runtime_force_suspend(pdev);
}
static int __maybe_unused sprd_i2c_resume_noirq(struct device *pdev)
{
return pm_runtime_force_resume(pdev);
}
static int __maybe_unused sprd_i2c_runtime_suspend(struct device *pdev)
{
struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev);
clk_disable_unprepare(i2c_dev->clk);
return 0;
}
static int __maybe_unused sprd_i2c_runtime_resume(struct device *pdev)
{
struct sprd_i2c *i2c_dev = dev_get_drvdata(pdev);
int ret;
ret = clk_prepare_enable(i2c_dev->clk);
if (ret)
return ret;
sprd_i2c_enable(i2c_dev);
return 0;
}
static const struct dev_pm_ops sprd_i2c_pm_ops = {
SET_RUNTIME_PM_OPS(sprd_i2c_runtime_suspend,
sprd_i2c_runtime_resume, NULL)
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sprd_i2c_suspend_noirq,
sprd_i2c_resume_noirq)
};
static const struct of_device_id sprd_i2c_of_match[] = {
{ .compatible = "sprd,sc9860-i2c", },
};
static struct platform_driver sprd_i2c_driver = {
.probe = sprd_i2c_probe,
.remove = sprd_i2c_remove,
.driver = {
.name = "sprd-i2c",
.of_match_table = sprd_i2c_of_match,
.pm = &sprd_i2c_pm_ops,
},
};
static int sprd_i2c_init(void)
{
return platform_driver_register(&sprd_i2c_driver);
}
arch_initcall_sync(sprd_i2c_init);

View File

@ -745,8 +745,7 @@ static int st_i2c_xfer(struct i2c_adapter *i2c_adap,
#ifdef CONFIG_PM_SLEEP
static int st_i2c_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct st_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
struct st_i2c_dev *i2c_dev = dev_get_drvdata(dev);
if (i2c_dev->busy)
return -EBUSY;

View File

@ -751,7 +751,7 @@ static u32 stm32f4_i2c_func(struct i2c_adapter *adap)
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static struct i2c_algorithm stm32f4_i2c_algo = {
static const struct i2c_algorithm stm32f4_i2c_algo = {
.master_xfer = stm32f4_i2c_xfer,
.functionality = stm32f4_i2c_func,
};
@ -798,7 +798,7 @@ static int stm32f4_i2c_probe(struct platform_device *pdev)
return ret;
}
rst = devm_reset_control_get(&pdev->dev, NULL);
rst = devm_reset_control_get_exclusive(&pdev->dev, NULL);
if (IS_ERR(rst)) {
dev_err(&pdev->dev, "Error: Missing controller reset\n");
ret = PTR_ERR(rst);

View File

@ -223,8 +223,8 @@ static int p2wi_probe(struct platform_device *pdev)
if (childnp) {
ret = of_property_read_u32(childnp, "reg", &slave_addr);
if (ret) {
dev_err(dev, "invalid slave address on node %s\n",
childnp->full_name);
dev_err(dev, "invalid slave address on node %pOF\n",
childnp);
return -EINVAL;
}
@ -258,7 +258,7 @@ static int p2wi_probe(struct platform_device *pdev)
parent_clk_freq = clk_get_rate(p2wi->clk);
p2wi->rstc = devm_reset_control_get(dev, NULL);
p2wi->rstc = devm_reset_control_get_exclusive(dev, NULL);
if (IS_ERR(p2wi->rstc)) {
ret = PTR_ERR(p2wi->rstc);
dev_err(dev, "failed to retrieve reset controller: %d\n", ret);

View File

@ -291,7 +291,7 @@ static void taos_disconnect(struct serio *serio)
dev_info(&serio->dev, "Disconnected from TAOS EVM\n");
}
static struct serio_device_id taos_serio_ids[] = {
static const struct serio_device_id taos_serio_ids[] = {
{
.type = SERIO_RS232,
.proto = SERIO_TAOSEVM,

View File

@ -793,7 +793,7 @@ static const struct i2c_algorithm tegra_i2c_algo = {
};
/* payload size is only 12 bit */
static struct i2c_adapter_quirks tegra_i2c_quirks = {
static const struct i2c_adapter_quirks tegra_i2c_quirks = {
.max_read_len = 4096,
.max_write_len = 4096,
};
@ -911,7 +911,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
i2c_dev->cont_id = pdev->id;
i2c_dev->dev = &pdev->dev;
i2c_dev->rst = devm_reset_control_get(&pdev->dev, "i2c");
i2c_dev->rst = devm_reset_control_get_exclusive(&pdev->dev, "i2c");
if (IS_ERR(i2c_dev->rst)) {
dev_err(&pdev->dev, "missing controller reset\n");
return PTR_ERR(i2c_dev->rst);

View File

@ -75,7 +75,7 @@ static const struct i2c_algorithm thunderx_i2c_algo = {
.functionality = thunderx_i2c_functionality,
};
static struct i2c_adapter thunderx_i2c_ops = {
static const struct i2c_adapter thunderx_i2c_ops = {
.owner = THIS_MODULE,
.name = "ThunderX adapter",
.algo = &thunderx_i2c_algo,

View File

@ -97,6 +97,7 @@ struct uniphier_fi2c_priv {
int error;
unsigned int flags;
unsigned int busy_cnt;
unsigned int clk_cycle;
};
static void uniphier_fi2c_fill_txfifo(struct uniphier_fi2c_priv *priv,
@ -461,9 +462,9 @@ static struct i2c_bus_recovery_info uniphier_fi2c_bus_recovery_info = {
.unprepare_recovery = uniphier_fi2c_unprepare_recovery,
};
static void uniphier_fi2c_hw_init(struct uniphier_fi2c_priv *priv,
u32 bus_speed, unsigned long clk_rate)
static void uniphier_fi2c_hw_init(struct uniphier_fi2c_priv *priv)
{
unsigned int cyc = priv->clk_cycle;
u32 tmp;
tmp = readl(priv->membase + UNIPHIER_FI2C_CR);
@ -472,12 +473,10 @@ static void uniphier_fi2c_hw_init(struct uniphier_fi2c_priv *priv,
uniphier_fi2c_reset(priv);
tmp = clk_rate / bus_speed;
writel(tmp, priv->membase + UNIPHIER_FI2C_CYC);
writel(tmp / 2, priv->membase + UNIPHIER_FI2C_LCTL);
writel(tmp / 2, priv->membase + UNIPHIER_FI2C_SSUT);
writel(tmp / 16, priv->membase + UNIPHIER_FI2C_DSUT);
writel(cyc, priv->membase + UNIPHIER_FI2C_CYC);
writel(cyc / 2, priv->membase + UNIPHIER_FI2C_LCTL);
writel(cyc / 2, priv->membase + UNIPHIER_FI2C_SSUT);
writel(cyc / 16, priv->membase + UNIPHIER_FI2C_DSUT);
uniphier_fi2c_prepare_operation(priv);
}
@ -531,6 +530,7 @@ static int uniphier_fi2c_probe(struct platform_device *pdev)
goto disable_clk;
}
priv->clk_cycle = clk_rate / bus_speed;
init_completion(&priv->comp);
priv->adap.owner = THIS_MODULE;
priv->adap.algo = &uniphier_fi2c_algo;
@ -541,7 +541,7 @@ static int uniphier_fi2c_probe(struct platform_device *pdev)
i2c_set_adapdata(&priv->adap, priv);
platform_set_drvdata(pdev, priv);
uniphier_fi2c_hw_init(priv, bus_speed, clk_rate);
uniphier_fi2c_hw_init(priv);
ret = devm_request_irq(dev, irq, uniphier_fi2c_interrupt, 0,
pdev->name, priv);
@ -568,6 +568,33 @@ static int uniphier_fi2c_remove(struct platform_device *pdev)
return 0;
}
static int __maybe_unused uniphier_fi2c_suspend(struct device *dev)
{
struct uniphier_fi2c_priv *priv = dev_get_drvdata(dev);
clk_disable_unprepare(priv->clk);
return 0;
}
static int __maybe_unused uniphier_fi2c_resume(struct device *dev)
{
struct uniphier_fi2c_priv *priv = dev_get_drvdata(dev);
int ret;
ret = clk_prepare_enable(priv->clk);
if (ret)
return ret;
uniphier_fi2c_hw_init(priv);
return 0;
}
static const struct dev_pm_ops uniphier_fi2c_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(uniphier_fi2c_suspend, uniphier_fi2c_resume)
};
static const struct of_device_id uniphier_fi2c_match[] = {
{ .compatible = "socionext,uniphier-fi2c" },
{ /* sentinel */ }
@ -580,6 +607,7 @@ static struct platform_driver uniphier_fi2c_drv = {
.driver = {
.name = "uniphier-fi2c",
.of_match_table = uniphier_fi2c_match,
.pm = &uniphier_fi2c_pm_ops,
},
};
module_platform_driver(uniphier_fi2c_drv);

View File

@ -53,6 +53,7 @@ struct uniphier_i2c_priv {
void __iomem *membase;
struct clk *clk;
unsigned int busy_cnt;
unsigned int clk_cycle;
};
static irqreturn_t uniphier_i2c_interrupt(int irq, void *dev_id)
@ -316,13 +317,13 @@ static struct i2c_bus_recovery_info uniphier_i2c_bus_recovery_info = {
.unprepare_recovery = uniphier_i2c_unprepare_recovery,
};
static void uniphier_i2c_hw_init(struct uniphier_i2c_priv *priv,
u32 bus_speed, unsigned long clk_rate)
static void uniphier_i2c_hw_init(struct uniphier_i2c_priv *priv)
{
unsigned int cyc = priv->clk_cycle;
uniphier_i2c_reset(priv, true);
writel((clk_rate / bus_speed / 2 << 16) | (clk_rate / bus_speed),
priv->membase + UNIPHIER_I2C_CLK);
writel((cyc / 2 << 16) | cyc, priv->membase + UNIPHIER_I2C_CLK);
uniphier_i2c_reset(priv, false);
}
@ -376,6 +377,7 @@ static int uniphier_i2c_probe(struct platform_device *pdev)
goto disable_clk;
}
priv->clk_cycle = clk_rate / bus_speed;
init_completion(&priv->comp);
priv->adap.owner = THIS_MODULE;
priv->adap.algo = &uniphier_i2c_algo;
@ -386,7 +388,7 @@ static int uniphier_i2c_probe(struct platform_device *pdev)
i2c_set_adapdata(&priv->adap, priv);
platform_set_drvdata(pdev, priv);
uniphier_i2c_hw_init(priv, bus_speed, clk_rate);
uniphier_i2c_hw_init(priv);
ret = devm_request_irq(dev, irq, uniphier_i2c_interrupt, 0, pdev->name,
priv);
@ -413,6 +415,33 @@ static int uniphier_i2c_remove(struct platform_device *pdev)
return 0;
}
static int __maybe_unused uniphier_i2c_suspend(struct device *dev)
{
struct uniphier_i2c_priv *priv = dev_get_drvdata(dev);
clk_disable_unprepare(priv->clk);
return 0;
}
static int __maybe_unused uniphier_i2c_resume(struct device *dev)
{
struct uniphier_i2c_priv *priv = dev_get_drvdata(dev);
int ret;
ret = clk_prepare_enable(priv->clk);
if (ret)
return ret;
uniphier_i2c_hw_init(priv);
return 0;
}
static const struct dev_pm_ops uniphier_i2c_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(uniphier_i2c_suspend, uniphier_i2c_resume)
};
static const struct of_device_id uniphier_i2c_match[] = {
{ .compatible = "socionext,uniphier-i2c" },
{ /* sentinel */ }
@ -425,6 +454,7 @@ static struct platform_driver uniphier_i2c_drv = {
.driver = {
.name = "uniphier-i2c",
.of_match_table = uniphier_i2c_match,
.pm = &uniphier_i2c_pm_ops,
},
};
module_platform_driver(uniphier_i2c_drv);

View File

@ -55,7 +55,7 @@ static int i2c_versatile_getscl(void *data)
return !!(readl(i2c->base + I2C_CONTROL) & SCL);
}
static struct i2c_algo_bit_data i2c_versatile_algo = {
static const struct i2c_algo_bit_data i2c_versatile_algo = {
.setsda = i2c_versatile_setsda,
.setscl = i2c_versatile_setscl,
.getsda = i2c_versatile_getsda,

View File

@ -721,7 +721,7 @@ static const struct i2c_algorithm xiic_algorithm = {
.functionality = xiic_func,
};
static struct i2c_adapter xiic_adapter = {
static const struct i2c_adapter xiic_adapter = {
.owner = THIS_MODULE,
.name = DRIVER_NAME,
.class = I2C_CLASS_DEPRECATED,
@ -853,8 +853,7 @@ MODULE_DEVICE_TABLE(of, xiic_of_match);
static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct xiic_i2c *i2c = platform_get_drvdata(pdev);
struct xiic_i2c *i2c = dev_get_drvdata(dev);
clk_disable(i2c->clk);
@ -863,8 +862,7 @@ static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev)
static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct xiic_i2c *i2c = platform_get_drvdata(pdev);
struct xiic_i2c *i2c = dev_get_drvdata(dev);
int ret;
ret = clk_enable(i2c->clk);

View File

@ -32,18 +32,17 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
u32 addr;
int len;
dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name);
dev_dbg(&adap->dev, "of_i2c: register %pOF\n", node);
if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
dev_err(&adap->dev, "of_i2c: modalias failure on %s\n",
node->full_name);
dev_err(&adap->dev, "of_i2c: modalias failure on %pOF\n",
node);
return ERR_PTR(-EINVAL);
}
addr_be = of_get_property(node, "reg", &len);
if (!addr_be || (len < sizeof(*addr_be))) {
dev_err(&adap->dev, "of_i2c: invalid reg on %s\n",
node->full_name);
dev_err(&adap->dev, "of_i2c: invalid reg on %pOF\n", node);
return ERR_PTR(-EINVAL);
}
@ -59,8 +58,8 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
}
if (i2c_check_addr_validity(addr, info.flags)) {
dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",
addr, node->full_name);
dev_err(&adap->dev, "of_i2c: invalid addr=%x on %pOF\n",
addr, node);
return ERR_PTR(-EINVAL);
}
@ -76,8 +75,7 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
result = i2c_new_device(adap, &info);
if (result == NULL) {
dev_err(&adap->dev, "of_i2c: Failure registering %s\n",
node->full_name);
dev_err(&adap->dev, "of_i2c: Failure registering %pOF\n", node);
of_node_put(node);
return ERR_PTR(-EINVAL);
}
@ -106,8 +104,8 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
client = of_i2c_register_device(adap, node);
if (IS_ERR(client)) {
dev_warn(&adap->dev,
"Failed to create I2C device for %s\n",
node->full_name);
"Failed to create I2C device for %pOF\n",
node);
of_node_clear_flag(node, OF_POPULATED);
}
}
@ -243,8 +241,8 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action,
put_device(&adap->dev);
if (IS_ERR(client)) {
dev_err(&adap->dev, "failed to create client for '%s'\n",
rd->dn->full_name);
dev_err(&adap->dev, "failed to create client for '%pOF'\n",
rd->dn);
of_node_clear_flag(rd->dn, OF_POPULATED);
return notifier_from_errno(PTR_ERR(client));
}

View File

@ -8,7 +8,7 @@ menu "Multiplexer I2C Chip support"
config I2C_ARB_GPIO_CHALLENGE
tristate "GPIO-based I2C arbitration"
depends on GPIOLIB || COMPILE_TEST
depends on OF
depends on OF || COMPILE_TEST
help
If you say yes to this option, support will be included for an
I2C multimaster arbitration scheme using GPIOs and a challenge &
@ -76,6 +76,7 @@ config I2C_MUX_PCA954x
config I2C_MUX_PINCTRL
tristate "pinctrl-based I2C multiplexer"
depends on PINCTRL
depends on OF || COMPILE_TEST
help
If you say yes to this option, support will be included for an I2C
multiplexer that uses the pinctrl subsystem, i.e. pin multiplexing.

View File

@ -167,8 +167,8 @@ static ssize_t available_masters_show(struct device *dev,
int count = 0, i;
for (i = 0; i < priv->num_chan && count < PAGE_SIZE; i++)
count += scnprintf(buf + count, PAGE_SIZE - count, "%d:%s%c",
i, priv->chan[i].parent_np->full_name,
count += scnprintf(buf + count, PAGE_SIZE - count, "%d:%pOF%c",
i, priv->chan[i].parent_np,
i == priv->num_chan - 1 ? '\n' : ' ');
return count;

View File

@ -38,9 +38,9 @@
#include <linux/io.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_data/x86/mlxcpld.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/i2c/mlxcpld.h>
#define CPLD_MUX_MAX_NCHANS 8

View File

@ -16,15 +16,14 @@
* warranty of any kind, whether express or implied.
*/
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
#include <linux/i2c/pca954x.h>
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/platform_data/pca954x.h>
#include <linux/slab.h>
/*
* The PCA9541 is a bus master selector. It supports two I2C masters connected

View File

@ -39,13 +39,13 @@
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
#include <linux/i2c/pca954x.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/platform_data/pca954x.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include <linux/spinlock.h>

View File

@ -20,17 +20,14 @@
#include <linux/i2c-mux.h>
#include <linux/module.h>
#include <linux/pinctrl/consumer.h>
#include <linux/i2c-mux-pinctrl.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/of.h>
#include "../../pinctrl/core.h"
struct i2c_mux_pinctrl {
struct i2c_mux_pinctrl_platform_data *pdata;
struct pinctrl *pinctrl;
struct pinctrl_state **states;
struct pinctrl_state *state_idle;
};
static int i2c_mux_pinctrl_select(struct i2c_mux_core *muxc, u32 chan)
@ -42,85 +39,9 @@ static int i2c_mux_pinctrl_select(struct i2c_mux_core *muxc, u32 chan)
static int i2c_mux_pinctrl_deselect(struct i2c_mux_core *muxc, u32 chan)
{
struct i2c_mux_pinctrl *mux = i2c_mux_priv(muxc);
return pinctrl_select_state(mux->pinctrl, mux->state_idle);
return i2c_mux_pinctrl_select(muxc, muxc->num_adapters);
}
#ifdef CONFIG_OF
static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
int num_names, i, ret;
struct device_node *adapter_np;
struct i2c_adapter *adapter;
if (!np)
return 0;
mux->pdata = devm_kzalloc(&pdev->dev, sizeof(*mux->pdata), GFP_KERNEL);
if (!mux->pdata)
return -ENOMEM;
num_names = of_property_count_strings(np, "pinctrl-names");
if (num_names < 0) {
dev_err(&pdev->dev, "Cannot parse pinctrl-names: %d\n",
num_names);
return num_names;
}
mux->pdata->pinctrl_states = devm_kzalloc(&pdev->dev,
sizeof(*mux->pdata->pinctrl_states) * num_names,
GFP_KERNEL);
if (!mux->pdata->pinctrl_states)
return -ENOMEM;
for (i = 0; i < num_names; i++) {
ret = of_property_read_string_index(np, "pinctrl-names", i,
&mux->pdata->pinctrl_states[mux->pdata->bus_count]);
if (ret < 0) {
dev_err(&pdev->dev, "Cannot parse pinctrl-names: %d\n",
ret);
return ret;
}
if (!strcmp(mux->pdata->pinctrl_states[mux->pdata->bus_count],
"idle")) {
if (i != num_names - 1) {
dev_err(&pdev->dev,
"idle state must be last\n");
return -EINVAL;
}
mux->pdata->pinctrl_state_idle = "idle";
} else {
mux->pdata->bus_count++;
}
}
adapter_np = of_parse_phandle(np, "i2c-parent", 0);
if (!adapter_np) {
dev_err(&pdev->dev, "Cannot parse i2c-parent\n");
return -ENODEV;
}
adapter = of_find_i2c_adapter_by_node(adapter_np);
of_node_put(adapter_np);
if (!adapter) {
dev_err(&pdev->dev, "Cannot find parent bus\n");
return -EPROBE_DEFER;
}
mux->pdata->parent_bus_num = i2c_adapter_id(adapter);
put_device(&adapter->dev);
return 0;
}
#else
static inline int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux,
struct platform_device *pdev)
{
return 0;
}
#endif
static struct i2c_adapter *i2c_mux_pinctrl_root_adapter(
struct pinctrl_state *state)
{
@ -141,110 +62,108 @@ static struct i2c_adapter *i2c_mux_pinctrl_root_adapter(
return root;
}
static struct i2c_adapter *i2c_mux_pinctrl_parent_adapter(struct device *dev)
{
struct device_node *np = dev->of_node;
struct device_node *parent_np;
struct i2c_adapter *parent;
parent_np = of_parse_phandle(np, "i2c-parent", 0);
if (!parent_np) {
dev_err(dev, "Cannot parse i2c-parent\n");
return ERR_PTR(-ENODEV);
}
parent = of_find_i2c_adapter_by_node(parent_np);
of_node_put(parent_np);
if (!parent)
return ERR_PTR(-EPROBE_DEFER);
return parent;
}
static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct i2c_mux_core *muxc;
struct i2c_mux_pinctrl *mux;
struct i2c_adapter *parent;
struct i2c_adapter *root;
int i, ret;
int num_names, i, ret;
const char *name;
mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
if (!mux) {
ret = -ENOMEM;
goto err;
num_names = of_property_count_strings(np, "pinctrl-names");
if (num_names < 0) {
dev_err(dev, "Cannot parse pinctrl-names: %d\n",
num_names);
return num_names;
}
mux->pdata = dev_get_platdata(&pdev->dev);
if (!mux->pdata) {
ret = i2c_mux_pinctrl_parse_dt(mux, pdev);
if (ret < 0)
goto err;
}
if (!mux->pdata) {
dev_err(&pdev->dev, "Missing platform data\n");
ret = -ENODEV;
goto err;
}
parent = i2c_mux_pinctrl_parent_adapter(dev);
if (IS_ERR(parent))
return PTR_ERR(parent);
mux->states = devm_kzalloc(&pdev->dev,
sizeof(*mux->states) * mux->pdata->bus_count,
GFP_KERNEL);
if (!mux->states) {
dev_err(&pdev->dev, "Cannot allocate states\n");
ret = -ENOMEM;
goto err;
}
muxc = i2c_mux_alloc(NULL, &pdev->dev, mux->pdata->bus_count, 0, 0,
i2c_mux_pinctrl_select, NULL);
muxc = i2c_mux_alloc(parent, dev, num_names,
sizeof(*mux) + num_names * sizeof(*mux->states),
0, i2c_mux_pinctrl_select, NULL);
if (!muxc) {
ret = -ENOMEM;
goto err;
goto err_put_parent;
}
muxc->priv = mux;
mux = i2c_mux_priv(muxc);
mux->states = (struct pinctrl_state **)(mux + 1);
platform_set_drvdata(pdev, muxc);
mux->pinctrl = devm_pinctrl_get(&pdev->dev);
mux->pinctrl = devm_pinctrl_get(dev);
if (IS_ERR(mux->pinctrl)) {
ret = PTR_ERR(mux->pinctrl);
dev_err(&pdev->dev, "Cannot get pinctrl: %d\n", ret);
goto err;
dev_err(dev, "Cannot get pinctrl: %d\n", ret);
goto err_put_parent;
}
for (i = 0; i < mux->pdata->bus_count; i++) {
mux->states[i] = pinctrl_lookup_state(mux->pinctrl,
mux->pdata->pinctrl_states[i]);
for (i = 0; i < num_names; i++) {
ret = of_property_read_string_index(np, "pinctrl-names", i,
&name);
if (ret < 0) {
dev_err(dev, "Cannot parse pinctrl-names: %d\n", ret);
goto err_put_parent;
}
mux->states[i] = pinctrl_lookup_state(mux->pinctrl, name);
if (IS_ERR(mux->states[i])) {
ret = PTR_ERR(mux->states[i]);
dev_err(&pdev->dev,
"Cannot look up pinctrl state %s: %d\n",
mux->pdata->pinctrl_states[i], ret);
goto err;
}
}
if (mux->pdata->pinctrl_state_idle) {
mux->state_idle = pinctrl_lookup_state(mux->pinctrl,
mux->pdata->pinctrl_state_idle);
if (IS_ERR(mux->state_idle)) {
ret = PTR_ERR(mux->state_idle);
dev_err(&pdev->dev,
"Cannot look up pinctrl state %s: %d\n",
mux->pdata->pinctrl_state_idle, ret);
goto err;
dev_err(dev, "Cannot look up pinctrl state %s: %d\n",
name, ret);
goto err_put_parent;
}
if (strcmp(name, "idle"))
continue;
if (i != num_names - 1) {
dev_err(dev, "idle state must be last\n");
ret = -EINVAL;
goto err_put_parent;
}
muxc->deselect = i2c_mux_pinctrl_deselect;
}
muxc->parent = i2c_get_adapter(mux->pdata->parent_bus_num);
if (!muxc->parent) {
dev_err(&pdev->dev, "Parent adapter (%d) not found\n",
mux->pdata->parent_bus_num);
ret = -EPROBE_DEFER;
goto err;
}
root = i2c_root_adapter(&muxc->parent->dev);
muxc->mux_locked = true;
for (i = 0; i < mux->pdata->bus_count; i++) {
for (i = 0; i < num_names; i++) {
if (root != i2c_mux_pinctrl_root_adapter(mux->states[i])) {
muxc->mux_locked = false;
break;
}
}
if (muxc->mux_locked && mux->pdata->pinctrl_state_idle &&
root != i2c_mux_pinctrl_root_adapter(mux->state_idle))
muxc->mux_locked = false;
if (muxc->mux_locked)
dev_info(&pdev->dev, "mux-locked i2c mux\n");
dev_info(dev, "mux-locked i2c mux\n");
for (i = 0; i < mux->pdata->bus_count; i++) {
u32 bus = mux->pdata->base_bus_num ?
(mux->pdata->base_bus_num + i) : 0;
ret = i2c_mux_add_adapter(muxc, bus, i, 0);
/* Do not add any adapter for the idle state (if it's there at all). */
for (i = 0; i < num_names - !!muxc->deselect; i++) {
ret = i2c_mux_add_adapter(muxc, 0, i, 0);
if (ret)
goto err_del_adapter;
}
@ -253,8 +172,9 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev)
err_del_adapter:
i2c_mux_del_adapters(muxc);
i2c_put_adapter(muxc->parent);
err:
err_put_parent:
i2c_put_adapter(parent);
return ret;
}
@ -264,16 +184,15 @@ static int i2c_mux_pinctrl_remove(struct platform_device *pdev)
i2c_mux_del_adapters(muxc);
i2c_put_adapter(muxc->parent);
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id i2c_mux_pinctrl_of_match[] = {
{ .compatible = "i2c-mux-pinctrl", },
{},
};
MODULE_DEVICE_TABLE(of, i2c_mux_pinctrl_of_match);
#endif
static struct platform_driver i2c_mux_pinctrl_driver = {
.driver = {

View File

@ -1,41 +0,0 @@
/*
* i2c-mux-pinctrl platform data
*
* Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _LINUX_I2C_MUX_PINCTRL_H
#define _LINUX_I2C_MUX_PINCTRL_H
/**
* struct i2c_mux_pinctrl_platform_data - Platform data for i2c-mux-pinctrl
* @parent_bus_num: Parent I2C bus number
* @base_bus_num: Base I2C bus number for the child busses. 0 for dynamic.
* @bus_count: Number of child busses. Also the number of elements in
* @pinctrl_states
* @pinctrl_states: The names of the pinctrl state to select for each child bus
* @pinctrl_state_idle: The pinctrl state to select when no child bus is being
* accessed. If NULL, the most recently used pinctrl state will be left
* selected.
*/
struct i2c_mux_pinctrl_platform_data {
int parent_bus_num;
int base_bus_num;
int bus_count;
const char **pinctrl_states;
const char *pinctrl_state_idle;
};
#endif

View File

@ -1,145 +0,0 @@
/*
* i2c-bfin-twi.h - interface to ADI TWI controller
*
* Copyright 2005-2014 Analog Devices Inc.
*
* Licensed under the GPL-2 or later.
*/
#ifndef __I2C_BFIN_TWI_H__
#define __I2C_BFIN_TWI_H__
#include <linux/types.h>
#include <linux/i2c.h>
/*
* ADI twi registers layout
*/
struct bfin_twi_regs {
u16 clkdiv;
u16 dummy1;
u16 control;
u16 dummy2;
u16 slave_ctl;
u16 dummy3;
u16 slave_stat;
u16 dummy4;
u16 slave_addr;
u16 dummy5;
u16 master_ctl;
u16 dummy6;
u16 master_stat;
u16 dummy7;
u16 master_addr;
u16 dummy8;
u16 int_stat;
u16 dummy9;
u16 int_mask;
u16 dummy10;
u16 fifo_ctl;
u16 dummy11;
u16 fifo_stat;
u16 dummy12;
u32 __pad[20];
u16 xmt_data8;
u16 dummy13;
u16 xmt_data16;
u16 dummy14;
u16 rcv_data8;
u16 dummy15;
u16 rcv_data16;
u16 dummy16;
};
struct bfin_twi_iface {
int irq;
spinlock_t lock;
char read_write;
u8 command;
u8 *transPtr;
int readNum;
int writeNum;
int cur_mode;
int manual_stop;
int result;
struct i2c_adapter adap;
struct completion complete;
struct i2c_msg *pmsg;
int msg_num;
int cur_msg;
u16 saved_clkdiv;
u16 saved_control;
struct bfin_twi_regs __iomem *regs_base;
};
/* ******************** TWO-WIRE INTERFACE (TWI) MASKS ********************/
/* TWI_CLKDIV Macros (Use: *pTWI_CLKDIV = CLKLOW(x)|CLKHI(y); ) */
#define CLKLOW(x) ((x) & 0xFF) /* Periods Clock Is Held Low */
#define CLKHI(y) (((y)&0xFF)<<0x8) /* Periods Before New Clock Low */
/* TWI_PRESCALE Masks */
#define PRESCALE 0x007F /* SCLKs Per Internal Time Reference (10MHz) */
#define TWI_ENA 0x0080 /* TWI Enable */
#define SCCB 0x0200 /* SCCB Compatibility Enable */
/* TWI_SLAVE_CTL Masks */
#define SEN 0x0001 /* Slave Enable */
#define SADD_LEN 0x0002 /* Slave Address Length */
#define STDVAL 0x0004 /* Slave Transmit Data Valid */
#define NAK 0x0008 /* NAK Generated At Conclusion Of Transfer */
#define GEN 0x0010 /* General Call Address Matching Enabled */
/* TWI_SLAVE_STAT Masks */
#define SDIR 0x0001 /* Slave Transfer Direction (RX/TX*) */
#define GCALL 0x0002 /* General Call Indicator */
/* TWI_MASTER_CTL Masks */
#define MEN 0x0001 /* Master Mode Enable */
#define MADD_LEN 0x0002 /* Master Address Length */
#define MDIR 0x0004 /* Master Transmit Direction (RX/TX*) */
#define FAST 0x0008 /* Use Fast Mode Timing Specs */
#define STOP 0x0010 /* Issue Stop Condition */
#define RSTART 0x0020 /* Repeat Start or Stop* At End Of Transfer */
#define DCNT 0x3FC0 /* Data Bytes To Transfer */
#define SDAOVR 0x4000 /* Serial Data Override */
#define SCLOVR 0x8000 /* Serial Clock Override */
/* TWI_MASTER_STAT Masks */
#define MPROG 0x0001 /* Master Transfer In Progress */
#define LOSTARB 0x0002 /* Lost Arbitration Indicator (Xfer Aborted) */
#define ANAK 0x0004 /* Address Not Acknowledged */
#define DNAK 0x0008 /* Data Not Acknowledged */
#define BUFRDERR 0x0010 /* Buffer Read Error */
#define BUFWRERR 0x0020 /* Buffer Write Error */
#define SDASEN 0x0040 /* Serial Data Sense */
#define SCLSEN 0x0080 /* Serial Clock Sense */
#define BUSBUSY 0x0100 /* Bus Busy Indicator */
/* TWI_INT_SRC and TWI_INT_ENABLE Masks */
#define SINIT 0x0001 /* Slave Transfer Initiated */
#define SCOMP 0x0002 /* Slave Transfer Complete */
#define SERR 0x0004 /* Slave Transfer Error */
#define SOVF 0x0008 /* Slave Overflow */
#define MCOMP 0x0010 /* Master Transfer Complete */
#define MERR 0x0020 /* Master Transfer Error */
#define XMTSERV 0x0040 /* Transmit FIFO Service */
#define RCVSERV 0x0080 /* Receive FIFO Service */
/* TWI_FIFO_CTRL Masks */
#define XMTFLUSH 0x0001 /* Transmit Buffer Flush */
#define RCVFLUSH 0x0002 /* Receive Buffer Flush */
#define XMTINTLEN 0x0004 /* Transmit Buffer Interrupt Length */
#define RCVINTLEN 0x0008 /* Receive Buffer Interrupt Length */
/* TWI_FIFO_STAT Masks */
#define XMTSTAT 0x0003 /* Transmit FIFO Status */
#define XMT_EMPTY 0x0000 /* Transmit FIFO Empty */
#define XMT_HALF 0x0001 /* Transmit FIFO Has 1 Byte To Write */
#define XMT_FULL 0x0003 /* Transmit FIFO Full (2 Bytes To Write) */
#define RCVSTAT 0x000C /* Receive FIFO Status */
#define RCV_EMPTY 0x0000 /* Receive FIFO Empty */
#define RCV_HALF 0x0004 /* Receive FIFO Has 1 Byte To Read */
#define RCV_FULL 0x000C /* Receive FIFO Full (2 Bytes To Read) */
#endif