Hi everyone,
This is v2 of my patch series introducing basic kernel support for Allwinner's
H3 SoC. It mainly adds basic clocks and pinctrl. It also adds interrupts,
timers, watchdog, RTC, dmaengine, MMC and UARTs, which are mostly compatible
to those in earlier SoCs like A23 and A31, and can simply be reused.
These patches are based on Maxime's sunxi/for-next branch from
git://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux.git
The first four patches are documentation updates and generic changes to the
sunxi clock and pinctrl drivers, preparing them for the H3 addition.
Patch 1 updates the sunxi README with new SoCs, including the H3
Patch 2 adds support for multiple parents to the sunxi gates clock, needed
for the new bus gates in H3
Patch 3 improves the sunxi divs clock to read the name of the base factor clock
from devicetree instead of hardcoding it, which allows us to reuse sun6i-pll6
for our pll8.
Patch 4 prepares the sunxi pinctrl driver for building the SoC specific parts
as modules. This is later used for the H3 pinctrl driver. I believe the other
sunxi SoCs could or should be changed to tristate too, but that's independend
from this series and I wouldn't be able to test them anyway.
The remaining patches add H3 support.
Patch 5 adds machine support for the H3.
Patch 6 adds support for the basic clocks.
Patch 7 adds the pin sets for the H3 main PIO.
Patch 8 adds a new compatible for the H3 reset controller
Patch 9 adds the DTSI for the H3.
Patch 10 adds a DTS for the Orange Pi Plus SBC, which these patches
were developed and tested with.
Changes since v1:
- Update sunxi README in Documentation
- Add the multiple parents gates and use them for bus-gates instead of
ahb1, ahb2, apb1 and apb2 gates
- Merge the pll8 clock with sun6i pll6
- Merge the ahb12, apb1 and apb2 resets to bus-resets with own compatible
- Add sun6i_timer_init to sun8i machine
- Remove the single SoC names from machine definition, its sun8i family
- Make the pinctrl driver tristate and put its Kconfig entry in the right order
- Rename pinctrl "scr" to "sim" and clock "sim" to "scr" to match user manual
- Remove the address paragraph from GPL in dts and dtsi
- Some style cleanup and line wrapping in dtsi
- Add ARM architected timers
- dmaengine isn't included anymore, it is merged already
Best Regards,
Jens
Jens Kuske (10):
Documentation: sunxi: Update Allwinner SoC documentation
clk: sunxi: Add support for multiple parents to gates
clk: sunxi: Let divs clocks read the base factor clock name from
devicetree
pinctrl: sunxi: Prepare for building SoC specific drivers as modules
ARM: sunxi: Introduce Allwinner H3 support
clk: sunxi: Add H3 clocks support
pinctrl: sunxi: Add H3 PIO controller support
reset: sunxi: Add compatible for Allwinner H3 bus resets
ARM: dts: sunxi: Add Allwinner H3 DTSI
ARM: dts: sun8i: Add Orange Pi Plus support
Documentation/arm/sunxi/README | 18 +-
Documentation/devicetree/bindings/arm/sunxi.txt | 1 +
Documentation/devicetree/bindings/clock/sunxi.txt | 6 +
.../bindings/pinctrl/allwinner,sunxi-pinctrl.txt | 1 +
.../bindings/reset/allwinner,sunxi-clock-reset.txt | 1 +
arch/arm/boot/dts/Makefile | 3 +-
arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts | 77 +++
arch/arm/boot/dts/sun8i-h3.dtsi | 446 ++++++++++++++++++
arch/arm/mach-sunxi/Kconfig | 2 +-
arch/arm/mach-sunxi/sunxi.c | 4 +-
drivers/clk/sunxi/clk-sunxi.c | 84 +++-
drivers/pinctrl/sunxi/Kconfig | 8 +
drivers/pinctrl/sunxi/Makefile | 1 +
drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c | 522 +++++++++++++++++++++
drivers/pinctrl/sunxi/pinctrl-sunxi.c | 25 +-
drivers/pinctrl/sunxi/pinctrl-sunxi.h | 2 +
drivers/reset/reset-sunxi.c | 1 +
17 files changed, 1180 insertions(+), 22 deletions(-)
create mode 100644 arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts
create mode 100644 arch/arm/boot/dts/sun8i-h3.dtsi
create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c
--
2.4.0
There are some new Allwinner SoCs available, namely A33, A83T and H3.
Update the documentation to mention those and the related documents.
Signed-off-by: Jens Kuske <[email protected]>
---
Documentation/arm/sunxi/README | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/Documentation/arm/sunxi/README b/Documentation/arm/sunxi/README
index 1fe2d7f..5e38e15 100644
--- a/Documentation/arm/sunxi/README
+++ b/Documentation/arm/sunxi/README
@@ -36,7 +36,7 @@ SunXi family
+ User Manual
http://dl.linux-sunxi.org/A20/A20%20User%20Manual%202013-03-22.pdf
- - Allwinner A23
+ - Allwinner A23 (sun8i)
+ Datasheet
http://dl.linux-sunxi.org/A23/A23%20Datasheet%20V1.0%2020130830.pdf
+ User Manual
@@ -55,7 +55,23 @@ SunXi family
+ User Manual
http://dl.linux-sunxi.org/A31/A3x_release_document/A31s/IC/A31s%20User%20Manual%20%20V1.0%2020130322.pdf
+ - Allwinner A33 (sun8i)
+ + Datasheet
+ http://dl.linux-sunxi.org/A33/A33%20Datasheet%20release%201.1.pdf
+ + User Manual
+ http://dl.linux-sunxi.org/A33/A33%20user%20manual%20release%201.1.pdf
+
+ - Allwinner H3 (sun8i)
+ + Datasheet
+ http://dl.linux-sunxi.org/H3/Allwinner_H3_Datasheet_V1.0.pdf
+
* Quad ARM Cortex-A15, Quad ARM Cortex-A7 based SoCs
- Allwinner A80
+ Datasheet
http://dl.linux-sunxi.org/A80/A80_Datasheet_Revision_1.0_0404.pdf
+
+ * Octa ARM Cortex-A7 based SoCs
+ - Allwinner A83T
+ + Not Supported
+ + Datasheet
+ http://dl.linux-sunxi.org/A83T/A83T_datasheet_Revision_1.1.pdf
--
2.4.0
Some newer sunxi SoCs (A83T, H3) don't have individual registers for
AHB1, APB1 and APB2 gates anymore, but one big bus gates area where each
gate can have a different parent.
The current clock driver sets the same parent for all gates in a group.
This commit adds a new parents field to the gates_data structure, which
allows us to specify an array of parent indices for every single gate.
Signed-off-by: Jens Kuske <[email protected]>
---
drivers/clk/sunxi/clk-sunxi.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 9a82f17..17cba4d 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -898,6 +898,8 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
struct gates_data {
DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
+ /* If used, ARRAY_SIZE(parents) has to be >= bitmap_weight(mask) */
+ const u8 *parents;
};
static const struct gates_data sun4i_axi_gates_data __initconst = {
@@ -1000,16 +1002,21 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
struct gates_data *data)
{
struct clk_onecell_data *clk_data;
+ const char *parents[SUNXI_MAX_PARENTS];
const char *clk_parent;
const char *clk_name;
void __iomem *reg;
+ int npar = 0;
int qty;
int i = 0;
int j = 0;
reg = of_iomap(node, 0);
- clk_parent = of_clk_get_parent_name(node, 0);
+ while (npar < SUNXI_MAX_PARENTS &&
+ (parents[npar] = of_clk_get_parent_name(node, npar)) != NULL)
+ npar++;
+ clk_parent = parents[0];
/* Worst-case size approximation and memory allocation */
qty = find_last_bit(data->mask, SUNXI_GATES_MAX_SIZE);
@@ -1026,6 +1033,9 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
of_property_read_string_index(node, "clock-output-names",
j, &clk_name);
+ if (data->parents && !WARN_ON(data->parents[j] >= npar))
+ clk_parent = parents[data->parents[j]];
+
clk_data->clks[i] = clk_register_gate(NULL, clk_name,
clk_parent, 0,
reg + 4 * (i/32), i % 32,
--
2.4.0
Currently, the sunxi clock driver gets the name for the base factor clock
of divs clocks from the name field in factors_data. This prevents reusing
of the factor clock for clocks with same properties, but different name.
This commit makes the divs setup function try to get a name from
clock-output-names in the devicetree. It also removes the name field where
possible and merges the sun4i PLL5 and PLL6 clocks.
The sun4i PLL5 clock doesn't have a output for the base factor clock,
so we still have to use the name field there.
Signed-off-by: Jens Kuske <[email protected]>
---
drivers/clk/sunxi/clk-sunxi.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 17cba4d..afe560c 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -708,18 +708,10 @@ static const struct factors_data sun4i_pll5_data __initconst = {
.name = "pll5",
};
-static const struct factors_data sun4i_pll6_data __initconst = {
- .enable = 31,
- .table = &sun4i_pll5_config,
- .getter = sun4i_get_pll5_factors,
- .name = "pll6",
-};
-
static const struct factors_data sun6i_a31_pll6_data __initconst = {
.enable = 31,
.table = &sun6i_a31_pll6_config,
.getter = sun6i_a31_get_pll6_factors,
- .name = "pll6x2",
};
static const struct factors_data sun5i_a13_ahb_data __initconst = {
@@ -1099,7 +1091,7 @@ static const struct divs_data pll5_divs_data __initconst = {
};
static const struct divs_data pll6_divs_data __initconst = {
- .factors = &sun4i_pll6_data,
+ .factors = &sun4i_pll5_data,
.ndivs = 4,
.div = {
{ .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */
@@ -1141,6 +1133,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
struct clk_gate *gate = NULL;
struct clk_fixed_factor *fix_factor;
struct clk_divider *divider;
+ struct factors_data factors = *data->factors;
void __iomem *reg;
int ndivs = SUNXI_DIVS_MAX_QTY, i = 0;
int flags, clkflags;
@@ -1149,8 +1142,17 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
if (data->ndivs)
ndivs = data->ndivs;
+ /* Try to find a name for base factor clock */
+ for (i = 0; i < ndivs; i++) {
+ if (data->div[i].self) {
+ of_property_read_string_index(node, "clock-output-names",
+ i, &factors.name);
+ break;
+ }
+ }
+
/* Set up factor clock that we will be dividing */
- pclk = sunxi_factors_clk_setup(node, data->factors);
+ pclk = sunxi_factors_clk_setup(node, &factors);
parent = __clk_get_name(pclk);
reg = of_iomap(node, 0);
--
2.4.0
Add a remove function and export the init and remove function
to allow us to build the SoC specific drivers as modules.
Signed-off-by: Jens Kuske <[email protected]>
---
drivers/pinctrl/sunxi/pinctrl-sunxi.c | 25 +++++++++++++++++++------
drivers/pinctrl/sunxi/pinctrl-sunxi.h | 2 ++
2 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index f8e171b..4ef6b3d 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -856,7 +856,6 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
struct sunxi_pinctrl *pctl;
struct resource *res;
int i, ret, last_pin;
- struct clk *clk;
pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
if (!pctl)
@@ -954,13 +953,13 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
goto gpiochip_error;
}
- clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
+ pctl->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(pctl->clk)) {
+ ret = PTR_ERR(pctl->clk);
goto gpiochip_error;
}
- ret = clk_prepare_enable(clk);
+ ret = clk_prepare_enable(pctl->clk);
if (ret)
goto gpiochip_error;
@@ -1015,10 +1014,24 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
return 0;
clk_error:
- clk_disable_unprepare(clk);
+ clk_disable_unprepare(pctl->clk);
gpiochip_error:
gpiochip_remove(pctl->chip);
pinctrl_error:
pinctrl_unregister(pctl->pctl_dev);
return ret;
}
+EXPORT_SYMBOL(sunxi_pinctrl_init);
+
+int sunxi_pinctrl_remove(struct platform_device *pdev)
+{
+ struct sunxi_pinctrl *pctl = platform_get_drvdata(pdev);
+
+ gpiochip_remove(pctl->chip);
+ pinctrl_unregister(pctl->pctl_dev);
+
+ clk_disable_unprepare(pctl->clk);
+
+ return 0;
+}
+EXPORT_SYMBOL(sunxi_pinctrl_remove);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index e248e81..4442676 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -126,6 +126,7 @@ struct sunxi_pinctrl {
unsigned *irq_array;
spinlock_t lock;
struct pinctrl_dev *pctl_dev;
+ struct clk *clk;
};
#define SUNXI_PIN(_pin, ...) \
@@ -285,5 +286,6 @@ static inline u32 sunxi_irq_status_offset(u16 irq)
int sunxi_pinctrl_init(struct platform_device *pdev,
const struct sunxi_pinctrl_desc *desc);
+int sunxi_pinctrl_remove(struct platform_device *pdev);
#endif /* __PINCTRL_SUNXI_H */
--
2.4.0
The Allwinner H3 is a quad-core Cortex-A7-based SoC. It is very similar
to other sun8i family SoCs like the A23.
Signed-off-by: Jens Kuske <[email protected]>
---
Documentation/devicetree/bindings/arm/sunxi.txt | 1 +
arch/arm/mach-sunxi/Kconfig | 2 +-
arch/arm/mach-sunxi/sunxi.c | 4 +++-
3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/sunxi.txt b/Documentation/devicetree/bindings/arm/sunxi.txt
index 42941fd..3cb4b94 100644
--- a/Documentation/devicetree/bindings/arm/sunxi.txt
+++ b/Documentation/devicetree/bindings/arm/sunxi.txt
@@ -9,4 +9,5 @@ using one of the following compatible strings:
allwinner,sun6i-a31
allwinner,sun7i-a20
allwinner,sun8i-a23
+ allwinner,sun8i-h3
allwinner,sun9i-a80
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 81502b9..4efe2d4 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -35,7 +35,7 @@ config MACH_SUN7I
select SUN5I_HSTIMER
config MACH_SUN8I
- bool "Allwinner A23 (sun8i) SoCs support"
+ bool "Allwinner sun8i Family SoCs support"
default ARCH_SUNXI
select ARM_GIC
select MFD_SUN6I_PRCM
diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c
index 1bc811a..8270902 100644
--- a/arch/arm/mach-sunxi/sunxi.c
+++ b/arch/arm/mach-sunxi/sunxi.c
@@ -67,10 +67,12 @@ MACHINE_END
static const char * const sun8i_board_dt_compat[] = {
"allwinner,sun8i-a23",
+ "allwinner,sun8i-h3",
NULL,
};
-DT_MACHINE_START(SUN8I_DT, "Allwinner sun8i (A23) Family")
+DT_MACHINE_START(SUN8I_DT, "Allwinner sun8i Family")
+ .init_time = sun6i_timer_init,
.dt_compat = sun8i_board_dt_compat,
.init_late = sunxi_dt_cpufreq_init,
MACHINE_END
--
2.4.0
The H3 clock control unit is similar to the those of other sun8i family
members like the A23.
It makes use of the new multiple parents option for the bus gates.
Some of the gates use the new AHB2 clock as parent, whose clock source
is muxable between AHB1 and PLL6/2. The documentation isn't totally clear
about which devices belong to AHB2 now, especially USB EHIC/OHIC, so it
is mostly based on Allwinner kernel source code.
Signed-off-by: Jens Kuske <[email protected]>
---
Documentation/devicetree/bindings/clock/sunxi.txt | 6 +++
drivers/clk/sunxi/clk-sunxi.c | 50 ++++++++++++++++++++++-
2 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index 4fa11af..e367963 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -14,6 +14,7 @@ Required properties:
"allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock
"allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock
"allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
+ "allwinner,sun8i-h3-pll6-clk" - for the PLL6 clock on H3
"allwinner,sun9i-a80-gt-clk" - for the GT bus clock on A80
"allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock
"allwinner,sun4i-a10-axi-clk" - for the AXI clock
@@ -28,6 +29,7 @@ Required properties:
"allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20
"allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31
"allwinner,sun6i-a31-ahb1-clk" - for the AHB1 clock on A31
+ "allwinner,sun8i-h3-ahb2-clk" - for the AHB2 clock on H3
"allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31
"allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23
"allwinner,sun9i-a80-ahb0-gates-clk" - for the AHB0 gates on A80
@@ -55,6 +57,7 @@ Required properties:
"allwinner,sun9i-a80-apb1-gates-clk" - for the APB1 gates on A80
"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
"allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
+ "allwinner,sun8i-h3-bus-gates-clk" - for the bus gates on H3
"allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13
"allwinner,sun4i-a10-mmc-clk" - for the MMC clock
"allwinner,sun9i-a80-mmc-clk" - for mmc module clocks on A80
@@ -95,6 +98,9 @@ The "allwinner,sun9i-a80-mmc-config-clk" clock also requires:
For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate
dummy clocks at 25 MHz and 125 MHz, respectively. See example.
+For "allwinner,sun8i-h3-bus-gates-clk", the parent clocks shall be
+AHB1, AHB2, APB1 and APB2, in that order.
+
Clock consumers should specify the desired clocks they use with a
"clocks" phandle cell. Consumers that are using a gated clock should
provide an additional ID in their clock property. This ID is the
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index afe560c..79364be 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -771,6 +771,10 @@ static const struct mux_data sun6i_a31_ahb1_mux_data __initconst = {
.shift = 12,
};
+static const struct mux_data sun8i_h3_ahb2_mux_data __initconst = {
+ .shift = 0,
+};
+
static void __init sunxi_mux_clk_setup(struct device_node *node,
struct mux_data *data)
{
@@ -886,7 +890,7 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
* sunxi_gates_clk_setup() - Setup function for leaf gates on clocks
*/
-#define SUNXI_GATES_MAX_SIZE 64
+#define SUNXI_GATES_MAX_SIZE 160
struct gates_data {
DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
@@ -990,6 +994,36 @@ static const struct gates_data sun8i_a23_apb2_gates_data __initconst = {
.mask = {0x1F0007},
};
+#define BUS_GATE_PARENT_AHB1 0
+#define BUS_GATE_PARENT_AHB2 1
+#define BUS_GATE_PARENT_APB1 2
+#define BUS_GATE_PARENT_APB2 3
+
+static const u8 sun8i_h3_bus_gates_parents[] __initconst = {
+ BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
+ BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
+ BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB2, BUS_GATE_PARENT_AHB1,
+ BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
+ BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
+ BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
+ BUS_GATE_PARENT_AHB2, BUS_GATE_PARENT_AHB2, BUS_GATE_PARENT_AHB2,
+ BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
+ BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
+ BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
+ BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_APB1,
+ BUS_GATE_PARENT_APB1, BUS_GATE_PARENT_APB1, BUS_GATE_PARENT_APB1,
+ BUS_GATE_PARENT_APB1, BUS_GATE_PARENT_APB1, BUS_GATE_PARENT_APB1,
+ BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2,
+ BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2,
+ BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_AHB1,
+ BUS_GATE_PARENT_AHB1
+};
+
+static const struct gates_data sun8i_h3_bus_gates_data __initconst = {
+ .mask = {0xffbe6760, 0x00701b39, 0x00007123, 0x001f0007, 0x00000081},
+ .parents = sun8i_h3_bus_gates_parents,
+};
+
static void __init sunxi_gates_clk_setup(struct device_node *node,
struct gates_data *data)
{
@@ -1110,6 +1144,16 @@ static const struct divs_data sun6i_a31_pll6_divs_data __initconst = {
}
};
+static const struct divs_data sun8i_h3_pll6_divs_data __initconst = {
+ .factors = &sun6i_a31_pll6_data,
+ .ndivs = 3,
+ .div = {
+ { .fixed = 2 }, /* normal output, pll6 */
+ { .self = 1 }, /* base factor clock, pll6 x2 */
+ { .fixed = 4 }, /* divided output, pll6 /2 */
+ }
+};
+
/**
* sunxi_divs_clk_setup() - Setup function for leaf divisors on clocks
*
@@ -1283,6 +1327,7 @@ static const struct of_device_id clk_divs_match[] __initconst = {
{.compatible = "allwinner,sun4i-a10-pll5-clk", .data = &pll5_divs_data,},
{.compatible = "allwinner,sun4i-a10-pll6-clk", .data = &pll6_divs_data,},
{.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_divs_data,},
+ {.compatible = "allwinner,sun8i-h3-pll6-clk", .data = &sun8i_h3_pll6_divs_data,},
{}
};
@@ -1290,6 +1335,7 @@ static const struct of_device_id clk_divs_match[] __initconst = {
static const struct of_device_id clk_mux_match[] __initconst = {
{.compatible = "allwinner,sun4i-a10-cpu-clk", .data = &sun4i_cpu_mux_data,},
{.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,},
+ {.compatible = "allwinner,sun8i-h3-ahb2-clk", .data = &sun8i_h3_ahb2_mux_data,},
{}
};
@@ -1319,6 +1365,7 @@ static const struct of_device_id clk_gates_match[] __initconst = {
{.compatible = "allwinner,sun9i-a80-apb1-gates-clk", .data = &sun9i_a80_apb1_gates_data,},
{.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,},
{.compatible = "allwinner,sun8i-a23-apb2-gates-clk", .data = &sun8i_a23_apb2_gates_data,},
+ {.compatible = "allwinner,sun8i-h3-bus-gates-clk", .data = &sun8i_h3_bus_gates_data,},
{}
};
@@ -1403,6 +1450,7 @@ static void __init sun6i_init_clocks(struct device_node *node)
CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks);
CLK_OF_DECLARE(sun6i_a31s_clk_init, "allwinner,sun6i-a31s", sun6i_init_clocks);
CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks);
+CLK_OF_DECLARE(sun8i_h3_clk_init, "allwinner,sun8i-h3", sun6i_init_clocks);
static void __init sun9i_init_clocks(struct device_node *node)
{
--
2.4.0
The H3 uses the same pin controller as previous SoC's from Allwinner.
Add support for the pins controlled by the main PIO controller.
Signed-off-by: Jens Kuske <[email protected]>
---
.../bindings/pinctrl/allwinner,sunxi-pinctrl.txt | 1 +
drivers/pinctrl/sunxi/Kconfig | 8 +
drivers/pinctrl/sunxi/Makefile | 1 +
drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c | 522 +++++++++++++++++++++
4 files changed, 532 insertions(+)
create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c
diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
index fdd8046..c46af8e 100644
--- a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
@@ -16,6 +16,7 @@ Required properties:
"allwinner,sun7i-a20-pinctrl"
"allwinner,sun8i-a23-pinctrl"
"allwinner,sun8i-a23-r-pinctrl"
+ "allwinner,sun8i-h3-pinctrl"
- reg: Should contain the register physical address and length for the
pin controller.
diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index 2eb893e..6c1cec5 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -43,6 +43,14 @@ config PINCTRL_SUN8I_A23_R
depends on RESET_CONTROLLER
select PINCTRL_SUNXI_COMMON
+config PINCTRL_SUN8I_H3
+ tristate "Allwinner H3 pinctrl driver"
+ default MACH_SUN8I
+ select PINCTRL_SUNXI_COMMON
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ main Port Controller (PIO) of the Allwinner H3 SoC.
+
config PINCTRL_SUN9I_A80
def_bool MACH_SUN9I
select PINCTRL_SUNXI_COMMON
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index b796d57..fd4a068 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -11,4 +11,5 @@ obj-$(CONFIG_PINCTRL_SUN6I_A31_R) += pinctrl-sun6i-a31-r.o
obj-$(CONFIG_PINCTRL_SUN7I_A20) += pinctrl-sun7i-a20.o
obj-$(CONFIG_PINCTRL_SUN8I_A23) += pinctrl-sun8i-a23.o
obj-$(CONFIG_PINCTRL_SUN8I_A23_R) += pinctrl-sun8i-a23-r.o
+obj-$(CONFIG_PINCTRL_SUN8I_H3) += pinctrl-sun8i-h3.o
obj-$(CONFIG_PINCTRL_SUN9I_A80) += pinctrl-sun9i-a80.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c
new file mode 100644
index 0000000..d5ab91c
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c
@@ -0,0 +1,522 @@
+/*
+ * Allwinner H3 SoCs pinctrl driver.
+ *
+ * Copyright (C) 2015 Jens Kuske <[email protected]>
+ *
+ * Based on pinctrl-sun8i-a23.c, which is:
+ * Copyright (C) 2014 Chen-Yu Tsai <[email protected]>
+ * Copyright (C) 2014 Maxime Ripard <[email protected]>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin sun8i_h3_pins[] = {
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* TX */
+ SUNXI_FUNCTION(0x3, "jtag"), /* MS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)), /* PA_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* RX */
+ SUNXI_FUNCTION(0x3, "jtag"), /* CK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)), /* PA_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* RTS */
+ SUNXI_FUNCTION(0x3, "jtag"), /* DO */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)), /* PA_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* CTS */
+ SUNXI_FUNCTION(0x3, "jtag"), /* DI */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)), /* PA_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart0"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)), /* PA_EINT4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart0"), /* RX */
+ SUNXI_FUNCTION(0x3, "pwm0"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)), /* PA_EINT5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sim"), /* PWREN */
+ SUNXI_FUNCTION(0x3, "pwm1"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)), /* PA_EINT6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sim"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)), /* PA_EINT7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sim"), /* DATA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)), /* PA_EINT8 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sim"), /* RST */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 9)), /* PA_EINT9 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sim"), /* DET */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 10)), /* PA_EINT10 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c0"), /* SCK */
+ SUNXI_FUNCTION(0x3, "di"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 11)), /* PA_EINT11 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c0"), /* SDA */
+ SUNXI_FUNCTION(0x3, "di"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 12)), /* PA_EINT12 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* CS */
+ SUNXI_FUNCTION(0x3, "uart3"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 13)), /* PA_EINT13 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* CLK */
+ SUNXI_FUNCTION(0x3, "uart3"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 14)), /* PA_EINT14 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* MOSI */
+ SUNXI_FUNCTION(0x3, "uart3"), /* RTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 15)), /* PA_EINT15 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* MISO */
+ SUNXI_FUNCTION(0x3, "uart3"), /* CTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 16)), /* PA_EINT16 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 17),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spdif"), /* OUT */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 17)), /* PA_EINT17 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 18),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* SYNC */
+ SUNXI_FUNCTION(0x3, "i2c1"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 18)), /* PA_EINT18 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 19),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* CLK */
+ SUNXI_FUNCTION(0x3, "i2c1"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 19)), /* PA_EINT19 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 20),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* DOUT */
+ SUNXI_FUNCTION(0x3, "sim"), /* VPPEN */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 20)), /* PA_EINT20 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 21),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* DIN */
+ SUNXI_FUNCTION(0x3, "sim"), /* VPPPP */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 21)), /* PA_EINT21 */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* WE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* MOSI */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* ALE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* MISO */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* CLE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* CLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* CE1 */
+ SUNXI_FUNCTION(0x3, "spi0")), /* CS */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* CE0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* RE */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* CLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* RB0 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* CMD */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* RB1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ0 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ1 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ2 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ3 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ4 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ5 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand"), /* DQ6 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand"), /* DQ7 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand"), /* DQS */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* RST */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXD3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXD2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXD1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXD0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXCTL/RCDV */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXERR */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXD3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXD2L */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXD1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXD0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* CRS */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXCTL/TXEN */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXERR */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* CLKIN/COL */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* MDC */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* MDIO */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* PCLK */
+ SUNXI_FUNCTION(0x3, "ts")), /* CLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* MCLK */
+ SUNXI_FUNCTION(0x3, "ts")), /* ERR */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* HSYNC */
+ SUNXI_FUNCTION(0x3, "ts")), /* SYNC */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* VSYNC */
+ SUNXI_FUNCTION(0x3, "ts")), /* DVLD */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D0 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D1 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D2 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D3 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D4 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D5 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D6 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D7 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* SCK */
+ SUNXI_FUNCTION(0x3, "i2c2")), /* SCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* SDA */
+ SUNXI_FUNCTION(0x3, "i2c2")), /* SDA */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out")),
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D1 */
+ SUNXI_FUNCTION(0x3, "jtag")), /* MS */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D0 */
+ SUNXI_FUNCTION(0x3, "jtag")), /* DI */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* CLK */
+ SUNXI_FUNCTION(0x3, "uart0")), /* TX */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* CMD */
+ SUNXI_FUNCTION(0x3, "jtag")), /* DO */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D3 */
+ SUNXI_FUNCTION(0x3, "uart0")), /* RX */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D2 */
+ SUNXI_FUNCTION(0x3, "jtag")), /* CK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0")), /* DET */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 0)), /* PG_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* CMD */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 1)), /* PG_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D0 */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 2)), /* PG_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 3)), /* PG_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D2 */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 4)), /* PG_EINT4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D3 */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 5)), /* PG_EINT5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 6)), /* PG_EINT6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 7)), /* PG_EINT7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* RTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 8)), /* PG_EINT8 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* CTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 9)), /* PG_EINT9 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* SYNC */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 10)), /* PG_EINT10 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 11)), /* PG_EINT11 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* DOUT */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 12)), /* PG_EINT12 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* DIN */
+ SUNXI_FUNCTION_IRQ_BANK(0x4, 1, 13)), /* PG_EINT13 */
+};
+
+static const struct sunxi_pinctrl_desc sun8i_h3_pinctrl_data = {
+ .pins = sun8i_h3_pins,
+ .npins = ARRAY_SIZE(sun8i_h3_pins),
+ .irq_banks = 2,
+};
+
+static int sun8i_h3_pinctrl_probe(struct platform_device *pdev)
+{
+ return sunxi_pinctrl_init(pdev,
+ &sun8i_h3_pinctrl_data);
+}
+
+static const struct of_device_id sun8i_h3_pinctrl_match[] = {
+ { .compatible = "allwinner,sun8i-h3-pinctrl", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sun8i_h3_pinctrl_match);
+
+static struct platform_driver sun8i_h3_pinctrl_driver = {
+ .probe = sun8i_h3_pinctrl_probe,
+ .remove = sunxi_pinctrl_remove,
+ .driver = {
+ .name = "sun8i-h3-pinctrl",
+ .of_match_table = sun8i_h3_pinctrl_match,
+ },
+};
+module_platform_driver(sun8i_h3_pinctrl_driver);
+
+MODULE_AUTHOR("Jens Kuske <[email protected]>");
+MODULE_DESCRIPTION("Allwinner H3 pinctrl driver");
+MODULE_LICENSE("GPL");
--
2.4.0
Adding a new compatible allows us to define SoC specific behaviour
if necessary, for example forcing a particular device out of reset
even if no driver is actually using it.
Signed-off-by: Jens Kuske <[email protected]>
---
Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt | 1 +
drivers/reset/reset-sunxi.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt b/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt
index c8f7757..e11f023 100644
--- a/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt
+++ b/Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt
@@ -8,6 +8,7 @@ Required properties:
- compatible: Should be one of the following:
"allwinner,sun6i-a31-ahb1-reset"
"allwinner,sun6i-a31-clock-reset"
+ "allwinner,sun8i-h3-bus-reset"
- reg: should be register base and length as documented in the
datasheet
- #reset-cells: 1, see below
diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c
index 3d95c87..6f12b5c 100644
--- a/drivers/reset/reset-sunxi.c
+++ b/drivers/reset/reset-sunxi.c
@@ -124,6 +124,7 @@ err_alloc:
*/
static const struct of_device_id sunxi_early_reset_dt_ids[] __initdata = {
{ .compatible = "allwinner,sun6i-a31-ahb1-reset", },
+ { .compatible = "allwinner,sun8i-h3-bus-reset", },
{ /* sentinel */ },
};
--
2.4.0
The Allwinner H3 is a home entertainment system oriented SoC with
four Cortex-A7 cores and a Mali-400MP2 GPU.
Signed-off-by: Jens Kuske <[email protected]>
---
arch/arm/boot/dts/sun8i-h3.dtsi | 446 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 446 insertions(+)
create mode 100644 arch/arm/boot/dts/sun8i-h3.dtsi
diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
new file mode 100644
index 0000000..d541145
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -0,0 +1,446 @@
+/*
+ * Copyright (C) 2015 Jens Kuske <[email protected]>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "skeleton.dtsi"
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
+
+/ {
+ interrupt-parent = <&gic>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <0>;
+ };
+
+ cpu@1 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <1>;
+ };
+
+ cpu@2 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <2>;
+ };
+
+ cpu@3 {
+ compatible = "arm,cortex-a7";
+ device_type = "cpu";
+ reg = <3>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+ clock-frequency = <24000000>;
+ arm,cpu-registers-not-fw-configured;
+ };
+
+ memory {
+ reg = <0x40000000 0x80000000>;
+ };
+
+ clocks {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ osc24M: osc24M_clk {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <24000000>;
+ clock-output-names = "osc24M";
+ };
+
+ osc32k: osc32k_clk {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <32768>;
+ clock-output-names = "osc32k";
+ };
+
+ pll1: clk@01c20000 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun8i-a23-pll1-clk";
+ reg = <0x01c20000 0x4>;
+ clocks = <&osc24M>;
+ clock-output-names = "pll1";
+ };
+
+ pll6: clk@01c20028 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun8i-h3-pll6-clk";
+ reg = <0x01c20028 0x4>;
+ clocks = <&osc24M>;
+ clock-output-names = "pll6", "pll6x2", "pll6d2";
+ };
+
+ pll8: clk@01c20044 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun6i-a31-pll6-clk";
+ reg = <0x01c20044 0x4>;
+ clocks = <&osc24M>;
+ clock-output-names = "pll8", "pll8x2";
+ };
+
+ cpu: cpu_clk@01c20050 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-a10-cpu-clk";
+ reg = <0x01c20050 0x4>;
+ clocks = <&osc32k>, <&osc24M>, <&pll1>, <&pll1>;
+ clock-output-names = "cpu";
+ };
+
+ axi: axi_clk@01c20050 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-a10-axi-clk";
+ reg = <0x01c20050 0x4>;
+ clocks = <&cpu>;
+ clock-output-names = "axi";
+ };
+
+ ahb1: ahb1_clk@01c20054 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun6i-a31-ahb1-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&osc32k>, <&osc24M>, <&axi>, <&pll6 0>;
+ clock-output-names = "ahb1";
+ };
+
+ ahb2: ahb2_clk@01c2005c {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun8i-h3-ahb2-clk";
+ reg = <0x01c2005c 0x4>;
+ clocks = <&ahb1>, <&pll6 2>;
+ clock-output-names = "ahb2";
+ };
+
+ apb1: apb1_clk@01c20054 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-a10-apb0-clk";
+ reg = <0x01c20054 0x4>;
+ clocks = <&ahb1>;
+ clock-output-names = "apb1";
+ };
+
+ apb2: apb2_clk@01c20058 {
+ #clock-cells = <0>;
+ compatible = "allwinner,sun4i-a10-apb1-clk";
+ reg = <0x01c20058 0x4>;
+ clocks = <&osc32k>, <&osc24M>, <&pll6 0>, <&pll6 0>;
+ clock-output-names = "apb2";
+ };
+
+ bus_gates: clk@01c20060 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun8i-h3-bus-gates-clk";
+ reg = <0x01c20060 0x14>;
+ clocks = <&ahb1>, <&ahb2>, <&apb1>, <&apb2>;
+ clock-output-names = "ahb1_ce", "ahb1_dma", "ahb1_mmc0",
+ "ahb1_mmc1", "ahb1_mmc2",
+ "ahb1_nand", "ahb1_sdram",
+ "ahb2_gmac", "ahb1_ts",
+ "ahb1_hstimer", "ahb1_spi0",
+ "ahb1_spi1", "ahb1_otg",
+ "ahb1_otg_ehci0", "ahb1_ehic1",
+ "ahb1_ehic2", "ahb1_ehic3",
+ "ahb1_otg_ohci0", "ahb2_ohic1",
+ "ahb2_ohic2", "ahb2_ohic3",
+ "ahb1_ve", "ahb1_lcd0",
+ "ahb1_lcd1", "ahb1_deint",
+ "ahb1_csi", "ahb1_tve",
+ "ahb1_hdmi", "ahb1_de",
+ "ahb1_gpu", "ahb1_msgbox",
+ "ahb1_spinlock", "apb1_codec",
+ "apb1_spdif", "apb1_pio",
+ "apb1_ths", "apb1_i2s0",
+ "apb1_i2s1", "apb1_i2s2",
+ "apb2_i2c0", "apb2_i2c1",
+ "apb2_i2c2", "apb2_uart0",
+ "apb2_uart1", "apb2_uart2",
+ "apb2_uart3", "apb2_scr",
+ "ahb1_ephy", "ahb1_dbg";
+ };
+
+ mmc0_clk: clk@01c20088 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
+ reg = <0x01c20088 0x4>;
+ clocks = <&osc24M>, <&pll6 0>, <&pll8 0>;
+ clock-output-names = "mmc0",
+ "mmc0_output",
+ "mmc0_sample";
+ };
+
+ mmc1_clk: clk@01c2008c {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
+ reg = <0x01c2008c 0x4>;
+ clocks = <&osc24M>, <&pll6 0>, <&pll8 0>;
+ clock-output-names = "mmc1",
+ "mmc1_output",
+ "mmc1_sample";
+ };
+
+ mmc2_clk: clk@01c20090 {
+ #clock-cells = <1>;
+ compatible = "allwinner,sun4i-a10-mmc-clk";
+ reg = <0x01c20090 0x4>;
+ clocks = <&osc24M>, <&pll6 0>, <&pll8 0>;
+ clock-output-names = "mmc2",
+ "mmc2_output",
+ "mmc2_sample";
+ };
+ };
+
+ soc@01c00000 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ dma: dma-controller@01c02000 {
+ compatible = "allwinner,sun8i-h3-dma";
+ reg = <0x01c02000 0x1000>;
+ interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&bus_gates 6>;
+ resets = <&bus_rst 6>;
+ #dma-cells = <1>;
+ };
+
+ mmc0: mmc@01c0f000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c0f000 0x1000>;
+ clocks = <&bus_gates 8>,
+ <&mmc0_clk 0>,
+ <&mmc0_clk 1>,
+ <&mmc0_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
+ resets = <&bus_rst 8>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ mmc1: mmc@01c10000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c10000 0x1000>;
+ clocks = <&bus_gates 9>,
+ <&mmc1_clk 0>,
+ <&mmc1_clk 1>,
+ <&mmc1_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
+ resets = <&bus_rst 9>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ mmc2: mmc@01c11000 {
+ compatible = "allwinner,sun5i-a13-mmc";
+ reg = <0x01c11000 0x1000>;
+ clocks = <&bus_gates 10>,
+ <&mmc2_clk 0>,
+ <&mmc2_clk 1>,
+ <&mmc2_clk 2>;
+ clock-names = "ahb",
+ "mmc",
+ "output",
+ "sample";
+ resets = <&bus_rst 10>;
+ reset-names = "ahb";
+ interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ pio: pinctrl@01c20800 {
+ compatible = "allwinner,sun8i-h3-pinctrl";
+ reg = <0x01c20800 0x400>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&bus_gates 69>;
+ gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ #size-cells = <0>;
+ #gpio-cells = <3>;
+
+ uart0_pins_a: uart0@0 {
+ allwinner,pins = "PA4", "PA5";
+ allwinner,function = "uart0";
+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+ };
+
+ mmc0_pins_a: mmc0@0 {
+ allwinner,pins = "PF0", "PF1", "PF2", "PF3",
+ "PF4", "PF5";
+ allwinner,function = "mmc0";
+ allwinner,drive = <SUN4I_PINCTRL_30_MA>;
+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+ };
+
+ mmc0_cd_pin: mmc0_cd_pin@0 {
+ allwinner,pins = "PF6";
+ allwinner,function = "gpio_in";
+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+ allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
+ };
+
+ mmc1_pins_a: mmc1@0 {
+ allwinner,pins = "PG0", "PG1", "PG2", "PG3",
+ "PG4", "PG5";
+ allwinner,function = "mmc1";
+ allwinner,drive = <SUN4I_PINCTRL_30_MA>;
+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+ };
+ };
+
+ bus_rst: reset@01c202c0 {
+ #reset-cells = <1>;
+ compatible = "allwinner,sun8i-h3-bus-reset";
+ reg = <0x01c202c0 0x1c>;
+ };
+
+ timer@01c20c00 {
+ compatible = "allwinner,sun4i-a10-timer";
+ reg = <0x01c20c00 0xa0>;
+ interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&osc24M>;
+ };
+
+ wdt0: watchdog@01c20ca0 {
+ compatible = "allwinner,sun6i-a31-wdt";
+ reg = <0x01c20ca0 0x20>;
+ interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ uart0: serial@01c28000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x01c28000 0x400>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&bus_gates 112>;
+ resets = <&bus_rst 208>;
+ dmas = <&dma 6>, <&dma 6>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart1: serial@01c28400 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x01c28400 0x400>;
+ interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&bus_gates 113>;
+ resets = <&bus_rst 209>;
+ dmas = <&dma 7>, <&dma 7>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart2: serial@01c28800 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x01c28800 0x400>;
+ interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&bus_gates 114>;
+ resets = <&bus_rst 210>;
+ dmas = <&dma 8>, <&dma 8>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ uart3: serial@01c28c00 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0x01c28c00 0x400>;
+ interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ clocks = <&bus_gates 115>;
+ resets = <&bus_rst 211>;
+ dmas = <&dma 9>, <&dma 9>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ gic: interrupt-controller@01c81000 {
+ compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
+ reg = <0x01c81000 0x1000>,
+ <0x01c82000 0x1000>,
+ <0x01c84000 0x2000>,
+ <0x01c86000 0x2000>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ };
+
+ rtc: rtc@01f00000 {
+ compatible = "allwinner,sun6i-a31-rtc";
+ reg = <0x01f00000 0x54>;
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+};
--
2.4.0
The Orange Pi Plus is a SBC based on the Allwinner H3 SoC
with 8GB eMMC, multiple USB ports through a USB hub chip, SATA through
a USB-SATA bridge, one uSD slot, a 10/100/1000M ethernet port,
WiFi, HDMI, headphone jack, IR receiver, a microphone, a CSI connector
and a 40-pin GPIO header.
Signed-off-by: Jens Kuske <[email protected]>
---
arch/arm/boot/dts/Makefile | 3 +-
arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts | 77 ++++++++++++++++++++++++++++
2 files changed, 79 insertions(+), 1 deletion(-)
create mode 100644 arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 31e1f41..c5a96a9 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -571,7 +571,8 @@ dtb-$(CONFIG_MACH_SUN7I) += \
sun7i-a20-wexler-tab7200.dtb
dtb-$(CONFIG_MACH_SUN8I) += \
sun8i-a23-ippo-q8h-v5.dtb \
- sun8i-a23-ippo-q8h-v1.2.dtb
+ sun8i-a23-ippo-q8h-v1.2.dtb \
+ sun8i-h3-orangepi-plus.dtb
dtb-$(CONFIG_MACH_SUN9I) += \
sun9i-a80-optimus.dtb \
sun9i-a80-cubieboard4.dtb
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts
new file mode 100644
index 0000000..e67df59
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2015 Jens Kuske <[email protected]>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ * a) This file is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ * b) Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "sun8i-h3.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
+
+/ {
+ model = "Xunlong Orange Pi Plus";
+ compatible = "xunlong,orangepi-plus", "allwinner,sun8i-h3";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&mmc0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
+ vmmc-supply = <®_vcc3v3>;
+ bus-width = <4>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
+ cd-inverted;
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+ status = "okay";
+};
--
2.4.0
Just a nit: a license mismatch.
(I didn't bring this up in v1. Perhaps I should have.)
On Fri, 2015-05-15 at 18:38 +0200, Jens Kuske wrote:
> --- /dev/null
> +++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
This states the license is GPL v2.
> +MODULE_LICENSE("GPL");
According to include/linux/module.h this states the license is GPL v2 or
later. So I think that either the comment at the top of this file or the
ident used in the MODULE_LICENSE() macro needs to change.
Paul Bolle
Hi Jens,
On Fri, May 15, 2015 at 06:38:52PM +0200, Jens Kuske wrote:
> Some newer sunxi SoCs (A83T, H3) don't have individual registers for
> AHB1, APB1 and APB2 gates anymore, but one big bus gates area where each
> gate can have a different parent.
>
> The current clock driver sets the same parent for all gates in a group.
> This commit adds a new parents field to the gates_data structure, which
> allows us to specify an array of parent indices for every single gate.
>
> Signed-off-by: Jens Kuske <[email protected]>
> ---
> drivers/clk/sunxi/clk-sunxi.c | 12 +++++++++++-
> 1 file changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
> index 9a82f17..17cba4d 100644
> --- a/drivers/clk/sunxi/clk-sunxi.c
> +++ b/drivers/clk/sunxi/clk-sunxi.c
> @@ -898,6 +898,8 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
>
> struct gates_data {
> DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
> + /* If used, ARRAY_SIZE(parents) has to be >= bitmap_weight(mask) */
> + const u8 *parents;
> };
>
> static const struct gates_data sun4i_axi_gates_data __initconst = {
> @@ -1000,16 +1002,21 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
> struct gates_data *data)
> {
> struct clk_onecell_data *clk_data;
> + const char *parents[SUNXI_MAX_PARENTS];
> const char *clk_parent;
> const char *clk_name;
> void __iomem *reg;
> + int npar = 0;
> int qty;
> int i = 0;
> int j = 0;
>
> reg = of_iomap(node, 0);
>
> - clk_parent = of_clk_get_parent_name(node, 0);
> + while (npar < SUNXI_MAX_PARENTS &&
> + (parents[npar] = of_clk_get_parent_name(node, npar)) != NULL)
> + npar++;
> + clk_parent = parents[0];
>
> /* Worst-case size approximation and memory allocation */
> qty = find_last_bit(data->mask, SUNXI_GATES_MAX_SIZE);
> @@ -1026,6 +1033,9 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
> of_property_read_string_index(node, "clock-output-names",
> j, &clk_name);
>
> + if (data->parents && !WARN_ON(data->parents[j] >= npar))
> + clk_parent = parents[data->parents[j]];
> +
I'm currently removing that code, so I was more expecting a new
standalone driver for that clock.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
On Fri, May 15, 2015 at 06:38:51PM +0200, Jens Kuske wrote:
> There are some new Allwinner SoCs available, namely A33, A83T and H3.
> Update the documentation to mention those and the related documents.
>
> Signed-off-by: Jens Kuske <[email protected]>
Applied, thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
On Fri, May 15, 2015 at 06:38:53PM +0200, Jens Kuske wrote:
> Currently, the sunxi clock driver gets the name for the base factor clock
> of divs clocks from the name field in factors_data. This prevents reusing
> of the factor clock for clocks with same properties, but different name.
>
> This commit makes the divs setup function try to get a name from
> clock-output-names in the devicetree. It also removes the name field where
> possible and merges the sun4i PLL5 and PLL6 clocks.
>
> The sun4i PLL5 clock doesn't have a output for the base factor clock,
> so we still have to use the name field there.
>
> Signed-off-by: Jens Kuske <[email protected]>
> ---
> drivers/clk/sunxi/clk-sunxi.c | 22 ++++++++++++----------
> 1 file changed, 12 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
> index 17cba4d..afe560c 100644
> --- a/drivers/clk/sunxi/clk-sunxi.c
> +++ b/drivers/clk/sunxi/clk-sunxi.c
> @@ -708,18 +708,10 @@ static const struct factors_data sun4i_pll5_data __initconst = {
> .name = "pll5",
> };
>
> -static const struct factors_data sun4i_pll6_data __initconst = {
> - .enable = 31,
> - .table = &sun4i_pll5_config,
> - .getter = sun4i_get_pll5_factors,
> - .name = "pll6",
> -};
> -
> static const struct factors_data sun6i_a31_pll6_data __initconst = {
> .enable = 31,
> .table = &sun6i_a31_pll6_config,
> .getter = sun6i_a31_get_pll6_factors,
> - .name = "pll6x2",
> };
>
> static const struct factors_data sun5i_a13_ahb_data __initconst = {
> @@ -1099,7 +1091,7 @@ static const struct divs_data pll5_divs_data __initconst = {
> };
>
> static const struct divs_data pll6_divs_data __initconst = {
> - .factors = &sun4i_pll6_data,
> + .factors = &sun4i_pll5_data,
> .ndivs = 4,
> .div = {
> { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */
> @@ -1141,6 +1133,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
> struct clk_gate *gate = NULL;
> struct clk_fixed_factor *fix_factor;
> struct clk_divider *divider;
> + struct factors_data factors = *data->factors;
> void __iomem *reg;
> int ndivs = SUNXI_DIVS_MAX_QTY, i = 0;
> int flags, clkflags;
> @@ -1149,8 +1142,17 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
> if (data->ndivs)
> ndivs = data->ndivs;
>
> + /* Try to find a name for base factor clock */
> + for (i = 0; i < ndivs; i++) {
> + if (data->div[i].self) {
I'm not sure we should expect the factor clock to have a self factor.
what about taking the first output and taking the substring up to the
first "_" ?
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
On Fri, May 15, 2015 at 06:38:54PM +0200, Jens Kuske wrote:
> Add a remove function and export the init and remove function
> to allow us to build the SoC specific drivers as modules.
>
> Signed-off-by: Jens Kuske <[email protected]>
> ---
> drivers/pinctrl/sunxi/pinctrl-sunxi.c | 25 +++++++++++++++++++------
> drivers/pinctrl/sunxi/pinctrl-sunxi.h | 2 ++
> 2 files changed, 21 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> index f8e171b..4ef6b3d 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> @@ -856,7 +856,6 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
> struct sunxi_pinctrl *pctl;
> struct resource *res;
> int i, ret, last_pin;
> - struct clk *clk;
>
> pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
> if (!pctl)
> @@ -954,13 +953,13 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
> goto gpiochip_error;
> }
>
> - clk = devm_clk_get(&pdev->dev, NULL);
> - if (IS_ERR(clk)) {
> - ret = PTR_ERR(clk);
> + pctl->clk = devm_clk_get(&pdev->dev, NULL);
> + if (IS_ERR(pctl->clk)) {
> + ret = PTR_ERR(pctl->clk);
> goto gpiochip_error;
> }
>
> - ret = clk_prepare_enable(clk);
> + ret = clk_prepare_enable(pctl->clk);
> if (ret)
> goto gpiochip_error;
>
> @@ -1015,10 +1014,24 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
> return 0;
>
> clk_error:
> - clk_disable_unprepare(clk);
> + clk_disable_unprepare(pctl->clk);
> gpiochip_error:
> gpiochip_remove(pctl->chip);
> pinctrl_error:
> pinctrl_unregister(pctl->pctl_dev);
> return ret;
> }
> +EXPORT_SYMBOL(sunxi_pinctrl_init);
> +
> +int sunxi_pinctrl_remove(struct platform_device *pdev)
> +{
> + struct sunxi_pinctrl *pctl = platform_get_drvdata(pdev);
> +
> + gpiochip_remove(pctl->chip);
> + pinctrl_unregister(pctl->pctl_dev);
> +
> + clk_disable_unprepare(pctl->clk);
We should also remove the domain and the interrupt mapping here.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
On Fri, May 15, 2015 at 06:38:55PM +0200, Jens Kuske wrote:
> The Allwinner H3 is a quad-core Cortex-A7-based SoC. It is very similar
> to other sun8i family SoCs like the A23.
>
> Signed-off-by: Jens Kuske <[email protected]>
Applied, thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
On Fri, May 15, 2015 at 06:38:56PM +0200, Jens Kuske wrote:
> The H3 clock control unit is similar to the those of other sun8i family
> members like the A23.
>
> It makes use of the new multiple parents option for the bus gates.
> Some of the gates use the new AHB2 clock as parent, whose clock source
> is muxable between AHB1 and PLL6/2. The documentation isn't totally clear
> about which devices belong to AHB2 now, especially USB EHIC/OHIC, so it
> is mostly based on Allwinner kernel source code.
>
> Signed-off-by: Jens Kuske <[email protected]>
> ---
> Documentation/devicetree/bindings/clock/sunxi.txt | 6 +++
> drivers/clk/sunxi/clk-sunxi.c | 50 ++++++++++++++++++++++-
> 2 files changed, 55 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
> index 4fa11af..e367963 100644
> --- a/Documentation/devicetree/bindings/clock/sunxi.txt
> +++ b/Documentation/devicetree/bindings/clock/sunxi.txt
> @@ -14,6 +14,7 @@ Required properties:
> "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock
> "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock
> "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
> + "allwinner,sun8i-h3-pll6-clk" - for the PLL6 clock on H3
> "allwinner,sun9i-a80-gt-clk" - for the GT bus clock on A80
> "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock
> "allwinner,sun4i-a10-axi-clk" - for the AXI clock
> @@ -28,6 +29,7 @@ Required properties:
> "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20
> "allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31
> "allwinner,sun6i-a31-ahb1-clk" - for the AHB1 clock on A31
> + "allwinner,sun8i-h3-ahb2-clk" - for the AHB2 clock on H3
> "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31
> "allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23
> "allwinner,sun9i-a80-ahb0-gates-clk" - for the AHB0 gates on A80
> @@ -55,6 +57,7 @@ Required properties:
> "allwinner,sun9i-a80-apb1-gates-clk" - for the APB1 gates on A80
> "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
> "allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
> + "allwinner,sun8i-h3-bus-gates-clk" - for the bus gates on H3
> "allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13
> "allwinner,sun4i-a10-mmc-clk" - for the MMC clock
> "allwinner,sun9i-a80-mmc-clk" - for mmc module clocks on A80
> @@ -95,6 +98,9 @@ The "allwinner,sun9i-a80-mmc-config-clk" clock also requires:
> For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate
> dummy clocks at 25 MHz and 125 MHz, respectively. See example.
>
> +For "allwinner,sun8i-h3-bus-gates-clk", the parent clocks shall be
> +AHB1, AHB2, APB1 and APB2, in that order.
> +
> Clock consumers should specify the desired clocks they use with a
> "clocks" phandle cell. Consumers that are using a gated clock should
> provide an additional ID in their clock property. This ID is the
> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
> index afe560c..79364be 100644
> --- a/drivers/clk/sunxi/clk-sunxi.c
> +++ b/drivers/clk/sunxi/clk-sunxi.c
> @@ -771,6 +771,10 @@ static const struct mux_data sun6i_a31_ahb1_mux_data __initconst = {
> .shift = 12,
> };
>
> +static const struct mux_data sun8i_h3_ahb2_mux_data __initconst = {
> + .shift = 0,
> +};
> +
> static void __init sunxi_mux_clk_setup(struct device_node *node,
> struct mux_data *data)
> {
> @@ -886,7 +890,7 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
> * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks
> */
>
> -#define SUNXI_GATES_MAX_SIZE 64
> +#define SUNXI_GATES_MAX_SIZE 160
>
> struct gates_data {
> DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
> @@ -990,6 +994,36 @@ static const struct gates_data sun8i_a23_apb2_gates_data __initconst = {
> .mask = {0x1F0007},
> };
>
> +#define BUS_GATE_PARENT_AHB1 0
> +#define BUS_GATE_PARENT_AHB2 1
> +#define BUS_GATE_PARENT_APB1 2
> +#define BUS_GATE_PARENT_APB2 3
> +
> +static const u8 sun8i_h3_bus_gates_parents[] __initconst = {
> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
> + BUS_GATE_PARENT_AHB1,
> BUS_GATE_PARENT_AHB2,
> BUS_GATE_PARENT_AHB1,
> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
> + BUS_GATE_PARENT_AHB2, BUS_GATE_PARENT_AHB2, BUS_GATE_PARENT_AHB2,
> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
> BUS_GATE_PARENT_APB1,
> + BUS_GATE_PARENT_APB1, BUS_GATE_PARENT_APB1, BUS_GATE_PARENT_APB1,
> + BUS_GATE_PARENT_APB1, BUS_GATE_PARENT_APB1, BUS_GATE_PARENT_APB1,
> + BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2,
> + BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2,
> + BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2,
> BUS_GATE_PARENT_AHB1,
> + BUS_GATE_PARENT_AHB1
> +}
I think something like this:
if (index < .. || index > ..)
clk_parent = "ahb1"
if (index == .. || index < ...)
clk_parent = "ahb2"
etc...
Would be both easier to maintain and to read.
> +
> +static const struct gates_data sun8i_h3_bus_gates_data __initconst = {
> + .mask = {0xffbe6760, 0x00701b39, 0x00007123, 0x001f0007, 0x00000081},
> + .parents = sun8i_h3_bus_gates_parents,
> +};
> +
> static void __init sunxi_gates_clk_setup(struct device_node *node,
> struct gates_data *data)
> {
> @@ -1110,6 +1144,16 @@ static const struct divs_data sun6i_a31_pll6_divs_data __initconst = {
> }
> };
>
> +static const struct divs_data sun8i_h3_pll6_divs_data __initconst = {
> + .factors = &sun6i_a31_pll6_data,
> + .ndivs = 3,
> + .div = {
> + { .fixed = 2 }, /* normal output, pll6 */
> + { .self = 1 }, /* base factor clock, pll6 x2 */
> + { .fixed = 4 }, /* divided output, pll6 /2 */
> + }
> +};
This is exactly the same clock as A31's PLL6, it shouldn't be declared
as a different one.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
On Fri, May 15, 2015 at 06:38:57PM +0200, Jens Kuske wrote:
> The H3 uses the same pin controller as previous SoC's from Allwinner.
> Add support for the pins controlled by the main PIO controller.
>
> Signed-off-by: Jens Kuske <[email protected]>
> ---
> .../bindings/pinctrl/allwinner,sunxi-pinctrl.txt | 1 +
> drivers/pinctrl/sunxi/Kconfig | 8 +
> drivers/pinctrl/sunxi/Makefile | 1 +
> drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c | 522 +++++++++++++++++++++
> 4 files changed, 532 insertions(+)
> create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c
>
> diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
> index fdd8046..c46af8e 100644
> --- a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
> +++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
> @@ -16,6 +16,7 @@ Required properties:
> "allwinner,sun7i-a20-pinctrl"
> "allwinner,sun8i-a23-pinctrl"
> "allwinner,sun8i-a23-r-pinctrl"
> + "allwinner,sun8i-h3-pinctrl"
> - reg: Should contain the register physical address and length for the
> pin controller.
>
> diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
> index 2eb893e..6c1cec5 100644
> --- a/drivers/pinctrl/sunxi/Kconfig
> +++ b/drivers/pinctrl/sunxi/Kconfig
> @@ -43,6 +43,14 @@ config PINCTRL_SUN8I_A23_R
> depends on RESET_CONTROLLER
> select PINCTRL_SUNXI_COMMON
>
> +config PINCTRL_SUN8I_H3
> + tristate "Allwinner H3 pinctrl driver"
> + default MACH_SUN8I
> + select PINCTRL_SUNXI_COMMON
PINCTRL_SUNXI_COMMON should probably be turned into a tristate as well
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
On Fri, May 15, 2015 at 06:38:58PM +0200, Jens Kuske wrote:
> Adding a new compatible allows us to define SoC specific behaviour
> if necessary, for example forcing a particular device out of reset
> even if no driver is actually using it.
>
> Signed-off-by: Jens Kuske <[email protected]>
This should have been sent to the reset framework maintainer.
Looks good otherwise.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
Hi,
On 05/17/15 14:50, Maxime Ripard wrote:
> Hi Jens,
>
> On Fri, May 15, 2015 at 06:38:52PM +0200, Jens Kuske wrote:
>> Some newer sunxi SoCs (A83T, H3) don't have individual registers for
>> AHB1, APB1 and APB2 gates anymore, but one big bus gates area where each
>> gate can have a different parent.
>>
>> The current clock driver sets the same parent for all gates in a group.
>> This commit adds a new parents field to the gates_data structure, which
>> allows us to specify an array of parent indices for every single gate.
>>
>> Signed-off-by: Jens Kuske <[email protected]>
>> ---
>> drivers/clk/sunxi/clk-sunxi.c | 12 +++++++++++-
>> 1 file changed, 11 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
>> index 9a82f17..17cba4d 100644
>> --- a/drivers/clk/sunxi/clk-sunxi.c
>> +++ b/drivers/clk/sunxi/clk-sunxi.c
>> @@ -898,6 +898,8 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
>>
>> struct gates_data {
>> DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
>> + /* If used, ARRAY_SIZE(parents) has to be >= bitmap_weight(mask) */
>> + const u8 *parents;
>> };
>>
>> static const struct gates_data sun4i_axi_gates_data __initconst = {
>> @@ -1000,16 +1002,21 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
>> struct gates_data *data)
>> {
>> struct clk_onecell_data *clk_data;
>> + const char *parents[SUNXI_MAX_PARENTS];
>> const char *clk_parent;
>> const char *clk_name;
>> void __iomem *reg;
>> + int npar = 0;
>> int qty;
>> int i = 0;
>> int j = 0;
>>
>> reg = of_iomap(node, 0);
>>
>> - clk_parent = of_clk_get_parent_name(node, 0);
>> + while (npar < SUNXI_MAX_PARENTS &&
>> + (parents[npar] = of_clk_get_parent_name(node, npar)) != NULL)
>> + npar++;
>> + clk_parent = parents[0];
>>
>> /* Worst-case size approximation and memory allocation */
>> qty = find_last_bit(data->mask, SUNXI_GATES_MAX_SIZE);
>> @@ -1026,6 +1033,9 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
>> of_property_read_string_index(node, "clock-output-names",
>> j, &clk_name);
>>
>> + if (data->parents && !WARN_ON(data->parents[j] >= npar))
>> + clk_parent = parents[data->parents[j]];
>> +
>
> I'm currently removing that code, so I was more expecting a new
> standalone driver for that clock.
How do you want to replace that code? To me this looks like a good way
to set up all the different gates sunxi has.
Jens
Hi,
On 05/16/15 04:10, Chen-Yu Tsai wrote:
> 2015年5月16日 上午12:39於 "Jens Kuske" <[email protected]>寫道:
[..]
>> @@ -1141,6 +1133,7 @@ static void __init sunxi_divs_clk_setup(struct
> device_node *node,
>> struct clk_gate *gate = NULL;
>> struct clk_fixed_factor *fix_factor;
>> struct clk_divider *divider;
>> + struct factors_data factors = *data->factors;
Isn't this a copy?
>> void __iomem *reg;
>> int ndivs = SUNXI_DIVS_MAX_QTY, i = 0;
>> int flags, clkflags;
>> @@ -1149,8 +1142,17 @@ static void __init sunxi_divs_clk_setup(struct
> device_node *node,
>> if (data->ndivs)
>> ndivs = data->ndivs;
>>
>> + /* Try to find a name for base factor clock */
>> + for (i = 0; i < ndivs; i++) {
>> + if (data->div[i].self) {
>> + of_property_read_string_index(node,
> "clock-output-names",
>> + i, &factors.name);
>
> Please excuse the bad formatting.
> I'm at the airport without my laptop.
>
> This will not work. All the static factors_data structs are const.
> You should make a copy of it, maybe on the stack,
> update the .name field, and pass that to sunxi_factors_clk_setup().
>
If I didn't miss anything, or misunderstood what you want to copy, this
should be working fine.
Jens
On 05/17/15 15:06, Maxime Ripard wrote:
> On Fri, May 15, 2015 at 06:38:53PM +0200, Jens Kuske wrote:
>> Currently, the sunxi clock driver gets the name for the base factor clock
>> of divs clocks from the name field in factors_data. This prevents reusing
>> of the factor clock for clocks with same properties, but different name.
>>
>> This commit makes the divs setup function try to get a name from
>> clock-output-names in the devicetree. It also removes the name field where
>> possible and merges the sun4i PLL5 and PLL6 clocks.
>>
>> The sun4i PLL5 clock doesn't have a output for the base factor clock,
>> so we still have to use the name field there.
>>
>> Signed-off-by: Jens Kuske <[email protected]>
>> ---
>> drivers/clk/sunxi/clk-sunxi.c | 22 ++++++++++++----------
>> 1 file changed, 12 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
>> index 17cba4d..afe560c 100644
>> --- a/drivers/clk/sunxi/clk-sunxi.c
>> +++ b/drivers/clk/sunxi/clk-sunxi.c
>> @@ -708,18 +708,10 @@ static const struct factors_data sun4i_pll5_data __initconst = {
>> .name = "pll5",
>> };
>>
>> -static const struct factors_data sun4i_pll6_data __initconst = {
>> - .enable = 31,
>> - .table = &sun4i_pll5_config,
>> - .getter = sun4i_get_pll5_factors,
>> - .name = "pll6",
>> -};
>> -
>> static const struct factors_data sun6i_a31_pll6_data __initconst = {
>> .enable = 31,
>> .table = &sun6i_a31_pll6_config,
>> .getter = sun6i_a31_get_pll6_factors,
>> - .name = "pll6x2",
>> };
>>
>> static const struct factors_data sun5i_a13_ahb_data __initconst = {
>> @@ -1099,7 +1091,7 @@ static const struct divs_data pll5_divs_data __initconst = {
>> };
>>
>> static const struct divs_data pll6_divs_data __initconst = {
>> - .factors = &sun4i_pll6_data,
>> + .factors = &sun4i_pll5_data,
>> .ndivs = 4,
>> .div = {
>> { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */
>> @@ -1141,6 +1133,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
>> struct clk_gate *gate = NULL;
>> struct clk_fixed_factor *fix_factor;
>> struct clk_divider *divider;
>> + struct factors_data factors = *data->factors;
>> void __iomem *reg;
>> int ndivs = SUNXI_DIVS_MAX_QTY, i = 0;
>> int flags, clkflags;
>> @@ -1149,8 +1142,17 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
>> if (data->ndivs)
>> ndivs = data->ndivs;
>>
>> + /* Try to find a name for base factor clock */
>> + for (i = 0; i < ndivs; i++) {
>> + if (data->div[i].self) {
>
> I'm not sure we should expect the factor clock to have a self factor.
Maybe not, but in that case it would fall back to the name provided in
the factors_data struct, as it is the case for sun4i pll5.
> what about taking the first output and taking the substring up to the
> first "_" ?
That only works for the sun[457]i pll5 & pll6, for sun[68]i the base
clock name would have to be "pll6x2".
Jens
Hi,
On 05/17/15 16:19, Maxime Ripard wrote:
> On Fri, May 15, 2015 at 06:38:54PM +0200, Jens Kuske wrote:
>> Add a remove function and export the init and remove function
>> to allow us to build the SoC specific drivers as modules.
>>
>> Signed-off-by: Jens Kuske <[email protected]>
>> ---
>> drivers/pinctrl/sunxi/pinctrl-sunxi.c | 25 +++++++++++++++++++------
>> drivers/pinctrl/sunxi/pinctrl-sunxi.h | 2 ++
>> 2 files changed, 21 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> index f8e171b..4ef6b3d 100644
>> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> @@ -856,7 +856,6 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
>> struct sunxi_pinctrl *pctl;
>> struct resource *res;
>> int i, ret, last_pin;
>> - struct clk *clk;
>>
>> pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
>> if (!pctl)
>> @@ -954,13 +953,13 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
>> goto gpiochip_error;
>> }
>>
>> - clk = devm_clk_get(&pdev->dev, NULL);
>> - if (IS_ERR(clk)) {
>> - ret = PTR_ERR(clk);
>> + pctl->clk = devm_clk_get(&pdev->dev, NULL);
>> + if (IS_ERR(pctl->clk)) {
>> + ret = PTR_ERR(pctl->clk);
>> goto gpiochip_error;
>> }
>>
>> - ret = clk_prepare_enable(clk);
>> + ret = clk_prepare_enable(pctl->clk);
>> if (ret)
>> goto gpiochip_error;
>>
>> @@ -1015,10 +1014,24 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
>> return 0;
>>
>> clk_error:
>> - clk_disable_unprepare(clk);
>> + clk_disable_unprepare(pctl->clk);
>> gpiochip_error:
>> gpiochip_remove(pctl->chip);
>> pinctrl_error:
>> pinctrl_unregister(pctl->pctl_dev);
>> return ret;
>> }
>> +EXPORT_SYMBOL(sunxi_pinctrl_init);
>> +
>> +int sunxi_pinctrl_remove(struct platform_device *pdev)
>> +{
>> + struct sunxi_pinctrl *pctl = platform_get_drvdata(pdev);
>> +
>> + gpiochip_remove(pctl->chip);
>> + pinctrl_unregister(pctl->pctl_dev);
>> +
>> + clk_disable_unprepare(pctl->clk);
>
> We should also remove the domain and the interrupt mapping here.
Ouch, I missed that. Only looked at the *_error: labels.
Apart from that, currently the kernel panics some seconds after removing
the pinctrl module because mmc wants to access a gpio. Can this be
prevented somehow? I think pinctrl must not be removed once other
devices use any pin-related things.
Jens
Hi,
On 05/17/15 16:27, Maxime Ripard wrote:
> On Fri, May 15, 2015 at 06:38:56PM +0200, Jens Kuske wrote:
>> The H3 clock control unit is similar to the those of other sun8i family
>> members like the A23.
>>
>> It makes use of the new multiple parents option for the bus gates.
>> Some of the gates use the new AHB2 clock as parent, whose clock source
>> is muxable between AHB1 and PLL6/2. The documentation isn't totally clear
>> about which devices belong to AHB2 now, especially USB EHIC/OHIC, so it
>> is mostly based on Allwinner kernel source code.
>>
>> Signed-off-by: Jens Kuske <[email protected]>
>> ---
>> Documentation/devicetree/bindings/clock/sunxi.txt | 6 +++
>> drivers/clk/sunxi/clk-sunxi.c | 50 ++++++++++++++++++++++-
>> 2 files changed, 55 insertions(+), 1 deletion(-)
>>
>> diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
>> index 4fa11af..e367963 100644
>> --- a/Documentation/devicetree/bindings/clock/sunxi.txt
>> +++ b/Documentation/devicetree/bindings/clock/sunxi.txt
>> @@ -14,6 +14,7 @@ Required properties:
>> "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock
>> "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock
>> "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
>> + "allwinner,sun8i-h3-pll6-clk" - for the PLL6 clock on H3
>> "allwinner,sun9i-a80-gt-clk" - for the GT bus clock on A80
>> "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock
>> "allwinner,sun4i-a10-axi-clk" - for the AXI clock
>> @@ -28,6 +29,7 @@ Required properties:
>> "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20
>> "allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31
>> "allwinner,sun6i-a31-ahb1-clk" - for the AHB1 clock on A31
>> + "allwinner,sun8i-h3-ahb2-clk" - for the AHB2 clock on H3
>> "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31
>> "allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23
>> "allwinner,sun9i-a80-ahb0-gates-clk" - for the AHB0 gates on A80
>> @@ -55,6 +57,7 @@ Required properties:
>> "allwinner,sun9i-a80-apb1-gates-clk" - for the APB1 gates on A80
>> "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
>> "allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
>> + "allwinner,sun8i-h3-bus-gates-clk" - for the bus gates on H3
>> "allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13
>> "allwinner,sun4i-a10-mmc-clk" - for the MMC clock
>> "allwinner,sun9i-a80-mmc-clk" - for mmc module clocks on A80
>> @@ -95,6 +98,9 @@ The "allwinner,sun9i-a80-mmc-config-clk" clock also requires:
>> For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate
>> dummy clocks at 25 MHz and 125 MHz, respectively. See example.
>>
>> +For "allwinner,sun8i-h3-bus-gates-clk", the parent clocks shall be
>> +AHB1, AHB2, APB1 and APB2, in that order.
>> +
>> Clock consumers should specify the desired clocks they use with a
>> "clocks" phandle cell. Consumers that are using a gated clock should
>> provide an additional ID in their clock property. This ID is the
>> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
>> index afe560c..79364be 100644
>> --- a/drivers/clk/sunxi/clk-sunxi.c
>> +++ b/drivers/clk/sunxi/clk-sunxi.c
>> @@ -771,6 +771,10 @@ static const struct mux_data sun6i_a31_ahb1_mux_data __initconst = {
>> .shift = 12,
>> };
>>
>> +static const struct mux_data sun8i_h3_ahb2_mux_data __initconst = {
>> + .shift = 0,
>> +};
>> +
>> static void __init sunxi_mux_clk_setup(struct device_node *node,
>> struct mux_data *data)
>> {
>> @@ -886,7 +890,7 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
>> * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks
>> */
>>
>> -#define SUNXI_GATES_MAX_SIZE 64
>> +#define SUNXI_GATES_MAX_SIZE 160
>>
>> struct gates_data {
>> DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
>> @@ -990,6 +994,36 @@ static const struct gates_data sun8i_a23_apb2_gates_data __initconst = {
>> .mask = {0x1F0007},
>> };
>>
>> +#define BUS_GATE_PARENT_AHB1 0
>> +#define BUS_GATE_PARENT_AHB2 1
>> +#define BUS_GATE_PARENT_APB1 2
>> +#define BUS_GATE_PARENT_APB2 3
>> +
>> +static const u8 sun8i_h3_bus_gates_parents[] __initconst = {
>> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
>> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
>> + BUS_GATE_PARENT_AHB1,
>
>> BUS_GATE_PARENT_AHB2,
>> BUS_GATE_PARENT_AHB1,
>> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
>> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
>> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
>
>> + BUS_GATE_PARENT_AHB2, BUS_GATE_PARENT_AHB2, BUS_GATE_PARENT_AHB2,
>
>> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
>> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
>> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
>> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
>
>> BUS_GATE_PARENT_APB1,
>> + BUS_GATE_PARENT_APB1, BUS_GATE_PARENT_APB1, BUS_GATE_PARENT_APB1,
>> + BUS_GATE_PARENT_APB1, BUS_GATE_PARENT_APB1, BUS_GATE_PARENT_APB1,
>
>> + BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2,
>> + BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2,
>> + BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2,
>
>> BUS_GATE_PARENT_AHB1,
>> + BUS_GATE_PARENT_AHB1
>> +}
>
> I think something like this:
>
> if (index < .. || index > ..)
> clk_parent = "ahb1"
> if (index == .. || index < ...)
> clk_parent = "ahb2"
> etc...
>
> Would be both easier to maintain and to read.
At least as long as there aren't too many disjunct groups.
But it would mean duplicate setup functions for each SoC (or something
like sun8i_h3_bus_gate_get_parent(int index))
But since you want to rework the gate setup anyway I think I'll wait
until then. Currently I can't see how this should look like.
>
>> +
>> +static const struct gates_data sun8i_h3_bus_gates_data __initconst = {
>> + .mask = {0xffbe6760, 0x00701b39, 0x00007123, 0x001f0007, 0x00000081},
>> + .parents = sun8i_h3_bus_gates_parents,
>> +};
>> +
>> static void __init sunxi_gates_clk_setup(struct device_node *node,
>> struct gates_data *data)
>> {
>> @@ -1110,6 +1144,16 @@ static const struct divs_data sun6i_a31_pll6_divs_data __initconst = {
>> }
>> };
>>
>> +static const struct divs_data sun8i_h3_pll6_divs_data __initconst = {
>> + .factors = &sun6i_a31_pll6_data,
>> + .ndivs = 3,
>> + .div = {
>> + { .fixed = 2 }, /* normal output, pll6 */
>> + { .self = 1 }, /* base factor clock, pll6 x2 */
>> + { .fixed = 4 }, /* divided output, pll6 /2 */
>> + }
>> +};
>
> This is exactly the same clock as A31's PLL6, it shouldn't be declared
> as a different one.
Um, sorry, but I can't see the /2 output at A31's pll6.
Or shall we add the /2 output to A31's PLL6 and simply ignore it on A31?
I don't think this is a good idea, what happens if we need to add an
additional output on A31 later.
Regards,
Jens
Hi,
On 05/17/15 16:30, Maxime Ripard wrote:
> On Fri, May 15, 2015 at 06:38:57PM +0200, Jens Kuske wrote:
>> The H3 uses the same pin controller as previous SoC's from Allwinner.
>> Add support for the pins controlled by the main PIO controller.
>>
>> Signed-off-by: Jens Kuske <[email protected]>
>> ---
>> .../bindings/pinctrl/allwinner,sunxi-pinctrl.txt | 1 +
>> drivers/pinctrl/sunxi/Kconfig | 8 +
>> drivers/pinctrl/sunxi/Makefile | 1 +
>> drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c | 522 +++++++++++++++++++++
>> 4 files changed, 532 insertions(+)
>> create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c
>>
>> diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
>> index fdd8046..c46af8e 100644
>> --- a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
>> +++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
>> @@ -16,6 +16,7 @@ Required properties:
>> "allwinner,sun7i-a20-pinctrl"
>> "allwinner,sun8i-a23-pinctrl"
>> "allwinner,sun8i-a23-r-pinctrl"
>> + "allwinner,sun8i-h3-pinctrl"
>> - reg: Should contain the register physical address and length for the
>> pin controller.
>>
>> diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
>> index 2eb893e..6c1cec5 100644
>> --- a/drivers/pinctrl/sunxi/Kconfig
>> +++ b/drivers/pinctrl/sunxi/Kconfig
>> @@ -43,6 +43,14 @@ config PINCTRL_SUN8I_A23_R
>> depends on RESET_CONTROLLER
>> select PINCTRL_SUNXI_COMMON
>>
>> +config PINCTRL_SUN8I_H3
>> + tristate "Allwinner H3 pinctrl driver"
>> + default MACH_SUN8I
>> + select PINCTRL_SUNXI_COMMON
>
> PINCTRL_SUNXI_COMMON should probably be turned into a tristate as well
Probably, as well as all the other SoC specific drivers. But I think
this should be a separate patch, its independent from this addition.
But given the remove-panic problems I mentioned earlier this whole
pinctrl-as-module topic needs some attention from more experienced devs
I guess, this is beyond my current kernel knowledge.
Regards,
Jens
On 05/17/15 16:31, Maxime Ripard wrote:
> On Fri, May 15, 2015 at 06:38:58PM +0200, Jens Kuske wrote:
>> Adding a new compatible allows us to define SoC specific behaviour
>> if necessary, for example forcing a particular device out of reset
>> even if no driver is actually using it.
>>
>> Signed-off-by: Jens Kuske <[email protected]>
>
> This should have been sent to the reset framework maintainer.
I knew I missed something. Given all the other comments, I'll need a v3
anyway.
Jens
On Mon, May 18, 2015 at 5:15 PM, Jens Kuske <[email protected]> wrote:
> Hi,
>
> On 05/16/15 04:10, Chen-Yu Tsai wrote:
>> 2015年5月16日 上午12:39於 "Jens Kuske" <[email protected]>寫道:
> [..]
>>> @@ -1141,6 +1133,7 @@ static void __init sunxi_divs_clk_setup(struct
>> device_node *node,
>>> struct clk_gate *gate = NULL;
>>> struct clk_fixed_factor *fix_factor;
>>> struct clk_divider *divider;
>>> + struct factors_data factors = *data->factors;
>
> Isn't this a copy?
You're right. Sorry for the noise.
>
>>> void __iomem *reg;
>>> int ndivs = SUNXI_DIVS_MAX_QTY, i = 0;
>>> int flags, clkflags;
>>> @@ -1149,8 +1142,17 @@ static void __init sunxi_divs_clk_setup(struct
>> device_node *node,
>>> if (data->ndivs)
>>> ndivs = data->ndivs;
>>>
>>> + /* Try to find a name for base factor clock */
>>> + for (i = 0; i < ndivs; i++) {
>>> + if (data->div[i].self) {
>>> + of_property_read_string_index(node,
>> "clock-output-names",
>>> + i, &factors.name);
>>
>> Please excuse the bad formatting.
>> I'm at the airport without my laptop.
>>
>> This will not work. All the static factors_data structs are const.
>> You should make a copy of it, maybe on the stack,
>> update the .name field, and pass that to sunxi_factors_clk_setup().
>>
>
> If I didn't miss anything, or misunderstood what you want to copy, this
> should be working fine.
>
> Jens
>
On Mon, May 18, 2015 at 11:11:34AM +0200, Jens Kuske wrote:
> Hi,
>
> On 05/17/15 14:50, Maxime Ripard wrote:
> > Hi Jens,
> >
> > On Fri, May 15, 2015 at 06:38:52PM +0200, Jens Kuske wrote:
> >> Some newer sunxi SoCs (A83T, H3) don't have individual registers for
> >> AHB1, APB1 and APB2 gates anymore, but one big bus gates area where each
> >> gate can have a different parent.
> >>
> >> The current clock driver sets the same parent for all gates in a group.
> >> This commit adds a new parents field to the gates_data structure, which
> >> allows us to specify an array of parent indices for every single gate.
> >>
> >> Signed-off-by: Jens Kuske <[email protected]>
> >> ---
> >> drivers/clk/sunxi/clk-sunxi.c | 12 +++++++++++-
> >> 1 file changed, 11 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
> >> index 9a82f17..17cba4d 100644
> >> --- a/drivers/clk/sunxi/clk-sunxi.c
> >> +++ b/drivers/clk/sunxi/clk-sunxi.c
> >> @@ -898,6 +898,8 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
> >>
> >> struct gates_data {
> >> DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
> >> + /* If used, ARRAY_SIZE(parents) has to be >= bitmap_weight(mask) */
> >> + const u8 *parents;
> >> };
> >>
> >> static const struct gates_data sun4i_axi_gates_data __initconst = {
> >> @@ -1000,16 +1002,21 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
> >> struct gates_data *data)
> >> {
> >> struct clk_onecell_data *clk_data;
> >> + const char *parents[SUNXI_MAX_PARENTS];
> >> const char *clk_parent;
> >> const char *clk_name;
> >> void __iomem *reg;
> >> + int npar = 0;
> >> int qty;
> >> int i = 0;
> >> int j = 0;
> >>
> >> reg = of_iomap(node, 0);
> >>
> >> - clk_parent = of_clk_get_parent_name(node, 0);
> >> + while (npar < SUNXI_MAX_PARENTS &&
> >> + (parents[npar] = of_clk_get_parent_name(node, npar)) != NULL)
> >> + npar++;
> >> + clk_parent = parents[0];
> >>
> >> /* Worst-case size approximation and memory allocation */
> >> qty = find_last_bit(data->mask, SUNXI_GATES_MAX_SIZE);
> >> @@ -1026,6 +1033,9 @@ static void __init sunxi_gates_clk_setup(struct device_node *node,
> >> of_property_read_string_index(node, "clock-output-names",
> >> j, &clk_name);
> >>
> >> + if (data->parents && !WARN_ON(data->parents[j] >= npar))
> >> + clk_parent = parents[data->parents[j]];
> >> +
> >
> > I'm currently removing that code, so I was more expecting a new
> > standalone driver for that clock.
>
> How do you want to replace that code? To me this looks like a good way
> to set up all the different gates sunxi has.
By using clock-indices and moving all this gate stuff out of clk-sunxi
and into a new driver.
It's done already, I just need to make sure everything works at it
used to on all the SoCs.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
On Mon, May 18, 2015 at 11:32:31AM +0200, Jens Kuske wrote:
> Hi,
>
> On 05/17/15 16:19, Maxime Ripard wrote:
> > On Fri, May 15, 2015 at 06:38:54PM +0200, Jens Kuske wrote:
> >> Add a remove function and export the init and remove function
> >> to allow us to build the SoC specific drivers as modules.
> >>
> >> Signed-off-by: Jens Kuske <[email protected]>
> >> ---
> >> drivers/pinctrl/sunxi/pinctrl-sunxi.c | 25 +++++++++++++++++++------
> >> drivers/pinctrl/sunxi/pinctrl-sunxi.h | 2 ++
> >> 2 files changed, 21 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> index f8e171b..4ef6b3d 100644
> >> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> @@ -856,7 +856,6 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
> >> struct sunxi_pinctrl *pctl;
> >> struct resource *res;
> >> int i, ret, last_pin;
> >> - struct clk *clk;
> >>
> >> pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
> >> if (!pctl)
> >> @@ -954,13 +953,13 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
> >> goto gpiochip_error;
> >> }
> >>
> >> - clk = devm_clk_get(&pdev->dev, NULL);
> >> - if (IS_ERR(clk)) {
> >> - ret = PTR_ERR(clk);
> >> + pctl->clk = devm_clk_get(&pdev->dev, NULL);
> >> + if (IS_ERR(pctl->clk)) {
> >> + ret = PTR_ERR(pctl->clk);
> >> goto gpiochip_error;
> >> }
> >>
> >> - ret = clk_prepare_enable(clk);
> >> + ret = clk_prepare_enable(pctl->clk);
> >> if (ret)
> >> goto gpiochip_error;
> >>
> >> @@ -1015,10 +1014,24 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
> >> return 0;
> >>
> >> clk_error:
> >> - clk_disable_unprepare(clk);
> >> + clk_disable_unprepare(pctl->clk);
> >> gpiochip_error:
> >> gpiochip_remove(pctl->chip);
> >> pinctrl_error:
> >> pinctrl_unregister(pctl->pctl_dev);
> >> return ret;
> >> }
> >> +EXPORT_SYMBOL(sunxi_pinctrl_init);
> >> +
> >> +int sunxi_pinctrl_remove(struct platform_device *pdev)
> >> +{
> >> + struct sunxi_pinctrl *pctl = platform_get_drvdata(pdev);
> >> +
> >> + gpiochip_remove(pctl->chip);
> >> + pinctrl_unregister(pctl->pctl_dev);
> >> +
> >> + clk_disable_unprepare(pctl->clk);
> >
> > We should also remove the domain and the interrupt mapping here.
>
> Ouch, I missed that. Only looked at the *_error: labels.
>
> Apart from that, currently the kernel panics some seconds after removing
> the pinctrl module because mmc wants to access a gpio. Can this be
> prevented somehow? I think pinctrl must not be removed once other
> devices use any pin-related things.
pinctrl_unregister doesn't look like it cares about whether or not
there's users left in the system.
Maybe the easiest path would be to just make this builtin like Paul
suggested then ... :/
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
On Tue, May 19, 2015 at 3:55 PM, Maxime Ripard
<[email protected]> wrote:
> On Mon, May 18, 2015 at 11:32:31AM +0200, Jens Kuske wrote:
>> Hi,
>>
>> On 05/17/15 16:19, Maxime Ripard wrote:
>> > On Fri, May 15, 2015 at 06:38:54PM +0200, Jens Kuske wrote:
>> >> Add a remove function and export the init and remove function
>> >> to allow us to build the SoC specific drivers as modules.
>> >>
>> >> Signed-off-by: Jens Kuske <[email protected]>
>> >> ---
>> >> drivers/pinctrl/sunxi/pinctrl-sunxi.c | 25 +++++++++++++++++++------
>> >> drivers/pinctrl/sunxi/pinctrl-sunxi.h | 2 ++
>> >> 2 files changed, 21 insertions(+), 6 deletions(-)
>> >>
>> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> >> index f8e171b..4ef6b3d 100644
>> >> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
>> >> @@ -856,7 +856,6 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
>> >> struct sunxi_pinctrl *pctl;
>> >> struct resource *res;
>> >> int i, ret, last_pin;
>> >> - struct clk *clk;
>> >>
>> >> pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
>> >> if (!pctl)
>> >> @@ -954,13 +953,13 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
>> >> goto gpiochip_error;
>> >> }
>> >>
>> >> - clk = devm_clk_get(&pdev->dev, NULL);
>> >> - if (IS_ERR(clk)) {
>> >> - ret = PTR_ERR(clk);
>> >> + pctl->clk = devm_clk_get(&pdev->dev, NULL);
>> >> + if (IS_ERR(pctl->clk)) {
>> >> + ret = PTR_ERR(pctl->clk);
>> >> goto gpiochip_error;
>> >> }
>> >>
>> >> - ret = clk_prepare_enable(clk);
>> >> + ret = clk_prepare_enable(pctl->clk);
>> >> if (ret)
>> >> goto gpiochip_error;
>> >>
>> >> @@ -1015,10 +1014,24 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
>> >> return 0;
>> >>
>> >> clk_error:
>> >> - clk_disable_unprepare(clk);
>> >> + clk_disable_unprepare(pctl->clk);
>> >> gpiochip_error:
>> >> gpiochip_remove(pctl->chip);
>> >> pinctrl_error:
>> >> pinctrl_unregister(pctl->pctl_dev);
>> >> return ret;
>> >> }
>> >> +EXPORT_SYMBOL(sunxi_pinctrl_init);
>> >> +
>> >> +int sunxi_pinctrl_remove(struct platform_device *pdev)
>> >> +{
>> >> + struct sunxi_pinctrl *pctl = platform_get_drvdata(pdev);
>> >> +
>> >> + gpiochip_remove(pctl->chip);
>> >> + pinctrl_unregister(pctl->pctl_dev);
>> >> +
>> >> + clk_disable_unprepare(pctl->clk);
>> >
>> > We should also remove the domain and the interrupt mapping here.
>>
>> Ouch, I missed that. Only looked at the *_error: labels.
>>
>> Apart from that, currently the kernel panics some seconds after removing
>> the pinctrl module because mmc wants to access a gpio. Can this be
>> prevented somehow? I think pinctrl must not be removed once other
>> devices use any pin-related things.
>
> pinctrl_unregister doesn't look like it cares about whether or not
> there's users left in the system.
>
> Maybe the easiest path would be to just make this builtin like Paul
> suggested then ... :/
Is there a way to mark modules as not removable? At least we can keep
the multi-platform kernel image small.
On Tue, May 19, 2015 at 04:02:39PM +0800, Chen-Yu Tsai wrote:
> On Tue, May 19, 2015 at 3:55 PM, Maxime Ripard
> <[email protected]> wrote:
> > On Mon, May 18, 2015 at 11:32:31AM +0200, Jens Kuske wrote:
> >> Hi,
> >>
> >> On 05/17/15 16:19, Maxime Ripard wrote:
> >> > On Fri, May 15, 2015 at 06:38:54PM +0200, Jens Kuske wrote:
> >> >> Add a remove function and export the init and remove function
> >> >> to allow us to build the SoC specific drivers as modules.
> >> >>
> >> >> Signed-off-by: Jens Kuske <[email protected]>
> >> >> ---
> >> >> drivers/pinctrl/sunxi/pinctrl-sunxi.c | 25 +++++++++++++++++++------
> >> >> drivers/pinctrl/sunxi/pinctrl-sunxi.h | 2 ++
> >> >> 2 files changed, 21 insertions(+), 6 deletions(-)
> >> >>
> >> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> >> index f8e171b..4ef6b3d 100644
> >> >> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> >> @@ -856,7 +856,6 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
> >> >> struct sunxi_pinctrl *pctl;
> >> >> struct resource *res;
> >> >> int i, ret, last_pin;
> >> >> - struct clk *clk;
> >> >>
> >> >> pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
> >> >> if (!pctl)
> >> >> @@ -954,13 +953,13 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
> >> >> goto gpiochip_error;
> >> >> }
> >> >>
> >> >> - clk = devm_clk_get(&pdev->dev, NULL);
> >> >> - if (IS_ERR(clk)) {
> >> >> - ret = PTR_ERR(clk);
> >> >> + pctl->clk = devm_clk_get(&pdev->dev, NULL);
> >> >> + if (IS_ERR(pctl->clk)) {
> >> >> + ret = PTR_ERR(pctl->clk);
> >> >> goto gpiochip_error;
> >> >> }
> >> >>
> >> >> - ret = clk_prepare_enable(clk);
> >> >> + ret = clk_prepare_enable(pctl->clk);
> >> >> if (ret)
> >> >> goto gpiochip_error;
> >> >>
> >> >> @@ -1015,10 +1014,24 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
> >> >> return 0;
> >> >>
> >> >> clk_error:
> >> >> - clk_disable_unprepare(clk);
> >> >> + clk_disable_unprepare(pctl->clk);
> >> >> gpiochip_error:
> >> >> gpiochip_remove(pctl->chip);
> >> >> pinctrl_error:
> >> >> pinctrl_unregister(pctl->pctl_dev);
> >> >> return ret;
> >> >> }
> >> >> +EXPORT_SYMBOL(sunxi_pinctrl_init);
> >> >> +
> >> >> +int sunxi_pinctrl_remove(struct platform_device *pdev)
> >> >> +{
> >> >> + struct sunxi_pinctrl *pctl = platform_get_drvdata(pdev);
> >> >> +
> >> >> + gpiochip_remove(pctl->chip);
> >> >> + pinctrl_unregister(pctl->pctl_dev);
> >> >> +
> >> >> + clk_disable_unprepare(pctl->clk);
> >> >
> >> > We should also remove the domain and the interrupt mapping here.
> >>
> >> Ouch, I missed that. Only looked at the *_error: labels.
> >>
> >> Apart from that, currently the kernel panics some seconds after removing
> >> the pinctrl module because mmc wants to access a gpio. Can this be
> >> prevented somehow? I think pinctrl must not be removed once other
> >> devices use any pin-related things.
> >
> > pinctrl_unregister doesn't look like it cares about whether or not
> > there's users left in the system.
> >
> > Maybe the easiest path would be to just make this builtin like Paul
> > suggested then ... :/
>
> Is there a way to mark modules as not removable? At least we can keep
> the multi-platform kernel image small.
If there's no module_exit, the module will only be removable through a
rmmod -f, which seems like an acceptable solution.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
On Mon, May 18, 2015 at 11:22:32AM +0200, Jens Kuske wrote:
> On 05/17/15 15:06, Maxime Ripard wrote:
> > On Fri, May 15, 2015 at 06:38:53PM +0200, Jens Kuske wrote:
> >> Currently, the sunxi clock driver gets the name for the base factor clock
> >> of divs clocks from the name field in factors_data. This prevents reusing
> >> of the factor clock for clocks with same properties, but different name.
> >>
> >> This commit makes the divs setup function try to get a name from
> >> clock-output-names in the devicetree. It also removes the name field where
> >> possible and merges the sun4i PLL5 and PLL6 clocks.
> >>
> >> The sun4i PLL5 clock doesn't have a output for the base factor clock,
> >> so we still have to use the name field there.
> >>
> >> Signed-off-by: Jens Kuske <[email protected]>
> >> ---
> >> drivers/clk/sunxi/clk-sunxi.c | 22 ++++++++++++----------
> >> 1 file changed, 12 insertions(+), 10 deletions(-)
> >>
> >> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
> >> index 17cba4d..afe560c 100644
> >> --- a/drivers/clk/sunxi/clk-sunxi.c
> >> +++ b/drivers/clk/sunxi/clk-sunxi.c
> >> @@ -708,18 +708,10 @@ static const struct factors_data sun4i_pll5_data __initconst = {
> >> .name = "pll5",
> >> };
> >>
> >> -static const struct factors_data sun4i_pll6_data __initconst = {
> >> - .enable = 31,
> >> - .table = &sun4i_pll5_config,
> >> - .getter = sun4i_get_pll5_factors,
> >> - .name = "pll6",
> >> -};
> >> -
> >> static const struct factors_data sun6i_a31_pll6_data __initconst = {
> >> .enable = 31,
> >> .table = &sun6i_a31_pll6_config,
> >> .getter = sun6i_a31_get_pll6_factors,
> >> - .name = "pll6x2",
> >> };
> >>
> >> static const struct factors_data sun5i_a13_ahb_data __initconst = {
> >> @@ -1099,7 +1091,7 @@ static const struct divs_data pll5_divs_data __initconst = {
> >> };
> >>
> >> static const struct divs_data pll6_divs_data __initconst = {
> >> - .factors = &sun4i_pll6_data,
> >> + .factors = &sun4i_pll5_data,
> >> .ndivs = 4,
> >> .div = {
> >> { .shift = 0, .table = pll6_sata_tbl, .gate = 14 }, /* M, SATA */
> >> @@ -1141,6 +1133,7 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
> >> struct clk_gate *gate = NULL;
> >> struct clk_fixed_factor *fix_factor;
> >> struct clk_divider *divider;
> >> + struct factors_data factors = *data->factors;
> >> void __iomem *reg;
> >> int ndivs = SUNXI_DIVS_MAX_QTY, i = 0;
> >> int flags, clkflags;
> >> @@ -1149,8 +1142,17 @@ static void __init sunxi_divs_clk_setup(struct device_node *node,
> >> if (data->ndivs)
> >> ndivs = data->ndivs;
> >>
> >> + /* Try to find a name for base factor clock */
> >> + for (i = 0; i < ndivs; i++) {
> >> + if (data->div[i].self) {
> >
> > I'm not sure we should expect the factor clock to have a self factor.
>
> Maybe not, but in that case it would fall back to the name provided in
> the factors_data struct, as it is the case for sun4i pll5.
Which doesn't really solve the underlying issue, just make it work in
your (pll6/pll8) case.
> > what about taking the first output and taking the substring up to the
> > first "_" ?
>
> That only works for the sun[457]i pll5 & pll6, for sun[68]i the base
> clock name would have to be "pll6x2".
Why?
It's called pll6 in the datasheet, it should really be called
pll6. The fact that there is some fixed factors or dividers on some
children only impacts those children, and not the system as a whole.
And the fact that the "base" clock is pll6x2 and not pll6 itself is
very debatable. How do you know which clock is the base one? Most
clocks are actually using pll6 as a reference.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
On Mon, May 18, 2015 at 11:45:50AM +0200, Jens Kuske wrote:
> Hi,
>
> On 05/17/15 16:27, Maxime Ripard wrote:
> > On Fri, May 15, 2015 at 06:38:56PM +0200, Jens Kuske wrote:
> >> The H3 clock control unit is similar to the those of other sun8i family
> >> members like the A23.
> >>
> >> It makes use of the new multiple parents option for the bus gates.
> >> Some of the gates use the new AHB2 clock as parent, whose clock source
> >> is muxable between AHB1 and PLL6/2. The documentation isn't totally clear
> >> about which devices belong to AHB2 now, especially USB EHIC/OHIC, so it
> >> is mostly based on Allwinner kernel source code.
> >>
> >> Signed-off-by: Jens Kuske <[email protected]>
> >> ---
> >> Documentation/devicetree/bindings/clock/sunxi.txt | 6 +++
> >> drivers/clk/sunxi/clk-sunxi.c | 50 ++++++++++++++++++++++-
> >> 2 files changed, 55 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
> >> index 4fa11af..e367963 100644
> >> --- a/Documentation/devicetree/bindings/clock/sunxi.txt
> >> +++ b/Documentation/devicetree/bindings/clock/sunxi.txt
> >> @@ -14,6 +14,7 @@ Required properties:
> >> "allwinner,sun4i-a10-pll5-clk" - for the PLL5 clock
> >> "allwinner,sun4i-a10-pll6-clk" - for the PLL6 clock
> >> "allwinner,sun6i-a31-pll6-clk" - for the PLL6 clock on A31
> >> + "allwinner,sun8i-h3-pll6-clk" - for the PLL6 clock on H3
> >> "allwinner,sun9i-a80-gt-clk" - for the GT bus clock on A80
> >> "allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock
> >> "allwinner,sun4i-a10-axi-clk" - for the AXI clock
> >> @@ -28,6 +29,7 @@ Required properties:
> >> "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20
> >> "allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31
> >> "allwinner,sun6i-a31-ahb1-clk" - for the AHB1 clock on A31
> >> + "allwinner,sun8i-h3-ahb2-clk" - for the AHB2 clock on H3
> >> "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31
> >> "allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23
> >> "allwinner,sun9i-a80-ahb0-gates-clk" - for the AHB0 gates on A80
> >> @@ -55,6 +57,7 @@ Required properties:
> >> "allwinner,sun9i-a80-apb1-gates-clk" - for the APB1 gates on A80
> >> "allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
> >> "allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
> >> + "allwinner,sun8i-h3-bus-gates-clk" - for the bus gates on H3
> >> "allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13
> >> "allwinner,sun4i-a10-mmc-clk" - for the MMC clock
> >> "allwinner,sun9i-a80-mmc-clk" - for mmc module clocks on A80
> >> @@ -95,6 +98,9 @@ The "allwinner,sun9i-a80-mmc-config-clk" clock also requires:
> >> For "allwinner,sun7i-a20-gmac-clk", the parent clocks shall be fixed rate
> >> dummy clocks at 25 MHz and 125 MHz, respectively. See example.
> >>
> >> +For "allwinner,sun8i-h3-bus-gates-clk", the parent clocks shall be
> >> +AHB1, AHB2, APB1 and APB2, in that order.
> >> +
> >> Clock consumers should specify the desired clocks they use with a
> >> "clocks" phandle cell. Consumers that are using a gated clock should
> >> provide an additional ID in their clock property. This ID is the
> >> diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
> >> index afe560c..79364be 100644
> >> --- a/drivers/clk/sunxi/clk-sunxi.c
> >> +++ b/drivers/clk/sunxi/clk-sunxi.c
> >> @@ -771,6 +771,10 @@ static const struct mux_data sun6i_a31_ahb1_mux_data __initconst = {
> >> .shift = 12,
> >> };
> >>
> >> +static const struct mux_data sun8i_h3_ahb2_mux_data __initconst = {
> >> + .shift = 0,
> >> +};
> >> +
> >> static void __init sunxi_mux_clk_setup(struct device_node *node,
> >> struct mux_data *data)
> >> {
> >> @@ -886,7 +890,7 @@ static void __init sunxi_divider_clk_setup(struct device_node *node,
> >> * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks
> >> */
> >>
> >> -#define SUNXI_GATES_MAX_SIZE 64
> >> +#define SUNXI_GATES_MAX_SIZE 160
> >>
> >> struct gates_data {
> >> DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
> >> @@ -990,6 +994,36 @@ static const struct gates_data sun8i_a23_apb2_gates_data __initconst = {
> >> .mask = {0x1F0007},
> >> };
> >>
> >> +#define BUS_GATE_PARENT_AHB1 0
> >> +#define BUS_GATE_PARENT_AHB2 1
> >> +#define BUS_GATE_PARENT_APB1 2
> >> +#define BUS_GATE_PARENT_APB2 3
> >> +
> >> +static const u8 sun8i_h3_bus_gates_parents[] __initconst = {
> >> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
> >> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
> >> + BUS_GATE_PARENT_AHB1,
> >
> >> BUS_GATE_PARENT_AHB2,
> >> BUS_GATE_PARENT_AHB1,
> >> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
> >> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
> >> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
> >
> >> + BUS_GATE_PARENT_AHB2, BUS_GATE_PARENT_AHB2, BUS_GATE_PARENT_AHB2,
> >
> >> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
> >> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
> >> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
> >> + BUS_GATE_PARENT_AHB1, BUS_GATE_PARENT_AHB1,
> >
> >> BUS_GATE_PARENT_APB1,
> >> + BUS_GATE_PARENT_APB1, BUS_GATE_PARENT_APB1, BUS_GATE_PARENT_APB1,
> >> + BUS_GATE_PARENT_APB1, BUS_GATE_PARENT_APB1, BUS_GATE_PARENT_APB1,
> >
> >> + BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2,
> >> + BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2,
> >> + BUS_GATE_PARENT_APB2, BUS_GATE_PARENT_APB2,
> >
> >> BUS_GATE_PARENT_AHB1,
> >> + BUS_GATE_PARENT_AHB1
> >> +}
> >
> > I think something like this:
> >
> > if (index < .. || index > ..)
> > clk_parent = "ahb1"
> > if (index == .. || index < ...)
> > clk_parent = "ahb2"
> > etc...
> >
> > Would be both easier to maintain and to read.
>
> At least as long as there aren't too many disjunct groups.
> But it would mean duplicate setup functions for each SoC (or something
> like sun8i_h3_bus_gate_get_parent(int index))
>
> But since you want to rework the gate setup anyway I think I'll wait
> until then. Currently I can't see how this should look like.
We shouldn't care too much about how we can factorise things that
don't need to be factorised.
We have a single user for a clock like this one. Don't try to be smart
by covering all possible cases that might or might not happen in the
future, just make it work for your single user, hardcoding everything
is a good option here.
> >> +static const struct gates_data sun8i_h3_bus_gates_data __initconst = {
> >> + .mask = {0xffbe6760, 0x00701b39, 0x00007123, 0x001f0007, 0x00000081},
> >> + .parents = sun8i_h3_bus_gates_parents,
> >> +};
> >> +
> >> static void __init sunxi_gates_clk_setup(struct device_node *node,
> >> struct gates_data *data)
> >> {
> >> @@ -1110,6 +1144,16 @@ static const struct divs_data sun6i_a31_pll6_divs_data __initconst = {
> >> }
> >> };
> >>
> >> +static const struct divs_data sun8i_h3_pll6_divs_data __initconst = {
> >> + .factors = &sun6i_a31_pll6_data,
> >> + .ndivs = 3,
> >> + .div = {
> >> + { .fixed = 2 }, /* normal output, pll6 */
> >> + { .self = 1 }, /* base factor clock, pll6 x2 */
> >> + { .fixed = 4 }, /* divided output, pll6 /2 */
> >> + }
> >> +};
> >
> > This is exactly the same clock as A31's PLL6, it shouldn't be declared
> > as a different one.
>
> Um, sorry, but I can't see the /2 output at A31's pll6.
>
> Or shall we add the /2 output to A31's PLL6 and simply ignore it on A31?
> I don't think this is a good idea, what happens if we need to add an
> additional output on A31 later.
This /2 output is not an output, it really is an input of some other
clocks.
This whole thing is currently a mess, I agree, but still, it's the
exact same clock from a register point of view. How it's used by other
components in the system shouldn't matter at all.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
On Fri, May 15, 2015 at 6:38 PM, Jens Kuske <[email protected]> wrote:
> The H3 uses the same pin controller as previous SoC's from Allwinner.
> Add support for the pins controlled by the main PIO controller.
>
> Signed-off-by: Jens Kuske <[email protected]>
Waiting for Maxime's ACKs on these patches before merging.
Yours,
Linus Walleij
On Tue, May 19, 2015 at 9:55 AM, Maxime Ripard
<[email protected]> wrote:
>> Apart from that, currently the kernel panics some seconds after removing
>> the pinctrl module because mmc wants to access a gpio. Can this be
>> prevented somehow? I think pinctrl must not be removed once other
>> devices use any pin-related things.
>
> pinctrl_unregister doesn't look like it cares about whether or not
> there's users left in the system.
Both GPIO and pinctrl has this problem, Johan Hovold has been
looking at fixing the GPIO side of things.
Patches welcome.
Yours,
Linus Walleij
On Tue, May 19, 2015 at 04:04:58PM +0200, Linus Walleij wrote:
> On Fri, May 15, 2015 at 6:38 PM, Jens Kuske <[email protected]> wrote:
>
> > The H3 uses the same pin controller as previous SoC's from Allwinner.
> > Add support for the pins controlled by the main PIO controller.
> >
> > Signed-off-by: Jens Kuske <[email protected]>
>
> Waiting for Maxime's ACKs on these patches before merging.
There's still the modules issue being debated on another patch of this
serie, so there will probably be a v3 of these patches.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com