sckc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. /*
  2. * drivers/clk/at91/sckc.c
  3. *
  4. * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. */
  12. #include <linux/clk-provider.h>
  13. #include <linux/clkdev.h>
  14. #include <linux/delay.h>
  15. #include <linux/of.h>
  16. #include <linux/of_address.h>
  17. #include <linux/io.h>
  18. #define SLOW_CLOCK_FREQ 32768
  19. #define SLOWCK_SW_CYCLES 5
  20. #define SLOWCK_SW_TIME_USEC ((SLOWCK_SW_CYCLES * USEC_PER_SEC) / \
  21. SLOW_CLOCK_FREQ)
  22. #define AT91_SCKC_CR 0x00
  23. #define AT91_SCKC_RCEN (1 << 0)
  24. #define AT91_SCKC_OSC32EN (1 << 1)
  25. #define AT91_SCKC_OSC32BYP (1 << 2)
  26. #define AT91_SCKC_OSCSEL (1 << 3)
  27. struct clk_slow_osc {
  28. struct clk_hw hw;
  29. void __iomem *sckcr;
  30. unsigned long startup_usec;
  31. };
  32. #define to_clk_slow_osc(hw) container_of(hw, struct clk_slow_osc, hw)
  33. struct clk_sama5d4_slow_osc {
  34. struct clk_hw hw;
  35. void __iomem *sckcr;
  36. unsigned long startup_usec;
  37. bool prepared;
  38. };
  39. #define to_clk_sama5d4_slow_osc(hw) container_of(hw, struct clk_sama5d4_slow_osc, hw)
  40. struct clk_slow_rc_osc {
  41. struct clk_hw hw;
  42. void __iomem *sckcr;
  43. unsigned long frequency;
  44. unsigned long accuracy;
  45. unsigned long startup_usec;
  46. };
  47. #define to_clk_slow_rc_osc(hw) container_of(hw, struct clk_slow_rc_osc, hw)
  48. struct clk_sam9x5_slow {
  49. struct clk_hw hw;
  50. void __iomem *sckcr;
  51. u8 parent;
  52. };
  53. #define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw)
  54. static int clk_slow_osc_prepare(struct clk_hw *hw)
  55. {
  56. struct clk_slow_osc *osc = to_clk_slow_osc(hw);
  57. void __iomem *sckcr = osc->sckcr;
  58. u32 tmp = readl(sckcr);
  59. if (tmp & (AT91_SCKC_OSC32BYP | AT91_SCKC_OSC32EN))
  60. return 0;
  61. writel(tmp | AT91_SCKC_OSC32EN, sckcr);
  62. if (system_state < SYSTEM_RUNNING)
  63. udelay(osc->startup_usec);
  64. else
  65. usleep_range(osc->startup_usec, osc->startup_usec + 1);
  66. return 0;
  67. }
  68. static void clk_slow_osc_unprepare(struct clk_hw *hw)
  69. {
  70. struct clk_slow_osc *osc = to_clk_slow_osc(hw);
  71. void __iomem *sckcr = osc->sckcr;
  72. u32 tmp = readl(sckcr);
  73. if (tmp & AT91_SCKC_OSC32BYP)
  74. return;
  75. writel(tmp & ~AT91_SCKC_OSC32EN, sckcr);
  76. }
  77. static int clk_slow_osc_is_prepared(struct clk_hw *hw)
  78. {
  79. struct clk_slow_osc *osc = to_clk_slow_osc(hw);
  80. void __iomem *sckcr = osc->sckcr;
  81. u32 tmp = readl(sckcr);
  82. if (tmp & AT91_SCKC_OSC32BYP)
  83. return 1;
  84. return !!(tmp & AT91_SCKC_OSC32EN);
  85. }
  86. static const struct clk_ops slow_osc_ops = {
  87. .prepare = clk_slow_osc_prepare,
  88. .unprepare = clk_slow_osc_unprepare,
  89. .is_prepared = clk_slow_osc_is_prepared,
  90. };
  91. static struct clk_hw * __init
  92. at91_clk_register_slow_osc(void __iomem *sckcr,
  93. const char *name,
  94. const char *parent_name,
  95. unsigned long startup,
  96. bool bypass)
  97. {
  98. struct clk_slow_osc *osc;
  99. struct clk_hw *hw;
  100. struct clk_init_data init;
  101. int ret;
  102. if (!sckcr || !name || !parent_name)
  103. return ERR_PTR(-EINVAL);
  104. osc = kzalloc(sizeof(*osc), GFP_KERNEL);
  105. if (!osc)
  106. return ERR_PTR(-ENOMEM);
  107. init.name = name;
  108. init.ops = &slow_osc_ops;
  109. init.parent_names = &parent_name;
  110. init.num_parents = 1;
  111. init.flags = CLK_IGNORE_UNUSED;
  112. osc->hw.init = &init;
  113. osc->sckcr = sckcr;
  114. osc->startup_usec = startup;
  115. if (bypass)
  116. writel((readl(sckcr) & ~AT91_SCKC_OSC32EN) | AT91_SCKC_OSC32BYP,
  117. sckcr);
  118. hw = &osc->hw;
  119. ret = clk_hw_register(NULL, &osc->hw);
  120. if (ret) {
  121. kfree(osc);
  122. hw = ERR_PTR(ret);
  123. }
  124. return hw;
  125. }
  126. static void __init
  127. of_at91sam9x5_clk_slow_osc_setup(struct device_node *np, void __iomem *sckcr)
  128. {
  129. struct clk_hw *hw;
  130. const char *parent_name;
  131. const char *name = np->name;
  132. u32 startup;
  133. bool bypass;
  134. parent_name = of_clk_get_parent_name(np, 0);
  135. of_property_read_string(np, "clock-output-names", &name);
  136. of_property_read_u32(np, "atmel,startup-time-usec", &startup);
  137. bypass = of_property_read_bool(np, "atmel,osc-bypass");
  138. hw = at91_clk_register_slow_osc(sckcr, name, parent_name, startup,
  139. bypass);
  140. if (IS_ERR(hw))
  141. return;
  142. of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
  143. }
  144. static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw,
  145. unsigned long parent_rate)
  146. {
  147. struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
  148. return osc->frequency;
  149. }
  150. static unsigned long clk_slow_rc_osc_recalc_accuracy(struct clk_hw *hw,
  151. unsigned long parent_acc)
  152. {
  153. struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
  154. return osc->accuracy;
  155. }
  156. static int clk_slow_rc_osc_prepare(struct clk_hw *hw)
  157. {
  158. struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
  159. void __iomem *sckcr = osc->sckcr;
  160. writel(readl(sckcr) | AT91_SCKC_RCEN, sckcr);
  161. if (system_state < SYSTEM_RUNNING)
  162. udelay(osc->startup_usec);
  163. else
  164. usleep_range(osc->startup_usec, osc->startup_usec + 1);
  165. return 0;
  166. }
  167. static void clk_slow_rc_osc_unprepare(struct clk_hw *hw)
  168. {
  169. struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
  170. void __iomem *sckcr = osc->sckcr;
  171. writel(readl(sckcr) & ~AT91_SCKC_RCEN, sckcr);
  172. }
  173. static int clk_slow_rc_osc_is_prepared(struct clk_hw *hw)
  174. {
  175. struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
  176. return !!(readl(osc->sckcr) & AT91_SCKC_RCEN);
  177. }
  178. static const struct clk_ops slow_rc_osc_ops = {
  179. .prepare = clk_slow_rc_osc_prepare,
  180. .unprepare = clk_slow_rc_osc_unprepare,
  181. .is_prepared = clk_slow_rc_osc_is_prepared,
  182. .recalc_rate = clk_slow_rc_osc_recalc_rate,
  183. .recalc_accuracy = clk_slow_rc_osc_recalc_accuracy,
  184. };
  185. static struct clk_hw * __init
  186. at91_clk_register_slow_rc_osc(void __iomem *sckcr,
  187. const char *name,
  188. unsigned long frequency,
  189. unsigned long accuracy,
  190. unsigned long startup)
  191. {
  192. struct clk_slow_rc_osc *osc;
  193. struct clk_hw *hw;
  194. struct clk_init_data init;
  195. int ret;
  196. if (!sckcr || !name)
  197. return ERR_PTR(-EINVAL);
  198. osc = kzalloc(sizeof(*osc), GFP_KERNEL);
  199. if (!osc)
  200. return ERR_PTR(-ENOMEM);
  201. init.name = name;
  202. init.ops = &slow_rc_osc_ops;
  203. init.parent_names = NULL;
  204. init.num_parents = 0;
  205. init.flags = CLK_IGNORE_UNUSED;
  206. osc->hw.init = &init;
  207. osc->sckcr = sckcr;
  208. osc->frequency = frequency;
  209. osc->accuracy = accuracy;
  210. osc->startup_usec = startup;
  211. hw = &osc->hw;
  212. ret = clk_hw_register(NULL, &osc->hw);
  213. if (ret) {
  214. kfree(osc);
  215. hw = ERR_PTR(ret);
  216. }
  217. return hw;
  218. }
  219. static void __init
  220. of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np, void __iomem *sckcr)
  221. {
  222. struct clk_hw *hw;
  223. u32 frequency = 0;
  224. u32 accuracy = 0;
  225. u32 startup = 0;
  226. const char *name = np->name;
  227. of_property_read_string(np, "clock-output-names", &name);
  228. of_property_read_u32(np, "clock-frequency", &frequency);
  229. of_property_read_u32(np, "clock-accuracy", &accuracy);
  230. of_property_read_u32(np, "atmel,startup-time-usec", &startup);
  231. hw = at91_clk_register_slow_rc_osc(sckcr, name, frequency, accuracy,
  232. startup);
  233. if (IS_ERR(hw))
  234. return;
  235. of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
  236. }
  237. static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index)
  238. {
  239. struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
  240. void __iomem *sckcr = slowck->sckcr;
  241. u32 tmp;
  242. if (index > 1)
  243. return -EINVAL;
  244. tmp = readl(sckcr);
  245. if ((!index && !(tmp & AT91_SCKC_OSCSEL)) ||
  246. (index && (tmp & AT91_SCKC_OSCSEL)))
  247. return 0;
  248. if (index)
  249. tmp |= AT91_SCKC_OSCSEL;
  250. else
  251. tmp &= ~AT91_SCKC_OSCSEL;
  252. writel(tmp, sckcr);
  253. if (system_state < SYSTEM_RUNNING)
  254. udelay(SLOWCK_SW_TIME_USEC);
  255. else
  256. usleep_range(SLOWCK_SW_TIME_USEC, SLOWCK_SW_TIME_USEC + 1);
  257. return 0;
  258. }
  259. static u8 clk_sam9x5_slow_get_parent(struct clk_hw *hw)
  260. {
  261. struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
  262. return !!(readl(slowck->sckcr) & AT91_SCKC_OSCSEL);
  263. }
  264. static const struct clk_ops sam9x5_slow_ops = {
  265. .set_parent = clk_sam9x5_slow_set_parent,
  266. .get_parent = clk_sam9x5_slow_get_parent,
  267. };
  268. static struct clk_hw * __init
  269. at91_clk_register_sam9x5_slow(void __iomem *sckcr,
  270. const char *name,
  271. const char **parent_names,
  272. int num_parents)
  273. {
  274. struct clk_sam9x5_slow *slowck;
  275. struct clk_hw *hw;
  276. struct clk_init_data init;
  277. int ret;
  278. if (!sckcr || !name || !parent_names || !num_parents)
  279. return ERR_PTR(-EINVAL);
  280. slowck = kzalloc(sizeof(*slowck), GFP_KERNEL);
  281. if (!slowck)
  282. return ERR_PTR(-ENOMEM);
  283. init.name = name;
  284. init.ops = &sam9x5_slow_ops;
  285. init.parent_names = parent_names;
  286. init.num_parents = num_parents;
  287. init.flags = 0;
  288. slowck->hw.init = &init;
  289. slowck->sckcr = sckcr;
  290. slowck->parent = !!(readl(sckcr) & AT91_SCKC_OSCSEL);
  291. hw = &slowck->hw;
  292. ret = clk_hw_register(NULL, &slowck->hw);
  293. if (ret) {
  294. kfree(slowck);
  295. hw = ERR_PTR(ret);
  296. }
  297. return hw;
  298. }
  299. static void __init
  300. of_at91sam9x5_clk_slow_setup(struct device_node *np, void __iomem *sckcr)
  301. {
  302. struct clk_hw *hw;
  303. const char *parent_names[2];
  304. unsigned int num_parents;
  305. const char *name = np->name;
  306. num_parents = of_clk_get_parent_count(np);
  307. if (num_parents == 0 || num_parents > 2)
  308. return;
  309. of_clk_parent_fill(np, parent_names, num_parents);
  310. of_property_read_string(np, "clock-output-names", &name);
  311. hw = at91_clk_register_sam9x5_slow(sckcr, name, parent_names,
  312. num_parents);
  313. if (IS_ERR(hw))
  314. return;
  315. of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
  316. }
  317. static const struct of_device_id sckc_clk_ids[] __initconst = {
  318. /* Slow clock */
  319. {
  320. .compatible = "atmel,at91sam9x5-clk-slow-osc",
  321. .data = of_at91sam9x5_clk_slow_osc_setup,
  322. },
  323. {
  324. .compatible = "atmel,at91sam9x5-clk-slow-rc-osc",
  325. .data = of_at91sam9x5_clk_slow_rc_osc_setup,
  326. },
  327. {
  328. .compatible = "atmel,at91sam9x5-clk-slow",
  329. .data = of_at91sam9x5_clk_slow_setup,
  330. },
  331. { /*sentinel*/ }
  332. };
  333. static void __init of_at91sam9x5_sckc_setup(struct device_node *np)
  334. {
  335. struct device_node *childnp;
  336. void (*clk_setup)(struct device_node *, void __iomem *);
  337. const struct of_device_id *clk_id;
  338. void __iomem *regbase = of_iomap(np, 0);
  339. if (!regbase)
  340. return;
  341. for_each_child_of_node(np, childnp) {
  342. clk_id = of_match_node(sckc_clk_ids, childnp);
  343. if (!clk_id)
  344. continue;
  345. clk_setup = clk_id->data;
  346. clk_setup(childnp, regbase);
  347. }
  348. }
  349. CLK_OF_DECLARE(at91sam9x5_clk_sckc, "atmel,at91sam9x5-sckc",
  350. of_at91sam9x5_sckc_setup);
  351. static int clk_sama5d4_slow_osc_prepare(struct clk_hw *hw)
  352. {
  353. struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(hw);
  354. if (osc->prepared)
  355. return 0;
  356. /*
  357. * Assume that if it has already been selected (for example by the
  358. * bootloader), enough time has aready passed.
  359. */
  360. if ((readl(osc->sckcr) & AT91_SCKC_OSCSEL)) {
  361. osc->prepared = true;
  362. return 0;
  363. }
  364. if (system_state < SYSTEM_RUNNING)
  365. udelay(osc->startup_usec);
  366. else
  367. usleep_range(osc->startup_usec, osc->startup_usec + 1);
  368. osc->prepared = true;
  369. return 0;
  370. }
  371. static int clk_sama5d4_slow_osc_is_prepared(struct clk_hw *hw)
  372. {
  373. struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(hw);
  374. return osc->prepared;
  375. }
  376. static const struct clk_ops sama5d4_slow_osc_ops = {
  377. .prepare = clk_sama5d4_slow_osc_prepare,
  378. .is_prepared = clk_sama5d4_slow_osc_is_prepared,
  379. };
  380. static void __init of_sama5d4_sckc_setup(struct device_node *np)
  381. {
  382. void __iomem *regbase = of_iomap(np, 0);
  383. struct clk_hw *hw;
  384. struct clk_sama5d4_slow_osc *osc;
  385. struct clk_init_data init;
  386. const char *xtal_name;
  387. const char *parent_names[2] = { "slow_rc_osc", "slow_osc" };
  388. bool bypass;
  389. int ret;
  390. if (!regbase)
  391. return;
  392. hw = clk_hw_register_fixed_rate_with_accuracy(NULL, parent_names[0],
  393. NULL, 0, 32768,
  394. 250000000);
  395. if (IS_ERR(hw))
  396. return;
  397. xtal_name = of_clk_get_parent_name(np, 0);
  398. bypass = of_property_read_bool(np, "atmel,osc-bypass");
  399. osc = kzalloc(sizeof(*osc), GFP_KERNEL);
  400. if (!osc)
  401. return;
  402. init.name = parent_names[1];
  403. init.ops = &sama5d4_slow_osc_ops;
  404. init.parent_names = &xtal_name;
  405. init.num_parents = 1;
  406. init.flags = CLK_IGNORE_UNUSED;
  407. osc->hw.init = &init;
  408. osc->sckcr = regbase;
  409. osc->startup_usec = 1200000;
  410. if (bypass)
  411. writel((readl(regbase) | AT91_SCKC_OSC32BYP), regbase);
  412. hw = &osc->hw;
  413. ret = clk_hw_register(NULL, &osc->hw);
  414. if (ret) {
  415. kfree(osc);
  416. return;
  417. }
  418. hw = at91_clk_register_sam9x5_slow(regbase, "slowck", parent_names, 2);
  419. if (IS_ERR(hw))
  420. return;
  421. of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
  422. }
  423. CLK_OF_DECLARE(sama5d4_clk_sckc, "atmel,sama5d4-sckc",
  424. of_sama5d4_sckc_setup);