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