1247 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * SAMA7G5 PMC code.4 *5 * Copyright (C) 2020 Microchip Technology Inc. and its subsidiaries6 *7 * Author: Claudiu Beznea <claudiu.beznea@microchip.com>8 *9 */10#include <linux/clk.h>11#include <linux/clk-provider.h>12#include <linux/mfd/syscon.h>13#include <linux/slab.h>14 15#include <dt-bindings/clock/at91.h>16 17#include "pmc.h"18 19static DEFINE_SPINLOCK(pmc_pll_lock);20static DEFINE_SPINLOCK(pmc_mck0_lock);21static DEFINE_SPINLOCK(pmc_mckX_lock);22 23/*24 * PLL clocks identifiers25 * @PLL_ID_CPU: CPU PLL identifier26 * @PLL_ID_SYS: System PLL identifier27 * @PLL_ID_DDR: DDR PLL identifier28 * @PLL_ID_IMG: Image subsystem PLL identifier29 * @PLL_ID_BAUD: Baud PLL identifier30 * @PLL_ID_AUDIO: Audio PLL identifier31 * @PLL_ID_ETH: Ethernet PLL identifier32 */33enum pll_ids {34 PLL_ID_CPU,35 PLL_ID_SYS,36 PLL_ID_DDR,37 PLL_ID_IMG,38 PLL_ID_BAUD,39 PLL_ID_AUDIO,40 PLL_ID_ETH,41 PLL_ID_MAX,42};43 44/*45 * PLL component identifier46 * @PLL_COMPID_FRAC: Fractional PLL component identifier47 * @PLL_COMPID_DIV0: 1st PLL divider component identifier48 * @PLL_COMPID_DIV1: 2nd PLL divider component identifier49 */50enum pll_component_id {51 PLL_COMPID_FRAC,52 PLL_COMPID_DIV0,53 PLL_COMPID_DIV1,54 PLL_COMPID_MAX,55};56 57/*58 * PLL type identifiers59 * @PLL_TYPE_FRAC: fractional PLL identifier60 * @PLL_TYPE_DIV: divider PLL identifier61 */62enum pll_type {63 PLL_TYPE_FRAC,64 PLL_TYPE_DIV,65};66 67/* Layout for fractional PLLs. */68static const struct clk_pll_layout pll_layout_frac = {69 .mul_mask = GENMASK(31, 24),70 .frac_mask = GENMASK(21, 0),71 .mul_shift = 24,72 .frac_shift = 0,73};74 75/* Layout for DIVPMC dividers. */76static const struct clk_pll_layout pll_layout_divpmc = {77 .div_mask = GENMASK(7, 0),78 .endiv_mask = BIT(29),79 .div_shift = 0,80 .endiv_shift = 29,81};82 83/* Layout for DIVIO dividers. */84static const struct clk_pll_layout pll_layout_divio = {85 .div_mask = GENMASK(19, 12),86 .endiv_mask = BIT(30),87 .div_shift = 12,88 .endiv_shift = 30,89};90 91/*92 * CPU PLL output range.93 * Notice: The upper limit has been setup to 1000000002 due to hardware94 * block which cannot output exactly 1GHz.95 */96static const struct clk_range cpu_pll_outputs[] = {97 { .min = 2343750, .max = 1000000002 },98};99 100/* PLL output range. */101static const struct clk_range pll_outputs[] = {102 { .min = 2343750, .max = 1200000000 },103};104 105/* Fractional PLL core output range. */106static const struct clk_range core_outputs[] = {107 { .min = 600000000, .max = 1200000000 },108};109 110/* CPU PLL characteristics. */111static const struct clk_pll_characteristics cpu_pll_characteristics = {112 .input = { .min = 12000000, .max = 50000000 },113 .num_output = ARRAY_SIZE(cpu_pll_outputs),114 .output = cpu_pll_outputs,115 .core_output = core_outputs,116};117 118/* PLL characteristics. */119static const struct clk_pll_characteristics pll_characteristics = {120 .input = { .min = 12000000, .max = 50000000 },121 .num_output = ARRAY_SIZE(pll_outputs),122 .output = pll_outputs,123 .core_output = core_outputs,124};125 126/*127 * SAMA7G5 PLL possible parents128 * @SAMA7G5_PLL_PARENT_MAINCK: MAINCK is PLL a parent129 * @SAMA7G5_PLL_PARENT_MAIN_XTAL: MAIN XTAL is a PLL parent130 * @SAMA7G5_PLL_PARENT_FRACCK: Frac PLL is a PLL parent (for PLL dividers)131 */132enum sama7g5_pll_parent {133 SAMA7G5_PLL_PARENT_MAINCK,134 SAMA7G5_PLL_PARENT_MAIN_XTAL,135 SAMA7G5_PLL_PARENT_FRACCK,136};137 138/*139 * PLL clocks description140 * @n: clock name141 * @l: clock layout142 * @c: clock characteristics143 * @hw: pointer to clk_hw144 * @t: clock type145 * @f: clock flags146 * @p: clock parent147 * @eid: export index in sama7g5->chws[] array148 * @safe_div: intermediate divider need to be set on PRE_RATE_CHANGE149 * notification150 */151static struct sama7g5_pll {152 const char *n;153 const struct clk_pll_layout *l;154 const struct clk_pll_characteristics *c;155 struct clk_hw *hw;156 unsigned long f;157 enum sama7g5_pll_parent p;158 u8 t;159 u8 eid;160 u8 safe_div;161} sama7g5_plls[][PLL_COMPID_MAX] = {162 [PLL_ID_CPU] = {163 [PLL_COMPID_FRAC] = {164 .n = "cpupll_fracck",165 .p = SAMA7G5_PLL_PARENT_MAINCK,166 .l = &pll_layout_frac,167 .c = &cpu_pll_characteristics,168 .t = PLL_TYPE_FRAC,169 /*170 * This feeds cpupll_divpmcck which feeds CPU. It should171 * not be disabled.172 */173 .f = CLK_IS_CRITICAL,174 },175 176 [PLL_COMPID_DIV0] = {177 .n = "cpupll_divpmcck",178 .p = SAMA7G5_PLL_PARENT_FRACCK,179 .l = &pll_layout_divpmc,180 .c = &cpu_pll_characteristics,181 .t = PLL_TYPE_DIV,182 /* This feeds CPU. It should not be disabled. */183 .f = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT,184 .eid = PMC_CPUPLL,185 /*186 * Safe div=15 should be safe even for switching b/w 1GHz and187 * 90MHz (frac pll might go up to 1.2GHz).188 */189 .safe_div = 15,190 },191 },192 193 [PLL_ID_SYS] = {194 [PLL_COMPID_FRAC] = {195 .n = "syspll_fracck",196 .p = SAMA7G5_PLL_PARENT_MAINCK,197 .l = &pll_layout_frac,198 .c = &pll_characteristics,199 .t = PLL_TYPE_FRAC,200 /*201 * This feeds syspll_divpmcck which may feed critical parts202 * of the systems like timers. Therefore it should not be203 * disabled.204 */205 .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,206 },207 208 [PLL_COMPID_DIV0] = {209 .n = "syspll_divpmcck",210 .p = SAMA7G5_PLL_PARENT_FRACCK,211 .l = &pll_layout_divpmc,212 .c = &pll_characteristics,213 .t = PLL_TYPE_DIV,214 /*215 * This may feed critical parts of the systems like timers.216 * Therefore it should not be disabled.217 */218 .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,219 .eid = PMC_SYSPLL,220 },221 },222 223 [PLL_ID_DDR] = {224 [PLL_COMPID_FRAC] = {225 .n = "ddrpll_fracck",226 .p = SAMA7G5_PLL_PARENT_MAINCK,227 .l = &pll_layout_frac,228 .c = &pll_characteristics,229 .t = PLL_TYPE_FRAC,230 /*231 * This feeds ddrpll_divpmcck which feeds DDR. It should not232 * be disabled.233 */234 .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,235 },236 237 [PLL_COMPID_DIV0] = {238 .n = "ddrpll_divpmcck",239 .p = SAMA7G5_PLL_PARENT_FRACCK,240 .l = &pll_layout_divpmc,241 .c = &pll_characteristics,242 .t = PLL_TYPE_DIV,243 /* This feeds DDR. It should not be disabled. */244 .f = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,245 },246 },247 248 [PLL_ID_IMG] = {249 [PLL_COMPID_FRAC] = {250 .n = "imgpll_fracck",251 .p = SAMA7G5_PLL_PARENT_MAINCK,252 .l = &pll_layout_frac,253 .c = &pll_characteristics,254 .t = PLL_TYPE_FRAC,255 .f = CLK_SET_RATE_GATE,256 },257 258 [PLL_COMPID_DIV0] = {259 .n = "imgpll_divpmcck",260 .p = SAMA7G5_PLL_PARENT_FRACCK,261 .l = &pll_layout_divpmc,262 .c = &pll_characteristics,263 .t = PLL_TYPE_DIV,264 .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |265 CLK_SET_RATE_PARENT,266 },267 },268 269 [PLL_ID_BAUD] = {270 [PLL_COMPID_FRAC] = {271 .n = "baudpll_fracck",272 .p = SAMA7G5_PLL_PARENT_MAINCK,273 .l = &pll_layout_frac,274 .c = &pll_characteristics,275 .t = PLL_TYPE_FRAC,276 .f = CLK_SET_RATE_GATE, },277 278 [PLL_COMPID_DIV0] = {279 .n = "baudpll_divpmcck",280 .p = SAMA7G5_PLL_PARENT_FRACCK,281 .l = &pll_layout_divpmc,282 .c = &pll_characteristics,283 .t = PLL_TYPE_DIV,284 .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |285 CLK_SET_RATE_PARENT,286 },287 },288 289 [PLL_ID_AUDIO] = {290 [PLL_COMPID_FRAC] = {291 .n = "audiopll_fracck",292 .p = SAMA7G5_PLL_PARENT_MAIN_XTAL,293 .l = &pll_layout_frac,294 .c = &pll_characteristics,295 .t = PLL_TYPE_FRAC,296 .f = CLK_SET_RATE_GATE,297 },298 299 [PLL_COMPID_DIV0] = {300 .n = "audiopll_divpmcck",301 .p = SAMA7G5_PLL_PARENT_FRACCK,302 .l = &pll_layout_divpmc,303 .c = &pll_characteristics,304 .t = PLL_TYPE_DIV,305 .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |306 CLK_SET_RATE_PARENT,307 .eid = PMC_AUDIOPMCPLL,308 },309 310 [PLL_COMPID_DIV1] = {311 .n = "audiopll_diviock",312 .p = SAMA7G5_PLL_PARENT_FRACCK,313 .l = &pll_layout_divio,314 .c = &pll_characteristics,315 .t = PLL_TYPE_DIV,316 .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |317 CLK_SET_RATE_PARENT,318 .eid = PMC_AUDIOIOPLL,319 },320 },321 322 [PLL_ID_ETH] = {323 [PLL_COMPID_FRAC] = {324 .n = "ethpll_fracck",325 .p = SAMA7G5_PLL_PARENT_MAIN_XTAL,326 .l = &pll_layout_frac,327 .c = &pll_characteristics,328 .t = PLL_TYPE_FRAC,329 .f = CLK_SET_RATE_GATE,330 },331 332 [PLL_COMPID_DIV0] = {333 .n = "ethpll_divpmcck",334 .p = SAMA7G5_PLL_PARENT_FRACCK,335 .l = &pll_layout_divpmc,336 .c = &pll_characteristics,337 .t = PLL_TYPE_DIV,338 .f = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |339 CLK_SET_RATE_PARENT,340 },341 },342};343 344/* Used to create an array entry identifying a PLL by its components. */345#define PLL_IDS_TO_ARR_ENTRY(_id, _comp) { PLL_ID_##_id, PLL_COMPID_##_comp}346 347/*348 * Master clock (MCK[1..4]) description349 * @n: clock name350 * @ep: extra parents names array (entry formed by PLL components351 * identifiers (see enum pll_component_id))352 * @hw: pointer to clk_hw353 * @ep_chg_id: index in parents array that specifies the changeable354 * parent355 * @ep_count: extra parents count356 * @ep_mux_table: mux table for extra parents357 * @id: clock id358 * @eid: export index in sama7g5->chws[] array359 * @c: true if clock is critical and cannot be disabled360 */361static struct {362 const char *n;363 struct {364 int pll_id;365 int pll_compid;366 } ep[4];367 struct clk_hw *hw;368 int ep_chg_id;369 u8 ep_count;370 u8 ep_mux_table[4];371 u8 id;372 u8 eid;373 u8 c;374} sama7g5_mckx[] = {375 { .n = "mck0", }, /* Dummy entry for MCK0 to store hw in probe. */376 { .n = "mck1",377 .id = 1,378 .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), },379 .ep_mux_table = { 5, },380 .ep_count = 1,381 .ep_chg_id = INT_MIN,382 .eid = PMC_MCK1,383 .c = 1, },384 385 { .n = "mck2",386 .id = 2,387 .ep = { PLL_IDS_TO_ARR_ENTRY(DDR, DIV0), },388 .ep_mux_table = { 6, },389 .ep_count = 1,390 .ep_chg_id = INT_MIN,391 .c = 1, },392 393 { .n = "mck3",394 .id = 3,395 .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(DDR, DIV0),396 PLL_IDS_TO_ARR_ENTRY(IMG, DIV0), },397 .ep_mux_table = { 5, 6, 7, },398 .ep_count = 3,399 .ep_chg_id = 5, },400 401 { .n = "mck4",402 .id = 4,403 .ep = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), },404 .ep_mux_table = { 5, },405 .ep_count = 1,406 .ep_chg_id = INT_MIN,407 .c = 1, },408};409 410/*411 * System clock description412 * @n: clock name413 * @id: clock id414 */415static const struct {416 const char *n;417 u8 id;418} sama7g5_systemck[] = {419 { .n = "pck0", .id = 8, },420 { .n = "pck1", .id = 9, },421 { .n = "pck2", .id = 10, },422 { .n = "pck3", .id = 11, },423 { .n = "pck4", .id = 12, },424 { .n = "pck5", .id = 13, },425 { .n = "pck6", .id = 14, },426 { .n = "pck7", .id = 15, },427};428 429/* Mux table for programmable clocks. */430static u32 sama7g5_prog_mux_table[] = { 0, 1, 2, 5, 6, 7, 8, 9, 10, };431 432/*433 * Peripheral clock parent hw identifier (used to index in sama7g5_mckx[])434 * @PCK_PARENT_HW_MCK0: pck parent hw identifier is MCK0435 * @PCK_PARENT_HW_MCK1: pck parent hw identifier is MCK1436 * @PCK_PARENT_HW_MCK2: pck parent hw identifier is MCK2437 * @PCK_PARENT_HW_MCK3: pck parent hw identifier is MCK3438 * @PCK_PARENT_HW_MCK4: pck parent hw identifier is MCK4439 * @PCK_PARENT_HW_MAX: max identifier440 */441enum sama7g5_pck_parent_hw_id {442 PCK_PARENT_HW_MCK0,443 PCK_PARENT_HW_MCK1,444 PCK_PARENT_HW_MCK2,445 PCK_PARENT_HW_MCK3,446 PCK_PARENT_HW_MCK4,447 PCK_PARENT_HW_MAX,448};449 450/*451 * Peripheral clock description452 * @n: clock name453 * @p: clock parent hw id454 * @r: clock range values455 * @id: clock id456 * @chgp: index in parent array of the changeable parent457 */458static struct {459 const char *n;460 enum sama7g5_pck_parent_hw_id p;461 struct clk_range r;462 u8 chgp;463 u8 id;464} sama7g5_periphck[] = {465 { .n = "pioA_clk", .p = PCK_PARENT_HW_MCK0, .id = 11, },466 { .n = "securam_clk", .p = PCK_PARENT_HW_MCK0, .id = 18, },467 { .n = "sfr_clk", .p = PCK_PARENT_HW_MCK1, .id = 19, },468 { .n = "hsmc_clk", .p = PCK_PARENT_HW_MCK1, .id = 21, },469 { .n = "xdmac0_clk", .p = PCK_PARENT_HW_MCK1, .id = 22, },470 { .n = "xdmac1_clk", .p = PCK_PARENT_HW_MCK1, .id = 23, },471 { .n = "xdmac2_clk", .p = PCK_PARENT_HW_MCK1, .id = 24, },472 { .n = "acc_clk", .p = PCK_PARENT_HW_MCK1, .id = 25, },473 { .n = "aes_clk", .p = PCK_PARENT_HW_MCK1, .id = 27, },474 { .n = "tzaesbasc_clk", .p = PCK_PARENT_HW_MCK1, .id = 28, },475 { .n = "asrc_clk", .p = PCK_PARENT_HW_MCK1, .id = 30, .r = { .max = 200000000, }, },476 { .n = "cpkcc_clk", .p = PCK_PARENT_HW_MCK0, .id = 32, },477 { .n = "csi_clk", .p = PCK_PARENT_HW_MCK3, .id = 33, .r = { .max = 266000000, }, .chgp = 1, },478 { .n = "csi2dc_clk", .p = PCK_PARENT_HW_MCK3, .id = 34, .r = { .max = 266000000, }, .chgp = 1, },479 { .n = "eic_clk", .p = PCK_PARENT_HW_MCK1, .id = 37, },480 { .n = "flex0_clk", .p = PCK_PARENT_HW_MCK1, .id = 38, },481 { .n = "flex1_clk", .p = PCK_PARENT_HW_MCK1, .id = 39, },482 { .n = "flex2_clk", .p = PCK_PARENT_HW_MCK1, .id = 40, },483 { .n = "flex3_clk", .p = PCK_PARENT_HW_MCK1, .id = 41, },484 { .n = "flex4_clk", .p = PCK_PARENT_HW_MCK1, .id = 42, },485 { .n = "flex5_clk", .p = PCK_PARENT_HW_MCK1, .id = 43, },486 { .n = "flex6_clk", .p = PCK_PARENT_HW_MCK1, .id = 44, },487 { .n = "flex7_clk", .p = PCK_PARENT_HW_MCK1, .id = 45, },488 { .n = "flex8_clk", .p = PCK_PARENT_HW_MCK1, .id = 46, },489 { .n = "flex9_clk", .p = PCK_PARENT_HW_MCK1, .id = 47, },490 { .n = "flex10_clk", .p = PCK_PARENT_HW_MCK1, .id = 48, },491 { .n = "flex11_clk", .p = PCK_PARENT_HW_MCK1, .id = 49, },492 { .n = "gmac0_clk", .p = PCK_PARENT_HW_MCK1, .id = 51, },493 { .n = "gmac1_clk", .p = PCK_PARENT_HW_MCK1, .id = 52, },494 { .n = "icm_clk", .p = PCK_PARENT_HW_MCK1, .id = 55, },495 { .n = "isc_clk", .p = PCK_PARENT_HW_MCK3, .id = 56, .r = { .max = 266000000, }, .chgp = 1, },496 { .n = "i2smcc0_clk", .p = PCK_PARENT_HW_MCK1, .id = 57, .r = { .max = 200000000, }, },497 { .n = "i2smcc1_clk", .p = PCK_PARENT_HW_MCK1, .id = 58, .r = { .max = 200000000, }, },498 { .n = "matrix_clk", .p = PCK_PARENT_HW_MCK1, .id = 60, },499 { .n = "mcan0_clk", .p = PCK_PARENT_HW_MCK1, .id = 61, .r = { .max = 200000000, }, },500 { .n = "mcan1_clk", .p = PCK_PARENT_HW_MCK1, .id = 62, .r = { .max = 200000000, }, },501 { .n = "mcan2_clk", .p = PCK_PARENT_HW_MCK1, .id = 63, .r = { .max = 200000000, }, },502 { .n = "mcan3_clk", .p = PCK_PARENT_HW_MCK1, .id = 64, .r = { .max = 200000000, }, },503 { .n = "mcan4_clk", .p = PCK_PARENT_HW_MCK1, .id = 65, .r = { .max = 200000000, }, },504 { .n = "mcan5_clk", .p = PCK_PARENT_HW_MCK1, .id = 66, .r = { .max = 200000000, }, },505 { .n = "pdmc0_clk", .p = PCK_PARENT_HW_MCK1, .id = 68, .r = { .max = 200000000, }, },506 { .n = "pdmc1_clk", .p = PCK_PARENT_HW_MCK1, .id = 69, .r = { .max = 200000000, }, },507 { .n = "pit64b0_clk", .p = PCK_PARENT_HW_MCK1, .id = 70, },508 { .n = "pit64b1_clk", .p = PCK_PARENT_HW_MCK1, .id = 71, },509 { .n = "pit64b2_clk", .p = PCK_PARENT_HW_MCK1, .id = 72, },510 { .n = "pit64b3_clk", .p = PCK_PARENT_HW_MCK1, .id = 73, },511 { .n = "pit64b4_clk", .p = PCK_PARENT_HW_MCK1, .id = 74, },512 { .n = "pit64b5_clk", .p = PCK_PARENT_HW_MCK1, .id = 75, },513 { .n = "pwm_clk", .p = PCK_PARENT_HW_MCK1, .id = 77, },514 { .n = "qspi0_clk", .p = PCK_PARENT_HW_MCK1, .id = 78, },515 { .n = "qspi1_clk", .p = PCK_PARENT_HW_MCK1, .id = 79, },516 { .n = "sdmmc0_clk", .p = PCK_PARENT_HW_MCK1, .id = 80, },517 { .n = "sdmmc1_clk", .p = PCK_PARENT_HW_MCK1, .id = 81, },518 { .n = "sdmmc2_clk", .p = PCK_PARENT_HW_MCK1, .id = 82, },519 { .n = "sha_clk", .p = PCK_PARENT_HW_MCK1, .id = 83, },520 { .n = "spdifrx_clk", .p = PCK_PARENT_HW_MCK1, .id = 84, .r = { .max = 200000000, }, },521 { .n = "spdiftx_clk", .p = PCK_PARENT_HW_MCK1, .id = 85, .r = { .max = 200000000, }, },522 { .n = "ssc0_clk", .p = PCK_PARENT_HW_MCK1, .id = 86, .r = { .max = 200000000, }, },523 { .n = "ssc1_clk", .p = PCK_PARENT_HW_MCK1, .id = 87, .r = { .max = 200000000, }, },524 { .n = "tcb0_ch0_clk", .p = PCK_PARENT_HW_MCK1, .id = 88, .r = { .max = 200000000, }, },525 { .n = "tcb0_ch1_clk", .p = PCK_PARENT_HW_MCK1, .id = 89, .r = { .max = 200000000, }, },526 { .n = "tcb0_ch2_clk", .p = PCK_PARENT_HW_MCK1, .id = 90, .r = { .max = 200000000, }, },527 { .n = "tcb1_ch0_clk", .p = PCK_PARENT_HW_MCK1, .id = 91, .r = { .max = 200000000, }, },528 { .n = "tcb1_ch1_clk", .p = PCK_PARENT_HW_MCK1, .id = 92, .r = { .max = 200000000, }, },529 { .n = "tcb1_ch2_clk", .p = PCK_PARENT_HW_MCK1, .id = 93, .r = { .max = 200000000, }, },530 { .n = "tcpca_clk", .p = PCK_PARENT_HW_MCK1, .id = 94, },531 { .n = "tcpcb_clk", .p = PCK_PARENT_HW_MCK1, .id = 95, },532 { .n = "tdes_clk", .p = PCK_PARENT_HW_MCK1, .id = 96, },533 { .n = "trng_clk", .p = PCK_PARENT_HW_MCK1, .id = 97, },534 { .n = "udphsa_clk", .p = PCK_PARENT_HW_MCK1, .id = 104, },535 { .n = "udphsb_clk", .p = PCK_PARENT_HW_MCK1, .id = 105, },536 { .n = "uhphs_clk", .p = PCK_PARENT_HW_MCK1, .id = 106, },537};538 539/*540 * Generic clock description541 * @n: clock name542 * @pp: PLL parents (entry formed by PLL components identifiers543 * (see enum pll_component_id))544 * @pp_mux_table: PLL parents mux table545 * @r: clock output range546 * @pp_chg_id: id in parent array of changeable PLL parent547 * @pp_count: PLL parents count548 * @id: clock id549 */550static const struct {551 const char *n;552 struct {553 int pll_id;554 int pll_compid;555 } pp[8];556 const char pp_mux_table[8];557 struct clk_range r;558 int pp_chg_id;559 u8 pp_count;560 u8 id;561} sama7g5_gck[] = {562 { .n = "adc_gclk",563 .id = 26,564 .r = { .max = 100000000, },565 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),566 PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },567 .pp_mux_table = { 5, 7, 9, },568 .pp_count = 3,569 .pp_chg_id = INT_MIN, },570 571 { .n = "asrc_gclk",572 .id = 30,573 .r = { .max = 200000000 },574 .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },575 .pp_mux_table = { 9, },576 .pp_count = 1,577 .pp_chg_id = 3, },578 579 { .n = "csi_gclk",580 .id = 33,581 .r = { .max = 27000000 },582 .pp = { PLL_IDS_TO_ARR_ENTRY(DDR, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0), },583 .pp_mux_table = { 6, 7, },584 .pp_count = 2,585 .pp_chg_id = INT_MIN, },586 587 { .n = "flex0_gclk",588 .id = 38,589 .r = { .max = 200000000 },590 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },591 .pp_mux_table = { 5, 8, },592 .pp_count = 2,593 .pp_chg_id = INT_MIN, },594 595 { .n = "flex1_gclk",596 .id = 39,597 .r = { .max = 200000000 },598 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },599 .pp_mux_table = { 5, 8, },600 .pp_count = 2,601 .pp_chg_id = INT_MIN, },602 603 { .n = "flex2_gclk",604 .id = 40,605 .r = { .max = 200000000 },606 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },607 .pp_mux_table = { 5, 8, },608 .pp_count = 2,609 .pp_chg_id = INT_MIN, },610 611 { .n = "flex3_gclk",612 .id = 41,613 .r = { .max = 200000000 },614 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },615 .pp_mux_table = { 5, 8, },616 .pp_count = 2,617 .pp_chg_id = INT_MIN, },618 619 { .n = "flex4_gclk",620 .id = 42,621 .r = { .max = 200000000 },622 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },623 .pp_mux_table = { 5, 8, },624 .pp_count = 2,625 .pp_chg_id = INT_MIN, },626 627 { .n = "flex5_gclk",628 .id = 43,629 .r = { .max = 200000000 },630 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },631 .pp_mux_table = { 5, 8, },632 .pp_count = 2,633 .pp_chg_id = INT_MIN, },634 635 { .n = "flex6_gclk",636 .id = 44,637 .r = { .max = 200000000 },638 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },639 .pp_mux_table = { 5, 8, },640 .pp_count = 2,641 .pp_chg_id = INT_MIN, },642 643 { .n = "flex7_gclk",644 .id = 45,645 .r = { .max = 200000000 },646 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },647 .pp_mux_table = { 5, 8, },648 .pp_count = 2,649 .pp_chg_id = INT_MIN, },650 651 { .n = "flex8_gclk",652 .id = 46,653 .r = { .max = 200000000 },654 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },655 .pp_mux_table = { 5, 8, },656 .pp_count = 2,657 .pp_chg_id = INT_MIN, },658 659 { .n = "flex9_gclk",660 .id = 47,661 .r = { .max = 200000000 },662 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },663 .pp_mux_table = { 5, 8, },664 .pp_count = 2,665 .pp_chg_id = INT_MIN, },666 667 { .n = "flex10_gclk",668 .id = 48,669 .r = { .max = 200000000 },670 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },671 .pp_mux_table = { 5, 8, },672 .pp_count = 2,673 .pp_chg_id = INT_MIN, },674 675 { .n = "flex11_gclk",676 .id = 49,677 .r = { .max = 200000000 },678 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },679 .pp_mux_table = { 5, 8, },680 .pp_count = 2,681 .pp_chg_id = INT_MIN, },682 683 { .n = "gmac0_gclk",684 .id = 51,685 .r = { .max = 125000000 },686 .pp = { PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },687 .pp_mux_table = { 10, },688 .pp_count = 1,689 .pp_chg_id = 3, },690 691 { .n = "gmac1_gclk",692 .id = 52,693 .r = { .max = 50000000 },694 .pp = { PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },695 .pp_mux_table = { 10, },696 .pp_count = 1,697 .pp_chg_id = INT_MIN, },698 699 { .n = "gmac0_tsu_gclk",700 .id = 53,701 .r = { .max = 300000000 },702 .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },703 .pp_mux_table = { 9, 10, },704 .pp_count = 2,705 .pp_chg_id = INT_MIN, },706 707 { .n = "gmac1_tsu_gclk",708 .id = 54,709 .r = { .max = 300000000 },710 .pp = { PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },711 .pp_mux_table = { 9, 10, },712 .pp_count = 2,713 .pp_chg_id = INT_MIN, },714 715 { .n = "i2smcc0_gclk",716 .id = 57,717 .r = { .max = 100000000 },718 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },719 .pp_mux_table = { 5, 9, },720 .pp_count = 2,721 .pp_chg_id = 4, },722 723 { .n = "i2smcc1_gclk",724 .id = 58,725 .r = { .max = 100000000 },726 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },727 .pp_mux_table = { 5, 9, },728 .pp_count = 2,729 .pp_chg_id = 4, },730 731 { .n = "mcan0_gclk",732 .id = 61,733 .r = { .max = 200000000 },734 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },735 .pp_mux_table = { 5, 8, },736 .pp_count = 2,737 .pp_chg_id = INT_MIN, },738 739 { .n = "mcan1_gclk",740 .id = 62,741 .r = { .max = 200000000 },742 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },743 .pp_mux_table = { 5, 8, },744 .pp_count = 2,745 .pp_chg_id = INT_MIN, },746 747 { .n = "mcan2_gclk",748 .id = 63,749 .r = { .max = 200000000 },750 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },751 .pp_mux_table = { 5, 8, },752 .pp_count = 2,753 .pp_chg_id = INT_MIN, },754 755 { .n = "mcan3_gclk",756 .id = 64,757 .r = { .max = 200000000 },758 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },759 .pp_mux_table = { 5, 8, },760 .pp_count = 2,761 .pp_chg_id = INT_MIN, },762 763 { .n = "mcan4_gclk",764 .id = 65,765 .r = { .max = 200000000 },766 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },767 .pp_mux_table = { 5, 8, },768 .pp_count = 2,769 .pp_chg_id = INT_MIN, },770 771 { .n = "mcan5_gclk",772 .id = 66,773 .r = { .max = 200000000 },774 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },775 .pp_mux_table = { 5, 8, },776 .pp_count = 2,777 .pp_chg_id = INT_MIN, },778 779 { .n = "pdmc0_gclk",780 .id = 68,781 .r = { .max = 50000000 },782 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },783 .pp_mux_table = { 5, 9, },784 .pp_count = 2,785 .pp_chg_id = INT_MIN, },786 787 { .n = "pdmc1_gclk",788 .id = 69,789 .r = { .max = 50000000, },790 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },791 .pp_mux_table = { 5, 9, },792 .pp_count = 2,793 .pp_chg_id = INT_MIN, },794 795 { .n = "pit64b0_gclk",796 .id = 70,797 .r = { .max = 200000000 },798 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),799 PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),800 PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },801 .pp_mux_table = { 5, 7, 8, 9, 10, },802 .pp_count = 5,803 .pp_chg_id = INT_MIN, },804 805 { .n = "pit64b1_gclk",806 .id = 71,807 .r = { .max = 200000000 },808 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),809 PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),810 PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },811 .pp_mux_table = { 5, 7, 8, 9, 10, },812 .pp_count = 5,813 .pp_chg_id = INT_MIN, },814 815 { .n = "pit64b2_gclk",816 .id = 72,817 .r = { .max = 200000000 },818 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),819 PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),820 PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },821 .pp_mux_table = { 5, 7, 8, 9, 10, },822 .pp_count = 5,823 .pp_chg_id = INT_MIN, },824 825 { .n = "pit64b3_gclk",826 .id = 73,827 .r = { .max = 200000000 },828 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),829 PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),830 PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },831 .pp_mux_table = { 5, 7, 8, 9, 10, },832 .pp_count = 5,833 .pp_chg_id = INT_MIN, },834 835 { .n = "pit64b4_gclk",836 .id = 74,837 .r = { .max = 200000000 },838 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),839 PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),840 PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },841 .pp_mux_table = { 5, 7, 8, 9, 10, },842 .pp_count = 5,843 .pp_chg_id = INT_MIN, },844 845 { .n = "pit64b5_gclk",846 .id = 75,847 .r = { .max = 200000000 },848 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),849 PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),850 PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },851 .pp_mux_table = { 5, 7, 8, 9, 10, },852 .pp_count = 5,853 .pp_chg_id = INT_MIN, },854 855 { .n = "qspi0_gclk",856 .id = 78,857 .r = { .max = 200000000 },858 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },859 .pp_mux_table = { 5, 8, },860 .pp_count = 2,861 .pp_chg_id = INT_MIN, },862 863 { .n = "qspi1_gclk",864 .id = 79,865 .r = { .max = 200000000 },866 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },867 .pp_mux_table = { 5, 8, },868 .pp_count = 2,869 .pp_chg_id = INT_MIN, },870 871 { .n = "sdmmc0_gclk",872 .id = 80,873 .r = { .max = 208000000 },874 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },875 .pp_mux_table = { 5, 8, },876 .pp_count = 2,877 .pp_chg_id = 4, },878 879 { .n = "sdmmc1_gclk",880 .id = 81,881 .r = { .max = 208000000 },882 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },883 .pp_mux_table = { 5, 8, },884 .pp_count = 2,885 .pp_chg_id = 4, },886 887 { .n = "sdmmc2_gclk",888 .id = 82,889 .r = { .max = 208000000 },890 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), },891 .pp_mux_table = { 5, 8, },892 .pp_count = 2,893 .pp_chg_id = 4, },894 895 { .n = "spdifrx_gclk",896 .id = 84,897 .r = { .max = 150000000 },898 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },899 .pp_mux_table = { 5, 9, },900 .pp_count = 2,901 .pp_chg_id = 4, },902 903 { .n = "spdiftx_gclk",904 .id = 85,905 .r = { .max = 25000000 },906 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0), },907 .pp_mux_table = { 5, 9, },908 .pp_count = 2,909 .pp_chg_id = 4, },910 911 { .n = "tcb0_ch0_gclk",912 .id = 88,913 .r = { .max = 200000000 },914 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),915 PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),916 PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },917 .pp_mux_table = { 5, 7, 8, 9, 10, },918 .pp_count = 5,919 .pp_chg_id = INT_MIN, },920 921 { .n = "tcb1_ch0_gclk",922 .id = 91,923 .r = { .max = 200000000 },924 .pp = { PLL_IDS_TO_ARR_ENTRY(SYS, DIV0), PLL_IDS_TO_ARR_ENTRY(IMG, DIV0),925 PLL_IDS_TO_ARR_ENTRY(BAUD, DIV0), PLL_IDS_TO_ARR_ENTRY(AUDIO, DIV0),926 PLL_IDS_TO_ARR_ENTRY(ETH, DIV0), },927 .pp_mux_table = { 5, 7, 8, 9, 10, },928 .pp_count = 5,929 .pp_chg_id = INT_MIN, },930 931 { .n = "tcpca_gclk",932 .id = 94,933 .r = { .max = 32768, },934 .pp_chg_id = INT_MIN, },935 936 { .n = "tcpcb_gclk",937 .id = 95,938 .r = { .max = 32768, },939 .pp_chg_id = INT_MIN, },940};941 942/* MCK0 characteristics. */943static const struct clk_master_characteristics mck0_characteristics = {944 .output = { .min = 32768, .max = 200000000 },945 .divisors = { 1, 2, 4, 3, 5 },946 .have_div3_pres = 1,947};948 949/* MCK0 layout. */950static const struct clk_master_layout mck0_layout = {951 .mask = 0x773,952 .pres_shift = 4,953 .offset = 0x28,954};955 956/* Programmable clock layout. */957static const struct clk_programmable_layout programmable_layout = {958 .pres_mask = 0xff,959 .pres_shift = 8,960 .css_mask = 0x1f,961 .have_slck_mck = 0,962 .is_pres_direct = 1,963};964 965/* Peripheral clock layout. */966static const struct clk_pcr_layout sama7g5_pcr_layout = {967 .offset = 0x88,968 .cmd = BIT(31),969 .gckcss_mask = GENMASK(12, 8),970 .pid_mask = GENMASK(6, 0),971};972 973static void __init sama7g5_pmc_setup(struct device_node *np)974{975 const char *main_xtal_name = "main_xtal";976 struct pmc_data *sama7g5_pmc;977 void **alloc_mem = NULL;978 int alloc_mem_size = 0;979 struct regmap *regmap;980 struct clk_hw *hw, *main_rc_hw, *main_osc_hw, *main_xtal_hw;981 struct clk_hw *td_slck_hw, *md_slck_hw;982 static struct clk_parent_data parent_data;983 struct clk_hw *parent_hws[10];984 bool bypass;985 int i, j;986 987 td_slck_hw = __clk_get_hw(of_clk_get_by_name(np, "td_slck"));988 md_slck_hw = __clk_get_hw(of_clk_get_by_name(np, "md_slck"));989 main_xtal_hw = __clk_get_hw(of_clk_get_by_name(np, main_xtal_name));990 991 if (!td_slck_hw || !md_slck_hw || !main_xtal_hw)992 return;993 994 regmap = device_node_to_regmap(np);995 if (IS_ERR(regmap))996 return;997 998 sama7g5_pmc = pmc_data_allocate(PMC_MCK1 + 1,999 nck(sama7g5_systemck),1000 nck(sama7g5_periphck),1001 nck(sama7g5_gck), 8);1002 if (!sama7g5_pmc)1003 return;1004 1005 alloc_mem = kmalloc(sizeof(void *) *1006 (ARRAY_SIZE(sama7g5_mckx) + ARRAY_SIZE(sama7g5_gck)),1007 GFP_KERNEL);1008 if (!alloc_mem)1009 goto err_free;1010 1011 main_rc_hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,1012 50000000);1013 if (IS_ERR(main_rc_hw))1014 goto err_free;1015 1016 bypass = of_property_read_bool(np, "atmel,osc-bypass");1017 1018 parent_data.name = main_xtal_name;1019 parent_data.fw_name = main_xtal_name;1020 main_osc_hw = at91_clk_register_main_osc(regmap, "main_osc", NULL,1021 &parent_data, bypass);1022 if (IS_ERR(main_osc_hw))1023 goto err_free;1024 1025 parent_hws[0] = main_rc_hw;1026 parent_hws[1] = main_osc_hw;1027 hw = at91_clk_register_sam9x5_main(regmap, "mainck", NULL, parent_hws, 2);1028 if (IS_ERR(hw))1029 goto err_free;1030 1031 sama7g5_pmc->chws[PMC_MAIN] = hw;1032 1033 for (i = 0; i < PLL_ID_MAX; i++) {1034 for (j = 0; j < PLL_COMPID_MAX; j++) {1035 struct clk_hw *parent_hw;1036 1037 if (!sama7g5_plls[i][j].n)1038 continue;1039 1040 switch (sama7g5_plls[i][j].t) {1041 case PLL_TYPE_FRAC:1042 switch (sama7g5_plls[i][j].p) {1043 case SAMA7G5_PLL_PARENT_MAINCK:1044 parent_hw = sama7g5_pmc->chws[PMC_MAIN];1045 break;1046 case SAMA7G5_PLL_PARENT_MAIN_XTAL:1047 parent_hw = main_xtal_hw;1048 break;1049 default:1050 /* Should not happen. */1051 parent_hw = NULL;1052 break;1053 }1054 1055 hw = sam9x60_clk_register_frac_pll(regmap,1056 &pmc_pll_lock, sama7g5_plls[i][j].n,1057 NULL, parent_hw, i,1058 sama7g5_plls[i][j].c,1059 sama7g5_plls[i][j].l,1060 sama7g5_plls[i][j].f);1061 break;1062 1063 case PLL_TYPE_DIV:1064 hw = sam9x60_clk_register_div_pll(regmap,1065 &pmc_pll_lock, sama7g5_plls[i][j].n,1066 NULL, sama7g5_plls[i][0].hw, i,1067 sama7g5_plls[i][j].c,1068 sama7g5_plls[i][j].l,1069 sama7g5_plls[i][j].f,1070 sama7g5_plls[i][j].safe_div);1071 break;1072 1073 default:1074 continue;1075 }1076 1077 if (IS_ERR(hw))1078 goto err_free;1079 1080 sama7g5_plls[i][j].hw = hw;1081 if (sama7g5_plls[i][j].eid)1082 sama7g5_pmc->chws[sama7g5_plls[i][j].eid] = hw;1083 }1084 }1085 1086 hw = at91_clk_register_master_div(regmap, "mck0", NULL,1087 sama7g5_plls[PLL_ID_CPU][1].hw,1088 &mck0_layout, &mck0_characteristics,1089 &pmc_mck0_lock, CLK_GET_RATE_NOCACHE, 5);1090 if (IS_ERR(hw))1091 goto err_free;1092 1093 sama7g5_mckx[PCK_PARENT_HW_MCK0].hw = sama7g5_pmc->chws[PMC_MCK] = hw;1094 1095 parent_hws[0] = md_slck_hw;1096 parent_hws[1] = td_slck_hw;1097 parent_hws[2] = sama7g5_pmc->chws[PMC_MAIN];1098 for (i = PCK_PARENT_HW_MCK1; i < ARRAY_SIZE(sama7g5_mckx); i++) {1099 u8 num_parents = 3 + sama7g5_mckx[i].ep_count;1100 struct clk_hw *tmp_parent_hws[8];1101 u32 *mux_table;1102 1103 mux_table = kmalloc_array(num_parents, sizeof(*mux_table),1104 GFP_KERNEL);1105 if (!mux_table)1106 goto err_free;1107 1108 PMC_INIT_TABLE(mux_table, 3);1109 PMC_FILL_TABLE(&mux_table[3], sama7g5_mckx[i].ep_mux_table,1110 sama7g5_mckx[i].ep_count);1111 for (j = 0; j < sama7g5_mckx[i].ep_count; j++) {1112 u8 pll_id = sama7g5_mckx[i].ep[j].pll_id;1113 u8 pll_compid = sama7g5_mckx[i].ep[j].pll_compid;1114 1115 tmp_parent_hws[j] = sama7g5_plls[pll_id][pll_compid].hw;1116 }1117 PMC_FILL_TABLE(&parent_hws[3], tmp_parent_hws,1118 sama7g5_mckx[i].ep_count);1119 1120 hw = at91_clk_sama7g5_register_master(regmap, sama7g5_mckx[i].n,1121 num_parents, NULL, parent_hws, mux_table,1122 &pmc_mckX_lock, sama7g5_mckx[i].id,1123 sama7g5_mckx[i].c,1124 sama7g5_mckx[i].ep_chg_id);1125 if (IS_ERR(hw))1126 goto err_free;1127 1128 alloc_mem[alloc_mem_size++] = mux_table;1129 1130 sama7g5_mckx[i].hw = hw;1131 if (sama7g5_mckx[i].eid)1132 sama7g5_pmc->chws[sama7g5_mckx[i].eid] = hw;1133 }1134 1135 hw = at91_clk_sama7g5_register_utmi(regmap, "utmick", NULL, main_xtal_hw);1136 if (IS_ERR(hw))1137 goto err_free;1138 1139 sama7g5_pmc->chws[PMC_UTMI] = hw;1140 1141 parent_hws[0] = md_slck_hw;1142 parent_hws[1] = td_slck_hw;1143 parent_hws[2] = sama7g5_pmc->chws[PMC_MAIN];1144 parent_hws[3] = sama7g5_plls[PLL_ID_SYS][PLL_COMPID_DIV0].hw;1145 parent_hws[4] = sama7g5_plls[PLL_ID_DDR][PLL_COMPID_DIV0].hw;1146 parent_hws[5] = sama7g5_plls[PLL_ID_IMG][PLL_COMPID_DIV0].hw;1147 parent_hws[6] = sama7g5_plls[PLL_ID_BAUD][PLL_COMPID_DIV0].hw;1148 parent_hws[7] = sama7g5_plls[PLL_ID_AUDIO][PLL_COMPID_DIV0].hw;1149 parent_hws[8] = sama7g5_plls[PLL_ID_ETH][PLL_COMPID_DIV0].hw;1150 for (i = 0; i < 8; i++) {1151 char name[6];1152 1153 snprintf(name, sizeof(name), "prog%d", i);1154 1155 hw = at91_clk_register_programmable(regmap, name, NULL, parent_hws,1156 9, i,1157 &programmable_layout,1158 sama7g5_prog_mux_table);1159 if (IS_ERR(hw))1160 goto err_free;1161 1162 sama7g5_pmc->pchws[i] = hw;1163 }1164 1165 for (i = 0; i < ARRAY_SIZE(sama7g5_systemck); i++) {1166 hw = at91_clk_register_system(regmap, sama7g5_systemck[i].n,1167 NULL, sama7g5_pmc->pchws[i],1168 sama7g5_systemck[i].id, 0);1169 if (IS_ERR(hw))1170 goto err_free;1171 1172 sama7g5_pmc->shws[sama7g5_systemck[i].id] = hw;1173 }1174 1175 for (i = 0; i < ARRAY_SIZE(sama7g5_periphck); i++) {1176 hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,1177 &sama7g5_pcr_layout,1178 sama7g5_periphck[i].n,1179 NULL,1180 sama7g5_mckx[sama7g5_periphck[i].p].hw,1181 sama7g5_periphck[i].id,1182 &sama7g5_periphck[i].r,1183 sama7g5_periphck[i].chgp ? 0 :1184 INT_MIN, 0);1185 if (IS_ERR(hw))1186 goto err_free;1187 1188 sama7g5_pmc->phws[sama7g5_periphck[i].id] = hw;1189 }1190 1191 parent_hws[0] = md_slck_hw;1192 parent_hws[1] = td_slck_hw;1193 parent_hws[2] = sama7g5_pmc->chws[PMC_MAIN];1194 for (i = 0; i < ARRAY_SIZE(sama7g5_gck); i++) {1195 u8 num_parents = 3 + sama7g5_gck[i].pp_count;1196 struct clk_hw *tmp_parent_hws[8];1197 u32 *mux_table;1198 1199 mux_table = kmalloc_array(num_parents, sizeof(*mux_table),1200 GFP_KERNEL);1201 if (!mux_table)1202 goto err_free;1203 1204 PMC_INIT_TABLE(mux_table, 3);1205 PMC_FILL_TABLE(&mux_table[3], sama7g5_gck[i].pp_mux_table,1206 sama7g5_gck[i].pp_count);1207 for (j = 0; j < sama7g5_gck[i].pp_count; j++) {1208 u8 pll_id = sama7g5_gck[i].pp[j].pll_id;1209 u8 pll_compid = sama7g5_gck[i].pp[j].pll_compid;1210 1211 tmp_parent_hws[j] = sama7g5_plls[pll_id][pll_compid].hw;1212 }1213 PMC_FILL_TABLE(&parent_hws[3], tmp_parent_hws,1214 sama7g5_gck[i].pp_count);1215 1216 hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,1217 &sama7g5_pcr_layout,1218 sama7g5_gck[i].n, NULL,1219 parent_hws, mux_table,1220 num_parents,1221 sama7g5_gck[i].id,1222 &sama7g5_gck[i].r,1223 sama7g5_gck[i].pp_chg_id);1224 if (IS_ERR(hw))1225 goto err_free;1226 1227 sama7g5_pmc->ghws[sama7g5_gck[i].id] = hw;1228 alloc_mem[alloc_mem_size++] = mux_table;1229 }1230 1231 of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sama7g5_pmc);1232 1233 return;1234 1235err_free:1236 if (alloc_mem) {1237 for (i = 0; i < alloc_mem_size; i++)1238 kfree(alloc_mem[i]);1239 kfree(alloc_mem);1240 }1241 1242 kfree(sama7g5_pmc);1243}1244 1245/* Some clks are used for a clocksource */1246CLK_OF_DECLARE(sama7g5_pmc, "microchip,sama7g5-pmc", sama7g5_pmc_setup);1247