diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-16 11:31:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-16 11:31:32 -0400 |
commit | 22c58fd70ca48a29505922b1563826593b08cc00 (patch) | |
tree | ee3154075bcd0a867fd0abf7e00ba3b4055999d4 /arch/arm/mach-omap2/omap_hwmod.c | |
parent | a455eda33faafcaac1effb31d682765b14ef868c (diff) | |
parent | 7a0c4c17089a8aff52f516f0f52002be52950aae (diff) |
Merge tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
Pull ARM SoC platform updates from Olof Johansson:
"SoC updates, mostly refactorings and cleanups of old legacy platforms.
Major themes this release:
- Conversion of ixp4xx to a modern platform (drivers, DT, bindings)
- Moving some of the ep93xx headers around to get it closer to
multiplatform enabled.
- Cleanups of Davinci
This also contains a few patches that were queued up as fixes before
5.1 but I didn't get sent in before release"
* tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (123 commits)
ARM: debug-ll: add default address for digicolor
ARM: u300: regulator: add MODULE_LICENSE()
ARM: ep93xx: move private headers out of mach/*
ARM: ep93xx: move pinctrl interfaces into include/linux/soc
ARM: ep93xx: keypad: stop using mach/platform.h
ARM: ep93xx: move network platform data to separate header
ARM: stm32: add AMBA support for stm32 family
MAINTAINERS: update arch/arm/mach-davinci
ARM: rockchip: add missing of_node_put in rockchip_smp_prepare_pmu
ARM: dts: Add queue manager and NPE to the IXP4xx DTSI
soc: ixp4xx: qmgr: Add DT probe code
soc: ixp4xx: qmgr: Add DT bindings for IXP4xx qmgr
soc: ixp4xx: npe: Add DT probe code
soc: ixp4xx: Add DT bindings for IXP4xx NPE
soc: ixp4xx: qmgr: Pass resources
soc: ixp4xx: Remove unused functions
soc: ixp4xx: Uninline several functions
soc: ixp4xx: npe: Pass addresses as resources
ARM: ixp4xx: Turn the QMGR into a platform device
ARM: ixp4xx: Turn the NPE into a platform device
...
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod.c | 210 |
1 files changed, 184 insertions, 26 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index baadddf9aad4..405ac24def05 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c | |||
@@ -155,6 +155,8 @@ | |||
155 | #include "soc.h" | 155 | #include "soc.h" |
156 | #include "common.h" | 156 | #include "common.h" |
157 | #include "clockdomain.h" | 157 | #include "clockdomain.h" |
158 | #include "hdq1w.h" | ||
159 | #include "mmc.h" | ||
158 | #include "powerdomain.h" | 160 | #include "powerdomain.h" |
159 | #include "cm2xxx.h" | 161 | #include "cm2xxx.h" |
160 | #include "cm3xxx.h" | 162 | #include "cm3xxx.h" |
@@ -165,6 +167,7 @@ | |||
165 | #include "prm33xx.h" | 167 | #include "prm33xx.h" |
166 | #include "prminst44xx.h" | 168 | #include "prminst44xx.h" |
167 | #include "pm.h" | 169 | #include "pm.h" |
170 | #include "wd_timer.h" | ||
168 | 171 | ||
169 | /* Name of the OMAP hwmod for the MPU */ | 172 | /* Name of the OMAP hwmod for the MPU */ |
170 | #define MPU_INITIATOR_NAME "mpu" | 173 | #define MPU_INITIATOR_NAME "mpu" |
@@ -205,6 +208,20 @@ struct clkctrl_provider { | |||
205 | static LIST_HEAD(clkctrl_providers); | 208 | static LIST_HEAD(clkctrl_providers); |
206 | 209 | ||
207 | /** | 210 | /** |
211 | * struct omap_hwmod_reset - IP specific reset functions | ||
212 | * @match: string to match against the module name | ||
213 | * @len: number of characters to match | ||
214 | * @reset: IP specific reset function | ||
215 | * | ||
216 | * Used only in cases where struct omap_hwmod is dynamically allocated. | ||
217 | */ | ||
218 | struct omap_hwmod_reset { | ||
219 | const char *match; | ||
220 | int len; | ||
221 | int (*reset)(struct omap_hwmod *oh); | ||
222 | }; | ||
223 | |||
224 | /** | ||
208 | * struct omap_hwmod_soc_ops - fn ptrs for some SoC-specific operations | 225 | * struct omap_hwmod_soc_ops - fn ptrs for some SoC-specific operations |
209 | * @enable_module: function to enable a module (via MODULEMODE) | 226 | * @enable_module: function to enable a module (via MODULEMODE) |
210 | * @disable_module: function to disable a module (via MODULEMODE) | 227 | * @disable_module: function to disable a module (via MODULEMODE) |
@@ -235,6 +252,7 @@ static struct omap_hwmod_soc_ops soc_ops; | |||
235 | 252 | ||
236 | /* omap_hwmod_list contains all registered struct omap_hwmods */ | 253 | /* omap_hwmod_list contains all registered struct omap_hwmods */ |
237 | static LIST_HEAD(omap_hwmod_list); | 254 | static LIST_HEAD(omap_hwmod_list); |
255 | static DEFINE_MUTEX(list_lock); | ||
238 | 256 | ||
239 | /* mpu_oh: used to add/remove MPU initiator from sleepdep list */ | 257 | /* mpu_oh: used to add/remove MPU initiator from sleepdep list */ |
240 | static struct omap_hwmod *mpu_oh; | 258 | static struct omap_hwmod *mpu_oh; |
@@ -2465,7 +2483,7 @@ static void _setup_iclk_autoidle(struct omap_hwmod *oh) | |||
2465 | */ | 2483 | */ |
2466 | static int _setup_reset(struct omap_hwmod *oh) | 2484 | static int _setup_reset(struct omap_hwmod *oh) |
2467 | { | 2485 | { |
2468 | int r; | 2486 | int r = 0; |
2469 | 2487 | ||
2470 | if (oh->_state != _HWMOD_STATE_INITIALIZED) | 2488 | if (oh->_state != _HWMOD_STATE_INITIALIZED) |
2471 | return -EINVAL; | 2489 | return -EINVAL; |
@@ -2624,7 +2642,7 @@ static int _setup(struct omap_hwmod *oh, void *data) | |||
2624 | * that the copy process would be relatively complex due to the large number | 2642 | * that the copy process would be relatively complex due to the large number |
2625 | * of substructures. | 2643 | * of substructures. |
2626 | */ | 2644 | */ |
2627 | static int __init _register(struct omap_hwmod *oh) | 2645 | static int _register(struct omap_hwmod *oh) |
2628 | { | 2646 | { |
2629 | if (!oh || !oh->name || !oh->class || !oh->class->name || | 2647 | if (!oh || !oh->name || !oh->class || !oh->class->name || |
2630 | (oh->_state != _HWMOD_STATE_UNKNOWN)) | 2648 | (oh->_state != _HWMOD_STATE_UNKNOWN)) |
@@ -2663,7 +2681,7 @@ static int __init _register(struct omap_hwmod *oh) | |||
2663 | * locking in this code. Changes to this assumption will require | 2681 | * locking in this code. Changes to this assumption will require |
2664 | * additional locking. Returns 0. | 2682 | * additional locking. Returns 0. |
2665 | */ | 2683 | */ |
2666 | static int __init _add_link(struct omap_hwmod_ocp_if *oi) | 2684 | static int _add_link(struct omap_hwmod_ocp_if *oi) |
2667 | { | 2685 | { |
2668 | pr_debug("omap_hwmod: %s -> %s: adding link\n", oi->master->name, | 2686 | pr_debug("omap_hwmod: %s -> %s: adding link\n", oi->master->name, |
2669 | oi->slave->name); | 2687 | oi->slave->name); |
@@ -3241,9 +3259,10 @@ static int omap_hwmod_init_regbits(struct device *dev, | |||
3241 | * @sysc_offs: sysc register offset | 3259 | * @sysc_offs: sysc register offset |
3242 | * @syss_offs: syss register offset | 3260 | * @syss_offs: syss register offset |
3243 | */ | 3261 | */ |
3244 | int omap_hwmod_init_reg_offs(struct device *dev, | 3262 | static int omap_hwmod_init_reg_offs(struct device *dev, |
3245 | const struct ti_sysc_module_data *data, | 3263 | const struct ti_sysc_module_data *data, |
3246 | s32 *rev_offs, s32 *sysc_offs, s32 *syss_offs) | 3264 | s32 *rev_offs, s32 *sysc_offs, |
3265 | s32 *syss_offs) | ||
3247 | { | 3266 | { |
3248 | *rev_offs = -ENODEV; | 3267 | *rev_offs = -ENODEV; |
3249 | *sysc_offs = 0; | 3268 | *sysc_offs = 0; |
@@ -3267,9 +3286,9 @@ int omap_hwmod_init_reg_offs(struct device *dev, | |||
3267 | * @data: module data | 3286 | * @data: module data |
3268 | * @sysc_flags: module configuration | 3287 | * @sysc_flags: module configuration |
3269 | */ | 3288 | */ |
3270 | int omap_hwmod_init_sysc_flags(struct device *dev, | 3289 | static int omap_hwmod_init_sysc_flags(struct device *dev, |
3271 | const struct ti_sysc_module_data *data, | 3290 | const struct ti_sysc_module_data *data, |
3272 | u32 *sysc_flags) | 3291 | u32 *sysc_flags) |
3273 | { | 3292 | { |
3274 | *sysc_flags = 0; | 3293 | *sysc_flags = 0; |
3275 | 3294 | ||
@@ -3341,9 +3360,9 @@ int omap_hwmod_init_sysc_flags(struct device *dev, | |||
3341 | * @data: module data | 3360 | * @data: module data |
3342 | * @idlemodes: module supported idle modes | 3361 | * @idlemodes: module supported idle modes |
3343 | */ | 3362 | */ |
3344 | int omap_hwmod_init_idlemodes(struct device *dev, | 3363 | static int omap_hwmod_init_idlemodes(struct device *dev, |
3345 | const struct ti_sysc_module_data *data, | 3364 | const struct ti_sysc_module_data *data, |
3346 | u32 *idlemodes) | 3365 | u32 *idlemodes) |
3347 | { | 3366 | { |
3348 | *idlemodes = 0; | 3367 | *idlemodes = 0; |
3349 | 3368 | ||
@@ -3434,14 +3453,18 @@ static int omap_hwmod_check_module(struct device *dev, | |||
3434 | * | 3453 | * |
3435 | * Note that the allocations here cannot use devm as ti-sysc can rebind. | 3454 | * Note that the allocations here cannot use devm as ti-sysc can rebind. |
3436 | */ | 3455 | */ |
3437 | int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh, | 3456 | static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh, |
3438 | const struct ti_sysc_module_data *data, | 3457 | const struct ti_sysc_module_data *data, |
3439 | struct sysc_regbits *sysc_fields, | 3458 | struct sysc_regbits *sysc_fields, |
3440 | s32 rev_offs, s32 sysc_offs, s32 syss_offs, | 3459 | s32 rev_offs, s32 sysc_offs, |
3441 | u32 sysc_flags, u32 idlemodes) | 3460 | s32 syss_offs, u32 sysc_flags, |
3461 | u32 idlemodes) | ||
3442 | { | 3462 | { |
3443 | struct omap_hwmod_class_sysconfig *sysc; | 3463 | struct omap_hwmod_class_sysconfig *sysc; |
3444 | struct omap_hwmod_class *class; | 3464 | struct omap_hwmod_class *class = NULL; |
3465 | struct omap_hwmod_ocp_if *oi = NULL; | ||
3466 | struct clockdomain *clkdm = NULL; | ||
3467 | struct clk *clk = NULL; | ||
3445 | void __iomem *regs = NULL; | 3468 | void __iomem *regs = NULL; |
3446 | unsigned long flags; | 3469 | unsigned long flags; |
3447 | 3470 | ||
@@ -3465,26 +3488,128 @@ int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh, | |||
3465 | } | 3488 | } |
3466 | 3489 | ||
3467 | /* | 3490 | /* |
3468 | * We need new oh->class as the other devices in the same class | 3491 | * We may need a new oh->class as the other devices in the same class |
3469 | * may not yet have ioremapped their registers. | 3492 | * may not yet have ioremapped their registers. |
3470 | */ | 3493 | */ |
3471 | class = kmemdup(oh->class, sizeof(*oh->class), GFP_KERNEL); | 3494 | if (oh->class->name && strcmp(oh->class->name, data->name)) { |
3472 | if (!class) | 3495 | class = kmemdup(oh->class, sizeof(*oh->class), GFP_KERNEL); |
3473 | return -ENOMEM; | 3496 | if (!class) |
3497 | return -ENOMEM; | ||
3498 | } | ||
3474 | 3499 | ||
3475 | class->sysc = sysc; | 3500 | if (list_empty(&oh->slave_ports)) { |
3501 | oi = kcalloc(1, sizeof(*oi), GFP_KERNEL); | ||
3502 | if (!oi) | ||
3503 | return -ENOMEM; | ||
3504 | |||
3505 | /* | ||
3506 | * Note that we assume interconnect interface clocks will be | ||
3507 | * managed by the interconnect driver for OCPIF_SWSUP_IDLE case | ||
3508 | * on omap24xx and omap3. | ||
3509 | */ | ||
3510 | oi->slave = oh; | ||
3511 | oi->user = OCP_USER_MPU | OCP_USER_SDMA; | ||
3512 | } | ||
3513 | |||
3514 | if (!oh->_clk) { | ||
3515 | struct clk_hw_omap *hwclk; | ||
3516 | |||
3517 | clk = of_clk_get_by_name(dev->of_node, "fck"); | ||
3518 | if (!IS_ERR(clk)) | ||
3519 | clk_prepare(clk); | ||
3520 | else | ||
3521 | clk = NULL; | ||
3522 | |||
3523 | /* | ||
3524 | * Populate clockdomain based on dts clock. It is needed for | ||
3525 | * clkdm_deny_idle() and clkdm_allow_idle() until we have have | ||
3526 | * interconnect driver and reset driver capable of blocking | ||
3527 | * clockdomain idle during reset, enable and idle. | ||
3528 | */ | ||
3529 | if (clk) { | ||
3530 | hwclk = to_clk_hw_omap(__clk_get_hw(clk)); | ||
3531 | if (hwclk && hwclk->clkdm_name) | ||
3532 | clkdm = clkdm_lookup(hwclk->clkdm_name); | ||
3533 | } | ||
3534 | |||
3535 | /* | ||
3536 | * Note that we assume interconnect driver manages the clocks | ||
3537 | * and do not need to populate oh->_clk for dynamically | ||
3538 | * allocated modules. | ||
3539 | */ | ||
3540 | clk_unprepare(clk); | ||
3541 | clk_put(clk); | ||
3542 | } | ||
3476 | 3543 | ||
3477 | spin_lock_irqsave(&oh->_lock, flags); | 3544 | spin_lock_irqsave(&oh->_lock, flags); |
3478 | if (regs) | 3545 | if (regs) |
3479 | oh->_mpu_rt_va = regs; | 3546 | oh->_mpu_rt_va = regs; |
3480 | oh->class = class; | 3547 | if (class) |
3548 | oh->class = class; | ||
3549 | oh->class->sysc = sysc; | ||
3550 | if (oi) | ||
3551 | _add_link(oi); | ||
3552 | if (clkdm) | ||
3553 | oh->clkdm = clkdm; | ||
3481 | oh->_state = _HWMOD_STATE_INITIALIZED; | 3554 | oh->_state = _HWMOD_STATE_INITIALIZED; |
3555 | oh->_postsetup_state = _HWMOD_STATE_DEFAULT; | ||
3482 | _setup(oh, NULL); | 3556 | _setup(oh, NULL); |
3483 | spin_unlock_irqrestore(&oh->_lock, flags); | 3557 | spin_unlock_irqrestore(&oh->_lock, flags); |
3484 | 3558 | ||
3485 | return 0; | 3559 | return 0; |
3486 | } | 3560 | } |
3487 | 3561 | ||
3562 | static const struct omap_hwmod_reset omap24xx_reset_quirks[] = { | ||
3563 | { .match = "msdi", .len = 4, .reset = omap_msdi_reset, }, | ||
3564 | }; | ||
3565 | |||
3566 | static const struct omap_hwmod_reset dra7_reset_quirks[] = { | ||
3567 | { .match = "pcie", .len = 4, .reset = dra7xx_pciess_reset, }, | ||
3568 | }; | ||
3569 | |||
3570 | static const struct omap_hwmod_reset omap_reset_quirks[] = { | ||
3571 | { .match = "dss", .len = 3, .reset = omap_dss_reset, }, | ||
3572 | { .match = "hdq1w", .len = 5, .reset = omap_hdq1w_reset, }, | ||
3573 | { .match = "i2c", .len = 3, .reset = omap_i2c_reset, }, | ||
3574 | { .match = "wd_timer", .len = 8, .reset = omap2_wd_timer_reset, }, | ||
3575 | }; | ||
3576 | |||
3577 | static void | ||
3578 | omap_hwmod_init_reset_quirk(struct device *dev, struct omap_hwmod *oh, | ||
3579 | const struct ti_sysc_module_data *data, | ||
3580 | const struct omap_hwmod_reset *quirks, | ||
3581 | int quirks_sz) | ||
3582 | { | ||
3583 | const struct omap_hwmod_reset *quirk; | ||
3584 | int i; | ||
3585 | |||
3586 | for (i = 0; i < quirks_sz; i++) { | ||
3587 | quirk = &quirks[i]; | ||
3588 | if (!strncmp(data->name, quirk->match, quirk->len)) { | ||
3589 | oh->class->reset = quirk->reset; | ||
3590 | |||
3591 | return; | ||
3592 | } | ||
3593 | } | ||
3594 | } | ||
3595 | |||
3596 | static void | ||
3597 | omap_hwmod_init_reset_quirks(struct device *dev, struct omap_hwmod *oh, | ||
3598 | const struct ti_sysc_module_data *data) | ||
3599 | { | ||
3600 | if (soc_is_omap24xx()) | ||
3601 | omap_hwmod_init_reset_quirk(dev, oh, data, | ||
3602 | omap24xx_reset_quirks, | ||
3603 | ARRAY_SIZE(omap24xx_reset_quirks)); | ||
3604 | |||
3605 | if (soc_is_dra7xx()) | ||
3606 | omap_hwmod_init_reset_quirk(dev, oh, data, dra7_reset_quirks, | ||
3607 | ARRAY_SIZE(dra7_reset_quirks)); | ||
3608 | |||
3609 | omap_hwmod_init_reset_quirk(dev, oh, data, omap_reset_quirks, | ||
3610 | ARRAY_SIZE(omap_reset_quirks)); | ||
3611 | } | ||
3612 | |||
3488 | /** | 3613 | /** |
3489 | * omap_hwmod_init_module - initialize new module | 3614 | * omap_hwmod_init_module - initialize new module |
3490 | * @dev: struct device | 3615 | * @dev: struct device |
@@ -3505,8 +3630,31 @@ int omap_hwmod_init_module(struct device *dev, | |||
3505 | return -EINVAL; | 3630 | return -EINVAL; |
3506 | 3631 | ||
3507 | oh = _lookup(data->name); | 3632 | oh = _lookup(data->name); |
3508 | if (!oh) | 3633 | if (!oh) { |
3509 | return -ENODEV; | 3634 | oh = kzalloc(sizeof(*oh), GFP_KERNEL); |
3635 | if (!oh) | ||
3636 | return -ENOMEM; | ||
3637 | |||
3638 | oh->name = data->name; | ||
3639 | oh->_state = _HWMOD_STATE_UNKNOWN; | ||
3640 | lockdep_register_key(&oh->hwmod_key); | ||
3641 | |||
3642 | /* Unused, can be handled by PRM driver handling resets */ | ||
3643 | oh->prcm.omap4.flags = HWMOD_OMAP4_NO_CONTEXT_LOSS_BIT; | ||
3644 | |||
3645 | oh->class = kzalloc(sizeof(*oh->class), GFP_KERNEL); | ||
3646 | if (!oh->class) { | ||
3647 | kfree(oh); | ||
3648 | return -ENOMEM; | ||
3649 | } | ||
3650 | |||
3651 | omap_hwmod_init_reset_quirks(dev, oh, data); | ||
3652 | |||
3653 | oh->class->name = data->name; | ||
3654 | mutex_lock(&list_lock); | ||
3655 | error = _register(oh); | ||
3656 | mutex_unlock(&list_lock); | ||
3657 | } | ||
3510 | 3658 | ||
3511 | cookie->data = oh; | 3659 | cookie->data = oh; |
3512 | 3660 | ||
@@ -3527,10 +3675,20 @@ int omap_hwmod_init_module(struct device *dev, | |||
3527 | if (error) | 3675 | if (error) |
3528 | return error; | 3676 | return error; |
3529 | 3677 | ||
3678 | if (data->cfg->quirks & SYSC_QUIRK_NO_IDLE) | ||
3679 | oh->flags |= HWMOD_NO_IDLE; | ||
3530 | if (data->cfg->quirks & SYSC_QUIRK_NO_IDLE_ON_INIT) | 3680 | if (data->cfg->quirks & SYSC_QUIRK_NO_IDLE_ON_INIT) |
3531 | oh->flags |= HWMOD_INIT_NO_IDLE; | 3681 | oh->flags |= HWMOD_INIT_NO_IDLE; |
3532 | if (data->cfg->quirks & SYSC_QUIRK_NO_RESET_ON_INIT) | 3682 | if (data->cfg->quirks & SYSC_QUIRK_NO_RESET_ON_INIT) |
3533 | oh->flags |= HWMOD_INIT_NO_RESET; | 3683 | oh->flags |= HWMOD_INIT_NO_RESET; |
3684 | if (data->cfg->quirks & SYSC_QUIRK_USE_CLOCKACT) | ||
3685 | oh->flags |= HWMOD_SET_DEFAULT_CLOCKACT; | ||
3686 | if (data->cfg->quirks & SYSC_QUIRK_SWSUP_SIDLE) | ||
3687 | oh->flags |= HWMOD_SWSUP_SIDLE; | ||
3688 | if (data->cfg->quirks & SYSC_QUIRK_SWSUP_SIDLE_ACT) | ||
3689 | oh->flags |= HWMOD_SWSUP_SIDLE_ACT; | ||
3690 | if (data->cfg->quirks & SYSC_QUIRK_SWSUP_MSTANDBY) | ||
3691 | oh->flags |= HWMOD_SWSUP_MSTANDBY; | ||
3534 | 3692 | ||
3535 | error = omap_hwmod_check_module(dev, oh, data, sysc_fields, | 3693 | error = omap_hwmod_check_module(dev, oh, data, sysc_fields, |
3536 | rev_offs, sysc_offs, syss_offs, | 3694 | rev_offs, sysc_offs, syss_offs, |