^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Purna Chandra Mandal,<purna.mandal@microchip.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2015 Microchip Technology Inc. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <dt-bindings/clock/microchip,pic32-clock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/clkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/traps.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "clk-core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /* FRC Postscaler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define OSC_FRCDIV_MASK 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define OSC_FRCDIV_SHIFT 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* SPLL fields */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define PLL_ICLK_MASK 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define PLL_ICLK_SHIFT 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define DECLARE_PERIPHERAL_CLOCK(__clk_name, __reg, __flags) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) .ctrl_reg = (__reg), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) .init_data = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) .name = (__clk_name), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) .parent_names = (const char *[]) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) "sys_clk" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) .num_parents = 1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) .ops = &pic32_pbclk_ops, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) .flags = (__flags), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define DECLARE_REFO_CLOCK(__clkid, __reg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) .ctrl_reg = (__reg), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .init_data = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) .name = "refo" #__clkid "_clk", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .parent_names = (const char *[]) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) "sys_clk", "pb1_clk", "posc_clk", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) "frc_clk", "lprc_clk", "sosc_clk", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) "sys_pll", "refi" #__clkid "_clk", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) "bfrc_clk", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .num_parents = 9, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE,\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) .ops = &pic32_roclk_ops, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) .parent_map = (const u32[]) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) 0, 1, 2, 3, 4, 5, 7, 8, 9 \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static const struct pic32_ref_osc_data ref_clks[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) DECLARE_REFO_CLOCK(1, 0x80),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) DECLARE_REFO_CLOCK(2, 0xa0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) DECLARE_REFO_CLOCK(3, 0xc0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) DECLARE_REFO_CLOCK(4, 0xe0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) DECLARE_REFO_CLOCK(5, 0x100),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) static const struct pic32_periph_clk_data periph_clocks[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) DECLARE_PERIPHERAL_CLOCK("pb1_clk", 0x140, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) DECLARE_PERIPHERAL_CLOCK("pb2_clk", 0x150, CLK_IGNORE_UNUSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) DECLARE_PERIPHERAL_CLOCK("pb3_clk", 0x160, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) DECLARE_PERIPHERAL_CLOCK("pb4_clk", 0x170, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) DECLARE_PERIPHERAL_CLOCK("pb5_clk", 0x180, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) DECLARE_PERIPHERAL_CLOCK("pb6_clk", 0x190, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) DECLARE_PERIPHERAL_CLOCK("cpu_clk", 0x1a0, CLK_IGNORE_UNUSED),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static const struct pic32_sys_clk_data sys_mux_clk = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .slew_reg = 0x1c0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .slew_div = 2, /* step of div_4 -> div_2 -> no_div */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .init_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .name = "sys_clk",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .parent_names = (const char *[]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) "frcdiv_clk", "sys_pll", "posc_clk",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) "sosc_clk", "lprc_clk", "frcdiv_clk",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .num_parents = 6,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .ops = &pic32_sclk_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .parent_map = (const u32[]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) 0, 1, 2, 4, 5, 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static const struct pic32_sys_pll_data sys_pll = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .ctrl_reg = 0x020,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .status_reg = 0x1d0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .lock_mask = BIT(7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .init_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .name = "sys_pll",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .parent_names = (const char *[]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) "spll_mux_clk"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) .num_parents = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .ops = &pic32_spll_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static const struct pic32_sec_osc_data sosc_clk = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .status_reg = 0x1d0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .enable_mask = BIT(1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .status_mask = BIT(4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .fixed_rate = 32768,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .init_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .name = "sosc_clk",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) .parent_names = NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .ops = &pic32_sosc_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static int pic32mzda_critical_clks[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) PB2CLK, PB7CLK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* PIC32MZDA clock data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct pic32mzda_clk_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct clk *clks[MAXCLKS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct pic32_clk_common core;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct clk_onecell_data onecell_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct notifier_block failsafe_notifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static int pic32_fscm_nmi(struct notifier_block *nb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) unsigned long action, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct pic32mzda_clk_data *cd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) cd = container_of(nb, struct pic32mzda_clk_data, failsafe_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* SYSCLK is now running from BFRCCLK. Report clock failure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (readl(cd->core.iobase) & BIT(2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) pr_alert("pic32-clk: FSCM detected clk failure.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* TODO: detect reason of failure and recover accordingly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return NOTIFY_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static int pic32mzda_clk_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) const char *const pll_mux_parents[] = {"posc_clk", "frc_clk"};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct pic32mzda_clk_data *cd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct pic32_clk_common *core;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct clk *pll_mux_clk, *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct clk **clks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) int nr_clks, i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) cd = devm_kzalloc(&pdev->dev, sizeof(*cd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (!cd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) core = &cd->core;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) core->iobase = of_io_request_and_map(np, 0, of_node_full_name(np));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (IS_ERR(core->iobase)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) dev_err(&pdev->dev, "pic32-clk: failed to map registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return PTR_ERR(core->iobase);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) spin_lock_init(&core->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) core->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) clks = &cd->clks[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) /* register fixed rate clocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) clks[POSCCLK] = clk_register_fixed_rate(&pdev->dev, "posc_clk", NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 0, 24000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) clks[FRCCLK] = clk_register_fixed_rate(&pdev->dev, "frc_clk", NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 0, 8000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) clks[BFRCCLK] = clk_register_fixed_rate(&pdev->dev, "bfrc_clk", NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 0, 8000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) clks[LPRCCLK] = clk_register_fixed_rate(&pdev->dev, "lprc_clk", NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 0, 32000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) clks[UPLLCLK] = clk_register_fixed_rate(&pdev->dev, "usbphy_clk", NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 0, 24000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /* fixed rate (optional) clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (of_find_property(np, "microchip,pic32mzda-sosc", NULL)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) pr_info("pic32-clk: dt requests SOSC.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) clks[SOSCCLK] = pic32_sosc_clk_register(&sosc_clk, core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /* divider clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) clks[FRCDIVCLK] = clk_register_divider(&pdev->dev, "frcdiv_clk",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) "frc_clk", 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) core->iobase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) OSC_FRCDIV_SHIFT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) OSC_FRCDIV_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) CLK_DIVIDER_POWER_OF_TWO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) &core->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) /* PLL ICLK mux */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) pll_mux_clk = clk_register_mux(&pdev->dev, "spll_mux_clk",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) pll_mux_parents, 2, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) core->iobase + 0x020,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) PLL_ICLK_SHIFT, 1, 0, &core->reg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (IS_ERR(pll_mux_clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) pr_err("spll_mux_clk: clk register failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /* PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) clks[PLLCLK] = pic32_spll_clk_register(&sys_pll, core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /* SYSTEM clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) clks[SCLK] = pic32_sys_clk_register(&sys_mux_clk, core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /* Peripheral bus clocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) for (nr_clks = PB1CLK, i = 0; nr_clks <= PB7CLK; i++, nr_clks++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) clks[nr_clks] = pic32_periph_clk_register(&periph_clocks[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /* Reference oscillator clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) for (nr_clks = REF1CLK, i = 0; nr_clks <= REF5CLK; i++, nr_clks++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) clks[nr_clks] = pic32_refo_clk_register(&ref_clks[i], core);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /* register clkdev */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) for (i = 0; i < MAXCLKS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (IS_ERR(clks[i]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) clk_register_clkdev(clks[i], NULL, __clk_get_name(clks[i]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* register clock provider */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) cd->onecell_data.clks = clks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) cd->onecell_data.clk_num = MAXCLKS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) ret = of_clk_add_provider(np, of_clk_src_onecell_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) &cd->onecell_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /* force enable critical clocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) for (i = 0; i < ARRAY_SIZE(pic32mzda_critical_clks); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) clk = clks[pic32mzda_critical_clks[i]];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (clk_prepare_enable(clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) dev_err(&pdev->dev, "clk_prepare_enable(%s) failed\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) __clk_get_name(clk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /* register NMI for failsafe clock monitor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) cd->failsafe_notifier.notifier_call = pic32_fscm_nmi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return register_nmi_notifier(&cd->failsafe_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static const struct of_device_id pic32mzda_clk_match_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) { .compatible = "microchip,pic32mzda-clk", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) MODULE_DEVICE_TABLE(of, pic32mzda_clk_match_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static struct platform_driver pic32mzda_clk_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) .probe = pic32mzda_clk_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) .name = "clk-pic32mzda",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) .of_match_table = pic32mzda_clk_match_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static int __init microchip_pic32mzda_clk_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return platform_driver_register(&pic32mzda_clk_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) core_initcall(microchip_pic32mzda_clk_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) MODULE_DESCRIPTION("Microchip PIC32MZDA Clock Driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) MODULE_ALIAS("platform:clk-pic32mzda");