mirror of https://gitee.com/openkylin/linux.git
i2c: at91: add support for the HOLD field
The hold field allows to configure the data hold time which can be set with the help of the generic binding 'i2c-sda-hold-time-ns'. This feature has been introduced with SAMA5D4 SoC family. Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com> Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com> Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
This commit is contained in:
parent
d7a4c76336
commit
cc018e3612
|
@ -3,7 +3,7 @@ I2C for Atmel platforms
|
|||
Required properties :
|
||||
- compatible : Must be "atmel,at91rm9200-i2c", "atmel,at91sam9261-i2c",
|
||||
"atmel,at91sam9260-i2c", "atmel,at91sam9g20-i2c", "atmel,at91sam9g10-i2c",
|
||||
"atmel,at91sam9x5-i2c" or "atmel,sama5d2-i2c"
|
||||
"atmel,at91sam9x5-i2c", "atmel,sama5d4-i2c" or "atmel,sama5d2-i2c"
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts: interrupt number to the cpu.
|
||||
|
@ -17,6 +17,8 @@ Optional properties:
|
|||
- dma-names: should contain "tx" and "rx".
|
||||
- atmel,fifo-size: maximum number of data the RX and TX FIFOs can store for FIFO
|
||||
capable I2C controllers.
|
||||
- i2c-sda-hold-time-ns: TWD hold time, only available for "atmel,sama5d4-i2c"
|
||||
and "atmel,sama5d2-i2c".
|
||||
- Child nodes conforming to i2c bus binding
|
||||
|
||||
Examples :
|
||||
|
@ -52,6 +54,7 @@ i2c0: i2c@f8034600 {
|
|||
#size-cells = <0>;
|
||||
clocks = <&flx0>;
|
||||
atmel,fifo-size = <16>;
|
||||
i2c-sda-hold-time-ns = <336>;
|
||||
|
||||
wm8731: wm8731@1a {
|
||||
compatible = "wm8731";
|
||||
|
|
|
@ -64,6 +64,8 @@
|
|||
#define AT91_TWI_IADR 0x000c /* Internal Address Register */
|
||||
|
||||
#define AT91_TWI_CWGR 0x0010 /* Clock Waveform Generator Reg */
|
||||
#define AT91_TWI_CWGR_HOLD_MAX 0x1f
|
||||
#define AT91_TWI_CWGR_HOLD(x) (((x) & AT91_TWI_CWGR_HOLD_MAX) << 24)
|
||||
|
||||
#define AT91_TWI_SR 0x0020 /* Status Register */
|
||||
#define AT91_TWI_TXCOMP BIT(0) /* Transmission Complete */
|
||||
|
@ -110,6 +112,7 @@ struct at91_twi_pdata {
|
|||
unsigned clk_offset;
|
||||
bool has_unre_flag;
|
||||
bool has_alt_cmd;
|
||||
bool has_hold_field;
|
||||
struct at_dma_slave dma_slave;
|
||||
};
|
||||
|
||||
|
@ -187,10 +190,11 @@ static void at91_init_twi_bus(struct at91_twi_dev *dev)
|
|||
*/
|
||||
static void at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
|
||||
{
|
||||
int ckdiv, cdiv, div;
|
||||
int ckdiv, cdiv, div, hold = 0;
|
||||
struct at91_twi_pdata *pdata = dev->pdata;
|
||||
int offset = pdata->clk_offset;
|
||||
int max_ckdiv = pdata->clk_max_div;
|
||||
u32 twd_hold_time_ns = 0;
|
||||
|
||||
div = max(0, (int)DIV_ROUND_UP(clk_get_rate(dev->clk),
|
||||
2 * twi_clk) - offset);
|
||||
|
@ -204,8 +208,33 @@ static void at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
|
|||
cdiv = 255;
|
||||
}
|
||||
|
||||
dev->twi_cwgr_reg = (ckdiv << 16) | (cdiv << 8) | cdiv;
|
||||
dev_dbg(dev->dev, "cdiv %d ckdiv %d\n", cdiv, ckdiv);
|
||||
if (pdata->has_hold_field) {
|
||||
of_property_read_u32(dev->dev->of_node, "i2c-sda-hold-time-ns",
|
||||
&twd_hold_time_ns);
|
||||
|
||||
/*
|
||||
* hold time = HOLD + 3 x T_peripheral_clock
|
||||
* Use clk rate in kHz to prevent overflows when computing
|
||||
* hold.
|
||||
*/
|
||||
hold = DIV_ROUND_UP(twd_hold_time_ns
|
||||
* (clk_get_rate(dev->clk) / 1000), 1000000);
|
||||
hold -= 3;
|
||||
if (hold < 0)
|
||||
hold = 0;
|
||||
if (hold > AT91_TWI_CWGR_HOLD_MAX) {
|
||||
dev_warn(dev->dev,
|
||||
"HOLD field set to its maximum value (%d instead of %d)\n",
|
||||
AT91_TWI_CWGR_HOLD_MAX, hold);
|
||||
hold = AT91_TWI_CWGR_HOLD_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
dev->twi_cwgr_reg = (ckdiv << 16) | (cdiv << 8) | cdiv
|
||||
| AT91_TWI_CWGR_HOLD(hold);
|
||||
|
||||
dev_dbg(dev->dev, "cdiv %d ckdiv %d hold %d (%d ns)\n",
|
||||
cdiv, ckdiv, hold, twd_hold_time_ns);
|
||||
}
|
||||
|
||||
static void at91_twi_dma_cleanup(struct at91_twi_dev *dev)
|
||||
|
@ -797,6 +826,7 @@ static struct at91_twi_pdata at91rm9200_config = {
|
|||
.clk_offset = 3,
|
||||
.has_unre_flag = true,
|
||||
.has_alt_cmd = false,
|
||||
.has_hold_field = false,
|
||||
};
|
||||
|
||||
static struct at91_twi_pdata at91sam9261_config = {
|
||||
|
@ -804,6 +834,7 @@ static struct at91_twi_pdata at91sam9261_config = {
|
|||
.clk_offset = 4,
|
||||
.has_unre_flag = false,
|
||||
.has_alt_cmd = false,
|
||||
.has_hold_field = false,
|
||||
};
|
||||
|
||||
static struct at91_twi_pdata at91sam9260_config = {
|
||||
|
@ -811,6 +842,7 @@ static struct at91_twi_pdata at91sam9260_config = {
|
|||
.clk_offset = 4,
|
||||
.has_unre_flag = false,
|
||||
.has_alt_cmd = false,
|
||||
.has_hold_field = false,
|
||||
};
|
||||
|
||||
static struct at91_twi_pdata at91sam9g20_config = {
|
||||
|
@ -818,6 +850,7 @@ static struct at91_twi_pdata at91sam9g20_config = {
|
|||
.clk_offset = 4,
|
||||
.has_unre_flag = false,
|
||||
.has_alt_cmd = false,
|
||||
.has_hold_field = false,
|
||||
};
|
||||
|
||||
static struct at91_twi_pdata at91sam9g10_config = {
|
||||
|
@ -825,6 +858,7 @@ static struct at91_twi_pdata at91sam9g10_config = {
|
|||
.clk_offset = 4,
|
||||
.has_unre_flag = false,
|
||||
.has_alt_cmd = false,
|
||||
.has_hold_field = false,
|
||||
};
|
||||
|
||||
static const struct platform_device_id at91_twi_devtypes[] = {
|
||||
|
@ -854,6 +888,15 @@ static struct at91_twi_pdata at91sam9x5_config = {
|
|||
.clk_offset = 4,
|
||||
.has_unre_flag = false,
|
||||
.has_alt_cmd = false,
|
||||
.has_hold_field = false,
|
||||
};
|
||||
|
||||
static struct at91_twi_pdata sama5d4_config = {
|
||||
.clk_max_div = 7,
|
||||
.clk_offset = 4,
|
||||
.has_unre_flag = false,
|
||||
.has_alt_cmd = false,
|
||||
.has_hold_field = true,
|
||||
};
|
||||
|
||||
static struct at91_twi_pdata sama5d2_config = {
|
||||
|
@ -861,6 +904,7 @@ static struct at91_twi_pdata sama5d2_config = {
|
|||
.clk_offset = 4,
|
||||
.has_unre_flag = true,
|
||||
.has_alt_cmd = true,
|
||||
.has_hold_field = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id atmel_twi_dt_ids[] = {
|
||||
|
@ -882,6 +926,9 @@ static const struct of_device_id atmel_twi_dt_ids[] = {
|
|||
}, {
|
||||
.compatible = "atmel,at91sam9x5-i2c",
|
||||
.data = &at91sam9x5_config,
|
||||
}, {
|
||||
.compatible = "atmel,sama5d4-i2c",
|
||||
.data = &sama5d4_config,
|
||||
}, {
|
||||
.compatible = "atmel,sama5d2-i2c",
|
||||
.data = &sama5d2_config,
|
||||
|
|
Loading…
Reference in New Issue