Commit 1fe7c040 authored by Stephen Boyd's avatar Stephen Boyd

Merge branches 'clk-actions-reset', 'clk-imx7-init-critical', 'clk-mmp2-ids'...

Merge branches 'clk-actions-reset', 'clk-imx7-init-critical', 'clk-mmp2-ids' and 'clk-at91-pmc-rework' into clk-next

 - Reset Controller (RMU) support for Actions Semi Owl S900 and S700 SoCs
 - Rework at91 PMC clock driver for new DT bindings

* clk-actions-reset:
  clk: actions: Add Actions Semi S900 SoC Reset Management Unit support
  clk: actions: Add Actions Semi S700 SoC Reset Management Unit support
  clk: actions: Add Actions Semi Owl SoCs Reset Management Unit support
  dt-bindings: reset: Add binding constants for Actions Semi S900 RMU
  dt-bindings: reset: Add binding constants for Actions Semi S700 RMU
  dt-bindings: clock: Add reset controller bindings for Actions Semi Owl SoCs
  clk: actions: Cache regmap info in private clock descriptor

* clk-imx7-init-critical:
  clk: imx7d: remove CLK_IS_CRITICAL flag for arm_a7_root_clk
  clk: imx: cpu clock should be always critical
  clk: imx: imx7d: remove clks_init_on array
  clk: imx: imx7d: remove unnecessary clocks from clks_init_on array

* clk-mmp2-ids:
  clk: mmp2: fix the clock id for sdh2_clk and sdh3_clk

* clk-at91-pmc-rework:
  clk: at91: move DT compatibility code to its own file
  clk: at91: add at91sam9rl PMC driver
  clk: at91: add at91sam9x5 PMCs driver
  clk: at91: add at91sam9260 PMC driver
  clk: at91: add sama5d2 PMC driver
  clk: at91: add sama5d4 pmc driver
  clk: at91: add new DT lookup function
  dt-bindings: clk: at91: Document new PMC binding
  clk: at91: add pmc_data struct and helpers
  clk: at91: allow clock registration from C code
  clk: at91: generated: set audio_pll_allowed in at91_clk_register_generated()
  clk: at91: audio-pll: separate registration from DT parsing
  clk: at91: h32mx: separate registration from DT parsing
  clk: at91: generated: SSCs don't have a gclk
  clk: at91: audio-pll: fix audio pmc type
...@@ -13,6 +13,7 @@ Required Properties: ...@@ -13,6 +13,7 @@ Required Properties:
region. region.
- clocks: Reference to the parent clocks ("hosc", "losc") - clocks: Reference to the parent clocks ("hosc", "losc")
- #clock-cells: should be 1. - #clock-cells: should be 1.
- #reset-cells: should be 1.
Each clock is assigned an identifier, and client nodes can use this identifier Each clock is assigned an identifier, and client nodes can use this identifier
to specify the clock which they consume. to specify the clock which they consume.
...@@ -36,6 +37,7 @@ Example: Clock Management Unit node: ...@@ -36,6 +37,7 @@ Example: Clock Management Unit node:
reg = <0x0 0xe0160000 0x0 0x1000>; reg = <0x0 0xe0160000 0x0 0x1000>;
clocks = <&hosc>, <&losc>; clocks = <&hosc>, <&losc>;
#clock-cells = <1>; #clock-cells = <1>;
#reset-cells = <1>;
}; };
Example: UART controller node that consumes clock generated by the clock Example: UART controller node that consumes clock generated by the clock
......
...@@ -2,6 +2,7 @@ config CLK_ACTIONS ...@@ -2,6 +2,7 @@ config CLK_ACTIONS
bool "Clock driver for Actions Semi SoCs" bool "Clock driver for Actions Semi SoCs"
depends on ARCH_ACTIONS || COMPILE_TEST depends on ARCH_ACTIONS || COMPILE_TEST
select REGMAP_MMIO select REGMAP_MMIO
select RESET_CONTROLLER
default ARCH_ACTIONS default ARCH_ACTIONS
if CLK_ACTIONS if CLK_ACTIONS
......
...@@ -7,6 +7,7 @@ clk-owl-y += owl-divider.o ...@@ -7,6 +7,7 @@ clk-owl-y += owl-divider.o
clk-owl-y += owl-factor.o clk-owl-y += owl-factor.o
clk-owl-y += owl-composite.o clk-owl-y += owl-composite.o
clk-owl-y += owl-pll.o clk-owl-y += owl-pll.o
clk-owl-y += owl-reset.o
# SoC support # SoC support
obj-$(CONFIG_CLK_OWL_S700) += owl-s700.o obj-$(CONFIG_CLK_OWL_S700) += owl-s700.o
......
...@@ -39,7 +39,7 @@ static void owl_clk_set_regmap(const struct owl_clk_desc *desc, ...@@ -39,7 +39,7 @@ static void owl_clk_set_regmap(const struct owl_clk_desc *desc,
} }
int owl_clk_regmap_init(struct platform_device *pdev, int owl_clk_regmap_init(struct platform_device *pdev,
const struct owl_clk_desc *desc) struct owl_clk_desc *desc)
{ {
void __iomem *base; void __iomem *base;
struct regmap *regmap; struct regmap *regmap;
...@@ -57,6 +57,7 @@ int owl_clk_regmap_init(struct platform_device *pdev, ...@@ -57,6 +57,7 @@ int owl_clk_regmap_init(struct platform_device *pdev,
} }
owl_clk_set_regmap(desc, regmap); owl_clk_set_regmap(desc, regmap);
desc->regmap = regmap;
return 0; return 0;
} }
......
...@@ -26,6 +26,9 @@ struct owl_clk_desc { ...@@ -26,6 +26,9 @@ struct owl_clk_desc {
struct owl_clk_common **clks; struct owl_clk_common **clks;
unsigned long num_clks; unsigned long num_clks;
struct clk_hw_onecell_data *hw_clks; struct clk_hw_onecell_data *hw_clks;
const struct owl_reset_map *resets;
unsigned long num_resets;
struct regmap *regmap;
}; };
static inline struct owl_clk_common * static inline struct owl_clk_common *
...@@ -35,7 +38,7 @@ static inline struct owl_clk_common * ...@@ -35,7 +38,7 @@ static inline struct owl_clk_common *
} }
int owl_clk_regmap_init(struct platform_device *pdev, int owl_clk_regmap_init(struct platform_device *pdev,
const struct owl_clk_desc *desc); struct owl_clk_desc *desc);
int owl_clk_probe(struct device *dev, struct clk_hw_onecell_data *hw_clks); int owl_clk_probe(struct device *dev, struct clk_hw_onecell_data *hw_clks);
#endif /* _OWL_COMMON_H_ */ #endif /* _OWL_COMMON_H_ */
// SPDX-License-Identifier: GPL-2.0-or-later
//
// Actions Semi Owl SoCs Reset Management Unit driver
//
// Copyright (c) 2018 Linaro Ltd.
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
#include <linux/delay.h>
#include <linux/regmap.h>
#include <linux/reset-controller.h>
#include "owl-reset.h"
static int owl_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct owl_reset *reset = to_owl_reset(rcdev);
const struct owl_reset_map *map = &reset->reset_map[id];
return regmap_update_bits(reset->regmap, map->reg, map->bit, 0);
}
static int owl_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct owl_reset *reset = to_owl_reset(rcdev);
const struct owl_reset_map *map = &reset->reset_map[id];
return regmap_update_bits(reset->regmap, map->reg, map->bit, map->bit);
}
static int owl_reset_reset(struct reset_controller_dev *rcdev,
unsigned long id)
{
owl_reset_assert(rcdev, id);
udelay(1);
owl_reset_deassert(rcdev, id);
return 0;
}
static int owl_reset_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct owl_reset *reset = to_owl_reset(rcdev);
const struct owl_reset_map *map = &reset->reset_map[id];
u32 reg;
int ret;
ret = regmap_read(reset->regmap, map->reg, &reg);
if (ret)
return ret;
/*
* The reset control API expects 0 if reset is not asserted,
* which is the opposite of what our hardware uses.
*/
return !(map->bit & reg);
}
const struct reset_control_ops owl_reset_ops = {
.assert = owl_reset_assert,
.deassert = owl_reset_deassert,
.reset = owl_reset_reset,
.status = owl_reset_status,
};
// SPDX-License-Identifier: GPL-2.0-or-later
//
// Actions Semi Owl SoCs Reset Management Unit driver
//
// Copyright (c) 2018 Linaro Ltd.
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
#ifndef _OWL_RESET_H_
#define _OWL_RESET_H_
#include <linux/reset-controller.h>
struct owl_reset_map {
u32 reg;
u32 bit;
};
struct owl_reset {
struct reset_controller_dev rcdev;
const struct owl_reset_map *reset_map;
struct regmap *regmap;
};
static inline struct owl_reset *to_owl_reset(struct reset_controller_dev *rcdev)
{
return container_of(rcdev, struct owl_reset, rcdev);
}
extern const struct reset_control_ops owl_reset_ops;
#endif /* _OWL_RESET_H_ */
...@@ -20,8 +20,10 @@ ...@@ -20,8 +20,10 @@
#include "owl-gate.h" #include "owl-gate.h"
#include "owl-mux.h" #include "owl-mux.h"
#include "owl-pll.h" #include "owl-pll.h"
#include "owl-reset.h"
#include <dt-bindings/clock/actions,s700-cmu.h> #include <dt-bindings/clock/actions,s700-cmu.h>
#include <dt-bindings/reset/actions,s700-reset.h>
#define CMU_COREPLL (0x0000) #define CMU_COREPLL (0x0000)
#define CMU_DEVPLL (0x0004) #define CMU_DEVPLL (0x0004)
...@@ -569,20 +571,69 @@ static struct clk_hw_onecell_data s700_hw_clks = { ...@@ -569,20 +571,69 @@ static struct clk_hw_onecell_data s700_hw_clks = {
.num = CLK_NR_CLKS, .num = CLK_NR_CLKS,
}; };
static const struct owl_clk_desc s700_clk_desc = { static const struct owl_reset_map s700_resets[] = {
[RESET_DE] = { CMU_DEVRST0, BIT(0) },
[RESET_LCD0] = { CMU_DEVRST0, BIT(1) },
[RESET_DSI] = { CMU_DEVRST0, BIT(2) },
[RESET_CSI] = { CMU_DEVRST0, BIT(13) },
[RESET_SI] = { CMU_DEVRST0, BIT(14) },
[RESET_I2C0] = { CMU_DEVRST1, BIT(0) },
[RESET_I2C1] = { CMU_DEVRST1, BIT(1) },
[RESET_I2C2] = { CMU_DEVRST1, BIT(2) },
[RESET_I2C3] = { CMU_DEVRST1, BIT(3) },
[RESET_SPI0] = { CMU_DEVRST1, BIT(4) },
[RESET_SPI1] = { CMU_DEVRST1, BIT(5) },
[RESET_SPI2] = { CMU_DEVRST1, BIT(6) },
[RESET_SPI3] = { CMU_DEVRST1, BIT(7) },
[RESET_UART0] = { CMU_DEVRST1, BIT(8) },
[RESET_UART1] = { CMU_DEVRST1, BIT(9) },
[RESET_UART2] = { CMU_DEVRST1, BIT(10) },
[RESET_UART3] = { CMU_DEVRST1, BIT(11) },
[RESET_UART4] = { CMU_DEVRST1, BIT(12) },
[RESET_UART5] = { CMU_DEVRST1, BIT(13) },
[RESET_UART6] = { CMU_DEVRST1, BIT(14) },
[RESET_KEY] = { CMU_DEVRST1, BIT(24) },
[RESET_GPIO] = { CMU_DEVRST1, BIT(25) },
[RESET_AUDIO] = { CMU_DEVRST1, BIT(29) },
};
static struct owl_clk_desc s700_clk_desc = {
.clks = s700_clks, .clks = s700_clks,
.num_clks = ARRAY_SIZE(s700_clks), .num_clks = ARRAY_SIZE(s700_clks),
.hw_clks = &s700_hw_clks, .hw_clks = &s700_hw_clks,
.resets = s700_resets,
.num_resets = ARRAY_SIZE(s700_resets),
}; };
static int s700_clk_probe(struct platform_device *pdev) static int s700_clk_probe(struct platform_device *pdev)
{ {
const struct owl_clk_desc *desc; struct owl_clk_desc *desc;
struct owl_reset *reset;
int ret;
desc = &s700_clk_desc; desc = &s700_clk_desc;
owl_clk_regmap_init(pdev, desc); owl_clk_regmap_init(pdev, desc);
/*
* FIXME: Reset controller registration should be moved to
* common code, once all SoCs of Owl family supports it.
*/
reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
if (!reset)
return -ENOMEM;
reset->rcdev.of_node = pdev->dev.of_node;
reset->rcdev.ops = &owl_reset_ops;
reset->rcdev.nr_resets = desc->num_resets;
reset->reset_map = desc->resets;
reset->regmap = desc->regmap;
ret = devm_reset_controller_register(&pdev->dev, &reset->rcdev);
if (ret)
dev_err(&pdev->dev, "Failed to register reset controller\n");
return owl_clk_probe(&pdev->dev, desc->hw_clks); return owl_clk_probe(&pdev->dev, desc->hw_clks);
} }
......
...@@ -19,8 +19,10 @@ ...@@ -19,8 +19,10 @@
#include "owl-gate.h" #include "owl-gate.h"
#include "owl-mux.h" #include "owl-mux.h"
#include "owl-pll.h" #include "owl-pll.h"
#include "owl-reset.h"
#include <dt-bindings/clock/actions,s900-cmu.h> #include <dt-bindings/clock/actions,s900-cmu.h>
#include <dt-bindings/reset/actions,s900-reset.h>
#define CMU_COREPLL (0x0000) #define CMU_COREPLL (0x0000)
#define CMU_DEVPLL (0x0004) #define CMU_DEVPLL (0x0004)
...@@ -684,20 +686,100 @@ static struct clk_hw_onecell_data s900_hw_clks = { ...@@ -684,20 +686,100 @@ static struct clk_hw_onecell_data s900_hw_clks = {
.num = CLK_NR_CLKS, .num = CLK_NR_CLKS,
}; };
static const struct owl_clk_desc s900_clk_desc = { static const struct owl_reset_map s900_resets[] = {
[RESET_DMAC] = { CMU_DEVRST0, BIT(0) },
[RESET_SRAMI] = { CMU_DEVRST0, BIT(1) },
[RESET_DDR_CTL_PHY] = { CMU_DEVRST0, BIT(2) },
[RESET_NANDC0] = { CMU_DEVRST0, BIT(3) },
[RESET_SD0] = { CMU_DEVRST0, BIT(4) },
[RESET_SD1] = { CMU_DEVRST0, BIT(5) },
[RESET_PCM1] = { CMU_DEVRST0, BIT(6) },
[RESET_DE] = { CMU_DEVRST0, BIT(7) },
[RESET_LVDS] = { CMU_DEVRST0, BIT(8) },
[RESET_SD2] = { CMU_DEVRST0, BIT(9) },
[RESET_DSI] = { CMU_DEVRST0, BIT(10) },
[RESET_CSI0] = { CMU_DEVRST0, BIT(11) },
[RESET_BISP_AXI] = { CMU_DEVRST0, BIT(12) },
[RESET_CSI1] = { CMU_DEVRST0, BIT(13) },
[RESET_GPIO] = { CMU_DEVRST0, BIT(15) },
[RESET_EDP] = { CMU_DEVRST0, BIT(16) },
[RESET_AUDIO] = { CMU_DEVRST0, BIT(17) },
[RESET_PCM0] = { CMU_DEVRST0, BIT(18) },
[RESET_HDE] = { CMU_DEVRST0, BIT(21) },
[RESET_GPU3D_PA] = { CMU_DEVRST0, BIT(22) },
[RESET_IMX] = { CMU_DEVRST0, BIT(23) },
[RESET_SE] = { CMU_DEVRST0, BIT(24) },
[RESET_NANDC1] = { CMU_DEVRST0, BIT(25) },
[RESET_SD3] = { CMU_DEVRST0, BIT(26) },
[RESET_GIC] = { CMU_DEVRST0, BIT(27) },
[RESET_GPU3D_PB] = { CMU_DEVRST0, BIT(28) },
[RESET_DDR_CTL_PHY_AXI] = { CMU_DEVRST0, BIT(29) },
[RESET_CMU_DDR] = { CMU_DEVRST0, BIT(30) },
[RESET_DMM] = { CMU_DEVRST0, BIT(31) },
[RESET_USB2HUB] = { CMU_DEVRST1, BIT(0) },
[RESET_USB2HSIC] = { CMU_DEVRST1, BIT(1) },
[RESET_HDMI] = { CMU_DEVRST1, BIT(2) },
[RESET_HDCP2TX] = { CMU_DEVRST1, BIT(3) },
[RESET_UART6] = { CMU_DEVRST1, BIT(4) },
[RESET_UART0] = { CMU_DEVRST1, BIT(5) },
[RESET_UART1] = { CMU_DEVRST1, BIT(6) },
[RESET_UART2] = { CMU_DEVRST1, BIT(7) },
[RESET_SPI0] = { CMU_DEVRST1, BIT(8) },
[RESET_SPI1] = { CMU_DEVRST1, BIT(9) },
[RESET_SPI2] = { CMU_DEVRST1, BIT(10) },
[RESET_SPI3] = { CMU_DEVRST1, BIT(11) },
[RESET_I2C0] = { CMU_DEVRST1, BIT(12) },
[RESET_I2C1] = { CMU_DEVRST1, BIT(13) },
[RESET_USB3] = { CMU_DEVRST1, BIT(14) },
[RESET_UART3] = { CMU_DEVRST1, BIT(15) },
[RESET_UART4] = { CMU_DEVRST1, BIT(16) },
[RESET_UART5] = { CMU_DEVRST1, BIT(17) },
[RESET_I2C2] = { CMU_DEVRST1, BIT(18) },
[RESET_I2C3] = { CMU_DEVRST1, BIT(19) },
[RESET_ETHERNET] = { CMU_DEVRST1, BIT(20) },
[RESET_CHIPID] = { CMU_DEVRST1, BIT(21) },
[RESET_I2C4] = { CMU_DEVRST1, BIT(22) },
[RESET_I2C5] = { CMU_DEVRST1, BIT(23) },
[RESET_CPU_SCNT] = { CMU_DEVRST1, BIT(30) }
};
static struct owl_clk_desc s900_clk_desc = {
.clks = s900_clks, .clks = s900_clks,
.num_clks = ARRAY_SIZE(s900_clks), .num_clks = ARRAY_SIZE(s900_clks),
.hw_clks = &s900_hw_clks, .hw_clks = &s900_hw_clks,
.resets = s900_resets,
.num_resets = ARRAY_SIZE(s900_resets),
}; };
static int s900_clk_probe(struct platform_device *pdev) static int s900_clk_probe(struct platform_device *pdev)
{ {
const struct owl_clk_desc *desc; struct owl_clk_desc *desc;
struct owl_reset *reset;
int ret;
desc = &s900_clk_desc; desc = &s900_clk_desc;
owl_clk_regmap_init(pdev, desc); owl_clk_regmap_init(pdev, desc);
/*
* FIXME: Reset controller registration should be moved to
* common code, once all SoCs of Owl family supports it.
*/
reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
if (!reset)
return -ENOMEM;
reset->rcdev.of_node = pdev->dev.of_node;
reset->rcdev.ops = &owl_reset_ops;
reset->rcdev.nr_resets = desc->num_resets;
reset->reset_map = desc->resets;
reset->regmap = desc->regmap;
ret = devm_reset_controller_register(&pdev->dev, &reset->rcdev);
if (ret)
dev_err(&pdev->dev, "Failed to register reset controller\n");
return owl_clk_probe(&pdev->dev, desc->hw_clks); return owl_clk_probe(&pdev->dev, desc->hw_clks);
} }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# Makefile for at91 specific clk # Makefile for at91 specific clk
# #
obj-y += pmc.o sckc.o obj-y += pmc.o sckc.o dt-compat.o
obj-y += clk-slow.o clk-main.o clk-pll.o clk-plldiv.o clk-master.o obj-y += clk-slow.o clk-main.o clk-pll.o clk-plldiv.o clk-master.o
obj-y += clk-system.o clk-peripheral.o clk-programmable.o obj-y += clk-system.o clk-peripheral.o clk-programmable.o
...@@ -14,3 +14,6 @@ obj-$(CONFIG_HAVE_AT91_SMD) += clk-smd.o ...@@ -14,3 +14,6 @@ obj-$(CONFIG_HAVE_AT91_SMD) += clk-smd.o
obj-$(CONFIG_HAVE_AT91_H32MX) += clk-h32mx.o obj-$(CONFIG_HAVE_AT91_H32MX) += clk-h32mx.o
obj-$(CONFIG_HAVE_AT91_GENERATED_CLK) += clk-generated.o obj-$(CONFIG_HAVE_AT91_GENERATED_CLK) += clk-generated.o
obj-$(CONFIG_HAVE_AT91_I2S_MUX_CLK) += clk-i2s-mux.o obj-$(CONFIG_HAVE_AT91_I2S_MUX_CLK) += clk-i2s-mux.o
obj-$(CONFIG_SOC_AT91SAM9) += at91sam9260.o at91sam9rl.o at91sam9x5.o
obj-$(CONFIG_SOC_SAMA5D4) += sama5d4.o
obj-$(CONFIG_SOC_SAMA5D2) += sama5d2.o
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0
#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
#include <linux/slab.h>
#include <dt-bindings/clock/at91.h>
#include "pmc.h"
static const struct clk_master_characteristics sam9rl_mck_characteristics = {
.output = { .min = 0, .max = 94000000 },
.divisors = { 1, 2, 4, 0 },
};
static u8 sam9rl_plla_out[] = { 0, 2 };
static struct clk_range sam9rl_plla_outputs[] = {
{ .min = 80000000, .max = 200000000 },
{ .min = 190000000, .max = 240000000 },
};
static const struct clk_pll_characteristics sam9rl_plla_characteristics = {
.input = { .min = 1000000, .max = 32000000 },
.num_output = ARRAY_SIZE(sam9rl_plla_outputs),
.output = sam9rl_plla_outputs,
.out = sam9rl_plla_out,
};
static const struct {
char *n;
char *p;
u8 id;
} at91sam9rl_systemck[] = {
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
};
static const struct {
char *n;
u8 id;
} at91sam9rl_periphck[] = {
{ .n = "pioA_clk", .id = 2, },
{ .n = "pioB_clk", .id = 3, },
{ .n = "pioC_clk", .id = 4, },
{ .n = "pioD_clk", .id = 5, },
{ .n = "usart0_clk", .id = 6, },
{ .n = "usart1_clk", .id = 7, },
{ .n = "usart2_clk", .id = 8, },
{ .n = "usart3_clk", .id = 9, },
{ .n = "mci0_clk", .id = 10, },
{ .n = "twi0_clk", .id = 11, },
{ .n = "twi1_clk", .id = 12, },
{ .n = "spi0_clk", .id = 13, },
{ .n = "ssc0_clk", .id = 14, },
{ .n = "ssc1_clk", .id = 15, },
{ .n = "tc0_clk", .id = 16, },
{ .n = "tc1_clk", .id = 17, },
{ .n = "tc2_clk", .id = 18, },
{ .n = "pwm_clk", .id = 19, },
{ .n = "adc_clk", .id = 20, },
{ .n = "dma0_clk", .id = 21, },
{ .n = "udphs_clk", .id = 22, },
{ .n = "lcd_clk", .id = 23, },
};
static void __init at91sam9rl_pmc_setup(struct device_node *np)
{
const char *slck_name, *mainxtal_name;
struct pmc_data *at91sam9rl_pmc;
const char *parent_names[6];
struct regmap *regmap;
struct clk_hw *hw;
int i;
i = of_property_match_string(np, "clock-names", "slow_clk");
if (i < 0)
return;
slck_name = of_clk_get_parent_name(np, i);
i = of_property_match_string(np, "clock-names", "main_xtal");
if (i < 0)
return;
mainxtal_name = of_clk_get_parent_name(np, i);
regmap = syscon_node_to_regmap(np);
if (IS_ERR(regmap))
return;
at91sam9rl_pmc = pmc_data_allocate(PMC_MAIN + 1,
nck(at91sam9rl_systemck),
nck(at91sam9rl_periphck), 0);
if (!at91sam9rl_pmc)
return;
hw = at91_clk_register_rm9200_main(regmap, "mainck", mainxtal_name);
if (IS_ERR(hw))
goto err_free;
at91sam9rl_pmc->chws[PMC_MAIN] = hw;
hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
&at91rm9200_pll_layout,
&sam9rl_plla_characteristics);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
if (IS_ERR(hw))
goto err_free;
at91sam9rl_pmc->chws[PMC_UTMI] = hw;
parent_names[0] = slck_name;
parent_names[1] = "mainck";
parent_names[2] = "pllack";
parent_names[3] = "utmick";
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
&at91rm9200_master_layout,
&sam9rl_mck_characteristics);
if (IS_ERR(hw))
goto err_free;
at91sam9rl_pmc->chws[PMC_MCK] = hw;
parent_names[0] = slck_name;
parent_names[1] = "mainck";
parent_names[2] = "pllack";
parent_names[3] = "utmick";
parent_names[4] = "masterck";
for (i = 0; i < 2; i++) {
char name[6];
snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
parent_names, 5, i,
&at91rm9200_programmable_layout);
if (IS_ERR(hw))
goto err_free;
}
for (i = 0; i < ARRAY_SIZE(at91sam9rl_systemck); i++) {
hw = at91_clk_register_system(regmap, at91sam9rl_systemck[i].n,
at91sam9rl_systemck[i].p,
at91sam9rl_systemck[i].id);
if (IS_ERR(hw))
goto err_free;
at91sam9rl_pmc->shws[at91sam9rl_systemck[i].id] = hw;
}
for (i = 0; i < ARRAY_SIZE(at91sam9rl_periphck); i++) {
hw = at91_clk_register_peripheral(regmap,
at91sam9rl_periphck[i].n,
"masterck",
at91sam9rl_periphck[i].id);
if (IS_ERR(hw))
goto err_free;
at91sam9rl_pmc->phws[at91sam9rl_periphck[i].id] = hw;
}
of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9rl_pmc);
return;
err_free:
pmc_data_free(at91sam9rl_pmc);
}
CLK_OF_DECLARE_DRIVER(at91sam9rl_pmc, "atmel,at91sam9rl-pmc", at91sam9rl_pmc_setup);
// SPDX-License-Identifier: GPL-2.0
#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
#include <linux/slab.h>
#include <dt-bindings/clock/at91.h>
#include "pmc.h"
static const struct clk_master_characteristics mck_characteristics = {
.output = { .min = 0, .max = 133333333 },
.divisors = { 1, 2, 4, 3 },
.have_div3_pres = 1,
};
static u8 plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 };
static u16 plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 };
static struct clk_range plla_outputs[] = {
{ .min = 745000000, .max = 800000000 },
{ .min = 695000000, .max = 750000000 },
{ .min = 645000000, .max = 700000000 },
{ .min = 595000000, .max = 650000000 },
{ .min = 545000000, .max = 600000000 },
{ .min = 495000000, .max = 555000000 },
{ .min = 445000000, .max = 500000000 },
{ .min = 400000000, .max = 450000000 },
};
static const struct clk_pll_characteristics plla_characteristics = {
.input = { .min = 2000000, .max = 32000000 },
.num_output = ARRAY_SIZE(plla_outputs),
.output = plla_outputs,
.icpll = plla_icpll,
.out = plla_out,
};
static const struct {
char *n;
char *p;
u8 id;
} at91sam9x5_systemck[] = {
{ .n = "ddrck", .p = "masterck", .id = 2 },
{ .n = "smdck", .p = "smdclk", .id = 4 },
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "udpck", .p = "usbck", .id = 7 },
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
};
struct pck {
char *n;
u8 id;
};
static const struct pck at91sam9x5_periphck[] = {
{ .n = "pioAB_clk", .id = 2, },
{ .n = "pioCD_clk", .id = 3, },
{ .n = "smd_clk", .id = 4, },
{ .n = "usart0_clk", .id = 5, },
{ .n = "usart1_clk", .id = 6, },
{ .n = "usart2_clk", .id = 7, },
{ .n = "twi0_clk", .id = 9, },
{ .n = "twi1_clk", .id = 10, },
{ .n = "twi2_clk", .id = 11, },
{ .n = "mci0_clk", .id = 12, },
{ .n = "spi0_clk", .id = 13, },
{ .n = "spi1_clk", .id = 14, },
{ .n = "uart0_clk", .id = 15, },
{ .n = "uart1_clk", .id = 16, },
{ .n = "tcb0_clk", .id = 17, },
{ .n = "pwm_clk", .id = 18, },
{ .n = "adc_clk", .id = 19, },
{ .n = "dma0_clk", .id = 20, },
{ .n = "dma1_clk", .id = 21, },
{ .n = "uhphs_clk", .id = 22, },
{ .n = "udphs_clk", .id = 23, },
{ .n = "mci1_clk", .id = 26, },
{ .n = "ssc0_clk", .id = 28, },
};
static const struct pck at91sam9g15_periphck[] = {
{ .n = "lcdc_clk", .id = 25, },
{ /* sentinel */}
};
static const struct pck at91sam9g25_periphck[] = {
{ .n = "usart3_clk", .id = 8, },
{ .n = "macb0_clk", .id = 24, },
{ .n = "isi_clk", .id = 25, },
{ /* sentinel */}
};
static const struct pck at91sam9g35_periphck[] = {
{ .n = "macb0_clk", .id = 24, },
{ .n = "lcdc_clk", .id = 25, },
{ /* sentinel */}
};
static const struct pck at91sam9x25_periphck[] = {
{ .n = "usart3_clk", .id = 8, },
{ .n = "macb0_clk", .id = 24, },
{ .n = "macb1_clk", .id = 27, },
{ .n = "can0_clk", .id = 29, },
{ .n = "can1_clk", .id = 30, },
{ /* sentinel */}
};
static const struct pck at91sam9x35_periphck[] = {
{ .n = "macb0_clk", .id = 24, },
{ .n = "lcdc_clk", .id = 25, },
{ .n = "can0_clk", .id = 29, },
{ .n = "can1_clk", .id = 30, },
{ /* sentinel */}
};
static void __init at91sam9x5_pmc_setup(struct device_node *np,
const struct pck *extra_pcks,
bool has_lcdck)
{
struct clk_range range = CLK_RANGE(0, 0);
const char *slck_name, *mainxtal_name;
struct pmc_data *at91sam9x5_pmc;
const char *parent_names[6];
struct regmap *regmap;
struct clk_hw *hw;
int i;
bool bypass;
i = of_property_match_string(np, "clock-names", "slow_clk");
if (i < 0)
return;
slck_name = of_clk_get_parent_name(np, i);
i = of_property_match_string(np, "clock-names", "main_xtal");
if (i < 0)
return;
mainxtal_name = of_clk_get_parent_name(np, i);
regmap = syscon_node_to_regmap(np);
if (IS_ERR(regmap))
return;
at91sam9x5_pmc = pmc_data_allocate(PMC_MAIN + 1,
nck(at91sam9x5_systemck),
nck(at91sam9x35_periphck), 0);
if (!at91sam9x5_pmc)
return;
hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
50000000);
if (IS_ERR(hw))
goto err_free;
bypass = of_property_read_bool(np, "atmel,osc-bypass");
hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
bypass);
if (IS_ERR(hw))
goto err_free;
parent_names[0] = "main_rc_osc";
parent_names[1] = "main_osc";
hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
if (IS_ERR(hw))
goto err_free;
at91sam9x5_pmc->chws[PMC_MAIN] = hw;
hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
&at91rm9200_pll_layout, &plla_characteristics);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_plldiv(regmap, "plladivck", "pllack");
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
if (IS_ERR(hw))
goto err_free;
at91sam9x5_pmc->chws[PMC_UTMI] = hw;
parent_names[0] = slck_name;
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
&at91sam9x5_master_layout,
&mck_characteristics);
if (IS_ERR(hw))
goto err_free;
at91sam9x5_pmc->chws[PMC_MCK] = hw;
parent_names[0] = "plladivck";
parent_names[1] = "utmick";
hw = at91sam9x5_clk_register_usb(regmap, "usbck", parent_names, 2);
if (IS_ERR(hw))
goto err_free;
hw = at91sam9x5_clk_register_smd(regmap, "smdclk", parent_names, 2);
if (IS_ERR(hw))
goto err_free;
parent_names[0] = slck_name;
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
parent_names[4] = "mck";
for (i = 0; i < 2; i++) {
char name[6];
snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
parent_names, 5, i,
&at91sam9x5_programmable_layout);
if (IS_ERR(hw))
goto err_free;
}
for (i = 0; i < ARRAY_SIZE(at91sam9x5_systemck); i++) {
hw = at91_clk_register_system(regmap, at91sam9x5_systemck[i].n,
at91sam9x5_systemck[i].p,
at91sam9x5_systemck[i].id);
if (IS_ERR(hw))
goto err_free;
at91sam9x5_pmc->shws[at91sam9x5_systemck[i].id] = hw;
}
if (has_lcdck) {
hw = at91_clk_register_system(regmap, "lcdck", "masterck", 3);
if (IS_ERR(hw))
goto err_free;
at91sam9x5_pmc->shws[3] = hw;
}
for (i = 0; i < ARRAY_SIZE(at91sam9x5_periphck); i++) {
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
at91sam9x5_periphck[i].n,
"masterck",
at91sam9x5_periphck[i].id,
&range);
if (IS_ERR(hw))
goto err_free;
at91sam9x5_pmc->phws[at91sam9x5_periphck[i].id] = hw;
}
for (i = 0; extra_pcks[i].id; i++) {
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
extra_pcks[i].n,
"masterck",
extra_pcks[i].id,
&range);
if (IS_ERR(hw))
goto err_free;
at91sam9x5_pmc->phws[extra_pcks[i].id] = hw;
}
of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9x5_pmc);
return;
err_free:
pmc_data_free(at91sam9x5_pmc);
}
static void __init at91sam9g15_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9g15_periphck, true);
}
CLK_OF_DECLARE_DRIVER(at91sam9g15_pmc, "atmel,at91sam9g15-pmc",
at91sam9g15_pmc_setup);
static void __init at91sam9g25_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9g25_periphck, false);
}
CLK_OF_DECLARE_DRIVER(at91sam9g25_pmc, "atmel,at91sam9g25-pmc",
at91sam9g25_pmc_setup);
static void __init at91sam9g35_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9g35_periphck, true);
}
CLK_OF_DECLARE_DRIVER(at91sam9g35_pmc, "atmel,at91sam9g35-pmc",
at91sam9g35_pmc_setup);
static void __init at91sam9x25_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9x25_periphck, false);
}
CLK_OF_DECLARE_DRIVER(at91sam9x25_pmc, "atmel,at91sam9x25-pmc",
at91sam9x25_pmc_setup);
static void __init at91sam9x35_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9x35_periphck, true);
}
CLK_OF_DECLARE_DRIVER(at91sam9x35_pmc, "atmel,at91sam9x35-pmc",
at91sam9x35_pmc_setup);
...@@ -43,6 +43,8 @@ ...@@ -43,6 +43,8 @@
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "pmc.h"
#define AUDIO_PLL_DIV_FRAC BIT(22) #define AUDIO_PLL_DIV_FRAC BIT(22)
#define AUDIO_PLL_ND_MAX (AT91_PMC_AUDIO_PLL_ND_MASK >> \ #define AUDIO_PLL_ND_MAX (AT91_PMC_AUDIO_PLL_ND_MASK >> \
AT91_PMC_AUDIO_PLL_ND_OFFSET) AT91_PMC_AUDIO_PLL_ND_OFFSET)
...@@ -444,93 +446,94 @@ static const struct clk_ops audio_pll_pmc_ops = { ...@@ -444,93 +446,94 @@ static const struct clk_ops audio_pll_pmc_ops = {
.set_rate = clk_audio_pll_pmc_set_rate, .set_rate = clk_audio_pll_pmc_set_rate,
}; };
static int of_sama5d2_clk_audio_pll_setup(struct device_node *np, struct clk_hw * __init
struct clk_init_data *init, at91_clk_register_audio_pll_frac(struct regmap *regmap, const char *name,
struct clk_hw *hw, const char *parent_name)
struct regmap **clk_audio_regmap)
{
struct regmap *regmap;
const char *parent_names[1];
int ret;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return PTR_ERR(regmap);
init->name = np->name;
of_clk_parent_fill(np, parent_names, 1);
init->parent_names = parent_names;
init->num_parents = 1;
hw->init = init;
*clk_audio_regmap = regmap;
ret = clk_hw_register(NULL, hw);
if (ret)
return ret;
return of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np)
{ {
struct clk_audio_frac *frac_ck; struct clk_audio_frac *frac_ck;
struct clk_init_data init = {}; struct clk_init_data init = {};
int ret;
frac_ck = kzalloc(sizeof(*frac_ck), GFP_KERNEL); frac_ck = kzalloc(sizeof(*frac_ck), GFP_KERNEL);
if (!frac_ck) if (!frac_ck)
return; return ERR_PTR(-ENOMEM);
init.name = name;
init.ops = &audio_pll_frac_ops; init.ops = &audio_pll_frac_ops;
init.parent_names = &parent_name;
init.num_parents = 1;
init.flags = CLK_SET_RATE_GATE; init.flags = CLK_SET_RATE_GATE;
if (of_sama5d2_clk_audio_pll_setup(np, &init, &frac_ck->hw, frac_ck->hw.init = &init;
&frac_ck->regmap)) frac_ck->regmap = regmap;
ret = clk_hw_register(NULL, &frac_ck->hw);
if (ret) {
kfree(frac_ck); kfree(frac_ck);
return ERR_PTR(ret);
}
return &frac_ck->hw;
} }
static void __init of_sama5d2_clk_audio_pll_pad_setup(struct device_node *np) struct clk_hw * __init
at91_clk_register_audio_pll_pad(struct regmap *regmap, const char *name,
const char *parent_name)
{ {
struct clk_audio_pad *apad_ck; struct clk_audio_pad *apad_ck;
struct clk_init_data init = {}; struct clk_init_data init;
int ret;
apad_ck = kzalloc(sizeof(*apad_ck), GFP_KERNEL); apad_ck = kzalloc(sizeof(*apad_ck), GFP_KERNEL);
if (!apad_ck) if (!apad_ck)
return; return ERR_PTR(-ENOMEM);
init.name = name;
init.ops = &audio_pll_pad_ops; init.ops = &audio_pll_pad_ops;
init.parent_names = &parent_name;
init.num_parents = 1;
init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
CLK_SET_RATE_PARENT; CLK_SET_RATE_PARENT;
if (of_sama5d2_clk_audio_pll_setup(np, &init, &apad_ck->hw, apad_ck->hw.init = &init;
&apad_ck->regmap)) apad_ck->regmap = regmap;
ret = clk_hw_register(NULL, &apad_ck->hw);
if (ret) {
kfree(apad_ck); kfree(apad_ck);
return ERR_PTR(ret);
}
return &apad_ck->hw;
} }
static void __init of_sama5d2_clk_audio_pll_pmc_setup(struct device_node *np) struct clk_hw * __init
at91_clk_register_audio_pll_pmc(struct regmap *regmap, const char *name,
const char *parent_name)
{ {
struct clk_audio_pad *apmc_ck; struct clk_audio_pmc *apmc_ck;
struct clk_init_data init = {}; struct clk_init_data init;
int ret;
apmc_ck = kzalloc(sizeof(*apmc_ck), GFP_KERNEL); apmc_ck = kzalloc(sizeof(*apmc_ck), GFP_KERNEL);
if (!apmc_ck) if (!apmc_ck)
return; return ERR_PTR(-ENOMEM);
init.name = name;
init.ops = &audio_pll_pmc_ops; init.ops = &audio_pll_pmc_ops;
init.parent_names = &parent_name;
init.num_parents = 1;
init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
CLK_SET_RATE_PARENT; CLK_SET_RATE_PARENT;
if (of_sama5d2_clk_audio_pll_setup(np, &init, &apmc_ck->hw, apmc_ck->hw.init = &init;
&apmc_ck->regmap)) apmc_ck->regmap = regmap;
ret = clk_hw_register(NULL, &apmc_ck->hw);
if (ret) {
kfree(apmc_ck); kfree(apmc_ck);
} return ERR_PTR(ret);
}
CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_frac_setup, return &apmc_ck->hw;
"atmel,sama5d2-clk-audio-pll-frac", }
of_sama5d2_clk_audio_pll_frac_setup);
CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pad_setup,
"atmel,sama5d2-clk-audio-pll-pad",
of_sama5d2_clk_audio_pll_pad_setup);
CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pmc_setup,
"atmel,sama5d2-clk-audio-pll-pmc",
of_sama5d2_clk_audio_pll_pmc_setup);
...@@ -20,17 +20,8 @@ ...@@ -20,17 +20,8 @@
#include "pmc.h" #include "pmc.h"
#define PERIPHERAL_MAX 64
#define PERIPHERAL_ID_MIN 2
#define GENERATED_SOURCE_MAX 6
#define GENERATED_MAX_DIV 255 #define GENERATED_MAX_DIV 255
#define GCK_ID_SSC0 43
#define GCK_ID_SSC1 44
#define GCK_ID_I2S0 54
#define GCK_ID_I2S1 55
#define GCK_ID_CLASSD 59
#define GCK_INDEX_DT_AUDIO_PLL 5 #define GCK_INDEX_DT_AUDIO_PLL 5
struct clk_generated { struct clk_generated {
...@@ -279,10 +270,10 @@ static void clk_generated_startup(struct clk_generated *gck) ...@@ -279,10 +270,10 @@ static void clk_generated_startup(struct clk_generated *gck)
>> AT91_PMC_PCR_GCKDIV_OFFSET; >> AT91_PMC_PCR_GCKDIV_OFFSET;
} }
static struct clk_hw * __init struct clk_hw * __init
at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock, at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
const char *name, const char **parent_names, const char *name, const char **parent_names,
u8 num_parents, u8 id, u8 num_parents, u8 id, bool pll_audio,
const struct clk_range *range) const struct clk_range *range)
{ {
struct clk_generated *gck; struct clk_generated *gck;
...@@ -306,6 +297,7 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock, ...@@ -306,6 +297,7 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
gck->regmap = regmap; gck->regmap = regmap;
gck->lock = lock; gck->lock = lock;
gck->range = *range; gck->range = *range;
gck->audio_pll_allowed = pll_audio;
clk_generated_startup(gck); clk_generated_startup(gck);
hw = &gck->hw; hw = &gck->hw;
...@@ -319,70 +311,3 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock, ...@@ -319,70 +311,3 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
return hw; return hw;
} }
static void __init of_sama5d2_clk_generated_setup(struct device_node *np)
{
int num;
u32 id;
const char *name;
struct clk_hw *hw;
unsigned int num_parents;
const char *parent_names[GENERATED_SOURCE_MAX];
struct device_node *gcknp;
struct clk_range range = CLK_RANGE(0, 0);
struct regmap *regmap;
struct clk_generated *gck;
num_parents = of_clk_get_parent_count(np);
if (num_parents == 0 || num_parents > GENERATED_SOURCE_MAX)
return;
of_clk_parent_fill(np, parent_names, num_parents);
num = of_get_child_count(np);
if (!num || num > PERIPHERAL_MAX)
return;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
for_each_child_of_node(np, gcknp) {
if (of_property_read_u32(gcknp, "reg", &id))
continue;
if (id < PERIPHERAL_ID_MIN || id >= PERIPHERAL_MAX)
continue;
if (of_property_read_string(np, "clock-output-names", &name))
name = gcknp->name;
of_at91_get_clk_range(gcknp, "atmel,clk-output-range",
&range);
hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, name,
parent_names, num_parents,
id, &range);
gck = to_clk_generated(hw);
if (of_device_is_compatible(np,
"atmel,sama5d2-clk-generated")) {
if (gck->id == GCK_ID_SSC0 || gck->id == GCK_ID_SSC1 ||
gck->id == GCK_ID_I2S0 || gck->id == GCK_ID_I2S1 ||
gck->id == GCK_ID_CLASSD)
gck->audio_pll_allowed = true;
else
gck->audio_pll_allowed = false;
} else {
gck->audio_pll_allowed = false;
}
if (IS_ERR(hw))
continue;
of_clk_add_hw_provider(gcknp, of_clk_hw_simple_get, hw);
}
}
CLK_OF_DECLARE(of_sama5d2_clk_generated_setup, "atmel,sama5d2-clk-generated",
of_sama5d2_clk_generated_setup);
...@@ -86,25 +86,19 @@ static const struct clk_ops h32mx_ops = { ...@@ -86,25 +86,19 @@ static const struct clk_ops h32mx_ops = {
.set_rate = clk_sama5d4_h32mx_set_rate, .set_rate = clk_sama5d4_h32mx_set_rate,
}; };
static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np) struct clk_hw * __init
at91_clk_register_h32mx(struct regmap *regmap, const char *name,
const char *parent_name)
{ {
struct clk_sama5d4_h32mx *h32mxclk; struct clk_sama5d4_h32mx *h32mxclk;
struct clk_init_data init; struct clk_init_data init;
const char *parent_name;
struct regmap *regmap;
int ret; int ret;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
h32mxclk = kzalloc(sizeof(*h32mxclk), GFP_KERNEL); h32mxclk = kzalloc(sizeof(*h32mxclk), GFP_KERNEL);
if (!h32mxclk) if (!h32mxclk)
return; return ERR_PTR(-ENOMEM);
parent_name = of_clk_get_parent_name(np, 0);
init.name = np->name; init.name = name;
init.ops = &h32mx_ops; init.ops = &h32mx_ops;
init.parent_names = parent_name ? &parent_name : NULL; init.parent_names = parent_name ? &parent_name : NULL;
init.num_parents = parent_name ? 1 : 0; init.num_parents = parent_name ? 1 : 0;
...@@ -116,10 +110,8 @@ static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np) ...@@ -116,10 +110,8 @@ static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np)
ret = clk_hw_register(NULL, &h32mxclk->hw); ret = clk_hw_register(NULL, &h32mxclk->hw);
if (ret) { if (ret) {
kfree(h32mxclk); kfree(h32mxclk);
return; return ERR_PTR(ret);
} }
of_clk_add_hw_provider(np, of_clk_hw_simple_get, &h32mxclk->hw); return &h32mxclk->hw;
} }
CLK_OF_DECLARE(of_sama5d4_clk_h32mx_setup, "atmel,sama5d4-clk-h32mx",
of_sama5d4_clk_h32mx_setup);
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#include <soc/at91/atmel-sfr.h> #include <soc/at91/atmel-sfr.h>
#define I2S_BUS_NR 2 #include "pmc.h"
struct clk_i2s_mux { struct clk_i2s_mux {
struct clk_hw hw; struct clk_hw hw;
...@@ -48,7 +48,7 @@ static const struct clk_ops clk_i2s_mux_ops = { ...@@ -48,7 +48,7 @@ static const struct clk_ops clk_i2s_mux_ops = {
.determine_rate = __clk_mux_determine_rate, .determine_rate = __clk_mux_determine_rate,
}; };
static struct clk_hw * __init struct clk_hw * __init
at91_clk_i2s_mux_register(struct regmap *regmap, const char *name, at91_clk_i2s_mux_register(struct regmap *regmap, const char *name,
const char * const *parent_names, const char * const *parent_names,
unsigned int num_parents, u8 bus_id) unsigned int num_parents, u8 bus_id)
...@@ -78,39 +78,3 @@ at91_clk_i2s_mux_register(struct regmap *regmap, const char *name, ...@@ -78,39 +78,3 @@ at91_clk_i2s_mux_register(struct regmap *regmap, const char *name,
return &i2s_ck->hw; return &i2s_ck->hw;
} }
static void __init of_sama5d2_clk_i2s_mux_setup(struct device_node *np)
{
struct regmap *regmap_sfr;
u8 bus_id;
const char *parent_names[2];
struct device_node *i2s_mux_np;
struct clk_hw *hw;
int ret;
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
if (IS_ERR(regmap_sfr))
return;
for_each_child_of_node(np, i2s_mux_np) {
if (of_property_read_u8(i2s_mux_np, "reg", &bus_id))
continue;
if (bus_id > I2S_BUS_NR)
continue;
ret = of_clk_parent_fill(i2s_mux_np, parent_names, 2);
if (ret != 2)
continue;
hw = at91_clk_i2s_mux_register(regmap_sfr, i2s_mux_np->name,
parent_names, 2, bus_id);
if (IS_ERR(hw))
continue;
of_clk_add_hw_provider(i2s_mux_np, of_clk_hw_simple_get, hw);
}
}
CLK_OF_DECLARE(sama5d2_clk_i2s_mux, "atmel,sama5d2-clk-i2s-mux",
of_sama5d2_clk_i2s_mux_setup);
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include <linux/clkdev.h> #include <linux/clkdev.h>
#include <linux/clk/at91_pmc.h> #include <linux/clk/at91_pmc.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/of.h>
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/regmap.h> #include <linux/regmap.h>
...@@ -128,7 +127,7 @@ static const struct clk_ops main_osc_ops = { ...@@ -128,7 +127,7 @@ static const struct clk_ops main_osc_ops = {
.is_prepared = clk_main_osc_is_prepared, .is_prepared = clk_main_osc_is_prepared,
}; };
static struct clk_hw * __init struct clk_hw * __init
at91_clk_register_main_osc(struct regmap *regmap, at91_clk_register_main_osc(struct regmap *regmap,
const char *name, const char *name,
const char *parent_name, const char *parent_name,
...@@ -171,31 +170,6 @@ at91_clk_register_main_osc(struct regmap *regmap, ...@@ -171,31 +170,6 @@ at91_clk_register_main_osc(struct regmap *regmap,
return hw; return hw;
} }
static void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *name = np->name;
const char *parent_name;
struct regmap *regmap;
bool bypass;
of_property_read_string(np, "clock-output-names", &name);
bypass = of_property_read_bool(np, "atmel,osc-bypass");
parent_name = of_clk_get_parent_name(np, 0);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91_clk_register_main_osc(regmap, name, parent_name, bypass);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91rm9200_clk_main_osc, "atmel,at91rm9200-clk-main-osc",
of_at91rm9200_clk_main_osc_setup);
static bool clk_main_rc_osc_ready(struct regmap *regmap) static bool clk_main_rc_osc_ready(struct regmap *regmap)
{ {
unsigned int status; unsigned int status;
...@@ -275,7 +249,7 @@ static const struct clk_ops main_rc_osc_ops = { ...@@ -275,7 +249,7 @@ static const struct clk_ops main_rc_osc_ops = {
.recalc_accuracy = clk_main_rc_osc_recalc_accuracy, .recalc_accuracy = clk_main_rc_osc_recalc_accuracy,
}; };
static struct clk_hw * __init struct clk_hw * __init
at91_clk_register_main_rc_osc(struct regmap *regmap, at91_clk_register_main_rc_osc(struct regmap *regmap,
const char *name, const char *name,
u32 frequency, u32 accuracy) u32 frequency, u32 accuracy)
...@@ -313,32 +287,6 @@ at91_clk_register_main_rc_osc(struct regmap *regmap, ...@@ -313,32 +287,6 @@ at91_clk_register_main_rc_osc(struct regmap *regmap,
return hw; return hw;
} }
static void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np)
{
struct clk_hw *hw;
u32 frequency = 0;
u32 accuracy = 0;
const char *name = np->name;
struct regmap *regmap;
of_property_read_string(np, "clock-output-names", &name);
of_property_read_u32(np, "clock-frequency", &frequency);
of_property_read_u32(np, "clock-accuracy", &accuracy);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91_clk_register_main_rc_osc(regmap, name, frequency, accuracy);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9x5_clk_main_rc_osc, "atmel,at91sam9x5-clk-main-rc-osc",
of_at91sam9x5_clk_main_rc_osc_setup);
static int clk_main_probe_frequency(struct regmap *regmap) static int clk_main_probe_frequency(struct regmap *regmap)
{ {
unsigned long prep_time, timeout; unsigned long prep_time, timeout;
...@@ -403,7 +351,7 @@ static const struct clk_ops rm9200_main_ops = { ...@@ -403,7 +351,7 @@ static const struct clk_ops rm9200_main_ops = {
.recalc_rate = clk_rm9200_main_recalc_rate, .recalc_rate = clk_rm9200_main_recalc_rate,
}; };
static struct clk_hw * __init struct clk_hw * __init
at91_clk_register_rm9200_main(struct regmap *regmap, at91_clk_register_rm9200_main(struct regmap *regmap,
const char *name, const char *name,
const char *parent_name) const char *parent_name)
...@@ -442,29 +390,6 @@ at91_clk_register_rm9200_main(struct regmap *regmap, ...@@ -442,29 +390,6 @@ at91_clk_register_rm9200_main(struct regmap *regmap,
return hw; return hw;
} }
static void __init of_at91rm9200_clk_main_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_name;
const char *name = np->name;
struct regmap *regmap;
parent_name = of_clk_get_parent_name(np, 0);
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91_clk_register_rm9200_main(regmap, name, parent_name);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91rm9200_clk_main, "atmel,at91rm9200-clk-main",
of_at91rm9200_clk_main_setup);
static inline bool clk_sam9x5_main_ready(struct regmap *regmap) static inline bool clk_sam9x5_main_ready(struct regmap *regmap)
{ {
unsigned int status; unsigned int status;
...@@ -541,7 +466,7 @@ static const struct clk_ops sam9x5_main_ops = { ...@@ -541,7 +466,7 @@ static const struct clk_ops sam9x5_main_ops = {
.get_parent = clk_sam9x5_main_get_parent, .get_parent = clk_sam9x5_main_get_parent,
}; };
static struct clk_hw * __init struct clk_hw * __init
at91_clk_register_sam9x5_main(struct regmap *regmap, at91_clk_register_sam9x5_main(struct regmap *regmap,
const char *name, const char *name,
const char **parent_names, const char **parent_names,
...@@ -583,32 +508,3 @@ at91_clk_register_sam9x5_main(struct regmap *regmap, ...@@ -583,32 +508,3 @@ at91_clk_register_sam9x5_main(struct regmap *regmap,
return hw; return hw;
} }
static void __init of_at91sam9x5_clk_main_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_names[2];
unsigned int num_parents;
const char *name = np->name;
struct regmap *regmap;
num_parents = of_clk_get_parent_count(np);
if (num_parents == 0 || num_parents > 2)
return;
of_clk_parent_fill(np, parent_names, num_parents);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
of_property_read_string(np, "clock-output-names", &name);
hw = at91_clk_register_sam9x5_main(regmap, name, parent_names,
num_parents);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9x5_clk_main, "atmel,at91sam9x5-clk-main",
of_at91sam9x5_clk_main_setup);
...@@ -17,24 +17,11 @@ ...@@ -17,24 +17,11 @@
#include "pmc.h" #include "pmc.h"
#define MASTER_SOURCE_MAX 4
#define MASTER_PRES_MASK 0x7 #define MASTER_PRES_MASK 0x7
#define MASTER_PRES_MAX MASTER_PRES_MASK #define MASTER_PRES_MAX MASTER_PRES_MASK
#define MASTER_DIV_SHIFT 8 #define MASTER_DIV_SHIFT 8
#define MASTER_DIV_MASK 0x3 #define MASTER_DIV_MASK 0x3
struct clk_master_characteristics {
struct clk_range output;
u32 divisors[4];
u8 have_div3_pres;
};
struct clk_master_layout {
u32 mask;
u8 pres_shift;
};
#define to_clk_master(hw) container_of(hw, struct clk_master, hw) #define to_clk_master(hw) container_of(hw, struct clk_master, hw)
struct clk_master { struct clk_master {
...@@ -120,7 +107,7 @@ static const struct clk_ops master_ops = { ...@@ -120,7 +107,7 @@ static const struct clk_ops master_ops = {
.get_parent = clk_master_get_parent, .get_parent = clk_master_get_parent,
}; };
static struct clk_hw * __init struct clk_hw * __init
at91_clk_register_master(struct regmap *regmap, at91_clk_register_master(struct regmap *regmap,
const char *name, int num_parents, const char *name, int num_parents,
const char **parent_names, const char **parent_names,
...@@ -161,92 +148,12 @@ at91_clk_register_master(struct regmap *regmap, ...@@ -161,92 +148,12 @@ at91_clk_register_master(struct regmap *regmap,
} }
static const struct clk_master_layout at91rm9200_master_layout = { const struct clk_master_layout at91rm9200_master_layout = {
.mask = 0x31F, .mask = 0x31F,
.pres_shift = 2, .pres_shift = 2,
}; };
static const struct clk_master_layout at91sam9x5_master_layout = { const struct clk_master_layout at91sam9x5_master_layout = {
.mask = 0x373, .mask = 0x373,
.pres_shift = 4, .pres_shift = 4,
}; };
static struct clk_master_characteristics * __init
of_at91_clk_master_get_characteristics(struct device_node *np)
{
struct clk_master_characteristics *characteristics;
characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
if (!characteristics)
return NULL;
if (of_at91_get_clk_range(np, "atmel,clk-output-range", &characteristics->output))
goto out_free_characteristics;
of_property_read_u32_array(np, "atmel,clk-divisors",
characteristics->divisors, 4);
characteristics->have_div3_pres =
of_property_read_bool(np, "atmel,master-clk-have-div3-pres");
return characteristics;
out_free_characteristics:
kfree(characteristics);
return NULL;
}
static void __init
of_at91_clk_master_setup(struct device_node *np,
const struct clk_master_layout *layout)
{
struct clk_hw *hw;
unsigned int num_parents;
const char *parent_names[MASTER_SOURCE_MAX];
const char *name = np->name;
struct clk_master_characteristics *characteristics;
struct regmap *regmap;
num_parents = of_clk_get_parent_count(np);
if (num_parents == 0 || num_parents > MASTER_SOURCE_MAX)
return;
of_clk_parent_fill(np, parent_names, num_parents);
of_property_read_string(np, "clock-output-names", &name);
characteristics = of_at91_clk_master_get_characteristics(np);
if (!characteristics)
return;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91_clk_register_master(regmap, name, num_parents,
parent_names, layout,
characteristics);
if (IS_ERR(hw))
goto out_free_characteristics;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
return;
out_free_characteristics:
kfree(characteristics);
}
static void __init of_at91rm9200_clk_master_setup(struct device_node *np)
{
of_at91_clk_master_setup(np, &at91rm9200_master_layout);
}
CLK_OF_DECLARE(at91rm9200_clk_master, "atmel,at91rm9200-clk-master",
of_at91rm9200_clk_master_setup);
static void __init of_at91sam9x5_clk_master_setup(struct device_node *np)
{
of_at91_clk_master_setup(np, &at91sam9x5_master_layout);
}
CLK_OF_DECLARE(at91sam9x5_clk_master, "atmel,at91sam9x5-clk-master",
of_at91sam9x5_clk_master_setup);
...@@ -19,11 +19,6 @@ ...@@ -19,11 +19,6 @@
DEFINE_SPINLOCK(pmc_pcr_lock); DEFINE_SPINLOCK(pmc_pcr_lock);
#define PERIPHERAL_MAX 64
#define PERIPHERAL_AT91RM9200 0
#define PERIPHERAL_AT91SAM9X5 1
#define PERIPHERAL_ID_MIN 2 #define PERIPHERAL_ID_MIN 2
#define PERIPHERAL_ID_MAX 31 #define PERIPHERAL_ID_MAX 31
#define PERIPHERAL_MASK(id) (1 << ((id) & PERIPHERAL_ID_MAX)) #define PERIPHERAL_MASK(id) (1 << ((id) & PERIPHERAL_ID_MAX))
...@@ -104,7 +99,7 @@ static const struct clk_ops peripheral_ops = { ...@@ -104,7 +99,7 @@ static const struct clk_ops peripheral_ops = {
.is_enabled = clk_peripheral_is_enabled, .is_enabled = clk_peripheral_is_enabled,
}; };
static struct clk_hw * __init struct clk_hw * __init
at91_clk_register_peripheral(struct regmap *regmap, const char *name, at91_clk_register_peripheral(struct regmap *regmap, const char *name,
const char *parent_name, u32 id) const char *parent_name, u32 id)
{ {
...@@ -331,7 +326,7 @@ static const struct clk_ops sam9x5_peripheral_ops = { ...@@ -331,7 +326,7 @@ static const struct clk_ops sam9x5_peripheral_ops = {
.set_rate = clk_sam9x5_peripheral_set_rate, .set_rate = clk_sam9x5_peripheral_set_rate,
}; };
static struct clk_hw * __init struct clk_hw * __init
at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock, at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
const char *name, const char *parent_name, const char *name, const char *parent_name,
u32 id, const struct clk_range *range) u32 id, const struct clk_range *range)
...@@ -374,75 +369,3 @@ at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock, ...@@ -374,75 +369,3 @@ at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
return hw; return hw;
} }
static void __init
of_at91_clk_periph_setup(struct device_node *np, u8 type)
{
int num;
u32 id;
struct clk_hw *hw;
const char *parent_name;
const char *name;
struct device_node *periphclknp;
struct regmap *regmap;
parent_name = of_clk_get_parent_name(np, 0);
if (!parent_name)
return;
num = of_get_child_count(np);
if (!num || num > PERIPHERAL_MAX)
return;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
for_each_child_of_node(np, periphclknp) {
if (of_property_read_u32(periphclknp, "reg", &id))
continue;
if (id >= PERIPHERAL_MAX)
continue;
if (of_property_read_string(np, "clock-output-names", &name))
name = periphclknp->name;
if (type == PERIPHERAL_AT91RM9200) {
hw = at91_clk_register_peripheral(regmap, name,
parent_name, id);
} else {
struct clk_range range = CLK_RANGE(0, 0);
of_at91_get_clk_range(periphclknp,
"atmel,clk-output-range",
&range);
hw = at91_clk_register_sam9x5_peripheral(regmap,
&pmc_pcr_lock,
name,
parent_name,
id, &range);
}
if (IS_ERR(hw))
continue;
of_clk_add_hw_provider(periphclknp, of_clk_hw_simple_get, hw);
}
}
static void __init of_at91rm9200_clk_periph_setup(struct device_node *np)
{
of_at91_clk_periph_setup(np, PERIPHERAL_AT91RM9200);
}
CLK_OF_DECLARE(at91rm9200_clk_periph, "atmel,at91rm9200-clk-peripheral",
of_at91rm9200_clk_periph_setup);
static void __init of_at91sam9x5_clk_periph_setup(struct device_node *np)
{
of_at91_clk_periph_setup(np, PERIPHERAL_AT91SAM9X5);
}
CLK_OF_DECLARE(at91sam9x5_clk_periph, "atmel,at91sam9x5-clk-peripheral",
of_at91sam9x5_clk_periph_setup);
...@@ -34,20 +34,6 @@ ...@@ -34,20 +34,6 @@
#define PLL_OUT_SHIFT 14 #define PLL_OUT_SHIFT 14
#define PLL_MAX_ID 1 #define PLL_MAX_ID 1
struct clk_pll_characteristics {
struct clk_range input;
int num_output;
struct clk_range *output;
u16 *icpll;
u8 *out;
};
struct clk_pll_layout {
u32 pllr_mask;
u16 mul_mask;
u8 mul_shift;
};
#define to_clk_pll(hw) container_of(hw, struct clk_pll, hw) #define to_clk_pll(hw) container_of(hw, struct clk_pll, hw)
struct clk_pll { struct clk_pll {
...@@ -288,7 +274,7 @@ static const struct clk_ops pll_ops = { ...@@ -288,7 +274,7 @@ static const struct clk_ops pll_ops = {
.set_rate = clk_pll_set_rate, .set_rate = clk_pll_set_rate,
}; };
static struct clk_hw * __init struct clk_hw * __init
at91_clk_register_pll(struct regmap *regmap, const char *name, at91_clk_register_pll(struct regmap *regmap, const char *name,
const char *parent_name, u8 id, const char *parent_name, u8 id,
const struct clk_pll_layout *layout, const struct clk_pll_layout *layout,
...@@ -334,189 +320,26 @@ at91_clk_register_pll(struct regmap *regmap, const char *name, ...@@ -334,189 +320,26 @@ at91_clk_register_pll(struct regmap *regmap, const char *name,
} }
static const struct clk_pll_layout at91rm9200_pll_layout = { const struct clk_pll_layout at91rm9200_pll_layout = {
.pllr_mask = 0x7FFFFFF, .pllr_mask = 0x7FFFFFF,
.mul_shift = 16, .mul_shift = 16,
.mul_mask = 0x7FF, .mul_mask = 0x7FF,
}; };
static const struct clk_pll_layout at91sam9g45_pll_layout = { const struct clk_pll_layout at91sam9g45_pll_layout = {
.pllr_mask = 0xFFFFFF, .pllr_mask = 0xFFFFFF,
.mul_shift = 16, .mul_shift = 16,
.mul_mask = 0xFF, .mul_mask = 0xFF,
}; };
static const struct clk_pll_layout at91sam9g20_pllb_layout = { const struct clk_pll_layout at91sam9g20_pllb_layout = {
.pllr_mask = 0x3FFFFF, .pllr_mask = 0x3FFFFF,
.mul_shift = 16, .mul_shift = 16,
.mul_mask = 0x3F, .mul_mask = 0x3F,
}; };
static const struct clk_pll_layout sama5d3_pll_layout = { const struct clk_pll_layout sama5d3_pll_layout = {
.pllr_mask = 0x1FFFFFF, .pllr_mask = 0x1FFFFFF,
.mul_shift = 18, .mul_shift = 18,
.mul_mask = 0x7F, .mul_mask = 0x7F,
}; };
static struct clk_pll_characteristics * __init
of_at91_clk_pll_get_characteristics(struct device_node *np)
{
int i;
int offset;
u32 tmp;
int num_output;
u32 num_cells;
struct clk_range input;
struct clk_range *output;
u8 *out = NULL;
u16 *icpll = NULL;
struct clk_pll_characteristics *characteristics;
if (of_at91_get_clk_range(np, "atmel,clk-input-range", &input))
return NULL;
if (of_property_read_u32(np, "#atmel,pll-clk-output-range-cells",
&num_cells))
return NULL;
if (num_cells < 2 || num_cells > 4)
return NULL;
if (!of_get_property(np, "atmel,pll-clk-output-ranges", &tmp))
return NULL;
num_output = tmp / (sizeof(u32) * num_cells);
characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
if (!characteristics)
return NULL;
output = kcalloc(num_output, sizeof(*output), GFP_KERNEL);
if (!output)
goto out_free_characteristics;
if (num_cells > 2) {
out = kcalloc(num_output, sizeof(*out), GFP_KERNEL);
if (!out)
goto out_free_output;
}
if (num_cells > 3) {
icpll = kcalloc(num_output, sizeof(*icpll), GFP_KERNEL);
if (!icpll)
goto out_free_output;
}
for (i = 0; i < num_output; i++) {
offset = i * num_cells;
if (of_property_read_u32_index(np,
"atmel,pll-clk-output-ranges",
offset, &tmp))
goto out_free_output;
output[i].min = tmp;
if (of_property_read_u32_index(np,
"atmel,pll-clk-output-ranges",
offset + 1, &tmp))
goto out_free_output;
output[i].max = tmp;
if (num_cells == 2)
continue;
if (of_property_read_u32_index(np,
"atmel,pll-clk-output-ranges",
offset + 2, &tmp))
goto out_free_output;
out[i] = tmp;
if (num_cells == 3)
continue;
if (of_property_read_u32_index(np,
"atmel,pll-clk-output-ranges",
offset + 3, &tmp))
goto out_free_output;
icpll[i] = tmp;
}
characteristics->input = input;
characteristics->num_output = num_output;
characteristics->output = output;
characteristics->out = out;
characteristics->icpll = icpll;
return characteristics;
out_free_output:
kfree(icpll);
kfree(out);
kfree(output);
out_free_characteristics:
kfree(characteristics);
return NULL;
}
static void __init
of_at91_clk_pll_setup(struct device_node *np,
const struct clk_pll_layout *layout)
{
u32 id;
struct clk_hw *hw;
struct regmap *regmap;
const char *parent_name;
const char *name = np->name;
struct clk_pll_characteristics *characteristics;
if (of_property_read_u32(np, "reg", &id))
return;
parent_name = of_clk_get_parent_name(np, 0);
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
characteristics = of_at91_clk_pll_get_characteristics(np);
if (!characteristics)
return;
hw = at91_clk_register_pll(regmap, name, parent_name, id, layout,
characteristics);
if (IS_ERR(hw))
goto out_free_characteristics;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
return;
out_free_characteristics:
kfree(characteristics);
}
static void __init of_at91rm9200_clk_pll_setup(struct device_node *np)
{
of_at91_clk_pll_setup(np, &at91rm9200_pll_layout);
}
CLK_OF_DECLARE(at91rm9200_clk_pll, "atmel,at91rm9200-clk-pll",
of_at91rm9200_clk_pll_setup);
static void __init of_at91sam9g45_clk_pll_setup(struct device_node *np)
{
of_at91_clk_pll_setup(np, &at91sam9g45_pll_layout);
}
CLK_OF_DECLARE(at91sam9g45_clk_pll, "atmel,at91sam9g45-clk-pll",
of_at91sam9g45_clk_pll_setup);
static void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np)
{
of_at91_clk_pll_setup(np, &at91sam9g20_pllb_layout);
}
CLK_OF_DECLARE(at91sam9g20_clk_pllb, "atmel,at91sam9g20-clk-pllb",
of_at91sam9g20_clk_pllb_setup);
static void __init of_sama5d3_clk_pll_setup(struct device_node *np)
{
of_at91_clk_pll_setup(np, &sama5d3_pll_layout);
}
CLK_OF_DECLARE(sama5d3_clk_pll, "atmel,sama5d3-clk-pll",
of_sama5d3_clk_pll_setup);
...@@ -75,7 +75,7 @@ static const struct clk_ops plldiv_ops = { ...@@ -75,7 +75,7 @@ static const struct clk_ops plldiv_ops = {
.set_rate = clk_plldiv_set_rate, .set_rate = clk_plldiv_set_rate,
}; };
static struct clk_hw * __init struct clk_hw * __init
at91_clk_register_plldiv(struct regmap *regmap, const char *name, at91_clk_register_plldiv(struct regmap *regmap, const char *name,
const char *parent_name) const char *parent_name)
{ {
...@@ -106,28 +106,3 @@ at91_clk_register_plldiv(struct regmap *regmap, const char *name, ...@@ -106,28 +106,3 @@ at91_clk_register_plldiv(struct regmap *regmap, const char *name,
return hw; return hw;
} }
static void __init
of_at91sam9x5_clk_plldiv_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_name;
const char *name = np->name;
struct regmap *regmap;
parent_name = of_clk_get_parent_name(np, 0);
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91_clk_register_plldiv(regmap, name, parent_name);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9x5_clk_plldiv, "atmel,at91sam9x5-clk-plldiv",
of_at91sam9x5_clk_plldiv_setup);
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include "pmc.h" #include "pmc.h"
#define PROG_SOURCE_MAX 5
#define PROG_ID_MAX 7 #define PROG_ID_MAX 7
#define PROG_STATUS_MASK(id) (1 << ((id) + 8)) #define PROG_STATUS_MASK(id) (1 << ((id) + 8))
...@@ -25,12 +24,6 @@ ...@@ -25,12 +24,6 @@
#define PROG_PRES(layout, pckr) ((pckr >> layout->pres_shift) & PROG_PRES_MASK) #define PROG_PRES(layout, pckr) ((pckr >> layout->pres_shift) & PROG_PRES_MASK)
#define PROG_MAX_RM9200_CSS 3 #define PROG_MAX_RM9200_CSS 3
struct clk_programmable_layout {
u8 pres_shift;
u8 css_mask;
u8 have_slck_mck;
};
struct clk_programmable { struct clk_programmable {
struct clk_hw hw; struct clk_hw hw;
struct regmap *regmap; struct regmap *regmap;
...@@ -170,7 +163,7 @@ static const struct clk_ops programmable_ops = { ...@@ -170,7 +163,7 @@ static const struct clk_ops programmable_ops = {
.set_rate = clk_programmable_set_rate, .set_rate = clk_programmable_set_rate,
}; };
static struct clk_hw * __init struct clk_hw * __init
at91_clk_register_programmable(struct regmap *regmap, at91_clk_register_programmable(struct regmap *regmap,
const char *name, const char **parent_names, const char *name, const char **parent_names,
u8 num_parents, u8 id, u8 num_parents, u8 id,
...@@ -211,86 +204,20 @@ at91_clk_register_programmable(struct regmap *regmap, ...@@ -211,86 +204,20 @@ at91_clk_register_programmable(struct regmap *regmap,
return hw; return hw;
} }
static const struct clk_programmable_layout at91rm9200_programmable_layout = { const struct clk_programmable_layout at91rm9200_programmable_layout = {
.pres_shift = 2, .pres_shift = 2,
.css_mask = 0x3, .css_mask = 0x3,
.have_slck_mck = 0, .have_slck_mck = 0,
}; };
static const struct clk_programmable_layout at91sam9g45_programmable_layout = { const struct clk_programmable_layout at91sam9g45_programmable_layout = {
.pres_shift = 2, .pres_shift = 2,
.css_mask = 0x3, .css_mask = 0x3,
.have_slck_mck = 1, .have_slck_mck = 1,
}; };
static const struct clk_programmable_layout at91sam9x5_programmable_layout = { const struct clk_programmable_layout at91sam9x5_programmable_layout = {
.pres_shift = 4, .pres_shift = 4,
.css_mask = 0x7, .css_mask = 0x7,
.have_slck_mck = 0, .have_slck_mck = 0,
}; };
static void __init
of_at91_clk_prog_setup(struct device_node *np,
const struct clk_programmable_layout *layout)
{
int num;
u32 id;
struct clk_hw *hw;
unsigned int num_parents;
const char *parent_names[PROG_SOURCE_MAX];
const char *name;
struct device_node *progclknp;
struct regmap *regmap;
num_parents = of_clk_get_parent_count(np);
if (num_parents == 0 || num_parents > PROG_SOURCE_MAX)
return;
of_clk_parent_fill(np, parent_names, num_parents);
num = of_get_child_count(np);
if (!num || num > (PROG_ID_MAX + 1))
return;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
for_each_child_of_node(np, progclknp) {
if (of_property_read_u32(progclknp, "reg", &id))
continue;
if (of_property_read_string(np, "clock-output-names", &name))
name = progclknp->name;
hw = at91_clk_register_programmable(regmap, name,
parent_names, num_parents,
id, layout);
if (IS_ERR(hw))
continue;
of_clk_add_hw_provider(progclknp, of_clk_hw_simple_get, hw);
}
}
static void __init of_at91rm9200_clk_prog_setup(struct device_node *np)
{
of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout);
}
CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable",
of_at91rm9200_clk_prog_setup);
static void __init of_at91sam9g45_clk_prog_setup(struct device_node *np)
{
of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout);
}
CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable",
of_at91sam9g45_clk_prog_setup);
static void __init of_at91sam9x5_clk_prog_setup(struct device_node *np)
{
of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout);
}
CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable",
of_at91sam9x5_clk_prog_setup);
...@@ -40,7 +40,7 @@ static const struct clk_ops sam9260_slow_ops = { ...@@ -40,7 +40,7 @@ static const struct clk_ops sam9260_slow_ops = {
.get_parent = clk_sam9260_slow_get_parent, .get_parent = clk_sam9260_slow_get_parent,
}; };
static struct clk_hw * __init struct clk_hw * __init
at91_clk_register_sam9260_slow(struct regmap *regmap, at91_clk_register_sam9260_slow(struct regmap *regmap,
const char *name, const char *name,
const char **parent_names, const char **parent_names,
...@@ -79,33 +79,3 @@ at91_clk_register_sam9260_slow(struct regmap *regmap, ...@@ -79,33 +79,3 @@ at91_clk_register_sam9260_slow(struct regmap *regmap,
return hw; return hw;
} }
static void __init of_at91sam9260_clk_slow_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_names[2];
unsigned int num_parents;
const char *name = np->name;
struct regmap *regmap;
num_parents = of_clk_get_parent_count(np);
if (num_parents != 2)
return;
of_clk_parent_fill(np, parent_names, num_parents);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
of_property_read_string(np, "clock-output-names", &name);
hw = at91_clk_register_sam9260_slow(regmap, name, parent_names,
num_parents);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9260_clk_slow, "atmel,at91sam9260-clk-slow",
of_at91sam9260_clk_slow_setup);
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
#include "pmc.h" #include "pmc.h"
#define SMD_SOURCE_MAX 2
#define SMD_DIV_SHIFT 8 #define SMD_DIV_SHIFT 8
#define SMD_MAX_DIV 0xf #define SMD_MAX_DIV 0xf
...@@ -111,7 +109,7 @@ static const struct clk_ops at91sam9x5_smd_ops = { ...@@ -111,7 +109,7 @@ static const struct clk_ops at91sam9x5_smd_ops = {
.set_rate = at91sam9x5_clk_smd_set_rate, .set_rate = at91sam9x5_clk_smd_set_rate,
}; };
static struct clk_hw * __init struct clk_hw * __init
at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name, at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name,
const char **parent_names, u8 num_parents) const char **parent_names, u8 num_parents)
{ {
...@@ -142,33 +140,3 @@ at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name, ...@@ -142,33 +140,3 @@ at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name,
return hw; return hw;
} }
static void __init of_at91sam9x5_clk_smd_setup(struct device_node *np)
{
struct clk_hw *hw;
unsigned int num_parents;
const char *parent_names[SMD_SOURCE_MAX];
const char *name = np->name;
struct regmap *regmap;
num_parents = of_clk_get_parent_count(np);
if (num_parents == 0 || num_parents > SMD_SOURCE_MAX)
return;
of_clk_parent_fill(np, parent_names, num_parents);
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91sam9x5_clk_register_smd(regmap, name, parent_names,
num_parents);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9x5_clk_smd, "atmel,at91sam9x5-clk-smd",
of_at91sam9x5_clk_smd_setup);
...@@ -88,7 +88,7 @@ static const struct clk_ops system_ops = { ...@@ -88,7 +88,7 @@ static const struct clk_ops system_ops = {
.is_prepared = clk_system_is_prepared, .is_prepared = clk_system_is_prepared,
}; };
static struct clk_hw * __init struct clk_hw * __init
at91_clk_register_system(struct regmap *regmap, const char *name, at91_clk_register_system(struct regmap *regmap, const char *name,
const char *parent_name, u8 id) const char *parent_name, u8 id)
{ {
...@@ -123,40 +123,3 @@ at91_clk_register_system(struct regmap *regmap, const char *name, ...@@ -123,40 +123,3 @@ at91_clk_register_system(struct regmap *regmap, const char *name,
return hw; return hw;
} }
static void __init of_at91rm9200_clk_sys_setup(struct device_node *np)
{
int num;
u32 id;
struct clk_hw *hw;
const char *name;
struct device_node *sysclknp;
const char *parent_name;
struct regmap *regmap;
num = of_get_child_count(np);
if (num > (SYSTEM_MAX_ID + 1))
return;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
for_each_child_of_node(np, sysclknp) {
if (of_property_read_u32(sysclknp, "reg", &id))
continue;
if (of_property_read_string(np, "clock-output-names", &name))
name = sysclknp->name;
parent_name = of_clk_get_parent_name(sysclknp, 0);
hw = at91_clk_register_system(regmap, name, parent_name, id);
if (IS_ERR(hw))
continue;
of_clk_add_hw_provider(sysclknp, of_clk_hw_simple_get, hw);
}
}
CLK_OF_DECLARE(at91rm9200_clk_sys, "atmel,at91rm9200-clk-system",
of_at91rm9200_clk_sys_setup);
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
#include "pmc.h" #include "pmc.h"
#define USB_SOURCE_MAX 2
#define SAM9X5_USB_DIV_SHIFT 8 #define SAM9X5_USB_DIV_SHIFT 8
#define SAM9X5_USB_MAX_DIV 0xf #define SAM9X5_USB_MAX_DIV 0xf
...@@ -192,7 +190,7 @@ static const struct clk_ops at91sam9n12_usb_ops = { ...@@ -192,7 +190,7 @@ static const struct clk_ops at91sam9n12_usb_ops = {
.set_rate = at91sam9x5_clk_usb_set_rate, .set_rate = at91sam9x5_clk_usb_set_rate,
}; };
static struct clk_hw * __init struct clk_hw * __init
at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name, at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
const char **parent_names, u8 num_parents) const char **parent_names, u8 num_parents)
{ {
...@@ -225,7 +223,7 @@ at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name, ...@@ -225,7 +223,7 @@ at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
return hw; return hw;
} }
static struct clk_hw * __init struct clk_hw * __init
at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name, at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name,
const char *parent_name) const char *parent_name)
{ {
...@@ -342,7 +340,7 @@ static const struct clk_ops at91rm9200_usb_ops = { ...@@ -342,7 +340,7 @@ static const struct clk_ops at91rm9200_usb_ops = {
.set_rate = at91rm9200_clk_usb_set_rate, .set_rate = at91rm9200_clk_usb_set_rate,
}; };
static struct clk_hw * __init struct clk_hw * __init
at91rm9200_clk_register_usb(struct regmap *regmap, const char *name, at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
const char *parent_name, const u32 *divisors) const char *parent_name, const u32 *divisors)
{ {
...@@ -374,89 +372,3 @@ at91rm9200_clk_register_usb(struct regmap *regmap, const char *name, ...@@ -374,89 +372,3 @@ at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
return hw; return hw;
} }
static void __init of_at91sam9x5_clk_usb_setup(struct device_node *np)
{
struct clk_hw *hw;
unsigned int num_parents;
const char *parent_names[USB_SOURCE_MAX];
const char *name = np->name;
struct regmap *regmap;
num_parents = of_clk_get_parent_count(np);
if (num_parents == 0 || num_parents > USB_SOURCE_MAX)
return;
of_clk_parent_fill(np, parent_names, num_parents);
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91sam9x5_clk_register_usb(regmap, name, parent_names,
num_parents);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9x5_clk_usb, "atmel,at91sam9x5-clk-usb",
of_at91sam9x5_clk_usb_setup);
static void __init of_at91sam9n12_clk_usb_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_name;
const char *name = np->name;
struct regmap *regmap;
parent_name = of_clk_get_parent_name(np, 0);
if (!parent_name)
return;
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91sam9n12_clk_register_usb(regmap, name, parent_name);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9n12_clk_usb, "atmel,at91sam9n12-clk-usb",
of_at91sam9n12_clk_usb_setup);
static void __init of_at91rm9200_clk_usb_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_name;
const char *name = np->name;
u32 divisors[4] = {0, 0, 0, 0};
struct regmap *regmap;
parent_name = of_clk_get_parent_name(np, 0);
if (!parent_name)
return;
of_property_read_u32_array(np, "atmel,clk-divisors", divisors, 4);
if (!divisors[0])
return;
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91rm9200_clk_register_usb(regmap, name, parent_name, divisors);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91rm9200_clk_usb, "atmel,at91rm9200-clk-usb",
of_at91rm9200_clk_usb_setup);
...@@ -125,7 +125,7 @@ static const struct clk_ops utmi_ops = { ...@@ -125,7 +125,7 @@ static const struct clk_ops utmi_ops = {
.recalc_rate = clk_utmi_recalc_rate, .recalc_rate = clk_utmi_recalc_rate,
}; };
static struct clk_hw * __init struct clk_hw * __init
at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr, at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
const char *name, const char *parent_name) const char *name, const char *parent_name)
{ {
...@@ -157,46 +157,3 @@ at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr, ...@@ -157,46 +157,3 @@ at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
return hw; return hw;
} }
static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_name;
const char *name = np->name;
struct regmap *regmap_pmc, *regmap_sfr;
parent_name = of_clk_get_parent_name(np, 0);
of_property_read_string(np, "clock-output-names", &name);
regmap_pmc = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap_pmc))
return;
/*
* If the device supports different mainck rates, this value has to be
* set in the UTMI Clock Trimming register.
* - 9x5: mainck supports several rates but it is indicated that a
* 12 MHz is needed in case of USB.
* - sama5d3 and sama5d2: mainck supports several rates. Configuring
* the FREQ field of the UTMI Clock Trimming register is mandatory.
* - sama5d4: mainck is at 12 MHz.
*
* We only need to retrieve sama5d3 or sama5d2 sfr regmap.
*/
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d3-sfr");
if (IS_ERR(regmap_sfr)) {
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
if (IS_ERR(regmap_sfr))
regmap_sfr = NULL;
}
hw = at91_clk_register_utmi(regmap_pmc, regmap_sfr, name, parent_name);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
return;
}
CLK_OF_DECLARE(at91sam9x5_clk_utmi, "atmel,at91sam9x5-clk-utmi",
of_at91sam9x5_clk_utmi_setup);
This diff is collapsed.
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#include <asm/proc-fns.h> #include <asm/proc-fns.h>
#include <dt-bindings/clock/at91.h>
#include "pmc.h" #include "pmc.h"
#define PMC_MAX_IDS 128 #define PMC_MAX_IDS 128
...@@ -47,6 +49,82 @@ int of_at91_get_clk_range(struct device_node *np, const char *propname, ...@@ -47,6 +49,82 @@ int of_at91_get_clk_range(struct device_node *np, const char *propname,
} }
EXPORT_SYMBOL_GPL(of_at91_get_clk_range); EXPORT_SYMBOL_GPL(of_at91_get_clk_range);
struct clk_hw *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data)
{
unsigned int type = clkspec->args[0];
unsigned int idx = clkspec->args[1];
struct pmc_data *pmc_data = data;
switch (type) {
case PMC_TYPE_CORE:
if (idx < pmc_data->ncore)
return pmc_data->chws[idx];
break;
case PMC_TYPE_SYSTEM:
if (idx < pmc_data->nsystem)
return pmc_data->shws[idx];
break;
case PMC_TYPE_PERIPHERAL:
if (idx < pmc_data->nperiph)
return pmc_data->phws[idx];
break;
case PMC_TYPE_GCK:
if (idx < pmc_data->ngck)
return pmc_data->ghws[idx];
break;
default:
break;
}
pr_err("%s: invalid type (%u) or index (%u)\n", __func__, type, idx);
return ERR_PTR(-EINVAL);
}
void pmc_data_free(struct pmc_data *pmc_data)
{
kfree(pmc_data->chws);
kfree(pmc_data->shws);
kfree(pmc_data->phws);
kfree(pmc_data->ghws);
}
struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
unsigned int nperiph, unsigned int ngck)
{
struct pmc_data *pmc_data = kzalloc(sizeof(*pmc_data), GFP_KERNEL);
if (!pmc_data)
return NULL;
pmc_data->ncore = ncore;
pmc_data->chws = kcalloc(ncore, sizeof(struct clk_hw *), GFP_KERNEL);
if (!pmc_data->chws)
goto err;
pmc_data->nsystem = nsystem;
pmc_data->shws = kcalloc(nsystem, sizeof(struct clk_hw *), GFP_KERNEL);
if (!pmc_data->shws)
goto err;
pmc_data->nperiph = nperiph;
pmc_data->phws = kcalloc(nperiph, sizeof(struct clk_hw *), GFP_KERNEL);
if (!pmc_data->phws)
goto err;
pmc_data->ngck = ngck;
pmc_data->ghws = kcalloc(ngck, sizeof(struct clk_hw *), GFP_KERNEL);
if (!pmc_data->ghws)
goto err;
return pmc_data;
err:
pmc_data_free(pmc_data);
return NULL;
}
#ifdef CONFIG_PM #ifdef CONFIG_PM
static struct regmap *pmcreg; static struct regmap *pmcreg;
......
...@@ -19,6 +19,17 @@ ...@@ -19,6 +19,17 @@
extern spinlock_t pmc_pcr_lock; extern spinlock_t pmc_pcr_lock;
struct pmc_data {
unsigned int ncore;
struct clk_hw **chws;
unsigned int nsystem;
struct clk_hw **shws;
unsigned int nperiph;
struct clk_hw **phws;
unsigned int ngck;
struct clk_hw **ghws;
};
struct clk_range { struct clk_range {
unsigned long min; unsigned long min;
unsigned long max; unsigned long max;
...@@ -26,9 +37,157 @@ struct clk_range { ...@@ -26,9 +37,157 @@ struct clk_range {
#define CLK_RANGE(MIN, MAX) {.min = MIN, .max = MAX,} #define CLK_RANGE(MIN, MAX) {.min = MIN, .max = MAX,}
struct clk_master_layout {
u32 mask;
u8 pres_shift;
};
extern const struct clk_master_layout at91rm9200_master_layout;
extern const struct clk_master_layout at91sam9x5_master_layout;
struct clk_master_characteristics {
struct clk_range output;
u32 divisors[4];
u8 have_div3_pres;
};
struct clk_pll_layout {
u32 pllr_mask;
u16 mul_mask;
u8 mul_shift;
};
extern const struct clk_pll_layout at91rm9200_pll_layout;
extern const struct clk_pll_layout at91sam9g45_pll_layout;
extern const struct clk_pll_layout at91sam9g20_pllb_layout;
extern const struct clk_pll_layout sama5d3_pll_layout;
struct clk_pll_characteristics {
struct clk_range input;
int num_output;
struct clk_range *output;
u16 *icpll;
u8 *out;
};
struct clk_programmable_layout {
u8 pres_shift;
u8 css_mask;
u8 have_slck_mck;
};
extern const struct clk_programmable_layout at91rm9200_programmable_layout;
extern const struct clk_programmable_layout at91sam9g45_programmable_layout;
extern const struct clk_programmable_layout at91sam9x5_programmable_layout;
#define ndck(a, s) (a[s - 1].id + 1)
#define nck(a) (a[ARRAY_SIZE(a) - 1].id + 1)
struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
unsigned int nperiph, unsigned int ngck);
void pmc_data_free(struct pmc_data *pmc_data);
int of_at91_get_clk_range(struct device_node *np, const char *propname, int of_at91_get_clk_range(struct device_node *np, const char *propname,
struct clk_range *range); struct clk_range *range);
struct clk_hw *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data);
struct clk_hw * __init
at91_clk_register_audio_pll_frac(struct regmap *regmap, const char *name,
const char *parent_name);
struct clk_hw * __init
at91_clk_register_audio_pll_pad(struct regmap *regmap, const char *name,
const char *parent_name);
struct clk_hw * __init
at91_clk_register_audio_pll_pmc(struct regmap *regmap, const char *name,
const char *parent_name);
struct clk_hw * __init
at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
const char *name, const char **parent_names,
u8 num_parents, u8 id, bool pll_audio,
const struct clk_range *range);
struct clk_hw * __init
at91_clk_register_h32mx(struct regmap *regmap, const char *name,
const char *parent_name);
struct clk_hw * __init
at91_clk_i2s_mux_register(struct regmap *regmap, const char *name,
const char * const *parent_names,
unsigned int num_parents, u8 bus_id);
struct clk_hw * __init
at91_clk_register_main_rc_osc(struct regmap *regmap, const char *name,
u32 frequency, u32 accuracy);
struct clk_hw * __init
at91_clk_register_main_osc(struct regmap *regmap, const char *name,
const char *parent_name, bool bypass);
struct clk_hw * __init
at91_clk_register_rm9200_main(struct regmap *regmap,
const char *name,
const char *parent_name);
struct clk_hw * __init
at91_clk_register_sam9x5_main(struct regmap *regmap, const char *name,
const char **parent_names, int num_parents);
struct clk_hw * __init
at91_clk_register_master(struct regmap *regmap, const char *name,
int num_parents, const char **parent_names,
const struct clk_master_layout *layout,
const struct clk_master_characteristics *characteristics);
struct clk_hw * __init
at91_clk_register_peripheral(struct regmap *regmap, const char *name,
const char *parent_name, u32 id);
struct clk_hw * __init
at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
const char *name, const char *parent_name,
u32 id, const struct clk_range *range);
struct clk_hw * __init
at91_clk_register_pll(struct regmap *regmap, const char *name,
const char *parent_name, u8 id,
const struct clk_pll_layout *layout,
const struct clk_pll_characteristics *characteristics);
struct clk_hw * __init
at91_clk_register_plldiv(struct regmap *regmap, const char *name,
const char *parent_name);
struct clk_hw * __init
at91_clk_register_programmable(struct regmap *regmap, const char *name,
const char **parent_names, u8 num_parents, u8 id,
const struct clk_programmable_layout *layout);
struct clk_hw * __init
at91_clk_register_sam9260_slow(struct regmap *regmap,
const char *name,
const char **parent_names,
int num_parents);
struct clk_hw * __init
at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name,
const char **parent_names, u8 num_parents);
struct clk_hw * __init
at91_clk_register_system(struct regmap *regmap, const char *name,
const char *parent_name, u8 id);
struct clk_hw * __init
at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
const char **parent_names, u8 num_parents);
struct clk_hw * __init
at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name,
const char *parent_name);
struct clk_hw * __init
at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
const char *parent_name, const u32 *divisors);
struct clk_hw * __init
at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
const char *name, const char *parent_name);
#ifdef CONFIG_PM #ifdef CONFIG_PM
void pmc_register_id(u8 id); void pmc_register_id(u8 id);
void pmc_register_pck(u8 pck); void pmc_register_pck(u8 pck);
......
This diff is collapsed.
This diff is collapsed.
...@@ -94,7 +94,7 @@ struct clk *imx_clk_cpu(const char *name, const char *parent_name, ...@@ -94,7 +94,7 @@ struct clk *imx_clk_cpu(const char *name, const char *parent_name,
init.name = name; init.name = name;
init.ops = &clk_cpu_ops; init.ops = &clk_cpu_ops;
init.flags = 0; init.flags = CLK_IS_CRITICAL;
init.parent_names = &parent_name; init.parent_names = &parent_name;
init.num_parents = 1; init.num_parents = 1;
......
...@@ -379,14 +379,6 @@ static const char *pll_enet_bypass_sel[] = { "pll_enet_main", "pll_enet_main_src ...@@ -379,14 +379,6 @@ static const char *pll_enet_bypass_sel[] = { "pll_enet_main", "pll_enet_main_src
static const char *pll_audio_bypass_sel[] = { "pll_audio_main", "pll_audio_main_src", }; static const char *pll_audio_bypass_sel[] = { "pll_audio_main", "pll_audio_main_src", };
static const char *pll_video_bypass_sel[] = { "pll_video_main", "pll_video_main_src", }; static const char *pll_video_bypass_sel[] = { "pll_video_main", "pll_video_main_src", };
static int const clks_init_on[] __initconst = {
IMX7D_ARM_A7_ROOT_CLK, IMX7D_MAIN_AXI_ROOT_CLK,
IMX7D_PLL_SYS_MAIN_480M_CLK, IMX7D_NAND_USDHC_BUS_ROOT_CLK,
IMX7D_DRAM_PHYM_ROOT_CLK, IMX7D_DRAM_ROOT_CLK,
IMX7D_DRAM_PHYM_ALT_ROOT_CLK, IMX7D_DRAM_ALT_ROOT_CLK,
IMX7D_AHB_CHANNEL_ROOT_CLK, IMX7D_IPG_ROOT_CLK,
};
static struct clk_onecell_data clk_data; static struct clk_onecell_data clk_data;
static struct clk ** const uart_clks[] __initconst = { static struct clk ** const uart_clks[] __initconst = {
...@@ -404,7 +396,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) ...@@ -404,7 +396,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
{ {
struct device_node *np; struct device_node *np;
void __iomem *base; void __iomem *base;
int i;
clks[IMX7D_CLK_DUMMY] = imx_clk_fixed("dummy", 0); clks[IMX7D_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
clks[IMX7D_OSC_24M_CLK] = of_clk_get_by_name(ccm_node, "osc"); clks[IMX7D_OSC_24M_CLK] = of_clk_get_by_name(ccm_node, "osc");
...@@ -467,7 +458,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) ...@@ -467,7 +458,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_PLL_SYS_MAIN_120M] = imx_clk_fixed_factor("pll_sys_main_120m", "pll_sys_main_clk", 1, 4); clks[IMX7D_PLL_SYS_MAIN_120M] = imx_clk_fixed_factor("pll_sys_main_120m", "pll_sys_main_clk", 1, 4);
clks[IMX7D_PLL_DRAM_MAIN_533M] = imx_clk_fixed_factor("pll_dram_533m", "pll_dram_main_clk", 1, 2); clks[IMX7D_PLL_DRAM_MAIN_533M] = imx_clk_fixed_factor("pll_dram_533m", "pll_dram_main_clk", 1, 2);
clks[IMX7D_PLL_SYS_MAIN_480M_CLK] = imx_clk_gate_dis("pll_sys_main_480m_clk", "pll_sys_main_480m", base + 0xb0, 4); clks[IMX7D_PLL_SYS_MAIN_480M_CLK] = imx_clk_gate_dis_flags("pll_sys_main_480m_clk", "pll_sys_main_480m", base + 0xb0, 4, CLK_IS_CRITICAL);
clks[IMX7D_PLL_SYS_MAIN_240M_CLK] = imx_clk_gate_dis("pll_sys_main_240m_clk", "pll_sys_main_240m", base + 0xb0, 5); clks[IMX7D_PLL_SYS_MAIN_240M_CLK] = imx_clk_gate_dis("pll_sys_main_240m_clk", "pll_sys_main_240m", base + 0xb0, 5);
clks[IMX7D_PLL_SYS_MAIN_120M_CLK] = imx_clk_gate_dis("pll_sys_main_120m_clk", "pll_sys_main_120m", base + 0xb0, 6); clks[IMX7D_PLL_SYS_MAIN_120M_CLK] = imx_clk_gate_dis("pll_sys_main_120m_clk", "pll_sys_main_120m", base + 0xb0, 6);
clks[IMX7D_PLL_DRAM_MAIN_533M_CLK] = imx_clk_gate("pll_dram_533m_clk", "pll_dram_533m", base + 0x70, 12); clks[IMX7D_PLL_DRAM_MAIN_533M_CLK] = imx_clk_gate("pll_dram_533m_clk", "pll_dram_533m", base + 0x70, 12);
...@@ -720,7 +711,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) ...@@ -720,7 +711,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider2("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6); clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider2("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6);
clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_divider2("nand_usdhc_root_clk", "nand_usdhc_pre_div", base + 0x8980, 0, 6); clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_divider2("nand_usdhc_root_clk", "nand_usdhc_pre_div", base + 0x8980, 0, 6);
clks[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_divider2("ahb_root_clk", "ahb_pre_div", base + 0x9000, 0, 6); clks[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_divider2("ahb_root_clk", "ahb_pre_div", base + 0x9000, 0, 6);
clks[IMX7D_IPG_ROOT_CLK] = imx_clk_divider2("ipg_root_clk", "ahb_root_clk", base + 0x9080, 0, 2); clks[IMX7D_IPG_ROOT_CLK] = imx_clk_divider_flags("ipg_root_clk", "ahb_root_clk", base + 0x9080, 0, 2, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_PARENT);
clks[IMX7D_DRAM_ROOT_DIV] = imx_clk_divider2("dram_post_div", "dram_cg", base + 0x9880, 0, 3); clks[IMX7D_DRAM_ROOT_DIV] = imx_clk_divider2("dram_post_div", "dram_cg", base + 0x9880, 0, 3);
clks[IMX7D_DRAM_PHYM_ALT_ROOT_DIV] = imx_clk_divider2("dram_phym_alt_post_div", "dram_phym_alt_pre_div", base + 0xa000, 0, 3); clks[IMX7D_DRAM_PHYM_ALT_ROOT_DIV] = imx_clk_divider2("dram_phym_alt_post_div", "dram_phym_alt_pre_div", base + 0xa000, 0, 3);
clks[IMX7D_DRAM_ALT_ROOT_DIV] = imx_clk_divider2("dram_alt_post_div", "dram_alt_pre_div", base + 0xa080, 0, 3); clks[IMX7D_DRAM_ALT_ROOT_DIV] = imx_clk_divider2("dram_alt_post_div", "dram_alt_pre_div", base + 0xa080, 0, 3);
...@@ -784,17 +775,17 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) ...@@ -784,17 +775,17 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_CLKO1_ROOT_DIV] = imx_clk_divider2("clko1_post_div", "clko1_pre_div", base + 0xbd80, 0, 6); clks[IMX7D_CLKO1_ROOT_DIV] = imx_clk_divider2("clko1_post_div", "clko1_pre_div", base + 0xbd80, 0, 6);
clks[IMX7D_CLKO2_ROOT_DIV] = imx_clk_divider2("clko2_post_div", "clko2_pre_div", base + 0xbe00, 0, 6); clks[IMX7D_CLKO2_ROOT_DIV] = imx_clk_divider2("clko2_post_div", "clko2_pre_div", base + 0xbe00, 0, 6);
clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate4("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0); clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate2_flags("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0, CLK_OPS_PARENT_ENABLE);
clks[IMX7D_ARM_M4_ROOT_CLK] = imx_clk_gate4("arm_m4_root_clk", "arm_m4_div", base + 0x4010, 0); clks[IMX7D_ARM_M4_ROOT_CLK] = imx_clk_gate4("arm_m4_root_clk", "arm_m4_div", base + 0x4010, 0);
clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate4("main_axi_root_clk", "axi_post_div", base + 0x4040, 0); clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate2_flags("main_axi_root_clk", "axi_post_div", base + 0x4040, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate4("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0); clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate4("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0);
clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate4("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0); clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate4("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0);
clks[IMX7D_OCRAM_CLK] = imx_clk_gate4("ocram_clk", "main_axi_root_clk", base + 0x4110, 0); clks[IMX7D_OCRAM_CLK] = imx_clk_gate4("ocram_clk", "main_axi_root_clk", base + 0x4110, 0);
clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate4("ocram_s_clk", "ahb_root_clk", base + 0x4120, 0); clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate4("ocram_s_clk", "ahb_root_clk", base + 0x4120, 0);
clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate4("dram_root_clk", "dram_post_div", base + 0x4130, 0); clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate2_flags("dram_root_clk", "dram_post_div", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0); clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate2_flags("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate4("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0); clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate2_flags("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate4("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0); clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate2_flags("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
clks[IMX7D_OCOTP_CLK] = imx_clk_gate4("ocotp_clk", "ipg_root_clk", base + 0x4230, 0); clks[IMX7D_OCOTP_CLK] = imx_clk_gate4("ocotp_clk", "ipg_root_clk", base + 0x4230, 0);
clks[IMX7D_SNVS_CLK] = imx_clk_gate4("snvs_clk", "ipg_root_clk", base + 0x4250, 0); clks[IMX7D_SNVS_CLK] = imx_clk_gate4("snvs_clk", "ipg_root_clk", base + 0x4250, 0);
clks[IMX7D_MU_ROOT_CLK] = imx_clk_gate4("mu_root_clk", "ipg_root_clk", base + 0x4270, 0); clks[IMX7D_MU_ROOT_CLK] = imx_clk_gate4("mu_root_clk", "ipg_root_clk", base + 0x4270, 0);
...@@ -883,9 +874,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) ...@@ -883,9 +874,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clk_data.clk_num = ARRAY_SIZE(clks); clk_data.clk_num = ARRAY_SIZE(clks);
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
clk_prepare_enable(clks[clks_init_on[i]]);
clk_set_parent(clks[IMX7D_PLL_ARM_MAIN_BYPASS], clks[IMX7D_PLL_ARM_MAIN]); clk_set_parent(clks[IMX7D_PLL_ARM_MAIN_BYPASS], clks[IMX7D_PLL_ARM_MAIN]);
clk_set_parent(clks[IMX7D_PLL_DRAM_MAIN_BYPASS], clks[IMX7D_PLL_DRAM_MAIN]); clk_set_parent(clks[IMX7D_PLL_DRAM_MAIN_BYPASS], clks[IMX7D_PLL_DRAM_MAIN]);
clk_set_parent(clks[IMX7D_PLL_SYS_MAIN_BYPASS], clks[IMX7D_PLL_SYS_MAIN]); clk_set_parent(clks[IMX7D_PLL_SYS_MAIN_BYPASS], clks[IMX7D_PLL_SYS_MAIN]);
......
...@@ -137,6 +137,13 @@ static inline struct clk *imx_clk_gate_dis(const char *name, const char *parent, ...@@ -137,6 +137,13 @@ static inline struct clk *imx_clk_gate_dis(const char *name, const char *parent,
shift, CLK_GATE_SET_TO_DISABLE, &imx_ccm_lock); shift, CLK_GATE_SET_TO_DISABLE, &imx_ccm_lock);
} }
static inline struct clk *imx_clk_gate_dis_flags(const char *name, const char *parent,
void __iomem *reg, u8 shift, unsigned long flags)
{
return clk_register_gate(NULL, name, parent, flags | CLK_SET_RATE_PARENT, reg,
shift, CLK_GATE_SET_TO_DISABLE, &imx_ccm_lock);
}
static inline struct clk *imx_clk_gate2(const char *name, const char *parent, static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
void __iomem *reg, u8 shift) void __iomem *reg, u8 shift)
{ {
......
...@@ -227,8 +227,8 @@ static struct mmp_param_gate_clk apmu_gate_clks[] = { ...@@ -227,8 +227,8 @@ static struct mmp_param_gate_clk apmu_gate_clks[] = {
/* The gate clocks has mux parent. */ /* The gate clocks has mux parent. */
{MMP2_CLK_SDH0, "sdh0_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH0, 0x1b, 0x1b, 0x0, 0, &sdh_lock}, {MMP2_CLK_SDH0, "sdh0_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH0, 0x1b, 0x1b, 0x0, 0, &sdh_lock},
{MMP2_CLK_SDH1, "sdh1_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH1, 0x1b, 0x1b, 0x0, 0, &sdh_lock}, {MMP2_CLK_SDH1, "sdh1_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH1, 0x1b, 0x1b, 0x0, 0, &sdh_lock},
{MMP2_CLK_SDH1, "sdh2_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH2, 0x1b, 0x1b, 0x0, 0, &sdh_lock}, {MMP2_CLK_SDH2, "sdh2_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH2, 0x1b, 0x1b, 0x0, 0, &sdh_lock},
{MMP2_CLK_SDH1, "sdh3_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH3, 0x1b, 0x1b, 0x0, 0, &sdh_lock}, {MMP2_CLK_SDH3, "sdh3_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH3, 0x1b, 0x1b, 0x0, 0, &sdh_lock},
{MMP2_CLK_DISP0, "disp0_clk", "disp0_div", CLK_SET_RATE_PARENT, APMU_DISP0, 0x1b, 0x1b, 0x0, 0, &disp0_lock}, {MMP2_CLK_DISP0, "disp0_clk", "disp0_div", CLK_SET_RATE_PARENT, APMU_DISP0, 0x1b, 0x1b, 0x0, 0, &disp0_lock},
{MMP2_CLK_DISP0_SPHY, "disp0_sphy_clk", "disp0_sphy_div", CLK_SET_RATE_PARENT, APMU_DISP0, 0x1024, 0x1024, 0x0, 0, &disp0_lock}, {MMP2_CLK_DISP0_SPHY, "disp0_sphy_clk", "disp0_sphy_div", CLK_SET_RATE_PARENT, APMU_DISP0, 0x1024, 0x1024, 0x0, 0, &disp0_lock},
{MMP2_CLK_DISP1, "disp1_clk", "disp1_div", CLK_SET_RATE_PARENT, APMU_DISP1, 0x1b, 0x1b, 0x0, 0, &disp1_lock}, {MMP2_CLK_DISP1, "disp1_clk", "disp1_div", CLK_SET_RATE_PARENT, APMU_DISP1, 0x1b, 0x1b, 0x0, 0, &disp1_lock},
......
...@@ -9,6 +9,20 @@ ...@@ -9,6 +9,20 @@
#ifndef _DT_BINDINGS_CLK_AT91_H #ifndef _DT_BINDINGS_CLK_AT91_H
#define _DT_BINDINGS_CLK_AT91_H #define _DT_BINDINGS_CLK_AT91_H
#define PMC_TYPE_CORE 0
#define PMC_TYPE_SYSTEM 1
#define PMC_TYPE_PERIPHERAL 2
#define PMC_TYPE_GCK 3
#define PMC_SLOW 0
#define PMC_MCK 1
#define PMC_UTMI 2
#define PMC_MAIN 3
#define PMC_MCK2 4
#define PMC_I2S0_MUX 5
#define PMC_I2S1_MUX 6
#ifndef AT91_PMC_MOSCS
#define AT91_PMC_MOSCS 0 /* MOSCS Flag */ #define AT91_PMC_MOSCS 0 /* MOSCS Flag */
#define AT91_PMC_LOCKA 1 /* PLLA Lock */ #define AT91_PMC_LOCKA 1 /* PLLA Lock */
#define AT91_PMC_LOCKB 2 /* PLLB Lock */ #define AT91_PMC_LOCKB 2 /* PLLB Lock */
...@@ -19,5 +33,6 @@ ...@@ -19,5 +33,6 @@
#define AT91_PMC_MOSCRCS 17 /* Main On-Chip RC */ #define AT91_PMC_MOSCRCS 17 /* Main On-Chip RC */
#define AT91_PMC_CFDEV 18 /* Clock Failure Detector Event */ #define AT91_PMC_CFDEV 18 /* Clock Failure Detector Event */
#define AT91_PMC_GCKRDY 24 /* Generated Clocks */ #define AT91_PMC_GCKRDY 24 /* Generated Clocks */
#endif
#endif #endif
This diff is collapsed.
This diff is collapsed.
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