am335x_prcm.c revision 251015
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 251015 2013-05-27 00:06:24Z gonzo $"); 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_TIMER5_CLKCTRL (CM_PER + 0x0EC) 82#define CM_PER_TIMER6_CLKCTRL (CM_PER + 0x0F0) 83#define CM_PER_MMC1_CLKCTRL (CM_PER + 0x0F4) 84#define CM_PER_MMC2_CLKCTRL (CM_PER + 0x0F8) 85#define CM_PER_TPTC1_CLKCTRL (CM_PER + 0x0FC) 86#define CM_PER_TPTC2_CLKCTRL (CM_PER + 0x100) 87#define CM_PER_OCPWP_L3_CLKSTCTRL (CM_PER + 0x12C) 88#define CM_PER_OCPWP_CLKCTRL (CM_PER + 0x130) 89#define CM_PER_CPSW_CLKSTCTRL (CM_PER + 0x144) 90 91#define CM_WKUP 0x400 92#define CM_WKUP_CLKSTCTRL (CM_WKUP + 0x000) 93#define CM_WKUP_CONTROL_CLKCTRL (CM_WKUP + 0x004) 94#define CM_WKUP_GPIO0_CLKCTRL (CM_WKUP + 0x008) 95#define CM_WKUP_CM_L3_AON_CLKSTCTRL (CM_WKUP + 0x01C) 96#define CM_WKUP_CM_CLKSEL_DPLL_MPU (CM_WKUP + 0x02C) 97#define CM_WKUP_CM_IDLEST_DPLL_DISP (CM_WKUP + 0x048) 98#define CM_WKUP_CM_CLKSEL_DPLL_DISP (CM_WKUP + 0x054) 99#define CM_WKUP_CM_CLKDCOLDO_DPLL_PER (CM_WKUP + 0x07C) 100#define CM_WKUP_CM_CLKMODE_DPLL_DISP (CM_WKUP + 0x098) 101#define CM_WKUP_I2C0_CLKCTRL (CM_WKUP + 0x0B8) 102 103#define CM_DPLL 0x500 104#define CLKSEL_TIMER7_CLK (CM_DPLL + 0x004) 105#define CLKSEL_TIMER2_CLK (CM_DPLL + 0x008) 106#define CLKSEL_TIMER3_CLK (CM_DPLL + 0x00C) 107#define CLKSEL_TIMER4_CLK (CM_DPLL + 0x010) 108#define CLKSEL_TIMER5_CLK (CM_DPLL + 0x018) 109#define CLKSEL_TIMER6_CLK (CM_DPLL + 0x01C) 110 111#define PRM_DEVICE_OFFSET 0xF00 112#define PRM_RSTCTRL (PRM_DEVICE_OFFSET + 0x00) 113 114struct am335x_prcm_softc { 115 struct resource * res[2]; 116 bus_space_tag_t bst; 117 bus_space_handle_t bsh; 118}; 119 120static struct resource_spec am335x_prcm_spec[] = { 121 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 122 { -1, 0 } 123}; 124 125static struct am335x_prcm_softc *am335x_prcm_sc = NULL; 126 127static int am335x_clk_generic_activate(struct ti_clock_dev *clkdev); 128static int am335x_clk_gpio_activate(struct ti_clock_dev *clkdev); 129static int am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev); 130static int am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc); 131static int am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq); 132static int am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq); 133static int am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq); 134static int am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq); 135static void am335x_prcm_reset(void); 136static int am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev); 137static int am335x_clk_musb0_activate(struct ti_clock_dev *clkdev); 138static int am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev); 139 140#define AM335X_GENERIC_CLOCK_DEV(i) \ 141 { .id = (i), \ 142 .clk_activate = am335x_clk_generic_activate, \ 143 .clk_deactivate = am335x_clk_generic_deactivate, \ 144 .clk_set_source = am335x_clk_generic_set_source, \ 145 .clk_accessible = NULL, \ 146 .clk_get_source_freq = NULL \ 147 } 148 149#define AM335X_GPIO_CLOCK_DEV(i) \ 150 { .id = (i), \ 151 .clk_activate = am335x_clk_gpio_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_MMCHS_CLOCK_DEV(i) \ 159 { .id = (i), \ 160 .clk_activate = am335x_clk_generic_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 = am335x_clk_hsmmc_get_source_freq \ 165 } 166 167struct ti_clock_dev ti_clk_devmap[] = { 168 /* System clocks */ 169 { .id = SYS_CLK, 170 .clk_activate = NULL, 171 .clk_deactivate = NULL, 172 .clk_set_source = NULL, 173 .clk_accessible = NULL, 174 .clk_get_source_freq = am335x_clk_get_sysclk_freq, 175 }, 176 /* MPU (ARM) core clocks */ 177 { .id = MPU_CLK, 178 .clk_activate = NULL, 179 .clk_deactivate = NULL, 180 .clk_set_source = NULL, 181 .clk_accessible = NULL, 182 .clk_get_source_freq = am335x_clk_get_arm_fclk_freq, 183 }, 184 /* CPSW Ethernet Switch core clocks */ 185 { .id = CPSW_CLK, 186 .clk_activate = am335x_clk_cpsw_activate, 187 .clk_deactivate = NULL, 188 .clk_set_source = NULL, 189 .clk_accessible = NULL, 190 .clk_get_source_freq = NULL, 191 }, 192 193 /* Mentor USB HS controller core clocks */ 194 { .id = MUSB0_CLK, 195 .clk_activate = am335x_clk_musb0_activate, 196 .clk_deactivate = NULL, 197 .clk_set_source = NULL, 198 .clk_accessible = NULL, 199 .clk_get_source_freq = NULL, 200 }, 201 202 /* LCD controller clocks */ 203 { .id = LCDC_CLK, 204 .clk_activate = am335x_clk_lcdc_activate, 205 .clk_deactivate = NULL, 206 .clk_set_source = NULL, 207 .clk_accessible = NULL, 208 .clk_get_source_freq = am335x_clk_get_arm_disp_freq, 209 }, 210 211 /* DMTimer */ 212 AM335X_GENERIC_CLOCK_DEV(DMTIMER2_CLK), 213 AM335X_GENERIC_CLOCK_DEV(DMTIMER3_CLK), 214 AM335X_GENERIC_CLOCK_DEV(DMTIMER4_CLK), 215 AM335X_GENERIC_CLOCK_DEV(DMTIMER5_CLK), 216 AM335X_GENERIC_CLOCK_DEV(DMTIMER6_CLK), 217 AM335X_GENERIC_CLOCK_DEV(DMTIMER7_CLK), 218 219 /* GPIO */ 220 AM335X_GPIO_CLOCK_DEV(GPIO0_CLK), 221 AM335X_GPIO_CLOCK_DEV(GPIO1_CLK), 222 AM335X_GPIO_CLOCK_DEV(GPIO2_CLK), 223 AM335X_GPIO_CLOCK_DEV(GPIO3_CLK), 224 225 /* I2C */ 226 AM335X_GENERIC_CLOCK_DEV(I2C0_CLK), 227 AM335X_GENERIC_CLOCK_DEV(I2C1_CLK), 228 AM335X_GENERIC_CLOCK_DEV(I2C2_CLK), 229 230 /* EDMA */ 231 AM335X_GENERIC_CLOCK_DEV(EDMA_TPCC_CLK), 232 AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC0_CLK), 233 AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC1_CLK), 234 AM335X_GENERIC_CLOCK_DEV(EDMA_TPTC2_CLK), 235 236 /* MMCHS */ 237 AM335X_MMCHS_CLOCK_DEV(MMC0_CLK), 238 AM335X_MMCHS_CLOCK_DEV(MMC1_CLK), 239 AM335X_MMCHS_CLOCK_DEV(MMC2_CLK), 240 241 /* PWMSS */ 242 AM335X_GENERIC_CLOCK_DEV(PWMSS0_CLK), 243 AM335X_GENERIC_CLOCK_DEV(PWMSS1_CLK), 244 AM335X_GENERIC_CLOCK_DEV(PWMSS2_CLK), 245 246 { INVALID_CLK_IDENT, NULL, NULL, NULL, NULL } 247}; 248 249struct am335x_clk_details { 250 clk_ident_t id; 251 uint32_t clkctrl_reg; 252 uint32_t clksel_reg; 253}; 254 255#define _CLK_DETAIL(i, c, s) \ 256 { .id = (i), \ 257 .clkctrl_reg = (c), \ 258 .clksel_reg = (s), \ 259 } 260 261static struct am335x_clk_details g_am335x_clk_details[] = { 262 263 /* DMTimer modules */ 264 _CLK_DETAIL(DMTIMER2_CLK, CM_PER_TIMER2_CLKCTRL, CLKSEL_TIMER2_CLK), 265 _CLK_DETAIL(DMTIMER3_CLK, CM_PER_TIMER3_CLKCTRL, CLKSEL_TIMER3_CLK), 266 _CLK_DETAIL(DMTIMER4_CLK, CM_PER_TIMER4_CLKCTRL, CLKSEL_TIMER4_CLK), 267 _CLK_DETAIL(DMTIMER5_CLK, CM_PER_TIMER5_CLKCTRL, CLKSEL_TIMER5_CLK), 268 _CLK_DETAIL(DMTIMER6_CLK, CM_PER_TIMER6_CLKCTRL, CLKSEL_TIMER6_CLK), 269 _CLK_DETAIL(DMTIMER7_CLK, CM_PER_TIMER7_CLKCTRL, CLKSEL_TIMER7_CLK), 270 271 /* GPIO modules */ 272 _CLK_DETAIL(GPIO0_CLK, CM_WKUP_GPIO0_CLKCTRL, 0), 273 _CLK_DETAIL(GPIO1_CLK, CM_PER_GPIO1_CLKCTRL, 0), 274 _CLK_DETAIL(GPIO2_CLK, CM_PER_GPIO2_CLKCTRL, 0), 275 _CLK_DETAIL(GPIO3_CLK, CM_PER_GPIO3_CLKCTRL, 0), 276 277 /* I2C modules */ 278 _CLK_DETAIL(I2C0_CLK, CM_WKUP_I2C0_CLKCTRL, 0), 279 _CLK_DETAIL(I2C1_CLK, CM_PER_I2C1_CLKCTRL, 0), 280 _CLK_DETAIL(I2C2_CLK, CM_PER_I2C2_CLKCTRL, 0), 281 282 /* EDMA modules */ 283 _CLK_DETAIL(EDMA_TPCC_CLK, CM_PER_TPCC_CLKCTRL, 0), 284 _CLK_DETAIL(EDMA_TPTC0_CLK, CM_PER_TPTC0_CLKCTRL, 0), 285 _CLK_DETAIL(EDMA_TPTC1_CLK, CM_PER_TPTC1_CLKCTRL, 0), 286 _CLK_DETAIL(EDMA_TPTC2_CLK, CM_PER_TPTC2_CLKCTRL, 0), 287 288 /* MMCHS modules*/ 289 _CLK_DETAIL(MMC0_CLK, CM_PER_MMC0_CLKCTRL, 0), 290 _CLK_DETAIL(MMC1_CLK, CM_PER_MMC1_CLKCTRL, 0), 291 _CLK_DETAIL(MMC2_CLK, CM_PER_MMC1_CLKCTRL, 0), 292 293 /* PWMSS modules */ 294 _CLK_DETAIL(PWMSS0_CLK, CM_PER_EPWMSS0_CLKCTRL, 0), 295 _CLK_DETAIL(PWMSS1_CLK, CM_PER_EPWMSS1_CLKCTRL, 0), 296 _CLK_DETAIL(PWMSS2_CLK, CM_PER_EPWMSS2_CLKCTRL, 0), 297 298 { INVALID_CLK_IDENT, 0}, 299}; 300 301/* Read/Write macros */ 302#define prcm_read_4(reg) \ 303 bus_space_read_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg) 304#define prcm_write_4(reg, val) \ 305 bus_space_write_4(am335x_prcm_sc->bst, am335x_prcm_sc->bsh, reg, val) 306 307void am335x_prcm_setup_dmtimer(int); 308 309static int 310am335x_prcm_probe(device_t dev) 311{ 312 if (ofw_bus_is_compatible(dev, "am335x,prcm")) { 313 device_set_desc(dev, "AM335x Power and Clock Management"); 314 return(BUS_PROBE_DEFAULT); 315 } 316 317 return (ENXIO); 318} 319 320static int 321am335x_prcm_attach(device_t dev) 322{ 323 struct am335x_prcm_softc *sc = device_get_softc(dev); 324 unsigned int sysclk, fclk; 325 326 if (am335x_prcm_sc) 327 return (ENXIO); 328 329 if (bus_alloc_resources(dev, am335x_prcm_spec, sc->res)) { 330 device_printf(dev, "could not allocate resources\n"); 331 return (ENXIO); 332 } 333 334 sc->bst = rman_get_bustag(sc->res[0]); 335 sc->bsh = rman_get_bushandle(sc->res[0]); 336 337 am335x_prcm_sc = sc; 338 ti_cpu_reset = am335x_prcm_reset; 339 340 am335x_clk_get_sysclk_freq(NULL, &sysclk); 341 am335x_clk_get_arm_fclk_freq(NULL, &fclk); 342 device_printf(dev, "Clocks: System %u.%01u MHz, CPU %u MHz\n", 343 sysclk/1000000, (sysclk % 1000000)/100000, fclk/1000000); 344 345 return (0); 346} 347 348static device_method_t am335x_prcm_methods[] = { 349 DEVMETHOD(device_probe, am335x_prcm_probe), 350 DEVMETHOD(device_attach, am335x_prcm_attach), 351 { 0, 0 } 352}; 353 354static driver_t am335x_prcm_driver = { 355 "am335x_prcm", 356 am335x_prcm_methods, 357 sizeof(struct am335x_prcm_softc), 358}; 359 360static devclass_t am335x_prcm_devclass; 361 362DRIVER_MODULE(am335x_prcm, simplebus, am335x_prcm_driver, 363 am335x_prcm_devclass, 0, 0); 364MODULE_DEPEND(am335x_prcm, ti_scm, 1, 1, 1); 365 366static struct am335x_clk_details* 367am335x_clk_details(clk_ident_t id) 368{ 369 struct am335x_clk_details *walker; 370 371 for (walker = g_am335x_clk_details; walker->id != INVALID_CLK_IDENT; walker++) { 372 if (id == walker->id) 373 return (walker); 374 } 375 376 return NULL; 377} 378 379static int 380am335x_clk_generic_activate(struct ti_clock_dev *clkdev) 381{ 382 struct am335x_prcm_softc *sc = am335x_prcm_sc; 383 struct am335x_clk_details* clk_details; 384 385 if (sc == NULL) 386 return ENXIO; 387 388 clk_details = am335x_clk_details(clkdev->id); 389 390 if (clk_details == NULL) 391 return (ENXIO); 392 393 /* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */ 394 prcm_write_4(clk_details->clkctrl_reg, 2); 395 while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 2) 396 DELAY(10); 397 398 return (0); 399} 400 401static int 402am335x_clk_gpio_activate(struct ti_clock_dev *clkdev) 403{ 404 struct am335x_prcm_softc *sc = am335x_prcm_sc; 405 struct am335x_clk_details* clk_details; 406 407 if (sc == NULL) 408 return ENXIO; 409 410 clk_details = am335x_clk_details(clkdev->id); 411 412 if (clk_details == NULL) 413 return (ENXIO); 414 415 /* set *_CLKCTRL register MODULEMODE[1:0] to enable(2) */ 416 /* set *_CLKCTRL register OPTFCLKEN_GPIO_1_G DBCLK[18] to FCLK_EN(1) */ 417 prcm_write_4(clk_details->clkctrl_reg, 2 | (1 << 18)); 418 while ((prcm_read_4(clk_details->clkctrl_reg) & 419 (3 | (1 << 18) )) != (2 | (1 << 18))) 420 DELAY(10); 421 422 return (0); 423} 424 425static int 426am335x_clk_generic_deactivate(struct ti_clock_dev *clkdev) 427{ 428 struct am335x_prcm_softc *sc = am335x_prcm_sc; 429 struct am335x_clk_details* clk_details; 430 431 if (sc == NULL) 432 return ENXIO; 433 434 clk_details = am335x_clk_details(clkdev->id); 435 436 if (clk_details == NULL) 437 return (ENXIO); 438 439 /* set *_CLKCTRL register MODULEMODE[1:0] to disable(0) */ 440 prcm_write_4(clk_details->clkctrl_reg, 0); 441 while ((prcm_read_4(clk_details->clkctrl_reg) & 0x3) != 0) 442 DELAY(10); 443 444 return (0); 445} 446 447static int 448am335x_clk_generic_set_source(struct ti_clock_dev *clkdev, clk_src_t clksrc) 449{ 450 struct am335x_prcm_softc *sc = am335x_prcm_sc; 451 struct am335x_clk_details* clk_details; 452 uint32_t reg; 453 454 if (sc == NULL) 455 return ENXIO; 456 457 clk_details = am335x_clk_details(clkdev->id); 458 459 if (clk_details == NULL) 460 return (ENXIO); 461 462 switch (clksrc) { 463 case EXT_CLK: 464 reg = 0; /* SEL2: TCLKIN clock */ 465 break; 466 case SYSCLK_CLK: 467 reg = 1; /* SEL1: CLK_M_OSC clock */ 468 break; 469 case F32KHZ_CLK: 470 reg = 2; /* SEL3: CLK_32KHZ clock */ 471 break; 472 default: 473 return (ENXIO); 474 } 475 476 prcm_write_4(clk_details->clksel_reg, reg); 477 while ((prcm_read_4(clk_details->clksel_reg) & 0x3) != reg) 478 DELAY(10); 479 480 return (0); 481} 482 483static int 484am335x_clk_hsmmc_get_source_freq(struct ti_clock_dev *clkdev, unsigned int *freq) 485{ 486 *freq = 96000000; 487 return (0); 488} 489 490static int 491am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq) 492{ 493 uint32_t ctrl_status; 494 495 /* Read the input clock freq from the control module */ 496 /* control_status reg (0x40) */ 497 if (ti_scm_reg_read_4(0x40, &ctrl_status)) 498 return ENXIO; 499 500 switch ((ctrl_status>>22) & 0x3) { 501 case 0x0: 502 /* 19.2Mhz */ 503 *freq = 19200000; 504 break; 505 case 0x1: 506 /* 24Mhz */ 507 *freq = 24000000; 508 break; 509 case 0x2: 510 /* 25Mhz */ 511 *freq = 25000000; 512 break; 513 case 0x3: 514 /* 26Mhz */ 515 *freq = 26000000; 516 break; 517 } 518 519 return (0); 520} 521 522#define DPLL_BYP_CLKSEL(reg) ((reg>>23) & 1) 523#define DPLL_DIV(reg) ((reg & 0x7f)+1) 524#define DPLL_MULT(reg) ((reg>>8) & 0x7FF) 525 526static int 527am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq) 528{ 529 uint32_t reg; 530 uint32_t sysclk; 531 532 reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_MPU); 533 534 /*Check if we are running in bypass */ 535 if (DPLL_BYP_CLKSEL(reg)) 536 return ENXIO; 537 538 am335x_clk_get_sysclk_freq(NULL, &sysclk); 539 *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg)); 540 return(0); 541} 542 543static int 544am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq) 545{ 546 uint32_t reg; 547 uint32_t sysclk; 548 549 reg = prcm_read_4(CM_WKUP_CM_CLKSEL_DPLL_DISP); 550 551 /*Check if we are running in bypass */ 552 if (DPLL_BYP_CLKSEL(reg)) 553 return ENXIO; 554 555 am335x_clk_get_sysclk_freq(NULL, &sysclk); 556 *freq = DPLL_MULT(reg) * (sysclk / DPLL_DIV(reg)); 557 return(0); 558} 559 560static void 561am335x_prcm_reset(void) 562{ 563 prcm_write_4(PRM_RSTCTRL, (1<<1)); 564} 565 566static int 567am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev) 568{ 569 struct am335x_prcm_softc *sc = am335x_prcm_sc; 570 571 if (sc == NULL) 572 return ENXIO; 573 574 /* set MODULENAME to ENABLE */ 575 prcm_write_4(CM_PER_CPGMAC0_CLKCTRL, 2); 576 577 /* wait for IDLEST to become Func(0) */ 578 while(prcm_read_4(CM_PER_CPGMAC0_CLKCTRL) & (3<<16)); 579 580 /*set CLKTRCTRL to SW_WKUP(2) */ 581 prcm_write_4(CM_PER_CPSW_CLKSTCTRL, 2); 582 583 /* wait for 125 MHz OCP clock to become active */ 584 while((prcm_read_4(CM_PER_CPSW_CLKSTCTRL) & (1<<4)) == 0); 585 return(0); 586} 587 588static int 589am335x_clk_musb0_activate(struct ti_clock_dev *clkdev) 590{ 591 struct am335x_prcm_softc *sc = am335x_prcm_sc; 592 593 if (sc == NULL) 594 return ENXIO; 595 596 /* set ST_DPLL_CLKDCOLDO(9) to CLK_GATED(1) */ 597 /* set DPLL_CLKDCOLDO_GATE_CTRL(8) to CLK_ENABLE(1)*/ 598 prcm_write_4(CM_WKUP_CM_CLKDCOLDO_DPLL_PER, 0x300); 599 600 /*set MODULEMODE to ENABLE(2) */ 601 prcm_write_4(CM_PER_USB0_CLKCTRL, 2); 602 603 /* wait for MODULEMODE to become ENABLE(2) */ 604 while ((prcm_read_4(CM_PER_USB0_CLKCTRL) & 0x3) != 2) 605 DELAY(10); 606 607 /* wait for IDLEST to become Func(0) */ 608 while(prcm_read_4(CM_PER_USB0_CLKCTRL) & (3<<16)) 609 DELAY(10); 610 611 return(0); 612} 613 614static int 615am335x_clk_lcdc_activate(struct ti_clock_dev *clkdev) 616{ 617 struct am335x_prcm_softc *sc = am335x_prcm_sc; 618 619 if (sc == NULL) 620 return (ENXIO); 621 622 /* Bypass mode */ 623 prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x4); 624 625 /* Make sure it's in bypass mode */ 626 while (!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP) 627 & (1 << 8))) 628 DELAY(10); 629 630 /* 631 * For now set frequenct to 5xSYSFREQ 632 * More flexible control might be required 633 */ 634 prcm_write_4(CM_WKUP_CM_CLKSEL_DPLL_DISP, (5 << 8) | 0); 635 636 /* Locked mode */ 637 prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7); 638 639 int timeout = 10000; 640 while ((!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP) 641 & (1 << 0))) && timeout--) 642 DELAY(10); 643 644 /*set MODULEMODE to ENABLE(2) */ 645 prcm_write_4(CM_PER_LCDC_CLKCTRL, 2); 646 647 /* wait for MODULEMODE to become ENABLE(2) */ 648 while ((prcm_read_4(CM_PER_LCDC_CLKCTRL) & 0x3) != 2) 649 DELAY(10); 650 651 /* wait for IDLEST to become Func(0) */ 652 while(prcm_read_4(CM_PER_LCDC_CLKCTRL) & (3<<16)) 653 DELAY(10); 654 655 return (0); 656} 657