sama7g5.c 35 KB

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