am335x_prcm.c revision 253830
1/*- 2 * Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: head/sys/arm/ti/am335x/am335x_prcm.c 253830 2013-07-31 05:52:03Z rpaulo $"); 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/bus.h> 33#include <sys/kernel.h> 34#include <sys/module.h> 35#include <sys/malloc.h> 36#include <sys/rman.h> 37#include <sys/timeet.h> 38#include <sys/timetc.h> 39#include <sys/watchdog.h> 40#include <machine/bus.h> 41#include <machine/cpu.h> 42#include <machine/frame.h> 43#include <machine/intr.h> 44 45#include <arm/ti/tivar.h> 46#include <arm/ti/ti_scm.h> 47#include <arm/ti/ti_prcm.h> 48 49#include <dev/fdt/fdt_common.h> 50#include <dev/ofw/openfirm.h> 51#include <dev/ofw/ofw_bus.h> 52#include <dev/ofw/ofw_bus_subr.h> 53 54#include <machine/bus.h> 55#include <machine/fdt.h> 56 57#define CM_PER 0 58#define CM_PER_L4LS_CLKSTCTRL (CM_PER + 0x000) 59#define CM_PER_L3S_CLKSTCTRL (CM_PER + 0x004) 60#define CM_PER_L3_CLKSTCTRL (CM_PER + 0x00C) 61#define CM_PER_CPGMAC0_CLKCTRL (CM_PER + 0x014) 62#define CM_PER_LCDC_CLKCTRL (CM_PER + 0x018) 63#define CM_PER_USB0_CLKCTRL (CM_PER + 0x01C) 64#define CM_PER_TPTC0_CLKCTRL (CM_PER + 0x024) 65#define CM_PER_MMC0_CLKCTRL (CM_PER + 0x03C) 66#define CM_PER_I2C2_CLKCTRL (CM_PER + 0x044) 67#define CM_PER_I2C1_CLKCTRL (CM_PER + 0x048) 68#define CM_PER_TIMER7_CLKCTRL (CM_PER + 0x07C) 69#define CM_PER_TIMER2_CLKCTRL (CM_PER + 0x080) 70#define CM_PER_TIMER3_CLKCTRL (CM_PER + 0x084) 71#define CM_PER_TIMER4_CLKCTRL (CM_PER + 0x088) 72#define CM_PER_GPIO1_CLKCTRL (CM_PER + 0x0AC) 73#define CM_PER_GPIO2_CLKCTRL (CM_PER + 0x0B0) 74#define CM_PER_GPIO3_CLKCTRL (CM_PER + 0x0B4) 75#define CM_PER_TPCC_CLKCTRL (CM_PER + 0x0BC) 76#define CM_PER_EPWMSS1_CLKCTRL (CM_PER + 0x0CC) 77#define CM_PER_EPWMSS0_CLKCTRL (CM_PER + 0x0D4) 78#define CM_PER_EPWMSS2_CLKCTRL (CM_PER + 0x0D8) 79#define CM_PER_L3_INSTR_CLKCTRL (CM_PER + 0x0DC) 80#define CM_PER_L3_CLKCTRL (CM_PER + 0x0E0) 81#define CM_PER_PRUSS_CLKCTRL (CM_PER + 0x0E8) 82#define CM_PER_TIMER5_CLKCTRL (CM_PER + 0x0EC) 83#define CM_PER_TIMER6_CLKCTRL (CM_PER + 0x0F0) 84#define CM_PER_MMC1_CLKCTRL (CM_PER + 0x0F4) 85#define CM_PER_MMC2_CLKCTRL (CM_PER + 0x0F8) 86#define CM_PER_TPTC1_CLKCTRL (CM_PER + 0x0FC) 87#define CM_PER_TPTC2_CLKCTRL (CM_PER + 0x100) 88#define CM_PER_SPINLOCK0_CLKCTRL (CM_PER + 0x10C) 89#define CM_PER_MAILBOX0_CLKCTRL (CM_PER + 0x110) 90#define CM_PER_OCPWP_L3_CLKSTCTRL (CM_PER + 0x12C) 91#define CM_PER_OCPWP_CLKCTRL (CM_PER + 0x130) 92#define CM_PER_CPSW_CLKSTCTRL (CM_PER + 0x144) 93#define CM_PER_PRUSS_CLKSTCTRL (CM_PER + 0x140) 94 95#define CM_WKUP 0x400 96#define CM_WKUP_CLKSTCTRL (CM_WKUP + 0x000) 97#define CM_WKUP_CONTROL_CLKCTRL (CM_WKUP + 0x004) 98#define CM_WKUP_GPIO0_CLKCTRL (CM_WKUP + 0x008) 99#define CM_WKUP_CM_L3_AON_CLKSTCTRL (CM_WKUP + 0x01C) 100#define CM_WKUP_CM_CLKSEL_DPLL_MPU (CM_WKUP + 0x02C) 101#define CM_WKUP_CM_IDLEST_DPLL_DISP (CM_WKUP + 0x048) 102#define CM_WKUP_CM_CLKSEL_DPLL_DISP (CM_WKUP + 0x054) 103#define CM_WKUP_CM_CLKDCOLDO_DPLL_PER (CM_WKUP + 0x07C) 104#define CM_WKUP_CM_CLKMODE_DPLL_DISP (CM_WKUP + 0x098) 105#define CM_WKUP_I2C0_CLKCTRL (CM_WKUP + 0x0B8) 106 107#define CM_DPLL 0x500 108#define CLKSEL_TIMER7_CLK (CM_DPLL + 0x004) 109#define CLKSEL_TIMER2_CLK (CM_DPLL + 0x008) 110#define CLKSEL_TIMER3_CLK (CM_DPLL + 0x00C) 111#define CLKSEL_TIMER4_CLK (CM_DPLL + 0x010) 112#define CLKSEL_TIMER5_CLK (CM_DPLL + 0x018) 113#define CLKSEL_TIMER6_CLK (CM_DPLL + 0x01C) 114#define CLKSEL_PRUSS_OCP_CLK (CM_DPLL + 0x030) 115 116#define PRM_PER 0xC00 117#define PRM_PER_RSTCTRL (PRM_PER + 0x00) 118 119#define PRM_DEVICE_OFFSET 0xF00 120#define PRM_RSTCTRL (PRM_DEVICE_OFFSET + 0x00) 121 122struct am335x_prcm_softc { 123 struct resource * res[2]; 124 bus_space_tag_t bst; 125 bus_space_handle_t bsh; 126}; 127 128static struct resource_spec am335x_prcm_spec[] = { 129 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 130 { -1, 0 } 131}; 132 133static struct am335x_prcm_softc *am335x_prcm_sc = NULL; 134 135static int am335x_clk_generic_activate(struct ti_clock_dev *clkdev); 136static int am335x_clk_gpio_activate(struct ti_clock_dev *clkdev); 137static int am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev); 138static int am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc); 139static int am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq); 140static int am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq); 141static int am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq); 142static int am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq); 143static void am335x_prcm_reset(void); 144static int am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev); 145static int am335x_clk_musb0_activate(struct ti_clock_dev *clkdev); 146static int am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev); 147static int am335x_clk_pruss_activate(struct ti_clock_dev *clkdev); 148 149#define AM335X_GENERIC_CLOCK_DEV(i) \ 150 { .id = (i), \ 151 .clk_activate = am335x_clk_generic_activate, \ 152 .clk_deactivate = am335x_clk_generic_deactivate, \ 153 .clk_set_source = am335x_clk_generic_set_source, \ 154 .clk_accessible = NULL, \ 155 .clk_get_source_freq = NULL \ 156 } 157 158#define AM335X_GPIO_CLOCK_DEV(i) \ 159 { .id = (i), \ 160 .clk_activate = am335x_clk_gpio_activate, \ 161 .clk_deactivate = am335x_clk_generic_deactivate, \ 162 .clk_set_source = am335x_clk_generic_set_source, \ 163 .clk_accessible = NULL, \ 164 .clk_get_source_freq = NULL \ 165 } 166 167#define AM335X_MMCHS_CLOCK_DEV(i) \ 168 { .id = (i), \ 169 .clk_activate = am335x_clk_generic_activate, \ 170 .clk_deactivate = am335x_clk_generic_deactivate, \ 171 .clk_set_source = am335x_clk_generic_set_source, \ 172 .clk_accessible = NULL, \ 173 .clk_get_source_freq = am335x_clk_hsmmc_get_source_freq \ 174 } 175 176struct ti_clock_dev ti_clk_devmap[] = { 177 /* System clocks */ 178 { .id = SYS_CLK, 179 .clk_activate = NULL, 180 .clk_deactivate = NULL, 181 .clk_set_source = NULL, 182 .clk_accessible = NULL, 183 .clk_get_source_freq = am335x_clk_get_sysclk_freq, 184 }, 185 /* MPU (ARM) core clocks */ 186 { .id = MPU_CLK, 187 .clk_activate = NULL, 188 .clk_deactivate = NULL, 189 .clk_set_source = NULL, 190 .clk_accessible = NULL, 191 .clk_get_source_freq = am335x_clk_get_arm_fclk_freq, 192 }, 193 /* CPSW Ethernet Switch core clocks */ 194 { .id = CPSW_CLK, 195 .clk_activate = am335x_clk_cpsw_activate, 196 .clk_deactivate = NULL, 197 .clk_set_source = NULL, 198 .clk_accessible = NULL, 199 .clk_get_source_freq = NULL, 200 }, 201 202 /* Mentor USB HS controller core clocks */ 203 { .id = MUSB0_CLK, 204 .clk_activate = am335x_clk_musb0_activate, 205 .clk_deactivate = NULL, 206 .clk_set_source = NULL, 207 .clk_accessible = NULL, 208 .clk_get_source_freq = NULL, 209 }, 210 211 /* LCD controller clocks */ 212 { .id = LCDC_CLK, 213 .clk_activate = am335x_clk_lcdc_activate, 214 .clk_deactivate = NULL, 215 .clk_set_source = NULL, 216 .clk_accessible = NULL, 217 .clk_get_source_freq = am335x_clk_get_arm_disp_freq, 218 }, 219 220 /* DMTimer */ 221 AM335X_GENERIC_CLOCK_DEV(DMTIMER2_CLK), 222 AM335X_GENERIC_CLOCK_DEV(DMTIMER3_CLK), 223 AM335X_GENERIC_CLOCK_DEV(DMTIMER4_CLK), 224 AM335X_GENERIC_CLOCK_DEV(DMTIMER5_CLK), 225 AM335X_GENERIC_CLOCK_DEV(DMTIMER6_CLK), 226 AM335X_GENERIC_CLOCK_DEV(DMTIMER7_CLK), 227 228 /* GPIO */ 229 AM335X_GPIO_CLOCK_DEV(GPIO0_CLK), 230 AM335X_GPIO_CLOCK_DEV(GPIO1_CLK), 231 AM335X_GPIO_CLOCK_DEV(GPIO2_CLK), 232 AM335X_GPIO_CLOCK_DEV(GPIO3_CLK), 233 234 /* I2C */ 235 AM335X_GENERIC_CLOCK_DEV(I2C0_CLK), 236 AM335X_GENERIC_CLOCK_DEV(I2C1_CLK), 237 AM335X_GENERIC_CLOCK_DEV(I2C2_CLK), 238 239 /* EDMA */ 240 AM335X_GENERIC_CLOCK_DEV(EDMA_TPCC_CLK), 241 AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC0_CLK), 242 AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC1_CLK), 243 AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC2_CLK), 244 245 /* MMCHS */ 246 AM335X_MMCHS_CLOCK_DEV(MMC0_CLK), 247 AM335X_MMCHS_CLOCK_DEV(MMC1_CLK), 248 AM335X_MMCHS_CLOCK_DEV(MMC2_CLK), 249 250 /* PWMSS */ 251 AM335X_GENERIC_CLOCK_DEV(PWMSS0_CLK), 252 AM335X_GENERIC_CLOCK_DEV(PWMSS1_CLK), 253 AM335X_GENERIC_CLOCK_DEV(PWMSS2_CLK), 254 255 /* System Mailbox clock */ 256 AM335X_GENERIC_CLOCK_DEV(MAILBOX0_CLK), 257 258 /* SPINLOCK */ 259 AM335X_GENERIC_CLOCK_DEV(SPINLOCK0_CLK), 260 261 /* PRU-ICSS */ 262 { .id = PRUSS_CLK, 263 .clk_activate = am335x_clk_pruss_activate, 264 .clk_deactivate = NULL, 265 .clk_set_source = NULL, 266 .clk_accessible = NULL, 267 .clk_get_source_freq = NULL, 268 }, 269 270 271 272 { INVALID_CLK_IDENT, NULL, NULL, NULL, NULL } 273}; 274 275struct am335x_clk_details { 276 clk_ident_t id; 277 uint32_t clkctrl_reg; 278 uint32_t clksel_reg; 279}; 280 281#define _CLK_DETAIL(i, c, s) \ 282 { .id = (i), \ 283 .clkctrl_reg = (c), \ 284 .clksel_reg = (s), \ 285 } 286 287static struct am335x_clk_details g_am335x_clk_details[] = { 288 289 /* DMTimer modules */ 290 _CLK_DETAIL(DMTIMER2_CLK, CM_PER_TIMER2_CLKCTRL, CLKSEL_TIMER2_CLK), 291 _CLK_DETAIL(DMTIMER3_CLK, CM_PER_TIMER3_CLKCTRL, CLKSEL_TIMER3_CLK), 292 _CLK_DETAIL(DMTIMER4_CLK, CM_PER_TIMER4_CLKCTRL, CLKSEL_TIMER4_CLK), 293 _CLK_DETAIL(DMTIMER5_CLK, CM_PER_TIMER5_CLKCTRL, CLKSEL_TIMER5_CLK), 294 _CLK_DETAIL(DMTIMER6_CLK, CM_PER_TIMER6_CLKCTRL, CLKSEL_TIMER6_CLK), 295 _CLK_DETAIL(DMTIMER7_CLK, CM_PER_TIMER7_CLKCTRL, CLKSEL_TIMER7_CLK), 296 297 /* GPIO modules */ 298 _CLK_DETAIL(GPIO0_CLK, CM_WKUP_GPIO0_CLKCTRL, 0), 299 _CLK_DETAIL(GPIO1_CLK, CM_PER_GPIO1_CLKCTRL, 0), 300 _CLK_DETAIL(GPIO2_CLK, CM_PER_GPIO2_CLKCTRL, 0), 301 _CLK_DETAIL(GPIO3_CLK, CM_PER_GPIO3_CLKCTRL, 0), 302 303 /* I2C modules */ 304 _CLK_DETAIL(I2C0_CLK, CM_WKUP_I2C0_CLKCTRL, 0), 305 _CLK_DETAIL(I2C1_CLK, CM_PER_I2C1_CLKCTRL, 0), 306 _CLK_DETAIL(I2C2_CLK, CM_PER_I2C2_CLKCTRL, 0), 307 308 /* EDMA modules */ 309 _CLK_DETAIL(EDMA_TPCC_CLK, CM_PER_TPCC_CLKCTRL, 0), 310 _CLK_DETAIL(EDMA_TPTC0_CLK, CM_PER_TPTC0_CLKCTRL, 0), 311 _CLK_DETAIL(EDMA_TPTC1_CLK, CM_PER_TPTC1_CLKCTRL, 0), 312 _CLK_DETAIL(EDMA_TPTC2_CLK, CM_PER_TPTC2_CLKCTRL, 0), 313 314 /* MMCHS modules*/ 315 _CLK_DETAIL(MMC0_CLK, CM_PER_MMC0_CLKCTRL, 0), 316 _CLK_DETAIL(MMC1_CLK, CM_PER_MMC1_CLKCTRL, 0), 317 _CLK_DETAIL(MMC2_CLK, CM_PER_MMC1_CLKCTRL, 0), 318 319 /* PWMSS modules */ 320 _CLK_DETAIL(PWMSS0_CLK, CM_PER_EPWMSS0_CLKCTRL, 0), 321 _CLK_DETAIL(PWMSS1_CLK, CM_PER_EPWMSS1_CLKCTRL, 0), 322 _CLK_DETAIL(PWMSS2_CLK, CM_PER_EPWMSS2_CLKCTRL, 0), 323 324 _CLK_DETAIL(MAILBOX0_CLK, CM_PER_MAILBOX0_CLKCTRL, 0), 325 _CLK_DETAIL(SPINLOCK0_CLK, CM_PER_SPINLOCK0_CLKCTRL, 0), 326 327 { INVALID_CLK_IDENT, 0}, 328}; 329 330/* Read/Write macros */ 331#define prcm_read_4(reg) \ 332 bus_space_read_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg) 333#define prcm_write_4(reg, val) \ 334 bus_space_write_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg, val) 335 336void am335x_prcm_setup_dmtimer(int); 337 338static int 339am335x_prcm_probe(device_t dev) 340{ 341 if (ofw_bus_is_compatible(dev, "am335x,prcm")) { 342 device_set_desc(dev, "AM335x Power and Clock Management"); 343 return(BUS_PROBE_DEFAULT); 344 } 345 346 return (ENXIO); 347} 348 349static int 350am335x_prcm_attach(device_t dev) 351{ 352 struct am335x_prcm_softc *sc = device_get_softc(dev); 353 unsigned int sysclk, fclk; 354 355 if (am335x_prcm_sc) 356 return (ENXIO); 357 358 if (bus_alloc_resources(dev, am335x_prcm_spec, sc->res)) { 359 device_printf(dev, "could not allocate resources\n"); 360 return (ENXIO); 361 } 362 363 sc->bst = rman_get_bustag(sc->res[0]); 364 sc->bsh = rman_get_bushandle(sc->res[0]); 365 366 am335x_prcm_sc = sc; 367 ti_cpu_reset = am335x_prcm_reset; 368 369 am335x_clk_get_sysclk_freq(NULL, &sysclk); 370 am335x_clk_get_arm_fclk_freq(NULL, &fclk); 371 device_printf(dev, "Clocks: System %u.%01u MHz, CPU %u MHz\n", 372 sysclk/1000000, (sysclk % 1000000)/100000, fclk/1000000); 373 374 return (0); 375} 376 377static device_method_t am335x_prcm_methods[] = { 378 DEVMETHOD(device_probe, am335x_prcm_probe), 379 DEVMETHOD(device_attach, am335x_prcm_attach), 380 { 0, 0 } 381}; 382 383static driver_t am335x_prcm_driver = { 384 "am335x_prcm", 385 am335x_prcm_methods, 386 sizeof(struct am335x_prcm_softc), 387}; 388 389static devclass_t am335x_prcm_devclass; 390 391DRIVER_MODULE(am335x_prcm, simplebus, am335x_prcm_driver, 392 am335x_prcm_devclass, 0, 0); 393MODULE_DEPEND(am335x_prcm, ti_scm, 1, 1, 1); 394 395static struct am335x_clk_details* 396am335x_clk_details(clk_ident_t id) 397{ 398 struct am335x_clk_details *walker; 399 400 for (walker = g_am335x_clk_details; walker->id != INVALID_CLK_IDENT; walker++) { 401 if (id == walker->id) 402 return (walker); 403 } 404 405 return NULL; 406} 407 408static int 409am335x_clk_generic_activate(struct ti_clock_dev *clkdev) 410{ 411 struct am335x_prcm_softc *sc = am335x_prcm_sc; 412 struct am335x_clk_details* clk_details; 413 414 if (sc == NULL) 415 return ENXIO; 416 417 clk_details = am335x_clk_details(clkdev->id); 418 419 if (clk_details == NULL) 420 return (ENXIO); 421 422 /* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */ 423 prcm_write_4(clk_details->clkctrl_reg, 2); 424 while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 2) 425 DELAY(10); 426 427 return (0); 428} 429 430static int 431am335x_clk_gpio_activate(struct ti_clock_dev *clkdev) 432{ 433 struct am335x_prcm_softc *sc = am335x_prcm_sc; 434 struct am335x_clk_details* clk_details; 435 436 if (sc == NULL) 437 return ENXIO; 438 439 clk_details = am335x_clk_details(clkdev->id); 440 441 if (clk_details == NULL) 442 return (ENXIO); 443 444 /* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */ 445 /* set *_CLKCTRL register OPTFCLKEN_GPIO_1_G DBCLK[18] to FCLK_EN(1) */ 446 prcm_write_4(clk_details->clkctrl_reg, 2 | (1 << 18)); 447 while ((prcm_read_4(clk_details->clkctrl_reg) & 448 (3 | (1 << 18) )) != (2 | (1 << 18))) 449 DELAY(10); 450 451 return (0); 452} 453 454static int 455am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev) 456{ 457 struct am335x_prcm_softc *sc = am335x_prcm_sc; 458 struct am335x_clk_details* clk_details; 459 460 if (sc == NULL) 461 return ENXIO; 462 463 clk_details = am335x_clk_details(clkdev->id); 464 465 if (clk_details == NULL) 466 return (ENXIO); 467 468 /* set *_CLKCTRL register MODULEMODE[1:0] to disable(0) */ 469 prcm_write_4(clk_details->clkctrl_reg, 0); 470 while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 0) 471 DELAY(10); 472 473 return (0); 474} 475 476static int 477am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc) 478{ 479 struct am335x_prcm_softc *sc = am335x_prcm_sc; 480 struct am335x_clk_details* clk_details; 481 uint32_t reg; 482 483 if (sc == NULL) 484 return ENXIO; 485 486 clk_details = am335x_clk_details(clkdev->id); 487 488 if (clk_details == NULL) 489 return (ENXIO); 490 491 switch (clksrc) { 492 case EXT_CLK: 493 reg = 0; /* SEL2: TCLKIN clock */ 494 break; 495 case SYSCLK_CLK: 496 reg = 1; /* SEL1: CLK_M_OSC clock */ 497 break; 498 case F32KHZ_CLK: 499 reg = 2; /* SEL3: CLK_32KHZ clock */ 500 break; 501 default: 502 return (ENXIO); 503 } 504 505 prcm_write_4(clk_details->clksel_reg, reg); 506 while ((prcm_read_4(clk_details->clksel_reg) & 0x3) != reg) 507 DELAY(10); 508 509 return (0); 510} 511 512static int 513am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq) 514{ 515 *freq = 96000000; 516 return (0); 517} 518 519static int 520am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq) 521{ 522 uint32_t ctrl_status; 523 524 /* Read the input clock freq from the control module */ 525 /* control_status reg (0x40) */ 526 if (ti_scm_reg_read_4(0x40, &ctrl_status)) 527 return ENXIO; 528 529 switch ((ctrl_status>>22) & 0x3) { 530 case 0x0: 531 /* 19.2Mhz */ 532 *freq = 19200000; 533 break; 534 case 0x1: 535 /* 24Mhz */ 536 *freq = 24000000; 537 break; 538 case 0x2: 539 /* 25Mhz */ 540 *freq = 25000000; 541 break; 542 case 0x3: 543 /* 26Mhz */ 544 *freq = 26000000; 545 break; 546 } 547 548 return (0); 549} 550 551#define DPLL_BYP_CLKSEL(reg) ((reg>>23) & 1) 552#define DPLL_DIV(reg) ((reg & 0x7f)+1) 553#define DPLL_MULT(reg) ((reg>>8) & 0x7FF) 554 555static int 556am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq) 557{ 558 uint32_t reg; 559 uint32_t sysclk; 560 561 reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_MPU); 562 563 /*Check if we are running in bypass */ 564 if (DPLL_BYP_CLKSEL(reg)) 565 return ENXIO; 566 567 am335x_clk_get_sysclk_freq(NULL, &sysclk); 568 *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg)); 569 return(0); 570} 571 572static int 573am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq) 574{ 575 uint32_t reg; 576 uint32_t sysclk; 577 578 reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_DISP); 579 580 /*Check if we are running in bypass */ 581 if (DPLL_BYP_CLKSEL(reg)) 582 return ENXIO; 583 584 am335x_clk_get_sysclk_freq(NULL, &sysclk); 585 *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg)); 586 return(0); 587} 588 589static void 590am335x_prcm_reset(void) 591{ 592 prcm_write_4(PRM_RSTCTRL, (1<<1)); 593} 594 595static int 596am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev) 597{ 598 struct am335x_prcm_softc *sc = am335x_prcm_sc; 599 600 if (sc == NULL) 601 return ENXIO; 602 603 /* set MODULENAME to ENABLE */ 604 prcm_write_4(CM_PER_CPGMAC0_CLKCTRL, 2); 605 606 /* wait for IDLEST to become Func(0) */ 607 while(prcm_read_4(CM_PER_CPGMAC0_CLKCTRL) & (3<<16)); 608 609 /*set CLKTRCTRL to SW_WKUP(2) */ 610 prcm_write_4(CM_PER_CPSW_CLKSTCTRL, 2); 611 612 /* wait for 125 MHz OCP clock to become active */ 613 while((prcm_read_4(CM_PER_CPSW_CLKSTCTRL) & (1<<4)) == 0); 614 return(0); 615} 616 617static int 618am335x_clk_musb0_activate(struct ti_clock_dev *clkdev) 619{ 620 struct am335x_prcm_softc *sc = am335x_prcm_sc; 621 622 if (sc == NULL) 623 return ENXIO; 624 625 /* set ST_DPLL_CLKDCOLDO(9) to CLK_GATED(1) */ 626 /* set DPLL_CLKDCOLDO_GATE_CTRL(8) to CLK_ENABLE(1)*/ 627 prcm_write_4(CM_WKUP_CM_CLKDCOLDO_DPLL_PER, 0x300); 628 629 /*set MODULEMODE to ENABLE(2) */ 630 prcm_write_4(CM_PER_USB0_CLKCTRL, 2); 631 632 /* wait for MODULEMODE to become ENABLE(2) */ 633 while ((prcm_read_4(CM_PER_USB0_CLKCTRL) & 0x3) != 2) 634 DELAY(10); 635 636 /* wait for IDLEST to become Func(0) */ 637 while(prcm_read_4(CM_PER_USB0_CLKCTRL) & (3<<16)) 638 DELAY(10); 639 640 return(0); 641} 642 643static int 644am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev) 645{ 646 struct am335x_prcm_softc *sc = am335x_prcm_sc; 647 648 if (sc == NULL) 649 return (ENXIO); 650 651 /* Bypass mode */ 652 prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x4); 653 654 /* Make sure it's in bypass mode */ 655 while (!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP) 656 & (1 << 8))) 657 DELAY(10); 658 659 /* 660 * For now set frequency to 5xSYSFREQ 661 * More flexible control might be required 662 */ 663 prcm_write_4(CM_WKUP_CM_CLKSEL_DPLL_DISP, (5 << 8) | 0); 664 665 /* Locked mode */ 666 prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7); 667 668 int timeout = 10000; 669 while ((!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP) 670 & (1 << 0))) && timeout--) 671 DELAY(10); 672 673 /*set MODULEMODE to ENABLE(2) */ 674 prcm_write_4(CM_PER_LCDC_CLKCTRL, 2); 675 676 /* wait for MODULEMODE to become ENABLE(2) */ 677 while ((prcm_read_4(CM_PER_LCDC_CLKCTRL) & 0x3) != 2) 678 DELAY(10); 679 680 /* wait for IDLEST to become Func(0) */ 681 while(prcm_read_4(CM_PER_LCDC_CLKCTRL) & (3<<16)) 682 DELAY(10); 683 684 return (0); 685} 686 687static int 688am335x_clk_pruss_activate(struct ti_clock_dev *clkdev) 689{ 690 struct am335x_prcm_softc *sc = am335x_prcm_sc; 691 692 if (sc == NULL) 693 return (ENXIO); 694 695 /* Set MODULEMODE to ENABLE(2) */ 696 prcm_write_4(CM_PER_PRUSS_CLKCTRL, 2); 697 698 /* Wait for MODULEMODE to become ENABLE(2) */ 699 while ((prcm_read_4(CM_PER_PRUSS_CLKCTRL) & 0x3) != 2) 700 DELAY(10); 701 702 /* Set CLKTRCTRL to SW_WKUP(2) */ 703 prcm_write_4(CM_PER_PRUSS_CLKSTCTRL, 2); 704 705 /* Wait for the 200 MHz OCP clock to become active */ 706 while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<4)) == 0) 707 DELAY(10); 708 709 /* Wait for the 200 MHz IEP clock to become active */ 710 while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<5)) == 0) 711 DELAY(10); 712 713 /* Wait for the 192 MHz UART clock to become active */ 714 while ((prcm_read_4(CM_PER_PRUSS_CLKSTCTRL) & (1<<6)) == 0) 715 DELAY(10); 716 717 /* Select DISP DPLL as OCP clock */ 718 prcm_write_4(CLKSEL_PRUSS_OCP_CLK, 1); 719 while ((prcm_read_4(CLKSEL_PRUSS_OCP_CLK) & 0x3) != 1) 720 DELAY(10); 721 722 /* Clear the RESET bit */ 723 prcm_write_4(PRM_PER_RSTCTRL, prcm_read_4(PRM_PER_RSTCTRL) & ~2); 724 725 return (0); 726} 727