diff --git a/sys/arm/ti/am335x/am335x_gpio.c b/sys/arm/ti/am335x/am335x_gpio.c --- a/sys/arm/ti/am335x/am335x_gpio.c +++ b/sys/arm/ti/am335x/am335x_gpio.c @@ -153,6 +153,6 @@ DEFINE_CLASS_1(gpio, am335x_gpio_driver, am335x_gpio_methods, sizeof(struct ti_gpio_softc), ti_gpio_driver); -DRIVER_MODULE(am335x_gpio, simplebus, am335x_gpio_driver, am335x_gpio_devclass, - 0, 0); +EARLY_DRIVER_MODULE(am335x_gpio, simplebus, am335x_gpio_driver, am335x_gpio_devclass, + 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); MODULE_DEPEND(am335x_gpio, ti_sysc, 1, 1, 1); diff --git a/sys/arm/ti/clk/clock_common.h b/sys/arm/ti/clk/clock_common.h --- a/sys/arm/ti/clk/clock_common.h +++ b/sys/arm/ti/clk/clock_common.h @@ -30,14 +30,20 @@ #include __FBSDID("$FreeBSD$"); -struct clock_cell_info { - cell_t *clock_cells; - uint8_t *clock_cells_ncells; - uint32_t num_clock_cells; - uint8_t num_real_clocks; +struct parent_lookup_table { + const char *node_name; + int parent_cnt; + const char **parent_names; }; -void read_clock_cells(device_t dev, struct clock_cell_info *clk); -int find_parent_clock_names(device_t dev, struct clock_cell_info *clk, struct clknode_init_def *def); -void create_clkdef(device_t dev, struct clock_cell_info *clk, struct clknode_init_def *def); -void free_clkdef(struct clknode_init_def *def); +/* From rk3399_cru.c & rk_cru.c */ +#define PLIST(x) static const char *x[] + +#define LINK(_name) \ +{ \ + .clkdef.id = 0, \ + .clkdef.name = _name, \ + .clkdef.parent_names = NULL, \ + .clkdef.parent_cnt = 0, \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ +} diff --git a/sys/arm/ti/clk/clock_common.c b/sys/arm/ti/clk/clock_common.c deleted file mode 100644 --- a/sys/arm/ti/clk/clock_common.c +++ /dev/null @@ -1,152 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2020 Oskar Holmlund - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "clock_common.h" - -#if 0 -#define DPRINTF(dev, msg...) device_printf(dev, msg) -#else -#define DPRINTF(dev, msg...) -#endif - -void -read_clock_cells(device_t dev, struct clock_cell_info *clk) { - ssize_t numbytes_clocks; - phandle_t node, parent, *cells; - int index, ncells, rv; - - node = ofw_bus_get_node(dev); - - /* Get names of parent clocks */ - numbytes_clocks = OF_getproplen(node, "clocks"); - clk->num_clock_cells = numbytes_clocks / sizeof(cell_t); - - /* Allocate space and get clock cells content */ - /* clock_cells / clock_cells_ncells will be freed in - * find_parent_clock_names() - */ - clk->clock_cells = malloc(numbytes_clocks, M_DEVBUF, M_WAITOK|M_ZERO); - clk->clock_cells_ncells = malloc(clk->num_clock_cells*sizeof(uint8_t), - M_DEVBUF, M_WAITOK|M_ZERO); - OF_getencprop(node, "clocks", clk->clock_cells, numbytes_clocks); - - /* Count number of clocks */ - clk->num_real_clocks = 0; - for (index = 0; index < clk->num_clock_cells; index++) { - rv = ofw_bus_parse_xref_list_alloc(node, "clocks", "#clock-cells", - clk->num_real_clocks, &parent, &ncells, &cells); - if (rv != 0) - continue; - - if (cells != NULL) - OF_prop_free(cells); - - clk->clock_cells_ncells[index] = ncells; - index += ncells; - clk->num_real_clocks++; - } -} - -int -find_parent_clock_names(device_t dev, struct clock_cell_info *clk, struct clknode_init_def *def) { - int index, clock_index, err; - bool found_all = true; - clk_t parent; - - /* Figure out names */ - for (index = 0, clock_index = 0; index < clk->num_clock_cells; index++) { - /* Get name of parent clock */ - err = clk_get_by_ofw_index(dev, 0, clock_index, &parent); - if (err != 0) { - clock_index++; - found_all = false; - DPRINTF(dev, "Failed to find clock_cells[%d]=0x%x\n", - index, clk->clock_cells[index]); - - index += clk->clock_cells_ncells[index]; - continue; - } - - def->parent_names[clock_index] = clk_get_name(parent); - clk_release(parent); - - DPRINTF(dev, "Found parent clock[%d/%d]: %s\n", - clock_index, clk->num_real_clocks, - def->parent_names[clock_index]); - - clock_index++; - index += clk->clock_cells_ncells[index]; - } - - if (!found_all) { - return 1; - } - - free(clk->clock_cells, M_DEVBUF); - free(clk->clock_cells_ncells, M_DEVBUF); - return 0; -} - -void -create_clkdef(device_t dev, struct clock_cell_info *clk, struct clknode_init_def *def) { - def->id = 1; - - clk_parse_ofw_clk_name(dev, ofw_bus_get_node(dev), &def->name); - - DPRINTF(dev, "node name: %s\n", def->name); - - def->parent_cnt = clk->num_real_clocks; - def->parent_names = malloc(clk->num_real_clocks*sizeof(char *), - M_OFWPROP, M_WAITOK); -} -void -free_clkdef(struct clknode_init_def *def) { - OF_prop_free(__DECONST(char *, def->name)); - OF_prop_free(def->parent_names); -} diff --git a/sys/arm/ti/clk/ti_clk_clkctrl.c b/sys/arm/ti/clk/ti_clk_clkctrl.c --- a/sys/arm/ti/clk/ti_clk_clkctrl.c +++ b/sys/arm/ti/clk/ti_clk_clkctrl.c @@ -102,6 +102,7 @@ sc = clknode_get_softc(clk); + DEVICE_LOCK(clk); READ4(clk, sc->register_offset, &val); DPRINTF(sc->dev, "val(%x) & (%x | %x = %x)\n", val, GPIO_X_GDBCLK_MASK, MODULEMODE_MASK, @@ -129,6 +130,8 @@ DELAY(10); timeout--; } + DEVICE_UNLOCK(clk); + if (timeout == 0) { device_printf(sc->dev, "ti_clkctrl_set_gdbclk_gate: Timeout\n"); return (1); @@ -151,7 +154,7 @@ err = ti_clkctrl_set_gdbclk_gate(clk, enable); return (err); } - + DEVICE_LOCK(clk); READ4(clk, sc->register_offset, &val); if (enable) @@ -175,6 +178,7 @@ timeout--; } + DEVICE_UNLOCK(clk); if (timeout == 0) { device_printf(sc->dev, "ti_clkctrl_set_gate: Timeout\n"); return (1); diff --git a/sys/arm/ti/clk/ti_clkctrl.c b/sys/arm/ti/clk/ti_clkctrl.c --- a/sys/arm/ti/clk/ti_clkctrl.c +++ b/sys/arm/ti/clk/ti_clkctrl.c @@ -51,6 +51,7 @@ #include #include +#include #include #include #include @@ -89,6 +90,309 @@ struct clkdom *clkdom; }; +/* reg = <0x38 0x2c>, <0x6c 0x28>, <0xac 0xc>, <0xc0 0x1c>, <0xec 0xc>, <0x10c 0x8>, <0x130 0x4>; */ +/* <0x38 0x2c> */ +PLIST(l4ls_clkctrl_38_0) = { "dpll_per_m2_div4_ck" }; /* am3.h UART6 clkctrl, TRM 19.2.2 */ +PLIST(l4ls_clkctrl_38_4) = { "mmc_clk" }; /* am3.h MMC1 clkctrl, TRM 18.2.2 */ +PLIST(l4ls_clkctrl_38_8) = { "l4ls_gclk" }; /* am3.h ELM clkctrl, TRM 7.4.2.2 */ +PLIST(l4ls_clkctrl_38_c) = { "dpll_per_m2_div4_ck" }; /* am3.h I2C3 clkctrl, TRM 21.2.2 */ +PLIST(l4ls_clkctrl_38_10) = { "dpll_per_m2_div4_ck" }; /* am3.h I2C2 clkctrl, TRM 21.2.2 */ +PLIST(l4ls_clkctrl_38_14) = { "dpll_per_m2_div4_ck" }; /* am3.h SPI0 clkctrl, TRM 24.2.2 */ +PLIST(l4ls_clkctrl_38_18) = { "dpll_per_m2_div4_ck" }; /* am3.h SPI1 clkctrl, TRM 24.2.2 */ +/* 1c, 20, 24 are not described in the TRM */ +//PLIST(l4ls_clkctrl_38_1c) = { NULL }; /* am3.h TRM ? */ +//PLIST(l4ls_clkctrl_38_20) = { NULL }; /* am3.h TRM ? */ +//PLIST(l4ls_clkctrl_38_24) = { NULL }; /* am3.h TRM ? */ +PLIST(l4ls_clkctrl_38_28) = { "l4ls_gclk" }; /* am3.h L4_LS clkctrl, TRM 8.1.12.1.19 */ +/* <0x6c 0x28> */ +PLIST(l4ls_clkctrl_38_34) = { "dpll_per_m2_div4_ck" }; /* am3.h UART2 clkctrl, TRM 19.2.2 */ +PLIST(l4ls_clkctrl_38_38) = { "dpll_per_m2_div4_ck" }; /* am3.h UART3 clkctrl, TRM 19.2.2 */ +PLIST(l4ls_clkctrl_38_3c) = { "dpll_per_m2_div4_ck" }; /* am3.h UART4 clkctrl, TRM 19.2.2 */ +PLIST(l4ls_clkctrl_38_40) = { "dpll_per_m2_div4_ck" }; /* am3.h UART4 clkctrl, TRM 19.2.2 */ +PLIST(l4ls_clkctrl_38_44) = { "dpll_per_m2_div4_ck" }; /* am3.h UART5 clkctrl, TRM 19.2.2 */ +PLIST(l4ls_clkctrl_38_48) = { "timer7_fck@504" }; /* am3.h TIMER7 clkctrl, TRM 20.1.2.3 */ +PLIST(l4ls_clkctrl_38_4c) = { "timer2_fck@508" }; /* am3.h TIMER2 clkctrl, TRM 20.1.2.3 */ +PLIST(l4ls_clkctrl_38_50) = { "timer3_fck@50c" }; /* am3.h TIMER3 clkctrl, TRM 20.1.2.3 */ +PLIST(l4ls_clkctrl_38_54) = { "timer4_fck@510" }; /* am3.h TIMER4 clkctrl, TRM 20.1.2.3 */ +PLIST(l4ls_clkctrl_38_58) = { "rng_fck" }; /* am3.h RNG clkctrl, TRM doesnt describe the rng, rng_fck only from the am33xx-clocks.dtsi */ +/* <0xac 0xc> */ +PLIST(l4ls_clkctrl_38_74) = { "l4ls_gclk" }; /* am3.h GPIO2 clkctrl, TRM 25.2.2 */ +PLIST(l4ls_clkctrl_38_75) = { "clk_32768_ck" }; /* am3.h GPIO2 clkctrl, TRM 25.2.2 */ +PLIST(l4ls_clkctrl_38_78) = { "l4ls_gclk" }; /* am3.h GPIO3 clkctrl, TRM 25.2.2 */ +PLIST(l4ls_clkctrl_38_79) = { "clk_32768_ck" }; /* am3.h GPIO3 clkctrl, TRM 25.2.2 */ +PLIST(l4ls_clkctrl_38_7c) = { "l4ls_gclk" }; /* am3.h GPIO4 clkctrl, TRM 25.2.2 */ +PLIST(l4ls_clkctrl_38_7d) = { "clk_32768_ck" }; /* am3.h GPIO4 clkctrl, TRM 25.2.2 */ +/* <0xc0 0x1c> */ +PLIST(l4ls_clkctrl_38_88) = { "dcan0_fck" }; /* am3.h D_CAN0 clkctrl, TRM 23.2.2 */ +PLIST(l4ls_clkctrl_38_8c) = { "dcan1_fck" }; /* am3.h D_CAN1 clkctrl, TRM 23.2.2 */ +/* 90 not described in am3.h */ +//PLIST(l4ls_clkctrl_38_90) = { NULL }; /* am3.h */ +PLIST(l4ls_clkctrl_38_94) = { "l4ls_gclk" }; /* am3.h EPWMMS1 clkctrl, TRM 15.1.2.3 */ +/* 98 not described in am3.h */ +//PLIST(l4ls_clkctrl_38_98) = { NULL }; /* am3.h */ +PLIST(l4ls_clkctrl_38_9c) = { "l4ls_gclk" }; /* am3.h EPWMMS0 clkctrl, TRM 15.1.2.3 */ +PLIST(l4ls_clkctrl_38_a0) = { "l4ls_gclk" }; /* am3.h EPWMMS2 clkctrl, TRM 15.1.2.3 */ +/* <0xec 0xc> */ +PLIST(l4ls_clkctrl_38_b4) = { "timer5_fck@518" }; /* am3.h TIMER5 clkctrl, TRM 20.1.2.3 */ +PLIST(l4ls_clkctrl_38_b8) = { "timer6_fck@51c" }; /* am3.h TIMER6 clkctrl, TRM 20.1.2.3 */ +PLIST(l4ls_clkctrl_38_bc) = { "mmc_clk" }; /* am3.h MMC2 clkctrl, TRM 18.2.2 */ +/* <0xd4 0x8> */ +PLIST(l4ls_clkctrl_38_d4) = { "l4ls_gclk" }; /* am3.h SPINLOCK clkctrl, TRM 8.1.12.1.48 "SPINLOCK clocks" */ +PLIST(l4ls_clkctrl_38_d8) = { "l4ls_gclk" }; /* am3.h MAILBOX clkctrl, TRM 17.1.1.2 */ +/* <0x130 0x4> */ +PLIST(l4ls_clkctrl_38_f8) = { "l4ls_gclk" }; /* am3.h OCPWP clkctrl, TRM 8.1.12.1.53 "OCPWP clocks" */ + +/* reg = <0x1c 0x4>, <0x30 0x8>, <0x68 0x4>, <0xf8 0x4> */ +/* <0x1c 0x4> */ +PLIST(l3s_clkctrl_1c_0) = { "usbotg_fck@47c" }; /* am3.h USB_OTG_HS clkctrl, TRM 16.1.2 fig 16-1 */ +/* <0x30 0x8> */ +PLIST(l3s_clkctrl_1c_14) = { "l3s_gclk" }; /* am3.h GPMC clkctrl, TRM 7.1.2.2 */ +PLIST(l3s_clkctrl_1c_18) = { "mcasp0_fck" }; /* am3.h MCASP0 clkctrl, TRM 22.2.2 */ +/* <0x68 0x4> */ +PLIST(l3s_clkctrl_1c_4c) = { "mcasp1_fck" }; /* am3.h MCASP1 clkctrl, TRM 22.2.2 */ +/* <0xf8 0x4> */ +PLIST(l3s_clkctrl_1c_dc) = { "mmc_clk" }; /* am3.h MMC3 clkctrl, TRM 18.2.2 */ + +/* reg = <0x24 0xc>, <0x94 0x10>, <0xbc 0x4>, <0xdc 0x8>, <0xfc 0x8>; */ +/* <0x24 0xc> */ +PLIST(l3_clkctrl_24_0) = { "l3_gclk" }; /* am3.h TPTC0 clkctrl, TRM 11.2.2.2 */ +PLIST(l3_clkctrl_24_4) = { "dpll_ddr_m2_div2_ck" }; /* am3.h EMIF clkctrl, TRM 7.3.2.2 */ +PLIST(l3_clkctrl_24_8) = { "l3_gclk" }; /* am3.h OCMCRAM clkctrl, TRM 7.2.2.2 */ +/* <0x94 0x10> */ +PLIST(l3_clkctrl_24_70) = { "aes0_fck" }; /* am3.h AES clkctrl, not in TRM, derived from am33xx-clocks.dtsi */ +//PLIST(l3_clkctrl_24_74) = { NULL }; /* am3.h ?? clkctrl, TRM ??? */ +//PLIST(l3_clkctrl_24_78) = { NULL }; /* am3.h ?? clkctrl, TRM ???? */ +PLIST(l3_clkctrl_24_7c) = { "l3_gclk" }; /* am3.h SHAM clkctrl, not in TRM, assume l3_gclk */ +/* <0xbc 0x4> */ +PLIST(l3_clkctrl_24_98) = { "l3_gclk" }; /* am3.h TPCC clkctrl, TRM 11.2.1.2 */ +/* <0xdc 0x8> */ +PLIST(l3_clkctrl_24_b8) = { "l3_gclk" }; /* am3.h L3 INSTR clkctrl, TRM 8.1.12.1.38 "L3 INSTR clocks" */ +PLIST(l3_clkctrl_24_bc) = { "l3_gclk" }; /* am3.h L3 Main clkctrl, TRM 18.1.12.1.39 "L3 interconnect clocks" */ +/* <0xfc 0x8> */ +PLIST(l3_clkctrl_24_d8) = { "l3_gclk" }; /* am3.h TPTC1 clkctrl, TRM 11.2.2.2 */ +PLIST(l3_clkctrl_24_dc) = { "l3_gclk" }; /* am3.h TPTC2 clkctrl, TRM 11.2.2.2 */ + +/* reg = <0x120 0x4>; */ +PLIST(l4hs_clkctrl_120_0) = { "l4hs_gclk" }; /* am3.h L4HS clkctrl, TRM 8.1.12.1.50 */ + +/* reg = <0xe8 0x4>; */ +PLIST(pruss_ocp_clkctrl_e8_0) = { "pruss_ocp_gclk@530" }; /* am3.h ocp pruss clkctrl, TRM 4.2.2 */ + +/* reg = <0x0 0x18>; */ +#if 0 +PLIST(cpsw_125mhz_clkctrl_0_0) = { NULL }; /* am3.h Not mentioned in TRM, TRM 14.2.2 */ +PLIST(cpsw_125mhz_clkctrl_0_4) = { NULL }; /* am3.h Not mentioned in TRM, TRM 14.2.2 */ +PLIST(cpsw_125mhz_clkctrl_0_8) = { NULL }; /* am3.h Not mentioned in TRM, TRM 14.2.2 */ +PLIST(cpsw_125mhz_clkctrl_0_c) = { NULL }; /* am3.h Not mentioned in TRM, TRM 14.2.2 */ +PLIST(cpsw_125mhz_clkctrl_0_10) = { NULL }; /* am3.h Not mentioned in TRM, TRM 14.2.2 */ +#endif +PLIST(cpsw_125mhz_clkctrl_0_14) = { "cpsw_125mhz_gclk" }; /* am3.h cpsw 125 mhz cpgmaco clkctrl, TRM 14.2.2 */ + +/* reg = <0x18 0x4>; */ +PLIST(lcdc_clkctrl_18_0) = { "lcd_gclk@534" }; /* am3.h lcdc clkctrl, TRM 13.2.2 */ + +/* reg = <0x14c 0x4>; */ +PLIST(clk_24mhz_clkctrl_14c_0) = { "clkdiv32k_ck" }; /* am3.h clkdiv32k clkctrl, TRM 8.1.12.1.57 */ + +/* reg = <0x0 0x10>, <0xb4 0x24>; */ +/* <0x0 0x10> */ +//PLIST(l4_wkup_clkctrl_0_0) = { NULL }; /* am3.h clkstctrl, TRM 8.1.12.2.1 */ +PLIST(l4_wkup_clkctrl_0_4) = { "mmc_clk" }; /* am3.h control clkctrl, TRM 18.2.2 */ +PLIST(l4_wkup_clkctrl_0_8) = { "dpll_core_m4_div2_ck" }; /* am3.h gpio1 clkctrl, TRM 25.2.2 */ +PLIST(l4_wkup_clkctrl_0_9) = { "gpio0_dbclk_mux_ck@53c" }; /* am3.h gpio1 clkctrl, TRM 25.2.2 */ +PLIST(l4_wkup_clkctrl_0_c) = { "mmc_clk" }; /* am3.h L4 wkup clkctrl, TRM 18.2.2 */ +/* <0xb4 0x24> */ +PLIST(l4_wkup_clkctrl_0_b4) = { "dpll_per_m2_div4_wkupdm_ck" }; /* am3.h uart1 clkctrl, TRM 19.2.2 */ +PLIST(l4_wkup_clkctrl_0_b8) = { "dpll_per_m2_div4_wkupdm_ck" }; /* am3.h i2c1 wkup clkctrl, TRM 21.2.2 */ +PLIST(l4_wkup_clkctrl_0_bc) = { "adc_tsc_fck" }; /* am3.h adc tsc clkctrl, TRM 12.2.2 */ +PLIST(l4_wkup_clkctrl_0_c0) = { "smartreflex0_fck" }; /* am3.h smartreflex0 clkctrl, TRM 8.1.12.2.49 */ +PLIST(l4_wkup_clkctrl_0_c4) = { "timer1_fck@528" }; /* am3.h timer1 clkctrl, TRM 20.1.2.3 */ +PLIST(l4_wkup_clkctrl_0_c8) = { "smartreflex1_fck" }; /* am3.h smartreflex1 clkctrl, TRM 8.1.12.2.51 */ +//PLIST(l4_wkup_clkctrl_0_cc) = { NULL }; /* am3.h l4_wkup_aon_clkstctrl, TRM 8.1.12.2.52 */ +//PLIST(l4_wkup_clkctrl_0_d0) = { NULL }; /* am3.h ??? clkctrl, not in TRM */ +PLIST(l4_wkup_clkctrl_0_d4) = { "wdt1_fck@538" }; /* am3.h wd timer2 clkctrl, TRM 20.4.2.2 */ + +/* reg = <0x14 0x4>; */ +//PLIST(l3_aon_clkctrl_14_0) = { NULL }; /* am3.h debugss clkctrl, TRM 8.1.12.2.6 multiple sub clocks - todo */ + +/* reg = <0xb0 0x4>; */ +//PLIST(l4_wkup_aon_wkup_m3_clkctrl_b0_0) = { NULL }; /* am3.h l4 wkup aon wkup m3 clkctrl, TRM 8.1.12.2.45 */ + +/* reg = <0x0 0x8>; */ +//PLIST(mpu_clkctrl_0_0) = { NULL }; /* am3.h mpu clkstctrl, TRM 8.1.12.4.1 */ +PLIST(mpu_clkctrl_0_4) = { "dpll_mpu_ck@488" }; /* am3.h mpu clkctrl, TRM 8.1.12.4.2 / 3.1.3 */ + +/* reg = <0x0 0x4>; */ +PLIST(l4_rtc_clkctrl_0_0) = { "clk_32768_ck" }; /* am3.h RTC clkctrl, TRM 20.3.2.2 */ + +/* reg = <0x0 0x8>; */ +//PLIST(gfx_l3_clkctrl_0_0) = { NULL }; /* am3.h L3 GFX clkctrl, TRM 5.1.2 */ +PLIST(gfx_l3_clkctrl_0_4) = { "gfx_fck_div_ck@52c" }; /* am3.h L3 GFX clkctrl, TRM 5.1.2 */ + +/* reg = <0x0 0x24>; */ +#if 0 +PLIST(l4_cefuse_clkctrl_0_0) = { NULL }; /* am3.h cefuse clkctrl, TRM 8.1.12.8.2 */ +PLIST(l4_cefuse_clkctrl_0_4) = { NULL }; /* am3.h cefuse clkctrl, TRM 8.1.12.8.2 */ +PLIST(l4_cefuse_clkctrl_0_8) = { NULL }; /* am3.h cefuse clkctrl, TRM 8.1.12.8.2 */ +PLIST(l4_cefuse_clkctrl_0_c) = { NULL }; /* am3.h cefuse clkctrl, TRM 8.1.12.8.2 */ +PLIST(l4_cefuse_clkctrl_0_10) = { NULL }; /* am3.h cefuse clkctrl, TRM 8.1.12.8.2 */ +PLIST(l4_cefuse_clkctrl_0_14) = { NULL }; /* am3.h cefuse clkctrl, TRM 8.1.12.8.2 */ +PLIST(l4_cefuse_clkctrl_0_18) = { NULL }; /* am3.h cefuse clkctrl, TRM 8.1.12.8.2 */ +PLIST(l4_cefuse_clkctrl_0_1c) = { NULL }; /* am3.h cefuse clkctrl, TRM 8.1.12.8.2 */ +PLIST(l4_cefuse_clkctrl_0_20) = { NULL }; /* am3.h cefuse clkctrl, TRM 8.1.12.8.2 */ +#endif + + +static struct parent_lookup_table clkctrl_parent_table[] = { + +/* reg = <0x38 0x2c>, <0x6c 0x28>, <0xac 0xc>, <0xc0 0x1c>, <0xec 0xc>, <0x10c 0x8>, <0x130 0x4>; + */ +/* <0x38 0x2c> */ + { "l4ls-clkctrl@38_0", nitems(l4ls_clkctrl_38_0), l4ls_clkctrl_38_0 }, + { "l4ls-clkctrl@38_4", nitems(l4ls_clkctrl_38_4), l4ls_clkctrl_38_4 }, + { "l4ls-clkctrl@38_8", nitems(l4ls_clkctrl_38_8), l4ls_clkctrl_38_8 }, + { "l4ls-clkctrl@38_c", nitems(l4ls_clkctrl_38_c), l4ls_clkctrl_38_c }, + { "l4ls-clkctrl@38_10", nitems(l4ls_clkctrl_38_10), l4ls_clkctrl_38_10 }, + { "l4ls-clkctrl@38_14", nitems(l4ls_clkctrl_38_14), l4ls_clkctrl_38_14 }, + { "l4ls-clkctrl@38_18", nitems(l4ls_clkctrl_38_18), l4ls_clkctrl_38_18 }, + { "l4ls-clkctrl@38_1c", 0, NULL }, + { "l4ls-clkctrl@38_20", 0, NULL }, + { "l4ls-clkctrl@38_24", 0, NULL }, + { "l4ls-clkctrl@38_28", nitems(l4ls_clkctrl_38_28), l4ls_clkctrl_38_28 }, +/* <0x6c 0x28> */ + { "l4ls-clkctrl@38_34", nitems(l4ls_clkctrl_38_34), l4ls_clkctrl_38_34 }, + { "l4ls-clkctrl@38_38", nitems(l4ls_clkctrl_38_38), l4ls_clkctrl_38_38 }, + { "l4ls-clkctrl@38_3c", nitems(l4ls_clkctrl_38_3c), l4ls_clkctrl_38_3c }, + { "l4ls-clkctrl@38_40", nitems(l4ls_clkctrl_38_40), l4ls_clkctrl_38_40 }, + { "l4ls-clkctrl@38_44", nitems(l4ls_clkctrl_38_44), l4ls_clkctrl_38_44 }, + { "l4ls-clkctrl@38_48", nitems(l4ls_clkctrl_38_48), l4ls_clkctrl_38_48 }, + { "l4ls-clkctrl@38_4c", nitems(l4ls_clkctrl_38_4c), l4ls_clkctrl_38_4c }, + { "l4ls-clkctrl@38_50", nitems(l4ls_clkctrl_38_50), l4ls_clkctrl_38_50 }, + { "l4ls-clkctrl@38_54", nitems(l4ls_clkctrl_38_54), l4ls_clkctrl_38_54 }, + { "l4ls-clkctrl@38_58", nitems(l4ls_clkctrl_38_58), l4ls_clkctrl_38_58 }, +/* <0xac 0xc> */ + { "l4ls-clkctrl@38_74", nitems(l4ls_clkctrl_38_74), l4ls_clkctrl_38_74 }, + { "l4ls-clkctrl@38_75", nitems(l4ls_clkctrl_38_75), l4ls_clkctrl_38_75 }, + { "l4ls-clkctrl@38_78", nitems(l4ls_clkctrl_38_78), l4ls_clkctrl_38_78 }, + { "l4ls-clkctrl@38_79", nitems(l4ls_clkctrl_38_79), l4ls_clkctrl_38_79 }, + { "l4ls-clkctrl@38_7c", nitems(l4ls_clkctrl_38_7c), l4ls_clkctrl_38_7c }, + { "l4ls-clkctrl@38_7d", nitems(l4ls_clkctrl_38_7d), l4ls_clkctrl_38_7d }, +/* <0xc0 0x1c> */ + { "l4ls-clkctrl@38_88", nitems(l4ls_clkctrl_38_88), l4ls_clkctrl_38_88 }, + { "l4ls-clkctrl@38_8c", nitems(l4ls_clkctrl_38_8c), l4ls_clkctrl_38_8c }, + { "l4ls-clkctrl@38_90", 0, NULL }, + { "l4ls-clkctrl@38_94", nitems(l4ls_clkctrl_38_94), l4ls_clkctrl_38_94 }, + { "l4ls-clkctrl@38_98", 0, NULL }, + { "l4ls-clkctrl@38_9c", nitems(l4ls_clkctrl_38_9c), l4ls_clkctrl_38_9c }, + { "l4ls-clkctrl@38_a0", nitems(l4ls_clkctrl_38_a0), l4ls_clkctrl_38_a0 }, +/* <0xec 0xc> */ + { "l4ls-clkctrl@38_b4", nitems(l4ls_clkctrl_38_b4), l4ls_clkctrl_38_b4 }, + { "l4ls-clkctrl@38_b8", nitems(l4ls_clkctrl_38_b8), l4ls_clkctrl_38_b8 }, + { "l4ls-clkctrl@38_bc", nitems(l4ls_clkctrl_38_bc), l4ls_clkctrl_38_bc }, +/* <0xd4 0x8> */ + { "l4ls-clkctrl@38_d4", nitems(l4ls_clkctrl_38_d4), l4ls_clkctrl_38_d4 }, + { "l4ls-clkctrl@38_d8", nitems(l4ls_clkctrl_38_d8), l4ls_clkctrl_38_d8 }, +/* <0x130 0x4> */ + { "l4ls-clkctrl@38_f8", nitems(l4ls_clkctrl_38_f8), l4ls_clkctrl_38_f8 }, + +/* reg = <0x1c 0x4>, <0x30 0x8>, <0x68 0x4>, <0xf8 0x4> */ +/* <0x1c 0x4> */ + { "l3s-clkctrl@1c_0", nitems(l3s_clkctrl_1c_0), l3s_clkctrl_1c_0 }, +/* <0x30 0x8> */ + { "l3s-clkctrl@1c_14", nitems(l3s_clkctrl_1c_14), l3s_clkctrl_1c_14 }, + { "l3s-clkctrl@1c_18", nitems(l3s_clkctrl_1c_18), l3s_clkctrl_1c_18 }, +/* <0x68 0x4> */ + { "l3s-clkctrl@1c_4c", nitems(l3s_clkctrl_1c_4c), l3s_clkctrl_1c_4c }, +/* <0xf8 0x4> */ + { "l3s-clkctrl@1c_dc", nitems(l3s_clkctrl_1c_dc), l3s_clkctrl_1c_dc }, + +/* reg = <0x24 0xc>, <0x94 0x10>, <0xbc 0x4>, <0xdc 0x8>, <0xfc 0x8>; */ +/* <0x24 0xc> */ + { "l3-clkctrl@24_0", nitems(l3_clkctrl_24_0), l3_clkctrl_24_0 }, + { "l3-clkctrl@24_4", nitems(l3_clkctrl_24_4), l3_clkctrl_24_4 }, + { "l3-clkctrl@24_8", nitems(l3_clkctrl_24_8), l3_clkctrl_24_8 }, +/* <0x94 0x10> */ + { "l3-clkctrl@24_70", nitems(l3_clkctrl_24_70), l3_clkctrl_24_70 }, + { "l3-clkctrl@24_74", 0, NULL }, + { "l3-clkctrl@24_78", 0, NULL }, + { "l3-clkctrl@24_7c", nitems(l3_clkctrl_24_7c), l3_clkctrl_24_7c }, +/* <0xbc 0x4> */ + { "l3-clkctrl@24_98", nitems(l3_clkctrl_24_98), l3_clkctrl_24_98 }, +/* <0xdc 0x8> */ + { "l3-clkctrl@24_b8", nitems(l3_clkctrl_24_b8), l3_clkctrl_24_b8 }, + { "l3-clkctrl@24_bc", nitems(l3_clkctrl_24_bc), l3_clkctrl_24_bc }, +/* <0xfc 0x8> */ + { "l3-clkctrl@24_d8", nitems(l3_clkctrl_24_d8), l3_clkctrl_24_d8 }, + { "l3-clkctrl@24_dc", nitems(l3_clkctrl_24_dc), l3_clkctrl_24_dc }, + +/* reg = <0x120 0x4>; */ + { "l4hs-clkctrl@120_0", nitems(l4hs_clkctrl_120_0), l4hs_clkctrl_120_0 }, + +/* reg = <0xe8 0x4>; */ + { "pruss-ocp-clkctrl@e8_0", nitems(pruss_ocp_clkctrl_e8_0), pruss_ocp_clkctrl_e8_0 }, + +/* reg = <0x0 0x18>; */ + { "cpsw-125mhz-clkctrl@0_0", 0, NULL }, + { "cpsw-125mhz-clkctrl@0_4", 0, NULL }, + { "cpsw-125mhz-clkctrl@0_8", 0, NULL }, + { "cpsw-125mhz-clkctrl@0_c", 0, NULL }, + { "cpsw-125mhz-clkctrl@0_10", 0, NULL }, + { "cpsw-125mhz-clkctrl@0_14", nitems(cpsw_125mhz_clkctrl_0_14), cpsw_125mhz_clkctrl_0_14 }, + +/* reg = <0x18 0x4>; */ + { "lcdc-clkctrl@18_0", nitems(lcdc_clkctrl_18_0), lcdc_clkctrl_18_0 }, + +/* reg = <0x14c 0x4>; */ + { "clk-24mhz-clkctrl@14c_0", nitems(clk_24mhz_clkctrl_14c_0), clk_24mhz_clkctrl_14c_0 }, + +/* reg = <0x0 0x10>, <0xb4 0x24>; */ +/* <0x0 0x10> */ + { "l4-wkup-clkctrl@0_0", 0, NULL }, + { "l4-wkup-clkctrl@0_4", nitems(l4_wkup_clkctrl_0_4), l4_wkup_clkctrl_0_4 }, + { "l4-wkup-clkctrl@0_8", nitems(l4_wkup_clkctrl_0_8), l4_wkup_clkctrl_0_8 }, + { "l4-wkup-clkctrl@0_9", nitems(l4_wkup_clkctrl_0_9), l4_wkup_clkctrl_0_9 }, + { "l4-wkup-clkctrl@0_c", nitems(l4_wkup_clkctrl_0_c), l4_wkup_clkctrl_0_c }, +/* <0xb4 0x24> */ + { "l4-wkup-clkctrl@0_b4", nitems(l4_wkup_clkctrl_0_b4), l4_wkup_clkctrl_0_b4 }, + { "l4-wkup-clkctrl@0_b8", nitems(l4_wkup_clkctrl_0_b8), l4_wkup_clkctrl_0_b8 }, + { "l4-wkup-clkctrl@0_bc", nitems(l4_wkup_clkctrl_0_bc), l4_wkup_clkctrl_0_bc }, + { "l4-wkup-clkctrl@0_c0", nitems(l4_wkup_clkctrl_0_c0), l4_wkup_clkctrl_0_c0 }, + { "l4-wkup-clkctrl@0_c4", nitems(l4_wkup_clkctrl_0_c4), l4_wkup_clkctrl_0_c4 }, + { "l4-wkup-clkctrl@0_c8", nitems(l4_wkup_clkctrl_0_c8), l4_wkup_clkctrl_0_c8 }, + { "l4-wkup-clkctrl@0_cc", 0, NULL }, + { "l4-wkup-clkctrl@0_d0", 0, NULL }, + { "l4-wkup-clkctrl@0_d4", nitems(l4_wkup_clkctrl_0_d4), l4_wkup_clkctrl_0_d4 }, + +/* reg = <0x14 0x4>; */ + { "l3-aon-clkctrl@14_0", 0, NULL }, + +/* reg = <0xb0 0x4>; */ + { "l4-wkup-aon-clkctrl@b0_0", 0, NULL }, + +/* reg = <0x0 0x8>; */ + { "mpu-clkctrl@0_0", 0, NULL }, + { "mpu-clkctrl@0_4", nitems(mpu_clkctrl_0_4), mpu_clkctrl_0_4 }, + +/* reg = <0x0 0x4>; */ + { "l4-rtc-clkctrl@0_0", nitems(l4_rtc_clkctrl_0_0), l4_rtc_clkctrl_0_0 }, + +/* reg = <0x0 0x8>; */ + { "gfx-l3-clkctrl@0_0", 0, NULL }, + { "gfx-l3-clkctrl@0_4", nitems(gfx_l3_clkctrl_0_4), gfx_l3_clkctrl_0_4 }, + +/* reg = <0x0 0x24>; */ + { "l4-cefuse-clkctrl@0_0", 0, NULL }, + { "l4-cefuse-clkctrl@0_4", 0, NULL }, + { "l4-cefuse-clkctrl@0_8", 0, NULL }, + { "l4-cefuse-clkctrl@0_c", 0, NULL }, + { "l4-cefuse-clkctrl@0_10", 0, NULL }, + { "l4-cefuse-clkctrl@0_14", 0, NULL }, + { "l4-cefuse-clkctrl@0_18", 0, NULL }, + { "l4-cefuse-clkctrl@0_1c", 0, NULL }, + { "l4-cefuse-clkctrl@0_20", 0, NULL }, +}; + + static int ti_clkctrl_probe(device_t dev); static int ti_clkctrl_attach(device_t dev); static int ti_clkctrl_detach(device_t dev); @@ -198,7 +502,7 @@ for (reg_offset = 0; reg_offset < reg[index+1]; reg_offset += sizeof(cell_t)) { err = create_clkctrl(sc, reg, index, reg_offset, parent_offset, org_name, false); - if (err) + if (err != 0) goto cleanup; /* Create special clkctrl for GDBCLK in GPIO registers */ @@ -213,7 +517,7 @@ { err = create_clkctrl(sc, reg, index, reg_offset, parent_offset, org_name, true); - if (err) + if (err != 0) goto cleanup; } break; @@ -223,7 +527,7 @@ { err = create_clkctrl(sc, reg, index, reg_offset, parent_offset, org_name, true); - if (err) + if (err != 0) goto cleanup; } break; @@ -232,7 +536,7 @@ } /* for */ err = clkdom_finit(sc->clkdom); - if (err) { + if (err != 0) { DPRINTF(sc->dev, "Clk domain finit fails %x.\n", err); err = ENXIO; goto cleanup; @@ -243,7 +547,7 @@ free(reg, M_DEVBUF); - if (err) + if (err != 0) return (err); return (bus_generic_attach(dev)); @@ -285,12 +589,12 @@ create_clkctrl(struct ti_clkctrl_softc *sc, cell_t *reg, uint32_t index, uint32_t reg_offset, uint64_t parent_offset, const char *org_name, bool special_gdbclk_reg) { struct ti_clk_clkctrl_def def; - char *name; + char *node_name; size_t name_len; - int err; + int err, p_index=0; name_len = strlen(org_name) + 1 + 5; /* 5 = _xxxx */ - name = malloc(name_len, M_OFWPROP, M_WAITOK); + node_name = malloc(name_len, M_OFWPROP, M_WAITOK); /* * Check out XX_CLKCTRL-INDEX(offset)-macro dance in @@ -307,28 +611,40 @@ def.gdbclk = special_gdbclk_reg; /* Make up an uniq name in the namespace for each clkctrl */ - snprintf(name, name_len, "%s_%x", + snprintf(node_name, name_len, "%s_%x", org_name, def.clkdef.id); - def.clkdef.name = (const char *) name; DPRINTF(sc->dev, "ti_clkctrl_attach: reg[%d]: %s %x\n", - index, def.clkdef.name, def.clkdef.id); + index, node_name, def.clkdef.id); + + /* Find parent in lookup table */ + for (p_index = 0; p_index < nitems(clkctrl_parent_table); p_index++) { + if (strcmp(node_name, clkctrl_parent_table[p_index].node_name) == 0) + break; + } + + if (p_index == nitems(clkctrl_parent_table)) + panic("Cant find clock %s\n", node_name); - /* No parent name */ - def.clkdef.parent_cnt = 0; + DPRINTF(sc->dev, "%s at clkctrl_parent_table[%d] parent_cnt %d \n", + node_name, p_index, clkctrl_parent_table[p_index].parent_cnt); + /* set flags and name */ + def.clkdef.flags = CLK_NODE_STATIC_STRINGS; + def.clkdef.name = clkctrl_parent_table[p_index].node_name; - /* set flags */ - def.clkdef.flags = 0x0; + /* Handle parents */ + def.clkdef.parent_cnt = clkctrl_parent_table[p_index].parent_cnt; + def.clkdef.parent_names = clkctrl_parent_table[p_index].parent_names; /* Register the clkctrl */ err = ti_clknode_clkctrl_register(sc->clkdom, &def); - if (err) { + if (err != 0) { DPRINTF(sc->dev, "ti_clknode_clkctrl_register[%d:%d] failed %x\n", index, reg_offset, err); err = ENXIO; } - OF_prop_free(name); + OF_prop_free(node_name); return (err); } diff --git a/sys/arm/ti/clk/ti_divider_clock.c b/sys/arm/ti/clk/ti_divider_clock.c --- a/sys/arm/ti/clk/ti_divider_clock.c +++ b/sys/arm/ti/clk/ti_divider_clock.c @@ -42,11 +42,15 @@ #include #include +#include #include #include #include "clock_common.h" +#include "clkdev_if.h" +#include "syscon_if.h" + #if 0 #define DPRINTF(dev, msg...) device_printf(dev, msg) #else @@ -59,12 +63,11 @@ */ struct ti_divider_softc { - device_t sc_dev; - bool attach_done; + device_t dev; struct clk_div_def div_def; - struct clock_cell_info clock_cell; struct clkdom *clkdom; + struct syscon *syscon; }; static int ti_divider_probe(device_t dev); @@ -81,31 +84,125 @@ { NULL, TI_DIVIDER_END } }; +PLIST(dpll_core_m4_ck_parent) = { "dpll_core_x2_ck" }; +PLIST(dpll_core_m5_ck_parent) = { "dpll_core_x2_ck" }; +PLIST(dpll_core_m6_ck_parent) = { "dpll_core_x2_ck" }; +PLIST(dpll_mpu_m2_ck_parent) = { "dpll_mpu_ck@488" }; +PLIST(dpll_ddr_m2_ck_parent) = { "dpll_ddr_ck@494" }; +PLIST(dpll_disp_m2_ck_parent) = { "dpll_disp_ck@498" }; +PLIST(dpll_per_m2_ck_parent) = { "dpll_per_ck@48c" }; +PLIST(gfx_fck_div_ck_parent) = { "gfx_fclk_clksel_ck@52c" }; +PLIST(clkout2_div_ck_parent) = { "sysclkout_pre_ck@700" }; + + +static struct parent_lookup_table div_parent_table[] = { + { + "dpll_core_m4_ck@480", + nitems(dpll_core_m4_ck_parent), + dpll_core_m4_ck_parent + }, + { + "dpll_core_m5_ck@484", + nitems(dpll_core_m5_ck_parent), + dpll_core_m5_ck_parent + }, + { + "dpll_core_m6_ck@4d8", + nitems(dpll_core_m6_ck_parent), + dpll_core_m6_ck_parent + }, + { + "dpll_mpu_m2_ck@4a8", + nitems(dpll_mpu_m2_ck_parent), + dpll_mpu_m2_ck_parent + }, + { + "dpll_ddr_m2_ck@4a0", + nitems(dpll_ddr_m2_ck_parent), + dpll_ddr_m2_ck_parent + }, + { + "dpll_disp_m2_ck@4a4", + nitems(dpll_disp_m2_ck_parent), + dpll_disp_m2_ck_parent + }, + { + "dpll_per_m2_ck@4ac", + nitems(dpll_per_m2_ck_parent), + dpll_per_m2_ck_parent + }, + { + "gfx_fck_div_ck@52c", + nitems(gfx_fck_div_ck_parent), + gfx_fck_div_ck_parent + }, + { + "clkout2_div_ck@700", + nitems(clkout2_div_ck_parent), + clkout2_div_ck_parent + }, +}; + + static int -register_clk(struct ti_divider_softc *sc) { - int err; +ti_divider_clkdev_write_4(device_t dev, bus_addr_t addr, uint32_t val) +{ + struct ti_divider_softc *sc; - sc->clkdom = clkdom_create(sc->sc_dev); - if (sc->clkdom == NULL) { - DPRINTF(sc->sc_dev, "Failed to create clkdom\n"); - return (ENXIO); - } + sc = device_get_softc(dev); + DPRINTF(sc->dev, "ti_divider_clkdev_write_4: addr %x val %x\n", + addr, val); + return (SYSCON_UNLOCKED_WRITE_4(sc->syscon, addr, val)); +} - err = clknode_div_register(sc->clkdom, &sc->div_def); - if (err) { - DPRINTF(sc->sc_dev, "clknode_div_register failed %x\n", err); - return (ENXIO); - } +static int +ti_divider_clkdev_read_4(device_t dev, bus_addr_t addr, uint32_t *val) +{ + struct ti_divider_softc *sc; + uint32_t rdval; - err = clkdom_finit(sc->clkdom); - if (err) { - DPRINTF(sc->sc_dev, "Clk domain finit fails %x.\n", err); - return (ENXIO); - } + sc = device_get_softc(dev); + rdval = SYSCON_UNLOCKED_READ_4(sc->syscon, addr); + *val = rdval; + DPRINTF(sc->dev, "ti_divider_clkdev_read_4: addr %x val %x\n", + addr, *val); return (0); } +static int +ti_divider_clkdev_modify_4(device_t dev, bus_addr_t addr, + uint32_t clear_mask, uint32_t set_mask) +{ + struct ti_divider_softc *sc; + + sc = device_get_softc(dev); + DPRINTF(sc->dev, "ti_divider_clkdev_modify_4: addr %x clear %x set %x\n", + addr, clear_mask, set_mask); + return (SYSCON_UNLOCKED_MODIFY_4(sc->syscon, addr, clear_mask, + set_mask)); +} + +static void +ti_divider_clkdev_device_lock(device_t dev) +{ + struct ti_divider_softc *sc; + + sc = device_get_softc(dev); + DPRINTF(sc->dev, "ti_divider_clkdev_device_lock\n"); + SYSCON_DEVICE_LOCK(sc->syscon->pdev); +} + +static void +ti_divider_clkdev_device_unlock(device_t dev) +{ + struct ti_divider_softc *sc; + + sc = device_get_softc(dev); + DPRINTF(sc->dev, "ti_divider_clkdev_device_unlock\n"); + SYSCON_DEVICE_UNLOCK(sc->syscon->pdev); +} + static int ti_divider_probe(device_t dev) { @@ -125,14 +222,25 @@ { struct ti_divider_softc *sc; phandle_t node; - int err; + int err, index; cell_t value; uint32_t ti_max_div; + const char *node_name; sc = device_get_softc(dev); - sc->sc_dev = dev; + sc->dev = dev; node = ofw_bus_get_node(dev); + err = SYSCON_GET_HANDLE(dev, &sc->syscon); + if (err != 0) { + panic("Cannot get syscon handle.\n"); + } + + node_name = ofw_bus_get_name(dev); + if (node_name == NULL) { + panic("Cannot get name of the clock node"); + } + /* Grab the content of reg properties */ OF_getencprop(node, "reg", &value, sizeof(value)); sc->div_def.offset = value; @@ -148,7 +256,8 @@ if (OF_hasprop(node, "ti,index-power-of-two")) { /* FIXME: later */ - device_printf(sc->sc_dev, "ti,index-power-of-two - Not implemented\n"); + device_printf(sc->dev, + "ti,index-power-of-two - Not implemented\n"); /* remember to update i_width a few lines below */ } if (OF_hasprop(node, "ti,max-div")) { @@ -157,18 +266,21 @@ } if (OF_hasprop(node, "clock-output-names")) - device_printf(sc->sc_dev, "clock-output-names\n"); + device_printf(sc->dev, "clock-output-names\n"); if (OF_hasprop(node, "ti,dividers")) - device_printf(sc->sc_dev, "ti,dividers\n"); + device_printf(sc->dev, "ti,dividers\n"); if (OF_hasprop(node, "ti,min-div")) - device_printf(sc->sc_dev, "ti,min-div - Not implemented\n"); + device_printf(sc->dev, "ti,min-div - Not implemented\n"); if (OF_hasprop(node, "ti,autoidle-shift")) - device_printf(sc->sc_dev, "ti,autoidle-shift - Not implemented\n"); + device_printf(sc->dev, + "ti,autoidle-shift - Not implemented\n"); if (OF_hasprop(node, "ti,set-rate-parent")) - device_printf(sc->sc_dev, "ti,set-rate-parent - Not implemented\n"); + device_printf(sc->dev, + "ti,set-rate-parent - Not implemented\n"); if (OF_hasprop(node, "ti,latch-bit")) - device_printf(sc->sc_dev, "ti,latch-bit - Not implemented\n"); + device_printf(sc->dev, + "ti,latch-bit - Not implemented\n"); /* Figure out the width from ti_max_div */ if (sc->div_def.div_flags) @@ -176,33 +288,46 @@ else sc->div_def.i_width = fls(ti_max_div); - DPRINTF(sc->sc_dev, "div_def.i_width %x\n", sc->div_def.i_width); + DPRINTF(sc->dev, "div_def.i_width %x\n", sc->div_def.i_width); - read_clock_cells(sc->sc_dev, &sc->clock_cell); + /* Find parent in lookup table */ + for (index = 0; index < nitems(div_parent_table); index++) { + if (strcmp(node_name, div_parent_table[index].node_name) == 0) + break; + } - create_clkdef(sc->sc_dev, &sc->clock_cell, &sc->div_def.clkdef); + if (index == nitems(div_parent_table)) + panic("Cant find clock %s\n", node_name); - err = find_parent_clock_names(sc->sc_dev, &sc->clock_cell, &sc->div_def.clkdef); + DPRINTF(sc->dev, "%s at div_parent_table[%d]\n", node_name, index); - if (err) { - /* free_clkdef will be called in ti_divider_new_pass */ - DPRINTF(sc->sc_dev, "find_parent_clock_names failed\n"); - return (bus_generic_attach(sc->sc_dev)); - } + /* Fill clknode_init_def */ + sc->div_def.clkdef.id = 1; + sc->div_def.clkdef.flags = CLK_NODE_STATIC_STRINGS; + sc->div_def.clkdef.name = div_parent_table[index].node_name; + sc->div_def.clkdef.parent_cnt = div_parent_table[index].parent_cnt; + sc->div_def.clkdef.parent_names = + div_parent_table[index].parent_names; - err = register_clk(sc); - - if (err) { - /* free_clkdef will be called in ti_divider_new_pass */ - DPRINTF(sc->sc_dev, "register_clk failed\n"); - return (bus_generic_attach(sc->sc_dev)); + sc->clkdom = clkdom_create(sc->dev); + if (sc->clkdom == NULL) { + DPRINTF(sc->dev, "Failed to create clkdom\n"); + return (ENXIO); } - sc->attach_done = true; + err = clknode_div_register(sc->clkdom, &sc->div_def); + if (err != 0) { + DPRINTF(sc->dev, "clknode_div_register failed %x\n", err); + return (ENXIO); + } - free_clkdef(&sc->div_def.clkdef); + err = clkdom_finit(sc->clkdom); + if (err != 0) { + DPRINTF(sc->dev, "Clk domain finit fails %x.\n", err); + return (ENXIO); + } - return (bus_generic_attach(sc->sc_dev)); + return (bus_generic_attach(sc->dev)); } static int @@ -211,45 +336,18 @@ return (EBUSY); } -static void -ti_divider_new_pass(device_t dev) -{ - struct ti_divider_softc *sc; - int err; - - sc = device_get_softc(dev); - - if (sc->attach_done) { - return; - } - - err = find_parent_clock_names(sc->sc_dev, &sc->clock_cell, &sc->div_def.clkdef); - if (err) { - /* free_clkdef will be called in a later call to ti_divider_new_pass */ - DPRINTF(sc->sc_dev, "new_pass find_parent_clock_names failed\n"); - return; - } - - err = register_clk(sc); - if (err) { - /* free_clkdef will be called in a later call to ti_divider_new_pass */ - DPRINTF(sc->sc_dev, "new_pass register_clk failed\n"); - return; - } - - sc->attach_done = true; - - free_clkdef(&sc->div_def.clkdef); -} - static device_method_t ti_divider_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ti_divider_probe), DEVMETHOD(device_attach, ti_divider_attach), DEVMETHOD(device_detach, ti_divider_detach), - /* Bus interface */ - DEVMETHOD(bus_new_pass, ti_divider_new_pass), + /* Clock device interface */ + DEVMETHOD(clkdev_device_lock, ti_divider_clkdev_device_lock), + DEVMETHOD(clkdev_device_unlock, ti_divider_clkdev_device_unlock), + DEVMETHOD(clkdev_read_4, ti_divider_clkdev_read_4), + DEVMETHOD(clkdev_write_4, ti_divider_clkdev_write_4), + DEVMETHOD(clkdev_modify_4, ti_divider_clkdev_modify_4), DEVMETHOD_END }; diff --git a/sys/arm/ti/clk/ti_dpll_clock.c b/sys/arm/ti/clk/ti_dpll_clock.c --- a/sys/arm/ti/clk/ti_dpll_clock.c +++ b/sys/arm/ti/clk/ti_dpll_clock.c @@ -63,10 +63,8 @@ device_t dev; uint8_t dpll_type; - bool attach_done; struct ti_clk_dpll_def dpll_def; - struct clock_cell_info clock_cell; struct clkdom *clkdom; }; @@ -114,31 +112,73 @@ { NULL, TI_DPLL_END } }; -static int -register_clk(struct ti_dpll_softc *sc) { - int err; - - sc->clkdom = clkdom_create(sc->dev); - if (sc->clkdom == NULL) { - DPRINTF(sc->dev, "Failed to create clkdom\n"); - return (ENXIO); - } - - err = ti_clknode_dpll_register(sc->clkdom, &sc->dpll_def); - if (err) { - DPRINTF(sc->dev, - "ti_clknode_dpll_register failed %x\n", err); - return (ENXIO); - } - - err = clkdom_finit(sc->clkdom); - if (err) { - DPRINTF(sc->dev, "Clk domain finit fails %x.\n", err); - return (ENXIO); - } - return (0); -} +PLIST(dpll_core_ck_parent) = { "sys_clkin_ck@40", "sys_clkin_ck@40" }; +PLIST(dpll_core_x2_parent) = { "dpll_core_ck@490" }; + +PLIST(dpll_mpu_ck_parent) = { "sys_clkin_ck@40", "sys_clkin_ck@40" }; + +PLIST(dpll_ddr_ck_parent) = { "sys_clkin_ck@40", "sys_clkin_ck@40" }; +PLIST(dpll_ddr_m2_div2_ck_parent) = { "dpll_ddr_m2_ck@4a0" }; + +PLIST(dpll_disp_ck_parent) = { "sys_clkin_ck@40", "sys_clkin_ck@40" }; + +PLIST(dpll_per_ck_parent) = { "sys_clkin_ck@40", "sys_clkin_ck@40" }; + +PLIST(dpll_per_m2_div4_wkupdm_ck_parent) = { "dpll_per_m2_ck@4ac" }; +PLIST(dpll_per_m2_div4_ck_parent) = { "dpll_per_m2_ck@4ac" }; + +static struct parent_lookup_table dpll_parent_table[] = { + { + "dpll_core_ck@490", + nitems(dpll_core_ck_parent), + dpll_core_ck_parent + }, + { + "dpll_core_x2_ck", + nitems(dpll_core_x2_parent), + dpll_core_x2_parent + }, + + { + "dpll_mpu_ck@488", + nitems(dpll_mpu_ck_parent), + dpll_mpu_ck_parent + }, + + { + "dpll_ddr_ck@494", + nitems(dpll_ddr_ck_parent), + dpll_ddr_ck_parent + }, + { + "dpll_ddr_m2_div2_ck", + nitems(dpll_ddr_m2_div2_ck_parent), + dpll_ddr_m2_div2_ck_parent + }, + + { + "dpll_disp_ck@498", + nitems(dpll_disp_ck_parent), + dpll_disp_ck_parent + }, + + { + "dpll_per_ck@48c", + nitems(dpll_per_ck_parent), + dpll_per_ck_parent + }, + { + "dpll_per_m2_div4_wkupdm_ck", + nitems(dpll_per_m2_div4_wkupdm_ck_parent), + dpll_per_m2_div4_wkupdm_ck_parent + }, + { + "dpll_per_m2_div4_ck", + nitems(dpll_per_m2_div4_ck_parent), + dpll_per_m2_div4_ck_parent + }, +}; static int ti_dpll_probe(device_t dev) @@ -261,9 +301,10 @@ static int ti_dpll_attach(device_t dev) { - struct ti_dpll_softc *sc; - phandle_t node; - int err; + struct ti_dpll_softc *sc; + phandle_t node; + int err, index; + const char *node_name; sc = device_get_softc(dev); sc->dev = dev; @@ -271,6 +312,11 @@ sc->dpll_type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; node = ofw_bus_get_node(dev); + node_name = ofw_bus_get_name(dev); + if (node_name == NULL) { + panic("Cannot get name of the clock node"); + } + /* Grab the content of reg properties */ parse_dpll_reg(sc); @@ -287,30 +333,43 @@ sc->dpll_def.ti_clkmode_flags |= LOCK_MODE_FLAG; } - read_clock_cells(sc->dev, &sc->clock_cell); - - create_clkdef(sc->dev, &sc->clock_cell, &sc->dpll_def.clkdef); + /* Find parent in lookup table */ + for (index = 0; index < nitems(dpll_parent_table); index++) { + if (strcmp(node_name, dpll_parent_table[index].node_name) == 0) + break; + } - err = find_parent_clock_names(sc->dev, &sc->clock_cell, - &sc->dpll_def.clkdef); + if (index == nitems(dpll_parent_table)) + panic("Cant find clock %s\n", node_name); - if (err) { - /* free_clkdef will be called in ti_dpll_new_pass */ - DPRINTF(sc->dev, "find_parent_clock_names failed\n"); - return (bus_generic_attach(sc->dev)); - } + DPRINTF(sc->dev, "%s at dpll_parent_table[%d]\n", node_name, index); - err = register_clk(sc); + /* Fill clknode_init_def */ + sc->dpll_def.clkdef.id = 1; + sc->dpll_def.clkdef.name = dpll_parent_table[index].node_name; + sc->dpll_def.clkdef.parent_cnt = dpll_parent_table[index].parent_cnt; + sc->dpll_def.clkdef.parent_names = + dpll_parent_table[index].parent_names; + sc->dpll_def.clkdef.flags = CLK_NODE_STATIC_STRINGS; - if (err) { - /* free_clkdef will be called in ti_dpll_new_pass */ - DPRINTF(sc->dev, "register_clk failed\n"); - return (bus_generic_attach(sc->dev)); + sc->clkdom = clkdom_create(sc->dev); + if (sc->clkdom == NULL) { + DPRINTF(sc->dev, "Failed to create clkdom\n"); + return (ENXIO); } - sc->attach_done = true; + err = ti_clknode_dpll_register(sc->clkdom, &sc->dpll_def); + if (err != 0) { + DPRINTF(sc->dev, + "ti_clknode_dpll_register failed %x\n", err); + return (ENXIO); + } - free_clkdef(&sc->dpll_def.clkdef); + err = clkdom_finit(sc->clkdom); + if (err != 0) { + DPRINTF(sc->dev, "Clk domain finit fails %x.\n", err); + return (ENXIO); + } return (bus_generic_attach(sc->dev)); } @@ -321,47 +380,12 @@ return (EBUSY); } -static void -ti_dpll_new_pass(device_t dev) -{ - struct ti_dpll_softc *sc; - int err; - - sc = device_get_softc(dev); - - if (sc->attach_done) { - return; - } - - err = find_parent_clock_names(sc->dev, &sc->clock_cell, - &sc->dpll_def.clkdef); - if (err) { - /* free_clkdef will be called in a later call to ti_dpll_new_pass */ - DPRINTF(sc->dev, - "new_pass find_parent_clock_names failed\n"); - return; - } - - err = register_clk(sc); - if (err) { - /* free_clkdef will be called in a later call to ti_dpll_new_pass */ - DPRINTF(sc->dev, "new_pass register_clk failed\n"); - return; - } - - sc->attach_done = true; - free_clkdef(&sc->dpll_def.clkdef); -} - static device_method_t ti_dpll_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ti_dpll_probe), DEVMETHOD(device_attach, ti_dpll_attach), DEVMETHOD(device_detach, ti_dpll_detach), - /* Bus interface */ - DEVMETHOD(bus_new_pass, ti_dpll_new_pass), - DEVMETHOD_END }; diff --git a/sys/arm/ti/clk/ti_gate_clock.c b/sys/arm/ti/clk/ti_gate_clock.c --- a/sys/arm/ti/clk/ti_gate_clock.c +++ b/sys/arm/ti/clk/ti_gate_clock.c @@ -41,11 +41,14 @@ #include #include -#include #include #include +#include +#include #include "clock_common.h" +#include "clkdev_if.h" +#include "syscon_if.h" #define DEBUG_GATE 0 @@ -61,13 +64,12 @@ */ struct ti_gate_softc { - device_t sc_dev; - bool attach_done; + device_t dev; uint8_t sc_type; struct clk_gate_def gate_def; - struct clock_cell_info clock_cell; struct clkdom *clkdom; + struct syscon *syscon; }; static int ti_gate_probe(device_t dev); @@ -88,12 +90,118 @@ { "ti,wait-gate-clock", TI_WAIT_GATE_CLOCK }, { "ti,dss-gate-clock", TI_DSS_GATE_CLOCK }, { "ti,am35xx-gate-clock", TI_AM35XX_GATE_CLOCK }, - { "ti,clkdm-gate-clock", TI_CLKDM_GATE_CLOCK }, + /* For now, dont support clkdm-gate-clock */ + /* { "ti,clkdm-gate-clock", TI_CLKDM_GATE_CLOCK }, */ { "ti,hsdiv-gate-cloc", TI_HSDIV_GATE_CLOCK }, - { "ti,composite-no-wait-gate-clock", TI_COMPOSITE_NO_WAIT_GATE_CLOCK }, + { "ti,composite-no-wait-gate-clock", TI_COMPOSITE_NO_WAIT_GATE_CLOCK }, { NULL, TI_GATE_END } }; +PLIST(ehrpwm0_tbclk_parent) = { "l4ls_gclk" }; +PLIST(ehrpwm1_tbclk_parent) = { "l4ls_gclk" }; +PLIST(ehrpwm2_tbclk_parent) = { "l4ls_gclk" }; +PLIST(mmu_fck_parent) = { "dpll_core_m4_ck@480" }; +PLIST(usbotg_fck_parent) = { "dpll_per_ck@48c" }; +PLIST(ieee5000_fck_parent) = { "dpll_core_m4_div2_ck" }; +PLIST(clkout2_ck_parent) = { "clkout2_div_ck@700" }; + + +static struct parent_lookup_table gate_parent_table[] = { + { + "ehrpwm0_tbclk@44e10664", + nitems(ehrpwm0_tbclk_parent), + ehrpwm0_tbclk_parent + }, + { + "ehrpwm1_tbclk@44e10664", + nitems(ehrpwm1_tbclk_parent), + ehrpwm1_tbclk_parent + }, + { + "ehrpwm2_tbclk@44e10664", + nitems(ehrpwm2_tbclk_parent), + ehrpwm2_tbclk_parent + }, + { + "mmu_fck@914", + nitems(mmu_fck_parent), + mmu_fck_parent + }, + { + "usbotg_fck@47c", + nitems(usbotg_fck_parent), + usbotg_fck_parent + }, + { + "ieee5000_fck@e4", + nitems(ieee5000_fck_parent), + ieee5000_fck_parent + }, + { + "clkout2_ck@700", + nitems(clkout2_ck_parent), + clkout2_ck_parent + }, +}; + + +static int +ti_gate_clkdev_write_4(device_t dev, bus_addr_t addr, uint32_t val) +{ + struct ti_gate_softc *sc; + + sc = device_get_softc(dev); + DPRINTF(sc->dev, "gate_clkdev_write_4: addr %x val %x\n", + addr, val); + return (SYSCON_UNLOCKED_WRITE_4(sc->syscon, addr, val)); +} + +static int +ti_gate_clkdev_read_4(device_t dev, bus_addr_t addr, uint32_t *val) +{ + struct ti_gate_softc *sc; + + sc = device_get_softc(dev); + + *val = SYSCON_UNLOCKED_READ_4(sc->syscon, addr); + DPRINTF(sc->dev, "gate_clkdev_write_4: addr %x val %x\n", + addr, *val); + return (0); +} + +static int +ti_gate_clkdev_modify_4(device_t dev, bus_addr_t addr, + uint32_t clear_mask, uint32_t set_mask) +{ + struct ti_gate_softc *sc; + + sc = device_get_softc(dev); + DPRINTF(sc->dev, "clkdev_modify_4: addr %x clear_mask %x set_mask %x\n", + addr, clear_mask, set_mask); + return (SYSCON_UNLOCKED_MODIFY_4(sc->syscon, addr, clear_mask, + set_mask)); +} + +static void +ti_gate_clkdev_device_lock(device_t dev) +{ + struct ti_gate_softc *sc; + + sc = device_get_softc(dev); + DPRINTF(sc->dev, "ti_gate_clkdev_device_lock\n"); + SYSCON_DEVICE_LOCK(sc->syscon->pdev); +} + +static void +ti_gate_clkdev_device_unlock(device_t dev) +{ + struct ti_gate_softc *sc; + + sc = device_get_softc(dev); + DPRINTF(sc->dev, "ti_gate_clkdev_device_unlock\n"); + SYSCON_DEVICE_UNLOCK(sc->syscon->pdev); +} + static int ti_gate_probe(device_t dev) { @@ -108,104 +216,106 @@ return (BUS_PROBE_DEFAULT); } -static int -register_clk(struct ti_gate_softc *sc) { - int err; - sc->clkdom = clkdom_create(sc->sc_dev); - if (sc->clkdom == NULL) { - DPRINTF(sc->sc_dev, "Failed to create clkdom\n"); - return ENXIO; - } - - err = clknode_gate_register(sc->clkdom, &sc->gate_def); - if (err) { - DPRINTF(sc->sc_dev, "clknode_gate_register failed %x\n", err); - return ENXIO; - } - - err = clkdom_finit(sc->clkdom); - if (err) { - DPRINTF(sc->sc_dev, "Clk domain finit fails %x.\n", err); - return ENXIO; - } - - return (0); -} - static int ti_gate_attach(device_t dev) { struct ti_gate_softc *sc; - phandle_t node; - int err; - cell_t value; + phandle_t node; + int err, index; + cell_t value; + const char *node_name; sc = device_get_softc(dev); - sc->sc_dev = dev; + sc->dev = dev; node = ofw_bus_get_node(dev); + /* Get syscon */ + err = SYSCON_GET_HANDLE(dev, &sc->syscon); + if (err != 0) { + panic("Cannot get syscon handle.\n"); + } + + node_name = ofw_bus_get_name(dev); + if (node_name == NULL) { + panic("Cannot get name of the clock node"); + } + /* Get the compatible type */ sc->sc_type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; /* Get the content of reg properties */ - if (sc->sc_type != TI_CLKDM_GATE_CLOCK) { - OF_getencprop(node, "reg", &value, sizeof(value)); - sc->gate_def.offset = value; - } -#if DEBUG_GATE - else { - DPRINTF(sc->sc_dev, "no reg (TI_CLKDM_GATE_CLOCK)\n"); + if (!OF_hasprop(node, "reg")) { + device_printf(sc->dev, "missing reg property\n"); + return (ENXIO); } -#endif + OF_getencprop(node, "reg", &value, sizeof(value)); + sc->gate_def.offset = value; if (OF_hasprop(node, "ti,bit-shift")) { OF_getencprop(node, "ti,bit-shift", &value, sizeof(value)); sc->gate_def.shift = value; - DPRINTF(sc->sc_dev, "ti,bit-shift => shift %x\n", sc->gate_def.shift); + DPRINTF(sc->dev, "ti,bit-shift => shift %x\n", + sc->gate_def.shift); } if (OF_hasprop(node, "ti,set-bit-to-disable")) { sc->gate_def.on_value = 0; sc->gate_def.off_value = 1; - DPRINTF(sc->sc_dev, - "on_value = 0, off_value = 1 (ti,set-bit-to-disable)\n"); + DPRINTF(sc->dev, + "ti,set-bit-to-disable (on = 0, off = 1)\n"); } else { sc->gate_def.on_value = 1; sc->gate_def.off_value = 0; - DPRINTF(sc->sc_dev, "on_value = 1, off_value = 0\n"); + DPRINTF(sc->dev, + "!ti,set-bit-to-disable (on = 1, off = 0)\n"); } sc->gate_def.gate_flags = 0x0; - read_clock_cells(sc->sc_dev, &sc->clock_cell); - create_clkdef(sc->sc_dev, &sc->clock_cell, &sc->gate_def.clkdef); + /* Find parent in lookup table */ + for (index = 0; index < nitems(gate_parent_table); index++) { + if (strcmp(node_name, gate_parent_table[index].node_name) == 0) + break; + } - /* Calculate mask */ - sc->gate_def.mask = (1 << fls(sc->clock_cell.num_real_clocks)) - 1; - DPRINTF(sc->sc_dev, "num_real_clocks %x gate_def.mask %x\n", - sc->clock_cell.num_real_clocks, sc->gate_def.mask); + if (index == nitems(gate_parent_table)) + panic("Cant find clock %s\n", node_name); - err = find_parent_clock_names(sc->sc_dev, &sc->clock_cell, &sc->gate_def.clkdef); + DPRINTF(dev, "%s at gate_parent_table[%d]\n", + node_name, index); - if (err) { - /* free_clkdef will be called in ti_gate_new_pass */ - DPRINTF(sc->sc_dev, "find_parent_clock_names failed\n"); - return (bus_generic_attach(sc->sc_dev)); - } + /* Fill clknode_init_def */ + sc->gate_def.clkdef.id = 1; + sc->gate_def.clkdef.flags = CLK_NODE_STATIC_STRINGS; + sc->gate_def.clkdef.name = gate_parent_table[index].node_name; + sc->gate_def.clkdef.parent_cnt = gate_parent_table[index].parent_cnt; + sc->gate_def.clkdef.parent_names =gate_parent_table[index].parent_names; - err = register_clk(sc); + /* Calculate mask */ + sc->gate_def.mask = (1 << fls(sc->gate_def.clkdef.parent_cnt)) - 1; + DPRINTF(sc->dev, "num_real_clocks %x gate_def.mask %x\n", + sc->gate_def.clkdef.parent_cnt, + sc->gate_def.mask); - if (err) { - /* free_clkdef will be called in ti_gate_new_pass */ - DPRINTF(sc->sc_dev, "register_clk failed\n"); - return (bus_generic_attach(sc->sc_dev)); + sc->clkdom = clkdom_create(sc->dev); + if (sc->clkdom == NULL) { + DPRINTF(sc->dev, "Failed to create clkdom\n"); + return ENXIO; } - sc->attach_done = true; + err = clknode_gate_register(sc->clkdom, &sc->gate_def); + if (err != 0) { + DPRINTF(sc->dev, "clknode_gate_register failed %x\n", err); + return ENXIO; + } - free_clkdef(&sc->gate_def.clkdef); + err = clkdom_finit(sc->clkdom); + if (err != 0) { + DPRINTF(sc->dev, "Clk domain finit fails %x.\n", err); + return ENXIO; + } - return (bus_generic_attach(sc->sc_dev)); + return (bus_generic_attach(sc->dev)); } static int @@ -214,44 +324,18 @@ return (EBUSY); } -static void -ti_gate_new_pass(device_t dev) { - struct ti_gate_softc *sc; - int err; - - sc = device_get_softc(dev); - - if (sc->attach_done) { - return; - } - - err = find_parent_clock_names(sc->sc_dev, &sc->clock_cell, &sc->gate_def.clkdef); - if (err) { - /* free_clkdef will be called in later call to ti_gate_new_pass */ - DPRINTF(sc->sc_dev, "new_pass find_parent_clock_names failed\n"); - return; - } - - err = register_clk(sc); - if (err) { - /* free_clkdef will be called in later call to ti_gate_new_pass */ - DPRINTF(sc->sc_dev, "new_pass register_clk failed\n"); - return; - } - - sc->attach_done = true; - - free_clkdef(&sc->gate_def.clkdef); -} - static device_method_t ti_gate_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ti_gate_probe), DEVMETHOD(device_attach, ti_gate_attach), DEVMETHOD(device_detach, ti_gate_detach), - /* Bus interface */ - DEVMETHOD(bus_new_pass, ti_gate_new_pass), + /* Clock device interface */ + DEVMETHOD(clkdev_device_lock, ti_gate_clkdev_device_lock), + DEVMETHOD(clkdev_device_unlock, ti_gate_clkdev_device_unlock), + DEVMETHOD(clkdev_read_4, ti_gate_clkdev_read_4), + DEVMETHOD(clkdev_write_4, ti_gate_clkdev_write_4), + DEVMETHOD(clkdev_modify_4, ti_gate_clkdev_modify_4), DEVMETHOD_END }; diff --git a/sys/arm/ti/clk/ti_mux_clock.c b/sys/arm/ti/clk/ti_mux_clock.c --- a/sys/arm/ti/clk/ti_mux_clock.c +++ b/sys/arm/ti/clk/ti_mux_clock.c @@ -44,10 +44,14 @@ #include #include +#include + #include #include #include "clock_common.h" +#include "clkdev_if.h" +#include "syscon_if.h" #if 0 #define DPRINTF(dev, msg...) device_printf(dev, msg) @@ -55,18 +59,184 @@ #define DPRINTF(dev, msg...) #endif + +PLIST(sys_clkin_ck_parent) = { + "virt_19200000_ck", + "virt_24000000_ck", + "virt_25000000_ck", + "virt_26000000_ck" +}; +PLIST(pruss_ocp_gclk_parent) = { + "l3_gclk", + "dpll_disp_m2_ck@4a4" +}; +PLIST(timer1_fck_parent) = { + "sys_clkin_ck@40", + "clk-24mhz-clkctrl@14c_0", + "tclkin_ck", + "clk_rc32k_ck", + "clk_32768_ck" +}; +PLIST(timer2_fck_parent) = { + "tclkin_ck", + "sys_clkin_ck@40", + "clk-24mhz-clkctrl@14c_0" +}; +PLIST(timer3_fck_parent) = { + "tclkin_ck", + "sys_clkin_ck@40", + "clk-24mhz-clkctrl@14c_0" +}; +PLIST(timer4_fck_parent) = +{ + "tclkin_ck", + "sys_clkin_ck@40", + "clk-24mhz-clkctrl@14c_0" +}; +PLIST(timer5_fck_parent) = +{ + "tclkin_ck", + "sys_clkin_ck@40", + "clk-24mhz-clkctrl@14c_0" +}; +PLIST(timer6_fck_parent) = +{ + "tclkin_ck", + "sys_clkin_ck@40", + "clk-24mhz-clkctrl@14c_0" +}; +PLIST(timer7_fck_parent) = +{ + "tclkin_ck", + "sys_clkin_ck@40", + "clk-24mhz-clkctrl@14c_0" +}; +PLIST(wdt1_fck_parent) = +{ + "clk_rc32k_ck", + "clk-24mhz-clkctrl@14c_0" +}; +PLIST(cpsw_cpts_tft_clk_parent) = +{ + "dpll_core_m5_ck@484", + "dpll_core_m4_ck@480" +}; +PLIST(gpio0_dbclk_mux_ck_parent) = +{ + "clk_rc32k_ck", + "clk_32768_ck", + "clk-24mhz-clkctrl@14c_0" +}; +PLIST(lcd_gclk_parent) = +{ + "dpll_disp_m2_ck@4a4", + "dpll_core_m5_ck@484", + "dpll_per_m2_ck@4ac" +}; +PLIST(gfx_fclk_clksel_ck_parent) = +{ + "dpll_core_m4_ck@480", + "dpll_per_m2_ck@4ac" +}; +PLIST(sysclkout_pre_ck_parent) = +{ + "clk_32768_ck", + "l3_gclk", + "dpll_ddr_m2_ck@4a0", + "dpll_per_m2_ck@4ac", + "lcd_gclk@534" +}; + +static struct parent_lookup_table mux_parent_table[] = +{ + { + "sys_clkin_ck@40", + nitems(sys_clkin_ck_parent), + sys_clkin_ck_parent + }, + { + "pruss_ocp_gclk@530", + nitems(pruss_ocp_gclk_parent), + pruss_ocp_gclk_parent + }, + { + "timer1_fck@528", + nitems(timer1_fck_parent), + timer1_fck_parent + }, + { + "timer2_fck@508", + nitems(timer2_fck_parent), + timer2_fck_parent + }, + { + "timer3_fck@50c", + nitems(timer3_fck_parent), + timer3_fck_parent + }, + { + "timer4_fck@510", + nitems(timer4_fck_parent), + timer4_fck_parent + }, + { + "timer5_fck@518", + nitems(timer5_fck_parent), + timer5_fck_parent + }, + { + "timer6_fck@51c", + nitems(timer6_fck_parent), + timer6_fck_parent + }, + { + "timer7_fck@504", + nitems(timer7_fck_parent), + timer7_fck_parent + }, + { + "wdt1_fck@538", + nitems(wdt1_fck_parent), + wdt1_fck_parent + }, + { + "cpsw_cpts_rft_clk@520", + nitems(cpsw_cpts_tft_clk_parent), + cpsw_cpts_tft_clk_parent + }, + { + "gpio0_dbclk_mux_ck@53c", + nitems(gpio0_dbclk_mux_ck_parent), + gpio0_dbclk_mux_ck_parent + }, + { + "lcd_gclk@534", + nitems(lcd_gclk_parent), + lcd_gclk_parent + }, + { + "gfx_fclk_clksel_ck@52c", + nitems(gfx_fclk_clksel_ck_parent), + gfx_fclk_clksel_ck_parent + }, + { + "sysclkout_pre_ck@700", + nitems(sysclkout_pre_ck_parent), + sysclkout_pre_ck_parent + }, +}; + /* * Devicetree description * Documentation/devicetree/bindings/clock/ti/mux.txt */ struct ti_mux_softc { - device_t sc_dev; - bool attach_done; + device_t dev; struct clk_mux_def mux_def; - struct clock_cell_info clock_cell; struct clkdom *clkdom; + struct syscon *syscon; }; static int ti_mux_probe(device_t dev); @@ -84,56 +254,101 @@ }; static int -ti_mux_probe(device_t dev) +ti_mux_clkdev_write_4(device_t dev, bus_addr_t addr, uint32_t val) { - if (!ofw_bus_status_okay(dev)) - return (ENXIO); + struct ti_mux_softc *sc; - if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) - return (ENXIO); + sc = device_get_softc(dev); + DPRINTF(sc->dev, "mux_clkdev_write_4: addr %x val %x\n", + addr, val); + return (SYSCON_UNLOCKED_WRITE_4(sc->syscon, addr, val)); +} - device_set_desc(dev, "TI Mux Clock"); +static int +ti_mux_clkdev_read_4(device_t dev, bus_addr_t addr, uint32_t *val) +{ + struct ti_mux_softc *sc; + uint32_t rdval; - return (BUS_PROBE_DEFAULT); + sc = device_get_softc(dev); + + rdval = SYSCON_UNLOCKED_READ_4(sc->syscon, addr); + *val = rdval; + DPRINTF(sc->dev, "clkdev_read_4: addr %x val %x\n", + addr, *val); + return (0); } static int -register_clk(struct ti_mux_softc *sc) { - int err; +ti_mux_clkdev_modify_4(device_t dev, bus_addr_t addr, + uint32_t clear_mask, uint32_t set_mask) +{ + struct ti_mux_softc *sc; - sc->clkdom = clkdom_create(sc->sc_dev); - if (sc->clkdom == NULL) { - DPRINTF(sc->sc_dev, "Failed to create clkdom\n"); - return ENXIO; - } + sc = device_get_softc(dev); + DPRINTF(sc->dev, "clkdev_modify_4: addr %x clear %x mask %x\n", + addr, clear_mask, set_mask); + return (SYSCON_UNLOCKED_MODIFY_4(sc->syscon, addr, clear_mask, + set_mask)); +} - err = clknode_mux_register(sc->clkdom, &sc->mux_def); - if (err) { - DPRINTF(sc->sc_dev, "clknode_mux_register failed %x\n", err); - return ENXIO; - } +static void +ti_mux_clkdev_device_lock(device_t dev) +{ + struct ti_mux_softc *sc; - err = clkdom_finit(sc->clkdom); - if (err) { - DPRINTF(sc->sc_dev, "Clk domain finit fails %x.\n", err); - return ENXIO; - } + sc = device_get_softc(dev); + DPRINTF(sc->dev, "ti_mux_clkdev_device_lock\n"); + SYSCON_DEVICE_LOCK(sc->syscon->pdev); +} + +static void +ti_mux_clkdev_device_unlock(device_t dev) +{ + struct ti_mux_softc *sc; + + sc = device_get_softc(dev); + DPRINTF(sc->dev, "ti_mux_clkdev_device_unlock\n"); + SYSCON_DEVICE_UNLOCK(sc->syscon->pdev); +} - return 0; +static int +ti_mux_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) + return (ENXIO); + + device_set_desc(dev, "TI Mux Clock"); + + return (BUS_PROBE_DEFAULT); } static int ti_mux_attach(device_t dev) { struct ti_mux_softc *sc; - phandle_t node; - int err; - cell_t value; + phandle_t node; + int err, index; + cell_t value; + const char *node_name; sc = device_get_softc(dev); - sc->sc_dev = dev; + sc->dev = dev; node = ofw_bus_get_node(dev); + err = SYSCON_GET_HANDLE(device_get_parent(dev), &sc->syscon); + if (err != 0) { + panic("Cannot get syscon handle.\n"); + } + + node_name = ofw_bus_get_name(dev); + if (node_name == NULL) { + panic("Cannot get name of the clock node"); + } + /* Grab the content of reg properties */ OF_getencprop(node, "reg", &value, sizeof(value)); sc->mux_def.offset = value; @@ -141,84 +356,70 @@ if (OF_hasprop(node, "ti,bit-shift")) { OF_getencprop(node, "ti,bit-shift", &value, sizeof(value)); sc->mux_def.shift = value; - DPRINTF(sc->sc_dev, "ti,bit-shift => shift %x\n", sc->mux_def.shift); + DPRINTF(sc->dev, "ti,bit-shift => shift %x\n", + sc->mux_def.shift); } if (OF_hasprop(node, "ti,index-starts-at-one")) { /* FIXME: Add support in dev/extres/clk */ /*sc->mux_def.mux_flags = ... */ - device_printf(sc->sc_dev, "ti,index-starts-at-one - Not implemented\n"); + device_printf(sc->dev, + "ti,index-starts-at-one - Not implemented\n"); } if (OF_hasprop(node, "ti,set-rate-parent")) - device_printf(sc->sc_dev, "ti,set-rate-parent - Not implemented\n"); + device_printf(sc->dev, + "ti,set-rate-parent - Not implemented\n"); if (OF_hasprop(node, "ti,latch-bit")) - device_printf(sc->sc_dev, "ti,latch-bit - Not implemented\n"); - - read_clock_cells(sc->sc_dev, &sc->clock_cell); - - create_clkdef(sc->sc_dev, &sc->clock_cell, &sc->mux_def.clkdef); - - /* Figure out the width from ti_max_div */ - if (sc->mux_def.mux_flags) - sc->mux_def.width = fls(sc->clock_cell.num_real_clocks-1); - else - sc->mux_def.width = fls(sc->clock_cell.num_real_clocks); - - DPRINTF(sc->sc_dev, "sc->clock_cell.num_real_clocks %x def.width %x\n", - sc->clock_cell.num_real_clocks, sc->mux_def.width); + device_printf(sc->dev, + "ti,latch-bit - Not implemented\n"); - err = find_parent_clock_names(sc->sc_dev, &sc->clock_cell, &sc->mux_def.clkdef); - if (err) { - /* free_clkdef will be called in ti_mux_new_pass */ - DPRINTF(sc->sc_dev, "find_parent_clock_names failed\n"); - return (bus_generic_attach(sc->sc_dev)); + /* Find parent in lookup table */ + for (index = 0; index < nitems(mux_parent_table); index++) { + if (strcmp(node_name, mux_parent_table[index].node_name) == 0) + break; } + if (index == nitems(mux_parent_table)) + panic("Cant find clock %s\n", node_name); - err = register_clk(sc); - - if (err) { - /* free_clkdef will be called in ti_mux_new_pass */ - DPRINTF(sc->sc_dev, "register_clk failed\n"); - return (bus_generic_attach(sc->sc_dev)); - } + DPRINTF(sc->dev, "%s at mux_parent_table[%d]\n", + node_name, index); + /* Fill clknode_init_def */ + sc->mux_def.clkdef.id = 1; + sc->mux_def.clkdef.flags = CLK_NODE_STATIC_STRINGS; - sc->attach_done = true; - - free_clkdef(&sc->mux_def.clkdef); - - return (bus_generic_attach(sc->sc_dev)); -} + sc->mux_def.clkdef.name = mux_parent_table[index].node_name; + sc->mux_def.clkdef.parent_cnt = mux_parent_table[index].parent_cnt; + sc->mux_def.clkdef.parent_names = mux_parent_table[index].parent_names; -static void -ti_mux_new_pass(device_t dev) -{ - struct ti_mux_softc *sc; - int err; + /* Figure out the width from ti_max_div */ + if (sc->mux_def.mux_flags) + sc->mux_def.width = fls(sc->mux_def.clkdef.parent_cnt-1); + else + sc->mux_def.width = fls(sc->mux_def.clkdef.parent_cnt); - sc = device_get_softc(dev); + DPRINTF(sc->dev, "parents %x def.width %x\n", + sc->mux_def.clkdef.parent_cnt, sc->mux_def.width); - if (sc->attach_done) { - return; + sc->clkdom = clkdom_create(sc->dev); + if (sc->clkdom == NULL) { + DPRINTF(sc->dev, "Failed to create clkdom\n"); + return ENXIO; } - err = find_parent_clock_names(sc->sc_dev, &sc->clock_cell, &sc->mux_def.clkdef); - if (err) { - /* free_clkdef will be called in later call to ti_mux_new_pass */ - DPRINTF(sc->sc_dev, "ti_mux_new_pass find_parent_clock_names failed\n"); - return; + err = clknode_mux_register(sc->clkdom, &sc->mux_def); + if (err != 0) { + DPRINTF(sc->dev, "clknode_mux_register failed %x\n", err); + return ENXIO; } - err = register_clk(sc); - if (err) { - /* free_clkdef will be called in later call to ti_mux_new_pass */ - DPRINTF(sc->sc_dev, "ti_mux_new_pass register_clk failed\n"); - return; + err = clkdom_finit(sc->clkdom); + if (err != 0) { + DPRINTF(sc->dev, "Clk domain finit fails %x.\n", err); + return ENXIO; } - sc->attach_done = true; - - free_clkdef(&sc->mux_def.clkdef); + return (bus_generic_attach(sc->dev)); } static int @@ -233,8 +434,12 @@ DEVMETHOD(device_attach, ti_mux_attach), DEVMETHOD(device_detach, ti_mux_detach), - /* Bus interface */ - DEVMETHOD(bus_new_pass, ti_mux_new_pass), + /* Clock device interface */ + DEVMETHOD(clkdev_device_lock, ti_mux_clkdev_device_lock), + DEVMETHOD(clkdev_device_unlock, ti_mux_clkdev_device_unlock), + DEVMETHOD(clkdev_read_4, ti_mux_clkdev_read_4), + DEVMETHOD(clkdev_write_4, ti_mux_clkdev_write_4), + DEVMETHOD(clkdev_modify_4, ti_mux_clkdev_modify_4), DEVMETHOD_END }; diff --git a/sys/arm/ti/files.ti b/sys/arm/ti/files.ti --- a/sys/arm/ti/files.ti +++ b/sys/arm/ti/files.ti @@ -20,7 +20,6 @@ arm/ti/ti_spi.c optional ti_spi arm/ti/ti_sysc.c standard -arm/ti/clk/clock_common.c standard arm/ti/clk/ti_clk_clkctrl.c standard arm/ti/clk/ti_clkctrl.c standard arm/ti/clk/ti_clk_dpll.c standard diff --git a/sys/arm/ti/ti_pinmux.c b/sys/arm/ti/ti_pinmux.c --- a/sys/arm/ti/ti_pinmux.c +++ b/sys/arm/ti/ti_pinmux.c @@ -455,6 +455,7 @@ static devclass_t ti_pinmux_devclass; -DRIVER_MODULE(ti_pinmux, simplebus, ti_pinmux_driver, ti_pinmux_devclass, 0, 0); +EARLY_DRIVER_MODULE(ti_pinmux, simplebus, ti_pinmux_driver, + ti_pinmux_devclass, 0, 0, BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE); MODULE_VERSION(ti_pinmux, 1); MODULE_DEPEND(ti_pinmux, ti_scm, 1, 1, 1); diff --git a/sys/arm/ti/ti_prcm.c b/sys/arm/ti/ti_prcm.c --- a/sys/arm/ti/ti_prcm.c +++ b/sys/arm/ti/ti_prcm.c @@ -40,18 +40,14 @@ #include #include #include -#include +#include #include -#include -#include -#include #include -#include -#include #include #include #include +#include #include @@ -59,6 +55,12 @@ #include #include +#include +#include +#include +#include + +#include "syscon_if.h" #include "clkdev_if.h" #if 0 @@ -67,17 +69,7 @@ #define DPRINTF(dev, msg...) #endif -struct ti_prcm_softc { - struct simplebus_softc sc_simplebus; - device_t dev; - struct resource * mem_res; - bus_space_tag_t bst; - bus_space_handle_t bsh; - int attach_done; - struct mtx mtx; -}; - -static struct ti_prcm_softc *ti_prcm_sc = NULL; +static device_t ti_prcm_dev; static void omap4_prcm_reset(void); static void am335x_prcm_reset(void); @@ -102,83 +94,234 @@ #define TI_PRCM_END 0 static struct ofw_compat_data compat_data[] = { - { "ti,am3-prcm", TI_AM3_PRCM }, - { "ti,am4-prcm", TI_AM4_PRCM }, - { "ti,omap2-prcm", TI_OMAP2_PRCM }, - { "ti,omap3-prm", TI_OMAP3_PRM }, - { "ti,omap3-cm", TI_OMAP3_CM }, - { "ti,omap4-cm1", TI_OMAP4_CM1 }, - { "ti,omap4-prm", TI_OMAP4_PRM }, - { "ti,omap4-cm2", TI_OMAP4_CM2 }, - { "ti,omap4-scrm", TI_OMAP4_SCRM }, - { "ti,omap5-prm", TI_OMAP5_PRM }, - { "ti,omap5-cm-core-aon", TI_OMAP5_CM_CORE_AON }, - { "ti,omap5-scrm", TI_OMAP5_SCRM }, - { "ti,omap5-cm-core", TI_OMAP5_CM_CORE }, - { "ti,dra7-prm", TI_DRA7_PRM }, - { "ti,dra7-cm-core-aon", TI_DRA7_CM_CORE_AON }, - { "ti,dra7-cm-core", TI_DRA7_CM_CORE }, - { "ti,dm814-prcm", TI_DM814_PRCM }, - { "ti,dm816-prcm", TI_DM816_PRCM }, - { NULL, TI_PRCM_END} + { "ti,am3-prcm", TI_AM3_PRCM }, + { "ti,am4-prcm", TI_AM4_PRCM }, + { "ti,omap2-prcm", TI_OMAP2_PRCM }, + { "ti,omap3-prm", TI_OMAP3_PRM }, + { "ti,omap3-cm", TI_OMAP3_CM }, + { "ti,omap4-cm1", TI_OMAP4_CM1 }, + { "ti,omap4-prm", TI_OMAP4_PRM }, + { "ti,omap4-cm2", TI_OMAP4_CM2 }, + { "ti,omap4-scrm", TI_OMAP4_SCRM }, + { "ti,omap5-prm", TI_OMAP5_PRM }, + { "ti,omap5-cm-core-aon", TI_OMAP5_CM_CORE_AON }, + { "ti,omap5-scrm", TI_OMAP5_SCRM }, + { "ti,omap5-cm-core", TI_OMAP5_CM_CORE }, + { "ti,dra7-prm", TI_DRA7_PRM }, + { "ti,dra7-cm-core-aon", TI_DRA7_CM_CORE_AON }, + { "ti,dra7-cm-core", TI_DRA7_CM_CORE }, + { "ti,dm814-prcm", TI_DM814_PRCM }, + { "ti,dm816-prcm", TI_DM816_PRCM }, + { NULL, TI_PRCM_END} +}; + +static struct clk_link_def scm_clocks[] = { + LINK("sys_clkin_ck@40"), + 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@44e10664"), + LINK("ehrpwm1_tbclk@44e10664"), + LINK("ehrpwm2_tbclk@44e10664"), +}; + +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"), }; static int ti_prcm_probe(device_t dev) { + int i, err; + struct clkdom *clkdom; + if (!ofw_bus_status_okay(dev)) 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); - } device_set_desc(dev, "TI Power and Clock Management"); - return(BUS_PROBE_DEFAULT); -} -static int -ti_prcm_attach(device_t dev) -{ - struct ti_prcm_softc *sc; - phandle_t node, child; - int rid; - - sc = device_get_softc(dev); - sc->dev = dev; + clkdom = clkdom_create(dev); + if (clkdom == NULL) + panic("Cannot create clkdom\n"); - node = ofw_bus_get_node(sc->dev); - simplebus_init(sc->dev, node); - - if (simplebus_fill_ranges(node, &sc->sc_simplebus) < 0) { - device_printf(sc->dev, "could not get ranges\n"); - return (ENXIO); - } - if (sc->sc_simplebus.nranges == 0) { - device_printf(sc->dev, "nranges == 0\n"); - return (ENXIO); + /* + * 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); } - - sc->mem_res = bus_alloc_resource(sc->dev, SYS_RES_MEMORY, &rid, - sc->sc_simplebus.ranges[0].host, - (sc->sc_simplebus.ranges[0].host + - sc->sc_simplebus.ranges[0].size - 1), - sc->sc_simplebus.ranges[0].size, - RF_ACTIVE | RF_SHAREABLE); - - if (sc->mem_res == NULL) { - return (ENXIO); + 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); } - sc->bst = rman_get_bustag(sc->mem_res); - sc->bsh = rman_get_bushandle(sc->mem_res); - - mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF); + if (clkdom_finit(clkdom) != 0) + panic("cannot finalize clkdom initialization\n"); - /* Fixme: for xxx_prcm_reset functions. - * Get rid of global variables? - */ - ti_prcm_sc = sc; + /* Setup reset handler */ + ti_prcm_dev = dev; switch(ti_chip()) { #ifdef SOC_OMAP4 @@ -193,32 +336,26 @@ #endif } - bus_generic_probe(sc->dev); - for (child = OF_child(node); child != 0; child = OF_peer(child)) { - simplebus_add_device(dev, child, 0, NULL, -1, NULL); - } - - return (bus_generic_attach(sc->dev)); + return (BUS_PROBE_DEFAULT); } int ti_prcm_write_4(device_t dev, bus_addr_t addr, uint32_t val) { - struct ti_prcm_softc *sc; + struct syscon_generic_softc *sc; sc = device_get_softc(dev); - DPRINTF(sc->dev, "offset=%lx write %x\n", addr, val); - bus_space_write_4(sc->bst, sc->bsh, addr, val); - return (0); + DPRINTF(sc->dev, "ti_prcm_write_4: offset=%lx write %x\n", addr, val); + return (SYSCON_UNLOCKED_WRITE_4(sc->syscon, addr, val)); } + int ti_prcm_read_4(device_t dev, bus_addr_t addr, uint32_t *val) { - struct ti_prcm_softc *sc; + struct syscon_generic_softc *sc; sc = device_get_softc(dev); - - *val = bus_space_read_4(sc->bst, sc->bsh, addr); + *val = SYSCON_UNLOCKED_READ_4(sc->syscon, addr); DPRINTF(sc->dev, "offset=%lx Read %x\n", addr, *val); return (0); } @@ -226,41 +363,53 @@ int ti_prcm_modify_4(device_t dev, bus_addr_t addr, uint32_t clr, uint32_t set) { - struct ti_prcm_softc *sc; - uint32_t reg; + struct syscon_generic_softc *sc; sc = device_get_softc(dev); - - reg = bus_space_read_4(sc->bst, sc->bsh, addr); - reg &= ~clr; - reg |= set; - bus_space_write_4(sc->bst, sc->bsh, addr, reg); - DPRINTF(sc->dev, "offset=%lx reg: %x (clr %x set %x)\n", addr, reg, clr, set); - - return (0); + DPRINTF(sc->dev, "ti_prcm_modify_4: addr %x clear_mask %x set_mask %x\n", + addr, clr, set); + return (SYSCON_UNLOCKED_MODIFY_4(sc->syscon, addr, clr, + set)); } void ti_prcm_device_lock(device_t dev) { - struct ti_prcm_softc *sc; + struct syscon_generic_softc *sc; sc = device_get_softc(dev); - mtx_lock(&sc->mtx); + DPRINTF(sc->dev, "ti_prcm_device_lock\n"); + SYSCON_DEVICE_LOCK(sc->syscon->pdev); } void ti_prcm_device_unlock(device_t dev) { - struct ti_prcm_softc *sc; + struct syscon_generic_softc *sc; + + sc = device_get_softc(dev); + DPRINTF(sc->dev, "ti_prcm_device_unlock\n"); + SYSCON_DEVICE_UNLOCK(sc->syscon->pdev); +} + +static int +ti_prcm_get_handle(device_t dev, struct syscon **syscon) +{ + struct syscon_generic_softc *sc; sc = device_get_softc(dev); - mtx_unlock(&sc->mtx); + *syscon = sc->syscon; + if (*syscon == NULL) + return (ENODEV); + return (0); } static device_method_t ti_prcm_methods[] = { + /* Device interface */ DEVMETHOD(device_probe, ti_prcm_probe), - DEVMETHOD(device_attach, ti_prcm_attach), + + /* Syscon */ + DEVMETHOD(syscon_get_handle, ti_prcm_get_handle), /* clkdev interface */ DEVMETHOD(clkdev_write_4, ti_prcm_write_4), @@ -273,16 +422,15 @@ }; DEFINE_CLASS_1(ti_prcm, ti_prcm_driver, ti_prcm_methods, - sizeof(struct ti_prcm_softc), simplebus_driver); + sizeof(struct syscon_generic_softc), syscon_generic_driver); static devclass_t ti_prcm_devclass; -EARLY_DRIVER_MODULE(ti_prcm, ofwbus, ti_prcm_driver, - ti_prcm_devclass, 0, 0, BUS_PASS_BUS); EARLY_DRIVER_MODULE(ti_prcm, simplebus, ti_prcm_driver, ti_prcm_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); + MODULE_VERSION(ti_prcm, 1); -MODULE_DEPEND(ti_prcm, ti_scm, 1, 1, 1); +MODULE_DEPEND(ti_prcm, syscon_generic_dev, 1, 1, 1); /* From sys/arm/ti/am335x/am335x_prcm.c * Copyright (c) 2012 Damjan Marion @@ -293,7 +441,9 @@ static void am335x_prcm_reset(void) { - ti_prcm_write_4(ti_prcm_sc->dev, AM335x_PRM_RSTCTRL, (1<<1)); + ti_prcm_device_lock(ti_prcm_dev); + ti_prcm_write_4(ti_prcm_dev, AM335x_PRM_RSTCTRL, (1<<1)); + ti_prcm_device_unlock(ti_prcm_dev); } /* FIXME: Is this correct - or should the license part be ontop? */ @@ -337,8 +487,10 @@ { uint32_t reg; - ti_prcm_read_4(ti_prcm_sc->dev, PRM_RSTCTRL, ®); + ti_prcm_device_lock(ti_prcm_dev); + ti_prcm_read_4(ti_prcm_dev, PRM_RSTCTRL, ®); reg = reg | PRM_RSTCTRL_RESET; - ti_prcm_write_4(ti_prcm_sc->dev, PRM_RSTCTRL, reg); - ti_prcm_read_4(ti_prcm_sc->dev, PRM_RSTCTRL, ®); + ti_prcm_write_4(ti_prcm_dev, PRM_RSTCTRL, reg); + ti_prcm_read_4(ti_prcm_dev, PRM_RSTCTRL, ®); + ti_prcm_device_unlock(ti_prcm_dev); } diff --git a/sys/arm/ti/ti_prm.c b/sys/arm/ti/ti_prm.c --- a/sys/arm/ti/ti_prm.c +++ b/sys/arm/ti/ti_prm.c @@ -42,9 +42,12 @@ #include +#include #include #include +#include "syscon_if.h" + #if 0 #define DPRINTF(dev, msg...) device_printf(dev, msg) #else @@ -58,6 +61,7 @@ device_t dev; uint8_t type; bool has_reset; + struct syscon *syscon; }; /* Device */ @@ -106,6 +110,7 @@ { struct ti_prm_softc *sc; phandle_t node; + int err; sc = device_get_softc(dev); sc->dev = dev; @@ -113,9 +118,13 @@ node = ofw_bus_get_node(sc->dev); - if (OF_hasprop(node, "#reset-cells")) { + err = SYSCON_GET_HANDLE(dev, &sc->syscon); + if (err != 0) + panic("Cannot get syscon handle.\n"); + + if (OF_hasprop(node, "#reset-cells") == 1) sc->has_reset = true; - } else + else sc->has_reset = false; /* Make device visible for other drivers */ @@ -139,56 +148,9 @@ if (sc->has_reset == false) return 1; - err = ti_prm_modify_4(dev, TI_PRM_PER_RSTCTRL, 0x2, 0x00); - return (err); -} - -int -ti_prm_write_4(device_t dev, bus_addr_t addr, uint32_t val) -{ - struct ti_prm_softc *sc; - device_t parent; - - parent = device_get_parent(dev); - sc = device_get_softc(dev); - DPRINTF(sc->dev, "offset=%lx write %x\n", addr, val); - ti_prcm_device_lock(parent); - ti_prcm_write_4(parent, addr, val); - ti_prcm_device_unlock(parent); - return (0); -} + err = SYSCON_MODIFY_4(sc->syscon, TI_PRM_PER_RSTCTRL, 0x2, 0x00); -int -ti_prm_read_4(device_t dev, bus_addr_t addr, uint32_t *val) -{ - struct ti_prm_softc *sc; - device_t parent; - - parent = device_get_parent(dev); - sc = device_get_softc(dev); - - ti_prcm_device_lock(parent); - ti_prcm_read_4(parent, addr, val); - ti_prcm_device_unlock(parent); - DPRINTF(sc->dev, "offset=%lx Read %x\n", addr, *val); - return (0); -} - -int -ti_prm_modify_4(device_t dev, bus_addr_t addr, uint32_t clr, uint32_t set) -{ - struct ti_prm_softc *sc; - device_t parent; - - parent = device_get_parent(dev); - sc = device_get_softc(dev); - - ti_prcm_device_lock(parent); - ti_prcm_modify_4(parent, addr, clr, set); - ti_prcm_device_unlock(parent); - DPRINTF(sc->dev, "offset=%lx (clr %x set %x)\n", addr, clr, set); - - return (0); + return (err); } static device_method_t ti_prm_methods[] = { diff --git a/sys/arm/ti/ti_scm_syscon.c b/sys/arm/ti/ti_scm_syscon.c --- a/sys/arm/ti/ti_scm_syscon.c +++ b/sys/arm/ti/ti_scm_syscon.c @@ -32,178 +32,57 @@ __FBSDID("$FreeBSD$"); #include -#include +#include #include #include -#include -#include -#include -#include #include - -#include -#include - -#include +#include #include #include #include -#include "syscon_if.h" #include -#include "clkdev_if.h" - +#include #include +#include "syscon_if.h" + #if 0 #define DPRINTF(dev, msg...) device_printf(dev, msg) #else #define DPRINTF(dev, msg...) #endif -MALLOC_DECLARE(M_SYSCON); - -struct ti_scm_syscon_softc { - struct simplebus_softc sc_simplebus; - device_t dev; - struct syscon * syscon; - struct resource * res[1]; - bus_space_tag_t bst; - bus_space_handle_t bsh; - struct mtx mtx; -}; - -static struct resource_spec ti_scm_syscon_res_spec[] = { - { SYS_RES_MEMORY, 0, RF_ACTIVE | RF_SHAREABLE }, - { -1, 0 } -}; - -/* Device */ -static struct ofw_compat_data compat_data[] = { - { "syscon", 1 }, - { NULL, 0 } -}; - -/* --- dev/extres/syscon syscon_method_t interface --- */ -static int -ti_scm_syscon_write_4(struct syscon *syscon, bus_size_t offset, uint32_t val) -{ - struct ti_scm_syscon_softc *sc; - - sc = device_get_softc(syscon->pdev); - DPRINTF(sc->dev, "offset=%lx write %x\n", offset, val); - mtx_lock(&sc->mtx); - bus_space_write_4(sc->bst, sc->bsh, offset, val); - mtx_unlock(&sc->mtx); - return (0); -} - -static uint32_t -ti_scm_syscon_read_4(struct syscon *syscon, bus_size_t offset) -{ - struct ti_scm_syscon_softc *sc; - uint32_t val; - - sc = device_get_softc(syscon->pdev); - - mtx_lock(&sc->mtx); - val = bus_space_read_4(sc->bst, sc->bsh, offset); - mtx_unlock(&sc->mtx); - DPRINTF(sc->dev, "offset=%lx Read %x\n", offset, val); - return (val); -} -static int -ti_scm_syscon_modify_4(struct syscon *syscon, bus_size_t offset, uint32_t clr, uint32_t set) -{ - struct ti_scm_syscon_softc *sc; - uint32_t reg; - - sc = device_get_softc(syscon->pdev); - - mtx_lock(&sc->mtx); - reg = bus_space_read_4(sc->bst, sc->bsh, offset); - reg &= ~clr; - reg |= set; - bus_space_write_4(sc->bst, sc->bsh, offset, reg); - mtx_unlock(&sc->mtx); - DPRINTF(sc->dev, "offset=%lx reg: %x (clr %x set %x)\n", offset, reg, clr, set); - - return (0); -} - -static syscon_method_t ti_scm_syscon_reg_methods[] = { - SYSCONMETHOD(syscon_read_4, ti_scm_syscon_read_4), - SYSCONMETHOD(syscon_write_4, ti_scm_syscon_write_4), - SYSCONMETHOD(syscon_modify_4, ti_scm_syscon_modify_4), - - SYSCONMETHOD_END -}; - -DEFINE_CLASS_1(ti_scm_syscon_reg, ti_scm_syscon_reg_class, ti_scm_syscon_reg_methods, - 0, syscon_class); - /* device interface */ static int ti_scm_syscon_probe(device_t dev) { + const char *name; if (!ofw_bus_status_okay(dev)) return (ENXIO); if (!ti_soc_is_supported()) return (ENXIO); - if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) - return (ENXIO); - - device_set_desc(dev, "TI OMAP Control Module Syscon"); - return(BUS_PROBE_DEFAULT); -} - -static int -ti_scm_syscon_attach(device_t dev) -{ - struct ti_scm_syscon_softc *sc; - phandle_t node, child; - int err; - - sc = device_get_softc(dev); - sc->dev = dev; - - if (bus_alloc_resources(dev, ti_scm_syscon_res_spec, sc->res)) { - device_printf(sc->dev, "Cant allocate resources\n"); + /* Need to be both "syscon" and "simple-bus" */ + if (ofw_bus_is_compatible(dev, "syscon") == 0 || + ofw_bus_is_compatible(dev, "simple-bus") == 0) return (ENXIO); - } - - sc->dev = dev; - sc->bst = rman_get_bustag(sc->res[0]); - sc->bsh = rman_get_bushandle(sc->res[0]); - - mtx_init(&sc->mtx, device_get_nameunit(sc->dev), NULL, MTX_DEF); - node = ofw_bus_get_node(sc->dev); - /* dev/extres/syscon interface */ - sc->syscon = syscon_create_ofw_node(dev, &ti_scm_syscon_reg_class, node); - if (sc->syscon == NULL) { - device_printf(dev, "Failed to create/register syscon\n"); + /* Require the node are named scm_conf@0 */ + name = ofw_bus_get_name(dev); + if (name == NULL || strcmp(name, "scm_conf@0") != 0) return (ENXIO); - } - simplebus_init(sc->dev, node); - - err = bus_generic_probe(sc->dev); - for (child = OF_child(node); child != 0; child = OF_peer(child)) { - simplebus_add_device(sc->dev, child, 0, NULL, -1, NULL); - } - - return (bus_generic_attach(sc->dev)); + device_set_desc(dev, "TI OMAP Control Module Syscon"); + return(BUS_PROBE_DEFAULT); } -/* syscon interface */ static int ti_scm_syscon_get_handle(device_t dev, struct syscon **syscon) { - struct ti_scm_syscon_softc *sc; + struct syscon_generic_softc *sc; sc = device_get_softc(dev); *syscon = sc->syscon; @@ -212,86 +91,19 @@ return (0); } -/* clkdev interface */ -static int -ti_scm_syscon_clk_write_4(device_t dev, bus_addr_t addr, uint32_t val) -{ - struct ti_scm_syscon_softc *sc; - - sc = device_get_softc(dev); - DPRINTF(sc->dev, "offset=%lx write %x\n", addr, val); - bus_space_write_4(sc->bst, sc->bsh, addr, val); - return (0); -} - -static int -ti_scm_syscon_clk_read_4(device_t dev, bus_addr_t addr, uint32_t *val) -{ - struct ti_scm_syscon_softc *sc; - - sc = device_get_softc(dev); - - *val = bus_space_read_4(sc->bst, sc->bsh, addr); - DPRINTF(sc->dev, "offset=%lx Read %x\n", addr, *val); - return (0); -} - -static int -ti_scm_syscon_clk_modify_4(device_t dev, bus_addr_t addr, uint32_t clr, uint32_t set) -{ - struct ti_scm_syscon_softc *sc; - uint32_t reg; - - sc = device_get_softc(dev); - - reg = bus_space_read_4(sc->bst, sc->bsh, addr); - reg &= ~clr; - reg |= set; - bus_space_write_4(sc->bst, sc->bsh, addr, reg); - DPRINTF(sc->dev, "offset=%lx reg: %x (clr %x set %x)\n", addr, reg, clr, set); - - return (0); -} - -static void -ti_scm_syscon_clk_device_lock(device_t dev) -{ - struct ti_scm_syscon_softc *sc; - - sc = device_get_softc(dev); - mtx_lock(&sc->mtx); -} - -static void -ti_scm_syscon_clk_device_unlock(device_t dev) -{ - struct ti_scm_syscon_softc *sc; - sc = device_get_softc(dev); - mtx_unlock(&sc->mtx); -} - static device_method_t ti_scm_syscon_methods[] = { DEVMETHOD(device_probe, ti_scm_syscon_probe), - DEVMETHOD(device_attach, ti_scm_syscon_attach), - - /* syscon interface */ DEVMETHOD(syscon_get_handle, ti_scm_syscon_get_handle), - /* clkdev interface */ - DEVMETHOD(clkdev_write_4, ti_scm_syscon_clk_write_4), - DEVMETHOD(clkdev_read_4, ti_scm_syscon_clk_read_4), - DEVMETHOD(clkdev_modify_4, ti_scm_syscon_clk_modify_4), - DEVMETHOD(clkdev_device_lock, ti_scm_syscon_clk_device_lock), - DEVMETHOD(clkdev_device_unlock, ti_scm_syscon_clk_device_unlock), - DEVMETHOD_END }; DEFINE_CLASS_1(ti_scm_syscon, ti_scm_syscon_driver, ti_scm_syscon_methods, - sizeof(struct ti_scm_syscon_softc), simplebus_driver); + sizeof(struct syscon_generic_softc), syscon_generic_driver); static devclass_t ti_scm_syscon_devclass; +/* ti_scm_syscon needs to attach "as soon as posible" due to it has clocks */ EARLY_DRIVER_MODULE(ti_scm_syscon, simplebus, ti_scm_syscon_driver, ti_scm_syscon_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); MODULE_VERSION(ti_scm_syscon, 1); diff --git a/sys/arm/ti/ti_sysc.c b/sys/arm/ti/ti_sysc.c --- a/sys/arm/ti/ti_sysc.c +++ b/sys/arm/ti/ti_sysc.c @@ -112,6 +112,342 @@ { 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" */ static const char * reg_names[] = { "rev", "sysc", "syss" }; #define REG_REV 0 @@ -135,7 +471,6 @@ struct ti_sysc_softc { struct simplebus_softc sc; - bool attach_done; device_t dev; int device_type; @@ -245,7 +580,7 @@ TAILQ_FOREACH_SAFE(clkp, &sc->clk_list, next, clkp_tmp) { err = clk_enable(clkp->clk); - if (err) { + if (err != 0) { DPRINTF(sc->dev, "clk_enable %s failed %d\n", clk_get_name(clkp->clk), err); break; @@ -263,7 +598,7 @@ TAILQ_FOREACH_SAFE(clkp, &sc->clk_list, next, clkp_tmp) { err = clk_disable(clkp->clk); - if (err) { + if (err != 0) { DPRINTF(sc->dev, "clk_enable %s failed %d\n", clk_get_name(clkp->clk), err); break; @@ -346,6 +681,7 @@ sc->reg[prop_idx].size); } free(reg, M_DEVBUF); + return (0); } @@ -357,9 +693,8 @@ node = ofw_bus_get_node(sc->dev); - if (!OF_hasprop(node, name)) { + if (OF_hasprop(node, name) == 0) return; - } len = OF_getproplen(node, name); no = len / sizeof(cell_t); @@ -395,39 +730,6 @@ idle[i] = -1; } -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) { device_t cdev; @@ -486,21 +788,21 @@ /* Required field reg & reg-names - assume at least "rev" exists */ err = parse_regfields(sc); - if (err) { + if (err != 0) { DPRINTF(sc->dev, "parse_regfields failed %d\n", err); return (ENXIO); } /* 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)); 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)); 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)); sc->ti_sysc_delay_us = value; } @@ -511,17 +813,17 @@ parse_idle(sc, "ti,sysc-midle", sc->ti_sysc_midle); 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; else 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; else 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; else sc->ti_no_idle = false; @@ -532,31 +834,52 @@ sc->ti_no_idle_on_init, sc->ti_no_idle); - if (OF_hasprop(node, "clocks")) { - struct clock_cell_info cell_info; - read_clock_cells(sc->dev, &cell_info); - free(cell_info.clock_cells, M_DEVBUF); - free(cell_info.clock_cells_ncells, M_DEVBUF); + if (OF_hasprop(node, "clocks") == 1) { + int idx, clk_idx; + const char *name = ofw_bus_get_name(dev); + DPRINTF(dev, "%s has clock\n", name); - sc->num_clocks = cell_info.num_real_clocks; - TAILQ_INIT(&sc->clk_list); + 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 + */ - err = ti_sysc_attach_clocks(sc); - if (err) { - DPRINTF(sc->dev, "Failed to attach clocks\n"); - return (bus_generic_attach(sc->dev)); + 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 = clk_get_by_name(dev, + sysc_clock_table[idx].parent_names[clk_idx], + &clkp->clk); + 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); - if (err) { + if (err != 0) { DPRINTF(sc->dev, "ti_sysc_simplebus_attach_child %d\n", err); return (err); } - sc->attach_done = true; - return (bus_generic_attach(sc->dev)); } @@ -566,50 +889,12 @@ 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[] = { /* Device interface */ DEVMETHOD(device_probe, ti_sysc_probe), DEVMETHOD(device_attach, ti_sysc_attach), DEVMETHOD(device_detach, ti_sysc_detach), - /* Bus interface */ - DEVMETHOD(bus_new_pass, ti_sysc_new_pass), - DEVMETHOD_END }; @@ -619,4 +904,4 @@ static devclass_t ti_sysc_devclass; 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);