162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2012 FUJITSU SEMICONDUCTOR LIMITED 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/acpi.h> 762306a36Sopenharmony_ci#include <linux/clk.h> 862306a36Sopenharmony_ci#include <linux/delay.h> 962306a36Sopenharmony_ci#include <linux/device.h> 1062306a36Sopenharmony_ci#include <linux/err.h> 1162306a36Sopenharmony_ci#include <linux/errno.h> 1262306a36Sopenharmony_ci#include <linux/i2c.h> 1362306a36Sopenharmony_ci#include <linux/interrupt.h> 1462306a36Sopenharmony_ci#include <linux/io.h> 1562306a36Sopenharmony_ci#include <linux/kernel.h> 1662306a36Sopenharmony_ci#include <linux/module.h> 1762306a36Sopenharmony_ci#include <linux/platform_device.h> 1862306a36Sopenharmony_ci#include <linux/sched.h> 1962306a36Sopenharmony_ci#include <linux/slab.h> 2062306a36Sopenharmony_ci#include <linux/spinlock.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#define WAIT_PCLK(n, rate) \ 2362306a36Sopenharmony_ci ndelay(DIV_ROUND_UP(DIV_ROUND_UP(1000000000, rate), n) + 10) 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* I2C register address definitions */ 2662306a36Sopenharmony_ci#define SYNQUACER_I2C_REG_BSR (0x00 << 2) // Bus Status 2762306a36Sopenharmony_ci#define SYNQUACER_I2C_REG_BCR (0x01 << 2) // Bus Control 2862306a36Sopenharmony_ci#define SYNQUACER_I2C_REG_CCR (0x02 << 2) // Clock Control 2962306a36Sopenharmony_ci#define SYNQUACER_I2C_REG_ADR (0x03 << 2) // Address 3062306a36Sopenharmony_ci#define SYNQUACER_I2C_REG_DAR (0x04 << 2) // Data 3162306a36Sopenharmony_ci#define SYNQUACER_I2C_REG_CSR (0x05 << 2) // Expansion CS 3262306a36Sopenharmony_ci#define SYNQUACER_I2C_REG_FSR (0x06 << 2) // Bus Clock Freq 3362306a36Sopenharmony_ci#define SYNQUACER_I2C_REG_BC2R (0x07 << 2) // Bus Control 2 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* I2C register bit definitions */ 3662306a36Sopenharmony_ci#define SYNQUACER_I2C_BSR_FBT BIT(0) // First Byte Transfer 3762306a36Sopenharmony_ci#define SYNQUACER_I2C_BSR_GCA BIT(1) // General Call Address 3862306a36Sopenharmony_ci#define SYNQUACER_I2C_BSR_AAS BIT(2) // Address as Slave 3962306a36Sopenharmony_ci#define SYNQUACER_I2C_BSR_TRX BIT(3) // Transfer/Receive 4062306a36Sopenharmony_ci#define SYNQUACER_I2C_BSR_LRB BIT(4) // Last Received Bit 4162306a36Sopenharmony_ci#define SYNQUACER_I2C_BSR_AL BIT(5) // Arbitration Lost 4262306a36Sopenharmony_ci#define SYNQUACER_I2C_BSR_RSC BIT(6) // Repeated Start Cond. 4362306a36Sopenharmony_ci#define SYNQUACER_I2C_BSR_BB BIT(7) // Bus Busy 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#define SYNQUACER_I2C_BCR_INT BIT(0) // Interrupt 4662306a36Sopenharmony_ci#define SYNQUACER_I2C_BCR_INTE BIT(1) // Interrupt Enable 4762306a36Sopenharmony_ci#define SYNQUACER_I2C_BCR_GCAA BIT(2) // Gen. Call Access Ack. 4862306a36Sopenharmony_ci#define SYNQUACER_I2C_BCR_ACK BIT(3) // Acknowledge 4962306a36Sopenharmony_ci#define SYNQUACER_I2C_BCR_MSS BIT(4) // Master Slave Select 5062306a36Sopenharmony_ci#define SYNQUACER_I2C_BCR_SCC BIT(5) // Start Condition Cont. 5162306a36Sopenharmony_ci#define SYNQUACER_I2C_BCR_BEIE BIT(6) // Bus Error Int Enable 5262306a36Sopenharmony_ci#define SYNQUACER_I2C_BCR_BER BIT(7) // Bus Error 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#define SYNQUACER_I2C_CCR_CS_MASK (0x1f) // CCR Clock Period Sel. 5562306a36Sopenharmony_ci#define SYNQUACER_I2C_CCR_EN BIT(5) // Enable 5662306a36Sopenharmony_ci#define SYNQUACER_I2C_CCR_FM BIT(6) // Speed Mode Select 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci#define SYNQUACER_I2C_CSR_CS_MASK (0x3f) // CSR Clock Period Sel. 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#define SYNQUACER_I2C_BC2R_SCLL BIT(0) // SCL Low Drive 6162306a36Sopenharmony_ci#define SYNQUACER_I2C_BC2R_SDAL BIT(1) // SDA Low Drive 6262306a36Sopenharmony_ci#define SYNQUACER_I2C_BC2R_SCLS BIT(4) // SCL Status 6362306a36Sopenharmony_ci#define SYNQUACER_I2C_BC2R_SDAS BIT(5) // SDA Status 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci/* PCLK frequency */ 6662306a36Sopenharmony_ci#define SYNQUACER_I2C_BUS_CLK_FR(rate) (((rate) / 20000000) + 1) 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/* STANDARD MODE frequency */ 6962306a36Sopenharmony_ci#define SYNQUACER_I2C_CLK_MASTER_STD(rate) \ 7062306a36Sopenharmony_ci DIV_ROUND_UP(DIV_ROUND_UP((rate), I2C_MAX_STANDARD_MODE_FREQ) - 2, 2) 7162306a36Sopenharmony_ci/* FAST MODE frequency */ 7262306a36Sopenharmony_ci#define SYNQUACER_I2C_CLK_MASTER_FAST(rate) \ 7362306a36Sopenharmony_ci DIV_ROUND_UP((DIV_ROUND_UP((rate), I2C_MAX_FAST_MODE_FREQ) - 2) * 2, 3) 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci/* (clkrate <= 18000000) */ 7662306a36Sopenharmony_ci/* calculate the value of CS bits in CCR register on standard mode */ 7762306a36Sopenharmony_ci#define SYNQUACER_I2C_CCR_CS_STD_MAX_18M(rate) \ 7862306a36Sopenharmony_ci ((SYNQUACER_I2C_CLK_MASTER_STD(rate) - 65) \ 7962306a36Sopenharmony_ci & SYNQUACER_I2C_CCR_CS_MASK) 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci/* calculate the value of CS bits in CSR register on standard mode */ 8262306a36Sopenharmony_ci#define SYNQUACER_I2C_CSR_CS_STD_MAX_18M(rate) 0x00 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci/* calculate the value of CS bits in CCR register on fast mode */ 8562306a36Sopenharmony_ci#define SYNQUACER_I2C_CCR_CS_FAST_MAX_18M(rate) \ 8662306a36Sopenharmony_ci ((SYNQUACER_I2C_CLK_MASTER_FAST(rate) - 1) \ 8762306a36Sopenharmony_ci & SYNQUACER_I2C_CCR_CS_MASK) 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci/* calculate the value of CS bits in CSR register on fast mode */ 9062306a36Sopenharmony_ci#define SYNQUACER_I2C_CSR_CS_FAST_MAX_18M(rate) 0x00 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci/* (clkrate > 18000000) */ 9362306a36Sopenharmony_ci/* calculate the value of CS bits in CCR register on standard mode */ 9462306a36Sopenharmony_ci#define SYNQUACER_I2C_CCR_CS_STD_MIN_18M(rate) \ 9562306a36Sopenharmony_ci ((SYNQUACER_I2C_CLK_MASTER_STD(rate) - 1) \ 9662306a36Sopenharmony_ci & SYNQUACER_I2C_CCR_CS_MASK) 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci/* calculate the value of CS bits in CSR register on standard mode */ 9962306a36Sopenharmony_ci#define SYNQUACER_I2C_CSR_CS_STD_MIN_18M(rate) \ 10062306a36Sopenharmony_ci (((SYNQUACER_I2C_CLK_MASTER_STD(rate) - 1) >> 5) \ 10162306a36Sopenharmony_ci & SYNQUACER_I2C_CSR_CS_MASK) 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci/* calculate the value of CS bits in CCR register on fast mode */ 10462306a36Sopenharmony_ci#define SYNQUACER_I2C_CCR_CS_FAST_MIN_18M(rate) \ 10562306a36Sopenharmony_ci ((SYNQUACER_I2C_CLK_MASTER_FAST(rate) - 1) \ 10662306a36Sopenharmony_ci & SYNQUACER_I2C_CCR_CS_MASK) 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci/* calculate the value of CS bits in CSR register on fast mode */ 10962306a36Sopenharmony_ci#define SYNQUACER_I2C_CSR_CS_FAST_MIN_18M(rate) \ 11062306a36Sopenharmony_ci (((SYNQUACER_I2C_CLK_MASTER_FAST(rate) - 1) >> 5) \ 11162306a36Sopenharmony_ci & SYNQUACER_I2C_CSR_CS_MASK) 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci/* min I2C clock frequency 14M */ 11462306a36Sopenharmony_ci#define SYNQUACER_I2C_MIN_CLK_RATE (14 * 1000000) 11562306a36Sopenharmony_ci/* max I2C clock frequency 200M */ 11662306a36Sopenharmony_ci#define SYNQUACER_I2C_MAX_CLK_RATE (200 * 1000000) 11762306a36Sopenharmony_ci/* I2C clock frequency 18M */ 11862306a36Sopenharmony_ci#define SYNQUACER_I2C_CLK_RATE_18M (18 * 1000000) 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci#define SYNQUACER_I2C_SPEED_FM 400 // Fast Mode 12162306a36Sopenharmony_ci#define SYNQUACER_I2C_SPEED_SM 100 // Standard Mode 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cienum i2c_state { 12462306a36Sopenharmony_ci STATE_IDLE, 12562306a36Sopenharmony_ci STATE_START, 12662306a36Sopenharmony_ci STATE_READ, 12762306a36Sopenharmony_ci STATE_WRITE 12862306a36Sopenharmony_ci}; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistruct synquacer_i2c { 13162306a36Sopenharmony_ci struct completion completion; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci struct i2c_msg *msg; 13462306a36Sopenharmony_ci u32 msg_num; 13562306a36Sopenharmony_ci u32 msg_idx; 13662306a36Sopenharmony_ci u32 msg_ptr; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci int irq; 13962306a36Sopenharmony_ci struct device *dev; 14062306a36Sopenharmony_ci void __iomem *base; 14162306a36Sopenharmony_ci struct clk *pclk; 14262306a36Sopenharmony_ci u32 pclkrate; 14362306a36Sopenharmony_ci u32 speed_khz; 14462306a36Sopenharmony_ci u32 timeout_ms; 14562306a36Sopenharmony_ci enum i2c_state state; 14662306a36Sopenharmony_ci struct i2c_adapter adapter; 14762306a36Sopenharmony_ci}; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cistatic inline int is_lastmsg(struct synquacer_i2c *i2c) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci return i2c->msg_idx >= (i2c->msg_num - 1); 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistatic inline int is_msglast(struct synquacer_i2c *i2c) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci return i2c->msg_ptr == (i2c->msg->len - 1); 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic inline int is_msgend(struct synquacer_i2c *i2c) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci return i2c->msg_ptr >= i2c->msg->len; 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic inline unsigned long calc_timeout_ms(struct synquacer_i2c *i2c, 16562306a36Sopenharmony_ci struct i2c_msg *msgs, 16662306a36Sopenharmony_ci int num) 16762306a36Sopenharmony_ci{ 16862306a36Sopenharmony_ci unsigned long bit_count = 0; 16962306a36Sopenharmony_ci int i; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci for (i = 0; i < num; i++, msgs++) 17262306a36Sopenharmony_ci bit_count += msgs->len; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci return DIV_ROUND_UP((bit_count * 9 + num * 10) * 3, 200) + 10; 17562306a36Sopenharmony_ci} 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistatic void synquacer_i2c_stop(struct synquacer_i2c *i2c, int ret) 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci /* 18062306a36Sopenharmony_ci * clear IRQ (INT=0, BER=0) 18162306a36Sopenharmony_ci * set Stop Condition (MSS=0) 18262306a36Sopenharmony_ci * Interrupt Disable 18362306a36Sopenharmony_ci */ 18462306a36Sopenharmony_ci writeb(0, i2c->base + SYNQUACER_I2C_REG_BCR); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci i2c->state = STATE_IDLE; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci i2c->msg_ptr = 0; 18962306a36Sopenharmony_ci i2c->msg = NULL; 19062306a36Sopenharmony_ci i2c->msg_idx++; 19162306a36Sopenharmony_ci i2c->msg_num = 0; 19262306a36Sopenharmony_ci if (ret) 19362306a36Sopenharmony_ci i2c->msg_idx = ret; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci complete(&i2c->completion); 19662306a36Sopenharmony_ci} 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_cistatic void synquacer_i2c_hw_init(struct synquacer_i2c *i2c) 19962306a36Sopenharmony_ci{ 20062306a36Sopenharmony_ci unsigned char ccr_cs, csr_cs; 20162306a36Sopenharmony_ci u32 rt = i2c->pclkrate; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci /* Set own Address */ 20462306a36Sopenharmony_ci writeb(0, i2c->base + SYNQUACER_I2C_REG_ADR); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci /* Set PCLK frequency */ 20762306a36Sopenharmony_ci writeb(SYNQUACER_I2C_BUS_CLK_FR(i2c->pclkrate), 20862306a36Sopenharmony_ci i2c->base + SYNQUACER_I2C_REG_FSR); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci switch (i2c->speed_khz) { 21162306a36Sopenharmony_ci case SYNQUACER_I2C_SPEED_FM: 21262306a36Sopenharmony_ci if (i2c->pclkrate <= SYNQUACER_I2C_CLK_RATE_18M) { 21362306a36Sopenharmony_ci ccr_cs = SYNQUACER_I2C_CCR_CS_FAST_MAX_18M(rt); 21462306a36Sopenharmony_ci csr_cs = SYNQUACER_I2C_CSR_CS_FAST_MAX_18M(rt); 21562306a36Sopenharmony_ci } else { 21662306a36Sopenharmony_ci ccr_cs = SYNQUACER_I2C_CCR_CS_FAST_MIN_18M(rt); 21762306a36Sopenharmony_ci csr_cs = SYNQUACER_I2C_CSR_CS_FAST_MIN_18M(rt); 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci /* Set Clock and enable, Set fast mode */ 22162306a36Sopenharmony_ci writeb(ccr_cs | SYNQUACER_I2C_CCR_FM | 22262306a36Sopenharmony_ci SYNQUACER_I2C_CCR_EN, 22362306a36Sopenharmony_ci i2c->base + SYNQUACER_I2C_REG_CCR); 22462306a36Sopenharmony_ci writeb(csr_cs, i2c->base + SYNQUACER_I2C_REG_CSR); 22562306a36Sopenharmony_ci break; 22662306a36Sopenharmony_ci case SYNQUACER_I2C_SPEED_SM: 22762306a36Sopenharmony_ci if (i2c->pclkrate <= SYNQUACER_I2C_CLK_RATE_18M) { 22862306a36Sopenharmony_ci ccr_cs = SYNQUACER_I2C_CCR_CS_STD_MAX_18M(rt); 22962306a36Sopenharmony_ci csr_cs = SYNQUACER_I2C_CSR_CS_STD_MAX_18M(rt); 23062306a36Sopenharmony_ci } else { 23162306a36Sopenharmony_ci ccr_cs = SYNQUACER_I2C_CCR_CS_STD_MIN_18M(rt); 23262306a36Sopenharmony_ci csr_cs = SYNQUACER_I2C_CSR_CS_STD_MIN_18M(rt); 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci /* Set Clock and enable, Set standard mode */ 23662306a36Sopenharmony_ci writeb(ccr_cs | SYNQUACER_I2C_CCR_EN, 23762306a36Sopenharmony_ci i2c->base + SYNQUACER_I2C_REG_CCR); 23862306a36Sopenharmony_ci writeb(csr_cs, i2c->base + SYNQUACER_I2C_REG_CSR); 23962306a36Sopenharmony_ci break; 24062306a36Sopenharmony_ci default: 24162306a36Sopenharmony_ci WARN_ON(1); 24262306a36Sopenharmony_ci } 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci /* clear IRQ (INT=0, BER=0), Interrupt Disable */ 24562306a36Sopenharmony_ci writeb(0, i2c->base + SYNQUACER_I2C_REG_BCR); 24662306a36Sopenharmony_ci writeb(0, i2c->base + SYNQUACER_I2C_REG_BC2R); 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_cistatic void synquacer_i2c_hw_reset(struct synquacer_i2c *i2c) 25062306a36Sopenharmony_ci{ 25162306a36Sopenharmony_ci /* Disable clock */ 25262306a36Sopenharmony_ci writeb(0, i2c->base + SYNQUACER_I2C_REG_CCR); 25362306a36Sopenharmony_ci writeb(0, i2c->base + SYNQUACER_I2C_REG_CSR); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci WAIT_PCLK(100, i2c->pclkrate); 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_cistatic int synquacer_i2c_master_start(struct synquacer_i2c *i2c, 25962306a36Sopenharmony_ci struct i2c_msg *pmsg) 26062306a36Sopenharmony_ci{ 26162306a36Sopenharmony_ci unsigned char bsr, bcr; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci writeb(i2c_8bit_addr_from_msg(pmsg), i2c->base + SYNQUACER_I2C_REG_DAR); 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci dev_dbg(i2c->dev, "slave:0x%02x\n", pmsg->addr); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci /* Generate Start Condition */ 26862306a36Sopenharmony_ci bsr = readb(i2c->base + SYNQUACER_I2C_REG_BSR); 26962306a36Sopenharmony_ci bcr = readb(i2c->base + SYNQUACER_I2C_REG_BCR); 27062306a36Sopenharmony_ci dev_dbg(i2c->dev, "bsr:0x%02x, bcr:0x%02x\n", bsr, bcr); 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci if ((bsr & SYNQUACER_I2C_BSR_BB) && 27362306a36Sopenharmony_ci !(bcr & SYNQUACER_I2C_BCR_MSS)) { 27462306a36Sopenharmony_ci dev_dbg(i2c->dev, "bus is busy"); 27562306a36Sopenharmony_ci return -EBUSY; 27662306a36Sopenharmony_ci } 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci if (bsr & SYNQUACER_I2C_BSR_BB) { /* Bus is busy */ 27962306a36Sopenharmony_ci dev_dbg(i2c->dev, "Continuous Start"); 28062306a36Sopenharmony_ci writeb(bcr | SYNQUACER_I2C_BCR_SCC, 28162306a36Sopenharmony_ci i2c->base + SYNQUACER_I2C_REG_BCR); 28262306a36Sopenharmony_ci } else { 28362306a36Sopenharmony_ci if (bcr & SYNQUACER_I2C_BCR_MSS) { 28462306a36Sopenharmony_ci dev_dbg(i2c->dev, "not in master mode"); 28562306a36Sopenharmony_ci return -EAGAIN; 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci dev_dbg(i2c->dev, "Start Condition"); 28862306a36Sopenharmony_ci /* Start Condition + Enable Interrupts */ 28962306a36Sopenharmony_ci writeb(bcr | SYNQUACER_I2C_BCR_MSS | 29062306a36Sopenharmony_ci SYNQUACER_I2C_BCR_INTE | SYNQUACER_I2C_BCR_BEIE, 29162306a36Sopenharmony_ci i2c->base + SYNQUACER_I2C_REG_BCR); 29262306a36Sopenharmony_ci } 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci WAIT_PCLK(10, i2c->pclkrate); 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci /* get BSR & BCR registers */ 29762306a36Sopenharmony_ci bsr = readb(i2c->base + SYNQUACER_I2C_REG_BSR); 29862306a36Sopenharmony_ci bcr = readb(i2c->base + SYNQUACER_I2C_REG_BCR); 29962306a36Sopenharmony_ci dev_dbg(i2c->dev, "bsr:0x%02x, bcr:0x%02x\n", bsr, bcr); 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci if ((bsr & SYNQUACER_I2C_BSR_AL) || 30262306a36Sopenharmony_ci !(bcr & SYNQUACER_I2C_BCR_MSS)) { 30362306a36Sopenharmony_ci dev_dbg(i2c->dev, "arbitration lost\n"); 30462306a36Sopenharmony_ci return -EAGAIN; 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci return 0; 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_cistatic int synquacer_i2c_doxfer(struct synquacer_i2c *i2c, 31162306a36Sopenharmony_ci struct i2c_msg *msgs, int num) 31262306a36Sopenharmony_ci{ 31362306a36Sopenharmony_ci unsigned char bsr; 31462306a36Sopenharmony_ci unsigned long timeout; 31562306a36Sopenharmony_ci int ret; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci synquacer_i2c_hw_init(i2c); 31862306a36Sopenharmony_ci bsr = readb(i2c->base + SYNQUACER_I2C_REG_BSR); 31962306a36Sopenharmony_ci if (bsr & SYNQUACER_I2C_BSR_BB) { 32062306a36Sopenharmony_ci dev_err(i2c->dev, "cannot get bus (bus busy)\n"); 32162306a36Sopenharmony_ci return -EBUSY; 32262306a36Sopenharmony_ci } 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci reinit_completion(&i2c->completion); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci i2c->msg = msgs; 32762306a36Sopenharmony_ci i2c->msg_num = num; 32862306a36Sopenharmony_ci i2c->msg_ptr = 0; 32962306a36Sopenharmony_ci i2c->msg_idx = 0; 33062306a36Sopenharmony_ci i2c->state = STATE_START; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci ret = synquacer_i2c_master_start(i2c, i2c->msg); 33362306a36Sopenharmony_ci if (ret < 0) { 33462306a36Sopenharmony_ci dev_dbg(i2c->dev, "Address failed: (%d)\n", ret); 33562306a36Sopenharmony_ci return ret; 33662306a36Sopenharmony_ci } 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci timeout = wait_for_completion_timeout(&i2c->completion, 33962306a36Sopenharmony_ci msecs_to_jiffies(i2c->timeout_ms)); 34062306a36Sopenharmony_ci if (timeout == 0) { 34162306a36Sopenharmony_ci dev_dbg(i2c->dev, "timeout\n"); 34262306a36Sopenharmony_ci return -EAGAIN; 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci ret = i2c->msg_idx; 34662306a36Sopenharmony_ci if (ret != num) { 34762306a36Sopenharmony_ci dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret); 34862306a36Sopenharmony_ci return -EAGAIN; 34962306a36Sopenharmony_ci } 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci /* wait 2 clock periods to ensure the stop has been through the bus */ 35262306a36Sopenharmony_ci udelay(DIV_ROUND_UP(2 * 1000, i2c->speed_khz)); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci return ret; 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_cistatic irqreturn_t synquacer_i2c_isr(int irq, void *dev_id) 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci struct synquacer_i2c *i2c = dev_id; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci unsigned char byte; 36262306a36Sopenharmony_ci unsigned char bsr, bcr; 36362306a36Sopenharmony_ci int ret; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci bcr = readb(i2c->base + SYNQUACER_I2C_REG_BCR); 36662306a36Sopenharmony_ci bsr = readb(i2c->base + SYNQUACER_I2C_REG_BSR); 36762306a36Sopenharmony_ci dev_dbg(i2c->dev, "bsr:0x%02x, bcr:0x%02x\n", bsr, bcr); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci if (bcr & SYNQUACER_I2C_BCR_BER) { 37062306a36Sopenharmony_ci dev_err(i2c->dev, "bus error\n"); 37162306a36Sopenharmony_ci synquacer_i2c_stop(i2c, -EAGAIN); 37262306a36Sopenharmony_ci goto out; 37362306a36Sopenharmony_ci } 37462306a36Sopenharmony_ci if ((bsr & SYNQUACER_I2C_BSR_AL) || 37562306a36Sopenharmony_ci !(bcr & SYNQUACER_I2C_BCR_MSS)) { 37662306a36Sopenharmony_ci dev_dbg(i2c->dev, "arbitration lost\n"); 37762306a36Sopenharmony_ci synquacer_i2c_stop(i2c, -EAGAIN); 37862306a36Sopenharmony_ci goto out; 37962306a36Sopenharmony_ci } 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci switch (i2c->state) { 38262306a36Sopenharmony_ci case STATE_START: 38362306a36Sopenharmony_ci if (bsr & SYNQUACER_I2C_BSR_LRB) { 38462306a36Sopenharmony_ci dev_dbg(i2c->dev, "ack was not received\n"); 38562306a36Sopenharmony_ci synquacer_i2c_stop(i2c, -EAGAIN); 38662306a36Sopenharmony_ci goto out; 38762306a36Sopenharmony_ci } 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci if (i2c->msg->flags & I2C_M_RD) 39062306a36Sopenharmony_ci i2c->state = STATE_READ; 39162306a36Sopenharmony_ci else 39262306a36Sopenharmony_ci i2c->state = STATE_WRITE; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci if (is_lastmsg(i2c) && i2c->msg->len == 0) { 39562306a36Sopenharmony_ci synquacer_i2c_stop(i2c, 0); 39662306a36Sopenharmony_ci goto out; 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci if (i2c->state == STATE_READ) 40062306a36Sopenharmony_ci goto prepare_read; 40162306a36Sopenharmony_ci fallthrough; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci case STATE_WRITE: 40462306a36Sopenharmony_ci if (bsr & SYNQUACER_I2C_BSR_LRB) { 40562306a36Sopenharmony_ci dev_dbg(i2c->dev, "WRITE: No Ack\n"); 40662306a36Sopenharmony_ci synquacer_i2c_stop(i2c, -EAGAIN); 40762306a36Sopenharmony_ci goto out; 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci if (!is_msgend(i2c)) { 41162306a36Sopenharmony_ci writeb(i2c->msg->buf[i2c->msg_ptr++], 41262306a36Sopenharmony_ci i2c->base + SYNQUACER_I2C_REG_DAR); 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci /* clear IRQ, and continue */ 41562306a36Sopenharmony_ci writeb(SYNQUACER_I2C_BCR_BEIE | 41662306a36Sopenharmony_ci SYNQUACER_I2C_BCR_MSS | 41762306a36Sopenharmony_ci SYNQUACER_I2C_BCR_INTE, 41862306a36Sopenharmony_ci i2c->base + SYNQUACER_I2C_REG_BCR); 41962306a36Sopenharmony_ci break; 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci if (is_lastmsg(i2c)) { 42262306a36Sopenharmony_ci synquacer_i2c_stop(i2c, 0); 42362306a36Sopenharmony_ci break; 42462306a36Sopenharmony_ci } 42562306a36Sopenharmony_ci dev_dbg(i2c->dev, "WRITE: Next Message\n"); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci i2c->msg_ptr = 0; 42862306a36Sopenharmony_ci i2c->msg_idx++; 42962306a36Sopenharmony_ci i2c->msg++; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci /* send the new start */ 43262306a36Sopenharmony_ci ret = synquacer_i2c_master_start(i2c, i2c->msg); 43362306a36Sopenharmony_ci if (ret < 0) { 43462306a36Sopenharmony_ci dev_dbg(i2c->dev, "restart error (%d)\n", ret); 43562306a36Sopenharmony_ci synquacer_i2c_stop(i2c, -EAGAIN); 43662306a36Sopenharmony_ci break; 43762306a36Sopenharmony_ci } 43862306a36Sopenharmony_ci i2c->state = STATE_START; 43962306a36Sopenharmony_ci break; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci case STATE_READ: 44262306a36Sopenharmony_ci byte = readb(i2c->base + SYNQUACER_I2C_REG_DAR); 44362306a36Sopenharmony_ci if (!(bsr & SYNQUACER_I2C_BSR_FBT)) /* data */ 44462306a36Sopenharmony_ci i2c->msg->buf[i2c->msg_ptr++] = byte; 44562306a36Sopenharmony_ci else /* address */ 44662306a36Sopenharmony_ci dev_dbg(i2c->dev, "address:0x%02x. ignore it.\n", byte); 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ciprepare_read: 44962306a36Sopenharmony_ci if (is_msglast(i2c)) { 45062306a36Sopenharmony_ci writeb(SYNQUACER_I2C_BCR_MSS | 45162306a36Sopenharmony_ci SYNQUACER_I2C_BCR_BEIE | 45262306a36Sopenharmony_ci SYNQUACER_I2C_BCR_INTE, 45362306a36Sopenharmony_ci i2c->base + SYNQUACER_I2C_REG_BCR); 45462306a36Sopenharmony_ci break; 45562306a36Sopenharmony_ci } 45662306a36Sopenharmony_ci if (!is_msgend(i2c)) { 45762306a36Sopenharmony_ci writeb(SYNQUACER_I2C_BCR_MSS | 45862306a36Sopenharmony_ci SYNQUACER_I2C_BCR_BEIE | 45962306a36Sopenharmony_ci SYNQUACER_I2C_BCR_INTE | 46062306a36Sopenharmony_ci SYNQUACER_I2C_BCR_ACK, 46162306a36Sopenharmony_ci i2c->base + SYNQUACER_I2C_REG_BCR); 46262306a36Sopenharmony_ci break; 46362306a36Sopenharmony_ci } 46462306a36Sopenharmony_ci if (is_lastmsg(i2c)) { 46562306a36Sopenharmony_ci /* last message, send stop and complete */ 46662306a36Sopenharmony_ci dev_dbg(i2c->dev, "READ: Send Stop\n"); 46762306a36Sopenharmony_ci synquacer_i2c_stop(i2c, 0); 46862306a36Sopenharmony_ci break; 46962306a36Sopenharmony_ci } 47062306a36Sopenharmony_ci dev_dbg(i2c->dev, "READ: Next Transfer\n"); 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci i2c->msg_ptr = 0; 47362306a36Sopenharmony_ci i2c->msg_idx++; 47462306a36Sopenharmony_ci i2c->msg++; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci ret = synquacer_i2c_master_start(i2c, i2c->msg); 47762306a36Sopenharmony_ci if (ret < 0) { 47862306a36Sopenharmony_ci dev_dbg(i2c->dev, "restart error (%d)\n", ret); 47962306a36Sopenharmony_ci synquacer_i2c_stop(i2c, -EAGAIN); 48062306a36Sopenharmony_ci } else { 48162306a36Sopenharmony_ci i2c->state = STATE_START; 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci break; 48462306a36Sopenharmony_ci default: 48562306a36Sopenharmony_ci dev_err(i2c->dev, "called in err STATE (%d)\n", i2c->state); 48662306a36Sopenharmony_ci break; 48762306a36Sopenharmony_ci } 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ciout: 49062306a36Sopenharmony_ci WAIT_PCLK(10, i2c->pclkrate); 49162306a36Sopenharmony_ci return IRQ_HANDLED; 49262306a36Sopenharmony_ci} 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_cistatic int synquacer_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, 49562306a36Sopenharmony_ci int num) 49662306a36Sopenharmony_ci{ 49762306a36Sopenharmony_ci struct synquacer_i2c *i2c; 49862306a36Sopenharmony_ci int retry; 49962306a36Sopenharmony_ci int ret; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci i2c = i2c_get_adapdata(adap); 50262306a36Sopenharmony_ci i2c->timeout_ms = calc_timeout_ms(i2c, msgs, num); 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci dev_dbg(i2c->dev, "calculated timeout %d ms\n", i2c->timeout_ms); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci for (retry = 0; retry <= adap->retries; retry++) { 50762306a36Sopenharmony_ci ret = synquacer_i2c_doxfer(i2c, msgs, num); 50862306a36Sopenharmony_ci if (ret != -EAGAIN) 50962306a36Sopenharmony_ci return ret; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci dev_dbg(i2c->dev, "Retrying transmission (%d)\n", retry); 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci synquacer_i2c_hw_reset(i2c); 51462306a36Sopenharmony_ci } 51562306a36Sopenharmony_ci return -EIO; 51662306a36Sopenharmony_ci} 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_cistatic u32 synquacer_i2c_functionality(struct i2c_adapter *adap) 51962306a36Sopenharmony_ci{ 52062306a36Sopenharmony_ci return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 52162306a36Sopenharmony_ci} 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_cistatic const struct i2c_algorithm synquacer_i2c_algo = { 52462306a36Sopenharmony_ci .master_xfer = synquacer_i2c_xfer, 52562306a36Sopenharmony_ci .functionality = synquacer_i2c_functionality, 52662306a36Sopenharmony_ci}; 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_cistatic const struct i2c_adapter synquacer_i2c_ops = { 52962306a36Sopenharmony_ci .owner = THIS_MODULE, 53062306a36Sopenharmony_ci .name = "synquacer_i2c-adapter", 53162306a36Sopenharmony_ci .algo = &synquacer_i2c_algo, 53262306a36Sopenharmony_ci .retries = 5, 53362306a36Sopenharmony_ci}; 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_cistatic int synquacer_i2c_probe(struct platform_device *pdev) 53662306a36Sopenharmony_ci{ 53762306a36Sopenharmony_ci struct synquacer_i2c *i2c; 53862306a36Sopenharmony_ci u32 bus_speed; 53962306a36Sopenharmony_ci int ret; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); 54262306a36Sopenharmony_ci if (!i2c) 54362306a36Sopenharmony_ci return -ENOMEM; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci bus_speed = i2c_acpi_find_bus_speed(&pdev->dev); 54662306a36Sopenharmony_ci if (!bus_speed) 54762306a36Sopenharmony_ci device_property_read_u32(&pdev->dev, "clock-frequency", 54862306a36Sopenharmony_ci &bus_speed); 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci device_property_read_u32(&pdev->dev, "socionext,pclk-rate", 55162306a36Sopenharmony_ci &i2c->pclkrate); 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci i2c->pclk = devm_clk_get(&pdev->dev, "pclk"); 55462306a36Sopenharmony_ci if (PTR_ERR(i2c->pclk) == -EPROBE_DEFER) 55562306a36Sopenharmony_ci return -EPROBE_DEFER; 55662306a36Sopenharmony_ci if (!IS_ERR_OR_NULL(i2c->pclk)) { 55762306a36Sopenharmony_ci dev_dbg(&pdev->dev, "clock source %p\n", i2c->pclk); 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci ret = clk_prepare_enable(i2c->pclk); 56062306a36Sopenharmony_ci if (ret) 56162306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, ret, "failed to enable clock\n"); 56262306a36Sopenharmony_ci i2c->pclkrate = clk_get_rate(i2c->pclk); 56362306a36Sopenharmony_ci } 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci if (i2c->pclkrate < SYNQUACER_I2C_MIN_CLK_RATE || 56662306a36Sopenharmony_ci i2c->pclkrate > SYNQUACER_I2C_MAX_CLK_RATE) 56762306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, -EINVAL, 56862306a36Sopenharmony_ci "PCLK missing or out of range (%d)\n", 56962306a36Sopenharmony_ci i2c->pclkrate); 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci i2c->base = devm_platform_ioremap_resource(pdev, 0); 57262306a36Sopenharmony_ci if (IS_ERR(i2c->base)) 57362306a36Sopenharmony_ci return PTR_ERR(i2c->base); 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci i2c->irq = platform_get_irq(pdev, 0); 57662306a36Sopenharmony_ci if (i2c->irq < 0) 57762306a36Sopenharmony_ci return i2c->irq; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci ret = devm_request_irq(&pdev->dev, i2c->irq, synquacer_i2c_isr, 58062306a36Sopenharmony_ci 0, dev_name(&pdev->dev), i2c); 58162306a36Sopenharmony_ci if (ret < 0) 58262306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, ret, "cannot claim IRQ %d\n", i2c->irq); 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci i2c->state = STATE_IDLE; 58562306a36Sopenharmony_ci i2c->dev = &pdev->dev; 58662306a36Sopenharmony_ci i2c->adapter = synquacer_i2c_ops; 58762306a36Sopenharmony_ci i2c_set_adapdata(&i2c->adapter, i2c); 58862306a36Sopenharmony_ci i2c->adapter.dev.parent = &pdev->dev; 58962306a36Sopenharmony_ci i2c->adapter.dev.of_node = pdev->dev.of_node; 59062306a36Sopenharmony_ci ACPI_COMPANION_SET(&i2c->adapter.dev, ACPI_COMPANION(&pdev->dev)); 59162306a36Sopenharmony_ci i2c->adapter.nr = pdev->id; 59262306a36Sopenharmony_ci init_completion(&i2c->completion); 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci if (bus_speed < I2C_MAX_FAST_MODE_FREQ) 59562306a36Sopenharmony_ci i2c->speed_khz = SYNQUACER_I2C_SPEED_SM; 59662306a36Sopenharmony_ci else 59762306a36Sopenharmony_ci i2c->speed_khz = SYNQUACER_I2C_SPEED_FM; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci synquacer_i2c_hw_init(i2c); 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci ret = i2c_add_numbered_adapter(&i2c->adapter); 60262306a36Sopenharmony_ci if (ret) 60362306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, ret, "failed to add bus to i2c core\n"); 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci platform_set_drvdata(pdev, i2c); 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci dev_info(&pdev->dev, "%s: synquacer_i2c adapter\n", 60862306a36Sopenharmony_ci dev_name(&i2c->adapter.dev)); 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci return 0; 61162306a36Sopenharmony_ci} 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_cistatic void synquacer_i2c_remove(struct platform_device *pdev) 61462306a36Sopenharmony_ci{ 61562306a36Sopenharmony_ci struct synquacer_i2c *i2c = platform_get_drvdata(pdev); 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci i2c_del_adapter(&i2c->adapter); 61862306a36Sopenharmony_ci if (!IS_ERR(i2c->pclk)) 61962306a36Sopenharmony_ci clk_disable_unprepare(i2c->pclk); 62062306a36Sopenharmony_ci}; 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_cistatic const struct of_device_id synquacer_i2c_dt_ids[] __maybe_unused = { 62362306a36Sopenharmony_ci { .compatible = "socionext,synquacer-i2c" }, 62462306a36Sopenharmony_ci { /* sentinel */ } 62562306a36Sopenharmony_ci}; 62662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, synquacer_i2c_dt_ids); 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci#ifdef CONFIG_ACPI 62962306a36Sopenharmony_cistatic const struct acpi_device_id synquacer_i2c_acpi_ids[] = { 63062306a36Sopenharmony_ci { "SCX0003" }, 63162306a36Sopenharmony_ci { /* sentinel */ } 63262306a36Sopenharmony_ci}; 63362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, synquacer_i2c_acpi_ids); 63462306a36Sopenharmony_ci#endif 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_cistatic struct platform_driver synquacer_i2c_driver = { 63762306a36Sopenharmony_ci .probe = synquacer_i2c_probe, 63862306a36Sopenharmony_ci .remove_new = synquacer_i2c_remove, 63962306a36Sopenharmony_ci .driver = { 64062306a36Sopenharmony_ci .name = "synquacer_i2c", 64162306a36Sopenharmony_ci .of_match_table = of_match_ptr(synquacer_i2c_dt_ids), 64262306a36Sopenharmony_ci .acpi_match_table = ACPI_PTR(synquacer_i2c_acpi_ids), 64362306a36Sopenharmony_ci }, 64462306a36Sopenharmony_ci}; 64562306a36Sopenharmony_cimodule_platform_driver(synquacer_i2c_driver); 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ciMODULE_AUTHOR("Fujitsu Semiconductor Ltd"); 64862306a36Sopenharmony_ciMODULE_DESCRIPTION("Socionext SynQuacer I2C Driver"); 64962306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 650