Changeset View
Changeset View
Standalone View
Standalone View
sys/arm/ti/ti_sysc.c
Show First 20 Lines • Show All 106 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_38000) = { "l3s-clkctrl@1c_18" }; /* mcasp0 */ | |||||
PLIST(target_module_3c000) = { "l3s-clkctrl@1c_4c" }; /* mcasp1 */ | |||||
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_49000000) = { "l3-clkctrl@24_98" }; /* tpcc */ | |||||
PLIST(target_module_49800000) = { "l3-clkctrl@24_0" }; /* tptco */ | |||||
PLIST(target_module_49900000) = { "l3-clkctrl@24_d8" }; /* tptc1 */ | |||||
PLIST(target_module_49a00000) = { "l3-clkctrl@24_dc" }; /* tptc2 */ | |||||
PLIST(target_module_47810000) = { "l3s-clkctrl@1c_dc" }; /* mmc3 */ | |||||
PLIST(target_module_47400000) = { "l3s-clkctrl@1c_0" }; /* usb otg hs */ | |||||
PLIST(target_module_53100000) = { "l3-clkctrl@24_7c" }; /* sham */ | |||||
PLIST(target_module_53500000) = { "l3-clkctrl@24_70" }; /* aes */ | |||||
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@38000", | |||||
nitems(target_module_38000), | |||||
target_module_38000 | |||||
}, | |||||
{ | |||||
"target-module@3c000", | |||||
nitems(target_module_3c000), | |||||
target_module_3c000 | |||||
}, | |||||
{ | |||||
"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@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@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 | |||||
}, | |||||
}; | |||||
/* 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); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | else | ||||
sc->sc.ranges[REG_REV].host; | sc->sc.ranges[REG_REV].host; | ||||
DPRINTF(sc->dev, "reg[%s] adress %#jx size %#jx\n", | DPRINTF(sc->dev, "reg[%s] adress %#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; | |||||
phandle_t cnode; | |||||
clk = malloc(sc->num_clocks*sizeof(clk_t), M_DEVBUF, M_WAITOK | M_ZERO); | |||||
cnode = ofw_bus_get_node(sc->dev); | |||||
/* 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 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | ti_sysc_attach(device_t dev) | ||||
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); | DPRINTF(dev, "%s has clock\n", name); | ||||
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); | ||||
static devclass_t ti_sysc_devclass; | static devclass_t ti_sysc_devclass; | ||||
EARLY_DRIVER_MODULE(ti_sysc, simplebus, ti_sysc_driver, | EARLY_DRIVER_MODULE(ti_sysc, simplebus, ti_sysc_driver, | ||||
ti_sysc_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_FIRST); | ti_sysc_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_LATE); |