aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap2/omap_hwmod.c
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2018-03-07 10:26:43 -0500
committerArnd Bergmann <arnd@arndb.de>2018-03-07 10:26:43 -0500
commit3bf5c70d06ce1d91cc73cee68bc6c4f850192cb0 (patch)
tree7d1fab0c67d26ebde22ea4c5e7eb8625f388ccf1 /arch/arm/mach-omap2/omap_hwmod.c
parent18b4788badeae8ed3a9bd3c240d83dffe5db8f37 (diff)
parent695eea3d2c7f3e70e852226c338d464a6251c70b (diff)
Merge tag 'omap-for-v4.17/ti-sysc-signed' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into next/soc
Pull "Driver changes for ti-sysc for v4.17" from Tony Lindgren: This series of changes enables the use device tree based sysconfig data for ti-sysc driver. As we already have SmartReflex data configured, we use that as the first driver to enable. To do that in a way where SmartReflex is not probed twice, we need to prepare the SmartReflex driver before flipping dts data on for it in the last patch of the series. To avoid regressions, we are checking the passed dts data against existing platform data since we still have it available. Then after the dts files are converted, we can simply drop the related platform data at some point in the future. * tag 'omap-for-v4.17/ti-sysc-signed' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: ARM: OMAP2+: Enable ti-sysc to use device tree data for smartreflex PM / AVS: SmartReflex: Prepare to use device tree based probing ARM: OMAP2+: Try to parse earlycon from parent too ARM: OMAP2+: Add checks for device tree based sysconfig data ARM: OMAP2+: Add functions to allocate module data from device tree bus: ti-sysc: Handle some devices in omap_device compatible way bus: ti-sysc: Add support for platform data callbacks bus: ti-sysc: Remove unnecessary debugging statements bus: ti-sysc: Improve handling for no-reset-on-init and no-idle-on-init bus: ti-sysc: Handle stdout-path for debug console bus: ti-sysc: Add suspend and resume handling bus: ti-sysc: Add fck clock alias for children with notifier_block ARM: OMAP2+: Prepare to pass auxdata for smartreflex
Diffstat (limited to 'arch/arm/mach-omap2/omap_hwmod.c')
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c418
1 files changed, 417 insertions, 1 deletions
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 34156eca8e23..e7d23e200ecc 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -145,6 +145,8 @@
145 145
146#include <linux/platform_data/ti-sysc.h> 146#include <linux/platform_data/ti-sysc.h>
147 147
148#include <dt-bindings/bus/ti-sysc.h>
149
148#include <asm/system_misc.h> 150#include <asm/system_misc.h>
149 151
150#include "clock.h" 152#include "clock.h"
@@ -2498,7 +2500,7 @@ static void __init _setup_postsetup(struct omap_hwmod *oh)
2498 * affects the IP block hardware, or system integration hardware 2500 * affects the IP block hardware, or system integration hardware
2499 * associated with the IP block. Returns 0. 2501 * associated with the IP block. Returns 0.
2500 */ 2502 */
2501static int __init _setup(struct omap_hwmod *oh, void *data) 2503static int _setup(struct omap_hwmod *oh, void *data)
2502{ 2504{
2503 if (oh->_state != _HWMOD_STATE_INITIALIZED) 2505 if (oh->_state != _HWMOD_STATE_INITIALIZED)
2504 return 0; 2506 return 0;
@@ -3060,6 +3062,414 @@ int __init omap_hwmod_setup_one(const char *oh_name)
3060 return 0; 3062 return 0;
3061} 3063}
3062 3064
3065static void omap_hwmod_check_one(struct device *dev,
3066 const char *name, s8 v1, u8 v2)
3067{
3068 if (v1 < 0)
3069 return;
3070
3071 if (v1 != v2)
3072 dev_warn(dev, "%s %d != %d\n", name, v1, v2);
3073}
3074
3075/**
3076 * omap_hwmod_check_sysc - check sysc against platform sysc
3077 * @dev: struct device
3078 * @data: module data
3079 * @sysc_fields: new sysc configuration
3080 */
3081static int omap_hwmod_check_sysc(struct device *dev,
3082 const struct ti_sysc_module_data *data,
3083 struct sysc_regbits *sysc_fields)
3084{
3085 const struct sysc_regbits *regbits = data->cap->regbits;
3086
3087 omap_hwmod_check_one(dev, "dmadisable_shift",
3088 regbits->dmadisable_shift,
3089 sysc_fields->dmadisable_shift);
3090 omap_hwmod_check_one(dev, "midle_shift",
3091 regbits->midle_shift,
3092 sysc_fields->midle_shift);
3093 omap_hwmod_check_one(dev, "sidle_shift",
3094 regbits->sidle_shift,
3095 sysc_fields->sidle_shift);
3096 omap_hwmod_check_one(dev, "clkact_shift",
3097 regbits->clkact_shift,
3098 sysc_fields->clkact_shift);
3099 omap_hwmod_check_one(dev, "enwkup_shift",
3100 regbits->enwkup_shift,
3101 sysc_fields->enwkup_shift);
3102 omap_hwmod_check_one(dev, "srst_shift",
3103 regbits->srst_shift,
3104 sysc_fields->srst_shift);
3105 omap_hwmod_check_one(dev, "autoidle_shift",
3106 regbits->autoidle_shift,
3107 sysc_fields->autoidle_shift);
3108
3109 return 0;
3110}
3111
3112/**
3113 * omap_hwmod_init_regbits - init sysconfig specific register bits
3114 * @dev: struct device
3115 * @data: module data
3116 * @sysc_fields: new sysc configuration
3117 */
3118static int omap_hwmod_init_regbits(struct device *dev,
3119 const struct ti_sysc_module_data *data,
3120 struct sysc_regbits **sysc_fields)
3121{
3122 *sysc_fields = NULL;
3123
3124 switch (data->cap->type) {
3125 case TI_SYSC_OMAP2:
3126 case TI_SYSC_OMAP2_TIMER:
3127 *sysc_fields = &omap_hwmod_sysc_type1;
3128 break;
3129 case TI_SYSC_OMAP3_SHAM:
3130 *sysc_fields = &omap3_sham_sysc_fields;
3131 break;
3132 case TI_SYSC_OMAP3_AES:
3133 *sysc_fields = &omap3xxx_aes_sysc_fields;
3134 break;
3135 case TI_SYSC_OMAP4:
3136 case TI_SYSC_OMAP4_TIMER:
3137 *sysc_fields = &omap_hwmod_sysc_type2;
3138 break;
3139 case TI_SYSC_OMAP4_SIMPLE:
3140 *sysc_fields = &omap_hwmod_sysc_type3;
3141 break;
3142 case TI_SYSC_OMAP34XX_SR:
3143 *sysc_fields = &omap34xx_sr_sysc_fields;
3144 break;
3145 case TI_SYSC_OMAP36XX_SR:
3146 *sysc_fields = &omap36xx_sr_sysc_fields;
3147 break;
3148 case TI_SYSC_OMAP4_SR:
3149 *sysc_fields = &omap36xx_sr_sysc_fields;
3150 break;
3151 case TI_SYSC_OMAP4_MCASP:
3152 *sysc_fields = &omap_hwmod_sysc_type_mcasp;
3153 break;
3154 case TI_SYSC_OMAP4_USB_HOST_FS:
3155 *sysc_fields = &omap_hwmod_sysc_type_usb_host_fs;
3156 break;
3157 default:
3158 return -EINVAL;
3159 }
3160
3161 return omap_hwmod_check_sysc(dev, data, *sysc_fields);
3162}
3163
3164/**
3165 * omap_hwmod_init_reg_offs - initialize sysconfig register offsets
3166 * @dev: struct device
3167 * @data: module data
3168 * @rev_offs: revision register offset
3169 * @sysc_offs: sysc register offset
3170 * @syss_offs: syss register offset
3171 */
3172int omap_hwmod_init_reg_offs(struct device *dev,
3173 const struct ti_sysc_module_data *data,
3174 u32 *rev_offs, u32 *sysc_offs, u32 *syss_offs)
3175{
3176 *rev_offs = 0;
3177 *sysc_offs = 0;
3178 *syss_offs = 0;
3179
3180 if (data->offsets[SYSC_REVISION] > 0)
3181 *rev_offs = data->offsets[SYSC_REVISION];
3182
3183 if (data->offsets[SYSC_SYSCONFIG] > 0)
3184 *sysc_offs = data->offsets[SYSC_SYSCONFIG];
3185
3186 if (data->offsets[SYSC_SYSSTATUS] > 0)
3187 *syss_offs = data->offsets[SYSC_SYSSTATUS];
3188
3189 return 0;
3190}
3191
3192/**
3193 * omap_hwmod_init_sysc_flags - initialize sysconfig features
3194 * @dev: struct device
3195 * @data: module data
3196 * @sysc_flags: module configuration
3197 */
3198int omap_hwmod_init_sysc_flags(struct device *dev,
3199 const struct ti_sysc_module_data *data,
3200 u32 *sysc_flags)
3201{
3202 *sysc_flags = 0;
3203
3204 switch (data->cap->type) {
3205 case TI_SYSC_OMAP2:
3206 case TI_SYSC_OMAP2_TIMER:
3207 /* See SYSC_OMAP2_* in include/dt-bindings/bus/ti-sysc.h */
3208 if (data->cfg->sysc_val & SYSC_OMAP2_CLOCKACTIVITY)
3209 *sysc_flags |= SYSC_HAS_CLOCKACTIVITY;
3210 if (data->cfg->sysc_val & SYSC_OMAP2_EMUFREE)
3211 *sysc_flags |= SYSC_HAS_EMUFREE;
3212 if (data->cfg->sysc_val & SYSC_OMAP2_ENAWAKEUP)
3213 *sysc_flags |= SYSC_HAS_ENAWAKEUP;
3214 if (data->cfg->sysc_val & SYSC_OMAP2_SOFTRESET)
3215 *sysc_flags |= SYSC_HAS_SOFTRESET;
3216 if (data->cfg->sysc_val & SYSC_OMAP2_AUTOIDLE)
3217 *sysc_flags |= SYSC_HAS_AUTOIDLE;
3218 break;
3219 case TI_SYSC_OMAP4:
3220 case TI_SYSC_OMAP4_TIMER:
3221 /* See SYSC_OMAP4_* in include/dt-bindings/bus/ti-sysc.h */
3222 if (data->cfg->sysc_val & SYSC_OMAP4_DMADISABLE)
3223 *sysc_flags |= SYSC_HAS_DMADISABLE;
3224 if (data->cfg->sysc_val & SYSC_OMAP4_FREEEMU)
3225 *sysc_flags |= SYSC_HAS_EMUFREE;
3226 if (data->cfg->sysc_val & SYSC_OMAP4_SOFTRESET)
3227 *sysc_flags |= SYSC_HAS_SOFTRESET;
3228 break;
3229 case TI_SYSC_OMAP34XX_SR:
3230 case TI_SYSC_OMAP36XX_SR:
3231 /* See SYSC_OMAP3_SR_* in include/dt-bindings/bus/ti-sysc.h */
3232 if (data->cfg->sysc_val & SYSC_OMAP3_SR_ENAWAKEUP)
3233 *sysc_flags |= SYSC_HAS_ENAWAKEUP;
3234 break;
3235 default:
3236 if (data->cap->regbits->emufree_shift >= 0)
3237 *sysc_flags |= SYSC_HAS_EMUFREE;
3238 if (data->cap->regbits->enwkup_shift >= 0)
3239 *sysc_flags |= SYSC_HAS_ENAWAKEUP;
3240 if (data->cap->regbits->srst_shift >= 0)
3241 *sysc_flags |= SYSC_HAS_SOFTRESET;
3242 if (data->cap->regbits->autoidle_shift >= 0)
3243 *sysc_flags |= SYSC_HAS_AUTOIDLE;
3244 break;
3245 }
3246
3247 if (data->cap->regbits->midle_shift >= 0 &&
3248 data->cfg->midlemodes)
3249 *sysc_flags |= SYSC_HAS_MIDLEMODE;
3250
3251 if (data->cap->regbits->sidle_shift >= 0 &&
3252 data->cfg->sidlemodes)
3253 *sysc_flags |= SYSC_HAS_SIDLEMODE;
3254
3255 if (data->cfg->quirks & SYSC_QUIRK_UNCACHED)
3256 *sysc_flags |= SYSC_NO_CACHE;
3257 if (data->cfg->quirks & SYSC_QUIRK_RESET_STATUS)
3258 *sysc_flags |= SYSC_HAS_RESET_STATUS;
3259
3260 if (data->cfg->syss_mask & 1)
3261 *sysc_flags |= SYSS_HAS_RESET_STATUS;
3262
3263 return 0;
3264}
3265
3266/**
3267 * omap_hwmod_init_idlemodes - initialize module idle modes
3268 * @dev: struct device
3269 * @data: module data
3270 * @idlemodes: module supported idle modes
3271 */
3272int omap_hwmod_init_idlemodes(struct device *dev,
3273 const struct ti_sysc_module_data *data,
3274 u32 *idlemodes)
3275{
3276 *idlemodes = 0;
3277
3278 if (data->cfg->midlemodes & BIT(SYSC_IDLE_FORCE))
3279 *idlemodes |= MSTANDBY_FORCE;
3280 if (data->cfg->midlemodes & BIT(SYSC_IDLE_NO))
3281 *idlemodes |= MSTANDBY_NO;
3282 if (data->cfg->midlemodes & BIT(SYSC_IDLE_SMART))
3283 *idlemodes |= MSTANDBY_SMART;
3284 if (data->cfg->midlemodes & BIT(SYSC_IDLE_SMART_WKUP))
3285 *idlemodes |= MSTANDBY_SMART_WKUP;
3286
3287 if (data->cfg->sidlemodes & BIT(SYSC_IDLE_FORCE))
3288 *idlemodes |= SIDLE_FORCE;
3289 if (data->cfg->sidlemodes & BIT(SYSC_IDLE_NO))
3290 *idlemodes |= SIDLE_NO;
3291 if (data->cfg->sidlemodes & BIT(SYSC_IDLE_SMART))
3292 *idlemodes |= SIDLE_SMART;
3293 if (data->cfg->sidlemodes & BIT(SYSC_IDLE_SMART_WKUP))
3294 *idlemodes |= SIDLE_SMART_WKUP;
3295
3296 return 0;
3297}
3298
3299/**
3300 * omap_hwmod_check_module - check new module against platform data
3301 * @dev: struct device
3302 * @oh: module
3303 * @data: new module data
3304 * @sysc_fields: sysc register bits
3305 * @rev_offs: revision register offset
3306 * @sysc_offs: sysconfig register offset
3307 * @syss_offs: sysstatus register offset
3308 * @sysc_flags: sysc specific flags
3309 * @idlemodes: sysc supported idlemodes
3310 */
3311static int omap_hwmod_check_module(struct device *dev,
3312 struct omap_hwmod *oh,
3313 const struct ti_sysc_module_data *data,
3314 struct sysc_regbits *sysc_fields,
3315 u32 rev_offs, u32 sysc_offs,
3316 u32 syss_offs, u32 sysc_flags,
3317 u32 idlemodes)
3318{
3319 if (!oh->class->sysc)
3320 return -ENODEV;
3321
3322 if (sysc_fields != oh->class->sysc->sysc_fields)
3323 dev_warn(dev, "sysc_fields %p != %p\n", sysc_fields,
3324 oh->class->sysc->sysc_fields);
3325
3326 if (rev_offs != oh->class->sysc->rev_offs)
3327 dev_warn(dev, "rev_offs %08x != %08x\n", rev_offs,
3328 oh->class->sysc->rev_offs);
3329 if (sysc_offs != oh->class->sysc->sysc_offs)
3330 dev_warn(dev, "sysc_offs %08x != %08x\n", sysc_offs,
3331 oh->class->sysc->sysc_offs);
3332 if (syss_offs != oh->class->sysc->syss_offs)
3333 dev_warn(dev, "syss_offs %08x != %08x\n", syss_offs,
3334 oh->class->sysc->syss_offs);
3335
3336 if (sysc_flags != oh->class->sysc->sysc_flags)
3337 dev_warn(dev, "sysc_flags %08x != %08x\n", sysc_flags,
3338 oh->class->sysc->sysc_flags);
3339
3340 if (idlemodes != oh->class->sysc->idlemodes)
3341 dev_warn(dev, "idlemodes %08x != %08x\n", idlemodes,
3342 oh->class->sysc->idlemodes);
3343
3344 if (data->cfg->srst_udelay != oh->class->sysc->srst_udelay)
3345 dev_warn(dev, "srst_udelay %i != %i\n",
3346 data->cfg->srst_udelay,
3347 oh->class->sysc->srst_udelay);
3348
3349 return 0;
3350}
3351
3352/**
3353 * omap_hwmod_allocate_module - allocate new module
3354 * @dev: struct device
3355 * @oh: module
3356 * @sysc_fields: sysc register bits
3357 * @rev_offs: revision register offset
3358 * @sysc_offs: sysconfig register offset
3359 * @syss_offs: sysstatus register offset
3360 * @sysc_flags: sysc specific flags
3361 * @idlemodes: sysc supported idlemodes
3362 *
3363 * Note that the allocations here cannot use devm as ti-sysc can rebind.
3364 */
3365int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
3366 const struct ti_sysc_module_data *data,
3367 struct sysc_regbits *sysc_fields,
3368 u32 rev_offs, u32 sysc_offs, u32 syss_offs,
3369 u32 sysc_flags, u32 idlemodes)
3370{
3371 struct omap_hwmod_class_sysconfig *sysc;
3372 struct omap_hwmod_class *class;
3373 void __iomem *regs = NULL;
3374 unsigned long flags;
3375
3376 sysc = kzalloc(sizeof(*sysc), GFP_KERNEL);
3377 if (!sysc)
3378 return -ENOMEM;
3379
3380 sysc->sysc_fields = sysc_fields;
3381 sysc->rev_offs = rev_offs;
3382 sysc->sysc_offs = sysc_offs;
3383 sysc->syss_offs = syss_offs;
3384 sysc->sysc_flags = sysc_flags;
3385 sysc->idlemodes = idlemodes;
3386 sysc->srst_udelay = data->cfg->srst_udelay;
3387
3388 if (!oh->_mpu_rt_va) {
3389 regs = ioremap(data->module_pa,
3390 data->module_size);
3391 if (!regs)
3392 return -ENOMEM;
3393 }
3394
3395 /*
3396 * We need new oh->class as the other devices in the same class
3397 * may not yet have ioremapped their registers.
3398 */
3399 class = kmemdup(oh->class, sizeof(*oh->class), GFP_KERNEL);
3400 if (!class)
3401 return -ENOMEM;
3402
3403 class->sysc = sysc;
3404
3405 spin_lock_irqsave(&oh->_lock, flags);
3406 if (regs)
3407 oh->_mpu_rt_va = regs;
3408 oh->class = class;
3409 oh->_state = _HWMOD_STATE_INITIALIZED;
3410 _setup(oh, NULL);
3411 spin_unlock_irqrestore(&oh->_lock, flags);
3412
3413 return 0;
3414}
3415
3416/**
3417 * omap_hwmod_init_module - initialize new module
3418 * @dev: struct device
3419 * @data: module data
3420 * @cookie: cookie for the caller to use for later calls
3421 */
3422int omap_hwmod_init_module(struct device *dev,
3423 const struct ti_sysc_module_data *data,
3424 struct ti_sysc_cookie *cookie)
3425{
3426 struct omap_hwmod *oh;
3427 struct sysc_regbits *sysc_fields;
3428 u32 rev_offs, sysc_offs, syss_offs, sysc_flags, idlemodes;
3429 int error;
3430
3431 if (!dev || !data)
3432 return -EINVAL;
3433
3434 oh = _lookup(data->name);
3435 if (!oh)
3436 return -ENODEV;
3437
3438 cookie->data = oh;
3439
3440 error = omap_hwmod_init_regbits(dev, data, &sysc_fields);
3441 if (error)
3442 return error;
3443
3444 error = omap_hwmod_init_reg_offs(dev, data, &rev_offs,
3445 &sysc_offs, &syss_offs);
3446 if (error)
3447 return error;
3448
3449 error = omap_hwmod_init_sysc_flags(dev, data, &sysc_flags);
3450 if (error)
3451 return error;
3452
3453 error = omap_hwmod_init_idlemodes(dev, data, &idlemodes);
3454 if (error)
3455 return error;
3456
3457 if (data->cfg->quirks & SYSC_QUIRK_NO_IDLE_ON_INIT)
3458 oh->flags |= HWMOD_INIT_NO_IDLE;
3459 if (data->cfg->quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
3460 oh->flags |= HWMOD_INIT_NO_RESET;
3461
3462 error = omap_hwmod_check_module(dev, oh, data, sysc_fields,
3463 rev_offs, sysc_offs, syss_offs,
3464 sysc_flags, idlemodes);
3465 if (!error)
3466 return error;
3467
3468 return omap_hwmod_allocate_module(dev, oh, data, sysc_fields,
3469 rev_offs, sysc_offs, syss_offs,
3470 sysc_flags, idlemodes);
3471}
3472
3063/** 3473/**
3064 * omap_hwmod_setup_earlycon_flags - set up flags for early console 3474 * omap_hwmod_setup_earlycon_flags - set up flags for early console
3065 * 3475 *
@@ -3082,6 +3492,12 @@ static void __init omap_hwmod_setup_earlycon_flags(void)
3082 if (np) { 3492 if (np) {
3083 uart = of_get_property(np, "ti,hwmods", NULL); 3493 uart = of_get_property(np, "ti,hwmods", NULL);
3084 oh = omap_hwmod_lookup(uart); 3494 oh = omap_hwmod_lookup(uart);
3495 if (!oh) {
3496 uart = of_get_property(np->parent,
3497 "ti,hwmods",
3498 NULL);
3499 oh = omap_hwmod_lookup(uart);
3500 }
3085 if (oh) 3501 if (oh)
3086 oh->flags |= DEBUG_OMAPUART_FLAGS; 3502 oh->flags |= DEBUG_OMAPUART_FLAGS;
3087 } 3503 }