mirror of https://gitee.com/openkylin/linux.git
Merge branch 'clk-bcm' into clk-next
- Make defines for bcm63xx-gate clks to use in DT - Support gate clks on BCM6318 SoCs - Add HDMI clks for BCM2711 SoCs - Support BCM2711 SoC firmware clks * clk-bcm: (42 commits) clk: bcm: dvp: Add missing module informations clk: bcm: rpi: Remove the quirks for the CPU clock clk: bcm2835: Don't cache the PLLB rate clk: bcm2835: Allow custom CCF flags for the PLLs Revert "clk: bcm2835: remove pllb" clk: bcm: rpi: Give firmware clocks a name clk: bcm: rpi: Discover the firmware clocks clk: bcm: rpi: Add an enum for the firmware clocks clk: bcm: rpi: Add DT provider for the clocks clk: bcm: rpi: Make the PLLB registration function return a clk_hw clk: bcm: rpi: Split pllb clock hooks clk: bcm: rpi: Rename is_prepared function clk: bcm: rpi: Pass the clocks data to the firmware function clk: bcm: rpi: Add clock id to data clk: bcm: rpi: Create a data structure for the clocks clk: bcm: rpi: Use CCF boundaries instead of rolling our own clk: bcm: rpi: Make sure the clkdev lookup is removed clk: bcm: rpi: Switch to clk_hw_register_clkdev clk: bcm: rpi: Remove pllb_arm_lookup global pointer clk: bcm: rpi: Make sure pllb_arm is removed ...
This commit is contained in:
commit
12ef3933b4
|
@ -1,14 +0,0 @@
|
||||||
Raspberry Pi VideoCore firmware driver
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
|
|
||||||
- compatible: Should be "raspberrypi,bcm2835-firmware"
|
|
||||||
- mboxes: Phandle to the firmware device's Mailbox.
|
|
||||||
(See: ../mailbox/mailbox.txt for more information)
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
firmware {
|
|
||||||
compatible = "raspberrypi,bcm2835-firmware";
|
|
||||||
mboxes = <&mailbox>;
|
|
||||||
};
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/arm/bcm/raspberrypi,bcm2835-firmware.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Raspberry Pi VideoCore firmware driver
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Eric Anholt <eric@anholt.net>
|
||||||
|
- Stefan Wahren <wahrenst@gmx.net>
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
items:
|
||||||
|
- const: raspberrypi,bcm2835-firmware
|
||||||
|
- const: simple-bus
|
||||||
|
|
||||||
|
mboxes:
|
||||||
|
$ref: '/schemas/types.yaml#/definitions/phandle'
|
||||||
|
description: |
|
||||||
|
Phandle to the firmware device's Mailbox.
|
||||||
|
(See: ../mailbox/mailbox.txt for more information)
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
type: object
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: raspberrypi,firmware-clocks
|
||||||
|
|
||||||
|
"#clock-cells":
|
||||||
|
const: 1
|
||||||
|
description: >
|
||||||
|
The argument is the ID of the clocks contained by the
|
||||||
|
firmware messages.
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- "#clock-cells"
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- mboxes
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
firmware {
|
||||||
|
compatible = "raspberrypi,bcm2835-firmware", "simple-bus";
|
||||||
|
mboxes = <&mailbox>;
|
||||||
|
|
||||||
|
firmware_clocks: clocks {
|
||||||
|
compatible = "raspberrypi,firmware-clocks";
|
||||||
|
#clock-cells = <1>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
...
|
|
@ -0,0 +1,47 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/clock/brcm,bcm2711-dvp.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Broadcom BCM2711 HDMI DVP Device Tree Bindings
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Maxime Ripard <mripard@kernel.org>
|
||||||
|
|
||||||
|
properties:
|
||||||
|
"#clock-cells":
|
||||||
|
const: 1
|
||||||
|
|
||||||
|
"#reset-cells":
|
||||||
|
const: 1
|
||||||
|
|
||||||
|
compatible:
|
||||||
|
const: brcm,brcm2711-dvp
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
required:
|
||||||
|
- "#clock-cells"
|
||||||
|
- "#reset-cells"
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- clocks
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
dvp: clock@7ef00000 {
|
||||||
|
compatible = "brcm,brcm2711-dvp";
|
||||||
|
reg = <0x7ef00000 0x10>;
|
||||||
|
clocks = <&clk_108MHz>;
|
||||||
|
#clock-cells = <1>;
|
||||||
|
#reset-cells = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
...
|
|
@ -3,6 +3,8 @@ Gated Clock Controller Bindings for MIPS based BCM63XX SoCs
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible: must be one of:
|
- compatible: must be one of:
|
||||||
"brcm,bcm3368-clocks"
|
"brcm,bcm3368-clocks"
|
||||||
|
"brcm,bcm6318-clocks"
|
||||||
|
"brcm,bcm6318-ubus-clocks"
|
||||||
"brcm,bcm6328-clocks"
|
"brcm,bcm6328-clocks"
|
||||||
"brcm,bcm6358-clocks"
|
"brcm,bcm6358-clocks"
|
||||||
"brcm,bcm6362-clocks"
|
"brcm,bcm6362-clocks"
|
||||||
|
|
|
@ -1,4 +1,15 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
config CLK_BCM2711_DVP
|
||||||
|
tristate "Broadcom BCM2711 DVP support"
|
||||||
|
depends on ARCH_BCM2835 ||COMPILE_TEST
|
||||||
|
depends on COMMON_CLK
|
||||||
|
default ARCH_BCM2835
|
||||||
|
select RESET_SIMPLE
|
||||||
|
help
|
||||||
|
Enable common clock framework support for the Broadcom BCM2711
|
||||||
|
DVP Controller.
|
||||||
|
|
||||||
config CLK_BCM2835
|
config CLK_BCM2835
|
||||||
bool "Broadcom BCM2835 clock support"
|
bool "Broadcom BCM2835 clock support"
|
||||||
depends on ARCH_BCM2835 || ARCH_BRCMSTB || COMPILE_TEST
|
depends on ARCH_BCM2835 || ARCH_BRCMSTB || COMPILE_TEST
|
||||||
|
|
|
@ -6,6 +6,7 @@ obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o
|
||||||
obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o
|
obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o
|
||||||
obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o
|
obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o
|
||||||
obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o
|
obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o
|
||||||
|
obj-$(CONFIG_CLK_BCM2711_DVP) += clk-bcm2711-dvp.o
|
||||||
obj-$(CONFIG_CLK_BCM2835) += clk-bcm2835.o
|
obj-$(CONFIG_CLK_BCM2835) += clk-bcm2835.o
|
||||||
obj-$(CONFIG_CLK_BCM2835) += clk-bcm2835-aux.o
|
obj-$(CONFIG_CLK_BCM2835) += clk-bcm2835-aux.o
|
||||||
obj-$(CONFIG_CLK_RASPBERRYPI) += clk-raspberrypi.o
|
obj-$(CONFIG_CLK_RASPBERRYPI) += clk-raspberrypi.o
|
||||||
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
// Copyright 2020 Cerno
|
||||||
|
|
||||||
|
#include <linux/clk-provider.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/reset-controller.h>
|
||||||
|
#include <linux/reset/reset-simple.h>
|
||||||
|
|
||||||
|
#define DVP_HT_RPI_SW_INIT 0x04
|
||||||
|
#define DVP_HT_RPI_MISC_CONFIG 0x08
|
||||||
|
|
||||||
|
#define NR_CLOCKS 2
|
||||||
|
#define NR_RESETS 6
|
||||||
|
|
||||||
|
struct clk_dvp {
|
||||||
|
struct clk_hw_onecell_data *data;
|
||||||
|
struct reset_simple_data reset;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct clk_parent_data clk_dvp_parent = {
|
||||||
|
.index = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int clk_dvp_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct clk_hw_onecell_data *data;
|
||||||
|
struct resource *res;
|
||||||
|
struct clk_dvp *dvp;
|
||||||
|
void __iomem *base;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
dvp = devm_kzalloc(&pdev->dev, sizeof(*dvp), GFP_KERNEL);
|
||||||
|
if (!dvp)
|
||||||
|
return -ENOMEM;
|
||||||
|
platform_set_drvdata(pdev, dvp);
|
||||||
|
|
||||||
|
dvp->data = devm_kzalloc(&pdev->dev,
|
||||||
|
struct_size(dvp->data, hws, NR_CLOCKS),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!dvp->data)
|
||||||
|
return -ENOMEM;
|
||||||
|
data = dvp->data;
|
||||||
|
|
||||||
|
base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
|
||||||
|
if (IS_ERR(base))
|
||||||
|
return PTR_ERR(base);
|
||||||
|
|
||||||
|
dvp->reset.rcdev.owner = THIS_MODULE;
|
||||||
|
dvp->reset.rcdev.nr_resets = NR_RESETS;
|
||||||
|
dvp->reset.rcdev.ops = &reset_simple_ops;
|
||||||
|
dvp->reset.rcdev.of_node = pdev->dev.of_node;
|
||||||
|
dvp->reset.membase = base + DVP_HT_RPI_SW_INIT;
|
||||||
|
spin_lock_init(&dvp->reset.lock);
|
||||||
|
|
||||||
|
ret = devm_reset_controller_register(&pdev->dev, &dvp->reset.rcdev);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
data->hws[0] = clk_hw_register_gate_parent_data(&pdev->dev,
|
||||||
|
"hdmi0-108MHz",
|
||||||
|
&clk_dvp_parent, 0,
|
||||||
|
base + DVP_HT_RPI_MISC_CONFIG, 3,
|
||||||
|
CLK_GATE_SET_TO_DISABLE,
|
||||||
|
&dvp->reset.lock);
|
||||||
|
if (IS_ERR(data->hws[0]))
|
||||||
|
return PTR_ERR(data->hws[0]);
|
||||||
|
|
||||||
|
data->hws[1] = clk_hw_register_gate_parent_data(&pdev->dev,
|
||||||
|
"hdmi1-108MHz",
|
||||||
|
&clk_dvp_parent, 0,
|
||||||
|
base + DVP_HT_RPI_MISC_CONFIG, 4,
|
||||||
|
CLK_GATE_SET_TO_DISABLE,
|
||||||
|
&dvp->reset.lock);
|
||||||
|
if (IS_ERR(data->hws[1])) {
|
||||||
|
ret = PTR_ERR(data->hws[1]);
|
||||||
|
goto unregister_clk0;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->num = NR_CLOCKS;
|
||||||
|
ret = of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_onecell_get,
|
||||||
|
data);
|
||||||
|
if (ret)
|
||||||
|
goto unregister_clk1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
unregister_clk1:
|
||||||
|
clk_hw_unregister_gate(data->hws[1]);
|
||||||
|
|
||||||
|
unregister_clk0:
|
||||||
|
clk_hw_unregister_gate(data->hws[0]);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int clk_dvp_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct clk_dvp *dvp = platform_get_drvdata(pdev);
|
||||||
|
struct clk_hw_onecell_data *data = dvp->data;
|
||||||
|
|
||||||
|
clk_hw_unregister_gate(data->hws[1]);
|
||||||
|
clk_hw_unregister_gate(data->hws[0]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id clk_dvp_dt_ids[] = {
|
||||||
|
{ .compatible = "brcm,brcm2711-dvp", },
|
||||||
|
{ /* sentinel */ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_driver clk_dvp_driver = {
|
||||||
|
.probe = clk_dvp_probe,
|
||||||
|
.remove = clk_dvp_remove,
|
||||||
|
.driver = {
|
||||||
|
.name = "brcm2711-dvp",
|
||||||
|
.of_match_table = clk_dvp_dt_ids,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
module_platform_driver(clk_dvp_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
|
||||||
|
MODULE_DESCRIPTION("BCM2711 DVP clock driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
|
@ -421,6 +421,7 @@ struct bcm2835_pll_data {
|
||||||
u32 reference_enable_mask;
|
u32 reference_enable_mask;
|
||||||
/* Bit in CM_LOCK to indicate when the PLL has locked. */
|
/* Bit in CM_LOCK to indicate when the PLL has locked. */
|
||||||
u32 lock_mask;
|
u32 lock_mask;
|
||||||
|
u32 flags;
|
||||||
|
|
||||||
const struct bcm2835_pll_ana_bits *ana;
|
const struct bcm2835_pll_ana_bits *ana;
|
||||||
|
|
||||||
|
@ -1310,7 +1311,7 @@ static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman,
|
||||||
init.num_parents = 1;
|
init.num_parents = 1;
|
||||||
init.name = pll_data->name;
|
init.name = pll_data->name;
|
||||||
init.ops = &bcm2835_pll_clk_ops;
|
init.ops = &bcm2835_pll_clk_ops;
|
||||||
init.flags = CLK_IGNORE_UNUSED;
|
init.flags = pll_data->flags | CLK_IGNORE_UNUSED;
|
||||||
|
|
||||||
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
|
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
|
||||||
if (!pll)
|
if (!pll)
|
||||||
|
@ -1684,10 +1685,33 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
|
||||||
.fixed_divider = 1,
|
.fixed_divider = 1,
|
||||||
.flags = CLK_SET_RATE_PARENT),
|
.flags = CLK_SET_RATE_PARENT),
|
||||||
|
|
||||||
/*
|
/* PLLB is used for the ARM's clock. */
|
||||||
* PLLB is used for the ARM's clock. Controlled by firmware, see
|
[BCM2835_PLLB] = REGISTER_PLL(
|
||||||
* clk-raspberrypi.c.
|
SOC_ALL,
|
||||||
*/
|
.name = "pllb",
|
||||||
|
.cm_ctrl_reg = CM_PLLB,
|
||||||
|
.a2w_ctrl_reg = A2W_PLLB_CTRL,
|
||||||
|
.frac_reg = A2W_PLLB_FRAC,
|
||||||
|
.ana_reg_base = A2W_PLLB_ANA0,
|
||||||
|
.reference_enable_mask = A2W_XOSC_CTRL_PLLB_ENABLE,
|
||||||
|
.lock_mask = CM_LOCK_FLOCKB,
|
||||||
|
|
||||||
|
.ana = &bcm2835_ana_default,
|
||||||
|
|
||||||
|
.min_rate = 600000000u,
|
||||||
|
.max_rate = 3000000000u,
|
||||||
|
.max_fb_rate = BCM2835_MAX_FB_RATE,
|
||||||
|
.flags = CLK_GET_RATE_NOCACHE),
|
||||||
|
[BCM2835_PLLB_ARM] = REGISTER_PLL_DIV(
|
||||||
|
SOC_ALL,
|
||||||
|
.name = "pllb_arm",
|
||||||
|
.source_pll = "pllb",
|
||||||
|
.cm_reg = CM_PLLB,
|
||||||
|
.a2w_reg = A2W_PLLB_ARM,
|
||||||
|
.load_mask = CM_PLLB_LOADARM,
|
||||||
|
.hold_mask = CM_PLLB_HOLDARM,
|
||||||
|
.fixed_divider = 1,
|
||||||
|
.flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PLLC is the core PLL, used to drive the core VPU clock.
|
* PLLC is the core PLL, used to drive the core VPU clock.
|
||||||
|
|
|
@ -6,6 +6,14 @@
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
|
||||||
|
#include <dt-bindings/clock/bcm3368-clock.h>
|
||||||
|
#include <dt-bindings/clock/bcm6318-clock.h>
|
||||||
|
#include <dt-bindings/clock/bcm6328-clock.h>
|
||||||
|
#include <dt-bindings/clock/bcm6358-clock.h>
|
||||||
|
#include <dt-bindings/clock/bcm6362-clock.h>
|
||||||
|
#include <dt-bindings/clock/bcm6368-clock.h>
|
||||||
|
#include <dt-bindings/clock/bcm63268-clock.h>
|
||||||
|
|
||||||
struct clk_bcm63xx_table_entry {
|
struct clk_bcm63xx_table_entry {
|
||||||
const char * const name;
|
const char * const name;
|
||||||
u8 bit;
|
u8 bit;
|
||||||
|
@ -20,126 +28,458 @@ struct clk_bcm63xx_hw {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct clk_bcm63xx_table_entry bcm3368_clocks[] = {
|
static const struct clk_bcm63xx_table_entry bcm3368_clocks[] = {
|
||||||
{ .name = "mac", .bit = 3, },
|
{
|
||||||
{ .name = "tc", .bit = 5, },
|
.name = "mac",
|
||||||
{ .name = "us_top", .bit = 6, },
|
.bit = BCM3368_CLK_MAC,
|
||||||
{ .name = "ds_top", .bit = 7, },
|
}, {
|
||||||
{ .name = "acm", .bit = 8, },
|
.name = "tc",
|
||||||
{ .name = "spi", .bit = 9, },
|
.bit = BCM3368_CLK_TC,
|
||||||
{ .name = "usbs", .bit = 10, },
|
}, {
|
||||||
{ .name = "bmu", .bit = 11, },
|
.name = "us_top",
|
||||||
{ .name = "pcm", .bit = 12, },
|
.bit = BCM3368_CLK_US_TOP,
|
||||||
{ .name = "ntp", .bit = 13, },
|
}, {
|
||||||
{ .name = "acp_b", .bit = 14, },
|
.name = "ds_top",
|
||||||
{ .name = "acp_a", .bit = 15, },
|
.bit = BCM3368_CLK_DS_TOP,
|
||||||
{ .name = "emusb", .bit = 17, },
|
}, {
|
||||||
{ .name = "enet0", .bit = 18, },
|
.name = "acm",
|
||||||
{ .name = "enet1", .bit = 19, },
|
.bit = BCM3368_CLK_ACM,
|
||||||
{ .name = "usbsu", .bit = 20, },
|
}, {
|
||||||
{ .name = "ephy", .bit = 21, },
|
.name = "spi",
|
||||||
{ },
|
.bit = BCM3368_CLK_SPI,
|
||||||
|
}, {
|
||||||
|
.name = "usbs",
|
||||||
|
.bit = BCM3368_CLK_USBS,
|
||||||
|
}, {
|
||||||
|
.name = "bmu",
|
||||||
|
.bit = BCM3368_CLK_BMU,
|
||||||
|
}, {
|
||||||
|
.name = "pcm",
|
||||||
|
.bit = BCM3368_CLK_PCM,
|
||||||
|
}, {
|
||||||
|
.name = "ntp",
|
||||||
|
.bit = BCM3368_CLK_NTP,
|
||||||
|
}, {
|
||||||
|
.name = "acp_b",
|
||||||
|
.bit = BCM3368_CLK_ACP_B,
|
||||||
|
}, {
|
||||||
|
.name = "acp_a",
|
||||||
|
.bit = BCM3368_CLK_ACP_A,
|
||||||
|
}, {
|
||||||
|
.name = "emusb",
|
||||||
|
.bit = BCM3368_CLK_EMUSB,
|
||||||
|
}, {
|
||||||
|
.name = "enet0",
|
||||||
|
.bit = BCM3368_CLK_ENET0,
|
||||||
|
}, {
|
||||||
|
.name = "enet1",
|
||||||
|
.bit = BCM3368_CLK_ENET1,
|
||||||
|
}, {
|
||||||
|
.name = "usbsu",
|
||||||
|
.bit = BCM3368_CLK_USBSU,
|
||||||
|
}, {
|
||||||
|
.name = "ephy",
|
||||||
|
.bit = BCM3368_CLK_EPHY,
|
||||||
|
}, {
|
||||||
|
/* sentinel */
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct clk_bcm63xx_table_entry bcm6318_clocks[] = {
|
||||||
|
{
|
||||||
|
.name = "adsl_asb",
|
||||||
|
.bit = BCM6318_CLK_ADSL_ASB,
|
||||||
|
}, {
|
||||||
|
.name = "usb_asb",
|
||||||
|
.bit = BCM6318_CLK_USB_ASB,
|
||||||
|
}, {
|
||||||
|
.name = "mips_asb",
|
||||||
|
.bit = BCM6318_CLK_MIPS_ASB,
|
||||||
|
}, {
|
||||||
|
.name = "pcie_asb",
|
||||||
|
.bit = BCM6318_CLK_PCIE_ASB,
|
||||||
|
}, {
|
||||||
|
.name = "phymips_asb",
|
||||||
|
.bit = BCM6318_CLK_PHYMIPS_ASB,
|
||||||
|
}, {
|
||||||
|
.name = "robosw_asb",
|
||||||
|
.bit = BCM6318_CLK_ROBOSW_ASB,
|
||||||
|
}, {
|
||||||
|
.name = "sar_asb",
|
||||||
|
.bit = BCM6318_CLK_SAR_ASB,
|
||||||
|
}, {
|
||||||
|
.name = "sdr_asb",
|
||||||
|
.bit = BCM6318_CLK_SDR_ASB,
|
||||||
|
}, {
|
||||||
|
.name = "swreg_asb",
|
||||||
|
.bit = BCM6318_CLK_SWREG_ASB,
|
||||||
|
}, {
|
||||||
|
.name = "periph_asb",
|
||||||
|
.bit = BCM6318_CLK_PERIPH_ASB,
|
||||||
|
}, {
|
||||||
|
.name = "cpubus160",
|
||||||
|
.bit = BCM6318_CLK_CPUBUS160,
|
||||||
|
}, {
|
||||||
|
.name = "adsl",
|
||||||
|
.bit = BCM6318_CLK_ADSL,
|
||||||
|
}, {
|
||||||
|
.name = "sar125",
|
||||||
|
.bit = BCM6318_CLK_SAR125,
|
||||||
|
}, {
|
||||||
|
.name = "mips",
|
||||||
|
.bit = BCM6318_CLK_MIPS,
|
||||||
|
.flags = CLK_IS_CRITICAL,
|
||||||
|
}, {
|
||||||
|
.name = "pcie",
|
||||||
|
.bit = BCM6318_CLK_PCIE,
|
||||||
|
}, {
|
||||||
|
.name = "robosw250",
|
||||||
|
.bit = BCM6318_CLK_ROBOSW250,
|
||||||
|
}, {
|
||||||
|
.name = "robosw025",
|
||||||
|
.bit = BCM6318_CLK_ROBOSW025,
|
||||||
|
}, {
|
||||||
|
.name = "sdr",
|
||||||
|
.bit = BCM6318_CLK_SDR,
|
||||||
|
.flags = CLK_IS_CRITICAL,
|
||||||
|
}, {
|
||||||
|
.name = "usbd",
|
||||||
|
.bit = BCM6318_CLK_USBD,
|
||||||
|
}, {
|
||||||
|
.name = "hsspi",
|
||||||
|
.bit = BCM6318_CLK_HSSPI,
|
||||||
|
}, {
|
||||||
|
.name = "pcie25",
|
||||||
|
.bit = BCM6318_CLK_PCIE25,
|
||||||
|
}, {
|
||||||
|
.name = "phymips",
|
||||||
|
.bit = BCM6318_CLK_PHYMIPS,
|
||||||
|
}, {
|
||||||
|
.name = "afe",
|
||||||
|
.bit = BCM6318_CLK_AFE,
|
||||||
|
}, {
|
||||||
|
.name = "qproc",
|
||||||
|
.bit = BCM6318_CLK_QPROC,
|
||||||
|
}, {
|
||||||
|
/* sentinel */
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct clk_bcm63xx_table_entry bcm6318_ubus_clocks[] = {
|
||||||
|
{
|
||||||
|
.name = "adsl-ubus",
|
||||||
|
.bit = BCM6318_UCLK_ADSL,
|
||||||
|
}, {
|
||||||
|
.name = "arb-ubus",
|
||||||
|
.bit = BCM6318_UCLK_ARB,
|
||||||
|
.flags = CLK_IS_CRITICAL,
|
||||||
|
}, {
|
||||||
|
.name = "mips-ubus",
|
||||||
|
.bit = BCM6318_UCLK_MIPS,
|
||||||
|
.flags = CLK_IS_CRITICAL,
|
||||||
|
}, {
|
||||||
|
.name = "pcie-ubus",
|
||||||
|
.bit = BCM6318_UCLK_PCIE,
|
||||||
|
}, {
|
||||||
|
.name = "periph-ubus",
|
||||||
|
.bit = BCM6318_UCLK_PERIPH,
|
||||||
|
.flags = CLK_IS_CRITICAL,
|
||||||
|
}, {
|
||||||
|
.name = "phymips-ubus",
|
||||||
|
.bit = BCM6318_UCLK_PHYMIPS,
|
||||||
|
}, {
|
||||||
|
.name = "robosw-ubus",
|
||||||
|
.bit = BCM6318_UCLK_ROBOSW,
|
||||||
|
}, {
|
||||||
|
.name = "sar-ubus",
|
||||||
|
.bit = BCM6318_UCLK_SAR,
|
||||||
|
}, {
|
||||||
|
.name = "sdr-ubus",
|
||||||
|
.bit = BCM6318_UCLK_SDR,
|
||||||
|
}, {
|
||||||
|
.name = "usb-ubus",
|
||||||
|
.bit = BCM6318_UCLK_USB,
|
||||||
|
}, {
|
||||||
|
/* sentinel */
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct clk_bcm63xx_table_entry bcm6328_clocks[] = {
|
static const struct clk_bcm63xx_table_entry bcm6328_clocks[] = {
|
||||||
{ .name = "phy_mips", .bit = 0, },
|
{
|
||||||
{ .name = "adsl_qproc", .bit = 1, },
|
.name = "phy_mips",
|
||||||
{ .name = "adsl_afe", .bit = 2, },
|
.bit = BCM6328_CLK_PHYMIPS,
|
||||||
{ .name = "adsl", .bit = 3, },
|
}, {
|
||||||
{ .name = "mips", .bit = 4, .flags = CLK_IS_CRITICAL, },
|
.name = "adsl_qproc",
|
||||||
{ .name = "sar", .bit = 5, },
|
.bit = BCM6328_CLK_ADSL_QPROC,
|
||||||
{ .name = "pcm", .bit = 6, },
|
}, {
|
||||||
{ .name = "usbd", .bit = 7, },
|
.name = "adsl_afe",
|
||||||
{ .name = "usbh", .bit = 8, },
|
.bit = BCM6328_CLK_ADSL_AFE,
|
||||||
{ .name = "hsspi", .bit = 9, },
|
}, {
|
||||||
{ .name = "pcie", .bit = 10, },
|
.name = "adsl",
|
||||||
{ .name = "robosw", .bit = 11, },
|
.bit = BCM6328_CLK_ADSL,
|
||||||
{ },
|
}, {
|
||||||
|
.name = "mips",
|
||||||
|
.bit = BCM6328_CLK_MIPS,
|
||||||
|
.flags = CLK_IS_CRITICAL,
|
||||||
|
}, {
|
||||||
|
.name = "sar",
|
||||||
|
.bit = BCM6328_CLK_SAR,
|
||||||
|
}, {
|
||||||
|
.name = "pcm",
|
||||||
|
.bit = BCM6328_CLK_PCM,
|
||||||
|
}, {
|
||||||
|
.name = "usbd",
|
||||||
|
.bit = BCM6328_CLK_USBD,
|
||||||
|
}, {
|
||||||
|
.name = "usbh",
|
||||||
|
.bit = BCM6328_CLK_USBH,
|
||||||
|
}, {
|
||||||
|
.name = "hsspi",
|
||||||
|
.bit = BCM6328_CLK_HSSPI,
|
||||||
|
}, {
|
||||||
|
.name = "pcie",
|
||||||
|
.bit = BCM6328_CLK_PCIE,
|
||||||
|
}, {
|
||||||
|
.name = "robosw",
|
||||||
|
.bit = BCM6328_CLK_ROBOSW,
|
||||||
|
}, {
|
||||||
|
/* sentinel */
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct clk_bcm63xx_table_entry bcm6358_clocks[] = {
|
static const struct clk_bcm63xx_table_entry bcm6358_clocks[] = {
|
||||||
{ .name = "enet", .bit = 4, },
|
{
|
||||||
{ .name = "adslphy", .bit = 5, },
|
.name = "enet",
|
||||||
{ .name = "pcm", .bit = 8, },
|
.bit = BCM6358_CLK_ENET,
|
||||||
{ .name = "spi", .bit = 9, },
|
}, {
|
||||||
{ .name = "usbs", .bit = 10, },
|
.name = "adslphy",
|
||||||
{ .name = "sar", .bit = 11, },
|
.bit = BCM6358_CLK_ADSLPHY,
|
||||||
{ .name = "emusb", .bit = 17, },
|
}, {
|
||||||
{ .name = "enet0", .bit = 18, },
|
.name = "pcm",
|
||||||
{ .name = "enet1", .bit = 19, },
|
.bit = BCM6358_CLK_PCM,
|
||||||
{ .name = "usbsu", .bit = 20, },
|
}, {
|
||||||
{ .name = "ephy", .bit = 21, },
|
.name = "spi",
|
||||||
{ },
|
.bit = BCM6358_CLK_SPI,
|
||||||
|
}, {
|
||||||
|
.name = "usbs",
|
||||||
|
.bit = BCM6358_CLK_USBS,
|
||||||
|
}, {
|
||||||
|
.name = "sar",
|
||||||
|
.bit = BCM6358_CLK_SAR,
|
||||||
|
}, {
|
||||||
|
.name = "emusb",
|
||||||
|
.bit = BCM6358_CLK_EMUSB,
|
||||||
|
}, {
|
||||||
|
.name = "enet0",
|
||||||
|
.bit = BCM6358_CLK_ENET0,
|
||||||
|
}, {
|
||||||
|
.name = "enet1",
|
||||||
|
.bit = BCM6358_CLK_ENET1,
|
||||||
|
}, {
|
||||||
|
.name = "usbsu",
|
||||||
|
.bit = BCM6358_CLK_USBSU,
|
||||||
|
}, {
|
||||||
|
.name = "ephy",
|
||||||
|
.bit = BCM6358_CLK_EPHY,
|
||||||
|
}, {
|
||||||
|
/* sentinel */
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct clk_bcm63xx_table_entry bcm6362_clocks[] = {
|
static const struct clk_bcm63xx_table_entry bcm6362_clocks[] = {
|
||||||
{ .name = "adsl_qproc", .bit = 1, },
|
{
|
||||||
{ .name = "adsl_afe", .bit = 2, },
|
.name = "adsl_qproc",
|
||||||
{ .name = "adsl", .bit = 3, },
|
.bit = BCM6362_CLK_ADSL_QPROC,
|
||||||
{ .name = "mips", .bit = 4, .flags = CLK_IS_CRITICAL, },
|
}, {
|
||||||
{ .name = "wlan_ocp", .bit = 5, },
|
.name = "adsl_afe",
|
||||||
{ .name = "swpkt_usb", .bit = 7, },
|
.bit = BCM6362_CLK_ADSL_AFE,
|
||||||
{ .name = "swpkt_sar", .bit = 8, },
|
}, {
|
||||||
{ .name = "sar", .bit = 9, },
|
.name = "adsl",
|
||||||
{ .name = "robosw", .bit = 10, },
|
.bit = BCM6362_CLK_ADSL,
|
||||||
{ .name = "pcm", .bit = 11, },
|
}, {
|
||||||
{ .name = "usbd", .bit = 12, },
|
.name = "mips",
|
||||||
{ .name = "usbh", .bit = 13, },
|
.bit = BCM6362_CLK_MIPS,
|
||||||
{ .name = "ipsec", .bit = 14, },
|
.flags = CLK_IS_CRITICAL,
|
||||||
{ .name = "spi", .bit = 15, },
|
}, {
|
||||||
{ .name = "hsspi", .bit = 16, },
|
.name = "wlan_ocp",
|
||||||
{ .name = "pcie", .bit = 17, },
|
.bit = BCM6362_CLK_WLAN_OCP,
|
||||||
{ .name = "fap", .bit = 18, },
|
}, {
|
||||||
{ .name = "phymips", .bit = 19, },
|
.name = "swpkt_usb",
|
||||||
{ .name = "nand", .bit = 20, },
|
.bit = BCM6362_CLK_SWPKT_USB,
|
||||||
{ },
|
}, {
|
||||||
|
.name = "swpkt_sar",
|
||||||
|
.bit = BCM6362_CLK_SWPKT_SAR,
|
||||||
|
}, {
|
||||||
|
.name = "sar",
|
||||||
|
.bit = BCM6362_CLK_SAR,
|
||||||
|
}, {
|
||||||
|
.name = "robosw",
|
||||||
|
.bit = BCM6362_CLK_ROBOSW,
|
||||||
|
}, {
|
||||||
|
.name = "pcm",
|
||||||
|
.bit = BCM6362_CLK_PCM,
|
||||||
|
}, {
|
||||||
|
.name = "usbd",
|
||||||
|
.bit = BCM6362_CLK_USBD,
|
||||||
|
}, {
|
||||||
|
.name = "usbh",
|
||||||
|
.bit = BCM6362_CLK_USBH,
|
||||||
|
}, {
|
||||||
|
.name = "ipsec",
|
||||||
|
.bit = BCM6362_CLK_IPSEC,
|
||||||
|
}, {
|
||||||
|
.name = "spi",
|
||||||
|
.bit = BCM6362_CLK_SPI,
|
||||||
|
}, {
|
||||||
|
.name = "hsspi",
|
||||||
|
.bit = BCM6362_CLK_HSSPI,
|
||||||
|
}, {
|
||||||
|
.name = "pcie",
|
||||||
|
.bit = BCM6362_CLK_PCIE,
|
||||||
|
}, {
|
||||||
|
.name = "fap",
|
||||||
|
.bit = BCM6362_CLK_FAP,
|
||||||
|
}, {
|
||||||
|
.name = "phymips",
|
||||||
|
.bit = BCM6362_CLK_PHYMIPS,
|
||||||
|
}, {
|
||||||
|
.name = "nand",
|
||||||
|
.bit = BCM6362_CLK_NAND,
|
||||||
|
}, {
|
||||||
|
/* sentinel */
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct clk_bcm63xx_table_entry bcm6368_clocks[] = {
|
static const struct clk_bcm63xx_table_entry bcm6368_clocks[] = {
|
||||||
{ .name = "vdsl_qproc", .bit = 2, },
|
{
|
||||||
{ .name = "vdsl_afe", .bit = 3, },
|
.name = "vdsl_qproc",
|
||||||
{ .name = "vdsl_bonding", .bit = 4, },
|
.bit = BCM6368_CLK_VDSL_QPROC,
|
||||||
{ .name = "vdsl", .bit = 5, },
|
}, {
|
||||||
{ .name = "phymips", .bit = 6, },
|
.name = "vdsl_afe",
|
||||||
{ .name = "swpkt_usb", .bit = 7, },
|
.bit = BCM6368_CLK_VDSL_AFE,
|
||||||
{ .name = "swpkt_sar", .bit = 8, },
|
}, {
|
||||||
{ .name = "spi", .bit = 9, },
|
.name = "vdsl_bonding",
|
||||||
{ .name = "usbd", .bit = 10, },
|
.bit = BCM6368_CLK_VDSL_BONDING,
|
||||||
{ .name = "sar", .bit = 11, },
|
}, {
|
||||||
{ .name = "robosw", .bit = 12, },
|
.name = "vdsl",
|
||||||
{ .name = "utopia", .bit = 13, },
|
.bit = BCM6368_CLK_VDSL,
|
||||||
{ .name = "pcm", .bit = 14, },
|
}, {
|
||||||
{ .name = "usbh", .bit = 15, },
|
.name = "phymips",
|
||||||
{ .name = "disable_gless", .bit = 16, },
|
.bit = BCM6368_CLK_PHYMIPS,
|
||||||
{ .name = "nand", .bit = 17, },
|
}, {
|
||||||
{ .name = "ipsec", .bit = 18, },
|
.name = "swpkt_usb",
|
||||||
{ },
|
.bit = BCM6368_CLK_SWPKT_USB,
|
||||||
|
}, {
|
||||||
|
.name = "swpkt_sar",
|
||||||
|
.bit = BCM6368_CLK_SWPKT_SAR,
|
||||||
|
}, {
|
||||||
|
.name = "spi",
|
||||||
|
.bit = BCM6368_CLK_SPI,
|
||||||
|
}, {
|
||||||
|
.name = "usbd",
|
||||||
|
.bit = BCM6368_CLK_USBD,
|
||||||
|
}, {
|
||||||
|
.name = "sar",
|
||||||
|
.bit = BCM6368_CLK_SAR,
|
||||||
|
}, {
|
||||||
|
.name = "robosw",
|
||||||
|
.bit = BCM6368_CLK_ROBOSW,
|
||||||
|
}, {
|
||||||
|
.name = "utopia",
|
||||||
|
.bit = BCM6368_CLK_UTOPIA,
|
||||||
|
}, {
|
||||||
|
.name = "pcm",
|
||||||
|
.bit = BCM6368_CLK_PCM,
|
||||||
|
}, {
|
||||||
|
.name = "usbh",
|
||||||
|
.bit = BCM6368_CLK_USBH,
|
||||||
|
}, {
|
||||||
|
.name = "disable_gless",
|
||||||
|
.bit = BCM6368_CLK_DIS_GLESS,
|
||||||
|
}, {
|
||||||
|
.name = "nand",
|
||||||
|
.bit = BCM6368_CLK_NAND,
|
||||||
|
}, {
|
||||||
|
.name = "ipsec",
|
||||||
|
.bit = BCM6368_CLK_IPSEC,
|
||||||
|
}, {
|
||||||
|
/* sentinel */
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct clk_bcm63xx_table_entry bcm63268_clocks[] = {
|
static const struct clk_bcm63xx_table_entry bcm63268_clocks[] = {
|
||||||
{ .name = "disable_gless", .bit = 0, },
|
{
|
||||||
{ .name = "vdsl_qproc", .bit = 1, },
|
.name = "disable_gless",
|
||||||
{ .name = "vdsl_afe", .bit = 2, },
|
.bit = BCM63268_CLK_DIS_GLESS,
|
||||||
{ .name = "vdsl", .bit = 3, },
|
}, {
|
||||||
{ .name = "mips", .bit = 4, .flags = CLK_IS_CRITICAL, },
|
.name = "vdsl_qproc",
|
||||||
{ .name = "wlan_ocp", .bit = 5, },
|
.bit = BCM63268_CLK_VDSL_QPROC,
|
||||||
{ .name = "dect", .bit = 6, },
|
}, {
|
||||||
{ .name = "fap0", .bit = 7, },
|
.name = "vdsl_afe",
|
||||||
{ .name = "fap1", .bit = 8, },
|
.bit = BCM63268_CLK_VDSL_AFE,
|
||||||
{ .name = "sar", .bit = 9, },
|
}, {
|
||||||
{ .name = "robosw", .bit = 10, },
|
.name = "vdsl",
|
||||||
{ .name = "pcm", .bit = 11, },
|
.bit = BCM63268_CLK_VDSL,
|
||||||
{ .name = "usbd", .bit = 12, },
|
}, {
|
||||||
{ .name = "usbh", .bit = 13, },
|
.name = "mips",
|
||||||
{ .name = "ipsec", .bit = 14, },
|
.bit = BCM63268_CLK_MIPS,
|
||||||
{ .name = "spi", .bit = 15, },
|
.flags = CLK_IS_CRITICAL,
|
||||||
{ .name = "hsspi", .bit = 16, },
|
}, {
|
||||||
{ .name = "pcie", .bit = 17, },
|
.name = "wlan_ocp",
|
||||||
{ .name = "phymips", .bit = 18, },
|
.bit = BCM63268_CLK_WLAN_OCP,
|
||||||
{ .name = "gmac", .bit = 19, },
|
}, {
|
||||||
{ .name = "nand", .bit = 20, },
|
.name = "dect",
|
||||||
{ .name = "tbus", .bit = 27, },
|
.bit = BCM63268_CLK_DECT,
|
||||||
{ .name = "robosw250", .bit = 31, },
|
}, {
|
||||||
{ },
|
.name = "fap0",
|
||||||
|
.bit = BCM63268_CLK_FAP0,
|
||||||
|
}, {
|
||||||
|
.name = "fap1",
|
||||||
|
.bit = BCM63268_CLK_FAP1,
|
||||||
|
}, {
|
||||||
|
.name = "sar",
|
||||||
|
.bit = BCM63268_CLK_SAR,
|
||||||
|
}, {
|
||||||
|
.name = "robosw",
|
||||||
|
.bit = BCM63268_CLK_ROBOSW,
|
||||||
|
}, {
|
||||||
|
.name = "pcm",
|
||||||
|
.bit = BCM63268_CLK_PCM,
|
||||||
|
}, {
|
||||||
|
.name = "usbd",
|
||||||
|
.bit = BCM63268_CLK_USBD,
|
||||||
|
}, {
|
||||||
|
.name = "usbh",
|
||||||
|
.bit = BCM63268_CLK_USBH,
|
||||||
|
}, {
|
||||||
|
.name = "ipsec",
|
||||||
|
.bit = BCM63268_CLK_IPSEC,
|
||||||
|
}, {
|
||||||
|
.name = "spi",
|
||||||
|
.bit = BCM63268_CLK_SPI,
|
||||||
|
}, {
|
||||||
|
.name = "hsspi",
|
||||||
|
.bit = BCM63268_CLK_HSSPI,
|
||||||
|
}, {
|
||||||
|
.name = "pcie",
|
||||||
|
.bit = BCM63268_CLK_PCIE,
|
||||||
|
}, {
|
||||||
|
.name = "phymips",
|
||||||
|
.bit = BCM63268_CLK_PHYMIPS,
|
||||||
|
}, {
|
||||||
|
.name = "gmac",
|
||||||
|
.bit = BCM63268_CLK_GMAC,
|
||||||
|
}, {
|
||||||
|
.name = "nand",
|
||||||
|
.bit = BCM63268_CLK_NAND,
|
||||||
|
}, {
|
||||||
|
.name = "tbus",
|
||||||
|
.bit = BCM63268_CLK_TBUS,
|
||||||
|
}, {
|
||||||
|
.name = "robosw250",
|
||||||
|
.bit = BCM63268_CLK_ROBOSW250,
|
||||||
|
}, {
|
||||||
|
/* sentinel */
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static int clk_bcm63xx_probe(struct platform_device *pdev)
|
static int clk_bcm63xx_probe(struct platform_device *pdev)
|
||||||
|
@ -155,6 +495,7 @@ static int clk_bcm63xx_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
for (entry = table; entry->name; entry++)
|
for (entry = table; entry->name; entry++)
|
||||||
maxbit = max_t(u8, maxbit, entry->bit);
|
maxbit = max_t(u8, maxbit, entry->bit);
|
||||||
|
maxbit++;
|
||||||
|
|
||||||
hw = devm_kzalloc(&pdev->dev, struct_size(hw, data.hws, maxbit),
|
hw = devm_kzalloc(&pdev->dev, struct_size(hw, data.hws, maxbit),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
|
@ -217,6 +558,8 @@ static int clk_bcm63xx_remove(struct platform_device *pdev)
|
||||||
|
|
||||||
static const struct of_device_id clk_bcm63xx_dt_ids[] = {
|
static const struct of_device_id clk_bcm63xx_dt_ids[] = {
|
||||||
{ .compatible = "brcm,bcm3368-clocks", .data = &bcm3368_clocks, },
|
{ .compatible = "brcm,bcm3368-clocks", .data = &bcm3368_clocks, },
|
||||||
|
{ .compatible = "brcm,bcm6318-clocks", .data = &bcm6318_clocks, },
|
||||||
|
{ .compatible = "brcm,bcm6318-ubus-clocks", .data = &bcm6318_ubus_clocks, },
|
||||||
{ .compatible = "brcm,bcm6328-clocks", .data = &bcm6328_clocks, },
|
{ .compatible = "brcm,bcm6328-clocks", .data = &bcm6328_clocks, },
|
||||||
{ .compatible = "brcm,bcm6358-clocks", .data = &bcm6358_clocks, },
|
{ .compatible = "brcm,bcm6358-clocks", .data = &bcm6358_clocks, },
|
||||||
{ .compatible = "brcm,bcm6362-clocks", .data = &bcm6362_clocks, },
|
{ .compatible = "brcm,bcm6362-clocks", .data = &bcm6362_clocks, },
|
||||||
|
|
|
@ -18,30 +18,56 @@
|
||||||
|
|
||||||
#include <soc/bcm2835/raspberrypi-firmware.h>
|
#include <soc/bcm2835/raspberrypi-firmware.h>
|
||||||
|
|
||||||
#define RPI_FIRMWARE_ARM_CLK_ID 0x00000003
|
enum rpi_firmware_clk_id {
|
||||||
|
RPI_FIRMWARE_EMMC_CLK_ID = 1,
|
||||||
|
RPI_FIRMWARE_UART_CLK_ID,
|
||||||
|
RPI_FIRMWARE_ARM_CLK_ID,
|
||||||
|
RPI_FIRMWARE_CORE_CLK_ID,
|
||||||
|
RPI_FIRMWARE_V3D_CLK_ID,
|
||||||
|
RPI_FIRMWARE_H264_CLK_ID,
|
||||||
|
RPI_FIRMWARE_ISP_CLK_ID,
|
||||||
|
RPI_FIRMWARE_SDRAM_CLK_ID,
|
||||||
|
RPI_FIRMWARE_PIXEL_CLK_ID,
|
||||||
|
RPI_FIRMWARE_PWM_CLK_ID,
|
||||||
|
RPI_FIRMWARE_HEVC_CLK_ID,
|
||||||
|
RPI_FIRMWARE_EMMC2_CLK_ID,
|
||||||
|
RPI_FIRMWARE_M2MC_CLK_ID,
|
||||||
|
RPI_FIRMWARE_PIXEL_BVB_CLK_ID,
|
||||||
|
RPI_FIRMWARE_NUM_CLK_ID,
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *rpi_firmware_clk_names[] = {
|
||||||
|
[RPI_FIRMWARE_EMMC_CLK_ID] = "emmc",
|
||||||
|
[RPI_FIRMWARE_UART_CLK_ID] = "uart",
|
||||||
|
[RPI_FIRMWARE_ARM_CLK_ID] = "arm",
|
||||||
|
[RPI_FIRMWARE_CORE_CLK_ID] = "core",
|
||||||
|
[RPI_FIRMWARE_V3D_CLK_ID] = "v3d",
|
||||||
|
[RPI_FIRMWARE_H264_CLK_ID] = "h264",
|
||||||
|
[RPI_FIRMWARE_ISP_CLK_ID] = "isp",
|
||||||
|
[RPI_FIRMWARE_SDRAM_CLK_ID] = "sdram",
|
||||||
|
[RPI_FIRMWARE_PIXEL_CLK_ID] = "pixel",
|
||||||
|
[RPI_FIRMWARE_PWM_CLK_ID] = "pwm",
|
||||||
|
[RPI_FIRMWARE_HEVC_CLK_ID] = "hevc",
|
||||||
|
[RPI_FIRMWARE_EMMC2_CLK_ID] = "emmc2",
|
||||||
|
[RPI_FIRMWARE_M2MC_CLK_ID] = "m2mc",
|
||||||
|
[RPI_FIRMWARE_PIXEL_BVB_CLK_ID] = "pixel-bvb",
|
||||||
|
};
|
||||||
|
|
||||||
#define RPI_FIRMWARE_STATE_ENABLE_BIT BIT(0)
|
#define RPI_FIRMWARE_STATE_ENABLE_BIT BIT(0)
|
||||||
#define RPI_FIRMWARE_STATE_WAIT_BIT BIT(1)
|
#define RPI_FIRMWARE_STATE_WAIT_BIT BIT(1)
|
||||||
|
|
||||||
/*
|
|
||||||
* Even though the firmware interface alters 'pllb' the frequencies are
|
|
||||||
* provided as per 'pllb_arm'. We need to scale before passing them trough.
|
|
||||||
*/
|
|
||||||
#define RPI_FIRMWARE_PLLB_ARM_DIV_RATE 2
|
|
||||||
|
|
||||||
#define A2W_PLL_FRAC_BITS 20
|
|
||||||
|
|
||||||
struct raspberrypi_clk {
|
struct raspberrypi_clk {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct rpi_firmware *firmware;
|
struct rpi_firmware *firmware;
|
||||||
struct platform_device *cpufreq;
|
struct platform_device *cpufreq;
|
||||||
|
};
|
||||||
|
|
||||||
unsigned long min_rate;
|
struct raspberrypi_clk_data {
|
||||||
unsigned long max_rate;
|
struct clk_hw hw;
|
||||||
|
|
||||||
struct clk_hw pllb;
|
unsigned int id;
|
||||||
struct clk_hw *pllb_arm;
|
|
||||||
struct clk_lookup *pllb_arm_lookup;
|
struct raspberrypi_clk *rpi;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -64,11 +90,12 @@ struct raspberrypi_firmware_prop {
|
||||||
__le32 disable_turbo;
|
__le32 disable_turbo;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
static int raspberrypi_clock_property(struct rpi_firmware *firmware, u32 tag,
|
static int raspberrypi_clock_property(struct rpi_firmware *firmware,
|
||||||
u32 clk, u32 *val)
|
const struct raspberrypi_clk_data *data,
|
||||||
|
u32 tag, u32 *val)
|
||||||
{
|
{
|
||||||
struct raspberrypi_firmware_prop msg = {
|
struct raspberrypi_firmware_prop msg = {
|
||||||
.id = cpu_to_le32(clk),
|
.id = cpu_to_le32(data->id),
|
||||||
.val = cpu_to_le32(*val),
|
.val = cpu_to_le32(*val),
|
||||||
.disable_turbo = cpu_to_le32(1),
|
.disable_turbo = cpu_to_le32(1),
|
||||||
};
|
};
|
||||||
|
@ -83,16 +110,16 @@ static int raspberrypi_clock_property(struct rpi_firmware *firmware, u32 tag,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int raspberrypi_fw_pll_is_on(struct clk_hw *hw)
|
static int raspberrypi_fw_is_prepared(struct clk_hw *hw)
|
||||||
{
|
{
|
||||||
struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
|
struct raspberrypi_clk_data *data =
|
||||||
pllb);
|
container_of(hw, struct raspberrypi_clk_data, hw);
|
||||||
|
struct raspberrypi_clk *rpi = data->rpi;
|
||||||
u32 val = 0;
|
u32 val = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = raspberrypi_clock_property(rpi->firmware,
|
ret = raspberrypi_clock_property(rpi->firmware, data,
|
||||||
RPI_FIRMWARE_GET_CLOCK_STATE,
|
RPI_FIRMWARE_GET_CLOCK_STATE, &val);
|
||||||
RPI_FIRMWARE_ARM_CLK_ID, &val);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -100,36 +127,34 @@ static int raspberrypi_fw_pll_is_on(struct clk_hw *hw)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw,
|
static unsigned long raspberrypi_fw_get_rate(struct clk_hw *hw,
|
||||||
unsigned long parent_rate)
|
unsigned long parent_rate)
|
||||||
{
|
{
|
||||||
struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
|
struct raspberrypi_clk_data *data =
|
||||||
pllb);
|
container_of(hw, struct raspberrypi_clk_data, hw);
|
||||||
|
struct raspberrypi_clk *rpi = data->rpi;
|
||||||
u32 val = 0;
|
u32 val = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = raspberrypi_clock_property(rpi->firmware,
|
ret = raspberrypi_clock_property(rpi->firmware, data,
|
||||||
RPI_FIRMWARE_GET_CLOCK_RATE,
|
RPI_FIRMWARE_GET_CLOCK_RATE, &val);
|
||||||
RPI_FIRMWARE_ARM_CLK_ID,
|
|
||||||
&val);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return val * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
static int raspberrypi_fw_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
unsigned long parent_rate)
|
unsigned long parent_rate)
|
||||||
{
|
{
|
||||||
struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
|
struct raspberrypi_clk_data *data =
|
||||||
pllb);
|
container_of(hw, struct raspberrypi_clk_data, hw);
|
||||||
u32 new_rate = rate / RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
|
struct raspberrypi_clk *rpi = data->rpi;
|
||||||
|
u32 _rate = rate;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = raspberrypi_clock_property(rpi->firmware,
|
ret = raspberrypi_clock_property(rpi->firmware, data,
|
||||||
RPI_FIRMWARE_SET_CLOCK_RATE,
|
RPI_FIRMWARE_SET_CLOCK_RATE, &_rate);
|
||||||
RPI_FIRMWARE_ARM_CLK_ID,
|
|
||||||
&new_rate);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d",
|
dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d",
|
||||||
clk_hw_get_name(hw), ret);
|
clk_hw_get_name(hw), ret);
|
||||||
|
@ -137,111 +162,128 @@ static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static int raspberrypi_fw_dumb_determine_rate(struct clk_hw *hw,
|
||||||
* Sadly there is no firmware rate rounding interface. We borrowed it from
|
struct clk_rate_request *req)
|
||||||
* clk-bcm2835.
|
|
||||||
*/
|
|
||||||
static int raspberrypi_pll_determine_rate(struct clk_hw *hw,
|
|
||||||
struct clk_rate_request *req)
|
|
||||||
{
|
{
|
||||||
struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
|
/*
|
||||||
pllb);
|
* The firmware will do the rounding but that isn't part of
|
||||||
u64 div, final_rate;
|
* the interface with the firmware, so we just do our best
|
||||||
u32 ndiv, fdiv;
|
* here.
|
||||||
|
*/
|
||||||
/* We can't use req->rate directly as it would overflow */
|
req->rate = clamp(req->rate, req->min_rate, req->max_rate);
|
||||||
final_rate = clamp(req->rate, rpi->min_rate, rpi->max_rate);
|
|
||||||
|
|
||||||
div = (u64)final_rate << A2W_PLL_FRAC_BITS;
|
|
||||||
do_div(div, req->best_parent_rate);
|
|
||||||
|
|
||||||
ndiv = div >> A2W_PLL_FRAC_BITS;
|
|
||||||
fdiv = div & ((1 << A2W_PLL_FRAC_BITS) - 1);
|
|
||||||
|
|
||||||
final_rate = ((u64)req->best_parent_rate *
|
|
||||||
((ndiv << A2W_PLL_FRAC_BITS) + fdiv));
|
|
||||||
|
|
||||||
req->rate = final_rate >> A2W_PLL_FRAC_BITS;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct clk_ops raspberrypi_firmware_pll_clk_ops = {
|
static const struct clk_ops raspberrypi_firmware_clk_ops = {
|
||||||
.is_prepared = raspberrypi_fw_pll_is_on,
|
.is_prepared = raspberrypi_fw_is_prepared,
|
||||||
.recalc_rate = raspberrypi_fw_pll_get_rate,
|
.recalc_rate = raspberrypi_fw_get_rate,
|
||||||
.set_rate = raspberrypi_fw_pll_set_rate,
|
.determine_rate = raspberrypi_fw_dumb_determine_rate,
|
||||||
.determine_rate = raspberrypi_pll_determine_rate,
|
.set_rate = raspberrypi_fw_set_rate,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi)
|
static struct clk_hw *raspberrypi_clk_register(struct raspberrypi_clk *rpi,
|
||||||
|
unsigned int parent,
|
||||||
|
unsigned int id)
|
||||||
{
|
{
|
||||||
u32 min_rate = 0, max_rate = 0;
|
struct raspberrypi_clk_data *data;
|
||||||
struct clk_init_data init;
|
struct clk_init_data init = {};
|
||||||
|
u32 min_rate, max_rate;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memset(&init, 0, sizeof(init));
|
data = devm_kzalloc(rpi->dev, sizeof(*data), GFP_KERNEL);
|
||||||
|
if (!data)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
data->rpi = rpi;
|
||||||
|
data->id = id;
|
||||||
|
|
||||||
/* All of the PLLs derive from the external oscillator. */
|
init.name = devm_kasprintf(rpi->dev, GFP_KERNEL,
|
||||||
init.parent_names = (const char *[]){ "osc" };
|
"fw-clk-%s",
|
||||||
init.num_parents = 1;
|
rpi_firmware_clk_names[id]);
|
||||||
init.name = "pllb";
|
init.ops = &raspberrypi_firmware_clk_ops;
|
||||||
init.ops = &raspberrypi_firmware_pll_clk_ops;
|
init.flags = CLK_GET_RATE_NOCACHE;
|
||||||
init.flags = CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED;
|
|
||||||
|
|
||||||
/* Get min & max rates set by the firmware */
|
data->hw.init = &init;
|
||||||
ret = raspberrypi_clock_property(rpi->firmware,
|
|
||||||
|
ret = raspberrypi_clock_property(rpi->firmware, data,
|
||||||
RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
|
RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
|
||||||
RPI_FIRMWARE_ARM_CLK_ID,
|
|
||||||
&min_rate);
|
&min_rate);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(rpi->dev, "Failed to get %s min freq: %d\n",
|
dev_err(rpi->dev, "Failed to get clock %d min freq: %d",
|
||||||
init.name, ret);
|
id, ret);
|
||||||
return ret;
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = raspberrypi_clock_property(rpi->firmware,
|
ret = raspberrypi_clock_property(rpi->firmware, data,
|
||||||
RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
|
RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
|
||||||
RPI_FIRMWARE_ARM_CLK_ID,
|
|
||||||
&max_rate);
|
&max_rate);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(rpi->dev, "Failed to get %s max freq: %d\n",
|
dev_err(rpi->dev, "Failed to get clock %d max freq: %d\n",
|
||||||
init.name, ret);
|
id, ret);
|
||||||
return ret;
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!min_rate || !max_rate) {
|
ret = devm_clk_hw_register(rpi->dev, &data->hw);
|
||||||
dev_err(rpi->dev, "Unexpected frequency range: min %u, max %u\n",
|
if (ret)
|
||||||
min_rate, max_rate);
|
return ERR_PTR(ret);
|
||||||
return -EINVAL;
|
|
||||||
|
clk_hw_set_rate_range(&data->hw, min_rate, max_rate);
|
||||||
|
|
||||||
|
if (id == RPI_FIRMWARE_ARM_CLK_ID) {
|
||||||
|
ret = devm_clk_hw_register_clkdev(rpi->dev, &data->hw,
|
||||||
|
NULL, "cpu0");
|
||||||
|
if (ret) {
|
||||||
|
dev_err(rpi->dev, "Failed to initialize clkdev\n");
|
||||||
|
return ERR_PTR(ret);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_info(rpi->dev, "CPU frequency range: min %u, max %u\n",
|
return &data->hw;
|
||||||
min_rate, max_rate);
|
|
||||||
|
|
||||||
rpi->min_rate = min_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
|
|
||||||
rpi->max_rate = max_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
|
|
||||||
|
|
||||||
rpi->pllb.init = &init;
|
|
||||||
|
|
||||||
return devm_clk_hw_register(rpi->dev, &rpi->pllb);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi)
|
struct rpi_firmware_get_clocks_response {
|
||||||
{
|
u32 parent;
|
||||||
rpi->pllb_arm = clk_hw_register_fixed_factor(rpi->dev,
|
u32 id;
|
||||||
"pllb_arm", "pllb",
|
};
|
||||||
CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
|
|
||||||
1, 2);
|
|
||||||
if (IS_ERR(rpi->pllb_arm)) {
|
|
||||||
dev_err(rpi->dev, "Failed to initialize pllb_arm\n");
|
|
||||||
return PTR_ERR(rpi->pllb_arm);
|
|
||||||
}
|
|
||||||
|
|
||||||
rpi->pllb_arm_lookup = clkdev_hw_create(rpi->pllb_arm, NULL, "cpu0");
|
static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi,
|
||||||
if (!rpi->pllb_arm_lookup) {
|
struct clk_hw_onecell_data *data)
|
||||||
dev_err(rpi->dev, "Failed to initialize pllb_arm_lookup\n");
|
{
|
||||||
clk_hw_unregister_fixed_factor(rpi->pllb_arm);
|
struct rpi_firmware_get_clocks_response *clks;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
clks = devm_kcalloc(rpi->dev,
|
||||||
|
sizeof(*clks), RPI_FIRMWARE_NUM_CLK_ID,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!clks)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ret = rpi_firmware_property(rpi->firmware, RPI_FIRMWARE_GET_CLOCKS,
|
||||||
|
clks,
|
||||||
|
sizeof(*clks) * RPI_FIRMWARE_NUM_CLK_ID);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
while (clks->id) {
|
||||||
|
struct clk_hw *hw;
|
||||||
|
|
||||||
|
switch (clks->id) {
|
||||||
|
case RPI_FIRMWARE_ARM_CLK_ID:
|
||||||
|
case RPI_FIRMWARE_CORE_CLK_ID:
|
||||||
|
case RPI_FIRMWARE_M2MC_CLK_ID:
|
||||||
|
case RPI_FIRMWARE_V3D_CLK_ID:
|
||||||
|
hw = raspberrypi_clk_register(rpi, clks->parent,
|
||||||
|
clks->id);
|
||||||
|
if (IS_ERR(hw))
|
||||||
|
return PTR_ERR(hw);
|
||||||
|
|
||||||
|
data->hws[clks->id] = hw;
|
||||||
|
data->num = clks->id + 1;
|
||||||
|
fallthrough;
|
||||||
|
|
||||||
|
default:
|
||||||
|
clks++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -249,14 +291,23 @@ static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi)
|
||||||
|
|
||||||
static int raspberrypi_clk_probe(struct platform_device *pdev)
|
static int raspberrypi_clk_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
struct clk_hw_onecell_data *clk_data;
|
||||||
struct device_node *firmware_node;
|
struct device_node *firmware_node;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct rpi_firmware *firmware;
|
struct rpi_firmware *firmware;
|
||||||
struct raspberrypi_clk *rpi;
|
struct raspberrypi_clk *rpi;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
firmware_node = of_find_compatible_node(NULL, NULL,
|
/*
|
||||||
"raspberrypi,bcm2835-firmware");
|
* We can be probed either through the an old-fashioned
|
||||||
|
* platform device registration or through a DT node that is a
|
||||||
|
* child of the firmware node. Handle both cases.
|
||||||
|
*/
|
||||||
|
if (dev->of_node)
|
||||||
|
firmware_node = of_get_parent(dev->of_node);
|
||||||
|
else
|
||||||
|
firmware_node = of_find_compatible_node(NULL, NULL,
|
||||||
|
"raspberrypi,bcm2835-firmware");
|
||||||
if (!firmware_node) {
|
if (!firmware_node) {
|
||||||
dev_err(dev, "Missing firmware node\n");
|
dev_err(dev, "Missing firmware node\n");
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
@ -275,13 +326,18 @@ static int raspberrypi_clk_probe(struct platform_device *pdev)
|
||||||
rpi->firmware = firmware;
|
rpi->firmware = firmware;
|
||||||
platform_set_drvdata(pdev, rpi);
|
platform_set_drvdata(pdev, rpi);
|
||||||
|
|
||||||
ret = raspberrypi_register_pllb(rpi);
|
clk_data = devm_kzalloc(dev, struct_size(clk_data, hws,
|
||||||
if (ret) {
|
RPI_FIRMWARE_NUM_CLK_ID),
|
||||||
dev_err(dev, "Failed to initialize pllb, %d\n", ret);
|
GFP_KERNEL);
|
||||||
return ret;
|
if (!clk_data)
|
||||||
}
|
return -ENOMEM;
|
||||||
|
|
||||||
ret = raspberrypi_register_pllb_arm(rpi);
|
ret = raspberrypi_discover_clocks(rpi, clk_data);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
|
||||||
|
clk_data);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -300,9 +356,16 @@ static int raspberrypi_clk_remove(struct platform_device *pdev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id raspberrypi_clk_match[] = {
|
||||||
|
{ .compatible = "raspberrypi,firmware-clocks" },
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, raspberrypi_clk_match);
|
||||||
|
|
||||||
static struct platform_driver raspberrypi_clk_driver = {
|
static struct platform_driver raspberrypi_clk_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "raspberrypi-clk",
|
.name = "raspberrypi-clk",
|
||||||
|
.of_match_table = raspberrypi_clk_match,
|
||||||
},
|
},
|
||||||
.probe = raspberrypi_clk_probe,
|
.probe = raspberrypi_clk_probe,
|
||||||
.remove = raspberrypi_clk_remove,
|
.remove = raspberrypi_clk_remove,
|
||||||
|
|
|
@ -208,6 +208,20 @@ rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw)
|
||||||
|
|
||||||
static void rpi_register_clk_driver(struct device *dev)
|
static void rpi_register_clk_driver(struct device *dev)
|
||||||
{
|
{
|
||||||
|
struct device_node *firmware;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Earlier DTs don't have a node for the firmware clocks but
|
||||||
|
* rely on us creating a platform device by hand. If we do
|
||||||
|
* have a node for the firmware clocks, just bail out here.
|
||||||
|
*/
|
||||||
|
firmware = of_get_compatible_child(dev->of_node,
|
||||||
|
"raspberrypi,firmware-clocks");
|
||||||
|
if (firmware) {
|
||||||
|
of_node_put(firmware);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
rpi_clk = platform_device_register_data(dev, "raspberrypi-clk",
|
rpi_clk = platform_device_register_data(dev, "raspberrypi-clk",
|
||||||
-1, NULL, 0);
|
-1, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
* Maxime Ripard <maxime.ripard@free-electrons.com>
|
* Maxime Ripard <maxime.ripard@free-electrons.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/delay.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
@ -18,10 +19,9 @@
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/reset-controller.h>
|
#include <linux/reset-controller.h>
|
||||||
|
#include <linux/reset/reset-simple.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
|
|
||||||
#include "reset-simple.h"
|
|
||||||
|
|
||||||
static inline struct reset_simple_data *
|
static inline struct reset_simple_data *
|
||||||
to_reset_simple_data(struct reset_controller_dev *rcdev)
|
to_reset_simple_data(struct reset_controller_dev *rcdev)
|
||||||
{
|
{
|
||||||
|
@ -64,6 +64,24 @@ static int reset_simple_deassert(struct reset_controller_dev *rcdev,
|
||||||
return reset_simple_update(rcdev, id, false);
|
return reset_simple_update(rcdev, id, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int reset_simple_reset(struct reset_controller_dev *rcdev,
|
||||||
|
unsigned long id)
|
||||||
|
{
|
||||||
|
struct reset_simple_data *data = to_reset_simple_data(rcdev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!data->reset_us)
|
||||||
|
return -ENOTSUPP;
|
||||||
|
|
||||||
|
ret = reset_simple_assert(rcdev, id);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
usleep_range(data->reset_us, data->reset_us * 2);
|
||||||
|
|
||||||
|
return reset_simple_deassert(rcdev, id);
|
||||||
|
}
|
||||||
|
|
||||||
static int reset_simple_status(struct reset_controller_dev *rcdev,
|
static int reset_simple_status(struct reset_controller_dev *rcdev,
|
||||||
unsigned long id)
|
unsigned long id)
|
||||||
{
|
{
|
||||||
|
@ -81,6 +99,7 @@ static int reset_simple_status(struct reset_controller_dev *rcdev,
|
||||||
const struct reset_control_ops reset_simple_ops = {
|
const struct reset_control_ops reset_simple_ops = {
|
||||||
.assert = reset_simple_assert,
|
.assert = reset_simple_assert,
|
||||||
.deassert = reset_simple_deassert,
|
.deassert = reset_simple_deassert,
|
||||||
|
.reset = reset_simple_reset,
|
||||||
.status = reset_simple_status,
|
.status = reset_simple_status,
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(reset_simple_ops);
|
EXPORT_SYMBOL_GPL(reset_simple_ops);
|
||||||
|
|
|
@ -11,13 +11,12 @@
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/reset-controller.h>
|
#include <linux/reset-controller.h>
|
||||||
|
#include <linux/reset/reset-simple.h>
|
||||||
#include <linux/reset/socfpga.h>
|
#include <linux/reset/socfpga.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
#include "reset-simple.h"
|
|
||||||
|
|
||||||
#define SOCFPGA_NR_BANKS 8
|
#define SOCFPGA_NR_BANKS 8
|
||||||
|
|
||||||
static int a10_reset_init(struct device_node *np)
|
static int a10_reset_init(struct device_node *np)
|
||||||
|
|
|
@ -14,13 +14,12 @@
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/reset-controller.h>
|
#include <linux/reset-controller.h>
|
||||||
|
#include <linux/reset/reset-simple.h>
|
||||||
#include <linux/reset/sunxi.h>
|
#include <linux/reset/sunxi.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
#include "reset-simple.h"
|
|
||||||
|
|
||||||
static int sunxi_reset_init(struct device_node *np)
|
static int sunxi_reset_init(struct device_node *np)
|
||||||
{
|
{
|
||||||
struct reset_simple_data *data;
|
struct reset_simple_data *data;
|
||||||
|
|
|
@ -9,8 +9,7 @@
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/reset.h>
|
#include <linux/reset.h>
|
||||||
|
#include <linux/reset/reset-simple.h>
|
||||||
#include "reset-simple.h"
|
|
||||||
|
|
||||||
#define MAX_CLKS 2
|
#define MAX_CLKS 2
|
||||||
#define MAX_RSTS 2
|
#define MAX_RSTS 2
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
|
||||||
|
#ifndef __DT_BINDINGS_CLOCK_BCM3368_H
|
||||||
|
#define __DT_BINDINGS_CLOCK_BCM3368_H
|
||||||
|
|
||||||
|
#define BCM3368_CLK_MAC 3
|
||||||
|
#define BCM3368_CLK_TC 5
|
||||||
|
#define BCM3368_CLK_US_TOP 6
|
||||||
|
#define BCM3368_CLK_DS_TOP 7
|
||||||
|
#define BCM3368_CLK_ACM 8
|
||||||
|
#define BCM3368_CLK_SPI 9
|
||||||
|
#define BCM3368_CLK_USBS 10
|
||||||
|
#define BCM3368_CLK_BMU 11
|
||||||
|
#define BCM3368_CLK_PCM 12
|
||||||
|
#define BCM3368_CLK_NTP 13
|
||||||
|
#define BCM3368_CLK_ACP_B 14
|
||||||
|
#define BCM3368_CLK_ACP_A 15
|
||||||
|
#define BCM3368_CLK_EMUSB 17
|
||||||
|
#define BCM3368_CLK_ENET0 18
|
||||||
|
#define BCM3368_CLK_ENET1 19
|
||||||
|
#define BCM3368_CLK_USBSU 20
|
||||||
|
#define BCM3368_CLK_EPHY 21
|
||||||
|
|
||||||
|
#endif /* __DT_BINDINGS_CLOCK_BCM3368_H */
|
|
@ -0,0 +1,42 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
|
||||||
|
#ifndef __DT_BINDINGS_CLOCK_BCM6318_H
|
||||||
|
#define __DT_BINDINGS_CLOCK_BCM6318_H
|
||||||
|
|
||||||
|
#define BCM6318_CLK_ADSL_ASB 0
|
||||||
|
#define BCM6318_CLK_USB_ASB 1
|
||||||
|
#define BCM6318_CLK_MIPS_ASB 2
|
||||||
|
#define BCM6318_CLK_PCIE_ASB 3
|
||||||
|
#define BCM6318_CLK_PHYMIPS_ASB 4
|
||||||
|
#define BCM6318_CLK_ROBOSW_ASB 5
|
||||||
|
#define BCM6318_CLK_SAR_ASB 6
|
||||||
|
#define BCM6318_CLK_SDR_ASB 7
|
||||||
|
#define BCM6318_CLK_SWREG_ASB 8
|
||||||
|
#define BCM6318_CLK_PERIPH_ASB 9
|
||||||
|
#define BCM6318_CLK_CPUBUS160 10
|
||||||
|
#define BCM6318_CLK_ADSL 11
|
||||||
|
#define BCM6318_CLK_SAR125 12
|
||||||
|
#define BCM6318_CLK_MIPS 13
|
||||||
|
#define BCM6318_CLK_PCIE 14
|
||||||
|
#define BCM6318_CLK_ROBOSW250 16
|
||||||
|
#define BCM6318_CLK_ROBOSW025 17
|
||||||
|
#define BCM6318_CLK_SDR 19
|
||||||
|
#define BCM6318_CLK_USBD 20
|
||||||
|
#define BCM6318_CLK_HSSPI 25
|
||||||
|
#define BCM6318_CLK_PCIE25 27
|
||||||
|
#define BCM6318_CLK_PHYMIPS 28
|
||||||
|
#define BCM6318_CLK_AFE 29
|
||||||
|
#define BCM6318_CLK_QPROC 30
|
||||||
|
|
||||||
|
#define BCM6318_UCLK_ADSL 0
|
||||||
|
#define BCM6318_UCLK_ARB 1
|
||||||
|
#define BCM6318_UCLK_MIPS 2
|
||||||
|
#define BCM6318_UCLK_PCIE 3
|
||||||
|
#define BCM6318_UCLK_PERIPH 4
|
||||||
|
#define BCM6318_UCLK_PHYMIPS 5
|
||||||
|
#define BCM6318_UCLK_ROBOSW 6
|
||||||
|
#define BCM6318_UCLK_SAR 7
|
||||||
|
#define BCM6318_UCLK_SDR 8
|
||||||
|
#define BCM6318_UCLK_USB 9
|
||||||
|
|
||||||
|
#endif /* __DT_BINDINGS_CLOCK_BCM6318_H */
|
|
@ -0,0 +1,30 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
|
||||||
|
#ifndef __DT_BINDINGS_CLOCK_BCM63268_H
|
||||||
|
#define __DT_BINDINGS_CLOCK_BCM63268_H
|
||||||
|
|
||||||
|
#define BCM63268_CLK_DIS_GLESS 0
|
||||||
|
#define BCM63268_CLK_VDSL_QPROC 1
|
||||||
|
#define BCM63268_CLK_VDSL_AFE 2
|
||||||
|
#define BCM63268_CLK_VDSL 3
|
||||||
|
#define BCM63268_CLK_MIPS 4
|
||||||
|
#define BCM63268_CLK_WLAN_OCP 5
|
||||||
|
#define BCM63268_CLK_DECT 6
|
||||||
|
#define BCM63268_CLK_FAP0 7
|
||||||
|
#define BCM63268_CLK_FAP1 8
|
||||||
|
#define BCM63268_CLK_SAR 9
|
||||||
|
#define BCM63268_CLK_ROBOSW 10
|
||||||
|
#define BCM63268_CLK_PCM 11
|
||||||
|
#define BCM63268_CLK_USBD 12
|
||||||
|
#define BCM63268_CLK_USBH 13
|
||||||
|
#define BCM63268_CLK_IPSEC 14
|
||||||
|
#define BCM63268_CLK_SPI 15
|
||||||
|
#define BCM63268_CLK_HSSPI 16
|
||||||
|
#define BCM63268_CLK_PCIE 17
|
||||||
|
#define BCM63268_CLK_PHYMIPS 18
|
||||||
|
#define BCM63268_CLK_GMAC 19
|
||||||
|
#define BCM63268_CLK_NAND 20
|
||||||
|
#define BCM63268_CLK_TBUS 27
|
||||||
|
#define BCM63268_CLK_ROBOSW250 31
|
||||||
|
|
||||||
|
#endif /* __DT_BINDINGS_CLOCK_BCM63268_H */
|
|
@ -0,0 +1,19 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
|
||||||
|
#ifndef __DT_BINDINGS_CLOCK_BCM6328_H
|
||||||
|
#define __DT_BINDINGS_CLOCK_BCM6328_H
|
||||||
|
|
||||||
|
#define BCM6328_CLK_PHYMIPS 0
|
||||||
|
#define BCM6328_CLK_ADSL_QPROC 1
|
||||||
|
#define BCM6328_CLK_ADSL_AFE 2
|
||||||
|
#define BCM6328_CLK_ADSL 3
|
||||||
|
#define BCM6328_CLK_MIPS 4
|
||||||
|
#define BCM6328_CLK_SAR 5
|
||||||
|
#define BCM6328_CLK_PCM 6
|
||||||
|
#define BCM6328_CLK_USBD 7
|
||||||
|
#define BCM6328_CLK_USBH 8
|
||||||
|
#define BCM6328_CLK_HSSPI 9
|
||||||
|
#define BCM6328_CLK_PCIE 10
|
||||||
|
#define BCM6328_CLK_ROBOSW 11
|
||||||
|
|
||||||
|
#endif /* __DT_BINDINGS_CLOCK_BCM6328_H */
|
|
@ -0,0 +1,18 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
|
||||||
|
#ifndef __DT_BINDINGS_CLOCK_BCM6358_H
|
||||||
|
#define __DT_BINDINGS_CLOCK_BCM6358_H
|
||||||
|
|
||||||
|
#define BCM6358_CLK_ENET 4
|
||||||
|
#define BCM6358_CLK_ADSLPHY 5
|
||||||
|
#define BCM6358_CLK_PCM 8
|
||||||
|
#define BCM6358_CLK_SPI 9
|
||||||
|
#define BCM6358_CLK_USBS 10
|
||||||
|
#define BCM6358_CLK_SAR 11
|
||||||
|
#define BCM6358_CLK_EMUSB 17
|
||||||
|
#define BCM6358_CLK_ENET0 18
|
||||||
|
#define BCM6358_CLK_ENET1 19
|
||||||
|
#define BCM6358_CLK_USBSU 20
|
||||||
|
#define BCM6358_CLK_EPHY 21
|
||||||
|
|
||||||
|
#endif /* __DT_BINDINGS_CLOCK_BCM6358_H */
|
|
@ -0,0 +1,26 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
|
||||||
|
#ifndef __DT_BINDINGS_CLOCK_BCM6362_H
|
||||||
|
#define __DT_BINDINGS_CLOCK_BCM6362_H
|
||||||
|
|
||||||
|
#define BCM6362_CLK_ADSL_QPROC 1
|
||||||
|
#define BCM6362_CLK_ADSL_AFE 2
|
||||||
|
#define BCM6362_CLK_ADSL 3
|
||||||
|
#define BCM6362_CLK_MIPS 4
|
||||||
|
#define BCM6362_CLK_WLAN_OCP 5
|
||||||
|
#define BCM6362_CLK_SWPKT_USB 7
|
||||||
|
#define BCM6362_CLK_SWPKT_SAR 8
|
||||||
|
#define BCM6362_CLK_SAR 9
|
||||||
|
#define BCM6362_CLK_ROBOSW 10
|
||||||
|
#define BCM6362_CLK_PCM 11
|
||||||
|
#define BCM6362_CLK_USBD 12
|
||||||
|
#define BCM6362_CLK_USBH 13
|
||||||
|
#define BCM6362_CLK_IPSEC 14
|
||||||
|
#define BCM6362_CLK_SPI 15
|
||||||
|
#define BCM6362_CLK_HSSPI 16
|
||||||
|
#define BCM6362_CLK_PCIE 17
|
||||||
|
#define BCM6362_CLK_FAP 18
|
||||||
|
#define BCM6362_CLK_PHYMIPS 19
|
||||||
|
#define BCM6362_CLK_NAND 20
|
||||||
|
|
||||||
|
#endif /* __DT_BINDINGS_CLOCK_BCM6362_H */
|
|
@ -0,0 +1,24 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||||
|
|
||||||
|
#ifndef __DT_BINDINGS_CLOCK_BCM6368_H
|
||||||
|
#define __DT_BINDINGS_CLOCK_BCM6368_H
|
||||||
|
|
||||||
|
#define BCM6368_CLK_VDSL_QPROC 2
|
||||||
|
#define BCM6368_CLK_VDSL_AFE 3
|
||||||
|
#define BCM6368_CLK_VDSL_BONDING 4
|
||||||
|
#define BCM6368_CLK_VDSL 5
|
||||||
|
#define BCM6368_CLK_PHYMIPS 6
|
||||||
|
#define BCM6368_CLK_SWPKT_USB 7
|
||||||
|
#define BCM6368_CLK_SWPKT_SAR 8
|
||||||
|
#define BCM6368_CLK_SPI 9
|
||||||
|
#define BCM6368_CLK_USBD 10
|
||||||
|
#define BCM6368_CLK_SAR 11
|
||||||
|
#define BCM6368_CLK_ROBOSW 12
|
||||||
|
#define BCM6368_CLK_UTOPIA 13
|
||||||
|
#define BCM6368_CLK_PCM 14
|
||||||
|
#define BCM6368_CLK_USBH 15
|
||||||
|
#define BCM6368_CLK_DIS_GLESS 16
|
||||||
|
#define BCM6368_CLK_NAND 17
|
||||||
|
#define BCM6368_CLK_IPSEC 18
|
||||||
|
|
||||||
|
#endif /* __DT_BINDINGS_CLOCK_BCM6368_H */
|
|
@ -27,6 +27,12 @@
|
||||||
* @status_active_low: if true, bits read back as cleared while the reset is
|
* @status_active_low: if true, bits read back as cleared while the reset is
|
||||||
* asserted. Otherwise, bits read back as set while the
|
* asserted. Otherwise, bits read back as set while the
|
||||||
* reset is asserted.
|
* reset is asserted.
|
||||||
|
* @reset_us: Minimum delay in microseconds needed that needs to be
|
||||||
|
* waited for between an assert and a deassert to reset the
|
||||||
|
* device. If multiple consumers with different delay
|
||||||
|
* requirements are connected to this controller, it must
|
||||||
|
* be the largest minimum delay. 0 means that such a delay is
|
||||||
|
* unknown and the reset operation is unsupported.
|
||||||
*/
|
*/
|
||||||
struct reset_simple_data {
|
struct reset_simple_data {
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
@ -34,6 +40,7 @@ struct reset_simple_data {
|
||||||
struct reset_controller_dev rcdev;
|
struct reset_controller_dev rcdev;
|
||||||
bool active_low;
|
bool active_low;
|
||||||
bool status_active_low;
|
bool status_active_low;
|
||||||
|
unsigned int reset_us;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const struct reset_control_ops reset_simple_ops;
|
extern const struct reset_control_ops reset_simple_ops;
|
Loading…
Reference in New Issue