Let's add watchdog, arm-pmu, dma, usb, mmc..... support for allwinner
a100 soc.
Yangtao Li (19):
pinctrl: sunxi: fix irq bank map for the Allwinner A100 pin controller
pinctrl: sunxi: Mark the irq bank not found in
sunxi_pinctrl_irq_handler() with WARN_ON
pinctrl: sunxi: Always call chained_irq_{enter, exit} in
sunxi_pinctrl_irq_handler
dt-bindings: dma: allwinner,sun50i-a64-dma: Add A100 compatible
dmaengine: sun6i: Add support for A100 DMA
arm64: allwinner: a100: Add device node for DMA controller
arm64: dts: allwinner: A100: Add PMU mode
phy: sun4i-usb: remove enable_pmu_unk1 from sun50i_h6_cfg
phy: allwinner: Convert to devm_platform_ioremap_* API
dt-bindings: watchdog: sun4i: Add A100 compatible
arm64: dts: allwinner: a100: add watchdog node
dt-bindings: Add bindings for USB phy on Allwinner A100
phy: sun4i-usb: add support for A100 USB PHY
arm64: dts: allwinner: a100: add usb related nodes
arm64: allwinner: A100: enable EHCI, OHCI and USB PHY nodes in Perf1
dt-bindings: mmc: sunxi: Add A100 compatibles
mmc: sunxi: add support for A100 mmc controller
arm64: allwinner: a100: Add MMC related nodes
arm64: dts: allwinner: a100: perf1: Add eMMC and MMC node
.../dma/allwinner,sun50i-a64-dma.yaml | 5 +-
.../bindings/mmc/allwinner,sun4i-a10-mmc.yaml | 2 +
.../phy/allwinner,sun50i-a100-usb-phy.yaml | 105 ++++++++++
.../watchdog/allwinner,sun4i-a10-wdt.yaml | 3 +
.../allwinner/sun50i-a100-allwinner-perf1.dts | 54 +++++
.../arm64/boot/dts/allwinner/sun50i-a100.dtsi | 197 +++++++++++++++++-
drivers/dma/sun6i-dma.c | 25 +++
drivers/mmc/host/sunxi-mmc.c | 28 ++-
drivers/phy/allwinner/phy-sun4i-usb.c | 29 ++-
drivers/phy/allwinner/phy-sun50i-usb3.c | 4 +-
drivers/phy/allwinner/phy-sun6i-mipi-dphy.c | 4 +-
drivers/phy/allwinner/phy-sun9i-usb.c | 4 +-
drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c | 2 +-
drivers/pinctrl/sunxi/pinctrl-sunxi.c | 9 +-
14 files changed, 443 insertions(+), 28 deletions(-)
create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun50i-a100-usb-phy.yaml
--
2.28.0
From: Yangtao Li <[email protected]>
A100's pin starts with PB, so it should start with 1.
Fixes: 473436e7647d6 ("pinctrl: sunxi: add support for the Allwinner A100 pin controller")
Signed-off-by: Yangtao Li <[email protected]>
---
drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
index 19cfd1e76ee2..e69f6da40dc0 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sun50i-a100.c
@@ -677,7 +677,7 @@ static const struct sunxi_desc_pin a100_pins[] = {
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 19)),
};
-static const unsigned int a100_irq_bank_map[] = { 0, 1, 2, 3, 4, 5, 6};
+static const unsigned int a100_irq_bank_map[] = { 1, 2, 3, 4, 5, 6, 7};
static const struct sunxi_pinctrl_desc a100_pinctrl_data = {
.pins = a100_pins,
--
2.28.0
From: Yangtao Li <[email protected]>
The interrupt descriptor cannot be found in the interrupt processing
function, and this situation cannot happen when the system is running
normally. It doesn't seem right to return directly to the status of not
handling gic. In this case, it must be a bug, let's mark it with
WARN_ON.
Signed-off-by: Yangtao Li <[email protected]>
---
drivers/pinctrl/sunxi/pinctrl-sunxi.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 8e792f8e2dc9..9d8b59dafa4b 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -1139,8 +1139,7 @@ static void sunxi_pinctrl_irq_handler(struct irq_desc *desc)
if (irq == pctl->irq[bank])
break;
- if (bank == pctl->desc->irq_banks)
- return;
+ WARN_ON(bank == pctl->desc->irq_banks);
reg = sunxi_irq_status_reg_from_bank(pctl->desc, bank);
val = readl(pctl->membase + reg);
--
2.28.0
From: Yangtao Li <[email protected]>
It is found on many allwinner soc that there is a low probability that
the interrupt status cannot be read in sunxi_pinctrl_irq_handler. This
will cause the interrupt status of a gpio bank to always be active on
gic, preventing gic from responding to other spi interrupts correctly.
So we should call the chained_irq_* each time enter sunxi_pinctrl_irq_handler().
Cc: [email protected]
Signed-off-by: Yangtao Li <[email protected]>
---
drivers/pinctrl/sunxi/pinctrl-sunxi.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 9d8b59dafa4b..dc8d39ae045b 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -1141,20 +1141,22 @@ static void sunxi_pinctrl_irq_handler(struct irq_desc *desc)
WARN_ON(bank == pctl->desc->irq_banks);
+ chained_irq_enter(chip, desc);
+
reg = sunxi_irq_status_reg_from_bank(pctl->desc, bank);
val = readl(pctl->membase + reg);
if (val) {
int irqoffset;
- chained_irq_enter(chip, desc);
for_each_set_bit(irqoffset, &val, IRQ_PER_BANK) {
int pin_irq = irq_find_mapping(pctl->domain,
bank * IRQ_PER_BANK + irqoffset);
generic_handle_irq(pin_irq);
}
- chained_irq_exit(chip, desc);
}
+
+ chained_irq_exit(chip, desc);
}
static int sunxi_pinctrl_add_function(struct sunxi_pinctrl *pctl,
--
2.28.0
From: Yangtao Li <[email protected]>
Add a binding for A100's dma controller.
Signed-off-by: Yangtao Li <[email protected]>
---
.../devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml b/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml
index 372679dbd216..b6e1ebfaf366 100644
--- a/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml
+++ b/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml
@@ -21,6 +21,7 @@ properties:
compatible:
oneOf:
- const: allwinner,sun50i-a64-dma
+ - const: allwinner,sun50i-a100-dma
- const: allwinner,sun50i-h6-dma
- items:
- const: allwinner,sun8i-r40-dma
@@ -56,7 +57,9 @@ required:
if:
properties:
compatible:
- const: allwinner,sun50i-h6-dma
+ enum:
+ - allwinner,sun50i-a100-dma
+ - allwinner,sun50i-h6-dma
then:
properties:
--
2.28.0
From: Yangtao Li <[email protected]>
The A100 SoC has a DMA controller that supports 8 DMA channels
to and from various peripherals.
Add a device node for it.
Signed-off-by: Yangtao Li <[email protected]>
---
arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
index cc321c04f121..c34ed8045363 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
@@ -101,6 +101,18 @@ ccu: clock@3001000 {
#reset-cells = <1>;
};
+ dma: dma-controller@3002000 {
+ compatible = "allwinner,sun50i-a100-dma";
+ reg = <0x03002000 0x1000>;
+ interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_DMA>, <&ccu CLK_MBUS_DMA>;
+ clock-names = "bus", "mbus";
+ dma-channels = <8>;
+ dma-requests = <51>;
+ resets = <&ccu RST_BUS_DMA>;
+ #dma-cells = <1>;
+ };
+
gic: interrupt-controller@3021000 {
compatible = "arm,gic-400";
reg = <0x03021000 0x1000>, <0x03022000 0x2000>,
--
2.28.0
From: Yangtao Li <[email protected]>
The dma of a100 is similar to h6, with some minor changes to
support greater addressing capabilities.
Add support for it.
Signed-off-by: Yangtao Li <[email protected]>
---
drivers/dma/sun6i-dma.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index f5f9c86c50bc..5cadd4d2b824 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -1173,6 +1173,30 @@ static struct sun6i_dma_config sun50i_a64_dma_cfg = {
BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
};
+/*
+ * TODO: Add support for more than 4g physical addressing.
+ *
+ * The A100 binding uses the number of dma channels from the
+ * device tree node.
+ */
+static struct sun6i_dma_config sun50i_a100_dma_cfg = {
+ .clock_autogate_enable = sun6i_enable_clock_autogate_h3,
+ .set_burst_length = sun6i_set_burst_length_h3,
+ .set_drq = sun6i_set_drq_h6,
+ .set_mode = sun6i_set_mode_h6,
+ .src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+ .dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+ .src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+ .dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+ BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+ BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+ .has_mbus_clk = true,
+};
+
/*
* The H6 binding uses the number of dma channels from the
* device tree node.
@@ -1225,6 +1249,7 @@ static const struct of_device_id sun6i_dma_match[] = {
{ .compatible = "allwinner,sun8i-h3-dma", .data = &sun8i_h3_dma_cfg },
{ .compatible = "allwinner,sun8i-v3s-dma", .data = &sun8i_v3s_dma_cfg },
{ .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg },
+ { .compatible = "allwinner,sun50i-a100-dma", .data = &sun50i_a100_dma_cfg },
{ .compatible = "allwinner,sun50i-h6-dma", .data = &sun50i_h6_dma_cfg },
{ /* sentinel */ }
};
--
2.28.0
From: Yangtao Li <[email protected]>
Add the Performance Monitoring Unit (PMU) device tree node to the A100
.dtsi, which tells DT users which interrupts are triggered by PMU overflow
events on each core.
Signed-off-by: Yangtao Li <[email protected]>
---
arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
index c34ed8045363..01ff53b5a7a8 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
@@ -25,21 +25,21 @@ cpu0: cpu@0 {
enable-method = "psci";
};
- cpu@1 {
+ cpu1: cpu@1 {
compatible = "arm,cortex-a53";
device_type = "cpu";
reg = <0x1>;
enable-method = "psci";
};
- cpu@2 {
+ cpu2: cpu@2 {
compatible = "arm,cortex-a53";
device_type = "cpu";
reg = <0x2>;
enable-method = "psci";
};
- cpu@3 {
+ cpu3: cpu@3 {
compatible = "arm,cortex-a53";
device_type = "cpu";
reg = <0x3>;
@@ -47,6 +47,15 @@ cpu@3 {
};
};
+ pmu {
+ compatible = "arm,cortex-a53-pmu";
+ interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+ };
+
psci {
compatible = "arm,psci-1.0";
method = "smc";
--
2.28.0
From: Yangtao Li <[email protected]>
For the current code, enable_pmu_unk1 only works in non-a83t and non-h6
types. So let's delete it from the sun50i_h6_cfg.
Signed-off-by: Yangtao Li <[email protected]>
---
drivers/phy/allwinner/phy-sun4i-usb.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index 651d5e2a25ce..0f1888b55dbd 100644
--- a/drivers/phy/allwinner/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -969,7 +969,6 @@ static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = {
.disc_thresh = 3,
.phyctl_offset = REG_PHYCTL_A33,
.dedicated_clocks = true,
- .enable_pmu_unk1 = true,
.phy0_dual_route = true,
.missing_phys = BIT(1) | BIT(2),
};
--
2.28.0
From: Yangtao Li <[email protected]>
Add a binding for A100's watchdog controller.
Signed-off-by: Yangtao Li <[email protected]>
---
.../devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
index e8f226376108..5ac607de8be4 100644
--- a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
@@ -21,6 +21,9 @@ properties:
- items:
- const: allwinner,sun50i-a64-wdt
- const: allwinner,sun6i-a31-wdt
+ - items:
+ - const: allwinner,sun50i-a100-wdt
+ - const: allwinner,sun6i-a31-wdt
- items:
- const: allwinner,sun50i-h6-wdt
- const: allwinner,sun6i-a31-wdt
--
2.28.0
From: Yangtao Li <[email protected]>
Use the devm_platform_ioremap_resource_byname() and
devm_platform_ioremap_resource helper to simplify the code.
Signed-off-by: Yangtao Li <[email protected]>
---
drivers/phy/allwinner/phy-sun4i-usb.c | 9 +++------
drivers/phy/allwinner/phy-sun50i-usb3.c | 4 +---
drivers/phy/allwinner/phy-sun6i-mipi-dphy.c | 4 +---
drivers/phy/allwinner/phy-sun9i-usb.c | 4 +---
4 files changed, 6 insertions(+), 15 deletions(-)
diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index 0f1888b55dbd..a6900495baa5 100644
--- a/drivers/phy/allwinner/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -686,7 +686,6 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct phy_provider *phy_provider;
- struct resource *res;
int i, ret;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
@@ -700,8 +699,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
if (!data->cfg)
return -EINVAL;
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl");
- data->base = devm_ioremap_resource(dev, res);
+ data->base = devm_platform_ioremap_resource_byname(pdev, "phy_ctrl");
if (IS_ERR(data->base))
return PTR_ERR(data->base);
@@ -796,9 +794,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
if (i || data->cfg->phy0_dual_route) { /* No pmu for musb */
snprintf(name, sizeof(name), "pmu%d", i);
- res = platform_get_resource_byname(pdev,
- IORESOURCE_MEM, name);
- phy->pmu = devm_ioremap_resource(dev, res);
+ phy->pmu = devm_platform_ioremap_resource_byname(pdev,
+ name);
if (IS_ERR(phy->pmu))
return PTR_ERR(phy->pmu);
}
diff --git a/drivers/phy/allwinner/phy-sun50i-usb3.c b/drivers/phy/allwinner/phy-sun50i-usb3.c
index b1c04f71a31d..84055b720016 100644
--- a/drivers/phy/allwinner/phy-sun50i-usb3.c
+++ b/drivers/phy/allwinner/phy-sun50i-usb3.c
@@ -134,7 +134,6 @@ static int sun50i_usb3_phy_probe(struct platform_device *pdev)
struct sun50i_usb3_phy *phy;
struct device *dev = &pdev->dev;
struct phy_provider *phy_provider;
- struct resource *res;
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
if (!phy)
@@ -153,8 +152,7 @@ static int sun50i_usb3_phy_probe(struct platform_device *pdev)
return PTR_ERR(phy->reset);
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- phy->regs = devm_ioremap_resource(dev, res);
+ phy->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(phy->regs))
return PTR_ERR(phy->regs);
diff --git a/drivers/phy/allwinner/phy-sun6i-mipi-dphy.c b/drivers/phy/allwinner/phy-sun6i-mipi-dphy.c
index 1fa761ba6cbb..f0bc87d654d4 100644
--- a/drivers/phy/allwinner/phy-sun6i-mipi-dphy.c
+++ b/drivers/phy/allwinner/phy-sun6i-mipi-dphy.c
@@ -253,15 +253,13 @@ static int sun6i_dphy_probe(struct platform_device *pdev)
{
struct phy_provider *phy_provider;
struct sun6i_dphy *dphy;
- struct resource *res;
void __iomem *regs;
dphy = devm_kzalloc(&pdev->dev, sizeof(*dphy), GFP_KERNEL);
if (!dphy)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- regs = devm_ioremap_resource(&pdev->dev, res);
+ regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs)) {
dev_err(&pdev->dev, "Couldn't map the DPHY encoder registers\n");
return PTR_ERR(regs);
diff --git a/drivers/phy/allwinner/phy-sun9i-usb.c b/drivers/phy/allwinner/phy-sun9i-usb.c
index fc6784dd7fa0..2f9e60c188b8 100644
--- a/drivers/phy/allwinner/phy-sun9i-usb.c
+++ b/drivers/phy/allwinner/phy-sun9i-usb.c
@@ -117,7 +117,6 @@ static int sun9i_usb_phy_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct phy_provider *phy_provider;
- struct resource *res;
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
if (!phy)
@@ -156,8 +155,7 @@ static int sun9i_usb_phy_probe(struct platform_device *pdev)
}
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- phy->pmu = devm_ioremap_resource(dev, res);
+ phy->pmu = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(phy->pmu))
return PTR_ERR(phy->pmu);
--
2.28.0
From: Yangtao Li <[email protected]>
Declare A100's watchdog in the device-tree.
Signed-off-by: Yangtao Li <[email protected]>
---
arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
index 01ff53b5a7a8..6aa3337ce0e9 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
@@ -144,6 +144,14 @@ ths_calibration: calib@14 {
};
};
+ watchdog@30090a0 {
+ compatible = "allwinner,sun50i-a100-wdt",
+ "allwinner,sun6i-a31-wdt";
+ reg = <0x030090a0 0x20>;
+ interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&dcxo24M>;
+ };
+
pio: pinctrl@300b000 {
compatible = "allwinner,sun50i-a100-pinctrl";
reg = <0x0300b000 0x400>;
--
2.28.0
From: Yangtao Li <[email protected]>
Add a device tree binding for the A100's USB PHY.
Signed-off-by: Yangtao Li <[email protected]>
---
.../phy/allwinner,sun50i-a100-usb-phy.yaml | 105 ++++++++++++++++++
1 file changed, 105 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun50i-a100-usb-phy.yaml
diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun50i-a100-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun50i-a100-usb-phy.yaml
new file mode 100644
index 000000000000..cc9bbebe2bd7
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/allwinner,sun50i-a100-usb-phy.yaml
@@ -0,0 +1,105 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/allwinner,sun50i-a100-usb-phy.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner A100 USB PHY Device Tree Bindings
+
+maintainers:
+ - Yangtao Li <[email protected]>
+
+properties:
+ "#phy-cells":
+ const: 1
+
+ compatible:
+ const: allwinner,sun50i-a100-usb-phy
+
+ reg:
+ items:
+ - description: PHY Control registers
+ - description: PHY PMU0 registers
+ - description: PHY PMU1 registers
+
+ reg-names:
+ items:
+ - const: phy_ctrl
+ - const: pmu0
+ - const: pmu1
+
+ clocks:
+ items:
+ - description: USB OTG PHY bus clock
+ - description: USB Host 0 PHY bus clock
+
+ clock-names:
+ items:
+ - const: usb0_phy
+ - const: usb1_phy
+
+ resets:
+ items:
+ - description: USB OTG reset
+ - description: USB Host 1 Controller reset
+
+ reset-names:
+ items:
+ - const: usb0_reset
+ - const: usb1_reset
+
+ usb0_id_det-gpios:
+ description: GPIO to the USB OTG ID pin
+
+ usb0_vbus_det-gpios:
+ description: GPIO to the USB OTG VBUS detect pin
+
+ usb0_vbus_power-supply:
+ description: Power supply to detect the USB OTG VBUS
+
+ usb0_vbus-supply:
+ description: Regulator controlling USB OTG VBUS
+
+ usb1_vbus-supply:
+ description: Regulator controlling USB1 Host controller
+
+required:
+ - "#phy-cells"
+ - compatible
+ - clocks
+ - clock-names
+ - reg
+ - reg-names
+ - resets
+ - reset-names
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/clock/sun50i-a100-ccu.h>
+ #include <dt-bindings/reset/sun50i-a100-ccu.h>
+
+ phy@5100400 {
+ #phy-cells = <1>;
+ compatible = "allwinner,sun50i-a100-usb-phy";
+ reg = <0x05100400 0x14>,
+ <0x05101800 0x4>,
+ <0x05200800 0x4>;
+ reg-names = "phy_ctrl",
+ "pmu0",
+ "pmu1";
+ clocks = <&ccu CLK_USB_PHY0>,
+ <&ccu CLK_USB_PHY1>;
+ clock-names = "usb0_phy",
+ "usb1_phy";
+ resets = <&ccu RST_USB_PHY0>,
+ <&ccu RST_USB_PHY1>;
+ reset-names = "usb0_reset",
+ "usb1_reset";
+ usb0_id_det-gpios = <&pio 7 10 GPIO_ACTIVE_HIGH>; /* PH10 */
+ usb0_vbus_power-supply = <&usb_power_supply>;
+ usb0_vbus-supply = <®_drivevbus>;
+ usb1_vbus-supply = <®_usb1_vbus>;
+ };
--
2.28.0
From: Yangtao Li <[email protected]>
Add support for a100's usb phy, which with 2 PHYs.
Signed-off-by: Yangtao Li <[email protected]>
---
drivers/phy/allwinner/phy-sun4i-usb.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index a6900495baa5..1a0e403131e7 100644
--- a/drivers/phy/allwinner/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -107,6 +107,7 @@ enum sun4i_usb_phy_type {
sun8i_r40_phy,
sun8i_v3s_phy,
sun50i_a64_phy,
+ sun50i_a100_phy,
sun50i_h6_phy,
};
@@ -289,7 +290,13 @@ static int sun4i_usb_phy_init(struct phy *_phy)
}
if (data->cfg->type == sun8i_a83t_phy ||
+ data->cfg->type == sun50i_a100_phy ||
data->cfg->type == sun50i_h6_phy) {
+ if (phy->pmu && data->cfg->enable_pmu_unk1) {
+ val = readl(phy->pmu + REG_PMU_UNK1);
+ writel(val & ~BIT(3), phy->pmu + REG_PMU_UNK1);
+ }
+
if (phy->index == 0) {
val = readl(data->base + data->cfg->phyctl_offset);
val |= PHY_CTL_VBUSVLDEXT;
@@ -339,6 +346,7 @@ static int sun4i_usb_phy_exit(struct phy *_phy)
if (phy->index == 0) {
if (data->cfg->type == sun8i_a83t_phy ||
+ data->cfg->type == sun50i_a100_phy ||
data->cfg->type == sun50i_h6_phy) {
void __iomem *phyctl = data->base +
data->cfg->phyctl_offset;
@@ -960,6 +968,16 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = {
.phy0_dual_route = true,
};
+static const struct sun4i_usb_phy_cfg sun50i_a100_cfg = {
+ .num_phys = 2,
+ .type = sun50i_a100_phy,
+ .disc_thresh = 3,
+ .phyctl_offset = REG_PHYCTL_A33,
+ .dedicated_clocks = true,
+ .enable_pmu_unk1 = true,
+ .phy0_dual_route = true,
+};
+
static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = {
.num_phys = 4,
.type = sun50i_h6_phy,
@@ -983,6 +1001,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = {
{ .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg },
{ .compatible = "allwinner,sun50i-a64-usb-phy",
.data = &sun50i_a64_cfg},
+ { .compatible = "allwinner,sun50i-a100-usb-phy", .data = &sun50i_a100_cfg },
{ .compatible = "allwinner,sun50i-h6-usb-phy", .data = &sun50i_h6_cfg },
{ },
};
--
2.28.0
From: Yangtao Li <[email protected]>
Allwinner A64 have two HCI USB controllers, a OTG controller and a USB
PHY device, let's add nodes on dts.
Signed-off-by: Yangtao Li <[email protected]>
---
.../arm64/boot/dts/allwinner/sun50i-a100.dtsi | 91 +++++++++++++++++++
1 file changed, 91 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
index 6aa3337ce0e9..c731bb9727c2 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
@@ -290,6 +290,97 @@ ths: thermal-sensor@5070400 {
#thermal-sensor-cells = <1>;
};
+ usbphy: phy@5100400 {
+ #phy-cells = <1>;
+ compatible = "allwinner,sun50i-a100-usb-phy";
+ reg = <0x05100400 0x14>,
+ <0x05101800 0x4>,
+ <0x05200800 0x4>;
+ reg-names = "phy_ctrl",
+ "pmu0",
+ "pmu1";
+ clocks = <&ccu CLK_USB_PHY0>,
+ <&ccu CLK_USB_PHY1>;
+ clock-names = "usb0_phy",
+ "usb1_phy";
+ resets = <&ccu RST_USB_PHY0>,
+ <&ccu RST_USB_PHY1>;
+ reset-names = "usb0_reset",
+ "usb1_reset";
+ status = "disabled";
+ };
+
+ ehci0: usb@5101000 {
+ compatible = "allwinner,sun50i-a100-ehci",
+ "generic-ehci";
+ reg = <0x05101000 0x100>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI0>,
+ <&ccu CLK_BUS_EHCI0>,
+ <&ccu CLK_USB_OHCI0>;
+ resets = <&ccu RST_BUS_OHCI0>,
+ <&ccu RST_BUS_EHCI0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci0: usb@5101400 {
+ compatible = "allwinner,sun50i-a100-ohci",
+ "generic-ohci";
+ reg = <0x05101400 0x100>;
+ interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI0>,
+ <&ccu CLK_USB_OHCI0>;
+ resets = <&ccu RST_BUS_OHCI0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ usb_otg: usb@5100000 {
+ compatible = "allwinner,sun50i-a100-musb",
+ "allwinner,sun8i-h3-musb";
+ reg = <0x05100000 0x0400>;
+ clocks = <&ccu CLK_BUS_OTG>;
+ resets = <&ccu RST_BUS_OTG>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "mc";
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ extcon = <&usbphy 0>;
+ dr_mode = "otg";
+ status = "disabled";
+ };
+
+ ehci1: usb@5200000 {
+ compatible = "allwinner,sun50i-a100-ehci",
+ "generic-ehci";
+ reg = <0x05200000 0x100>;
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI1>,
+ <&ccu CLK_BUS_EHCI1>,
+ <&ccu CLK_USB_OHCI1>;
+ resets = <&ccu RST_BUS_OHCI1>,
+ <&ccu RST_BUS_EHCI1>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci1: usb@5200400 {
+ compatible = "allwinner,sun50i-a100-ohci",
+ "generic-ohci";
+ reg = <0x05200400 0x100>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI1>,
+ <&ccu CLK_USB_OHCI1>;
+ resets = <&ccu RST_BUS_OHCI1>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
r_ccu: clock@7010000 {
compatible = "allwinner,sun50i-a100-r-ccu";
reg = <0x07010000 0x300>;
--
2.28.0
From: Yangtao Li <[email protected]>
Add USB support on A100 perf1 board, which include two USB2.0 port.
Signed-off-by: Yangtao Li <[email protected]>
---
.../allwinner/sun50i-a100-allwinner-perf1.dts | 38 +++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100-allwinner-perf1.dts b/arch/arm64/boot/dts/allwinner/sun50i-a100-allwinner-perf1.dts
index d34c2bb1079f..ef205c9b8ff4 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a100-allwinner-perf1.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a100-allwinner-perf1.dts
@@ -7,6 +7,8 @@
#include "sun50i-a100.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
/{
model = "Allwinner A100 Perf1";
compatible = "allwinner,a100-perf1", "allwinner,sun50i-a100";
@@ -18,6 +20,35 @@ aliases {
chosen {
stdout-path = "serial0:115200n8";
};
+
+ reg_usb1_vbus: usb1-vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb1-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&pio 7 10 GPIO_ACTIVE_HIGH>; /* PH10 */
+ enable-active-high;
+ };
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&usb_otg {
+ status = "okay";
};
&pio {
@@ -178,3 +209,10 @@ &uart0 {
pinctrl-0 = <&uart0_pb_pins>;
status = "okay";
};
+
+&usbphy {
+ usb0_id_det-gpios = <&pio 7 8 GPIO_ACTIVE_HIGH>; /* PH8 */
+ usb0_vbus-supply = <®_drivevbus>;
+ usb1_vbus-supply = <®_usb1_vbus>;
+ status = "okay";
+};
--
2.28.0
From: Yangtao Li <[email protected]>
Add binding for A100's mmc and emmc controller.
Signed-off-by: Yangtao Li <[email protected]>
---
.../devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
index e82c9a07b6fb..41821f14ecaa 100644
--- a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
+++ b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
@@ -26,6 +26,8 @@ properties:
- const: allwinner,sun9i-a80-mmc
- const: allwinner,sun50i-a64-emmc
- const: allwinner,sun50i-a64-mmc
+ - const: allwinner,sun50i-a100-emmc
+ - const: allwinner,sun50i-a100-mmc
- items:
- const: allwinner,sun8i-a83t-mmc
- const: allwinner,sun7i-a20-mmc
--
2.28.0
From: Yangtao Li <[email protected]>
This patch adds support for A100 MMC controller, which use word address
for internal dma.
Signed-off-by: Yangtao Li <[email protected]>
---
drivers/mmc/host/sunxi-mmc.c | 28 +++++++++++++++++++++++++---
1 file changed, 25 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index fc62773602ec..1518b64112b7 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -244,6 +244,7 @@ struct sunxi_idma_des {
struct sunxi_mmc_cfg {
u32 idma_des_size_bits;
+ u32 idma_des_shift;
const struct sunxi_mmc_clk_delay *clk_delays;
/* does the IP block support autocalibration? */
@@ -343,7 +344,7 @@ static int sunxi_mmc_init_host(struct sunxi_mmc_host *host)
/* Enable CEATA support */
mmc_writel(host, REG_FUNS, SDXC_CEATA_ON);
/* Set DMA descriptor list base address */
- mmc_writel(host, REG_DLBA, host->sg_dma);
+ mmc_writel(host, REG_DLBA, host->sg_dma >> host->cfg->idma_des_shift);
rval = mmc_readl(host, REG_GCTRL);
rval |= SDXC_INTERRUPT_ENABLE_BIT;
@@ -373,8 +374,10 @@ static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host,
next_desc += sizeof(struct sunxi_idma_des);
pdes[i].buf_addr_ptr1 =
- cpu_to_le32(sg_dma_address(&data->sg[i]));
- pdes[i].buf_addr_ptr2 = cpu_to_le32((u32)next_desc);
+ cpu_to_le32(sg_dma_address(&data->sg[i]) >>
+ host->cfg->idma_des_shift);
+ pdes[i].buf_addr_ptr2 = cpu_to_le32((u32)next_desc >>
+ host->cfg->idma_des_shift);
}
pdes[0].config |= cpu_to_le32(SDXC_IDMAC_DES0_FD);
@@ -1178,6 +1181,23 @@ static const struct sunxi_mmc_cfg sun50i_a64_emmc_cfg = {
.needs_new_timings = true,
};
+static const struct sunxi_mmc_cfg sun50i_a100_cfg = {
+ .idma_des_size_bits = 16,
+ .idma_des_shift = 2,
+ .clk_delays = NULL,
+ .can_calibrate = true,
+ .mask_data0 = true,
+ .needs_new_timings = true,
+};
+
+static const struct sunxi_mmc_cfg sun50i_a100_emmc_cfg = {
+ .idma_des_size_bits = 13,
+ .idma_des_shift = 2,
+ .clk_delays = NULL,
+ .can_calibrate = true,
+ .needs_new_timings = true,
+};
+
static const struct of_device_id sunxi_mmc_of_match[] = {
{ .compatible = "allwinner,sun4i-a10-mmc", .data = &sun4i_a10_cfg },
{ .compatible = "allwinner,sun5i-a13-mmc", .data = &sun5i_a13_cfg },
@@ -1186,6 +1206,8 @@ static const struct of_device_id sunxi_mmc_of_match[] = {
{ .compatible = "allwinner,sun9i-a80-mmc", .data = &sun9i_a80_cfg },
{ .compatible = "allwinner,sun50i-a64-mmc", .data = &sun50i_a64_cfg },
{ .compatible = "allwinner,sun50i-a64-emmc", .data = &sun50i_a64_emmc_cfg },
+ { .compatible = "allwinner,sun50i-a100-mmc", .data = &sun50i_a100_cfg },
+ { .compatible = "allwinner,sun50i-a100-emmc", .data = &sun50i_a100_emmc_cfg },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
--
2.28.0
From: Yangtao Li <[email protected]>
A100 perf1 hava MicroSD slot and on-board eMMC module, add support for them.
Signed-off-by: Yangtao Li <[email protected]>
---
.../allwinner/sun50i-a100-allwinner-perf1.dts | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100-allwinner-perf1.dts b/arch/arm64/boot/dts/allwinner/sun50i-a100-allwinner-perf1.dts
index ef205c9b8ff4..d102c50ff7c1 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a100-allwinner-perf1.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a100-allwinner-perf1.dts
@@ -39,6 +39,22 @@ &ehci1 {
status = "okay";
};
+&mmc0 {
+ vmmc-supply = <®_dcdc1>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+ bus-width = <4>;
+ status = "okay";
+};
+
+&mmc2 {
+ vmmc-supply = <®_dcdc1>;
+ vqmmc-supply = <®_aldo1>;
+ cap-mmc-hw-reset;
+ non-removable;
+ bus-width = <8>;
+ status = "okay";
+};
+
&ohci0 {
status = "okay";
};
--
2.28.0
From: Yangtao Li <[email protected]>
The A100 has 3 MMC controllers, one of them being especially targeted to
eMMC. Let's add nodes on dts.
Signed-off-by: Yangtao Li <[email protected]>
---
.../arm64/boot/dts/allwinner/sun50i-a100.dtsi | 71 +++++++++++++++++++
1 file changed, 71 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
index c731bb9727c2..4adfc7d4854a 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
@@ -169,12 +169,83 @@ pio: pinctrl@300b000 {
interrupt-controller;
#interrupt-cells = <3>;
+ mmc0_pins: mmc0-pins {
+ pins = "PF0", "PF1", "PF2", "PF3",
+ "PF4", "PF5";
+ function = "mmc0";
+ drive-strength = <30>;
+ bias-pull-up;
+ };
+
+ /omit-if-no-ref/
+ mmc1_pins: mmc1-pins {
+ pins = "PG0", "PG1", "PG2", "PG3",
+ "PG4", "PG5";
+ function = "mmc1";
+ drive-strength = <30>;
+ bias-pull-up;
+ };
+
+ mmc2_pins: mmc2-pins {
+ pins = "PC0", "PC1", "PC5", "PC6",
+ "PC8", "PC9", "PC10", "PC11",
+ "PC13", "PC14", "PC15", "PC16";
+ function = "mmc2";
+ drive-strength = <30>;
+ bias-pull-up;
+ };
+
uart0_pb_pins: uart0-pb-pins {
pins = "PB9", "PB10";
function = "uart0";
};
};
+ mmc0: mmc@4020000 {
+ compatible = "allwinner,sun50i-a100-mmc";
+ reg = <0x04020000 0x1000>;
+ clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC0>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc1: mmc@4021000 {
+ compatible = "allwinner,sun50i-a100-mmc";
+ reg = <0x04021000 0x1000>;
+ clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC1>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc1_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ mmc2: mmc@4022000 {
+ compatible = "allwinner,sun50i-a100-emmc";
+ reg = <0x04022000 0x1000>;
+ clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
+ clock-names = "ahb", "mmc";
+ resets = <&ccu RST_BUS_MMC2>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc2_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
uart0: serial@5000000 {
compatible = "snps,dw-apb-uart";
reg = <0x05000000 0x400>;
--
2.28.0
On Tue, 10 Nov 2020 14:45:16 +0800, Frank Lee wrote:
> From: Yangtao Li <[email protected]>
>
> Add binding for A100's mmc and emmc controller.
>
> Signed-off-by: Yangtao Li <[email protected]>
> ---
> .../devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml | 2 ++
> 1 file changed, 2 insertions(+)
>
Acked-by: Rob Herring <[email protected]>
On Tue, Nov 10, 2020 at 02:39:42PM +0800, Frank Lee wrote:
> From: Yangtao Li <[email protected]>
>
> Add a device tree binding for the A100's USB PHY.
>
> Signed-off-by: Yangtao Li <[email protected]>
> ---
> .../phy/allwinner,sun50i-a100-usb-phy.yaml | 105 ++++++++++++++++++
> 1 file changed, 105 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun50i-a100-usb-phy.yaml
>
> diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun50i-a100-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun50i-a100-usb-phy.yaml
> new file mode 100644
> index 000000000000..cc9bbebe2bd7
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/allwinner,sun50i-a100-usb-phy.yaml
> @@ -0,0 +1,105 @@
> +# SPDX-License-Identifier: GPL-2.0
Dual license new bindings. checkpatch.pl will tell you which ones.
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/phy/allwinner,sun50i-a100-usb-phy.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Allwinner A100 USB PHY Device Tree Bindings
> +
> +maintainers:
> + - Yangtao Li <[email protected]>
> +
> +properties:
> + "#phy-cells":
> + const: 1
> +
> + compatible:
> + const: allwinner,sun50i-a100-usb-phy
> +
> + reg:
> + items:
> + - description: PHY Control registers
> + - description: PHY PMU0 registers
> + - description: PHY PMU1 registers
> +
> + reg-names:
> + items:
> + - const: phy_ctrl
> + - const: pmu0
> + - const: pmu1
> +
> + clocks:
> + items:
> + - description: USB OTG PHY bus clock
> + - description: USB Host 0 PHY bus clock
> +
> + clock-names:
> + items:
> + - const: usb0_phy
> + - const: usb1_phy
> +
> + resets:
> + items:
> + - description: USB OTG reset
> + - description: USB Host 1 Controller reset
> +
> + reset-names:
> + items:
> + - const: usb0_reset
> + - const: usb1_reset
> +
> + usb0_id_det-gpios:
> + description: GPIO to the USB OTG ID pin
Needs 'maxItems: 1'
> +
> + usb0_vbus_det-gpios:
> + description: GPIO to the USB OTG VBUS detect pin
> +
> + usb0_vbus_power-supply:
> + description: Power supply to detect the USB OTG VBUS
> +
> + usb0_vbus-supply:
> + description: Regulator controlling USB OTG VBUS
> +
> + usb1_vbus-supply:
> + description: Regulator controlling USB1 Host controller
Are ID and VBus actually connected to the phy h/w? Really, all this
should be in a USB connector node for which we have bindings.
> +
> +required:
> + - "#phy-cells"
> + - compatible
> + - clocks
> + - clock-names
> + - reg
> + - reg-names
> + - resets
> + - reset-names
> +
> +additionalProperties: false
> +
> +examples:
> + - |
> + #include <dt-bindings/gpio/gpio.h>
> + #include <dt-bindings/clock/sun50i-a100-ccu.h>
> + #include <dt-bindings/reset/sun50i-a100-ccu.h>
> +
> + phy@5100400 {
> + #phy-cells = <1>;
> + compatible = "allwinner,sun50i-a100-usb-phy";
> + reg = <0x05100400 0x14>,
> + <0x05101800 0x4>,
> + <0x05200800 0x4>;
> + reg-names = "phy_ctrl",
> + "pmu0",
> + "pmu1";
> + clocks = <&ccu CLK_USB_PHY0>,
> + <&ccu CLK_USB_PHY1>;
> + clock-names = "usb0_phy",
> + "usb1_phy";
> + resets = <&ccu RST_USB_PHY0>,
> + <&ccu RST_USB_PHY1>;
> + reset-names = "usb0_reset",
> + "usb1_reset";
> + usb0_id_det-gpios = <&pio 7 10 GPIO_ACTIVE_HIGH>; /* PH10 */
> + usb0_vbus_power-supply = <&usb_power_supply>;
> + usb0_vbus-supply = <®_drivevbus>;
> + usb1_vbus-supply = <®_usb1_vbus>;
> + };
> --
> 2.28.0
>
On Tue, 10 Nov 2020 14:36:48 +0800, Frank Lee wrote:
> From: Yangtao Li <[email protected]>
>
> Add a binding for A100's watchdog controller.
>
> Signed-off-by: Yangtao Li <[email protected]>
> ---
> .../devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml | 3 +++
> 1 file changed, 3 insertions(+)
>
Acked-by: Rob Herring <[email protected]>
On Tue, 10 Nov 2020 14:26:38 +0800, Frank Lee wrote:
> From: Yangtao Li <[email protected]>
>
> Add a binding for A100's dma controller.
>
> Signed-off-by: Yangtao Li <[email protected]>
> ---
> .../devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
Acked-by: Rob Herring <[email protected]>
On 10-11-20, 14:28, Frank Lee wrote:
> From: Yangtao Li <[email protected]>
>
> The dma of a100 is similar to h6, with some minor changes to
> support greater addressing capabilities.
>
> Add support for it.
Applied, thanks
--
~Vinod
On 10-11-20, 14:26, Frank Lee wrote:
> From: Yangtao Li <[email protected]>
>
> Add a binding for A100's dma controller.
Applied, thanks
--
~Vinod
On 10-11-20, 14:32, Frank Lee wrote:
> From: Yangtao Li <[email protected]>
>
> For the current code, enable_pmu_unk1 only works in non-a83t and non-h6
> types. So let's delete it from the sun50i_h6_cfg.
Applied, thanks
--
~Vinod
On 10-11-20, 14:35, Frank Lee wrote:
> From: Yangtao Li <[email protected]>
>
> Use the devm_platform_ioremap_resource_byname() and
> devm_platform_ioremap_resource helper to simplify the code.
This fails to apply for me, pls rebase
--
~Vinod
On Tue, Nov 10, 2020 at 7:24 AM Frank Lee <[email protected]> wrote:
> From: Yangtao Li <[email protected]>
>
> The interrupt descriptor cannot be found in the interrupt processing
> function, and this situation cannot happen when the system is running
> normally. It doesn't seem right to return directly to the status of not
> handling gic. In this case, it must be a bug, let's mark it with
> WARN_ON.
>
> Signed-off-by: Yangtao Li <[email protected]>
Patch applied.
Yours,
Linus Walleij
On Tue, Nov 10, 2020 at 7:23 AM Frank Lee <[email protected]> wrote:
> From: Yangtao Li <[email protected]>
>
> A100's pin starts with PB, so it should start with 1.
>
> Fixes: 473436e7647d6 ("pinctrl: sunxi: add support for the Allwinner A100 pin controller")
> Signed-off-by: Yangtao Li <[email protected]>
No response from maintainers for 14 days so patch applied.
Yours,
Linus Walleij
On Tue, Nov 10, 2020 at 7:24 AM Frank Lee <[email protected]> wrote:
> From: Yangtao Li <[email protected]>
>
> It is found on many allwinner soc that there is a low probability that
> the interrupt status cannot be read in sunxi_pinctrl_irq_handler. This
> will cause the interrupt status of a gpio bank to always be active on
> gic, preventing gic from responding to other spi interrupts correctly.
>
> So we should call the chained_irq_* each time enter sunxi_pinctrl_irq_handler().
>
> Cc: [email protected]
> Signed-off-by: Yangtao Li <[email protected]>
Patch applied.
Yours,
Linus Walleij
On 10/11/2020 06:40, Frank Lee wrote:
Hi,
> From: Yangtao Li <[email protected]>
>
> Add support for a100's usb phy, which with 2 PHYs.
>
> Signed-off-by: Yangtao Li <[email protected]>
> ---
> drivers/phy/allwinner/phy-sun4i-usb.c | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
>
> diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
> index a6900495baa5..1a0e403131e7 100644
> --- a/drivers/phy/allwinner/phy-sun4i-usb.c
> +++ b/drivers/phy/allwinner/phy-sun4i-usb.c
> @@ -107,6 +107,7 @@ enum sun4i_usb_phy_type {
> sun8i_r40_phy,
> sun8i_v3s_phy,
> sun50i_a64_phy,
> + sun50i_a100_phy,
But with that patch fixing the H6 support you don't need a new name, do you?
Because below you just add the sun50i_a100_phy name next to every place
with a sun50i_h6_phy check.
> sun50i_h6_phy,
> };
>
> @@ -289,7 +290,13 @@ static int sun4i_usb_phy_init(struct phy *_phy)
> }
>
> if (data->cfg->type == sun8i_a83t_phy ||
> + data->cfg->type == sun50i_a100_phy ||
> data->cfg->type == sun50i_h6_phy) {
> + if (phy->pmu && data->cfg->enable_pmu_unk1) {
> + val = readl(phy->pmu + REG_PMU_UNK1);
> + writel(val & ~BIT(3), phy->pmu + REG_PMU_UNK1);
> + }
> +
> if (phy->index == 0) {
> val = readl(data->base + data->cfg->phyctl_offset);
> val |= PHY_CTL_VBUSVLDEXT;
> @@ -339,6 +346,7 @@ static int sun4i_usb_phy_exit(struct phy *_phy)
>
> if (phy->index == 0) {
> if (data->cfg->type == sun8i_a83t_phy ||
> + data->cfg->type == sun50i_a100_phy ||
> data->cfg->type == sun50i_h6_phy) {
> void __iomem *phyctl = data->base +
> data->cfg->phyctl_offset;
> @@ -960,6 +968,16 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = {
> .phy0_dual_route = true,
> };
>
> +static const struct sun4i_usb_phy_cfg sun50i_a100_cfg = {
> + .num_phys = 2,
> + .type = sun50i_a100_phy,
So you could just use the sun50i_h6_phy type here.
Cheers,
Andre
> + .disc_thresh = 3,
> + .phyctl_offset = REG_PHYCTL_A33,
> + .dedicated_clocks = true,
> + .enable_pmu_unk1 = true,
> + .phy0_dual_route = true,
> +};
> +
> static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = {
> .num_phys = 4,
> .type = sun50i_h6_phy,
> @@ -983,6 +1001,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = {
> { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg },
> { .compatible = "allwinner,sun50i-a64-usb-phy",
> .data = &sun50i_a64_cfg},
> + { .compatible = "allwinner,sun50i-a100-usb-phy", .data = &sun50i_a100_cfg },
> { .compatible = "allwinner,sun50i-h6-usb-phy", .data = &sun50i_h6_cfg },
> { },
> };
>
On 10/11/2020 06:46, Frank Lee wrote:
Hi,
> From: Yangtao Li <[email protected]>
>
> This patch adds support for A100 MMC controller, which use word address
> for internal dma.
>
> Signed-off-by: Yangtao Li <[email protected]>
> ---
> drivers/mmc/host/sunxi-mmc.c | 28 +++++++++++++++++++++++++---
> 1 file changed, 25 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
> index fc62773602ec..1518b64112b7 100644
> --- a/drivers/mmc/host/sunxi-mmc.c
> +++ b/drivers/mmc/host/sunxi-mmc.c
> @@ -244,6 +244,7 @@ struct sunxi_idma_des {
>
> struct sunxi_mmc_cfg {
> u32 idma_des_size_bits;
> + u32 idma_des_shift;
> const struct sunxi_mmc_clk_delay *clk_delays;
>
> /* does the IP block support autocalibration? */
> @@ -343,7 +344,7 @@ static int sunxi_mmc_init_host(struct sunxi_mmc_host *host)
> /* Enable CEATA support */
> mmc_writel(host, REG_FUNS, SDXC_CEATA_ON);
> /* Set DMA descriptor list base address */
> - mmc_writel(host, REG_DLBA, host->sg_dma);
> + mmc_writel(host, REG_DLBA, host->sg_dma >> host->cfg->idma_des_shift);
>
> rval = mmc_readl(host, REG_GCTRL);
> rval |= SDXC_INTERRUPT_ENABLE_BIT;
> @@ -373,8 +374,10 @@ static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host,
>
> next_desc += sizeof(struct sunxi_idma_des);
> pdes[i].buf_addr_ptr1 =
> - cpu_to_le32(sg_dma_address(&data->sg[i]));
> - pdes[i].buf_addr_ptr2 = cpu_to_le32((u32)next_desc);
> + cpu_to_le32(sg_dma_address(&data->sg[i]) >>
> + host->cfg->idma_des_shift);
> + pdes[i].buf_addr_ptr2 = cpu_to_le32((u32)next_desc >>
> + host->cfg->idma_des_shift);
I think you should cast after the shift, otherwise you lose the ability
to run above 4 GB. This won't be a problem at the moment, since we still
use the default 32-bit DMA mask, but might bite us later.
Otherwise this patch looks fine, and works on the H616 as well.
Cheers,
Andre
> }
>
> pdes[0].config |= cpu_to_le32(SDXC_IDMAC_DES0_FD);
> @@ -1178,6 +1181,23 @@ static const struct sunxi_mmc_cfg sun50i_a64_emmc_cfg = {
> .needs_new_timings = true,
> };
>
> +static const struct sunxi_mmc_cfg sun50i_a100_cfg = {
> + .idma_des_size_bits = 16,
> + .idma_des_shift = 2,
> + .clk_delays = NULL,
> + .can_calibrate = true,
> + .mask_data0 = true,
> + .needs_new_timings = true,
> +};
> +
> +static const struct sunxi_mmc_cfg sun50i_a100_emmc_cfg = {
> + .idma_des_size_bits = 13,
> + .idma_des_shift = 2,
> + .clk_delays = NULL,
> + .can_calibrate = true,
> + .needs_new_timings = true,
> +};
> +
> static const struct of_device_id sunxi_mmc_of_match[] = {
> { .compatible = "allwinner,sun4i-a10-mmc", .data = &sun4i_a10_cfg },
> { .compatible = "allwinner,sun5i-a13-mmc", .data = &sun5i_a13_cfg },
> @@ -1186,6 +1206,8 @@ static const struct of_device_id sunxi_mmc_of_match[] = {
> { .compatible = "allwinner,sun9i-a80-mmc", .data = &sun9i_a80_cfg },
> { .compatible = "allwinner,sun50i-a64-mmc", .data = &sun50i_a64_cfg },
> { .compatible = "allwinner,sun50i-a64-emmc", .data = &sun50i_a64_emmc_cfg },
> + { .compatible = "allwinner,sun50i-a100-mmc", .data = &sun50i_a100_cfg },
> + { .compatible = "allwinner,sun50i-a100-emmc", .data = &sun50i_a100_emmc_cfg },
> { /* sentinel */ }
> };
> MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
>
On 10/11/2020 06:38, Frank Lee wrote:
> From: Yangtao Li <[email protected]>
>
> Declare A100's watchdog in the device-tree.
>
> Signed-off-by: Yangtao Li <[email protected]>
I don't have any manual nor hardware, but this node looks alright, when
compared to the H6 one.
Reviewed-by: Andre Przywara <[email protected]>
Cheers,
Andre
> ---
> arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
> index 01ff53b5a7a8..6aa3337ce0e9 100644
> --- a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
> +++ b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
> @@ -144,6 +144,14 @@ ths_calibration: calib@14 {
> };
> };
>
> + watchdog@30090a0 {
> + compatible = "allwinner,sun50i-a100-wdt",
> + "allwinner,sun6i-a31-wdt";
> + reg = <0x030090a0 0x20>;
> + interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&dcxo24M>;
> + };
> +
> pio: pinctrl@300b000 {
> compatible = "allwinner,sun50i-a100-pinctrl";
> reg = <0x0300b000 0x400>;
>
On 10/11/2020 06:28, Frank Lee wrote:
Hi,
> From: Yangtao Li <[email protected]>
>
> The dma of a100 is similar to h6, with some minor changes to
> support greater addressing capabilities.
So apparently those changes are backwards compatible, right?
Why do we need then a new struct now, when this is actually identical to
the existing H6 one?
So as this seems to work with the same settings as the H6, I think we
don't need any change in the driver at the moment, just using the H6
compatible as a fallback in the .dtsi.
Cheers,
Andre
P.S. I understand that Vinod already applied it, and it doesn't hurt to
have that in at the moment, if we fix the compatible usage.
>
> Add support for it.>
> Signed-off-by: Yangtao Li <[email protected]>
> ---
> drivers/dma/sun6i-dma.c | 25 +++++++++++++++++++++++++
> 1 file changed, 25 insertions(+)
>
> diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
> index f5f9c86c50bc..5cadd4d2b824 100644
> --- a/drivers/dma/sun6i-dma.c
> +++ b/drivers/dma/sun6i-dma.c
> @@ -1173,6 +1173,30 @@ static struct sun6i_dma_config sun50i_a64_dma_cfg = {
> BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
> };
>
> +/*
> + * TODO: Add support for more than 4g physical addressing.
> + *
> + * The A100 binding uses the number of dma channels from the
> + * device tree node.
> + */
> +static struct sun6i_dma_config sun50i_a100_dma_cfg = {
> + .clock_autogate_enable = sun6i_enable_clock_autogate_h3,
> + .set_burst_length = sun6i_set_burst_length_h3,
> + .set_drq = sun6i_set_drq_h6,
> + .set_mode = sun6i_set_mode_h6,
> + .src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
> + .dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
> + .src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
> + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
> + BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
> + .dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
> + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
> + BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
> + .has_mbus_clk = true,
> +};
> +
> /*
> * The H6 binding uses the number of dma channels from the
> * device tree node.
> @@ -1225,6 +1249,7 @@ static const struct of_device_id sun6i_dma_match[] = {
> { .compatible = "allwinner,sun8i-h3-dma", .data = &sun8i_h3_dma_cfg },
> { .compatible = "allwinner,sun8i-v3s-dma", .data = &sun8i_v3s_dma_cfg },
> { .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg },
> + { .compatible = "allwinner,sun50i-a100-dma", .data = &sun50i_a100_dma_cfg },
> { .compatible = "allwinner,sun50i-h6-dma", .data = &sun50i_h6_dma_cfg },
> { /* sentinel */ }
> };
>
On 10/11/2020 06:48, Frank Lee wrote:
Hi,
> From: Yangtao Li <[email protected]>
>
> The A100 has 3 MMC controllers, one of them being especially targeted to
> eMMC. Let's add nodes on dts.
>
> Signed-off-by: Yangtao Li <[email protected]>
I don't have a datasheet nor a device for testing, but at least I could
check the pins against the pinctrl driver, and compare the MMC nodes
against the H6. Apart from the interrupts they are the same, so:
Reviewed-by: Andre Przywara <[email protected]>
Cheers,
Andre
> ---
> .../arm64/boot/dts/allwinner/sun50i-a100.dtsi | 71 +++++++++++++++++++
> 1 file changed, 71 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
> index c731bb9727c2..4adfc7d4854a 100644
> --- a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
> +++ b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
> @@ -169,12 +169,83 @@ pio: pinctrl@300b000 {
> interrupt-controller;
> #interrupt-cells = <3>;
>
> + mmc0_pins: mmc0-pins {
> + pins = "PF0", "PF1", "PF2", "PF3",
> + "PF4", "PF5";
> + function = "mmc0";
> + drive-strength = <30>;
> + bias-pull-up;
> + };
> +
> + /omit-if-no-ref/
> + mmc1_pins: mmc1-pins {
> + pins = "PG0", "PG1", "PG2", "PG3",
> + "PG4", "PG5";
> + function = "mmc1";
> + drive-strength = <30>;
> + bias-pull-up;
> + };
> +
> + mmc2_pins: mmc2-pins {
> + pins = "PC0", "PC1", "PC5", "PC6",
> + "PC8", "PC9", "PC10", "PC11",
> + "PC13", "PC14", "PC15", "PC16";
> + function = "mmc2";
> + drive-strength = <30>;
> + bias-pull-up;
> + };
> +
> uart0_pb_pins: uart0-pb-pins {
> pins = "PB9", "PB10";
> function = "uart0";
> };
> };
>
> + mmc0: mmc@4020000 {
> + compatible = "allwinner,sun50i-a100-mmc";
> + reg = <0x04020000 0x1000>;
> + clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
> + clock-names = "ahb", "mmc";
> + resets = <&ccu RST_BUS_MMC0>;
> + reset-names = "ahb";
> + interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
> + pinctrl-names = "default";
> + pinctrl-0 = <&mmc0_pins>;
> + status = "disabled";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + };
> +
> + mmc1: mmc@4021000 {
> + compatible = "allwinner,sun50i-a100-mmc";
> + reg = <0x04021000 0x1000>;
> + clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
> + clock-names = "ahb", "mmc";
> + resets = <&ccu RST_BUS_MMC1>;
> + reset-names = "ahb";
> + interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
> + pinctrl-names = "default";
> + pinctrl-0 = <&mmc1_pins>;
> + status = "disabled";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + };
> +
> + mmc2: mmc@4022000 {
> + compatible = "allwinner,sun50i-a100-emmc";
> + reg = <0x04022000 0x1000>;
> + clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
> + clock-names = "ahb", "mmc";
> + resets = <&ccu RST_BUS_MMC2>;
> + reset-names = "ahb";
> + interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
> + pinctrl-names = "default";
> + pinctrl-0 = <&mmc2_pins>;
> + status = "disabled";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + };
> +
> uart0: serial@5000000 {
> compatible = "snps,dw-apb-uart";
> reg = <0x05000000 0x400>;
>
On 10/11/2020 06:31, Frank Lee wrote:
Hi,
> From: Yangtao Li <[email protected]>
>
> Add the Performance Monitoring Unit (PMU) device tree node to the A100
> .dtsi, which tells DT users which interrupts are triggered by PMU overflow
> events on each core.
Have you tested that the interrupts actually work? For the A64 there
were wrong in the manual, and we realised only later.
"perf stat" works even without interrupts, but "perf record" requires
interrupts, and will return empty-handed if they don't work.
Can you confirm this?
>
> Signed-off-by: Yangtao Li <[email protected]>
Without being able to test or verify this, the nodes looks correct, so:
Reviewed-by: Andre Przywara <[email protected]>
Cheers,
Andre
> ---
> arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi | 15 ++++++++++++---
> 1 file changed, 12 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
> index c34ed8045363..01ff53b5a7a8 100644
> --- a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
> +++ b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
> @@ -25,21 +25,21 @@ cpu0: cpu@0 {
> enable-method = "psci";
> };
>
> - cpu@1 {
> + cpu1: cpu@1 {
> compatible = "arm,cortex-a53";
> device_type = "cpu";
> reg = <0x1>;
> enable-method = "psci";
> };
>
> - cpu@2 {
> + cpu2: cpu@2 {
> compatible = "arm,cortex-a53";
> device_type = "cpu";
> reg = <0x2>;
> enable-method = "psci";
> };
>
> - cpu@3 {
> + cpu3: cpu@3 {
> compatible = "arm,cortex-a53";
> device_type = "cpu";
> reg = <0x3>;
> @@ -47,6 +47,15 @@ cpu@3 {
> };
> };
>
> + pmu {
> + compatible = "arm,cortex-a53-pmu";
> + interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
> + <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
> + interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
> + };
> +
> psci {
> compatible = "arm,psci-1.0";
> method = "smc";
>
On 11/11/2020 22:50, Rob Herring wrote:
Hi,
> On Tue, Nov 10, 2020 at 02:39:42PM +0800, Frank Lee wrote:
>> From: Yangtao Li <[email protected]>
>>
>> Add a device tree binding for the A100's USB PHY.
Not your fault, Yangto, but why do we actually have a separate binding
document per SoC, when the differences between the PHYs are so minimal
that we get away with some flags in the compatible match, in one driver
file?
For a start this file is basically identical to the A64 one (apart from
the example), so can you just add the A100 compatible string to that
one, instead?
Cheers,
Andre
>>
>> Signed-off-by: Yangtao Li <[email protected]>
>> ---
>> .../phy/allwinner,sun50i-a100-usb-phy.yaml | 105 ++++++++++++++++++
>> 1 file changed, 105 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/phy/allwinner,sun50i-a100-usb-phy.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/phy/allwinner,sun50i-a100-usb-phy.yaml b/Documentation/devicetree/bindings/phy/allwinner,sun50i-a100-usb-phy.yaml
>> new file mode 100644
>> index 000000000000..cc9bbebe2bd7
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/phy/allwinner,sun50i-a100-usb-phy.yaml
>> @@ -0,0 +1,105 @@
>> +# SPDX-License-Identifier: GPL-2.0
>
> Dual license new bindings. checkpatch.pl will tell you which ones.
>
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/phy/allwinner,sun50i-a100-usb-phy.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Allwinner A100 USB PHY Device Tree Bindings
>> +
>> +maintainers:
>> + - Yangtao Li <[email protected]>
>> +
>> +properties:
>> + "#phy-cells":
>> + const: 1
>> +
>> + compatible:
>> + const: allwinner,sun50i-a100-usb-phy
>> +
>> + reg:
>> + items:
>> + - description: PHY Control registers
>> + - description: PHY PMU0 registers
>> + - description: PHY PMU1 registers
>> +
>> + reg-names:
>> + items:
>> + - const: phy_ctrl
>> + - const: pmu0
>> + - const: pmu1
>> +
>> + clocks:
>> + items:
>> + - description: USB OTG PHY bus clock
>> + - description: USB Host 0 PHY bus clock
>> +
>> + clock-names:
>> + items:
>> + - const: usb0_phy
>> + - const: usb1_phy
>> +
>> + resets:
>> + items:
>> + - description: USB OTG reset
>> + - description: USB Host 1 Controller reset
>> +
>> + reset-names:
>> + items:
>> + - const: usb0_reset
>> + - const: usb1_reset
>> +
>> + usb0_id_det-gpios:
>> + description: GPIO to the USB OTG ID pin
>
> Needs 'maxItems: 1'
>
>> +
>> + usb0_vbus_det-gpios:
>> + description: GPIO to the USB OTG VBUS detect pin
>> +
>> + usb0_vbus_power-supply:
>> + description: Power supply to detect the USB OTG VBUS
>> +
>> + usb0_vbus-supply:
>> + description: Regulator controlling USB OTG VBUS
>> +
>> + usb1_vbus-supply:
>> + description: Regulator controlling USB1 Host controller
>
> Are ID and VBus actually connected to the phy h/w? Really, all this
> should be in a USB connector node for which we have bindings.
>
>> +
>> +required:
>> + - "#phy-cells"
>> + - compatible
>> + - clocks
>> + - clock-names
>> + - reg
>> + - reg-names
>> + - resets
>> + - reset-names
>> +
>> +additionalProperties: false
>> +
>> +examples:
>> + - |
>> + #include <dt-bindings/gpio/gpio.h>
>> + #include <dt-bindings/clock/sun50i-a100-ccu.h>
>> + #include <dt-bindings/reset/sun50i-a100-ccu.h>
>> +
>> + phy@5100400 {
>> + #phy-cells = <1>;
>> + compatible = "allwinner,sun50i-a100-usb-phy";
>> + reg = <0x05100400 0x14>,
>> + <0x05101800 0x4>,
>> + <0x05200800 0x4>;
>> + reg-names = "phy_ctrl",
>> + "pmu0",
>> + "pmu1";
>> + clocks = <&ccu CLK_USB_PHY0>,
>> + <&ccu CLK_USB_PHY1>;
>> + clock-names = "usb0_phy",
>> + "usb1_phy";
>> + resets = <&ccu RST_USB_PHY0>,
>> + <&ccu RST_USB_PHY1>;
>> + reset-names = "usb0_reset",
>> + "usb1_reset";
>> + usb0_id_det-gpios = <&pio 7 10 GPIO_ACTIVE_HIGH>; /* PH10 */
>> + usb0_vbus_power-supply = <&usb_power_supply>;
>> + usb0_vbus-supply = <®_drivevbus>;
>> + usb1_vbus-supply = <®_usb1_vbus>;
>> + };
>> --
>> 2.28.0
>>
>
> _______________________________________________
> linux-arm-kernel mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
On 10/11/2020 06:29, Frank Lee wrote:
> From: Yangtao Li <[email protected]>
>
> The A100 SoC has a DMA controller that supports 8 DMA channels
> to and from various peripherals.
>
> Add a device node for it.
>
> Signed-off-by: Yangtao Li <[email protected]>
> ---
> arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
> index cc321c04f121..c34ed8045363 100644
> --- a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
> +++ b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
> @@ -101,6 +101,18 @@ ccu: clock@3001000 {
> #reset-cells = <1>;
> };
>
> + dma: dma-controller@3002000 {
> + compatible = "allwinner,sun50i-a100-dma";
So at it appears to work with the exact same settings in the driver as
the H6, we should have that as a compatible fallback:
compatible = "allwinner,sun50i-a100-dma", "allwinner,sun50i-h6-dma";
Cheers,
Andre
> + reg = <0x03002000 0x1000>;
> + interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&ccu CLK_BUS_DMA>, <&ccu CLK_MBUS_DMA>;
> + clock-names = "bus", "mbus";
> + dma-channels = <8>;
> + dma-requests = <51>;
> + resets = <&ccu RST_BUS_DMA>;
> + #dma-cells = <1>;
> + };
> +
> gic: interrupt-controller@3021000 {
> compatible = "arm,gic-400";
> reg = <0x03021000 0x1000>, <0x03022000 0x2000>,
>
On 28/11/2020 19:56, André Przywara wrote:
> On 10/11/2020 06:46, Frank Lee wrote:
Hi,
one more thing below ...
>> From: Yangtao Li <[email protected]>
>>
>> This patch adds support for A100 MMC controller, which use word address
>> for internal dma.
>>
>> Signed-off-by: Yangtao Li <[email protected]>
>> ---
>> drivers/mmc/host/sunxi-mmc.c | 28 +++++++++++++++++++++++++---
>> 1 file changed, 25 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
>> index fc62773602ec..1518b64112b7 100644
>> --- a/drivers/mmc/host/sunxi-mmc.c
>> +++ b/drivers/mmc/host/sunxi-mmc.c
>> @@ -244,6 +244,7 @@ struct sunxi_idma_des {
>>
>> struct sunxi_mmc_cfg {
>> u32 idma_des_size_bits;
>> + u32 idma_des_shift;
>> const struct sunxi_mmc_clk_delay *clk_delays;
>>
>> /* does the IP block support autocalibration? */
>> @@ -343,7 +344,7 @@ static int sunxi_mmc_init_host(struct sunxi_mmc_host *host)
>> /* Enable CEATA support */
>> mmc_writel(host, REG_FUNS, SDXC_CEATA_ON);
>> /* Set DMA descriptor list base address */
>> - mmc_writel(host, REG_DLBA, host->sg_dma);
>> + mmc_writel(host, REG_DLBA, host->sg_dma >> host->cfg->idma_des_shift);
>>
>> rval = mmc_readl(host, REG_GCTRL);
>> rval |= SDXC_INTERRUPT_ENABLE_BIT;
>> @@ -373,8 +374,10 @@ static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host,
>>
>> next_desc += sizeof(struct sunxi_idma_des);
>> pdes[i].buf_addr_ptr1 =
>> - cpu_to_le32(sg_dma_address(&data->sg[i]));
>> - pdes[i].buf_addr_ptr2 = cpu_to_le32((u32)next_desc);
>> + cpu_to_le32(sg_dma_address(&data->sg[i]) >>
>> + host->cfg->idma_des_shift);
>> + pdes[i].buf_addr_ptr2 = cpu_to_le32((u32)next_desc >>
>> + host->cfg->idma_des_shift);
>
> I think you should cast after the shift, otherwise you lose the ability
> to run above 4 GB. This won't be a problem at the moment, since we still
> use the default 32-bit DMA mask, but might bite us later.
>
> Otherwise this patch looks fine, and works on the H616 as well.
>
> Cheers,
> Andre
>
>> }
>>
>> pdes[0].config |= cpu_to_le32(SDXC_IDMAC_DES0_FD);
>> @@ -1178,6 +1181,23 @@ static const struct sunxi_mmc_cfg sun50i_a64_emmc_cfg = {
>> .needs_new_timings = true,
>> };
>>
>> +static const struct sunxi_mmc_cfg sun50i_a100_cfg = {
>> + .idma_des_size_bits = 16,
>> + .idma_des_shift = 2,
>> + .clk_delays = NULL,
>> + .can_calibrate = true,
>> + .mask_data0 = true,
>> + .needs_new_timings = true,
>> +};
>> +
>> +static const struct sunxi_mmc_cfg sun50i_a100_emmc_cfg = {
>> + .idma_des_size_bits = 13,
>> + .idma_des_shift = 2,
Is that actually true? Don't know about the A100, but the H616 manual
mentions that "SMHC2" deals with byte addresses, in contrast to the
other two ones. So MMC2 would be compatible with the a64_emmc_cfg?
Cheers,
Andre
>> + .clk_delays = NULL,
>> + .can_calibrate = true,
>> + .needs_new_timings = true,
>> +};
>> +
>> static const struct of_device_id sunxi_mmc_of_match[] = {
>> { .compatible = "allwinner,sun4i-a10-mmc", .data = &sun4i_a10_cfg },
>> { .compatible = "allwinner,sun5i-a13-mmc", .data = &sun5i_a13_cfg },
>> @@ -1186,6 +1206,8 @@ static const struct of_device_id sunxi_mmc_of_match[] = {
>> { .compatible = "allwinner,sun9i-a80-mmc", .data = &sun9i_a80_cfg },
>> { .compatible = "allwinner,sun50i-a64-mmc", .data = &sun50i_a64_cfg },
>> { .compatible = "allwinner,sun50i-a64-emmc", .data = &sun50i_a64_emmc_cfg },
>> + { .compatible = "allwinner,sun50i-a100-mmc", .data = &sun50i_a100_cfg },
>> + { .compatible = "allwinner,sun50i-a100-emmc", .data = &sun50i_a100_emmc_cfg },
>> { /* sentinel */ }
>> };
>> MODULE_DEVICE_TABLE(of, sunxi_mmc_of_match);
>>
>
On Sat, Nov 28, 2020 at 08:18:16PM +0000, Andr? Przywara wrote:
> On 11/11/2020 22:50, Rob Herring wrote:
>
> Hi,
>
> > On Tue, Nov 10, 2020 at 02:39:42PM +0800, Frank Lee wrote:
> >> From: Yangtao Li <[email protected]>
> >>
> >> Add a device tree binding for the A100's USB PHY.
>
> Not your fault, Yangto, but why do we actually have a separate binding
> document per SoC, when the differences between the PHYs are so minimal
> that we get away with some flags in the compatible match, in one driver
> file?
They are similar, but there's massive differences between them still
(like which regulators are supposed to be there, or the register names).
So putting them all in the same file just ended up in an unmaintainable
mess.
> For a start this file is basically identical to the A64 one (apart from
> the example), so can you just add the A100 compatible string to that
> one, instead?
But yeah, if two are identical they should be merged
Maxime
On 10/11/2020 06:40, Frank Lee wrote:
Hi,
> From: Yangtao Li <[email protected]>
>
> Add support for a100's usb phy, which with 2 PHYs.
>
> Signed-off-by: Yangtao Li <[email protected]>
> ---
> drivers/phy/allwinner/phy-sun4i-usb.c | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
>
> diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
> index a6900495baa5..1a0e403131e7 100644
> --- a/drivers/phy/allwinner/phy-sun4i-usb.c
> +++ b/drivers/phy/allwinner/phy-sun4i-usb.c
> @@ -107,6 +107,7 @@ enum sun4i_usb_phy_type {
> sun8i_r40_phy,
> sun8i_v3s_phy,
> sun50i_a64_phy,
> + sun50i_a100_phy,
> sun50i_h6_phy,
> };
>
> @@ -289,7 +290,13 @@ static int sun4i_usb_phy_init(struct phy *_phy)
> }
>
> if (data->cfg->type == sun8i_a83t_phy ||
> + data->cfg->type == sun50i_a100_phy ||
> data->cfg->type == sun50i_h6_phy) {
> + if (phy->pmu && data->cfg->enable_pmu_unk1) {
> + val = readl(phy->pmu + REG_PMU_UNK1);
> + writel(val & ~BIT(3), phy->pmu + REG_PMU_UNK1);
> + }
> +
So having a closer look, this does not look right. We should not use
this very same variable (enable_pmu_unk1) for a different bit.
So what about changing "bool enable_pmu_unk1;" into "u32
pmu_phy_tune_mask;", and using this to mask bits in this PMU register,
regardless of the PHY type (above this "if" statement)? We just check it
for being 0 and possibly skip the R/M/W sequence.
Then the newer SoCs get .pmu_phy_tune_mask = BIT(1), in their config
below, and the A100 gets BIT(3). Older PHYs just omit this line at all,
are initialised to 0, and are skipped.
That would look more cleaner and might even be a bit future proof.
Cheers,
Andre
> if (phy->index == 0) {
> val = readl(data->base + data->cfg->phyctl_offset);
> val |= PHY_CTL_VBUSVLDEXT;
> @@ -339,6 +346,7 @@ static int sun4i_usb_phy_exit(struct phy *_phy)
>
> if (phy->index == 0) {
> if (data->cfg->type == sun8i_a83t_phy ||
> + data->cfg->type == sun50i_a100_phy ||
> data->cfg->type == sun50i_h6_phy) {
> void __iomem *phyctl = data->base +
> data->cfg->phyctl_offset;
> @@ -960,6 +968,16 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = {
> .phy0_dual_route = true,
> };
>
> +static const struct sun4i_usb_phy_cfg sun50i_a100_cfg = {
> + .num_phys = 2,
> + .type = sun50i_a100_phy,
> + .disc_thresh = 3,
> + .phyctl_offset = REG_PHYCTL_A33,
> + .dedicated_clocks = true,
> + .enable_pmu_unk1 = true,
> + .phy0_dual_route = true,
> +};
> +
> static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = {
> .num_phys = 4,
> .type = sun50i_h6_phy,
> @@ -983,6 +1001,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = {
> { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg },
> { .compatible = "allwinner,sun50i-a64-usb-phy",
> .data = &sun50i_a64_cfg},
> + { .compatible = "allwinner,sun50i-a100-usb-phy", .data = &sun50i_a100_cfg },
> { .compatible = "allwinner,sun50i-h6-usb-phy", .data = &sun50i_h6_cfg },
> { },
> };
>