Commit 47c9e0ce authored by Stephen Boyd's avatar Stephen Boyd

Merge branches 'clk-rpi-cpufreq', 'clk-tegra', 'clk-simplify-provider.h',...

Merge branches 'clk-rpi-cpufreq', 'clk-tegra', 'clk-simplify-provider.h', 'clk-sprd' and 'clk-at91' into clk-next

 - Support for CPU clks on Raspberry Pi devices
 - Slow clk support for AT91 SAM9X60 SoCs

* clk-rpi-cpufreq:
  clk: raspberrypi: register platform device for raspberrypi-cpufreq
  firmware: raspberrypi: register clk device
  clk: bcm283x: add driver interfacing with Raspberry Pi's firmware
  clk: bcm2835: remove pllb

* clk-tegra:
  clk: tegra: Do not enable PLL_RE_VCO on Tegra210
  clk: tegra: Warn if an enabled PLL is in IDDQ
  clk: tegra: Do not warn unnecessarily
  clk: tegra210: fix PLLU and PLLU_OUT1

* clk-simplify-provider.h:
  clk: consoldiate the __clk_get_hw() declarations
  clk: Unexport __clk_of_table
  clk: Remove ifdef for COMMON_CLK in clk-provider.h

* clk-sprd:
  clk: sprd: Add check for return value of sprd_clk_regmap_init()
  clk: sprd: Check error only for devm_regmap_init_mmio()
  clk: sprd: Switch from of_iomap() to devm_ioremap_resource()

* clk-at91:
  clk: at91: sckc: use dedicated functions to unregister clock
  clk: at91: sckc: improve error path for sama5d4 sck registration
  clk: at91: sckc: remove unnecessary line
  clk: at91: sckc: improve error path for sam9x5 sck register
  clk: at91: sckc: add support to free slow clock osclillator
  clk: at91: sckc: add support to free slow rc oscillator
  clk: at91: sckc: add support to free slow oscillator
  clk: at91: sckc: add support for SAM9X60
  dt-bindings: clk: at91: add bindings for SAM9X60's slow clock controller
  clk: at91: sckc: add support to specify registers bit offsets
  clk: at91: sckc: sama5d4 has no bypass support
...@@ -9,10 +9,11 @@ Slow Clock controller: ...@@ -9,10 +9,11 @@ Slow Clock controller:
Required properties: Required properties:
- compatible : shall be one of the following: - compatible : shall be one of the following:
"atmel,at91sam9x5-sckc", "atmel,at91sam9x5-sckc",
"atmel,sama5d3-sckc" or "atmel,sama5d3-sckc",
"atmel,sama5d4-sckc": "atmel,sama5d4-sckc" or
"microchip,sam9x60-sckc":
at91 SCKC (Slow Clock Controller) at91 SCKC (Slow Clock Controller)
- #clock-cells : shall be 0. - #clock-cells : shall be 1 for "microchip,sam9x60-sckc" otherwise shall be 0.
- clocks : shall be the input parent clock phandle for the clock. - clocks : shall be the input parent clock phandle for the clock.
Optional properties: Optional properties:
......
This diff is collapsed.
...@@ -72,3 +72,10 @@ config CLK_BCM_SR ...@@ -72,3 +72,10 @@ config CLK_BCM_SR
default ARCH_BCM_IPROC default ARCH_BCM_IPROC
help help
Enable common clock framework support for the Broadcom Stingray SoC Enable common clock framework support for the Broadcom Stingray SoC
config CLK_RASPBERRYPI
tristate "Raspberry Pi firmware based clock support"
depends on RASPBERRYPI_FIRMWARE || (COMPILE_TEST && !RASPBERRYPI_FIRMWARE)
help
Enable common clock framework support for Raspberry Pi's firmware
dependent clocks
...@@ -7,6 +7,7 @@ obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o ...@@ -7,6 +7,7 @@ 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_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_ARCH_BCM_53573) += clk-bcm53573-ilp.o obj-$(CONFIG_ARCH_BCM_53573) += clk-bcm53573-ilp.o
obj-$(CONFIG_CLK_BCM_CYGNUS) += clk-cygnus.o obj-$(CONFIG_CLK_BCM_CYGNUS) += clk-cygnus.o
obj-$(CONFIG_CLK_BCM_HR2) += clk-hr2.o obj-$(CONFIG_CLK_BCM_HR2) += clk-hr2.o
......
...@@ -1651,30 +1651,10 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { ...@@ -1651,30 +1651,10 @@ 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. */ /*
[BCM2835_PLLB] = REGISTER_PLL( * PLLB is used for the ARM's clock. Controlled by firmware, see
.name = "pllb", * clk-raspberrypi.c.
.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),
[BCM2835_PLLB_ARM] = REGISTER_PLL_DIV(
.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),
/* /*
* PLLC is the core PLL, used to drive the core VPU clock. * PLLC is the core PLL, used to drive the core VPU clock.
......
// SPDX-License-Identifier: GPL-2.0+
/*
* Raspberry Pi driver for firmware controlled clocks
*
* Even though clk-bcm2835 provides an interface to the hardware registers for
* the system clocks we've had to factor out 'pllb' as the firmware 'owns' it.
* We're not allowed to change it directly as we might race with the
* over-temperature and under-voltage protections provided by the firmware.
*
* Copyright (C) 2019 Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
*/
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <soc/bcm2835/raspberrypi-firmware.h>
#define RPI_FIRMWARE_ARM_CLK_ID 0x00000003
#define RPI_FIRMWARE_STATE_ENABLE_BIT BIT(0)
#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 device *dev;
struct rpi_firmware *firmware;
struct platform_device *cpufreq;
unsigned long min_rate;
unsigned long max_rate;
struct clk_hw pllb;
struct clk_hw *pllb_arm;
struct clk_lookup *pllb_arm_lookup;
};
/*
* Structure of the message passed to Raspberry Pi's firmware in order to
* change clock rates. The 'disable_turbo' option is only available to the ARM
* clock (pllb) which we enable by default as turbo mode will alter multiple
* clocks at once.
*
* Even though we're able to access the clock registers directly we're bound to
* use the firmware interface as the firmware ultimately takes care of
* mitigating overheating/undervoltage situations and we would be changing
* frequencies behind his back.
*
* For more information on the firmware interface check:
* https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface
*/
struct raspberrypi_firmware_prop {
__le32 id;
__le32 val;
__le32 disable_turbo;
} __packed;
static int raspberrypi_clock_property(struct rpi_firmware *firmware, u32 tag,
u32 clk, u32 *val)
{
struct raspberrypi_firmware_prop msg = {
.id = cpu_to_le32(clk),
.val = cpu_to_le32(*val),
.disable_turbo = cpu_to_le32(1),
};
int ret;
ret = rpi_firmware_property(firmware, tag, &msg, sizeof(msg));
if (ret)
return ret;
*val = le32_to_cpu(msg.val);
return 0;
}
static int raspberrypi_fw_pll_is_on(struct clk_hw *hw)
{
struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
pllb);
u32 val = 0;
int ret;
ret = raspberrypi_clock_property(rpi->firmware,
RPI_FIRMWARE_GET_CLOCK_STATE,
RPI_FIRMWARE_ARM_CLK_ID, &val);
if (ret)
return 0;
return !!(val & RPI_FIRMWARE_STATE_ENABLE_BIT);
}
static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
pllb);
u32 val = 0;
int ret;
ret = raspberrypi_clock_property(rpi->firmware,
RPI_FIRMWARE_GET_CLOCK_RATE,
RPI_FIRMWARE_ARM_CLK_ID,
&val);
if (ret)
return ret;
return val * RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
}
static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk,
pllb);
u32 new_rate = rate / RPI_FIRMWARE_PLLB_ARM_DIV_RATE;
int ret;
ret = raspberrypi_clock_property(rpi->firmware,
RPI_FIRMWARE_SET_CLOCK_RATE,
RPI_FIRMWARE_ARM_CLK_ID,
&new_rate);
if (ret)
dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d",
clk_hw_get_name(hw), ret);
return ret;
}
/*
* Sadly there is no firmware rate rounding interface. We borrowed it from
* 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);
u64 div, final_rate;
u32 ndiv, fdiv;
/* We can't use req->rate directly as it would overflow */
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;
}
static const struct clk_ops raspberrypi_firmware_pll_clk_ops = {
.is_prepared = raspberrypi_fw_pll_is_on,
.recalc_rate = raspberrypi_fw_pll_get_rate,
.set_rate = raspberrypi_fw_pll_set_rate,
.determine_rate = raspberrypi_pll_determine_rate,
};
static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi)
{
u32 min_rate = 0, max_rate = 0;
struct clk_init_data init;
int ret;
memset(&init, 0, sizeof(init));
/* All of the PLLs derive from the external oscillator. */
init.parent_names = (const char *[]){ "osc" };
init.num_parents = 1;
init.name = "pllb";
init.ops = &raspberrypi_firmware_pll_clk_ops;
init.flags = CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED;
/* Get min & max rates set by the firmware */
ret = raspberrypi_clock_property(rpi->firmware,
RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
RPI_FIRMWARE_ARM_CLK_ID,
&min_rate);
if (ret) {
dev_err(rpi->dev, "Failed to get %s min freq: %d\n",
init.name, ret);
return ret;
}
ret = raspberrypi_clock_property(rpi->firmware,
RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
RPI_FIRMWARE_ARM_CLK_ID,
&max_rate);
if (ret) {
dev_err(rpi->dev, "Failed to get %s max freq: %d\n",
init.name, ret);
return ret;
}
if (!min_rate || !max_rate) {
dev_err(rpi->dev, "Unexpected frequency range: min %u, max %u\n",
min_rate, max_rate);
return -EINVAL;
}
dev_info(rpi->dev, "CPU frequency range: min %u, max %u\n",
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)
{
rpi->pllb_arm = clk_hw_register_fixed_factor(rpi->dev,
"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");
if (!rpi->pllb_arm_lookup) {
dev_err(rpi->dev, "Failed to initialize pllb_arm_lookup\n");
clk_hw_unregister_fixed_factor(rpi->pllb_arm);
return -ENOMEM;
}
return 0;
}
static int raspberrypi_clk_probe(struct platform_device *pdev)
{
struct device_node *firmware_node;
struct device *dev = &pdev->dev;
struct rpi_firmware *firmware;
struct raspberrypi_clk *rpi;
int ret;
firmware_node = of_find_compatible_node(NULL, NULL,
"raspberrypi,bcm2835-firmware");
if (!firmware_node) {
dev_err(dev, "Missing firmware node\n");
return -ENOENT;
}
firmware = rpi_firmware_get(firmware_node);
of_node_put(firmware_node);
if (!firmware)
return -EPROBE_DEFER;
rpi = devm_kzalloc(dev, sizeof(*rpi), GFP_KERNEL);
if (!rpi)
return -ENOMEM;
rpi->dev = dev;
rpi->firmware = firmware;
platform_set_drvdata(pdev, rpi);
ret = raspberrypi_register_pllb(rpi);
if (ret) {
dev_err(dev, "Failed to initialize pllb, %d\n", ret);
return ret;
}
ret = raspberrypi_register_pllb_arm(rpi);
if (ret)
return ret;
rpi->cpufreq = platform_device_register_data(dev, "raspberrypi-cpufreq",
-1, NULL, 0);
return 0;
}
static int raspberrypi_clk_remove(struct platform_device *pdev)
{
struct raspberrypi_clk *rpi = platform_get_drvdata(pdev);
platform_device_unregister(rpi->cpufreq);
return 0;
}
static struct platform_driver raspberrypi_clk_driver = {
.driver = {
.name = "raspberrypi-clk",
},
.probe = raspberrypi_clk_probe,
.remove = raspberrypi_clk_remove,
};
module_platform_driver(raspberrypi_clk_driver);
MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de>");
MODULE_DESCRIPTION("Raspberry Pi firmware clock driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:raspberrypi-clk");
...@@ -4084,6 +4084,7 @@ struct of_clk_provider { ...@@ -4084,6 +4084,7 @@ struct of_clk_provider {
void *data; void *data;
}; };
extern struct of_device_id __clk_of_table;
static const struct of_device_id __clk_of_table_sentinel static const struct of_device_id __clk_of_table_sentinel
__used __section(__clk_of_table_end); __used __section(__clk_of_table_end);
......
...@@ -33,10 +33,6 @@ clk_hw_create_clk(struct device *dev, struct clk_hw *hw, const char *dev_id, ...@@ -33,10 +33,6 @@ clk_hw_create_clk(struct device *dev, struct clk_hw *hw, const char *dev_id,
{ {
return (struct clk *)hw; return (struct clk *)hw;
} }
static struct clk_hw *__clk_get_hw(struct clk *clk)
{
return (struct clk_hw *)clk;
}
static inline void __clk_put(struct clk *clk) { } static inline void __clk_put(struct clk *clk) { }
#endif #endif
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clkdev.h> #include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h> #include <linux/of.h>
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <dt-bindings/clock/imx6sll-clock.h> #include <dt-bindings/clock/imx6sll-clock.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clkdev.h> #include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h> #include <linux/io.h>
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <dt-bindings/clock/imx6sx-clock.h> #include <dt-bindings/clock/imx6sx-clock.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clkdev.h> #include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h> #include <linux/io.h>
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <dt-bindings/clock/imx6ul-clock.h> #include <dt-bindings/clock/imx6ul-clock.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clkdev.h> #include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h> #include <linux/io.h>
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <dt-bindings/clock/imx7d-clock.h> #include <dt-bindings/clock/imx7d-clock.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clkdev.h> #include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h> #include <linux/io.h>
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of.h> #include <linux/of.h>
......
...@@ -42,6 +42,7 @@ int sprd_clk_regmap_init(struct platform_device *pdev, ...@@ -42,6 +42,7 @@ int sprd_clk_regmap_init(struct platform_device *pdev,
void __iomem *base; void __iomem *base;
struct device_node *node = pdev->dev.of_node; struct device_node *node = pdev->dev.of_node;
struct regmap *regmap; struct regmap *regmap;
struct resource *res;
if (of_find_property(node, "sprd,syscon", NULL)) { if (of_find_property(node, "sprd,syscon", NULL)) {
regmap = syscon_regmap_lookup_by_phandle(node, "sprd,syscon"); regmap = syscon_regmap_lookup_by_phandle(node, "sprd,syscon");
...@@ -50,10 +51,14 @@ int sprd_clk_regmap_init(struct platform_device *pdev, ...@@ -50,10 +51,14 @@ int sprd_clk_regmap_init(struct platform_device *pdev,
return PTR_ERR(regmap); return PTR_ERR(regmap);
} }
} else { } else {
base = of_iomap(node, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
regmap = devm_regmap_init_mmio(&pdev->dev, base, regmap = devm_regmap_init_mmio(&pdev->dev, base,
&sprdclk_regmap_config); &sprdclk_regmap_config);
if (IS_ERR_OR_NULL(regmap)) { if (IS_ERR(regmap)) {
pr_err("failed to init regmap\n"); pr_err("failed to init regmap\n");
return PTR_ERR(regmap); return PTR_ERR(regmap);
} }
......
...@@ -2023,6 +2023,7 @@ static int sc9860_clk_probe(struct platform_device *pdev) ...@@ -2023,6 +2023,7 @@ static int sc9860_clk_probe(struct platform_device *pdev)
{ {
const struct of_device_id *match; const struct of_device_id *match;
const struct sprd_clk_desc *desc; const struct sprd_clk_desc *desc;
int ret;
match = of_match_node(sprd_sc9860_clk_ids, pdev->dev.of_node); match = of_match_node(sprd_sc9860_clk_ids, pdev->dev.of_node);
if (!match) { if (!match) {
...@@ -2031,7 +2032,9 @@ static int sc9860_clk_probe(struct platform_device *pdev) ...@@ -2031,7 +2032,9 @@ static int sc9860_clk_probe(struct platform_device *pdev)
} }
desc = match->data; desc = match->data;
sprd_clk_regmap_init(pdev, desc); ret = sprd_clk_regmap_init(pdev, desc);
if (ret)
return ret;
return sprd_clk_probe(&pdev->dev, desc->hw_clks); return sprd_clk_probe(&pdev->dev, desc->hw_clks);
} }
......
...@@ -995,8 +995,6 @@ static void tegra210_pllre_set_defaults(struct tegra_clk_pll *pllre) ...@@ -995,8 +995,6 @@ static void tegra210_pllre_set_defaults(struct tegra_clk_pll *pllre)
pllre->params->defaults_set = true; pllre->params->defaults_set = true;
if (val & PLL_ENABLE) { if (val & PLL_ENABLE) {
pr_warn("PLL_RE already enabled. Postponing set full defaults\n");
/* /*
* PLL is ON: check if defaults already set, then set those * PLL is ON: check if defaults already set, then set those
* that can be updated in flight. * that can be updated in flight.
...@@ -1016,13 +1014,20 @@ static void tegra210_pllre_set_defaults(struct tegra_clk_pll *pllre) ...@@ -1016,13 +1014,20 @@ static void tegra210_pllre_set_defaults(struct tegra_clk_pll *pllre)
_pll_misc_chk_default(clk_base, pllre->params, 0, val, _pll_misc_chk_default(clk_base, pllre->params, 0, val,
~mask & PLLRE_MISC0_WRITE_MASK); ~mask & PLLRE_MISC0_WRITE_MASK);
/* Enable lock detect */ /* The PLL doesn't work if it's in IDDQ. */
val = readl_relaxed(clk_base + pllre->params->ext_misc_reg[0]); val = readl_relaxed(clk_base + pllre->params->ext_misc_reg[0]);
if (val & PLLRE_MISC0_IDDQ)
pr_warn("unexpected IDDQ bit set for enabled clock\n");
/* Enable lock detect */
val &= ~mask; val &= ~mask;
val |= PLLRE_MISC0_DEFAULT_VALUE & mask; val |= PLLRE_MISC0_DEFAULT_VALUE & mask;
writel_relaxed(val, clk_base + pllre->params->ext_misc_reg[0]); writel_relaxed(val, clk_base + pllre->params->ext_misc_reg[0]);
udelay(1); udelay(1);
if (!pllre->params->defaults_set)
pr_warn("PLL_RE already enabled. Postponing set full defaults\n");
return; return;
} }
...@@ -2215,9 +2220,9 @@ static struct div_nmp pllu_nmp = { ...@@ -2215,9 +2220,9 @@ static struct div_nmp pllu_nmp = {
}; };
static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
{ 12000000, 480000000, 40, 1, 0, 0 }, { 12000000, 480000000, 40, 1, 1, 0 },
{ 13000000, 480000000, 36, 1, 0, 0 }, /* actual: 468.0 MHz */ { 13000000, 480000000, 36, 1, 1, 0 }, /* actual: 468.0 MHz */
{ 38400000, 480000000, 25, 2, 0, 0 }, { 38400000, 480000000, 25, 2, 1, 0 },
{ 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0 },
}; };
...@@ -3343,7 +3348,7 @@ static struct tegra_clk_init_table init_table[] __initdata = { ...@@ -3343,7 +3348,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA210_CLK_DFLL_SOC, TEGRA210_CLK_PLL_P, 51000000, 1 }, { TEGRA210_CLK_DFLL_SOC, TEGRA210_CLK_PLL_P, 51000000, 1 },
{ TEGRA210_CLK_DFLL_REF, TEGRA210_CLK_PLL_P, 51000000, 1 }, { TEGRA210_CLK_DFLL_REF, TEGRA210_CLK_PLL_P, 51000000, 1 },
{ TEGRA210_CLK_SBC4, TEGRA210_CLK_PLL_P, 12000000, 1 }, { TEGRA210_CLK_SBC4, TEGRA210_CLK_PLL_P, 12000000, 1 },
{ TEGRA210_CLK_PLL_RE_VCO, TEGRA210_CLK_CLK_MAX, 672000000, 1 }, { TEGRA210_CLK_PLL_U_OUT1, TEGRA210_CLK_CLK_MAX, 48000000, 1 },
{ TEGRA210_CLK_XUSB_GATE, TEGRA210_CLK_CLK_MAX, 0, 1 }, { TEGRA210_CLK_XUSB_GATE, TEGRA210_CLK_CLK_MAX, 0, 1 },
{ TEGRA210_CLK_XUSB_SS_SRC, TEGRA210_CLK_PLL_U_480M, 120000000, 0 }, { TEGRA210_CLK_XUSB_SS_SRC, TEGRA210_CLK_PLL_U_480M, 120000000, 0 },
{ TEGRA210_CLK_XUSB_FS_SRC, TEGRA210_CLK_PLL_U_48M, 48000000, 0 }, { TEGRA210_CLK_XUSB_FS_SRC, TEGRA210_CLK_PLL_U_48M, 48000000, 0 },
...@@ -3368,7 +3373,6 @@ static struct tegra_clk_init_table init_table[] __initdata = { ...@@ -3368,7 +3373,6 @@ static struct tegra_clk_init_table init_table[] __initdata = {
{ TEGRA210_CLK_PLL_DP, TEGRA210_CLK_CLK_MAX, 270000000, 0 }, { TEGRA210_CLK_PLL_DP, TEGRA210_CLK_CLK_MAX, 270000000, 0 },
{ TEGRA210_CLK_SOC_THERM, TEGRA210_CLK_PLL_P, 51000000, 0 }, { TEGRA210_CLK_SOC_THERM, TEGRA210_CLK_PLL_P, 51000000, 0 },
{ TEGRA210_CLK_CCLK_G, TEGRA210_CLK_CLK_MAX, 0, 1 }, { TEGRA210_CLK_CCLK_G, TEGRA210_CLK_CLK_MAX, 0, 1 },
{ TEGRA210_CLK_PLL_U_OUT1, TEGRA210_CLK_CLK_MAX, 48000000, 1 },
{ TEGRA210_CLK_PLL_U_OUT2, TEGRA210_CLK_CLK_MAX, 60000000, 1 }, { TEGRA210_CLK_PLL_U_OUT2, TEGRA210_CLK_CLK_MAX, 60000000, 1 },
{ TEGRA210_CLK_SPDIF_IN_SYNC, TEGRA210_CLK_CLK_MAX, 24576000, 0 }, { TEGRA210_CLK_SPDIF_IN_SYNC, TEGRA210_CLK_CLK_MAX, 24576000, 0 },
{ TEGRA210_CLK_I2S0_SYNC, TEGRA210_CLK_CLK_MAX, 24576000, 0 }, { TEGRA210_CLK_I2S0_SYNC, TEGRA210_CLK_CLK_MAX, 24576000, 0 },
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#define MBOX_CHAN_PROPERTY 8 #define MBOX_CHAN_PROPERTY 8
static struct platform_device *rpi_hwmon; static struct platform_device *rpi_hwmon;
static struct platform_device *rpi_clk;
struct rpi_firmware { struct rpi_firmware {
struct mbox_client cl; struct mbox_client cl;
...@@ -207,6 +208,12 @@ rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw) ...@@ -207,6 +208,12 @@ rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw)
-1, NULL, 0); -1, NULL, 0);
} }
static void rpi_register_clk_driver(struct device *dev)
{
rpi_clk = platform_device_register_data(dev, "raspberrypi-clk",
-1, NULL, 0);
}
static int rpi_firmware_probe(struct platform_device *pdev) static int rpi_firmware_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
...@@ -234,6 +241,7 @@ static int rpi_firmware_probe(struct platform_device *pdev) ...@@ -234,6 +241,7 @@ static int rpi_firmware_probe(struct platform_device *pdev)
rpi_firmware_print_firmware_revision(fw); rpi_firmware_print_firmware_revision(fw);
rpi_register_hwmon_driver(dev, fw); rpi_register_hwmon_driver(dev, fw);
rpi_register_clk_driver(dev);
return 0; return 0;
} }
...@@ -254,6 +262,8 @@ static int rpi_firmware_remove(struct platform_device *pdev) ...@@ -254,6 +262,8 @@ static int rpi_firmware_remove(struct platform_device *pdev)
platform_device_unregister(rpi_hwmon); platform_device_unregister(rpi_hwmon);
rpi_hwmon = NULL; rpi_hwmon = NULL;
platform_device_unregister(rpi_clk);
rpi_clk = NULL;
mbox_free_channel(fw->chan); mbox_free_channel(fw->chan);
return 0; return 0;
......
...@@ -9,8 +9,6 @@ ...@@ -9,8 +9,6 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_clk.h> #include <linux/of_clk.h>
#ifdef CONFIG_COMMON_CLK
/* /*
* flags used across common struct clk. these flags should only affect the * flags used across common struct clk. these flags should only affect the
* top-level framework. custom flags for dealing with hardware specifics * top-level framework. custom flags for dealing with hardware specifics
...@@ -807,7 +805,14 @@ void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw); ...@@ -807,7 +805,14 @@ void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw);
/* helper functions */ /* helper functions */
const char *__clk_get_name(const struct clk *clk); const char *__clk_get_name(const struct clk *clk);
const char *clk_hw_get_name(const struct clk_hw *hw); const char *clk_hw_get_name(const struct clk_hw *hw);
#ifdef CONFIG_COMMON_CLK
struct clk_hw *__clk_get_hw(struct clk *clk); struct clk_hw *__clk_get_hw(struct clk *clk);
#else
static inline struct clk_hw *__clk_get_hw(struct clk *clk)
{
return (struct clk_hw *)clk;
}
#endif
unsigned int clk_hw_get_num_parents(const struct clk_hw *hw); unsigned int clk_hw_get_num_parents(const struct clk_hw *hw);
struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw); struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw);
struct clk_hw *clk_hw_get_parent_by_index(const struct clk_hw *hw, struct clk_hw *clk_hw_get_parent_by_index(const struct clk_hw *hw,
...@@ -867,8 +872,6 @@ static inline long divider_ro_round_rate(struct clk_hw *hw, unsigned long rate, ...@@ -867,8 +872,6 @@ static inline long divider_ro_round_rate(struct clk_hw *hw, unsigned long rate,
*/ */
unsigned long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate); unsigned long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate);
struct of_device_id;
struct clk_onecell_data { struct clk_onecell_data {
struct clk **clks; struct clk **clks;
unsigned int clk_num; unsigned int clk_num;
...@@ -879,8 +882,6 @@ struct clk_hw_onecell_data { ...@@ -879,8 +882,6 @@ struct clk_hw_onecell_data {
struct clk_hw *hws[]; struct clk_hw *hws[];
}; };
extern struct of_device_id __clk_of_table;
#define CLK_OF_DECLARE(name, compat, fn) OF_DECLARE_1(clk, name, compat, fn) #define CLK_OF_DECLARE(name, compat, fn) OF_DECLARE_1(clk, name, compat, fn)
/* /*
...@@ -1108,5 +1109,4 @@ static inline int of_clk_detect_critical(struct device_node *np, int index, ...@@ -1108,5 +1109,4 @@ static inline int of_clk_detect_critical(struct device_node *np, int index,
void clk_gate_restore_context(struct clk_hw *hw); void clk_gate_restore_context(struct clk_hw *hw);
#endif /* CONFIG_COMMON_CLK */
#endif /* CLK_PROVIDER_H */ #endif /* CLK_PROVIDER_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment