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