Changeset View
Changeset View
Standalone View
Standalone View
sys/arm/ti/ti_sysc.c
Show First 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | |||||
#include <vm/pmap.h> | #include <vm/pmap.h> | ||||
#include <dev/fdt/simplebus.h> | #include <dev/fdt/simplebus.h> | ||||
#include <dev/ofw/ofw_bus.h> | #include <dev/ofw/ofw_bus.h> | ||||
#include <dev/ofw/ofw_bus_subr.h> | #include <dev/ofw/ofw_bus_subr.h> | ||||
#include <dev/extres/clk/clk.h> | #include <dev/extres/clk/clk.h> | ||||
#include <dev/extres/clk/clk_link.h> | |||||
#include <arm/ti/ti_sysc.h> | #include <arm/ti/ti_sysc.h> | ||||
#include <arm/ti/clk/clock_common.h> | #include <arm/ti/clk/ti_clock_common.h> | ||||
#include <arm/ti/ti_cpuid.h> | |||||
#define DEBUG_SYSC 0 | #define DEBUG_SYSC 0 | ||||
#if DEBUG_SYSC | #if DEBUG_SYSC | ||||
#define DPRINTF(dev, msg...) device_printf(dev, msg) | #define DPRINTF(dev, msg...) device_printf(dev, msg) | ||||
#else | #else | ||||
#define DPRINTF(dev, msg...) | #define DPRINTF(dev, msg...) | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | static struct ofw_compat_data compat_data[] = { | ||||
/* Above needs special workarounds */ | /* Above needs special workarounds */ | ||||
{ "ti,sysc-omap4-simple", TI_SYSC_OMAP4_SIMPLE }, | { "ti,sysc-omap4-simple", TI_SYSC_OMAP4_SIMPLE }, | ||||
{ "ti,sysc-omap4", TI_SYSC_OMAP4 }, | { "ti,sysc-omap4", TI_SYSC_OMAP4 }, | ||||
{ "ti,sysc-omap2", TI_SYSC_OMAP2 }, | { "ti,sysc-omap2", TI_SYSC_OMAP2 }, | ||||
{ "ti,sysc", TI_SYSC }, | { "ti,sysc", TI_SYSC }, | ||||
{ NULL, TI_SYSC_END } | { NULL, TI_SYSC_END } | ||||
}; | }; | ||||
PLIST(target_module_7000) = { | |||||
"l4-wkup-clkctrl@0_8", | |||||
"l4-wkup-clkctrl@0_9" | |||||
}; /* gpio0 */ | |||||
PLIST(target_module_9000) = { "l4-wkup-clkctrl@0_b4" }; /* uart0 */ | |||||
PLIST(target_module_b000) = { "l4-wkup-clkctrl@0_b8" }; /* i2c1 */ | |||||
PLIST(target_module_d000) = { "l4-wkup-clkctrl@0_bc" }; /* adc_tsc */ | |||||
PLIST(target_module_31000) = { "l4-wkup-clkctrl@0_c4" }; /* timer1 */ | |||||
PLIST(target_module_35000) = { "l4-wkup-clkctrl@0_d4" }; /* timer2 */ | |||||
PLIST(target_module_3e000) = { "l4-rtc-clkctrl@0_0" }; /* rtc */ | |||||
PLIST(target_module_100000) = { | |||||
"cpsw-125mhz-clkctrl@0_14" | |||||
}; /* cpsw (ethernet) */ | |||||
PLIST(target_module_300000) = { "pruss-ocp-clkctrl@e8_0" }; /* pru */ | |||||
PLIST(target_module_22000) = { "l4ls-clkctrl@38_34" }; /* uart2 */ | |||||
PLIST(target_module_24000) = { "l4ls-clkctrl@38_38" }; /* uart3 */ | |||||
PLIST(target_module_2a000) = { "l4ls-clkctrl@38_10" }; /* i2c2 */ | |||||
PLIST(target_module_30000) = { "l4ls-clkctrl@38_14" }; /* spi0 */ | |||||
PLIST(target_module_40000) = { "l4ls-clkctrl@38_48" }; /* timer2 */ | |||||
PLIST(target_module_42000) = { "l4ls-clkctrl@38_4c" }; /* timer3 */ | |||||
PLIST(target_module_44000) = { "l4ls-clkctrl@38_50" }; /* timer4 */ | |||||
PLIST(target_module_46000) = { "l4ls-clkctrl@38_b4" }; /* timer5 */ | |||||
PLIST(target_module_48000) = { "l4ls-clkctrl@38_b8" }; /* timer6 */ | |||||
PLIST(target_module_4a000) = { "l4ls-clkctrl@38_44" }; /* timer7 */ | |||||
PLIST(target_module_4c000) = { | |||||
"l4ls-clkctrl@38_74", | |||||
"l4ls-clkctrl@38_75" | |||||
}; /* gpio2 */ | |||||
PLIST(target_module_60000) = { "l4ls-clkctrl@38_4" }; /* mmc1 */ | |||||
PLIST(target_module_80000) = { "l4ls-clkctrl@38_8" }; /* elm */ | |||||
PLIST(target_module_c8000) = { "l4ls-clkctrl@38_d8" }; /* mailbox */ | |||||
PLIST(target_module_ca000) = { "l4ls-clkctrl@38_d4" }; /* spinlock */ | |||||
PLIST(target_module_9c000) = { "l4ls-clkctrl@38_c" }; /* i2c3 */ | |||||
PLIST(target_module_a0000) = { "l4ls-clkctrl@38_18" }; /* spi1 */ | |||||
PLIST(target_module_a6000) = { "l4ls-clkctrl@38_3c" }; /* uart4 */ | |||||
PLIST(target_module_a8000) = { "l4ls-clkctrl@38_40" }; /* uart5 */ | |||||
PLIST(target_module_aa000) = { "l4ls-clkctrl@38_0" }; /* uart6 */ | |||||
PLIST(target_module_ac000) = { | |||||
"l4ls-clkctrl@38_78", | |||||
"l4ls-clkctrl@38_79" | |||||
}; /* gpio3 */ | |||||
PLIST(target_module_ae000) = { | |||||
"l4ls-clkctrl@38_7c", | |||||
"l4ls-clkctrl@38_7d" | |||||
}; /* gpio4 */ | |||||
PLIST(target_module_cc000) = { "l4ls-clkctrl@38_88" }; /* dcan0 */ | |||||
PLIST(target_module_d0000) = { "l4ls-clkctrl@38_8c" }; /* dcan1 */ | |||||
PLIST(target_module_d8000) = { "l4ls-clkctrl@38_bc" }; /* mmc2 */ | |||||
PLIST(target_module_0) = { "l4ls-clkctrl@38_9c" }; /* epwmss0 */ | |||||
PLIST(target_module_2000) = { "l4ls-clkctrl@38_94" }; /* epwmss1 */ | |||||
PLIST(target_module_4000) = { "l4ls-clkctrl@38_a0" }; /* epwmss2 */ | |||||
PLIST(target_module_e000) = { "lcdc-clkctrl@18_0" }; /* lcdc */ | |||||
PLIST(target_module_10000) = { "l4ls-clkctrl@38_58" }; /* rng */ | |||||
PLIST(target_module_49800000) = { "l3-clkctrl@24_0" }; /* tptco */ | |||||
PLIST(target_module_4c000000) = { "l3-clkctrl@24_4" }; /* emif */ | |||||
PLIST(target_module_40300000) = { "l3-clkctrl@24_8" }; /* ocmcram */ | |||||
PLIST(target_module_53500000) = { "l3-clkctrl@24_70" }; /* aes */ | |||||
PLIST(target_module_53100000) = { "l3-clkctrl@24_7c" }; /* sham */ | |||||
PLIST(target_module_49000000) = { "l3-clkctrl@24_98" }; /* tpcc */ | |||||
PLIST(target_module_4b000000) = { "l3-clkctrl@24_b8" }; /* l3 instr */ | |||||
PLIST(target_module_49900000) = { "l3-clkctrl@24_d8" }; /* tptc1 */ | |||||
PLIST(target_module_49a00000) = { "l3-clkctrl@24_dc" }; /* tptc2 */ | |||||
PLIST(target_module_47400000) = { "l3s-clkctrl@1c_0" }; /* usb otg hs */ | |||||
PLIST(target_module_50000000) = { "l3s-clkctrl@1c_14" }; /* gpmc */ | |||||
PLIST(target_module_38000) = { "l3s-clkctrl@1c_18" }; /* mcasp0 */ | |||||
PLIST(target_module_3c000) = { "l3s-clkctrl@1c_4c" }; /* mcasp1 */ | |||||
PLIST(target_module_47810000) = { "l3s-clkctrl@1c_dc" }; /* mmc3 */ | |||||
PLIST(target_module_140000) = { "l3-aon-clkctrl@14_0" }; /* l3 debugss */ | |||||
PLIST(target_module_56000000) = { "gfx-l3-clkctrl@0_4" }; /* gfx */ | |||||
static struct parent_lookup_table sysc_clock_table[] = { | |||||
{ | |||||
"target-module@7000", | |||||
nitems(target_module_7000), | |||||
target_module_7000 | |||||
}, | |||||
{ | |||||
"target-module@9000", | |||||
nitems(target_module_9000), | |||||
target_module_9000 | |||||
}, | |||||
{ | |||||
"target-module@b000", | |||||
nitems(target_module_b000), | |||||
target_module_b000 | |||||
}, | |||||
{ | |||||
"target-module@d000", | |||||
nitems(target_module_d000), | |||||
target_module_d000 | |||||
}, | |||||
{ | |||||
"target-module@31000", | |||||
nitems(target_module_31000), | |||||
target_module_31000 | |||||
}, | |||||
{ | |||||
"target-module@35000", | |||||
nitems(target_module_35000), | |||||
target_module_35000 | |||||
}, | |||||
{ | |||||
"target-module@3e000", | |||||
nitems(target_module_3e000), | |||||
target_module_3e000 | |||||
}, | |||||
{ | |||||
"target-module@100000", | |||||
nitems(target_module_100000), | |||||
target_module_100000 | |||||
}, | |||||
{ | |||||
"target-module@300000", | |||||
nitems(target_module_300000), | |||||
target_module_300000 | |||||
}, | |||||
{ | |||||
"target-module@22000", | |||||
nitems(target_module_22000), | |||||
target_module_22000 | |||||
}, | |||||
{ | |||||
"target-module@24000", | |||||
nitems(target_module_24000), | |||||
target_module_24000 | |||||
}, | |||||
{ | |||||
"target-module@2a000", | |||||
nitems(target_module_2a000), | |||||
target_module_2a000 | |||||
}, | |||||
{ | |||||
"target-module@30000", | |||||
nitems(target_module_30000), | |||||
target_module_30000 | |||||
}, | |||||
{ | |||||
"target-module@40000", | |||||
nitems(target_module_40000), | |||||
target_module_40000 | |||||
}, | |||||
{ | |||||
"target-module@42000", | |||||
nitems(target_module_42000), | |||||
target_module_42000 | |||||
}, | |||||
{ | |||||
"target-module@44000", | |||||
nitems(target_module_44000), | |||||
target_module_44000 | |||||
}, | |||||
{ | |||||
"target-module@46000", | |||||
nitems(target_module_46000), | |||||
target_module_46000 | |||||
}, | |||||
{ | |||||
"target-module@48000", | |||||
nitems(target_module_48000), | |||||
target_module_48000 | |||||
}, | |||||
{ | |||||
"target-module@4a000", | |||||
nitems(target_module_4a000), | |||||
target_module_4a000 | |||||
}, | |||||
{ | |||||
"target-module@4c000", | |||||
nitems(target_module_4c000), | |||||
target_module_4c000 | |||||
}, | |||||
{ | |||||
"target-module@60000", | |||||
nitems(target_module_60000), | |||||
target_module_60000 | |||||
}, | |||||
{ | |||||
"target-module@80000", | |||||
nitems(target_module_80000), | |||||
target_module_80000 | |||||
}, | |||||
{ | |||||
"target-module@c8000", | |||||
nitems(target_module_c8000), | |||||
target_module_c8000 | |||||
}, | |||||
{ | |||||
"target-module@ca000", | |||||
nitems(target_module_ca000), | |||||
target_module_ca000 | |||||
}, | |||||
{ | |||||
"target-module@9c000", | |||||
nitems(target_module_9c000), | |||||
target_module_9c000 | |||||
}, | |||||
{ | |||||
"target-module@a0000", | |||||
nitems(target_module_a0000), | |||||
target_module_a0000 | |||||
}, | |||||
{ | |||||
"target-module@a6000", | |||||
nitems(target_module_a6000), | |||||
target_module_a6000 | |||||
}, | |||||
{ | |||||
"target-module@a8000", | |||||
nitems(target_module_a8000), | |||||
target_module_a8000 | |||||
}, | |||||
{ | |||||
"target-module@aa000", | |||||
nitems(target_module_aa000), | |||||
target_module_aa000 | |||||
}, | |||||
{ | |||||
"target-module@ac000", | |||||
nitems(target_module_ac000), | |||||
target_module_ac000 | |||||
}, | |||||
{ | |||||
"target-module@ae000", | |||||
nitems(target_module_ae000), | |||||
target_module_ae000 | |||||
}, | |||||
{ | |||||
"target-module@cc000", | |||||
nitems(target_module_cc000), | |||||
target_module_cc000 | |||||
}, | |||||
{ | |||||
"target-module@d0000", | |||||
nitems(target_module_d0000), | |||||
target_module_d0000 | |||||
}, | |||||
{ | |||||
"target-module@d8000", | |||||
nitems(target_module_d8000), | |||||
target_module_d8000 | |||||
}, | |||||
{ | |||||
"target-module@0", | |||||
nitems(target_module_0), | |||||
target_module_0 | |||||
}, | |||||
{ | |||||
"target-module@2000", | |||||
nitems(target_module_2000), | |||||
target_module_2000 | |||||
}, | |||||
{ | |||||
"target-module@4000", | |||||
nitems(target_module_4000), | |||||
target_module_4000 | |||||
}, | |||||
{ | |||||
"target-module@e000", | |||||
nitems(target_module_e000), | |||||
target_module_e000 | |||||
}, | |||||
{ | |||||
"target-module@10000", | |||||
nitems(target_module_10000), | |||||
target_module_10000 | |||||
}, | |||||
{ | |||||
"target-module@49000000", | |||||
nitems(target_module_49000000), | |||||
target_module_49000000 | |||||
}, | |||||
{ | |||||
"target-module@49800000", | |||||
nitems(target_module_49800000), | |||||
target_module_49800000 | |||||
}, | |||||
{ | |||||
"target-module@4c000000", | |||||
nitems(target_module_4c000000), | |||||
target_module_4c000000 | |||||
}, | |||||
{ | |||||
"target-module@40300000", | |||||
nitems(target_module_40300000), | |||||
target_module_40300000 | |||||
}, | |||||
{ | |||||
"target-module@49900000", | |||||
nitems(target_module_49900000), | |||||
target_module_49900000 | |||||
}, | |||||
{ | |||||
"target-module@49a00000", | |||||
nitems(target_module_49a00000), | |||||
target_module_49a00000 | |||||
}, | |||||
{ | |||||
"target-module@47810000", | |||||
nitems(target_module_47810000), | |||||
target_module_47810000 | |||||
}, | |||||
{ | |||||
"target-module@47400000", | |||||
nitems(target_module_47400000), | |||||
target_module_47400000 | |||||
}, | |||||
{ | |||||
"target-module@50000000", | |||||
nitems(target_module_50000000), | |||||
target_module_50000000 | |||||
}, | |||||
{ | |||||
"target-module@38000", | |||||
nitems(target_module_38000), | |||||
target_module_38000 | |||||
}, | |||||
{ | |||||
"target-module@3c000", | |||||
nitems(target_module_3c000), | |||||
target_module_3c000 | |||||
}, | |||||
{ | |||||
"target-module@4b000000", | |||||
nitems(target_module_4b000000), | |||||
target_module_4b000000 | |||||
}, | |||||
{ | |||||
"target-module@140000", | |||||
nitems(target_module_140000), | |||||
target_module_140000 | |||||
}, | |||||
{ | |||||
"target-module@53100000", | |||||
nitems(target_module_53100000), | |||||
target_module_53100000 | |||||
}, | |||||
{ | |||||
"target-module@53500000", | |||||
nitems(target_module_53500000), | |||||
target_module_53500000 | |||||
}, | |||||
{ | |||||
"target-module@56000000", | |||||
nitems(target_module_56000000), | |||||
target_module_56000000 | |||||
}, | |||||
}; | |||||
static struct clk_link_def scm_clocks[] = { | |||||
LINK("sys_clkin_ck"), | |||||
LINK("adc_tsc_fck"), | |||||
LINK("dcan0_fck"), | |||||
LINK("dcan1_fck"), | |||||
LINK("mcasp0_fck"), | |||||
LINK("mcasp1_fck"), | |||||
LINK("smartreflex0_fck"), | |||||
LINK("smartreflex1_fck"), | |||||
LINK("sha0_fck"), | |||||
LINK("aes0_fck"), | |||||
LINK("rng_fck"), | |||||
LINK("ehrpwm0_tbclk"), | |||||
LINK("ehrpwm1_tbclk"), | |||||
LINK("ehrpwm2_tbclk"), | |||||
}; | |||||
static struct clk_link_def per_cm_0[] = { | |||||
/* reg = <0x38 0x2c>, <0x6c 0x28>, <0xac 0xc>, | |||||
<0xc0 0x1c>, <0xec 0xc>, <0x10c 0x8>, <0x130 0x4>; */ | |||||
/* <0x38 0x2c> */ | |||||
LINK("l4ls-clkctrl@38_0"), | |||||
LINK("l4ls-clkctrl@38_4"), | |||||
LINK("l4ls-clkctrl@38_8"), | |||||
LINK("l4ls-clkctrl@38_c"), | |||||
LINK("l4ls-clkctrl@38_10"), | |||||
LINK("l4ls-clkctrl@38_14"), | |||||
LINK("l4ls-clkctrl@38_18"), | |||||
LINK("l4ls-clkctrl@38_1c"), | |||||
LINK("l4ls-clkctrl@38_20"), | |||||
LINK("l4ls-clkctrl@38_24"), | |||||
LINK("l4ls-clkctrl@38_28"), | |||||
/* <0x6c 0x28> */ | |||||
LINK("l4ls-clkctrl@38_34"), | |||||
LINK("l4ls-clkctrl@38_38"), | |||||
LINK("l4ls-clkctrl@38_3c"), | |||||
LINK("l4ls-clkctrl@38_40"), | |||||
LINK("l4ls-clkctrl@38_44"), | |||||
LINK("l4ls-clkctrl@38_48"), | |||||
LINK("l4ls-clkctrl@38_4c"), | |||||
LINK("l4ls-clkctrl@38_50"), | |||||
LINK("l4ls-clkctrl@38_54"), | |||||
LINK("l4ls-clkctrl@38_58"), | |||||
/* <0xac 0xc> */ | |||||
LINK("l4ls-clkctrl@38_74"), | |||||
LINK("l4ls-clkctrl@38_75"), | |||||
LINK("l4ls-clkctrl@38_78"), | |||||
LINK("l4ls-clkctrl@38_79"), | |||||
LINK("l4ls-clkctrl@38_7c"), | |||||
LINK("l4ls-clkctrl@38_7d"), | |||||
/* <0xc0 0x1c> */ | |||||
LINK("l4ls-clkctrl@38_88"), | |||||
LINK("l4ls-clkctrl@38_8c"), | |||||
LINK("l4ls-clkctrl@38_90"), | |||||
LINK("l4ls-clkctrl@38_94"), | |||||
LINK("l4ls-clkctrl@38_98"), | |||||
LINK("l4ls-clkctrl@38_9c"), | |||||
LINK("l4ls-clkctrl@38_a0"), | |||||
/* <0xec 0xc> */ | |||||
LINK("l4ls-clkctrl@38_b4"), | |||||
LINK("l4ls-clkctrl@38_b8"), | |||||
LINK("l4ls-clkctrl@38_bc"), | |||||
/* <0xd4 0x8> */ | |||||
LINK("l4ls-clkctrl@38_d4"), | |||||
LINK("l4ls-clkctrl@38_d8"), | |||||
/* <0x130 0x4> */ | |||||
LINK("l4ls-clkctrl@38_f8"), | |||||
/* reg = <0x1c 0x4>, <0x30 0x8>, <0x68 0x4>, <0xf8 0x4> */ | |||||
/* <0x1c 0x4> */ | |||||
LINK("l3s-clkctrl@1c_0"), | |||||
/* <0x30 0x8> */ | |||||
LINK("l3s-clkctrl@1c_14"), | |||||
LINK("l3s-clkctrl@1c_18"), | |||||
/* <0x68 0x4> */ | |||||
LINK("l3s-clkctrl@1c_4c"), | |||||
/* <0xf8 0x4> */ | |||||
LINK("l3s-clkctrl@1c_dc"), | |||||
/* reg = <0x24 0xc>, <0x94 0x10>, <0xbc 0x4>, <0xdc 0x8>, <0xfc 0x8>; */ | |||||
/* <0x24 0xc> */ | |||||
LINK("l3-clkctrl@24_0"), | |||||
LINK("l3-clkctrl@24_4"), | |||||
LINK("l3-clkctrl@24_8"), | |||||
/* <0x94 0x10> */ | |||||
LINK("l3-clkctrl@24_70"), | |||||
LINK("l3-clkctrl@24_74"), | |||||
LINK("l3-clkctrl@24_78"), | |||||
LINK("l3-clkctrl@24_7c"), | |||||
/* <0xbc 0x4> */ | |||||
LINK("l3-clkctrl@24_98"), | |||||
/* <0xdc 0x8> */ | |||||
LINK("l3-clkctrl@24_b8"), | |||||
LINK("l3-clkctrl@24_bc"), | |||||
/* <0xfc 0x8> */ | |||||
LINK("l3-clkctrl@24_d8"), | |||||
LINK("l3-clkctrl@24_dc"), | |||||
/* reg = <0x120 0x4>; */ | |||||
LINK("l4hs-clkctrl@120_0"), | |||||
/* reg = <0xe8 0x4>; */ | |||||
LINK("pruss-ocp-clkctrl@e8_0"), | |||||
/* reg = <0x0 0x18>; */ | |||||
LINK("cpsw-125mhz-clkctrl@0_0"), | |||||
LINK("cpsw-125mhz-clkctrl@0_4"), | |||||
LINK("cpsw-125mhz-clkctrl@0_8"), | |||||
LINK("cpsw-125mhz-clkctrl@0_c"), | |||||
LINK("cpsw-125mhz-clkctrl@0_10"), | |||||
LINK("cpsw-125mhz-clkctrl@0_14"), | |||||
/* reg = <0x18 0x4>; */ | |||||
LINK("lcdc-clkctrl@18_0"), | |||||
/* reg = <0x14c 0x4>; */ | |||||
LINK("clk-24mhz-clkctrl@14c_0"), | |||||
/* reg = <0x0 0x10>, <0xb4 0x24>; */ | |||||
/* <0x0 0x10> */ | |||||
LINK("l4-wkup-clkctrl@0_0"), | |||||
LINK("l4-wkup-clkctrl@0_4"), | |||||
LINK("l4-wkup-clkctrl@0_8"), | |||||
LINK("l4-wkup-clkctrl@0_9"), | |||||
LINK("l4-wkup-clkctrl@0_c"), | |||||
/* <0xb4 0x24> */ | |||||
LINK("l4-wkup-clkctrl@0_b4"), | |||||
LINK("l4-wkup-clkctrl@0_b8"), | |||||
LINK("l4-wkup-clkctrl@0_bc"), | |||||
LINK("l4-wkup-clkctrl@0_c0"), | |||||
LINK("l4-wkup-clkctrl@0_c4"), | |||||
LINK("l4-wkup-clkctrl@0_c8"), | |||||
LINK("l4-wkup-clkctrl@0_cc"), | |||||
LINK("l4-wkup-clkctrl@0_d0"), | |||||
LINK("l4-wkup-clkctrl@0_d4"), | |||||
/* reg = <0x14 0x4>; */ | |||||
LINK("l3-aon-clkctrl@14_0"), | |||||
/* reg = <0xb0 0x4>; */ | |||||
LINK("l4-wkup-aon-clkctrl@b0_0"), | |||||
/* reg = <0x0 0x8>; */ | |||||
LINK("mpu-clkctrl@0_0"), | |||||
LINK("mpu-clkctrl@0_4"), | |||||
/* reg = <0x0 0x4>; */ | |||||
LINK("l4-rtc-clkctrl@0_0"), | |||||
/* reg = <0x0 0x8>; */ | |||||
LINK("gfx-l3-clkctrl@0_0"), | |||||
LINK("gfx-l3-clkctrl@0_4"), | |||||
/* reg = <0x0 0x24>; */ | |||||
LINK("l4-cefuse-clkctrl@0_0"), | |||||
LINK("l4-cefuse-clkctrl@0_4"), | |||||
LINK("l4-cefuse-clkctrl@0_8"), | |||||
LINK("l4-cefuse-clkctrl@0_c"), | |||||
LINK("l4-cefuse-clkctrl@0_10"), | |||||
LINK("l4-cefuse-clkctrl@0_14"), | |||||
LINK("l4-cefuse-clkctrl@0_18"), | |||||
LINK("l4-cefuse-clkctrl@0_1c"), | |||||
LINK("l4-cefuse-clkctrl@0_20"), | |||||
}; | |||||
/* reg-names can be "rev", "sysc" and "syss" */ | /* reg-names can be "rev", "sysc" and "syss" */ | ||||
static const char * reg_names[] = { "rev", "sysc", "syss" }; | static const char * reg_names[] = { "rev", "sysc", "syss" }; | ||||
#define REG_REV 0 | #define REG_REV 0 | ||||
#define REG_SYSC 1 | #define REG_SYSC 1 | ||||
#define REG_SYSS 2 | #define REG_SYSS 2 | ||||
#define REG_MAX 3 | #define REG_MAX 3 | ||||
/* master idle / slave idle mode defined in 8.1.3.2.1 / 8.1.3.2.2 */ | /* master idle / slave idle mode defined in 8.1.3.2.1 / 8.1.3.2.2 */ | ||||
#include <dt-bindings/bus/ti-sysc.h> | #include <dt-bindings/bus/ti-sysc.h> | ||||
#define SYSC_IDLE_MAX 4 | #define SYSC_IDLE_MAX 4 | ||||
struct sysc_reg { | struct sysc_reg { | ||||
uint64_t address; | uint64_t address; | ||||
uint64_t size; | uint64_t size; | ||||
}; | }; | ||||
struct clk_list { | struct clk_list { | ||||
TAILQ_ENTRY(clk_list) next; | TAILQ_ENTRY(clk_list) next; | ||||
clk_t clk; | clk_t clk; | ||||
}; | }; | ||||
struct ti_sysc_softc { | struct ti_sysc_softc { | ||||
struct simplebus_softc sc; | struct simplebus_softc sc; | ||||
bool attach_done; | |||||
device_t dev; | device_t dev; | ||||
int device_type; | int device_type; | ||||
struct sysc_reg reg[REG_MAX]; | struct sysc_reg reg[REG_MAX]; | ||||
/* Offset from host base address */ | /* Offset from host base address */ | ||||
uint64_t offset_reg[REG_MAX]; | uint64_t offset_reg[REG_MAX]; | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | |||||
ti_sysc_clock_enable(device_t dev) { | ti_sysc_clock_enable(device_t dev) { | ||||
struct clk_list *clkp, *clkp_tmp; | struct clk_list *clkp, *clkp_tmp; | ||||
struct ti_sysc_softc *sc = device_get_softc(dev); | struct ti_sysc_softc *sc = device_get_softc(dev); | ||||
int err; | int err; | ||||
TAILQ_FOREACH_SAFE(clkp, &sc->clk_list, next, clkp_tmp) { | TAILQ_FOREACH_SAFE(clkp, &sc->clk_list, next, clkp_tmp) { | ||||
err = clk_enable(clkp->clk); | err = clk_enable(clkp->clk); | ||||
if (err) { | if (err != 0) { | ||||
DPRINTF(sc->dev, "clk_enable %s failed %d\n", | DPRINTF(sc->dev, "clk_enable %s failed %d\n", | ||||
clk_get_name(clkp->clk), err); | clk_get_name(clkp->clk), err); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
return (err); | return (err); | ||||
} | } | ||||
int | int | ||||
ti_sysc_clock_disable(device_t dev) { | ti_sysc_clock_disable(device_t dev) { | ||||
struct clk_list *clkp, *clkp_tmp; | struct clk_list *clkp, *clkp_tmp; | ||||
struct ti_sysc_softc *sc = device_get_softc(dev); | struct ti_sysc_softc *sc = device_get_softc(dev); | ||||
int err = 0; | int err = 0; | ||||
TAILQ_FOREACH_SAFE(clkp, &sc->clk_list, next, clkp_tmp) { | TAILQ_FOREACH_SAFE(clkp, &sc->clk_list, next, clkp_tmp) { | ||||
err = clk_disable(clkp->clk); | err = clk_disable(clkp->clk); | ||||
if (err) { | if (err != 0) { | ||||
DPRINTF(sc->dev, "clk_enable %s failed %d\n", | DPRINTF(sc->dev, "clk_enable %s failed %d\n", | ||||
clk_get_name(clkp->clk), err); | clk_get_name(clkp->clk), err); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
return (err); | return (err); | ||||
} | } | ||||
static int | static int | ||||
parse_regfields(struct ti_sysc_softc *sc) { | parse_regfields(struct ti_sysc_softc *sc) { | ||||
phandle_t node; | phandle_t node; | ||||
uint32_t parent_address_cells; | uint32_t parent_address_cells; | ||||
uint32_t parent_size_cells; | uint32_t parent_size_cells; | ||||
cell_t *reg; | cell_t *reg; | ||||
ssize_t nreg; | ssize_t nreg; | ||||
int err, k, reg_i, prop_idx; | int err, k, reg_i, prop_idx; | ||||
uint32_t idx; | uint32_t idx; | ||||
/* Make sure address & size are 0 */ | |||||
for (idx = 0; idx < REG_MAX; idx++) { | |||||
sc->reg[idx].address = 0; | |||||
sc->reg[idx].size = 0; | |||||
} | |||||
node = ofw_bus_get_node(sc->dev); | node = ofw_bus_get_node(sc->dev); | ||||
/* Ensure its a reg node at all */ | |||||
if (!ofw_bus_has_prop(sc->dev, "reg")) | |||||
/* Silently ignore for now */ | |||||
return (0); | |||||
/* Get parents address and size properties */ | /* Get parents address and size properties */ | ||||
err = OF_searchencprop(OF_parent(node), "#address-cells", | err = OF_searchencprop(OF_parent(node), "#address-cells", | ||||
&parent_address_cells, sizeof(parent_address_cells)); | &parent_address_cells, sizeof(parent_address_cells)); | ||||
if (err == -1) | if (err == -1) | ||||
return (ENXIO); | return (ENXIO); | ||||
if (!(parent_address_cells == 1 || parent_address_cells == 2)) { | if (!(parent_address_cells == 1 || parent_address_cells == 2)) { | ||||
DPRINTF(sc->dev, "Expect parent #address-cells=[1||2]\n"); | DPRINTF(sc->dev, "Expect parent #address-cells=[1||2]\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
Show All 12 Lines | parse_regfields(struct ti_sysc_softc *sc) { | ||||
/* Grab the content of reg properties */ | /* Grab the content of reg properties */ | ||||
nreg = OF_getproplen(node, "reg"); | nreg = OF_getproplen(node, "reg"); | ||||
if (nreg <= 0) | if (nreg <= 0) | ||||
return (ENXIO); | return (ENXIO); | ||||
reg = malloc(nreg, M_DEVBUF, M_WAITOK); | reg = malloc(nreg, M_DEVBUF, M_WAITOK); | ||||
OF_getencprop(node, "reg", reg, nreg); | OF_getencprop(node, "reg", reg, nreg); | ||||
/* Make sure address & size are 0 */ | |||||
for (idx = 0; idx < REG_MAX; idx++) { | |||||
sc->reg[idx].address = 0; | |||||
sc->reg[idx].size = 0; | |||||
} | |||||
/* Loop through reg-names and figure out which reg-name corresponds to | /* Loop through reg-names and figure out which reg-name corresponds to | ||||
* index populate the values into the reg array. | * index populate the values into the reg array. | ||||
*/ | */ | ||||
for (idx = 0, reg_i = 0; idx < REG_MAX && reg_i < nreg; idx++) { | for (idx = 0, reg_i = 0; idx < REG_MAX && reg_i < nreg; idx++) { | ||||
err = ofw_bus_find_string_index(node, "reg-names", | err = ofw_bus_find_string_index(node, "reg-names", | ||||
reg_names[idx], &prop_idx); | reg_names[idx], &prop_idx); | ||||
if (err != 0) | if (err != 0) | ||||
continue; | continue; | ||||
Show All 15 Lines | else | ||||
sc->sc.ranges[REG_REV].host; | sc->sc.ranges[REG_REV].host; | ||||
DPRINTF(sc->dev, "reg[%s] address %#jx size %#jx\n", | DPRINTF(sc->dev, "reg[%s] address %#jx size %#jx\n", | ||||
reg_names[idx], | reg_names[idx], | ||||
sc->reg[prop_idx].address, | sc->reg[prop_idx].address, | ||||
sc->reg[prop_idx].size); | sc->reg[prop_idx].size); | ||||
} | } | ||||
free(reg, M_DEVBUF); | free(reg, M_DEVBUF); | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
parse_idle(struct ti_sysc_softc *sc, const char *name, uint32_t *idle) { | parse_idle(struct ti_sysc_softc *sc, const char *name, uint32_t *idle) { | ||||
phandle_t node; | phandle_t node; | ||||
cell_t value[SYSC_IDLE_MAX]; | cell_t value[SYSC_IDLE_MAX]; | ||||
int len, no, i; | int len, no, i; | ||||
node = ofw_bus_get_node(sc->dev); | node = ofw_bus_get_node(sc->dev); | ||||
if (!OF_hasprop(node, name)) { | if (OF_hasprop(node, name) == 0) | ||||
return; | return; | ||||
} | |||||
len = OF_getproplen(node, name); | len = OF_getproplen(node, name); | ||||
no = len / sizeof(cell_t); | no = len / sizeof(cell_t); | ||||
if (no >= SYSC_IDLE_MAX) { | if (no >= SYSC_IDLE_MAX) { | ||||
DPRINTF(sc->dev, "Limit %s\n", name); | DPRINTF(sc->dev, "Limit %s\n", name); | ||||
no = SYSC_IDLE_MAX-1; | no = SYSC_IDLE_MAX-1; | ||||
len = no * sizeof(cell_t); | len = no * sizeof(cell_t); | ||||
} | } | ||||
Show All 20 Lines | #if DEBUG_SYSC | ||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
for ( ; i < SYSC_IDLE_MAX; i++) | for ( ; i < SYSC_IDLE_MAX; i++) | ||||
idle[i] = -1; | idle[i] = -1; | ||||
} | } | ||||
static int | static int | ||||
ti_sysc_attach_clocks(struct ti_sysc_softc *sc) { | |||||
clk_t *clk; | |||||
struct clk_list *clkp; | |||||
int index, err; | |||||
clk = malloc(sc->num_clocks*sizeof(clk_t), M_DEVBUF, M_WAITOK | M_ZERO); | |||||
/* Check if all clocks can be found */ | |||||
for (index = 0; index < sc->num_clocks; index++) { | |||||
err = clk_get_by_ofw_index(sc->dev, 0, index, &clk[index]); | |||||
if (err != 0) { | |||||
free(clk, M_DEVBUF); | |||||
return (1); | |||||
} | |||||
} | |||||
/* All clocks are found, add to list */ | |||||
for (index = 0; index < sc->num_clocks; index++) { | |||||
clkp = malloc(sizeof(*clkp), M_DEVBUF, M_WAITOK | M_ZERO); | |||||
clkp->clk = clk[index]; | |||||
TAILQ_INSERT_TAIL(&sc->clk_list, clkp, next); | |||||
} | |||||
/* Release the clk array */ | |||||
free(clk, M_DEVBUF); | |||||
return (0); | |||||
} | |||||
static int | |||||
ti_sysc_simplebus_attach_child(device_t dev) { | ti_sysc_simplebus_attach_child(device_t dev) { | ||||
device_t cdev; | device_t cdev; | ||||
phandle_t node, child; | phandle_t node, child; | ||||
struct ti_sysc_softc *sc = device_get_softc(dev); | struct ti_sysc_softc *sc = device_get_softc(dev); | ||||
node = ofw_bus_get_node(sc->dev); | node = ofw_bus_get_node(sc->dev); | ||||
for (child = OF_child(node); child > 0; child = OF_peer(child)) { | for (child = OF_child(node); child > 0; child = OF_peer(child)) { | ||||
Show All 10 Lines | |||||
{ | { | ||||
if (!ofw_bus_status_okay(dev)) | if (!ofw_bus_status_okay(dev)) | ||||
return (ENXIO); | return (ENXIO); | ||||
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) | if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) | ||||
return (ENXIO); | return (ENXIO); | ||||
device_set_desc(dev, "TI SYSC Interconnect"); | device_set_desc(dev, "TI SYSC Interconnect"); | ||||
if (bootverbose == 0) | |||||
device_quiet(dev); | |||||
return (BUS_PROBE_DEFAULT); | return (BUS_PROBE_DEFAULT); | ||||
} | } | ||||
static void | |||||
ti_sysc_init_clk_links(device_t dev) { | |||||
int chip_id; | |||||
int i, err; | |||||
struct clkdom *clkdom; | |||||
device_t child; | |||||
device_t root_dev = dev; | |||||
device_t tmp_dev; | |||||
/* find device root to attach the imaginary ti_clkinit. | |||||
* Its used to create clk_link for future clocks. | |||||
*/ | |||||
while (1) { | |||||
tmp_dev = device_get_parent(root_dev); | |||||
if (tmp_dev == NULL) | |||||
break; | |||||
root_dev = tmp_dev; | |||||
} | |||||
/* If ti_clkinitX already exist the links are already created */ | |||||
if (device_find_child(root_dev, "ti_clkinit", -1) != NULL) | |||||
return; | |||||
/* otherwise add ti_clkinit as a child to the root */ | |||||
child = device_add_child(root_dev, "ti_clkinit", -1); | |||||
if (child == NULL) | |||||
panic("Cant add ti_clkinit\n"); | |||||
clkdom = clkdom_create(dev); | |||||
if (clkdom == NULL) | |||||
panic("Cannot create clkdom\n"); | |||||
chip_id = ti_chip(); | |||||
if (chip_id == CHIP_AM335X) { | |||||
/* | |||||
* pre-create clocks to get handles to parents | |||||
* before they actually exists | |||||
*/ | |||||
for (i = 0; i < nitems(scm_clocks); i++) { | |||||
err = clknode_link_register(clkdom, | |||||
&scm_clocks[i]); | |||||
if (err != 0) | |||||
device_printf(dev, "Cant create clock link %s\n", | |||||
scm_clocks[i].clkdef.name); | |||||
} | |||||
for (i = 0; i < nitems(per_cm_0); i++) { | |||||
err = clknode_link_register(clkdom, | |||||
&per_cm_0[i]); | |||||
if (err != 0) | |||||
device_printf(dev, "Cant create clock link %s\n", | |||||
per_cm_0[i].clkdef.name); | |||||
} | |||||
} | |||||
else if (chip_id == CHIP_OMAP_4) | |||||
device_printf(dev, "Todo - add clock support"); | |||||
if (clkdom_finit(clkdom) != 0) | |||||
panic("cannot finalize clkdom initialization\n"); | |||||
} | |||||
static int | static int | ||||
ti_sysc_attach(device_t dev) | ti_sysc_attach(device_t dev) | ||||
{ | { | ||||
struct ti_sysc_softc *sc; | struct ti_sysc_softc *sc; | ||||
phandle_t node; | phandle_t node; | ||||
int err; | int err; | ||||
cell_t value; | cell_t value; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
sc->dev = dev; | sc->dev = dev; | ||||
sc->device_type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; | sc->device_type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; | ||||
ti_sysc_init_clk_links(dev); | |||||
node = ofw_bus_get_node(sc->dev); | node = ofw_bus_get_node(sc->dev); | ||||
/* ranges - use simplebus */ | /* ranges - use simplebus */ | ||||
simplebus_init(sc->dev, node); | simplebus_init(sc->dev, node); | ||||
if (simplebus_fill_ranges(node, &sc->sc) < 0) { | if (simplebus_fill_ranges(node, &sc->sc) < 0) { | ||||
DPRINTF(sc->dev, "could not get ranges\n"); | DPRINTF(sc->dev, "could not get ranges\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
if (sc->sc.nranges == 0) { | if (sc->sc.nranges == 0) { | ||||
DPRINTF(sc->dev, "nranges == 0\n"); | DPRINTF(sc->dev, "nranges == 0\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
/* Required field reg & reg-names - assume at least "rev" exists */ | /* Required field reg & reg-names - assume at least "rev" exists */ | ||||
err = parse_regfields(sc); | err = parse_regfields(sc); | ||||
if (err) { | if (err != 0) { | ||||
DPRINTF(sc->dev, "parse_regfields failed %d\n", err); | DPRINTF(sc->dev, "parse_regfields failed %d\n", err); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
/* Optional */ | /* Optional */ | ||||
if (OF_hasprop(node, "ti,sysc-mask")) { | if (OF_hasprop(node, "ti,sysc-mask") == 1) { | ||||
OF_getencprop(node, "ti,sysc-mask", &value, sizeof(cell_t)); | OF_getencprop(node, "ti,sysc-mask", &value, sizeof(cell_t)); | ||||
sc->ti_sysc_mask = value; | sc->ti_sysc_mask = value; | ||||
} | } | ||||
if (OF_hasprop(node, "ti,syss-mask")) { | if (OF_hasprop(node, "ti,syss-mask") == 1) { | ||||
OF_getencprop(node, "ti,syss-mask", &value, sizeof(cell_t)); | OF_getencprop(node, "ti,syss-mask", &value, sizeof(cell_t)); | ||||
sc->ti_syss_mask = value; | sc->ti_syss_mask = value; | ||||
} | } | ||||
if (OF_hasprop(node, "ti,sysc-delay-us")) { | if (OF_hasprop(node, "ti,sysc-delay-us") == 1) { | ||||
OF_getencprop(node, "ti,sysc-delay-us", &value, sizeof(cell_t)); | OF_getencprop(node, "ti,sysc-delay-us", &value, sizeof(cell_t)); | ||||
sc->ti_sysc_delay_us = value; | sc->ti_sysc_delay_us = value; | ||||
} | } | ||||
DPRINTF(sc->dev, "sysc_mask %x syss_mask %x delay_us %x\n", | DPRINTF(sc->dev, "sysc_mask %x syss_mask %x delay_us %x\n", | ||||
sc->ti_sysc_mask, sc->ti_syss_mask, sc->ti_sysc_delay_us); | sc->ti_sysc_mask, sc->ti_syss_mask, sc->ti_sysc_delay_us); | ||||
parse_idle(sc, "ti,sysc-midle", sc->ti_sysc_midle); | parse_idle(sc, "ti,sysc-midle", sc->ti_sysc_midle); | ||||
parse_idle(sc, "ti,sysc-sidle", sc->ti_sysc_sidle); | parse_idle(sc, "ti,sysc-sidle", sc->ti_sysc_sidle); | ||||
if (OF_hasprop(node, "ti,no-reset-on-init")) | if (OF_hasprop(node, "ti,no-reset-on-init") == 1) | ||||
sc->ti_no_reset_on_init = true; | sc->ti_no_reset_on_init = true; | ||||
else | else | ||||
sc->ti_no_reset_on_init = false; | sc->ti_no_reset_on_init = false; | ||||
if (OF_hasprop(node, "ti,no-idle-on-init")) | if (OF_hasprop(node, "ti,no-idle-on-init") == 1) | ||||
sc->ti_no_idle_on_init = true; | sc->ti_no_idle_on_init = true; | ||||
else | else | ||||
sc->ti_no_idle_on_init = false; | sc->ti_no_idle_on_init = false; | ||||
if (OF_hasprop(node, "ti,no-idle")) | if (OF_hasprop(node, "ti,no-idle") == 1) | ||||
sc->ti_no_idle = true; | sc->ti_no_idle = true; | ||||
else | else | ||||
sc->ti_no_idle = false; | sc->ti_no_idle = false; | ||||
DPRINTF(sc->dev, | DPRINTF(sc->dev, | ||||
"no-reset-on-init %d, no-idle-on-init %d, no-idle %d\n", | "no-reset-on-init %d, no-idle-on-init %d, no-idle %d\n", | ||||
sc->ti_no_reset_on_init, | sc->ti_no_reset_on_init, | ||||
sc->ti_no_idle_on_init, | sc->ti_no_idle_on_init, | ||||
sc->ti_no_idle); | sc->ti_no_idle); | ||||
if (OF_hasprop(node, "clocks")) { | if (OF_hasprop(node, "clocks") == 1) { | ||||
struct clock_cell_info cell_info; | int idx, clk_idx; | ||||
read_clock_cells(sc->dev, &cell_info); | const char *name = ofw_bus_get_name(dev); | ||||
free(cell_info.clock_cells, M_DEVBUF); | |||||
free(cell_info.clock_cells_ncells, M_DEVBUF); | |||||
sc->num_clocks = cell_info.num_real_clocks; | for (idx = 0; idx < nitems(sysc_clock_table); idx++) { | ||||
if (strcmp(sysc_clock_table[idx].node_name, name)==0) | |||||
break; | |||||
} | |||||
if (idx == nitems(sysc_clock_table)) | |||||
panic("Cant find clocks for node %s\n", name); | |||||
DPRINTF(dev, "%s at sysc_clock_table[%d]\n", name, idx); | |||||
/* | |||||
* Found the correct place in the lookup table. | |||||
* Loop through and get the clocks | |||||
*/ | |||||
TAILQ_INIT(&sc->clk_list); | TAILQ_INIT(&sc->clk_list); | ||||
sc->num_clocks = sysc_clock_table[idx].parent_cnt; | |||||
clk_idx = 0; | |||||
for (; clk_idx < sysc_clock_table[idx].parent_cnt; clk_idx++) { | |||||
struct clk_list *clkp; | |||||
clkp = malloc(sizeof(*clkp), M_DEVBUF, | |||||
M_WAITOK | M_ZERO); | |||||
err = ti_sysc_attach_clocks(sc); | err = clk_get_by_name(dev, | ||||
if (err) { | sysc_clock_table[idx].parent_names[clk_idx], | ||||
DPRINTF(sc->dev, "Failed to attach clocks\n"); | &clkp->clk); | ||||
return (bus_generic_attach(sc->dev)); | if (err != 0) | ||||
panic("Cant get clock %s err %d", | |||||
sysc_clock_table[idx].parent_names[clk_idx], | |||||
err); | |||||
TAILQ_INSERT_TAIL(&sc->clk_list, clkp, next); | |||||
} | } | ||||
} | } | ||||
err = ti_sysc_simplebus_attach_child(sc->dev); | err = ti_sysc_simplebus_attach_child(sc->dev); | ||||
if (err) { | if (err != 0) { | ||||
DPRINTF(sc->dev, "ti_sysc_simplebus_attach_child %d\n", | DPRINTF(sc->dev, "ti_sysc_simplebus_attach_child %d\n", | ||||
err); | err); | ||||
return (err); | return (err); | ||||
} | } | ||||
sc->attach_done = true; | |||||
return (bus_generic_attach(sc->dev)); | return (bus_generic_attach(sc->dev)); | ||||
} | } | ||||
static int | static int | ||||
ti_sysc_detach(device_t dev) | ti_sysc_detach(device_t dev) | ||||
{ | { | ||||
return (EBUSY); | return (EBUSY); | ||||
} | } | ||||
/* Bus interface */ | |||||
static void | |||||
ti_sysc_new_pass(device_t dev) | |||||
{ | |||||
struct ti_sysc_softc *sc; | |||||
int err; | |||||
phandle_t node; | |||||
sc = device_get_softc(dev); | |||||
if (sc->attach_done) { | |||||
bus_generic_new_pass(sc->dev); | |||||
return; | |||||
} | |||||
node = ofw_bus_get_node(sc->dev); | |||||
if (OF_hasprop(node, "clocks")) { | |||||
err = ti_sysc_attach_clocks(sc); | |||||
if (err) { | |||||
DPRINTF(sc->dev, "Failed to attach clocks\n"); | |||||
return; | |||||
} | |||||
} | |||||
err = ti_sysc_simplebus_attach_child(sc->dev); | |||||
if (err) { | |||||
DPRINTF(sc->dev, | |||||
"ti_sysc_simplebus_attach_child failed %d\n", err); | |||||
return; | |||||
} | |||||
sc->attach_done = true; | |||||
bus_generic_attach(sc->dev); | |||||
} | |||||
static device_method_t ti_sysc_methods[] = { | static device_method_t ti_sysc_methods[] = { | ||||
/* Device interface */ | /* Device interface */ | ||||
DEVMETHOD(device_probe, ti_sysc_probe), | DEVMETHOD(device_probe, ti_sysc_probe), | ||||
DEVMETHOD(device_attach, ti_sysc_attach), | DEVMETHOD(device_attach, ti_sysc_attach), | ||||
DEVMETHOD(device_detach, ti_sysc_detach), | DEVMETHOD(device_detach, ti_sysc_detach), | ||||
/* Bus interface */ | |||||
DEVMETHOD(bus_new_pass, ti_sysc_new_pass), | |||||
DEVMETHOD_END | DEVMETHOD_END | ||||
}; | }; | ||||
DEFINE_CLASS_1(ti_sysc, ti_sysc_driver, ti_sysc_methods, | DEFINE_CLASS_1(ti_sysc, ti_sysc_driver, ti_sysc_methods, | ||||
sizeof(struct ti_sysc_softc), simplebus_driver); | sizeof(struct ti_sysc_softc), simplebus_driver); | ||||
EARLY_DRIVER_MODULE(ti_sysc, simplebus, ti_sysc_driver, 0, 0, | EARLY_DRIVER_MODULE(ti_sysc, simplebus, ti_sysc_driver, 0, 0, | ||||
BUS_PASS_BUS + BUS_PASS_ORDER_FIRST); | BUS_PASS_BUS + BUS_PASS_ORDER_LATE); |