-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
i2c: add Phytium i2c driver for both server and desktop platform #123
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
594c790
dt-bindings: Add bindings for Phytium I2C/SMBus controller
JiakunShuai f7073b8
i2c: phytium: Add i2c driver for Phytium I2C adapter
JiakunShuai 24425bb
i2c: designware: add i2c support for Phytium SoCs
JiakunShuai 4728b00
ACPI: APD: Add clock frequency for Phytium I2C controller
JiakunShuai File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | ||
%YAML 1.2 | ||
--- | ||
$id: http://devicetree.org/schemas/i2c/snps,designware-i2c.yaml# | ||
$schema: http://devicetree.org/meta-schemas/core.yaml# | ||
|
||
title: Phytium I2C/SMBus Controller | ||
|
||
maintainers: | ||
- Chen Baozi <[email protected]> | ||
|
||
allOf: | ||
- $ref: /schemas/i2c/i2c-controller.yaml# | ||
|
||
properties: | ||
compatible: | ||
const: phytium,i2c | ||
|
||
reg: | ||
minItems: 1 | ||
items: | ||
- description: Offset and length of the memory mapped registers | ||
|
||
interrupts: | ||
maxItems: 1 | ||
|
||
interrupt-names: | ||
const: smbus_alert | ||
description: should be "smbus_alert" if SMBus alert interrupt is supported | ||
|
||
clocks: | ||
minItems: 1 | ||
items: | ||
- description: I2C controller reference clock source | ||
|
||
unevaluatedProperties: false | ||
|
||
required: | ||
- compatible | ||
- reg | ||
- interrupts | ||
|
||
examples: | ||
- | | ||
i2c0: i2c@28011000 { | ||
compatible = "phytium,i2c"; | ||
reg = <0x0 0x28011000 0x0 0x1000>; | ||
interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>; | ||
interrupt-names = "smbus_alert"; | ||
clocks = <&sysclk_48mhz>; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -57,6 +57,7 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = { | |
{ "HISI02A2", 0 }, | ||
{ "HISI02A3", 0 }, | ||
{ "HYGO0010", ACCESS_INTR_MASK }, | ||
{ "PHYT0003", 0 }, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 同上 |
||
{ } | ||
}; | ||
MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
// SPDX-License-Identifier: GPL-2.0-or-later | ||
/* | ||
* Phytium I2C adapter driver. | ||
* | ||
* Derived from Synopysys I2C driver. | ||
* Copyright (C) 2006 Texas Instruments. | ||
* Copyright (C) 2007 MontaVista Software Inc. | ||
* Copyright (C) 2009 Provigent Ltd. | ||
* | ||
* Copyright (C) 2021-2023, Phytium Technology Co., Ltd. | ||
*/ | ||
#include <linux/clk.h> | ||
#include <linux/delay.h> | ||
#include <linux/export.h> | ||
#include <linux/errno.h> | ||
#include <linux/err.h> | ||
#include <linux/i2c.h> | ||
#include <linux/interrupt.h> | ||
#include <linux/io.h> | ||
#include <linux/module.h> | ||
#include <linux/pm_runtime.h> | ||
#include <linux/swab.h> | ||
|
||
#include "i2c-phytium-core.h" | ||
|
||
static char *abort_sources[] = { | ||
[ABRT_7B_ADDR_NOACK] = | ||
"slave address not acknowledged (7bit mode)", | ||
[ABRT_10ADDR1_NOACK] = | ||
"first address byte not acknowledged (10bit mode)", | ||
[ABRT_10ADDR2_NOACK] = | ||
"second address byte not acknowledged (10bit mode)", | ||
[ABRT_TXDATA_NOACK] = | ||
"data not acknowledged", | ||
[ABRT_GCALL_NOACK] = | ||
"no acknowledgment for a general call", | ||
[ABRT_GCALL_READ] = | ||
"read after general call", | ||
[ABRT_SBYTE_ACKDET] = | ||
"start byte acknowledged", | ||
[ABRT_SBYTE_NORSTRT] = | ||
"trying to send start byte when restart is disabled", | ||
[ABRT_10B_RD_NORSTRT] = | ||
"trying to read when restart is disabled (10bit mode)", | ||
[ABRT_MASTER_DIS] = | ||
"trying to use disabled adapter", | ||
[ARB_LOST] = | ||
"lost arbitration", | ||
[ABRT_SLAVE_FLUSH_TXFIFO] = | ||
"read command so flush old data in the TX FIFO", | ||
[ABRT_SLAVE_ARBLOST] = | ||
"slave lost the bus while transmitting data to a remote master", | ||
[ABRT_SLAVE_RD_INTX] = | ||
"incorrect slave-transmitter mode configuration", | ||
}; | ||
|
||
u32 phytium_readl(struct phytium_i2c_dev *dev, int offset) | ||
{ | ||
return readl_relaxed(dev->base + offset); | ||
} | ||
|
||
void phytium_writel(struct phytium_i2c_dev *dev, u32 b, int offset) | ||
{ | ||
writel_relaxed(b, dev->base + offset); | ||
} | ||
|
||
u32 i2c_phytium_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset) | ||
{ | ||
if (cond) | ||
return (ic_clk * tSYMBOL + 500000) / 1000000 - 8 + offset; | ||
else | ||
return (ic_clk * (tSYMBOL + tf) + 500000) / 1000000 - 3 + offset; | ||
} | ||
|
||
u32 i2c_phytium_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset) | ||
{ | ||
return ((ic_clk * (tLOW + tf) + 500000) / 1000000) - 1 + offset; | ||
} | ||
|
||
int i2c_phytium_set_sda_hold(struct phytium_i2c_dev *dev) | ||
{ | ||
if (!dev->sda_hold_time) { | ||
/* Keep previous hold time setting if no one set it */ | ||
dev->sda_hold_time = phytium_readl(dev, IC_SDA_HOLD); | ||
} | ||
|
||
if (!(dev->sda_hold_time & IC_SDA_HOLD_RX_MASK)) | ||
dev->sda_hold_time |= 1 << IC_SDA_HOLD_RX_SHIFT; | ||
|
||
dev_dbg(dev->dev, "SDA Hold Time TX:RX = %d:%d\n", | ||
dev->sda_hold_time & ~(u32)IC_SDA_HOLD_RX_MASK, | ||
dev->sda_hold_time >> IC_SDA_HOLD_RX_SHIFT); | ||
|
||
return 0; | ||
} | ||
|
||
void __i2c_phytium_disable(struct phytium_i2c_dev *dev) | ||
{ | ||
int timeout = 100; | ||
|
||
do { | ||
__i2c_phytium_disable_nowait(dev); | ||
if ((phytium_readl(dev, IC_ENABLE_STATUS) & 1) == 0) | ||
return; | ||
|
||
/* | ||
* Wait 10 times the signaling period of the highest I2C | ||
* transfer supported by the driver (for 400KHz this is | ||
* 25us). | ||
*/ | ||
usleep_range(25, 250); | ||
} while (timeout--); | ||
|
||
dev_warn(dev->dev, "timeout in disabling adapter\n"); | ||
} | ||
|
||
unsigned long i2c_phytium_clk_rate(struct phytium_i2c_dev *dev) | ||
{ | ||
if (WARN_ON_ONCE(!dev->get_clk_rate_khz)) | ||
return 0; | ||
return dev->get_clk_rate_khz(dev); | ||
} | ||
|
||
int i2c_phytium_prepare_clk(struct phytium_i2c_dev *dev, bool prepare) | ||
{ | ||
if (IS_ERR(dev->clk)) | ||
return PTR_ERR(dev->clk); | ||
|
||
if (prepare) | ||
return clk_prepare_enable(dev->clk); | ||
|
||
clk_disable_unprepare(dev->clk); | ||
return 0; | ||
} | ||
EXPORT_SYMBOL_GPL(i2c_phytium_prepare_clk); | ||
|
||
int i2c_phytium_wait_bus_not_busy(struct phytium_i2c_dev *dev) | ||
{ | ||
int timeout = 20; /* 20 ms */ | ||
|
||
while (phytium_readl(dev, IC_STATUS) & IC_STATUS_ACTIVITY) { | ||
if (timeout <= 0) { | ||
dev_warn(dev->dev, "timeout waiting for bus ready\n"); | ||
i2c_recover_bus(&dev->adapter); | ||
|
||
if (phytium_readl(dev, IC_STATUS) & IC_STATUS_ACTIVITY) | ||
return -ETIMEDOUT; | ||
return 0; | ||
} | ||
timeout--; | ||
usleep_range(1000, 1100); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
int i2c_phytium_handle_tx_abort(struct phytium_i2c_dev *dev) | ||
{ | ||
unsigned long abort_source = dev->abort_source; | ||
int i; | ||
|
||
if (abort_source & IC_TX_ABRT_NOACK) { | ||
for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) | ||
dev_dbg(dev->dev, | ||
"%s: %s\n", __func__, abort_sources[i]); | ||
return -EREMOTEIO; | ||
} | ||
|
||
for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) | ||
dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]); | ||
|
||
if (abort_source & IC_TX_ARB_LOST) | ||
return -EAGAIN; | ||
else if (abort_source & IC_TX_ABRT_GCALL_READ) | ||
return -EINVAL; | ||
else | ||
return -EIO; | ||
|
||
return 0; | ||
} | ||
|
||
u32 i2c_phytium_func(struct i2c_adapter *adapter) | ||
{ | ||
struct phytium_i2c_dev *dev = i2c_get_adapdata(adapter); | ||
|
||
return dev->functionality; | ||
} | ||
|
||
void i2c_phytium_disable(struct phytium_i2c_dev *dev) | ||
{ | ||
/* Disable controller */ | ||
__i2c_phytium_disable(dev); | ||
|
||
/* Disable all interrupts */ | ||
phytium_writel(dev, 0, IC_INTR_MASK); | ||
phytium_readl(dev, IC_CLR_INTR); | ||
} | ||
|
||
void i2c_phytium_disable_int(struct phytium_i2c_dev *dev) | ||
{ | ||
phytium_writel(dev, 0, IC_INTR_MASK); | ||
} | ||
|
||
MODULE_AUTHOR("Cheng Quan <[email protected]>"); | ||
MODULE_DESCRIPTION("Phytium I2C bus adapter core"); | ||
MODULE_LICENSE("GPL"); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
根据飞腾ACPI规范文档v1.2版本 p13页所说和一些旧代码的内容,
这里下面还需要添加FTI20001?
As Phytium ACPI Description Specification document v1.2 p13
Device HID said for old v1.0 Spec,FTI20001 is need?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
目前飞腾向主流开源社区推送的版本已经剔除了CID属性,如果还在使用acpi v1.0的旧规范的话建议是升级固件了,有很多属性acpi v1.0都不支持的。