diff --git a/Documentation/devicetree/bindings/bus/ti-sysc.txt b/Documentation/devicetree/bindings/bus/ti-sysc.txt index d8ed5b780ed9..91dc2333af01 100644 --- a/Documentation/devicetree/bindings/bus/ti-sysc.txt +++ b/Documentation/devicetree/bindings/bus/ti-sysc.txt @@ -36,6 +36,7 @@ Required standard properties: "ti,sysc-omap-aes" "ti,sysc-mcasp" "ti,sysc-usb-host-fs" + "ti,sysc-dra7-mcan" - reg shall have register areas implemented for the interconnect target module in question such as revision, sysc and syss diff --git a/arch/arm/boot/dts/dra76-evm.dts b/arch/arm/boot/dts/dra76-evm.dts index f983cfd1cb85..5a46163d465f 100644 --- a/arch/arm/boot/dts/dra76-evm.dts +++ b/arch/arm/boot/dts/dra76-evm.dts @@ -444,3 +444,9 @@ &extcon_usb1 { &extcon_usb2 { vbus-gpio = <&pcf_lcd 15 GPIO_ACTIVE_HIGH>; }; + +&m_can0 { + can-transceiver { + max-bitrate = <5000000>; + }; +}; diff --git a/arch/arm/boot/dts/dra76x.dtsi b/arch/arm/boot/dts/dra76x.dtsi index 1c88c581ff18..613e4dc0ed3e 100644 --- a/arch/arm/boot/dts/dra76x.dtsi +++ b/arch/arm/boot/dts/dra76x.dtsi @@ -11,9 +11,73 @@ / { compatible = "ti,dra762", "ti,dra7"; + ocp { + target-module@42c01900 { + compatible = "ti,sysc-dra7-mcan", "ti,sysc"; + ranges = <0x0 0x42c00000 0x2000>; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x42c01900 0x4>, + <0x42c01904 0x4>, + <0x42c01908 0x4>; + reg-names = "rev", "sysc", "syss"; + ti,sysc-mask = <(SYSC_OMAP4_SOFTRESET | + SYSC_DRA7_MCAN_ENAWAKEUP)>; + ti,syss-mask = <1>; + clocks = <&wkupaon_clkctrl DRA7_ADC_CLKCTRL 0>; + clock-names = "fck"; + + m_can0: mcan@1a00 { + compatible = "bosch,m_can"; + reg = <0x1a00 0x4000>, <0x0 0x18FC>; + reg-names = "m_can", "message_ram"; + interrupt-parent = <&gic>; + interrupts = , + ; + interrupt-names = "int0", "int1"; + clocks = <&mcan_clk>, <&l3_iclk_div>; + clock-names = "cclk", "hclk"; + bosch,mram-cfg = <0x0 0 0 32 0 0 1 1>; + }; + }; + }; + }; /* MCAN interrupts are hard-wired to irqs 67, 68 */ &crossbar_mpu { ti,irqs-skip = <10 67 68 133 139 140>; }; + +&scm_conf_clocks { + dpll_gmac_h14x2_ctrl_ck: dpll_gmac_h14x2_ctrl_ck@3fc { + #clock-cells = <0>; + compatible = "ti,divider-clock"; + clocks = <&dpll_gmac_x2_ck>; + ti,max-div = <63>; + reg = <0x03fc>; + ti,bit-shift=<20>; + ti,latch-bit=<26>; + assigned-clocks = <&dpll_gmac_h14x2_ctrl_ck>; + assigned-clock-rates = <80000000>; + }; + + dpll_gmac_h14x2_ctrl_mux_ck: dpll_gmac_h14x2_ctrl_mux_ck@3fc { + #clock-cells = <0>; + compatible = "ti,mux-clock"; + clocks = <&dpll_gmac_ck>, <&dpll_gmac_h14x2_ctrl_ck>; + reg = <0x3fc>; + ti,bit-shift = <29>; + ti,latch-bit=<26>; + assigned-clocks = <&dpll_gmac_h14x2_ctrl_mux_ck>; + assigned-clock-parents = <&dpll_gmac_h14x2_ctrl_ck>; + }; + + mcan_clk: mcan_clk@3fc { + #clock-cells = <0>; + compatible = "ti,gate-clock"; + clocks = <&dpll_gmac_h14x2_ctrl_mux_ck>; + ti,bit-shift = <27>; + reg = <0x3fc>; + }; +}; diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 1cc29629d238..c9bac9dc4637 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -23,11 +23,14 @@ #include #include #include +#include #include #include +#define MAX_MODULE_SOFTRESET_WAIT 10000 + static const char * const reg_names[] = { "rev", "sysc", "syss", }; enum sysc_clocks { @@ -88,6 +91,11 @@ struct sysc { struct delayed_work idle_work; }; +void sysc_write(struct sysc *ddata, int offset, u32 value) +{ + writel_relaxed(value, ddata->module_va + offset); +} + static u32 sysc_read(struct sysc *ddata, int offset) { if (ddata->cfg.quirks & SYSC_QUIRK_16BIT) { @@ -169,9 +177,9 @@ static int sysc_get_clocks(struct sysc *ddata) const char *name; int nr_fck = 0, nr_ick = 0, i, error = 0; - ddata->clock_roles = devm_kzalloc(ddata->dev, - sizeof(*ddata->clock_roles) * + ddata->clock_roles = devm_kcalloc(ddata->dev, SYSC_MAX_CLOCKS, + sizeof(*ddata->clock_roles), GFP_KERNEL); if (!ddata->clock_roles) return -ENOMEM; @@ -200,8 +208,8 @@ static int sysc_get_clocks(struct sysc *ddata) return -EINVAL; } - ddata->clocks = devm_kzalloc(ddata->dev, - sizeof(*ddata->clocks) * ddata->nr_clocks, + ddata->clocks = devm_kcalloc(ddata->dev, + ddata->nr_clocks, sizeof(*ddata->clocks), GFP_KERNEL); if (!ddata->clocks) return -ENOMEM; @@ -943,6 +951,36 @@ static void sysc_init_revision_quirks(struct sysc *ddata) } } +static int sysc_reset(struct sysc *ddata) +{ + int offset = ddata->offsets[SYSC_SYSCONFIG]; + int val; + + if (ddata->legacy_mode || offset < 0 || + ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT) + return 0; + + /* + * Currently only support reset status in sysstatus. + * Warn and return error in all other cases + */ + if (!ddata->cfg.syss_mask) { + dev_err(ddata->dev, "No ti,syss-mask. Reset failed\n"); + return -EINVAL; + } + + val = sysc_read(ddata, offset); + val |= (0x1 << ddata->cap->regbits->srst_shift); + sysc_write(ddata, offset, val); + + /* Poll on reset status */ + offset = ddata->offsets[SYSC_SYSSTATUS]; + + return readl_poll_timeout(ddata->module_va + offset, val, + (val & ddata->cfg.syss_mask) == 0x0, + 100, MAX_MODULE_SOFTRESET_WAIT); +} + /* At this point the module is configured enough to read the revision */ static int sysc_init_module(struct sysc *ddata) { @@ -960,6 +998,14 @@ static int sysc_init_module(struct sysc *ddata) return 0; } + error = sysc_reset(ddata); + if (error) { + dev_err(ddata->dev, "Reset failed with %d\n", error); + pm_runtime_put_sync(ddata->dev); + + return error; + } + ddata->revision = sysc_read_revision(ddata); pm_runtime_put_sync(ddata->dev); @@ -1552,6 +1598,23 @@ static const struct sysc_capabilities sysc_omap4_usb_host_fs = { .regbits = &sysc_regbits_omap4_usb_host_fs, }; +static const struct sysc_regbits sysc_regbits_dra7_mcan = { + .dmadisable_shift = -ENODEV, + .midle_shift = -ENODEV, + .sidle_shift = -ENODEV, + .clkact_shift = -ENODEV, + .enwkup_shift = 4, + .srst_shift = 0, + .emufree_shift = -ENODEV, + .autoidle_shift = -ENODEV, +}; + +static const struct sysc_capabilities sysc_dra7_mcan = { + .type = TI_SYSC_DRA7_MCAN, + .sysc_mask = SYSC_DRA7_MCAN_ENAWAKEUP | SYSC_OMAP4_SOFTRESET, + .regbits = &sysc_regbits_dra7_mcan, +}; + static int sysc_init_pdata(struct sysc *ddata) { struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev); @@ -1743,6 +1806,7 @@ static const struct of_device_id sysc_match[] = { { .compatible = "ti,sysc-mcasp", .data = &sysc_omap4_mcasp, }, { .compatible = "ti,sysc-usb-host-fs", .data = &sysc_omap4_usb_host_fs, }, + { .compatible = "ti,sysc-dra7-mcan", .data = &sysc_dra7_mcan, }, { }, }; MODULE_DEVICE_TABLE(of, sysc_match); diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c index fb249a1637a5..71a122b2dc67 100644 --- a/drivers/clk/ti/clk-7xx.c +++ b/drivers/clk/ti/clk-7xx.c @@ -708,6 +708,7 @@ static const struct omap_clkctrl_reg_data dra7_wkupaon_clkctrl_regs[] __initcons { DRA7_COUNTER_32K_CLKCTRL, NULL, 0, "wkupaon_iclk_mux" }, { DRA7_UART10_CLKCTRL, dra7_uart10_bit_data, CLKF_SW_SUP, "wkupaon_cm:clk:0060:24" }, { DRA7_DCAN1_CLKCTRL, dra7_dcan1_bit_data, CLKF_SW_SUP, "wkupaon_cm:clk:0068:24" }, + { DRA7_ADC_CLKCTRL, NULL, CLKF_SW_SUP, "mcan_clk"}, { 0 }, }; diff --git a/include/dt-bindings/bus/ti-sysc.h b/include/dt-bindings/bus/ti-sysc.h index 2c005376ac0e..7138384e2ef9 100644 --- a/include/dt-bindings/bus/ti-sysc.h +++ b/include/dt-bindings/bus/ti-sysc.h @@ -15,6 +15,8 @@ /* SmartReflex sysc found on 36xx and later */ #define SYSC_OMAP3_SR_ENAWAKEUP (1 << 26) +#define SYSC_DRA7_MCAN_ENAWAKEUP (1 << 4) + /* SYSCONFIG STANDBYMODE/MIDLEMODE/SIDLEMODE supported by hardware */ #define SYSC_IDLE_FORCE 0 #define SYSC_IDLE_NO 1 diff --git a/include/dt-bindings/clock/dra7.h b/include/dt-bindings/clock/dra7.h index 5e1061b15aed..d7549c57cac3 100644 --- a/include/dt-bindings/clock/dra7.h +++ b/include/dt-bindings/clock/dra7.h @@ -168,5 +168,6 @@ #define DRA7_COUNTER_32K_CLKCTRL DRA7_CLKCTRL_INDEX(0x50) #define DRA7_UART10_CLKCTRL DRA7_CLKCTRL_INDEX(0x80) #define DRA7_DCAN1_CLKCTRL DRA7_CLKCTRL_INDEX(0x88) +#define DRA7_ADC_CLKCTRL DRA7_CLKCTRL_INDEX(0xa0) #endif diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index 990aad477458..2efa3470a451 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -14,6 +14,7 @@ enum ti_sysc_module_type { TI_SYSC_OMAP4_SR, TI_SYSC_OMAP4_MCASP, TI_SYSC_OMAP4_USB_HOST_FS, + TI_SYSC_DRA7_MCAN, }; struct ti_sysc_cookie {