mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-11-27 03:55:37 +08:00
Merge branch 'i2c/i2c-host' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux.git
This commit is contained in:
commit
8d8905f347
@ -1,34 +0,0 @@
|
||||
* NXP PNX I2C Controller
|
||||
|
||||
Required properties:
|
||||
|
||||
- reg: Offset and length of the register set for the device
|
||||
- compatible: should be "nxp,pnx-i2c"
|
||||
- interrupts: configure one interrupt line
|
||||
- #address-cells: always 1 (for i2c addresses)
|
||||
- #size-cells: always 0
|
||||
|
||||
Optional properties:
|
||||
|
||||
- clock-frequency: desired I2C bus clock frequency in Hz, Default: 100000 Hz
|
||||
|
||||
Examples:
|
||||
|
||||
i2c1: i2c@400a0000 {
|
||||
compatible = "nxp,pnx-i2c";
|
||||
reg = <0x400a0000 0x100>;
|
||||
interrupt-parent = <&mic>;
|
||||
interrupts = <51 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
i2c2: i2c@400a8000 {
|
||||
compatible = "nxp,pnx-i2c";
|
||||
reg = <0x400a8000 0x100>;
|
||||
interrupt-parent = <&mic>;
|
||||
interrupts = <50 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-frequency = <100000>;
|
||||
};
|
46
Documentation/devicetree/bindings/i2c/nxp,pnx-i2c.yaml
Normal file
46
Documentation/devicetree/bindings/i2c/nxp,pnx-i2c.yaml
Normal file
@ -0,0 +1,46 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/i2c/nxp,pnx-i2c.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NXP PNX I2C Controller
|
||||
|
||||
maintainers:
|
||||
- Animesh Agarwal <animeshagarwal28@gmail.com>
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/i2c/i2c-controller.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: nxp,pnx-i2c
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clock-frequency:
|
||||
default: 100000
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c@400a0000 {
|
||||
compatible = "nxp,pnx-i2c";
|
||||
reg = <0x400a0000 0x100>;
|
||||
interrupt-parent = <&mic>;
|
||||
interrupts = <51 0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
@ -15,14 +15,17 @@ allOf:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- renesas,riic-r7s72100 # RZ/A1H
|
||||
- renesas,riic-r7s9210 # RZ/A2M
|
||||
- renesas,riic-r9a07g043 # RZ/G2UL and RZ/Five
|
||||
- renesas,riic-r9a07g044 # RZ/G2{L,LC}
|
||||
- renesas,riic-r9a07g054 # RZ/V2L
|
||||
- const: renesas,riic-rz # RZ/A or RZ/G2L
|
||||
oneOf:
|
||||
- items:
|
||||
- enum:
|
||||
- renesas,riic-r7s72100 # RZ/A1H
|
||||
- renesas,riic-r7s9210 # RZ/A2M
|
||||
- renesas,riic-r9a07g043 # RZ/G2UL and RZ/Five
|
||||
- renesas,riic-r9a07g044 # RZ/G2{L,LC}
|
||||
- renesas,riic-r9a07g054 # RZ/V2L
|
||||
- const: renesas,riic-rz # RZ/A or RZ/G2L
|
||||
|
||||
- const: renesas,riic-r9a09g057 # RZ/V2H(P)
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -46,18 +46,6 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#define RIIC_ICCR1 0x00
|
||||
#define RIIC_ICCR2 0x04
|
||||
#define RIIC_ICMR1 0x08
|
||||
#define RIIC_ICMR3 0x10
|
||||
#define RIIC_ICSER 0x18
|
||||
#define RIIC_ICIER 0x1c
|
||||
#define RIIC_ICSR2 0x24
|
||||
#define RIIC_ICBRL 0x34
|
||||
#define RIIC_ICBRH 0x38
|
||||
#define RIIC_ICDRT 0x3c
|
||||
#define RIIC_ICDRR 0x40
|
||||
|
||||
#define ICCR1_ICE 0x80
|
||||
#define ICCR1_IICRST 0x40
|
||||
#define ICCR1_SOWP 0x10
|
||||
@ -87,6 +75,25 @@
|
||||
|
||||
#define RIIC_INIT_MSG -1
|
||||
|
||||
enum riic_reg_list {
|
||||
RIIC_ICCR1 = 0,
|
||||
RIIC_ICCR2,
|
||||
RIIC_ICMR1,
|
||||
RIIC_ICMR3,
|
||||
RIIC_ICSER,
|
||||
RIIC_ICIER,
|
||||
RIIC_ICSR2,
|
||||
RIIC_ICBRL,
|
||||
RIIC_ICBRH,
|
||||
RIIC_ICDRT,
|
||||
RIIC_ICDRR,
|
||||
RIIC_REG_END,
|
||||
};
|
||||
|
||||
struct riic_of_data {
|
||||
u8 regs[RIIC_REG_END];
|
||||
};
|
||||
|
||||
struct riic_dev {
|
||||
void __iomem *base;
|
||||
u8 *buf;
|
||||
@ -94,6 +101,7 @@ struct riic_dev {
|
||||
int bytes_left;
|
||||
int err;
|
||||
int is_last;
|
||||
const struct riic_of_data *info;
|
||||
struct completion msg_done;
|
||||
struct i2c_adapter adapter;
|
||||
struct clk *clk;
|
||||
@ -105,9 +113,19 @@ struct riic_irq_desc {
|
||||
char *name;
|
||||
};
|
||||
|
||||
static inline void riic_writeb(struct riic_dev *riic, u8 val, u8 offset)
|
||||
{
|
||||
writeb(val, riic->base + riic->info->regs[offset]);
|
||||
}
|
||||
|
||||
static inline u8 riic_readb(struct riic_dev *riic, u8 offset)
|
||||
{
|
||||
return readb(riic->base + riic->info->regs[offset]);
|
||||
}
|
||||
|
||||
static inline void riic_clear_set_bit(struct riic_dev *riic, u8 clear, u8 set, u8 reg)
|
||||
{
|
||||
writeb((readb(riic->base + reg) & ~clear) | set, riic->base + reg);
|
||||
riic_writeb(riic, (riic_readb(riic, reg) & ~clear) | set, reg);
|
||||
}
|
||||
|
||||
static int riic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
||||
@ -119,7 +137,7 @@ static int riic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
||||
|
||||
pm_runtime_get_sync(adap->dev.parent);
|
||||
|
||||
if (readb(riic->base + RIIC_ICCR2) & ICCR2_BBSY) {
|
||||
if (riic_readb(riic, RIIC_ICCR2) & ICCR2_BBSY) {
|
||||
riic->err = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
@ -127,7 +145,7 @@ static int riic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
||||
reinit_completion(&riic->msg_done);
|
||||
riic->err = 0;
|
||||
|
||||
writeb(0, riic->base + RIIC_ICSR2);
|
||||
riic_writeb(riic, 0, RIIC_ICSR2);
|
||||
|
||||
for (i = 0, start_bit = ICCR2_ST; i < num; i++) {
|
||||
riic->bytes_left = RIIC_INIT_MSG;
|
||||
@ -135,9 +153,9 @@ static int riic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
||||
riic->msg = &msgs[i];
|
||||
riic->is_last = (i == num - 1);
|
||||
|
||||
writeb(ICIER_NAKIE | ICIER_TIE, riic->base + RIIC_ICIER);
|
||||
riic_writeb(riic, ICIER_NAKIE | ICIER_TIE, RIIC_ICIER);
|
||||
|
||||
writeb(start_bit, riic->base + RIIC_ICCR2);
|
||||
riic_writeb(riic, start_bit, RIIC_ICCR2);
|
||||
|
||||
time_left = wait_for_completion_timeout(&riic->msg_done, riic->adapter.timeout);
|
||||
if (time_left == 0)
|
||||
@ -191,7 +209,7 @@ static irqreturn_t riic_tdre_isr(int irq, void *data)
|
||||
* value could be moved to the shadow shift register right away. So
|
||||
* this must be after updates to ICIER (where we want to disable TIE)!
|
||||
*/
|
||||
writeb(val, riic->base + RIIC_ICDRT);
|
||||
riic_writeb(riic, val, RIIC_ICDRT);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -200,9 +218,9 @@ static irqreturn_t riic_tend_isr(int irq, void *data)
|
||||
{
|
||||
struct riic_dev *riic = data;
|
||||
|
||||
if (readb(riic->base + RIIC_ICSR2) & ICSR2_NACKF) {
|
||||
if (riic_readb(riic, RIIC_ICSR2) & ICSR2_NACKF) {
|
||||
/* We got a NACKIE */
|
||||
readb(riic->base + RIIC_ICDRR); /* dummy read */
|
||||
riic_readb(riic, RIIC_ICDRR); /* dummy read */
|
||||
riic_clear_set_bit(riic, ICSR2_NACKF, 0, RIIC_ICSR2);
|
||||
riic->err = -ENXIO;
|
||||
} else if (riic->bytes_left) {
|
||||
@ -211,7 +229,7 @@ static irqreturn_t riic_tend_isr(int irq, void *data)
|
||||
|
||||
if (riic->is_last || riic->err) {
|
||||
riic_clear_set_bit(riic, ICIER_TEIE, ICIER_SPIE, RIIC_ICIER);
|
||||
writeb(ICCR2_SP, riic->base + RIIC_ICCR2);
|
||||
riic_writeb(riic, ICCR2_SP, RIIC_ICCR2);
|
||||
} else {
|
||||
/* Transfer is complete, but do not send STOP */
|
||||
riic_clear_set_bit(riic, ICIER_TEIE, 0, RIIC_ICIER);
|
||||
@ -230,7 +248,7 @@ static irqreturn_t riic_rdrf_isr(int irq, void *data)
|
||||
|
||||
if (riic->bytes_left == RIIC_INIT_MSG) {
|
||||
riic->bytes_left = riic->msg->len;
|
||||
readb(riic->base + RIIC_ICDRR); /* dummy read */
|
||||
riic_readb(riic, RIIC_ICDRR); /* dummy read */
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@ -238,7 +256,7 @@ static irqreturn_t riic_rdrf_isr(int irq, void *data)
|
||||
/* STOP must come before we set ACKBT! */
|
||||
if (riic->is_last) {
|
||||
riic_clear_set_bit(riic, 0, ICIER_SPIE, RIIC_ICIER);
|
||||
writeb(ICCR2_SP, riic->base + RIIC_ICCR2);
|
||||
riic_writeb(riic, ICCR2_SP, RIIC_ICCR2);
|
||||
}
|
||||
|
||||
riic_clear_set_bit(riic, 0, ICMR3_ACKBT, RIIC_ICMR3);
|
||||
@ -248,7 +266,7 @@ static irqreturn_t riic_rdrf_isr(int irq, void *data)
|
||||
}
|
||||
|
||||
/* Reading acks the RIE interrupt */
|
||||
*riic->buf = readb(riic->base + RIIC_ICDRR);
|
||||
*riic->buf = riic_readb(riic, RIIC_ICDRR);
|
||||
riic->buf++;
|
||||
riic->bytes_left--;
|
||||
|
||||
@ -260,10 +278,10 @@ static irqreturn_t riic_stop_isr(int irq, void *data)
|
||||
struct riic_dev *riic = data;
|
||||
|
||||
/* read back registers to confirm writes have fully propagated */
|
||||
writeb(0, riic->base + RIIC_ICSR2);
|
||||
readb(riic->base + RIIC_ICSR2);
|
||||
writeb(0, riic->base + RIIC_ICIER);
|
||||
readb(riic->base + RIIC_ICIER);
|
||||
riic_writeb(riic, 0, RIIC_ICSR2);
|
||||
riic_readb(riic, RIIC_ICSR2);
|
||||
riic_writeb(riic, 0, RIIC_ICIER);
|
||||
riic_readb(riic, RIIC_ICIER);
|
||||
|
||||
complete(&riic->msg_done);
|
||||
|
||||
@ -365,15 +383,15 @@ static int riic_init_hw(struct riic_dev *riic, struct i2c_timings *t)
|
||||
t->scl_rise_ns / (1000000000 / rate), cks, brl, brh);
|
||||
|
||||
/* Changing the order of accessing IICRST and ICE may break things! */
|
||||
writeb(ICCR1_IICRST | ICCR1_SOWP, riic->base + RIIC_ICCR1);
|
||||
riic_writeb(riic, ICCR1_IICRST | ICCR1_SOWP, RIIC_ICCR1);
|
||||
riic_clear_set_bit(riic, 0, ICCR1_ICE, RIIC_ICCR1);
|
||||
|
||||
writeb(ICMR1_CKS(cks), riic->base + RIIC_ICMR1);
|
||||
writeb(brh | ICBR_RESERVED, riic->base + RIIC_ICBRH);
|
||||
writeb(brl | ICBR_RESERVED, riic->base + RIIC_ICBRL);
|
||||
riic_writeb(riic, ICMR1_CKS(cks), RIIC_ICMR1);
|
||||
riic_writeb(riic, brh | ICBR_RESERVED, RIIC_ICBRH);
|
||||
riic_writeb(riic, brl | ICBR_RESERVED, RIIC_ICBRL);
|
||||
|
||||
writeb(0, riic->base + RIIC_ICSER);
|
||||
writeb(ICMR3_ACKWP | ICMR3_RDRFS, riic->base + RIIC_ICMR3);
|
||||
riic_writeb(riic, 0, RIIC_ICSER);
|
||||
riic_writeb(riic, ICMR3_ACKWP | ICMR3_RDRFS, RIIC_ICMR3);
|
||||
|
||||
riic_clear_set_bit(riic, ICCR1_IICRST, 0, RIIC_ICCR1);
|
||||
|
||||
@ -443,6 +461,8 @@ static int riic_i2c_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
riic->info = of_device_get_match_data(&pdev->dev);
|
||||
|
||||
adap = &riic->adapter;
|
||||
i2c_set_adapdata(adap, riic);
|
||||
strscpy(adap->name, "Renesas RIIC adapter", sizeof(adap->name));
|
||||
@ -481,14 +501,47 @@ static void riic_i2c_remove(struct platform_device *pdev)
|
||||
struct riic_dev *riic = platform_get_drvdata(pdev);
|
||||
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
writeb(0, riic->base + RIIC_ICIER);
|
||||
riic_writeb(riic, 0, RIIC_ICIER);
|
||||
pm_runtime_put(&pdev->dev);
|
||||
i2c_del_adapter(&riic->adapter);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
}
|
||||
|
||||
static const struct riic_of_data riic_rz_a_info = {
|
||||
.regs = {
|
||||
[RIIC_ICCR1] = 0x00,
|
||||
[RIIC_ICCR2] = 0x04,
|
||||
[RIIC_ICMR1] = 0x08,
|
||||
[RIIC_ICMR3] = 0x10,
|
||||
[RIIC_ICSER] = 0x18,
|
||||
[RIIC_ICIER] = 0x1c,
|
||||
[RIIC_ICSR2] = 0x24,
|
||||
[RIIC_ICBRL] = 0x34,
|
||||
[RIIC_ICBRH] = 0x38,
|
||||
[RIIC_ICDRT] = 0x3c,
|
||||
[RIIC_ICDRR] = 0x40,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct riic_of_data riic_rz_v2h_info = {
|
||||
.regs = {
|
||||
[RIIC_ICCR1] = 0x00,
|
||||
[RIIC_ICCR2] = 0x01,
|
||||
[RIIC_ICMR1] = 0x02,
|
||||
[RIIC_ICMR3] = 0x04,
|
||||
[RIIC_ICSER] = 0x06,
|
||||
[RIIC_ICIER] = 0x07,
|
||||
[RIIC_ICSR2] = 0x09,
|
||||
[RIIC_ICBRL] = 0x10,
|
||||
[RIIC_ICBRH] = 0x11,
|
||||
[RIIC_ICDRT] = 0x12,
|
||||
[RIIC_ICDRR] = 0x13,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct of_device_id riic_i2c_dt_ids[] = {
|
||||
{ .compatible = "renesas,riic-rz", },
|
||||
{ .compatible = "renesas,riic-rz", .data = &riic_rz_a_info },
|
||||
{ .compatible = "renesas,riic-r9a09g057", .data = &riic_rz_v2h_info },
|
||||
{ /* Sentinel */ },
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user